mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-11 02:29:50 +00:00
6502: I might regret this, but move to a vector of instructions, rather than decoding them one at a time
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
43573ac699
commit
d57cb8c9be
@ -13,21 +13,6 @@
|
||||
namespace EightBit {
|
||||
class MOS6502 : public Processor {
|
||||
public:
|
||||
struct opcode_decoded_t {
|
||||
|
||||
int aaa = 0;
|
||||
int bbb = 0;
|
||||
int cc = 0;
|
||||
|
||||
opcode_decoded_t() {}
|
||||
|
||||
opcode_decoded_t(uint8_t opcode) {
|
||||
aaa = (opcode & 0b11100000) >> 5; // 0 - 7
|
||||
bbb = (opcode & 0b00011100) >> 2; // 0 - 7
|
||||
cc = (opcode & 0b00000011); // 0 - 3
|
||||
}
|
||||
};
|
||||
|
||||
enum StatusBits {
|
||||
NF = Bit7, // Negative
|
||||
VF = Bit6, // Overflow
|
||||
@ -196,10 +181,6 @@ namespace EightBit {
|
||||
|
||||
// Addressing modes, write
|
||||
|
||||
void AM_A(uint8_t value) {
|
||||
A() = value;
|
||||
}
|
||||
|
||||
void AM_Absolute(uint8_t value) {
|
||||
Address_Absolute();
|
||||
setByte(MEMPTR(), value);
|
||||
@ -240,343 +221,44 @@ namespace EightBit {
|
||||
setByte(MEMPTR(), value);
|
||||
}
|
||||
|
||||
// 6502 addressing mode switching
|
||||
|
||||
uint8_t AM_00(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX();
|
||||
case 0b010:
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void AM_00(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b001:
|
||||
AM_ZeroPage(value);
|
||||
break;
|
||||
case 0b011:
|
||||
AM_Absolute(value);
|
||||
break;
|
||||
case 0b101:
|
||||
AM_ZeroPageX(value);
|
||||
break;
|
||||
case 0b111:
|
||||
AM_AbsoluteX(value);
|
||||
break;
|
||||
case 0b000:
|
||||
case 0b010:
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AM_01(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_IndexedIndirectX();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b010:
|
||||
return AM_Immediate();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b100:
|
||||
return AM_IndirectIndexedY();
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b110:
|
||||
return AM_AbsoluteY();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX();
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void AM_01(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
AM_IndexedIndirectX(value);
|
||||
break;
|
||||
case 0b001:
|
||||
AM_ZeroPage(value);
|
||||
break;
|
||||
case 0b010:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
case 0b011:
|
||||
AM_Absolute(value);
|
||||
break;
|
||||
case 0b100:
|
||||
AM_IndirectIndexedY(value);
|
||||
break;
|
||||
case 0b101:
|
||||
AM_ZeroPageX(value);
|
||||
break;
|
||||
case 0b110:
|
||||
AM_AbsoluteY(value);
|
||||
break;
|
||||
case 0b111:
|
||||
AM_AbsoluteX(value);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AM_10(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b010:
|
||||
return AM_A();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX();
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void AM_10(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b010:
|
||||
AM_A(value);
|
||||
break;
|
||||
case 0b001:
|
||||
case 0b011:
|
||||
case 0b101:
|
||||
case 0b111:
|
||||
setByte(value);
|
||||
break;
|
||||
case 0b000:
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AM_10_x(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b010:
|
||||
return AM_A();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b101:
|
||||
return AM_ZeroPageY();
|
||||
case 0b111:
|
||||
return AM_AbsoluteY();
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void AM_10_x(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b001:
|
||||
AM_ZeroPage(value);
|
||||
break;
|
||||
case 0b010:
|
||||
AM_A(value);
|
||||
break;
|
||||
case 0b011:
|
||||
AM_Absolute(value);
|
||||
break;
|
||||
case 0b101:
|
||||
AM_ZeroPageY(value);
|
||||
break;
|
||||
case 0b111:
|
||||
AM_AbsoluteY(value);
|
||||
break;
|
||||
case 0b000:
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AM_11(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_IndexedIndirectX();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b010:
|
||||
return AM_Immediate();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b100:
|
||||
return AM_IndirectIndexedY();
|
||||
case 0b101:
|
||||
return AM_ZeroPageY();
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
case 0b111:
|
||||
return AM_AbsoluteY();
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void AM_11(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
AM_IndexedIndirectX(value);
|
||||
break;
|
||||
case 0b001:
|
||||
AM_ZeroPage(value);
|
||||
break;
|
||||
case 0b011:
|
||||
AM_Absolute(value);
|
||||
break;
|
||||
case 0b100:
|
||||
AM_IndirectIndexedY(value);
|
||||
break;
|
||||
case 0b101:
|
||||
AM_ZeroPageY(value);
|
||||
break;
|
||||
case 0b111:
|
||||
AM_AbsoluteY(value);
|
||||
break;
|
||||
case 0b010:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AM_11_x(int bbb) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_IndexedIndirectX();
|
||||
case 0b001:
|
||||
return AM_ZeroPage();
|
||||
case 0b010:
|
||||
return AM_Immediate();
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b100:
|
||||
return AM_IndirectIndexedY();
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b110:
|
||||
return AM_AbsoluteY();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX();
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void AM_11_x(int bbb, uint8_t value) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
AM_IndexedIndirectX(value);
|
||||
break;
|
||||
case 0b001:
|
||||
AM_ZeroPage(value);
|
||||
break;
|
||||
case 0b011:
|
||||
AM_Absolute(value);
|
||||
break;
|
||||
case 0b100:
|
||||
AM_IndirectIndexedY(value);
|
||||
break;
|
||||
case 0b101:
|
||||
AM_ZeroPageX(value);
|
||||
break;
|
||||
case 0b110:
|
||||
AM_AbsoluteY(value);
|
||||
break;
|
||||
case 0b111:
|
||||
AM_AbsoluteX(value);
|
||||
break;
|
||||
case 0b010:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Operations
|
||||
|
||||
void ASL(int bbb) {
|
||||
const auto result = ASL(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void DCP(uint8_t value) {
|
||||
setByte(--value);
|
||||
CMP(A(), value);
|
||||
}
|
||||
|
||||
void ROL(int bbb) {
|
||||
const auto result = ROL(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void ISB(uint8_t value) {
|
||||
setByte(++value);
|
||||
A() = SBC(A(), value);
|
||||
}
|
||||
|
||||
void LSR(int bbb) {
|
||||
const auto result = LSR(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void SLO(uint8_t value) {
|
||||
const auto result = ASL(value);
|
||||
setByte(result);
|
||||
ORA(result);
|
||||
}
|
||||
|
||||
void ROR(int bbb) {
|
||||
const auto result = ROR(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void SRE(uint8_t value) {
|
||||
const auto result = LSR(value);
|
||||
setByte(result);
|
||||
EORA(result);
|
||||
}
|
||||
|
||||
void DEC(int bbb) {
|
||||
const auto result = DEC(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void RLA(uint8_t value) {
|
||||
const auto result = ROL(value);
|
||||
setByte(result);
|
||||
ANDA(result);
|
||||
}
|
||||
|
||||
void INC(int bbb) {
|
||||
const auto result = INC(AM_10(bbb));
|
||||
AM_10(bbb, result);
|
||||
void RRA(uint8_t value) {
|
||||
const auto result = ROR(value);
|
||||
setByte(result);
|
||||
A() = ADC(A(), result);
|
||||
}
|
||||
|
||||
void DCP(int bbb) {
|
||||
auto operand = AM_11_x(bbb);
|
||||
setByte(--operand);
|
||||
CMP(A(), operand);
|
||||
}
|
||||
|
||||
void ISB(int bbb) {
|
||||
auto operand = AM_01(bbb);
|
||||
setByte(++operand);
|
||||
A() = SBC(A(), operand);
|
||||
void LAX(uint8_t value) {
|
||||
adjustNZ(X() = A() = value);
|
||||
}
|
||||
|
||||
//
|
||||
@ -597,38 +279,14 @@ namespace EightBit {
|
||||
adjustNZ(A() |= value);
|
||||
}
|
||||
|
||||
void SLO(int bbb) {
|
||||
const auto result = ASL(AM_01(bbb));
|
||||
setByte(result);
|
||||
ORA(result);
|
||||
}
|
||||
|
||||
void ANDA(uint8_t value) {
|
||||
adjustNZ(A() &= value);
|
||||
}
|
||||
|
||||
void RLA(int bbb) {
|
||||
const auto result = ROL(AM_01(bbb));
|
||||
setByte(result);
|
||||
ANDA(result);
|
||||
}
|
||||
|
||||
void EORA(uint8_t value) {
|
||||
adjustNZ(A() ^= value);
|
||||
}
|
||||
|
||||
void SRE(int bbb) {
|
||||
const auto result = LSR(AM_01(bbb));
|
||||
setByte(result);
|
||||
EORA(result);
|
||||
}
|
||||
|
||||
void RRA(int bbb) {
|
||||
const auto result = ROR(AM_01(bbb));
|
||||
setByte(result);
|
||||
A() = ADC(A(), result);
|
||||
}
|
||||
|
||||
uint8_t ROR(uint8_t value);
|
||||
|
||||
uint8_t LSR(uint8_t value);
|
||||
@ -668,8 +326,13 @@ namespace EightBit {
|
||||
uint8_t s; // stack pointer
|
||||
uint8_t p; // processor status
|
||||
|
||||
std::array<int, 0x100> m_timings;
|
||||
std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
|
||||
typedef std::function<void(void)> delegate_t;
|
||||
struct operation_t {
|
||||
int timing = 0;
|
||||
delegate_t method;
|
||||
};
|
||||
|
||||
std::vector<operation_t> m_operations;
|
||||
|
||||
PinLevel m_soLine = Low;
|
||||
};
|
||||
|
@ -3,29 +3,281 @@
|
||||
|
||||
EightBit::MOS6502::MOS6502(Bus& bus)
|
||||
: Processor(bus) {
|
||||
m_timings = {
|
||||
//// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
/* 0 */ 7, 6, 0, 8, 3, 3, 5, 5, 3, 2, 2, 0, 4, 4, 6, 6,
|
||||
/* 1 */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
/* 2 */ 6, 6, 0, 8, 3, 3, 5, 5, 4, 2, 2, 0, 4, 4, 6, 6,
|
||||
/* 3 */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
/* 4 */ 6, 6, 0, 8, 3, 3, 5, 5, 3, 2, 2, 0, 3, 4, 6, 6,
|
||||
/* 5 */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
/* 6 */ 6, 6, 0, 8, 3, 3, 5, 5, 4, 2, 2, 0, 5, 4, 6, 6,
|
||||
/* 7 */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
/* 8 */ 2, 6, 0, 6, 3, 3, 3, 3, 2, 0, 2, 0, 4, 4, 4, 4,
|
||||
/* 9 */ 2, 6, 0, 0, 4, 4, 4, 4, 2, 5, 2, 0, 0, 5, 0, 0,
|
||||
/* A */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 0, 4, 4, 4, 4,
|
||||
/* B */ 2, 5, 0, 5, 4, 4, 4, 4, 2, 4, 2, 0, 4, 4, 4, 4,
|
||||
/* C */ 2, 6, 0, 8, 3, 3, 5, 5, 2, 2, 2, 0, 4, 4, 6, 6,
|
||||
/* D */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
/* E */ 2, 6, 0, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,
|
||||
/* F */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
|
||||
};
|
||||
|
||||
|
||||
for (int i = 0; i < 0x100; ++i)
|
||||
m_decodedOpcodes[i] = i;
|
||||
m_operations = {
|
||||
/* 0 */
|
||||
/* 0 */ { 7, [this]() { BRK(); } },
|
||||
/* 1 */ { 6, [this]() { ORA(AM_IndexedIndirectX()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 8, [this]() { SLO(AM_IndexedIndirectX()); } }, // *SLO
|
||||
/* 4 */ { 3, [this]() { AM_ZeroPage(); } }, // *DOP
|
||||
/* 5 */ { 3, [this]() { ORA(AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(ASL(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { SLO(AM_ZeroPage()); } }, // *SLO
|
||||
/* 8 */ { 3, [this]() { PHP(); } },
|
||||
/* 9 */ { 2, [this]() { ORA(AM_Immediate()); } },
|
||||
/* a */ { 2, [this]() { A() = ASL(A()); } },
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { AM_Absolute(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { ORA(AM_Absolute()); } },
|
||||
/* e */ { 6, [this]() { setByte(ASL(AM_Absolute())); } },
|
||||
/* f */ { 6, [this]() { SLO(AM_Absolute()); } }, // *SLO
|
||||
/* 1 */
|
||||
/* 0 */ { 2, [this]() { Branch(!(P() & NF)); } },
|
||||
/* 1 */ { 5, [this]() { ORA(AM_IndirectIndexedY()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { SLO(AM_IndirectIndexedY()); } }, // *SLO
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { ORA(AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(ASL(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { SLO(AM_ZeroPageX()); } }, // *SLO
|
||||
/* 8 */ { 2, [this]() { clearFlag(P(), CF); } },
|
||||
/* 9 */ { 4, [this]() { ORA(AM_AbsoluteY()); } },
|
||||
/* a */ { 2, []() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { SLO(AM_AbsoluteY()); } }, // *SLO
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { ORA(AM_AbsoluteX()); } },
|
||||
/* e */ { 7, [this]() { setByte(ASL(AM_AbsoluteX())); } },
|
||||
/* f */ { 6, [this]() { SLO(AM_AbsoluteX()); } }, // *SLO
|
||||
/* 2 */
|
||||
/* 0 */ { 6, [this]() { JSR_abs(); } },
|
||||
/* 1 */ { 6, [this]() { ANDA(AM_IndexedIndirectX()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 8, [this]() { RLA(AM_IndexedIndirectX()); } }, // *RLA
|
||||
/* 4 */ { 3, [this]() { BIT(AM_ZeroPage()); } },
|
||||
/* 5 */ { 3, [this]() { ANDA(AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(ROL(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { RLA(AM_ZeroPage()); } }, // *RLA
|
||||
/* 8 */ { 4, [this]() { PLP(); } },
|
||||
/* 9 */ { 2, [this]() { ANDA(AM_Immediate()); } },
|
||||
/* a */ { 2, [this]() { A() = ROL(A()); } },
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { BIT(AM_Absolute()); } },
|
||||
/* d */ { 4, [this]() { ANDA(AM_Absolute()); } },
|
||||
/* e */ { 6, [this]() { setByte(ROL(AM_Absolute())); } },
|
||||
/* f */ { 6, [this]() { RLA(AM_Absolute()); } }, // *RLA
|
||||
/* 3 */
|
||||
/* 0 */ { 2, [this]() { Branch(!!(P() & NF)); } },
|
||||
/* 1 */ { 5, [this]() { ANDA(AM_IndirectIndexedY()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { RLA(AM_IndirectIndexedY()); } }, // *RLA
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { ANDA(AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(ROL(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { RLA(AM_ZeroPageX()); } }, // *RLA
|
||||
/* 8 */ { 2, [this]() { setFlag(P(), CF); } },
|
||||
/* 9 */ { 4, [this]() { ANDA(AM_AbsoluteY()); } },
|
||||
/* a */ { 2, []() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { RLA(AM_AbsoluteY()); } }, // *RLA
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { ANDA(AM_AbsoluteX()); } },
|
||||
/* e */ { 7, [this]() { setByte(ROL(AM_AbsoluteX())); } },
|
||||
/* f */ { 6, [this]() { RLA(AM_AbsoluteX()); } }, // *RLA
|
||||
/* 4 */
|
||||
/* 0 */ { 6, [this]() { RTI(); } },
|
||||
/* 1 */ { 6, [this]() { EORA(AM_IndexedIndirectX()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 8, [this]() { SRE(AM_IndexedIndirectX()); } }, // *SRE
|
||||
/* 4 */ { 3, [this]() { AM_ZeroPage(); } }, // *DOP
|
||||
/* 5 */ { 3, [this]() { EORA(AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(LSR(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { SRE(AM_ZeroPage()); } }, // *SRE
|
||||
/* 8 */ { 3, [this]() { push(A()); } },
|
||||
/* 9 */ { 2, [this]() { EORA(AM_Immediate()); } },
|
||||
/* a */ { 2, [this]() { A() = LSR(A()); } },
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 3, [this]() { JMP_abs(); } },
|
||||
/* d */ { 4, [this]() { EORA(AM_Absolute()); } },
|
||||
/* e */ { 6, [this]() { setByte(LSR(AM_Absolute())); } },
|
||||
/* f */ { 6, [this]() { SRE(AM_Absolute()); } }, // *SRE
|
||||
/* 5 */
|
||||
/* 0 */ { 2, [this]() { Branch(!(P() & VF)); } }, // *SRE
|
||||
/* 1 */ { 5, [this]() { EORA(AM_IndirectIndexedY()); } },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { SRE(AM_IndirectIndexedY()); } }, // *SRE
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPage(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { EORA(AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(LSR(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { SRE(AM_ZeroPageX()); } }, // *SRE
|
||||
/* 8 */ { 2, [this]() { clearFlag(P(), IF); } },
|
||||
/* 9 */ { 4, [this]() { EORA(AM_AbsoluteY()); } },
|
||||
/* a */ { 2, []() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { SRE(AM_AbsoluteY()); } }, // *SRE
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { EORA(AM_AbsoluteX()); } },
|
||||
/* e */ { 7, [this]() { setByte(LSR(AM_AbsoluteX())); } },
|
||||
/* f */ { 6, [this]() { SRE(AM_AbsoluteX()); } }, // *SRE
|
||||
/* 6 */
|
||||
/* 0 */ { 6, [this]() { RTS(); } },
|
||||
/* 1 */ { 6, [this]() { A() = ADC(A(), AM_IndexedIndirectX());} },
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 8, [this]() { RRA(AM_IndexedIndirectX()); } }, // *RRA
|
||||
/* 4 */ { 3, [this]() { AM_ZeroPage(); } }, // *DOP
|
||||
/* 5 */ { 3, [this]() { A() = ADC(A(), AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(ROR(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { RRA(AM_ZeroPage()); } }, // *RRA
|
||||
/* 8 */ { 4, [this]() { adjustNZ(A() = pop()); } },
|
||||
/* 9 */ { 2, [this]() { A() = ADC(A(), AM_Immediate()); } }, // ADC #
|
||||
/* a */ { 2, [this]() { A() = ROR(A()); } }, // ROR A
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 5, [this]() { JMP_ind(); } }, // JMP ind
|
||||
/* d */ { 4, [this]() { A() = ADC(A(), AM_Absolute()); } }, // ADC abs
|
||||
/* e */ { 6, [this]() { setByte(ROR(AM_Absolute())); } }, // ROR abs
|
||||
/* f */ { 6, [this]() { RRA(AM_Absolute()); } }, // *RRA
|
||||
/* 7 */
|
||||
/* 0 */ { 2, [this]() { Branch(!!(P() & VF)); } },
|
||||
/* 1 */ { 5, [this]() { A() = ADC(A(), AM_IndirectIndexedY());} }, // ADC ind,Y
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { RRA(AM_IndirectIndexedY()); } }, // *RRA
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { A() = ADC(A(), AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(ROR(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { RRA(AM_ZeroPageX()); } }, // *RRA
|
||||
/* 8 */ { 2, [this]() { setFlag(P(), IF); } },
|
||||
/* 9 */ { 4, [this]() { A() = ADC(A(), AM_AbsoluteY()); } }, // ADC abs,Y
|
||||
/* a */ { 2, [this]() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { RRA(AM_AbsoluteY()); } }, // *RRA
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { A() = ADC(A(), AM_AbsoluteX()); } }, // ADC abs,X
|
||||
/* e */ { 7, [this]() { setByte(ROR(AM_AbsoluteX())); } }, // ROR abs,X
|
||||
/* f */ { 6, [this]() { RRA(AM_AbsoluteX()); } }, // *RRA
|
||||
/* 8 */
|
||||
/* 0 */ { 2, [this]() { AM_Immediate(); } }, // *DOP
|
||||
/* 1 */ { 6, [this]() { AM_IndexedIndirectX(A()); } },
|
||||
/* 2 */ { 2, [this]() { AM_Immediate(); } }, // *DOP
|
||||
/* 3 */ { 6, [this]() { AM_IndexedIndirectX(A() & X()); } }, // *SAX
|
||||
/* 4 */ { 3, [this]() { AM_ZeroPage(Y()); } }, // STY zpg
|
||||
/* 5 */ { 3, [this]() { AM_ZeroPage(A()); } },
|
||||
/* 6 */ { 3, [this]() { AM_ZeroPage(X()); } },
|
||||
/* 7 */ { 3, [this]() { AM_ZeroPage(A() & X()); } }, // *SAX
|
||||
/* 8 */ { 2, [this]() { adjustNZ(--Y()); } },
|
||||
/* 9 */ { 2, [this]() { AM_Immediate(); } }, // *DOP
|
||||
/* a */ { 2, [this]() { adjustNZ(A() = X()); } }, // TXA impl
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { AM_Absolute(Y()); } }, // STY abs
|
||||
/* d */ { 4, [this]() { AM_Absolute(A()); } },
|
||||
/* e */ { 4, [this]() { AM_Absolute(X()); } }, // STX abs
|
||||
/* f */ { 4, [this]() { AM_Absolute(A() & X()); } }, // *SAX
|
||||
/* 9 */
|
||||
/* 0 */ { 2, [this]() { Branch(!(P() & CF)); } },
|
||||
/* 1 */ { 6, [this]() { AM_IndirectIndexedY(A()); } }, // STA ind,Y
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 0, []() { } },
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(Y()); } }, // STY zpg,X
|
||||
/* 5 */ { 4, [this]() { AM_ZeroPageX(A()); } },
|
||||
/* 6 */ { 4, [this]() { AM_ZeroPageY(X()); } },
|
||||
/* 7 */ { 4, [this]() { AM_ZeroPageY(A() & X()); } }, // *SAX
|
||||
/* 8 */ { 2, [this]() { adjustNZ(A() = Y()); } },
|
||||
/* 9 */ { 5, [this]() { AM_AbsoluteY(A()); } }, // STA abs,Y
|
||||
/* a */ { 2, [this]() { S() = X(); } },
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 0, []() { } },
|
||||
/* d */ { 5, [this]() { AM_AbsoluteX(A()); } }, // STA abs,X
|
||||
/* e */ { 0, []() { } },
|
||||
/* f */ { 0, []() { } },
|
||||
/* A */
|
||||
/* 0 */ { 2, [this]() { adjustNZ(Y() = AM_Immediate()); } },
|
||||
/* 1 */ { 6, [this]() { adjustNZ(A() = AM_IndexedIndirectX());} },
|
||||
/* 2 */ { 2, [this]() { adjustNZ(X() = AM_Immediate()); } },
|
||||
/* 3 */ { 6, [this]() { LAX(AM_IndexedIndirectX()); } }, // *LAX
|
||||
/* 4 */ { 3, [this]() { adjustNZ(Y() = AM_ZeroPage()); } }, // LDY zpg
|
||||
/* 5 */ { 3, [this]() { adjustNZ(A() = AM_ZeroPage()); } },
|
||||
/* 6 */ { 3, [this]() { adjustNZ(X() = AM_ZeroPage()); } },
|
||||
/* 7 */ { 3, [this]() { LAX(AM_ZeroPage()); } }, // *LAX
|
||||
/* 8 */ { 2, [this]() { adjustNZ(Y() = A()); } },
|
||||
/* 9 */ { 2, [this]() { adjustNZ(A() = AM_Immediate()); } },
|
||||
/* a */ { 2, [this]() { adjustNZ(X() = A()); } }, // TAX imp
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { adjustNZ(Y() = AM_Absolute()); } }, // LDY abs
|
||||
/* d */ { 4, [this]() { adjustNZ(A() = AM_Absolute()); } }, // LDA abs
|
||||
/* e */ { 4, [this]() { adjustNZ(X() = AM_Absolute()); } }, // LDX abs
|
||||
/* f */ { 4, [this]() { LAX(AM_Absolute()); } }, // *LAX
|
||||
/* B */
|
||||
/* 0 */ { 2, [this]() { Branch(!!(P() & CF)); } },
|
||||
/* 1 */ { 5, [this]() { adjustNZ(A() = AM_IndirectIndexedY());} }, // LDA ind,Y
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 5, [this]() { LAX(AM_IndirectIndexedY()); } }, // *LAX
|
||||
/* 4 */ { 4, [this]() { adjustNZ(Y() = AM_ZeroPageX()); } }, // LDY zpg,X
|
||||
/* 5 */ { 4, [this]() { adjustNZ(A() = AM_ZeroPageX()); } },
|
||||
/* 6 */ { 4, [this]() { adjustNZ(X() = AM_ZeroPageY()); } },
|
||||
/* 7 */ { 4, [this]() { LAX(AM_ZeroPageY()); } }, // *LAX
|
||||
/* 8 */ { 2, [this]() { clearFlag(P(), VF); } },
|
||||
/* 9 */ { 4, [this]() { adjustNZ(A() = AM_AbsoluteY()); } }, // LDA abs,Y
|
||||
/* a */ { 2, [this]() { adjustNZ(X() = S()); } }, // TSX impl
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { adjustNZ(Y() = AM_AbsoluteX()); } }, // LDY abs,X
|
||||
/* d */ { 4, [this]() { adjustNZ(A() = AM_AbsoluteX()); } }, // LDA abs,X
|
||||
/* e */ { 4, [this]() { adjustNZ(X() = AM_AbsoluteY()); } }, // LDX abs,Y
|
||||
/* f */ { 4, [this]() { LAX(AM_AbsoluteY()); } }, // *LAX
|
||||
/* C */
|
||||
/* 0 */ { 2, [this]() { CMP(Y(), AM_Immediate()); } },
|
||||
/* 1 */ { 6, [this]() { CMP(A(), AM_IndexedIndirectX()); } },
|
||||
/* 2 */ { 2, [this]() { AM_Immediate(); } }, // *DOP
|
||||
/* 3 */ { 8, [this]() { DCP(AM_IndexedIndirectX()); } }, // *DCP
|
||||
/* 4 */ { 3, [this]() { CMP(Y(), AM_ZeroPage()); } }, // CPY zpg
|
||||
/* 5 */ { 3, [this]() { CMP(A(), AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(DEC(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { DCP(AM_ZeroPage()); } }, // *DCP
|
||||
/* 8 */ { 2, [this]() { adjustNZ(++Y()); } },
|
||||
/* 9 */ { 2, [this]() { CMP(A(), AM_Immediate()); } }, // CMP #
|
||||
/* a */ { 2, [this]() { adjustNZ(--X()); } },
|
||||
/* b */ { 0, []() { } },
|
||||
/* c */ { 4, [this]() { CMP(Y(), AM_Absolute()); } }, // CPY abs
|
||||
/* d */ { 4, [this]() { CMP(A(), AM_Absolute()); } }, // CMP abs
|
||||
/* e */ { 6, [this]() { setByte(DEC(AM_Absolute())); } }, // DEC abs
|
||||
/* f */ { 6, [this]() { DCP(AM_Absolute()); } }, // *DCP
|
||||
/* D */
|
||||
/* 0 */ { 2, [this]() { Branch(!(P() & ZF)); } },
|
||||
/* 1 */ { 5, [this]() { CMP(A(), AM_IndirectIndexedY()); } }, // CMP ind,Y
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { DCP(AM_IndirectIndexedY()); } }, // *DCP
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { CMP(A(), AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(DEC(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { DCP(AM_ZeroPageX()); } }, // *DCP
|
||||
/* 8 */ { 2, [this]() { clearFlag(P(), DF); } },
|
||||
/* 9 */ { 4, [this]() { CMP(A(), AM_AbsoluteY()); } }, // CMP abs,Y
|
||||
/* a */ { 2, [this]() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { DCP(AM_AbsoluteY()); } }, // *DCP
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { CMP(A(), AM_AbsoluteX()); } }, // CMP abs,X
|
||||
/* e */ { 7, [this]() { setByte(DEC(AM_AbsoluteX())); } },
|
||||
/* f */ { 6, [this]() { DCP(AM_AbsoluteX()); } }, // *DCP
|
||||
/* E */
|
||||
/* 0 */ { 2, [this]() { CMP(X(), AM_Immediate()); } },
|
||||
/* 1 */ { 6, [this]() { A() = SBC(A(), AM_IndexedIndirectX());} },
|
||||
/* 2 */ { 2, [this]() { AM_Immediate(); } }, // *DOP
|
||||
/* 3 */ { 8, [this]() { ISB(AM_IndexedIndirectX()); } }, // *ISB
|
||||
/* 4 */ { 3, [this]() { CMP(X(), AM_ZeroPage()); } }, // CPX zpg
|
||||
/* 5 */ { 3, [this]() { A() = SBC(A(), AM_ZeroPage()); } },
|
||||
/* 6 */ { 5, [this]() { setByte(INC(AM_ZeroPage())); } },
|
||||
/* 7 */ { 5, [this]() { ISB(AM_ZeroPage()); } }, // *ISB
|
||||
/* 8 */ { 2, [this]() { adjustNZ(++X()); } },
|
||||
/* 9 */ { 2, [this]() { A() = SBC(A(), AM_Immediate()); } }, // SBC #
|
||||
/* a */ { 2, [this]() { } }, // NOP
|
||||
/* b */ { 2, [this]() { A() = SBC(A(), AM_Immediate()); } }, // *SBC
|
||||
/* c */ { 4, [this]() { CMP(X(), AM_Absolute()); } }, // CPX abs
|
||||
/* d */ { 4, [this]() { A() = SBC(A(), AM_Absolute()); } }, // SBC abs
|
||||
/* e */ { 6, [this]() { setByte(INC(AM_Absolute())); } }, // INC abs
|
||||
/* f */ { 6, [this]() { ISB(AM_Absolute()); } }, // *ISB
|
||||
/* F */
|
||||
/* 0 */ { 2, [this]() { Branch(!!(P() & ZF)); } },
|
||||
/* 1 */ { 5, [this]() { A() = SBC(A(), AM_IndirectIndexedY());} }, // SBC ind,Y
|
||||
/* 2 */ { 0, []() { } },
|
||||
/* 3 */ { 7, [this]() { ISB(AM_IndirectIndexedY()); } }, // *ISB
|
||||
/* 4 */ { 4, [this]() { AM_ZeroPageX(); } }, // *DOP
|
||||
/* 5 */ { 4, [this]() { A() = SBC(A(), AM_ZeroPageX()); } },
|
||||
/* 6 */ { 6, [this]() { setByte(INC(AM_ZeroPageX())); } },
|
||||
/* 7 */ { 6, [this]() { ISB(AM_ZeroPageX()); } }, // *ISB
|
||||
/* 8 */ { 2, [this]() { setFlag(P(), DF); } },
|
||||
/* 9 */ { 4, [this]() { A() = SBC(A(), AM_AbsoluteY()); } }, // SBC abs,Y
|
||||
/* a */ { 2, [this]() { } }, // *NOP
|
||||
/* b */ { 6, [this]() { ISB(AM_AbsoluteY()); } }, // *ISB
|
||||
/* c */ { 4, [this]() { AM_AbsoluteX(); } }, // *TOP
|
||||
/* d */ { 4, [this]() { A() = SBC(A(), AM_AbsoluteX()); } }, // SBC abs,X
|
||||
/* e */ { 7, [this]() { setByte(INC(AM_AbsoluteX())); } }, // INC abs,X
|
||||
/* f */ { 6, [this]() { ISB(AM_AbsoluteX()); } } // *ISB
|
||||
} ;
|
||||
|
||||
X() = Bit7;
|
||||
Y() = 0;
|
||||
@ -87,374 +339,10 @@ void EightBit::MOS6502::interrupt(uint8_t vector) {
|
||||
|
||||
int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
|
||||
addCycles(m_timings[cell]);
|
||||
const operation_t& operation = m_operations[cell];
|
||||
|
||||
// http://www.llx.com/~nparker/a2/opcodes.html
|
||||
|
||||
// Most instructions that explicitly reference memory
|
||||
// locations have bit patterns of the form aaabbbcc.
|
||||
// The aaa and cc bits determine the opcode, and the bbb
|
||||
// bits determine the addressing mode.
|
||||
|
||||
const auto& decoded = m_decodedOpcodes[cell];
|
||||
|
||||
switch (decoded.cc) {
|
||||
case 0b00:
|
||||
switch (decoded.aaa) {
|
||||
case 0b000:
|
||||
switch (decoded.bbb) {
|
||||
case 0b000: // BRK
|
||||
BRK();
|
||||
break;
|
||||
case 0b001: // DOP/NOP (0x04)
|
||||
AM_ZeroPage();
|
||||
break;
|
||||
case 0b010: // PHP
|
||||
PHP();
|
||||
break;
|
||||
case 0b011: // TOP/NOP (0b00001100, 0x0c)
|
||||
AM_Absolute();
|
||||
break;
|
||||
case 0b100: // BPL
|
||||
Branch(!(P() & NF));
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0x14)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // CLC
|
||||
clearFlag(P(), CF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b00011100, 0x1c)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default:
|
||||
throw std::domain_error("Illegal instruction");
|
||||
}
|
||||
break;
|
||||
case 0b001:
|
||||
switch (decoded.bbb) {
|
||||
case 0b000: // JSR
|
||||
JSR_abs();
|
||||
break;
|
||||
case 0b010: // PLP
|
||||
PLP();
|
||||
break;
|
||||
case 0b100: // BMI
|
||||
Branch((P() & NF) != 0);
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0x34)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // SEC
|
||||
setFlag(P(), CF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b00111100, 0x3c)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default: // BIT
|
||||
BIT(AM_00(decoded.bbb));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b010:
|
||||
switch (decoded.bbb) {
|
||||
case 0b000: // RTI
|
||||
RTI();
|
||||
break;
|
||||
case 0b001: // DOP/NOP (0x44)
|
||||
AM_ZeroPage();
|
||||
break;
|
||||
case 0b010: // PHA
|
||||
push(A());
|
||||
break;
|
||||
case 0b011: // JMP
|
||||
JMP_abs();
|
||||
break;
|
||||
case 0b100: // BVC
|
||||
Branch(!(P() & VF));
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0x54)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // CLI
|
||||
clearFlag(P(), IF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b01011100, 0x5c)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
}
|
||||
break;
|
||||
case 0b011:
|
||||
switch (decoded.bbb) {
|
||||
case 0b000: // RTS
|
||||
RTS();
|
||||
break;
|
||||
case 0b001: // DOP/NOP (0x64)
|
||||
AM_ZeroPage();
|
||||
break;
|
||||
case 0b010: // PLA
|
||||
adjustNZ(A() = pop());
|
||||
break;
|
||||
case 0b011: // JMP (abs)
|
||||
JMP_ind();
|
||||
break;
|
||||
case 0b100: // BVS
|
||||
Branch((P() & VF) != 0);
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0x74)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // SEI
|
||||
setFlag(P(), IF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b01111100, 0x7c)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
}
|
||||
break;
|
||||
case 0b100:
|
||||
switch (decoded.bbb) {
|
||||
case 0b000: // DOP/NOP (0x80)
|
||||
AM_Immediate();
|
||||
break;
|
||||
case 0b010: // DEY
|
||||
adjustNZ(--Y());
|
||||
break;
|
||||
case 0b100: // BCC
|
||||
Branch(!(P() & CF));
|
||||
break;
|
||||
case 0b110: // TYA
|
||||
adjustNZ(A() = Y());
|
||||
break;
|
||||
default: // STY
|
||||
AM_00(decoded.bbb, Y());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b101:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // TAY
|
||||
adjustNZ(Y() = A());
|
||||
break;
|
||||
case 0b100: // BCS
|
||||
Branch((P() & CF) != 0);
|
||||
break;
|
||||
case 0b110: // CLV
|
||||
clearFlag(P(), VF);
|
||||
break;
|
||||
default: // LDY
|
||||
adjustNZ(Y() = AM_00(decoded.bbb));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b110:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // INY
|
||||
adjustNZ(++Y());
|
||||
break;
|
||||
case 0b100: // BNE
|
||||
Branch(!(P() & ZF));
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0xd4)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // CLD
|
||||
clearFlag(P(), DF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b11011100, 0xdc)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default: // CPY
|
||||
CMP(Y(), AM_00(decoded.bbb));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b111:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // INX
|
||||
adjustNZ(++X());
|
||||
break;
|
||||
case 0b100: // BEQ
|
||||
Branch((P() & ZF) != 0);
|
||||
break;
|
||||
case 0b101: // DOP/NOP (0xf4)
|
||||
AM_ZeroPageX();
|
||||
break;
|
||||
case 0b110: // SED
|
||||
setFlag(P(), DF);
|
||||
break;
|
||||
case 0b111: // TOP/NOP (0b11111100, 0xfc)
|
||||
AM_AbsoluteX();
|
||||
break;
|
||||
default: // CPX
|
||||
CMP(X(), AM_00(decoded.bbb));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b01:
|
||||
switch (decoded.aaa) {
|
||||
case 0b000: // ORA
|
||||
ORA(AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b001: // AND
|
||||
ANDA(AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b010: // EOR
|
||||
EORA(AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b011: // ADC
|
||||
A() = ADC(A(), AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b100: // STA
|
||||
AM_01(decoded.bbb, A());
|
||||
break;
|
||||
case 0b101: // LDA
|
||||
adjustNZ(A() = AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b110: // CMP
|
||||
CMP(A(), AM_01(decoded.bbb));
|
||||
break;
|
||||
case 0b111: // SBC
|
||||
A() = SBC(A(), AM_01(decoded.bbb));
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
break;
|
||||
case 0b10:
|
||||
switch (decoded.aaa) {
|
||||
case 0b000: // ASL
|
||||
switch (decoded.bbb) {
|
||||
case 0b110:
|
||||
break; // *NOP (0x1a)
|
||||
default:
|
||||
ASL(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b001: // ROL
|
||||
switch (decoded.bbb) {
|
||||
case 0b110:
|
||||
break; // *NOP (0x3a)
|
||||
default:
|
||||
ROL(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b010: // LSR
|
||||
switch (decoded.bbb) {
|
||||
case 0b110:
|
||||
break; // *NOP (0x5a)
|
||||
default:
|
||||
LSR(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b011: // ROR (0x7a)
|
||||
switch (decoded.bbb) {
|
||||
case 0b110:
|
||||
break; // *NOP
|
||||
default:
|
||||
ROR(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b100:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // TXA
|
||||
adjustNZ(A() = X());
|
||||
break;
|
||||
case 0b110: // TXS
|
||||
S() = X();
|
||||
break;
|
||||
default: // STX
|
||||
AM_10_x(decoded.bbb, X());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b101:
|
||||
switch (decoded.bbb) {
|
||||
case 0b110: // TSX
|
||||
adjustNZ(X() = S());
|
||||
break;
|
||||
default: // LDX
|
||||
adjustNZ(X() = AM_10_x(decoded.bbb));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b110:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // DEX
|
||||
adjustNZ(--X());
|
||||
break;
|
||||
case 0b110: // *NOP (0xda)
|
||||
break;
|
||||
default: // DEC
|
||||
DEC(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0b111:
|
||||
switch (decoded.bbb) {
|
||||
case 0b010: // NOP
|
||||
break;
|
||||
case 0b110: // *NOP (0xfa)
|
||||
break;
|
||||
default: // INC
|
||||
INC(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
break;
|
||||
case 0b11:
|
||||
switch (decoded.aaa) {
|
||||
case 0b000: // *SLO
|
||||
SLO(decoded.bbb);
|
||||
break;
|
||||
case 0b001: // *RLA
|
||||
RLA(decoded.bbb);
|
||||
break;
|
||||
case 0b010: // *SRE
|
||||
SRE(decoded.bbb);
|
||||
break;
|
||||
case 0b011: // *RRA
|
||||
RRA(decoded.bbb);
|
||||
break;
|
||||
case 0b100: // *SAX
|
||||
AM_11(decoded.bbb, A() & X());
|
||||
break;
|
||||
case 0b101: // *LAX
|
||||
adjustNZ(X() = A() = AM_11(decoded.bbb));
|
||||
break;
|
||||
case 0b110: // *DCP
|
||||
DCP(decoded.bbb);
|
||||
break;
|
||||
case 0b111: // *SBC
|
||||
switch (decoded.bbb) {
|
||||
case 0b010:
|
||||
A() = SBC(A(), AM_11(decoded.bbb));
|
||||
break;
|
||||
default: // *ISB
|
||||
ISB(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::domain_error("Illegal instruction group");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
addCycles(operation.timing);
|
||||
(operation.method)();
|
||||
|
||||
if (UNLIKELY(cycles() == 0))
|
||||
throw std::logic_error("Unhandled opcode");
|
||||
|
Loading…
x
Reference in New Issue
Block a user