Compare commits

...

2 Commits

Author SHA1 Message Date
Adrian Conlon c15f7f836e Start testing undocumented instructions 2024-01-05 12:58:32 +00:00
Adrian Conlon 5d24a136a2 Correct loads of undocumented M6502 instructions 2024-01-05 12:52:27 +00:00
5 changed files with 209 additions and 91 deletions

View File

@ -1,9 +1,6 @@
#include "stdafx.h"
#include "checker_t.h"
std::set<uint8_t> checker_t::m_undocumented_opcodes;
bool checker_t::m_undocumented_opcodes_initialised = false;
void checker_t::addActualCycle(const uint16_t address, const uint8_t value, const std::string action) {
m_actualCycles.push_back({ address, value, action });
}
@ -114,8 +111,6 @@ void checker_t::initialiseState(const test_t test) {
void checker_t::initialise() {
seedUndocumentedOpcodes();
auto& bus = runner();
bus.ReadByte.connect([this, &bus](EightBit::EventArgs&) {
@ -180,7 +175,10 @@ bool checker_t::checkState(test_t test) {
ram_problem = true;
}
return pc_good && s_good && a_good && x_good && y_good && p_good && !ram_problem;
return
pc_good && s_good
&& a_good && x_good && y_good && p_good
&& !ram_problem;
}
//
void checker_t::pushCurrentMessage() {
@ -210,13 +208,6 @@ void checker_t::check(test_t test) {
const auto pc = cpu.PC().word;
const auto start_opcode = runner().peek(pc);
m_undocumented = m_undocumented_opcodes.contains(start_opcode);
if (undocumented()) {
m_valid = false;
m_messages.push_back("Undocumented");
return;
}
m_cycles = cpu.step();
runner().lowerPOWER();
@ -250,26 +241,3 @@ void checker_t::check(test_t test) {
dumpCycles("-- Actual cycles", m_actualCycles);
}
}
void checker_t::seedUndocumentedOpcodes() {
if (m_undocumented_opcodes_initialised) return;
m_undocumented_opcodes = {
0x02, 0x03, 0x04, 0x07, 0x0b, 0x0c, 0x0f,
0x12, 0x13, 0x14, 0x17, 0x1a, 0x1b, 0x1c, 0x1f,
0x22, 0x23, 0x27, 0x2b, 0x2f,
0x32, 0x33, 0x34, 0x37, 0x3a, 0x3b, 0x3c, 0x3f,
0x42, 0x43, 0x44, 0x47, 0x4b, 0x4f,
0x52, 0x53, 0x54, 0x57, 0x5a, 0x5b, 0x5c, 0x5f,
0x62, 0x63, 0x64, 0x67, 0x6b, 0x6f,
0x72, 0x73, 0x74, 0x77, 0x7a, 0x7b, 0x7c, 0x7f,
0x80, 0x82, 0x83, 0x87, 0x89, 0x8b, 0x8f,
0x92, 0x93, 0x97, 0x9b, 0x9c, 0x9e, 0x9f,
0xa3, 0xa7, 0xab, 0xaf,
0xb2, 0xb3, 0xb7, 0xbb, 0xbf,
0xc2, 0xc3, 0xc7, 0xcb, 0xcf,
0xd2, 0xd3, 0xd4, 0xd7, 0xda, 0xdb, 0xdc, 0xdf,
0xe2, 0xe3, 0xe7, 0xeb, 0xef,
0xf1, 0xf2, 0xf3, 0xf4, 0xf7, 0xfa, 0xfb, 0xfc, 0xff,
};
m_undocumented_opcodes_initialised = true;
}

View File

@ -1,7 +1,6 @@
#pragma once
#include <cstdint>
#include <set>
#include <Disassembly.h>
#include <Symbols.h>
@ -14,9 +13,6 @@
class checker_t {
private:
static std::set<uint8_t> m_undocumented_opcodes;
static bool m_undocumented_opcodes_initialised;
TestRunner& m_runner;
EightBit::Symbols m_symbols;
EightBit::Disassembly m_disassembler = { m_runner, m_runner.CPU(), m_symbols };
@ -31,13 +27,11 @@ private:
int m_cycles = 0;
bool m_valid = true;
bool m_undocumented = false;
[[nodiscard]] constexpr auto& os() noexcept { return m_os; }
[[nodiscard]] constexpr auto& runner() noexcept { return m_runner; }
void seedUndocumentedOpcodes();
[[nodiscard]] bool checkState(test_t test);
void pushCurrentMessage();
@ -92,8 +86,6 @@ public:
[[nodiscard]] constexpr auto invalid() const noexcept { return !valid(); }
[[nodiscard]] constexpr auto unimplemented() const noexcept { return invalid() && m_cycle_count_mismatch && (cycles() == 1); }
[[nodiscard]] constexpr auto implemented() const noexcept { return !unimplemented(); }
[[nodiscard]] constexpr auto undocumented() const noexcept { return m_undocumented; }
[[nodiscard]] constexpr auto documented() const noexcept { return !undocumented(); }
[[nodiscard]] constexpr const auto& messages() const noexcept { return m_messages; }

View File

@ -16,7 +16,6 @@ int main() {
const auto start_time = std::chrono::steady_clock::now();
int undocumented_opcode_count = 0;
int unimplemented_opcode_count = 0;
int invalid_opcode_count = 0;
@ -46,8 +45,6 @@ int main() {
++invalid_opcode_count;
if (checker.unimplemented())
++unimplemented_opcode_count;
if (checker.undocumented())
++undocumented_opcode_count;
std::cout << "** Failed: " << test.name() << "\n";
for (const auto& message : checker.messages())
std::cout << "**** " << message << "\n";
@ -61,7 +58,6 @@ int main() {
const auto seconds = std::chrono::duration_cast<std::chrono::duration<double>>(elapsed_time).count();
std::cout
<< "Elapsed time: " << seconds << " seconds"
<< ", undocumented opcode count: " << undocumented_opcode_count
<< ", unimplemented opcode count: " << unimplemented_opcode_count
<< ", invalid opcode count: " << (invalid_opcode_count - unimplemented_opcode_count)
<< std::endl;

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);
}