Correct loads of undocumented M6502 instructions

This commit is contained in:
Adrian Conlon 2024-01-05 12:52:27 +00:00
parent 72e548ae13
commit 5d24a136a2
2 changed files with 205 additions and 43 deletions

View File

@ -58,8 +58,8 @@ namespace EightBit {
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow) noexcept;
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow) noexcept;
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0) noexcept;
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data) noexcept;
@ -184,17 +184,82 @@ namespace EightBit {
void slo(uint8_t value) noexcept;
void sre(uint8_t value) noexcept;
// Unconditional page fixup cycle required
void fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
getBytePaged(unfixed_page, address.low); // Possible fixup for page boundary crossing
BUS().ADDRESS() = address;
}
// Complicated addressing mode implementations
void sta_AbsoluteX() noexcept;
void sta_AbsoluteY() noexcept;
void sta_IndirectIndexedY() noexcept;
void write_A_with_fixup(const register16_t& address, uint8_t unfixed_page) noexcept {
getBytePaged(unfixed_page, address.low); // Possible fixup for page boundary crossing
memoryWrite(address, A());
void sta_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
memoryWrite(A());
}
// Undocumented complicated mode implementations
// SLO
void slo_AbsoluteX() noexcept;
void slo_AbsoluteY() noexcept;
void slo_IndirectIndexedY() noexcept;
void slo_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
slo(memoryRead());
}
// ISB
void isb_AbsoluteX() noexcept;
void isb_AbsoluteY() noexcept;
void isb_IndirectIndexedY() noexcept;
void isb_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
isb(memoryRead());
}
// RLA
void rla_AbsoluteX() noexcept;
void rla_AbsoluteY() noexcept;
void rla_IndirectIndexedY() noexcept;
void rla_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
rla(memoryRead());
}
// RRA
void rra_AbsoluteX() noexcept;
void rra_AbsoluteY() noexcept;
void rra_IndirectIndexedY() noexcept;
void rra_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
rra(memoryRead());
}
// DCP
void dcp_AbsoluteX() noexcept;
void dcp_AbsoluteY() noexcept;
void dcp_IndirectIndexedY() noexcept;
void dcp_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
dcp(memoryRead());
}
// SRE
void sre_AbsoluteX() noexcept;
void sre_AbsoluteY() noexcept;
void sre_IndirectIndexedY() noexcept;
void sre_with_fixup(const register16_t address, const uint8_t unfixed_page) noexcept {
fixup(address, unfixed_page);
sre(memoryRead());
}
// NOP
void nop_AbsoluteX() noexcept;
uint8_t x = 0; // index register X
uint8_t y = 0; // index register Y
uint8_t a = 0; // accumulator

View File

