Reorganize emu cpu directory

This commit is contained in:
scawful
2023-12-05 21:16:16 -05:00
parent 042d07abdf
commit d0c9229093
19 changed files with 30 additions and 30 deletions

View File

@@ -0,0 +1,123 @@
#include "app/emu/cpu/cpu.h"
namespace yaze {
namespace app {
namespace emu {
uint16_t CPU::Absolute(CPU::AccessType access_type) {
auto operand = FetchWord();
uint32_t bank =
(access_type == CPU::AccessType::Data) ? (DB << 16) : (PB << 16);
return bank | (operand & 0xFFFF);
}
uint32_t CPU::AbsoluteIndexedX() {
uint16_t address = memory.ReadWord((PB << 16) | (PC + 1));
uint32_t effective_address = (DB << 16) | ((address + X) & 0xFFFF);
return effective_address;
}
uint32_t CPU::AbsoluteIndexedY() {
uint16_t address = memory.ReadWord((PB << 16) | (PC + 1));
uint32_t effective_address = (DB << 16) | address + Y;
return effective_address;
}
uint16_t CPU::AbsoluteIndexedIndirect() {
uint16_t address = FetchWord() + X;
return memory.ReadWord((DB << 16) | address & 0xFFFF);
}
uint16_t CPU::AbsoluteIndirect() {
uint16_t address = FetchWord();
return memory.ReadWord((PB << 16) | address);
}
uint32_t CPU::AbsoluteIndirectLong() {
uint16_t address = FetchWord();
return memory.ReadWordLong((PB << 16) | address);
}
uint32_t CPU::AbsoluteLong() { return FetchLong(); }
uint32_t CPU::AbsoluteLongIndexedX() { return FetchLong() + X; }
void CPU::BlockMove(uint16_t source, uint16_t dest, uint16_t length) {
for (int i = 0; i < length; i++) {
memory.WriteByte(dest + i, memory.ReadByte(source + i));
}
}
uint16_t CPU::DirectPage() {
uint8_t dp = FetchByte();
return D + dp;
}
uint16_t CPU::DirectPageIndexedX() {
uint8_t operand = FetchByte();
uint16_t x_by_mode = GetAccumulatorSize() ? X : X & 0xFF;
return D + operand + x_by_mode;
}
uint16_t CPU::DirectPageIndexedY() {
uint8_t operand = FetchByte();
return (operand + Y) & 0xFF;
}
uint16_t CPU::DirectPageIndexedIndirectX() {
uint8_t operand = FetchByte();
uint16_t indirect_address = D + operand + X;
uint16_t effective_address = memory.ReadWord(indirect_address & 0xFFFF);
return effective_address;
}
uint16_t CPU::DirectPageIndirect() {
uint8_t dp = FetchByte();
uint16_t effective_address = D + dp;
return memory.ReadWord(effective_address);
}
uint32_t CPU::DirectPageIndirectLong() {
uint8_t dp = FetchByte();
uint16_t effective_address = D + dp;
return memory.ReadWordLong((0x00 << 0x10) | effective_address);
}
uint16_t CPU::DirectPageIndirectIndexedY() {
uint8_t operand = FetchByte();
uint16_t indirect_address = D + operand;
return memory.ReadWord(indirect_address) + Y;
}
uint32_t CPU::DirectPageIndirectLongIndexedY() {
uint8_t operand = FetchByte();
uint16_t indirect_address = D + operand;
uint16_t y_by_mode = GetAccumulatorSize() ? Y : Y & 0xFF;
uint32_t effective_address =
memory.ReadWordLong(indirect_address) + y_by_mode;
return effective_address;
}
uint16_t CPU::Immediate(bool index_size) {
bool bit_mode = index_size ? GetIndexSize() : GetAccumulatorSize();
if (bit_mode) {
return memory.ReadByte((PB << 16) | PC + 1);
} else {
return memory.ReadWord((PB << 16) | PC + 1);
}
}
uint16_t CPU::StackRelative() {
uint8_t sr = FetchByte();
uint16_t effective_address = SP() + sr;
return effective_address;
}
uint32_t CPU::StackRelativeIndirectIndexedY() {
uint8_t sr = FetchByte();
return (DB << 0x10) | (memory.ReadWord(SP() + sr) + Y);
}
} // namespace emu
} // namespace app
} // namespace yaze

