From 017b2a64428dbf8435dd4a948e4f5d8a53ed6bbf Mon Sep 17 00:00:00 2001 From: "Adrian.Conlon" Date: Mon, 17 Jul 2017 21:00:05 +0100 Subject: [PATCH] Tidy up memory event handling to make it a bit easier to verify read/write events. Signed-off-by: Adrian.Conlon --- M6502/inc/mos6502.h | 92 +++++++++++++++++++++++++++++++------- M6502/src/mos6502.cpp | 75 ++++++++++--------------------- M6502/test_M6502/Board.cpp | 1 - inc/Memory.h | 12 ++++- 4 files changed, 110 insertions(+), 70 deletions(-) diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 1e4657c..bfa056a 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -40,6 +40,11 @@ namespace EightBit { CF = Bit0, // Carry }; + enum BusDirection { + Read, + Write + }; + MOS6502(Memory& memory); virtual ~MOS6502(); @@ -179,20 +184,20 @@ namespace EightBit { return m_memory.reference(); } - uint8_t& AM_AbsoluteX(bool read = true) { + uint8_t& AM_AbsoluteX(BusDirection direction = BusDirection::Read) { m_busRW = true; Address_AbsoluteX(); m_memory.ADDRESS() = MEMPTR(); - if (read && (m_memory.ADDRESS().low == Mask8)) + if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) ++cycles; return m_memory.reference(); } - uint8_t& AM_AbsoluteY(bool read = true) { + uint8_t& AM_AbsoluteY(BusDirection direction = BusDirection::Read) { m_busRW = true; Address_AbsoluteY(); m_memory.ADDRESS() = MEMPTR(); - if (read && (m_memory.ADDRESS().low == Mask8)) + if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) ++cycles; return m_memory.reference(); } @@ -218,11 +223,11 @@ namespace EightBit { return m_memory.reference(); } - uint8_t& AM_IndirectIndexedY(bool read = true) { + uint8_t& AM_IndirectIndexedY(BusDirection direction = BusDirection::Read) { m_busRW = true; Address_IndirectIndexedY(); m_memory.ADDRESS() = MEMPTR(); - if (read && (m_memory.ADDRESS().low == Mask8)) + if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) ++cycles; return m_memory.reference(); } @@ -231,7 +236,7 @@ namespace EightBit { #pragma region 6502 addressing mode switching - uint8_t& AM_00(int bbb, bool read = true) { + uint8_t& AM_00(int bbb, BusDirection direction = BusDirection::Read) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -242,7 +247,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(read); + return AM_AbsoluteX(direction); case 0b010: case 0b100: case 0b110: @@ -252,7 +257,7 @@ namespace EightBit { } } - uint8_t& AM_01(int bbb, bool read = true) { + uint8_t& AM_01(int bbb, BusDirection direction = BusDirection::Read) { switch (bbb) { case 0b000: return AM_IndexedIndirectX(); @@ -263,19 +268,19 @@ namespace EightBit { case 0b011: return AM_Absolute(); case 0b100: - return AM_IndirectIndexedY(read); + return AM_IndirectIndexedY(direction); case 0b101: return AM_ZeroPageX(); case 0b110: - return AM_AbsoluteY(read); + return AM_AbsoluteY(direction); case 0b111: - return AM_AbsoluteX(read); + return AM_AbsoluteX(direction); default: __assume(0); } } - uint8_t& AM_10(int bbb, bool read = true) { + uint8_t& AM_10(int bbb, BusDirection direction = BusDirection::Read) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -288,7 +293,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(read); + return AM_AbsoluteX(direction); case 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -297,7 +302,7 @@ namespace EightBit { } } - uint8_t& AM_10_x(int bbb, bool read = true) { + uint8_t& AM_10_x(int bbb, BusDirection direction = BusDirection::Read) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -310,7 +315,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageY(); case 0b111: - return AM_AbsoluteY(read); + return AM_AbsoluteY(direction); case 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -323,6 +328,61 @@ namespace EightBit { #pragma endregion 6502 addressing modes + void firePendingBusEvents(BusDirection direction) { + if (m_busRW) { + switch (direction) { + case BusDirection::Read: + m_memory.fireReadBusEvent(); + break; + case BusDirection::Write: + m_memory.fireWriteBusEvent(); + break; + } + } + } + + void ASL(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + ASL(reference); + firePendingBusEvents(BusDirection::Write); + } + + void ROL(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + ROL(reference); + firePendingBusEvents(BusDirection::Write); + } + + void LSR(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + LSR(reference); + firePendingBusEvents(BusDirection::Write); + } + + void ROR(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + ROR(reference); + firePendingBusEvents(BusDirection::Write); + } + + void DEC(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + adjustNZ(--reference); + firePendingBusEvents(BusDirection::Write); + } + + void INC(int bbb) { + auto& reference = AM_10(bbb, BusDirection::Write); + firePendingBusEvents(BusDirection::Read); + adjustNZ(++reference); + firePendingBusEvents(BusDirection::Write); + } + void ROR(uint8_t& output); void LSR(uint8_t& output); diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 8c81ce5..563cbc1 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -135,8 +135,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // BIT BIT(AM_00(decoded.bbb)); - assert(m_busRW); - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; } break; @@ -194,9 +193,8 @@ int EightBit::MOS6502::execute(uint8_t cell) { adjustNZ(A() = Y()); break; default: // STY - AM_00(decoded.bbb, false); - assert(m_busRW); - m_memory.write(Y()); + AM_00(decoded.bbb, BusDirection::Write) = Y(); + firePendingBusEvents(BusDirection::Write); break; } break; @@ -213,8 +211,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // LDY adjustNZ(Y() = AM_00(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; } break; @@ -231,8 +228,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // CPY CMP(Y(), AM_00(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; } break; @@ -249,8 +245,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // CPX CMP(X(), AM_00(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; } break; @@ -260,43 +255,35 @@ int EightBit::MOS6502::execute(uint8_t cell) { switch (decoded.aaa) { case 0b000: // ORA adjustNZ(A() |= AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b001: // AND adjustNZ(A() &= AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b010: // EOR adjustNZ(A() ^= AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b011: // ADC ADC(AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b100: // STA - AM_01(decoded.bbb, false); - assert(m_busRW); - m_memory.write(A()); + AM_01(decoded.bbb, BusDirection::Write) = A(); + firePendingBusEvents(BusDirection::Write); break; case 0b101: // LDA adjustNZ(A() = AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b110: // CMP CMP(A(), AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; case 0b111: // SBC SBC(AM_01(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; default: __assume(0); @@ -305,24 +292,16 @@ int EightBit::MOS6502::execute(uint8_t cell) { case 0b10: switch (decoded.aaa) { case 0b000: // ASL - ASL(AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + ASL(decoded.bbb); break; case 0b001: // ROL - ROL(AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + ROL(decoded.bbb); break; case 0b010: // LSR - LSR(AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + LSR(decoded.bbb); break; case 0b011: // ROR - ROR(AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + ROR(decoded.bbb); break; case 0b100: switch (decoded.bbb) { @@ -333,9 +312,8 @@ int EightBit::MOS6502::execute(uint8_t cell) { S() = X(); break; default: // STX - AM_10_x(decoded.bbb, false); - assert(m_busRW); - m_memory.write(X()); + AM_10_x(decoded.bbb, BusDirection::Write) = X(); + firePendingBusEvents(BusDirection::Write); break; } break; @@ -346,8 +324,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // LDX adjustNZ(X() = AM_10_x(decoded.bbb)); - if (m_busRW) - m_memory.read(); + firePendingBusEvents(BusDirection::Read); break; } break; @@ -357,9 +334,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { adjustNZ(--X()); break; default: // DEC - adjustNZ(--AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + DEC(decoded.bbb); break; } break; @@ -368,9 +343,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { case 0b010: // NOP break; default: // INC - adjustNZ(++AM_10(decoded.bbb, false)); - if (m_busRW) - m_memory.read(); + INC(decoded.bbb); break; } break; diff --git a/M6502/test_M6502/Board.cpp b/M6502/test_M6502/Board.cpp index 7aafca1..14768b4 100644 --- a/M6502/test_M6502/Board.cpp +++ b/M6502/test_M6502/Board.cpp @@ -48,7 +48,6 @@ void Board::initialise() { m_cpu.ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_StopLoop, this, std::placeholders::_1)); break; case Configuration::StopCondition::Halt: - break; default: throw std::domain_error("Unknown stop condition"); diff --git a/inc/Memory.h b/inc/Memory.h index ae5bcc9..685f474 100644 --- a/inc/Memory.h +++ b/inc/Memory.h @@ -65,9 +65,13 @@ namespace EightBit { return address & m_addressMask; } + void fireReadBusEvent() { + ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + uint8_t read() { auto content = reference(); - ReadByte.fire(AddressEventArgs(ADDRESS().word, content)); + fireReadBusEvent(); return content; } @@ -76,9 +80,13 @@ namespace EightBit { return read(); } + void fireWriteBusEvent() { + WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + void write(uint8_t value) { reference() = value; - WrittenByte.fire(AddressEventArgs(ADDRESS().word, value)); + fireWriteBusEvent(); } void write(uint16_t offset, uint8_t value) {