Compare commits

...

4 Commits

Author SHA1 Message Date
Adrian Conlon 22f337569d Looks like the stray tick in the 6502 step method wasn't stray after all! 2024-01-07 11:37:28 +00:00
Adrian Conlon 70c316fd4f Add support for the M6502 undocumented instruction *ANE 2024-01-06 23:10:53 +00:00
Adrian Conlon 3ebc321c59 Add an implementation of the *JAM instruction that passes HarteTest 2024-01-06 22:44:59 +00:00
Adrian Conlon 617abbb450 Couple of small C++ correctness changes 2024-01-06 22:05:29 +00:00
5 changed files with 40 additions and 17 deletions

View File

@ -84,7 +84,7 @@ public:
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
[[nodiscard]] constexpr auto valid() const noexcept { return m_valid; }
[[nodiscard]] constexpr auto invalid() const noexcept { return !valid(); }
[[nodiscard]] constexpr auto unimplemented() const noexcept { return invalid() && m_cycle_count_mismatch && (cycles() == 0); }
[[nodiscard]] constexpr auto unimplemented() const noexcept { return invalid() && m_cycle_count_mismatch && (cycles() == 1); }
[[nodiscard]] constexpr auto implemented() const noexcept { return !unimplemented(); }
[[nodiscard]] constexpr const auto& messages() const noexcept { return m_messages; }

View File