View File

@@ -0,0 +1,818 @@
#include <iostream>
#include <string>
#include <vector>
#include "app/emu/cpu/cpu.h"
namespace yaze {
namespace app {
namespace emu {
/**
* 65816 Instruction Set
*
* TODO: STP, WDM
*/
void CPU::ADC(uint16_t operand) {
bool C = GetCarryFlag();
if (GetAccumulatorSize()) { // 8-bit mode
uint16_t result = static_cast<uint16_t>(A & 0xFF) +
static_cast<uint16_t>(operand) + (C ? 1 : 0);
SetCarryFlag(result > 0xFF); // Update the carry flag
// Update the overflow flag
bool overflow = (~(A ^ operand) & (A ^ result) & 0x80) != 0;
SetOverflowFlag(overflow);
// Update the accumulator with proper wrap-around
A = (A & 0xFF00) | (result & 0xFF);
SetZeroFlag((A & 0xFF) == 0);
SetNegativeFlag(A & 0x80);
} else {
uint32_t result =
static_cast<uint32_t>(A) + static_cast<uint32_t>(operand) + (C ? 1 : 0);
SetCarryFlag(result > 0xFFFF); // Update the carry flag
// Update the overflow flag
bool overflow = (~(A ^ operand) & (A ^ result) & 0x8000) != 0;
SetOverflowFlag(overflow);
// Update the accumulator
A = result & 0xFFFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
}
void CPU::AND(uint32_t value, bool isImmediate) {
uint16_t operand;
if (GetAccumulatorSize()) { // 8-bit mode
operand = isImmediate ? value : memory.ReadByte(value);
A &= operand;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else { // 16-bit mode
operand = isImmediate ? value : memory.ReadWord(value);
A &= operand;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
}
// New function for absolute long addressing mode
void CPU::ANDAbsoluteLong(uint32_t address) {
uint32_t operand32 = memory.ReadWordLong(address);
A &= operand32;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
void CPU::ASL(uint16_t address) {
uint8_t value = memory.ReadByte(address);
SetCarryFlag(!(value & 0x80)); // Set carry flag if bit 7 is set
value <<= 1; // Shift left
value &= 0xFE; // Clear bit 0
memory.WriteByte(address, value);
SetNegativeFlag(!value);
SetZeroFlag(value);
}
void CPU::BCC(int8_t offset) {
if (!GetCarryFlag()) { // If the carry flag is clear
next_pc_ = offset;
}
}
void CPU::BCS(int8_t offset) {
if (GetCarryFlag()) { // If the carry flag is set
next_pc_ = offset;
}
}
void CPU::BEQ(int8_t offset) {
if (GetZeroFlag()) { // If the zero flag is set
next_pc_ = offset;
}
}
void CPU::BIT(uint16_t address) {
uint8_t value = memory.ReadByte(address);
SetNegativeFlag(value & 0x80);
SetOverflowFlag(value & 0x40);
SetZeroFlag((A & value) == 0);
}
void CPU::BMI(int8_t offset) {
if (GetNegativeFlag()) { // If the negative flag is set
next_pc_ = offset;
}
}
void CPU::BNE(int8_t offset) {
if (!GetZeroFlag()) { // If the zero flag is clear
// PC += offset;
next_pc_ = offset;
}
}
void CPU::BPL(int8_t offset) {
if (!GetNegativeFlag()) { // If the negative flag is clear
next_pc_ = offset;
}
}
void CPU::BRA(int8_t offset) { next_pc_ = offset; }
void CPU::BRK() {
next_pc_ = PC + 2; // Increment the program counter by 2
memory.PushWord(next_pc_);
memory.PushByte(status);
SetInterruptFlag(true);
try {
next_pc_ = memory.ReadWord(0xFFFE);
} catch (const std::exception& e) {
std::cout << "BRK: " << e.what() << std::endl;
}
}
void CPU::BRL(int16_t offset) { next_pc_ = offset; }
void CPU::BVC(int8_t offset) {
if (!GetOverflowFlag()) { // If the overflow flag is clear
next_pc_ = offset;
}
}
void CPU::BVS(int8_t offset) {
if (GetOverflowFlag()) { // If the overflow flag is set
next_pc_ = offset;
}
}
void CPU::CLC() { status &= ~0x01; }
void CPU::CLD() { status &= ~0x08; }
void CPU::CLI() { status &= ~0x04; }
void CPU::CLV() { status &= ~0x40; }
// n Set if MSB of result is set; else cleared
// z Set if result is zero; else cleared
// c Set if no borrow; else cleared
void CPU::CMP(uint32_t value, bool isImmediate) {
if (GetAccumulatorSize()) { // 8-bit
uint8_t result;
if (isImmediate) {
result = A - (value & 0xFF);
} else {
uint8_t memory_value = memory.ReadByte(value);
result = A - memory_value;
}
SetZeroFlag(result == 0);
SetNegativeFlag(result & 0x80);
SetCarryFlag(A >= (value & 0xFF));
} else { // 16-bit
uint16_t result;
if (isImmediate) {
result = A - (value & 0xFFFF);
} else {
uint16_t memory_value = memory.ReadWord(value);
result = A - memory_value;
}
SetZeroFlag(result == 0);
SetNegativeFlag(result & 0x8000);
SetCarryFlag(A >= (value & 0xFFFF));
}
}
void CPU::COP() {
next_pc_ += 2; // Increment the program counter by 2
memory.PushWord(next_pc_);
memory.PushByte(status);
SetInterruptFlag(true);
if (E) {
next_pc_ = memory.ReadWord(0xFFF4);
} else {
next_pc_ = memory.ReadWord(0xFFE4);
}
SetDecimalFlag(false);
}
void CPU::CPX(uint32_t value, bool isImmediate) {
if (GetIndexSize()) { // 8-bit
uint8_t memory_value = isImmediate ? value : memory.ReadByte(value);
compare(X, memory_value);
} else { // 16-bit
uint16_t memory_value = isImmediate ? value : memory.ReadWord(value);
compare(X, memory_value);
}
}
void CPU::CPY(uint32_t value, bool isImmediate) {
if (GetIndexSize()) { // 8-bit
uint8_t memory_value = isImmediate ? value : memory.ReadByte(value);
compare(Y, memory_value);
} else { // 16-bit
uint16_t memory_value = isImmediate ? value : memory.ReadWord(value);
compare(Y, memory_value);
}
}
void CPU::DEC(uint32_t address, bool accumulator) {
if (accumulator) {
if (GetAccumulatorSize()) { // 8-bit
A = (A - 1) & 0xFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else { // 16-bit
A = (A - 1) & 0xFFFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
return;
}
if (GetAccumulatorSize()) {
uint8_t value = memory.ReadByte(address);
value--;
memory.WriteByte(address, value);
SetZeroFlag(value == 0);
SetNegativeFlag(value & 0x80);
} else {
uint16_t value = memory.ReadWord(address);
value--;
memory.WriteWord(address, value);
SetZeroFlag(value == 0);
SetNegativeFlag(value & 0x8000);
}
}
void CPU::DEX() {
if (GetIndexSize()) { // 8-bit
X = static_cast<uint8_t>(X - 1);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
} else { // 16-bit
X = static_cast<uint16_t>(X - 1);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x8000);
}
}
void CPU::DEY() {
if (GetIndexSize()) { // 8-bit
Y = static_cast<uint8_t>(Y - 1);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
} else { // 16-bit
Y = static_cast<uint16_t>(Y - 1);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x8000);
}
}
void CPU::EOR(uint32_t address, bool isImmediate) {
if (GetAccumulatorSize()) {
A ^= isImmediate ? address : memory.ReadByte(address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else {
A ^= isImmediate ? address : memory.ReadWord(address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
}
void CPU::INC(uint32_t address, bool accumulator) {
if (accumulator) {
if (GetAccumulatorSize()) { // 8-bit
A = (A + 1) & 0xFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else { // 16-bit
A = (A + 1) & 0xFFFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
return;
}
if (GetAccumulatorSize()) {
uint8_t value = memory.ReadByte(address);
value++;
memory.WriteByte(address, value);
SetNegativeFlag(value & 0x80);
SetZeroFlag(value == 0);
} else {
uint16_t value = memory.ReadWord(address);
value++;
memory.WriteWord(address, value);
SetNegativeFlag(value & 0x8000);
SetZeroFlag(value == 0);
}
}
void CPU::INX() {
if (GetIndexSize()) { // 8-bit
X = static_cast<uint8_t>(X + 1);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
} else { // 16-bit
X = static_cast<uint16_t>(X + 1);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x8000);
}
}
void CPU::INY() {
if (GetIndexSize()) { // 8-bit
Y = static_cast<uint8_t>(Y + 1);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
} else { // 16-bit
Y = static_cast<uint16_t>(Y + 1);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x8000);
}
}
void CPU::JMP(uint16_t address) {
next_pc_ = address; // Set program counter to the new address
}
void CPU::JML(uint32_t address) {
next_pc_ = static_cast<uint16_t>(address & 0xFFFF);
// Set the PBR to the upper 8 bits of the address
PB = static_cast<uint8_t>((address >> 16) & 0xFF);
}
void CPU::JSR(uint16_t address) {
memory.PushWord(PC); // Push the program counter onto the stack
next_pc_ = address; // Set program counter to the new address
}
void CPU::JSL(uint32_t address) {
memory.PushLong(PC); // Push the program counter onto the stack as a long
// value (24 bits)
next_pc_ = address; // Set program counter to the new address
}
void CPU::LDA(uint16_t address, bool isImmediate, bool direct_page) {
uint8_t bank = PB;
if (direct_page) {
bank = 0;
}
if (GetAccumulatorSize()) {
A = isImmediate ? address : memory.ReadByte((bank << 16) | address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else {
A = isImmediate ? address : memory.ReadWord((bank << 16) | address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
}
void CPU::LDX(uint16_t address, bool isImmediate) {
if (GetIndexSize()) {
X = isImmediate ? address : memory.ReadByte(address);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
} else {
X = isImmediate ? address : memory.ReadWord(address);
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x8000);
}
}
void CPU::LDY(uint16_t address, bool isImmediate) {
if (GetIndexSize()) {
Y = isImmediate ? address : memory.ReadByte(address);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
} else {
Y = isImmediate ? address : memory.ReadWord(address);
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x8000);
}
}
void CPU::LSR(uint16_t address, bool accumulator) {
if (accumulator) {
if (GetAccumulatorSize()) { // 8-bit
SetCarryFlag(A & 0x01);
A >>= 1;
SetZeroFlag(A == 0);
SetNegativeFlag(false);
} else { // 16-bit
SetCarryFlag(A & 0x0001);
A >>= 1;
SetZeroFlag(A == 0);
SetNegativeFlag(false);
}
return;
}
uint8_t value = memory.ReadByte(address);
SetCarryFlag(value & 0x01);
value >>= 1;
memory.WriteByte(address, value);
SetNegativeFlag(false);
SetZeroFlag(value == 0);
}
void CPU::MVN(uint16_t source, uint16_t dest, uint16_t length) {
for (uint16_t i = 0; i < length; i++) {
memory.WriteByte(dest, memory.ReadByte(source));
source++;
dest++;
}
}
void CPU::MVP(uint16_t source, uint16_t dest, uint16_t length) {
for (uint16_t i = 0; i < length; i++) {
memory.WriteByte(dest, memory.ReadByte(source));
source--;
dest--;
}
}
void CPU::NOP() {
// Do nothing
}
void CPU::ORA(uint16_t address, bool isImmediate) {
if (GetAccumulatorSize()) {
A |= isImmediate ? address : memory.ReadByte(address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else {
A |= isImmediate ? address : memory.ReadWord(address);
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
}
void CPU::PEA() {
uint16_t address = FetchWord();
memory.PushWord(address);
}
void CPU::PEI() {
uint16_t address = FetchWord();
memory.PushWord(memory.ReadWord(address));
}
void CPU::PER() {
uint16_t address = FetchWord();
memory.PushWord(PC + address);
}
void CPU::PHA() {
if (GetAccumulatorSize()) {
memory.PushByte(static_cast<uint8_t>(A));
} else {
memory.PushWord(A);
}
}
void CPU::PHB() { memory.PushByte(DB); }
void CPU::PHD() { memory.PushWord(D); }
void CPU::PHK() { memory.PushByte(PB); }
void CPU::PHP() { memory.PushByte(status); }
void CPU::PHX() {
if (GetIndexSize()) {
memory.PushByte(static_cast<uint8_t>(X));
} else {
memory.PushWord(X);
}
}
void CPU::PHY() {
if (GetIndexSize()) {
memory.PushByte(static_cast<uint8_t>(Y));
} else {
memory.PushWord(Y);
}
}
void CPU::PLA() {
if (GetAccumulatorSize()) {
A = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
} else {
A = memory.PopWord();
SetNegativeFlag((A & 0x8000) != 0);
}
SetZeroFlag(A == 0);
}
void CPU::PLB() {
DB = memory.PopByte();
SetNegativeFlag((DB & 0x80) != 0);
SetZeroFlag(DB == 0);
}
// Pull Direct Page Register from Stack
void CPU::PLD() {
D = memory.PopWord();
SetNegativeFlag((D & 0x8000) != 0);
SetZeroFlag(D == 0);
}
// Pull Processor Status Register from Stack
void CPU::PLP() { status = memory.PopByte(); }
void CPU::PLX() {
if (GetIndexSize()) {
X = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
} else {
X = memory.PopWord();
SetNegativeFlag((A & 0x8000) != 0);
}
SetZeroFlag(X == 0);
}
void CPU::PLY() {
if (GetIndexSize()) {
Y = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
} else {
Y = memory.PopWord();
SetNegativeFlag((A & 0x8000) != 0);
}
SetZeroFlag(Y == 0);
}
void CPU::REP() {
auto byte = FetchByte();
status &= ~byte;
}
void CPU::ROL(uint32_t address, bool accumulator) {
if (accumulator) {
if (GetAccumulatorSize()) { // 8-bit
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
SetCarryFlag(A & 0x80);
A <<= 1;
A |= carry;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else { // 16-bit
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
SetCarryFlag(A & 0x8000);
A <<= 1;
A |= carry;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
return;
}
uint8_t value = memory.ReadByte(address);
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
SetCarryFlag(value & 0x80);
value <<= 1;
value |= carry;
memory.WriteByte(address, value);
SetNegativeFlag(value & 0x80);
SetZeroFlag(value == 0);
}
void CPU::ROR(uint32_t address, bool accumulator) {
if (accumulator) {
if (GetAccumulatorSize()) { // 8-bit
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
SetCarryFlag(A & 0x01);
A >>= 1;
A |= carry;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
} else { // 16-bit
uint8_t carry = GetCarryFlag() ? 0x8000 : 0x00;
SetCarryFlag(A & 0x0001);
A >>= 1;
A |= carry;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
}
return;
}
uint8_t value = memory.ReadByte(address);
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
SetCarryFlag(value & 0x01);
value >>= 1;
value |= carry;
memory.WriteByte(address, value);
SetNegativeFlag(value & 0x80);
SetZeroFlag(value == 0);
}
void CPU::RTI() {
status = memory.PopByte();
PC = memory.PopWord();
}
void CPU::RTL() {
next_pc_ = memory.PopWord();
PB = memory.PopByte();
}
void CPU::RTS() { last_call_frame_ = memory.PopWord(); }
void CPU::SBC(uint32_t value, bool isImmediate) {
uint16_t operand;
if (!GetAccumulatorSize()) { // 16-bit mode
operand = isImmediate ? value : memory.ReadWord(value);
uint16_t result = A - operand - (GetCarryFlag() ? 0 : 1);
SetCarryFlag(!(result > 0xFFFF)); // Update the carry flag
// Update the overflow flag
bool overflow = ((A ^ operand) & (A ^ result) & 0x8000) != 0;
SetOverflowFlag(overflow);
// Update the accumulator
A = result & 0xFFFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
} else { // 8-bit mode
operand = isImmediate ? value : memory.ReadByte(value);
uint8_t result = A - operand - (GetCarryFlag() ? 0 : 1);
SetCarryFlag(!(result > 0xFF)); // Update the carry flag
// Update the overflow flag
bool overflow = ((A ^ operand) & (A ^ result) & 0x80) != 0;
SetOverflowFlag(overflow);
// Update the accumulator
A = result & 0xFF;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
}
void CPU::SEC() { status |= 0x01; }
void CPU::SED() { status |= 0x08; }
void CPU::SEI() { status |= 0x04; }
void CPU::SEP() {
auto byte = FetchByte();
status |= byte;
}
void CPU::STA(uint32_t address) {
if (GetAccumulatorSize()) {
memory.WriteByte(address, static_cast<uint8_t>(A));
} else {
memory.WriteWord(address, A);
}
}
// TODO: Make this work with the Clock class of the CPU
void CPU::STP() {
// During the next phase 2 clock cycle, stop the processors oscillator input
// The processor is effectively shut down until a reset occurs (RES` pin).
}
void CPU::STX(uint16_t address) {
if (GetIndexSize()) {
memory.WriteByte(address, static_cast<uint8_t>(X));
} else {
memory.WriteWord(address, X);
}
}
void CPU::STY(uint16_t address) {
if (GetIndexSize()) {
memory.WriteByte(address, static_cast<uint8_t>(Y));
} else {
memory.WriteWord(address, Y);
}
}
void CPU::STZ(uint16_t address) {
if (GetAccumulatorSize()) {
memory.WriteByte(address, 0x00);
} else {
memory.WriteWord(address, 0x0000);
}
}
void CPU::TAX() {
X = A;
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
void CPU::TAY() {
Y = A;
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
}
void CPU::TCD() {
D = A;
SetZeroFlag(D == 0);
SetNegativeFlag(D & 0x80);
}
void CPU::TCS() { memory.SetSP(A); }
void CPU::TDC() {
A = D;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void CPU::TRB(uint16_t address) {
uint8_t value = memory.ReadByte(address);
SetZeroFlag((A & value) == 0);
value &= ~A;
memory.WriteByte(address, value);
}
void CPU::TSB(uint16_t address) {
uint8_t value = memory.ReadByte(address);
SetZeroFlag((A & value) == 0);
value |= A;
memory.WriteByte(address, value);
}
void CPU::TSC() {
A = SP();
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void CPU::TSX() {
X = SP();
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
void CPU::TXA() {
A = X;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void CPU::TXS() { memory.SetSP(X); }
void CPU::TXY() {
Y = X;
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
void CPU::TYA() {
A = Y;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void CPU::TYX() {
X = Y;
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
}
// TODO: Make this communicate with the SNES class
void CPU::WAI() {
// Pull the RDY pin low
// Power consumption is reduced(?)
// RDY remains low until an external hardware interupt
// (NMI, IRQ, ABORT, or RESET) is received from the SNES class
}
void CPU::XBA() {
uint8_t lowByte = A & 0xFF;
uint8_t highByte = (A >> 8) & 0xFF;
A = (lowByte << 8) | highByte;
}
void CPU::XCE() {
uint8_t carry = status & 0x01;
status &= ~0x01;
status |= E;
E = carry;
}
} // namespace emu
} // namespace app
} // namespace yaze

View File

@@ -0,0 +1,61 @@
#pragma once
#include <cstdint>
#include <string>
#include <unordered_map>
const std::unordered_map<uint8_t, std::string> opcode_to_mnemonic = {
{0x00, "BRK"}, {0x01, "ORA"}, {0x02, "COP"}, {0x03, "ORA"}, {0x04, "TSB"},
{0x05, "ORA"}, {0x06, "ASL"}, {0x07, "ORA"}, {0x08, "PHP"}, {0x09, "ORA"},
{0x0A, "ASL"}, {0x0B, "PHD"}, {0x0C, "TSB"}, {0x0D, "ORA"}, {0x0E, "ASL"},
{0x0F, "ORA"}, {0x10, "BPL"}, {0x11, "ORA"}, {0x12, "ORA"}, {0x13, "ORA"},
{0x14, "TRB"}, {0x15, "ORA"}, {0x16, "ASL"}, {0x17, "ORA"}, {0x18, "CLC"},
{0x19, "ORA"}, {0x1A, "INC"}, {0x1B, "TCS"}, {0x1C, "TRB"}, {0x1D, "ORA"},
{0x1E, "ASL"}, {0x1F, "ORA"}, {0x20, "JSR"}, {0x21, "AND"}, {0x22, "JSL"},
{0x23, "AND"}, {0x24, "BIT"}, {0x25, "AND"}, {0x26, "ROL"}, {0x27, "AND"},
{0x28, "PLP"}, {0x29, "AND"}, {0x2A, "ROL"}, {0x2B, "PLD"}, {0x2C, "BIT"},
{0x2D, "AND"}, {0x2E, "ROL"}, {0x2F, "AND"}, {0x30, "BMI"}, {0x31, "AND"},
{0x32, "AND"}, {0x33, "AND"}, {0x34, "BIT"}, {0x35, "AND"}, {0x36, "ROL"},
{0x37, "AND"}, {0x38, "SEC"}, {0x39, "AND"}, {0x3A, "DEC"}, {0x3B, "TSC"},
{0x3C, "BIT"}, {0x3D, "AND"}, {0x3E, "ROL"}, {0x3F, "AND"}, {0x40, "RTI"},
{0x41, "EOR"}, {0x42, "WDM"}, {0x43, "EOR"}, {0x44, "MVP"}, {0x45, "EOR"},
{0x46, "LSR"}, {0x47, "EOR"}, {0x48, "PHA"}, {0x49, "EOR"}, {0x4A, "LSR"},
{0x4B, "PHK"}, {0x4C, "JMP"}, {0x4D, "EOR"}, {0x4E, "LSR"}, {0x4F, "EOR"},
{0x50, "BVC"}, {0x51, "EOR"}, {0x52, "EOR"}, {0x53, "EOR"}, {0x54, "MVN"},
{0x55, "EOR"}, {0x56, "LSR"}, {0x57, "EOR"}, {0x58, "CLI"}, {0x59, "EOR"},
{0x5A, "PHY"}, {0x5B, "TCD"}, {0x5C, "JMP"}, {0x5D, "EOR"}, {0x5E, "LSR"},
{0x5F, "EOR"}, {0x60, "RTS"}, {0x61, "ADC"}, {0x62, "PER"}, {0x63, "ADC"},
{0x64, "STZ"}, {0x65, "ADC"}, {0x66, "ROR"}, {0x67, "ADC"}, {0x68, "PLA"},
{0x69, "ADC"}, {0x6A, "ROR"}, {0x6B, "RTL"}, {0x6C, "JMP"}, {0x6D, "ADC"},
{0x6E, "ROR"}, {0x6F, "ADC"}, {0x70, "BVS"}, {0x71, "ADC"}, {0x72, "ADC"},
{0x73, "ADC"}, {0x74, "STZ"}, {0x75, "ADC"}, {0x76, "ROR"}, {0x77, "ADC"},
{0x78, "SEI"}, {0x79, "ADC"}, {0x7A, "PLY"}, {0x7B, "TDC"}, {0x7C, "JMP"},
{0x7D, "ADC"}, {0x7E, "ROR"}, {0x7F, "ADC"}, {0x80, "BRA"}, {0x81, "STA"},
{0x82, "BRL"}, {0x83, "STA"}, {0x84, "STY"}, {0x85, "STA"}, {0x86, "STX"},
{0x87, "STA"}, {0x88, "DEY"}, {0x89, "BIT"}, {0x8A, "TXA"}, {0x8B, "PHB"},
{0x8C, "STY"}, {0x8D, "STA"}, {0x8E, "STX"}, {0x8F, "STA"}, {0x90, "BCC"},
{0x91, "STA"}, {0x92, "STA"}, {0x93, "STA"}, {0x94, "STY"}, {0x95, "STA"},
{0x96, "STX"}, {0x97, "STA"}, {0x98, "TYA"}, {0x99, "STA"}, {0x9A, "TXS"},
{0x9B, "TXY"}, {0x9C, "STZ"}, {0x9D, "STA"}, {0x9E, "STZ"}, {0x9F, "STA"},
{0xA0, "LDY"}, {0xA1, "LDA"}, {0xA2, "LDX"}, {0xA3, "LDA"}, {0xA4, "LDY"},
{0xA5, "LDA"}, {0xA6, "LDX"}, {0xA7, "LDA"}, {0xA8, "TAY"}, {0xA9, "LDA"},
{0xAA, "TAX"}, {0xAB, "PLB"}, {0xAC, "LDY"}, {0xAD, "LDA"}, {0xAE, "LDX"},
{0xAF, "LDA"}, {0xB0, "BCS"}, {0xB1, "LDA"}, {0xB2, "LDA"}, {0xB3, "LDA"},
{0xB4, "LDY"}, {0xB5, "LDA"}, {0xB6, "LDX"}, {0xB7, "LDA"}, {0xB8, "CLV"},
{0xB9, "LDA"}, {0xBA, "TSX"}, {0xBB, "TYX"}, {0xBC, "LDY"}, {0xBD, "LDA"},
{0xBE, "LDX"}, {0xBF, "LDA"}, {0xC0, "CPY"}, {0xC1, "CMP"}, {0xC2, "REP"},
{0xC3, "CMP"}, {0xC4, "CPY"}, {0xC5, "CMP"}, {0xC6, "DEC"}, {0xC7, "CMP"},
{0xC8, "INY"}, {0xC9, "CMP"}, {0xCA, "DEX"}, {0xCB, "WAI"}, {0xCC, "CPY"},
{0xCD, "CMP"}, {0xCE, "DEC"}, {0xCF, "CMP"}, {0xD0, "BNE"}, {0xD1, "CMP"},
{0xD2, "CMP"}, {0xD3, "CMP"}, {0xD4, "PEI"}, {0xD5, "CMP"}, {0xD6, "DEC"},
{0xD7, "CMP"}, {0xD8, "CLD"}, {0xD9, "CMP"}, {0xDA, "PHX"}, {0xDB, "STP"},
{0xDC, "JMP"}, {0xDD, "CMP"}, {0xDE, "DEC"}, {0xDF, "CMP"}, {0xE0, "CPX"},
{0xE1, "SBC"}, {0xE2, "SEP"}, {0xE3, "SBC"}, {0xE4, "CPX"}, {0xE5, "SBC"},
{0xE6, "INC"}, {0xE7, "SBC"}, {0xE8, "INX"}, {0xE9, "SBC"}, {0xEA, "NOP"},
{0xEB, "XBA"}, {0xEC, "CPX"}, {0xED, "SBC"}, {0xEE, "INC"}, {0xEF, "SBC"},
{0xF0, "BEQ"}, {0xF1, "SBC"}, {0xF2, "SBC"}, {0xF3, "SBC"}, {0xF4, "PEA"},
{0xF5, "SBC"}, {0xF6, "INC"}, {0xF7, "SBC"}, {0xF8, "SED"}, {0xF9, "SBC"},
{0xFA, "PLX"}, {0xFB, "XCE"}, {0xFC, "JSR"}, {0xFD, "SBC"}, {0xFE, "INC"},
{0xFF, "SBC"}
};