@ -14,11 +14,11 @@ EightBit::MOS6502::MOS6502(Bus& bus) noexcept
});
}
DEFINE_PIN_LEVEL_CHANGERS(NMI, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(SO, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(SYNC, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(NMI, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(SO, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(SYNC, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502)
int EightBit::MOS6502::step() noexcept {
resetCycles();
@ -124,15 +124,15 @@ int EightBit::MOS6502::execute() noexcept {
case 0x09: A() = orr(A(), AM_Immediate()); break; // ORA (immediate)
case 0x0a: memoryRead(PC()); A() = asl(A()); break; // ASL A (implied)
case 0x0b: anc(AM_Immediate()); break; // *ANC (immediate)
case 0x0c: AM_Absolute(); break; // *NOP (absolute)
case 0x0c: { auto ignored = Address_Absolute(); } break; // *NOP (absolute)
case 0x0d: A() = orr(A(), AM_Absolute()); break; // ORA (absolute)
case 0x0e: memoryReadModifyWrite(asl(AM_Absolute())); break; // ASL (absolute)
case 0x0f: slo(AM_Absolute()); break; // *SLO (absolute)
case 0x10: branch(!negative()); break; // BPL (relative)
case 0x10: branch(negative() == 0); break; // BPL (relative)
case 0x11: A() = orr(A(), AM_IndirectIndexedY()); break; // ORA (indirect indexed Y)
case 0x12: break;
case 0x13: slo(AM_IndirectIndexedY()); break; // *SLO (indirect indexed Y)
case 0x13: slo_IndirectIndexedY(); break; // *SLO (indirect indexed Y)
case 0x14: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x15: A() = orr(A(), AM_ZeroPageX()); break; // ORA (zero page, X)
case 0x16: memoryReadModifyWrite(asl(AM_ZeroPageX())); break; // ASL (zero page, X)
@ -140,11 +140,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0x18: memoryRead(PC()); P() = clearBit(P(), CF); break; // CLC (implied)
case 0x19: A() = orr(A(), AM_AbsoluteY()); break; // ORA (absolute, Y)
case 0x1a: memoryRead(PC()); break; // *NOP (implied)
case 0x1b: slo(AM_AbsoluteY()); break; // *SLO (absolute, Y)
case 0x1c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x1b: slo_AbsoluteY(); break; // *SLO (absolute, Y)
case 0x1c: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0x1d: A() = orr(A(), AM_AbsoluteX()); break; // ORA (absolute, X)
case 0x1e: memoryReadModifyWrite(asl(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ASL (absolute, X)
case 0x1f: slo(AM_AbsoluteX()); break; // *SLO (absolute, X)
case 0x1f: slo_AbsoluteX(); break; // *SLO (absolute, X)
case 0x20: jsr(); break; // JSR (absolute)
case 0x21: A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X)
@ -166,7 +166,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x30: branch(negative()); break; // BMI (relative)
case 0x31: A() = andr(A(), AM_IndirectIndexedY()); break; // AND (indirect indexed Y)
case 0x32: break;
case 0x33: rla(AM_IndirectIndexedY()); break; // *RLA (indirect indexed Y)
case 0x33: rla_IndirectIndexedY(); break; // *RLA (indirect indexed Y)
case 0x34: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x35: A() = andr(A(), AM_ZeroPageX()); break; // AND (zero page, X)
case 0x36: memoryReadModifyWrite(rol(AM_ZeroPageX())); break; // ROL (zero page, X)
@ -174,11 +174,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0x38: memoryRead(PC()); P() = setBit(P(), CF); break; // SEC (implied)
case 0x39: A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y)
case 0x3a: memoryRead(PC()); break; // *NOP (implied)
case 0x3b: rla(AM_AbsoluteY()); break; // *RLA (absolute, Y)
case 0x3c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x3b: rla_AbsoluteY(); break; // *RLA (absolute, Y)
case 0x3c: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0x3d: A() = andr(A(), AM_AbsoluteX()); break; // AND (absolute, X)
case 0x3e: memoryReadModifyWrite(rol(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROL (absolute, X)
case 0x3f: rla(AM_AbsoluteX()); break; // *RLA (absolute, X)
case 0x3f: rla_AbsoluteX(); break; // *RLA (absolute, X)
case 0x40: memoryRead(PC()); rti(); break; // RTI (implied)
case 0x41: A() = eorr(A(), AM_IndexedIndirectX()); break; // EOR (indexed indirect X)
@ -197,10 +197,10 @@ int EightBit::MOS6502::execute() noexcept {
case 0x4e: memoryReadModifyWrite(lsr(AM_Absolute())); break; // LSR (absolute)
case 0x4f: sre(AM_Absolute()); break; // *SRE (absolute)
case 0x50: branch(!overflow()); break; // BVC (relative)
case 0x50: branch(overflow() == 0); break; // BVC (relative)
case 0x51: A() = eorr(A(), AM_IndirectIndexedY()); break; // EOR (indirect indexed Y)
case 0x52: break;
case 0x53: sre(AM_IndirectIndexedY()); break; // *SRE (indirect indexed Y)
case 0x53: sre_IndirectIndexedY(); break; // *SRE (indirect indexed Y)
case 0x54: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x55: A() = eorr(A(), AM_ZeroPageX()); break; // EOR (zero page, X)
case 0x56: memoryReadModifyWrite(lsr(AM_ZeroPageX())); break; // LSR (zero page, X)
@ -208,11 +208,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0x58: memoryRead(PC()); P() = clearBit(P(), IF); break; // CLI (implied)
case 0x59: A() = eorr(A(), AM_AbsoluteY()); break; // EOR (absolute, Y)
case 0x5a: memoryRead(PC()); break; // *NOP (implied)
case 0x5b: sre(AM_AbsoluteY()); break; // *SRE (absolute, Y)
case 0x5c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x5b: sre_AbsoluteY(); break; // *SRE (absolute, Y)
case 0x5c: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0x5d: A() = eorr(A(), AM_AbsoluteX()); break; // EOR (absolute, X)
case 0x5e: memoryReadModifyWrite(lsr(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // LSR (absolute, X)
case 0x5f: sre(AM_AbsoluteX()); break; // *SRE (absolute, X)
case 0x5f: sre_AbsoluteX(); break; // *SRE (absolute, X)
case 0x60: memoryRead(PC()); rts(); break; // RTS (implied)
case 0x61: A() = adc(A(), AM_IndexedIndirectX()); break; // ADC (indexed indirect X)
@ -234,7 +234,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x70: branch(overflow()); break; // BVS (relative)
case 0x71: A() = adc(A(), AM_IndirectIndexedY()); break; // ADC (indirect indexed Y)
case 0x72: break;
case 0x73: rra(AM_IndirectIndexedY()); break; // *RRA (indirect indexed Y)
case 0x73: rra_IndirectIndexedY(); break; // *RRA (indirect indexed Y)
case 0x74: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0x75: A() = adc(A(), AM_ZeroPageX()); break; // ADC (zero page, X)
case 0x76: memoryReadModifyWrite(ror(AM_ZeroPageX())); break; // ROR (zero page, X)
@ -242,11 +242,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0x78: memoryRead(PC()); P() = setBit(P(), IF); break; // SEI (implied)
case 0x79: A() = adc(A(), AM_AbsoluteY()); break; // ADC (absolute, Y)
case 0x7a: memoryRead(PC()); break; // *NOP (implied)
case 0x7b: rra(AM_AbsoluteY()); break; // *RRA (absolute, Y)
case 0x7c: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0x7b: rra_AbsoluteY(); break; // *RRA (absolute, Y)
case 0x7c: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0x7d: A() = adc(A(), AM_AbsoluteX()); break; // ADC (absolute, X)
case 0x7e: memoryReadModifyWrite(ror(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // ROR (absolute, X)
case 0x7f: rra(AM_AbsoluteX()); break; // *RRA (absolute, X)
case 0x7f: rra_AbsoluteX(); break; // *RRA (absolute, X)
case 0x80: AM_Immediate(); break; // *NOP (immediate)
case 0x81: memoryWrite(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X)
@ -265,7 +265,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x8e: memoryWrite(Address_Absolute(), X()); break; // STX (absolute)
case 0x8f: memoryWrite(Address_Absolute(), A() & X()); break; // *SAX (absolute)
case 0x90: branch(!carry()); break; // BCC (relative)
case 0x90: branch(carry() == 0); break; // BCC (relative)
case 0x91: sta_IndirectIndexedY(); break; // STA (indirect indexed Y)
case 0x92: break;
case 0x93: break;
@ -333,10 +333,10 @@ int EightBit::MOS6502::execute() noexcept {
case 0xce: memoryReadModifyWrite(dec(AM_Absolute())); break; // DEC (absolute)
case 0xcf: dcp(AM_Absolute()); break; // *DCP (absolute)
case 0xd0: branch(!zero()); break; // BNE (relative)
case 0xd0: branch(zero() == 0); break; // BNE (relative)
case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd2: break;
case 0xd3: dcp(AM_IndirectIndexedY()); break; // *DCP (indirect indexed Y)
case 0xd3: dcp_IndirectIndexedY(); break; // *DCP (indirect indexed Y)
case 0xd4: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0xd5: cmp(A(), AM_ZeroPageX()); break; // CMP (zero page, X)
case 0xd6: memoryReadModifyWrite(dec(AM_ZeroPageX())); break; // DEC (zero page, X)
@ -344,11 +344,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0xd8: memoryRead(PC()); P() = clearBit(P(), DF); break; // CLD (implied)
case 0xd9: cmp(A(), AM_AbsoluteY()); break; // CMP (absolute, Y)
case 0xda: memoryRead(PC()); break; // *NOP (implied)
case 0xdb: dcp(AM_AbsoluteY()); break; // *DCP (absolute, Y)
case 0xdc: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0xdb: dcp_AbsoluteY(); break; // *DCP (absolute, Y)
case 0xdc: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0xdd: cmp(A(), AM_AbsoluteX()); break; // CMP (absolute, X)
case 0xde: memoryReadModifyWrite(dec(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // DEC (absolute, X)
case 0xdf: dcp(AM_AbsoluteX()); break; // *DCP (absolute, X)
case 0xdf: dcp_AbsoluteX(); break; // *DCP (absolute, X)
case 0xe0: cmp(X(), AM_Immediate()); break; // CPX (immediate)
case 0xe1: A() = sbc(A(), AM_IndexedIndirectX()); break; // SBC (indexed indirect X)
@ -370,7 +370,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0xf0: branch(zero()); break; // BEQ (relative)
case 0xf1: A() = sbc(A(), AM_IndirectIndexedY()); break; // SBC (indirect indexed Y)
case 0xf2: break;
case 0xf3: isb(AM_IndirectIndexedY()); break; // *ISB (indirect indexed Y)
case 0xf3: isb_IndirectIndexedY(); break; // *ISB (indirect indexed Y)
case 0xf4: AM_ZeroPageX(); break; // *NOP (zero page, X)
case 0xf5: A() = sbc(A(), AM_ZeroPageX()); break; // SBC (zero page, X)
case 0xf6: memoryReadModifyWrite(inc(AM_ZeroPageX())); break; // INC (zero page, X)
@ -378,11 +378,11 @@ int EightBit::MOS6502::execute() noexcept {
case 0xf8: memoryRead(PC()); P() = setBit(P(), DF); break; // SED (implied)
case 0xf9: A() = sbc(A(), AM_AbsoluteY()); break; // SBC (absolute, Y)
case 0xfa: memoryRead(PC()); break; // *NOP (implied)
case 0xfb: isb(AM_AbsoluteY()); break; // *ISB (absolute, Y)
case 0xfc: AM_AbsoluteX(); break; // *NOP (absolute, X)
case 0xfb: isb_AbsoluteY(); break; // *ISB (absolute, Y)
case 0xfc: nop_AbsoluteX(); break; // *NOP (absolute, X)
case 0xfd: A() = sbc(A(), AM_AbsoluteX()); break; // SBC (absolute, X)
case 0xfe: memoryReadModifyWrite(inc(AM_AbsoluteX(PageCrossingBehavior::AlwaysReadTwice))); break; // INC (absolute, X)
case 0xff: isb(AM_AbsoluteX()); break; // *ISB (absolute, X)
case 0xff: isb_AbsoluteX(); break; // *ISB (absolute, X)
}
ASSUME(cycles() > 0);
@ -710,7 +710,7 @@ void EightBit::MOS6502::asr(const uint8_t value) noexcept {
}
void EightBit::MOS6502::axs(const uint8_t value) noexcept {
X() = through(sub(A() & X(), value));
X() = through(sub_b(A() & X(), value));
P() = clearBit(P(), CF, m_intermediate.high);
}
@ -748,15 +748,112 @@ void EightBit::MOS6502::sre(const uint8_t value) noexcept {
void EightBit::MOS6502::sta_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
write_A_with_fixup(address, page);
sta_with_fixup(address, page);
}
void EightBit::MOS6502::sta_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
write_A_with_fixup(address, page);
sta_with_fixup(address, page);
}
void EightBit::MOS6502::sta_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
write_A_with_fixup(address, page);
sta_with_fixup(address, page);
}
//
void EightBit::MOS6502::slo_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
slo_with_fixup(address, page);
}
void EightBit::MOS6502::slo_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
slo_with_fixup(address, page);
}
void EightBit::MOS6502::slo_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
slo_with_fixup(address, page);
}
void EightBit::MOS6502::isb_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
isb_with_fixup(address, page);
}
void EightBit::MOS6502::isb_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
isb_with_fixup(address, page);
}
void EightBit::MOS6502::isb_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
isb_with_fixup(address, page);
}
void EightBit::MOS6502::rla_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
rla_with_fixup(address, page);
}
void EightBit::MOS6502::rla_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
rla_with_fixup(address, page);
}
void EightBit::MOS6502::rla_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
rla_with_fixup(address, page);
}
void EightBit::MOS6502::rra_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
rra_with_fixup(address, page);
}
void EightBit::MOS6502::rra_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
rra_with_fixup(address, page);
}
void EightBit::MOS6502::rra_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
rra_with_fixup(address, page);
}
void EightBit::MOS6502::dcp_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
dcp_with_fixup(address, page);
}
void EightBit::MOS6502::dcp_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
dcp_with_fixup(address, page);
}
void EightBit::MOS6502::dcp_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
dcp_with_fixup(address, page);
}
void EightBit::MOS6502::sre_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
sre_with_fixup(address, page);
}
void EightBit::MOS6502::sre_AbsoluteY() noexcept {
const auto [address, page] = Address_AbsoluteY();
sre_with_fixup(address, page);
}
void EightBit::MOS6502::sre_IndirectIndexedY() noexcept {
const auto [address, page] = Address_IndirectIndexedY();
sre_with_fixup(address, page);
}
void EightBit::MOS6502::nop_AbsoluteX() noexcept {
const auto [address, page] = Address_AbsoluteX();
fixup(address, page);
}