@ -190,6 +190,7 @@ namespace EightBit {
void rra(uint8_t value) noexcept;
void slo(uint8_t value) noexcept;
void sre(uint8_t value) noexcept;
void jam() noexcept;
// Unconditional page fixup cycle required
void fixup(const register16_t address, const uint8_t unfixed_page) noexcept {

View File

@ -21,25 +21,42 @@ DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502)
int EightBit::MOS6502::step() noexcept {
resetCycles();
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
tick(); // A cycle is used, whether or RDY is high or not
if (UNLIKELY(lowered(SO())))
handleSO();
if (LIKELY(raised(RDY()))) {
lowerSYNC(); // Instruction fetch beginning
// Read the opcode within the existing cycle
assert(cycles() == 1 && "An extra cycle has occurred");
// Can't use fetchByte, since that would add an extra tick.
raiseRW();
opcode() = BUS().read(PC()++); // can't use fetchByte
opcode() = BUS().read(PC()++);
assert(cycles() == 1 && "BUS read has introduced stray cycles");
// Priority: RESET > NMI > INT
if (UNLIKELY(lowered(RESET())))
handleRESET();
else if (UNLIKELY(lowered(NMI())))
handleNMI();
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
handleINT();
// Whatever opcode is available, execute it.
execute();
}
}
ExecutedInstruction.fire(*this);
return cycles();
}
@ -113,7 +130,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x00: fetchByte(); interrupt(); break; // BRK (implied)
case 0x01: A() = orr(A(), AM_IndexedIndirectX()); break; // ORA (indexed indirect X)
case 0x02: break;
case 0x02: jam(); break; // *JAM
case 0x03: slo(AM_IndexedIndirectX()); break; // *SLO (indexed indirect X)
case 0x04: AM_ZeroPage(); break; // *NOP (zero page)
case 0x05: A() = orr(A(), AM_ZeroPage()); break; // ORA (zero page)
@ -130,7 +147,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x10: branch(negative() == 0); break; // BPL (relative)
case 0x11: A() = orr(A(), AM_IndirectIndexedY()); break; // ORA (indirect indexed Y)
case 0x12: break;
case 0x12: jam(); break; // *JAM
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)
@ -147,7 +164,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x20: jsr(); break; // JSR (absolute)
case 0x21: A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X)
case 0x22: break;
case 0x22: jam(); break; // *JAM
case 0x23: rla(AM_IndexedIndirectX()); break; // *RLA (indexed indirect X)
case 0x24: bit(A(), AM_ZeroPage()); break; // BIT (zero page)
case 0x25: A() = andr(A(), AM_ZeroPage()); break; // AND (zero page)
@ -164,7 +181,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 0x32: jam(); break; // *JAM
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)
@ -181,7 +198,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x40: memoryRead(PC()); rti(); break; // RTI (implied)
case 0x41: A() = eorr(A(), AM_IndexedIndirectX()); break; // EOR (indexed indirect X)
case 0x42: break;
case 0x42: jam(); break; // *JAM
case 0x43: sre(AM_IndexedIndirectX()); break; // *SRE (indexed indirect X)
case 0x44: AM_ZeroPage(); break; // *NOP (zero page)
case 0x45: A() = eorr(A(), AM_ZeroPage()); break; // EOR (zero page)
@ -198,7 +215,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x50: branch(overflow() == 0); break; // BVC (relative)
case 0x51: A() = eorr(A(), AM_IndirectIndexedY()); break; // EOR (indirect indexed Y)
case 0x52: break;
case 0x52: jam(); break; // *JAM
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)
@ -215,7 +232,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x60: memoryRead(PC()); rts(); break; // RTS (implied)
case 0x61: A() = adc(A(), AM_IndexedIndirectX()); break; // ADC (indexed indirect X)
case 0x62: break;
case 0x62: jam(); break; // *JAM
case 0x63: rra(AM_IndexedIndirectX()); break; // *RRA (indexed indirect X)
case 0x64: AM_ZeroPage(); break; // *NOP (zero page)
case 0x65: A() = adc(A(), AM_ZeroPage()); break; // ADC (zero page)
@ -232,7 +249,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 0x72: jam(); break; // *JAM
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)
@ -258,7 +275,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x88: memoryRead(PC()); Y() = dec(Y()); break; // DEY (implied)
case 0x89: AM_Immediate(); break; // *NOP (immediate)
case 0x8a: memoryRead(PC()); A() = through(X()); break; // TXA (implied)
case 0x8b: break;
case 0x8b: A() = through((A() | 0xee) & X() & AM_Immediate()); break; // *ANE (immediate)
case 0x8c: memoryWrite(Address_Absolute(), Y()); break; // STY (absolute)
case 0x8d: memoryWrite(Address_Absolute(), A()); break; // STA (absolute)
case 0x8e: memoryWrite(Address_Absolute(), X()); break; // STX (absolute)
@ -266,7 +283,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0x90: branch(carry() == 0); break; // BCC (relative)
case 0x91: sta_IndirectIndexedY(); break; // STA (indirect indexed Y)
case 0x92: break;
case 0x92: jam(); break; // *JAM
case 0x93: break;
case 0x94: memoryWrite(Address_ZeroPageX(), Y()); break; // STY (zero page, X)
case 0x95: memoryWrite(Address_ZeroPageX(), A()); break; // STA (zero page, X)
@ -300,7 +317,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0xb0: branch(carry()); break; // BCS (relative)
case 0xb1: A() = through(AM_IndirectIndexedY()); break; // LDA (indirect indexed Y)
case 0xb2: break;
case 0xb2: jam(); break; // *JAM
case 0xb3: A() = X() = through(AM_IndirectIndexedY()); break; // *LAX (indirect indexed Y)
case 0xb4: Y() = through(AM_ZeroPageX()); break; // LDY (zero page, X)
case 0xb5: A() = through(AM_ZeroPageX()); break; // LDA (zero page, X)
@ -334,7 +351,7 @@ int EightBit::MOS6502::execute() noexcept {
case 0xd0: branch(zero() == 0); break; // BNE (relative)
case 0xd1: cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd2: break;
case 0xd2: jam(); break; // *JAM
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)
@ -368,7 +385,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 0xf2: jam(); break; // *JAM
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)
@ -766,6 +783,11 @@ void EightBit::MOS6502::sre(const uint8_t value) noexcept {
A() = eorr(A(), BUS().DATA());
}
void EightBit::MOS6502::jam() noexcept {
memoryRead(PC());
memoryRead(PC()--);
}
//
void EightBit::MOS6502::sta_AbsoluteX() noexcept {

View File

@ -66,7 +66,7 @@ namespace EightBit {
[[nodiscard]] static constexpr auto promoteNibble(const int value) noexcept { return value << 4; }
[[nodiscard]] static constexpr auto demoteNibble(const int value) noexcept { return highNibble(value); }
Chip(const Chip& rhs)
Chip(const Chip& rhs) noexcept
: Device(rhs) {}
protected:

View File

@ -17,7 +17,7 @@ namespace EightBit {
m_delegates.push_back(functor);
}
void fire(T& e = EventArgs::empty()) const noexcept {
void fire(T& e = EventArgs::empty()) const {
for (auto& delegate : m_delegates)
delegate(e);
}