diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 8c45e0f..c752487 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -56,7 +56,7 @@ namespace EightBit { bool m_interrupt; - uint8_t& R(int r) { + uint8_t R(int r) { __assume(r < 8); __assume(r >= 0); switch (r) { @@ -73,8 +73,7 @@ namespace EightBit { case 0b101: return L(); case 0b110: - m_memory.ADDRESS() = HL(); - return m_memory.reference(); + return m_memory.read(HL()); case 0b111: return A(); default: @@ -83,6 +82,39 @@ namespace EightBit { throw std::logic_error("Unhandled registry mechanism"); } + void R(int r, uint8_t value) { + __assume(r < 8); + __assume(r >= 0); + switch (r) { + case 0b000: + B() = value; + break; + case 0b001: + C() = value; + break; + case 0b010: + D() = value; + break; + case 0b011: + E() = value; + break; + case 0b100: + H() = value; + break; + case 0b101: + L() = value; + break; + case 0b110: + m_memory.write(HL(), value); + break; + case 0b111: + A() = value; + break; + default: + __assume(0); + } + } + register16_t& RP(int rp) { __assume(rp < 4); __assume(rp >= 0); diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index 078ab0d..54ae09b 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -257,12 +257,12 @@ void EightBit::Intel8080::cmc(uint8_t& a, uint8_t& f) { void EightBit::Intel8080::xhtl() { m_memory.ADDRESS() = SP(); - MEMPTR().low = m_memory.reference(); - m_memory.reference() = L(); + MEMPTR().low = m_memory.read(SP()); + m_memory.write(L()); L() = MEMPTR().low; m_memory.ADDRESS().word++; - MEMPTR().high = m_memory.reference(); - m_memory.reference() = H(); + MEMPTR().high = m_memory.read(); + m_memory.write(H()); H() = MEMPTR().high; } @@ -336,12 +336,14 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { switch (p) { case 0: // LD (BC),A MEMPTR() = BC(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 7; break; case 1: // LD (DE),A MEMPTR() = DE(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 7; break; case 2: // LD (nn),HL @@ -351,7 +353,8 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { break; case 3: // LD (nn),A fetchWord(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 13; break; default: @@ -362,12 +365,14 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { switch (p) { case 0: // LD A,(BC) MEMPTR() = BC(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 7; break; case 1: // LD A,(DE) MEMPTR() = DE(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 7; break; case 2: // LD HL,(nn) @@ -377,7 +382,8 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { break; case 3: // LD A,(nn) fetchWord(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 13; break; default: @@ -401,18 +407,22 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { } cycles += 6; break; - case 4: // 8-bit INC - increment(f, R(y)); // INC r + case 4: { // 8-bit INC + auto operand = R(y); + increment(f, operand); + R(y, operand); cycles += 4; break; - case 5: // 8-bit DEC - decrement(f, R(y)); // DEC r + } case 5: { // 8-bit DEC + auto operand = R(y); + decrement(f, operand); + R(y, operand); cycles += 4; if (y == 6) cycles += 7; break; - case 6: // 8-bit load immediate - R(y) = fetchByte(); + } case 6: // 8-bit load immediate + R(y, fetchByte()); cycles += 7; if (y == 6) cycles += 3; @@ -456,7 +466,7 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { if (z == 6 && y == 6) { // Exception (replaces LD (HL), (HL)) halt(); } else { - R(y) = R(z); + R(y, R(z)); if ((y == 6) || (z == 6)) // M operations cycles += 3; } diff --git a/Intel8080/test/Board.cpp b/Intel8080/test/Board.cpp index 00fcc7d..12ee442 100644 --- a/Intel8080/test/Board.cpp +++ b/Intel8080/test/Board.cpp @@ -20,8 +20,7 @@ void Board::initialise() { m_memory.loadRam(romDirectory + "/8080EX1.COM", 0x100); // Cringle/Bartholomew //m_memory.loadRam(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics - m_memory.ADDRESS().word = 5; - m_memory.reference() = 0xc9; // ret + m_memory.write(5, 0xc9); // ret m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1)); if (m_configuration.isProfileMode()) { diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index 2912830..2b06c25 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -54,40 +54,6 @@ namespace EightBit { virtual void reset(); virtual void initialise(); - protected: - virtual uint8_t fetchByte() override { - auto returned = IntelProcessor::fetchByte(); - m_memory.fireReadBusEvent(); - return returned; - } - - virtual void push(uint8_t value) override { - IntelProcessor::push(value); - m_memory.fireWriteBusEvent(); - } - - virtual uint8_t pop() override { - auto returned = IntelProcessor::pop(); - m_memory.fireReadBusEvent(); - return returned; - } - - virtual void getWordViaMemptr(register16_t& value) { - value.low = memptrReference(); - m_memory.fireReadBusEvent(); - m_memory.ADDRESS().word++; - value.high = m_memory.reference(); - m_memory.fireReadBusEvent(); - } - - virtual void setWordViaMemptr(register16_t value) { - memptrReference() = value.low; - m_memory.fireWriteBusEvent(); - m_memory.ADDRESS().word++; - m_memory.reference() = value.high; - m_memory.fireWriteBusEvent(); - } - private: Bus& m_bus; @@ -102,7 +68,7 @@ namespace EightBit { bool m_stopped; - uint8_t& R(int r, uint8_t& a) { + uint8_t R(int r, uint8_t& a) { switch (r) { case 0: return B(); @@ -117,14 +83,42 @@ namespace EightBit { case 5: return L(); case 6: - m_memory.ADDRESS() = HL(); - return m_memory.reference(); + return m_memory.read(HL()); case 7: return a; } throw std::logic_error("Unhandled registry mechanism"); } + void R(int r, uint8_t& a, uint8_t value) { + switch (r) { + case 0: + B() = value; + break; + case 1: + C() = value; + break; + case 2: + D() = value; + break; + case 3: + E() = value; + break; + case 4: + H() = value; + break; + case 5: + L() = value; + break; + case 6: + m_memory.write(HL(), value); + break; + case 7: + a = value; + break; + } + } + register16_t& RP(int rp) { __assume(rp < 4); __assume(rp >= 0); @@ -192,17 +186,17 @@ namespace EightBit { static void orr(uint8_t& f, uint8_t& operand, uint8_t value); static void compare(uint8_t& f, uint8_t check, uint8_t value); - static void rlc(uint8_t& f, uint8_t& operand); - static void rrc(uint8_t& f, uint8_t& operand); - static void rl(uint8_t& f, uint8_t& operand); - static void rr(uint8_t& f, uint8_t& operand); - static void sla(uint8_t& f, uint8_t& operand); - static void sra(uint8_t& f, uint8_t& operand); - static void srl(uint8_t& f, uint8_t& operand); + static uint8_t rlc(uint8_t& f, uint8_t operand); + static uint8_t rrc(uint8_t& f, uint8_t operand); + static uint8_t rl(uint8_t& f, uint8_t operand); + static uint8_t rr(uint8_t& f, uint8_t operand); + static uint8_t sla(uint8_t& f, uint8_t operand); + static uint8_t sra(uint8_t& f, uint8_t operand); + static uint8_t srl(uint8_t& f, uint8_t operand); - static void bit(uint8_t& f, int n, uint8_t& operand); - static void res(int n, uint8_t& operand); - static void set(int n, uint8_t& operand); + static uint8_t bit(uint8_t& f, int n, uint8_t operand); + static uint8_t res(int n, uint8_t operand); + static uint8_t set(int n, uint8_t operand); static void daa(uint8_t& a, uint8_t& f); @@ -210,6 +204,6 @@ namespace EightBit { static void ccf(uint8_t& a, uint8_t& f); static void cpl(uint8_t& a, uint8_t& f); - static void swap(uint8_t& f, uint8_t& operand); + static uint8_t swap(uint8_t& f, uint8_t operand); }; } \ No newline at end of file diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 18a51b8..2444406 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -212,76 +212,84 @@ void EightBit::LR35902::compare(uint8_t& f, uint8_t check, uint8_t value) { #pragma region Shift and rotate -void EightBit::LR35902::rlc(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::rlc(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit7); operand = _rotl8(operand, 1); adjustZero(f, operand); + return operand; } -void EightBit::LR35902::rrc(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::rrc(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = _rotr8(operand, 1); adjustZero(f, operand); + return operand; } -void EightBit::LR35902::rl(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::rl(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); const auto carry = (f & CF) >> 4; setFlag(f, CF, operand & Bit7); operand = (operand << 1) | carry; adjustZero(f, operand); + return operand; } -void EightBit::LR35902::rr(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::rr(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); const auto carry = (f & CF) >> 4; setFlag(f, CF, operand & Bit0); operand = (operand >> 1) | (carry << 7); adjustZero(f, operand); + return operand; } // -void EightBit::LR35902::sla(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::sla(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit7); operand <<= 1; adjustZero(f, operand); + return operand; } -void EightBit::LR35902::sra(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::sra(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = (operand >> 1) | operand & Bit7; adjustZero(f, operand); + return operand; } -void EightBit::LR35902::srl(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::srl(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = (operand >> 1) & ~Bit7; adjustZero(f, operand); + return operand; } #pragma endregion Shift and rotate #pragma region BIT/SET/RES -void EightBit::LR35902::bit(uint8_t& f, int n, uint8_t& operand) { +uint8_t EightBit::LR35902::bit(uint8_t& f, int n, uint8_t operand) { auto carry = f & CF; uint8_t discarded = operand; andr(f, discarded, 1 << n); setFlag(f, CF, carry); + return operand; } -void EightBit::LR35902::res(int n, uint8_t& operand) { - operand &= ~(1 << n); +uint8_t EightBit::LR35902::res(int n, uint8_t operand) { + return operand & ~(1 << n); } -void EightBit::LR35902::set(int n, uint8_t& operand) { - operand |= (1 << n); +uint8_t EightBit::LR35902::set(int n, uint8_t operand) { + return operand | (1 << n); } #pragma endregion BIT/SET/RES @@ -326,12 +334,13 @@ void EightBit::LR35902::ccf(uint8_t& a, uint8_t& f) { clearFlag(f, CF, f & CF); } -void EightBit::LR35902::swap(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::LR35902::swap(uint8_t& f, uint8_t operand) { auto low = lowNibble(operand); auto high = highNibble(operand); operand = promoteNibble(low) | demoteNibble(high); adjustZero(f, operand); clearFlag(f, NF | HC | CF); + return operand; } #pragma endregion Miscellaneous instructions @@ -369,64 +378,58 @@ void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) { auto& a = A(); auto& f = F(); switch (x) { - case 0: // rot[y] r[z] + case 0: { // rot[y] r[z] + auto operand = R(z, a); switch (y) { case 0: - rlc(f, R(z, a)); + operand = rlc(f, operand); break; case 1: - rrc(f, R(z, a)); + operand = rrc(f, operand); break; case 2: - rl(f, R(z, a)); + operand = rl(f, operand); break; case 3: - rr(f, R(z, a)); + operand = rr(f, operand); break; case 4: - sla(f, R(z, a)); + operand = sla(f, operand); break; case 5: - sra(f, R(z, a)); + operand = sra(f, operand); break; case 6: - swap(f, R(z, a)); + operand = swap(f, operand); break; case 7: - srl(f, R(z, a)); + operand = srl(f, operand); break; default: __assume(0); } cycles += 2; - if (z == 6) { - m_bus.fireWriteBusEvent(); + R(z, a, operand); + if (z == 6) cycles += 2; - } break; - case 1: // BIT y, r[z] + } case 1: // BIT y, r[z] bit(f, y, R(z, a)); cycles += 2; - if (z == 6) { - m_bus.fireReadBusEvent(); + if (z == 6) cycles += 2; - } break; case 2: // RES y, r[z] - res(y, R(z, a)); + R(z, a, res(y, R(z, a))); cycles += 2; - if (z == 6) { - m_bus.fireWriteBusEvent(); + if (z == 6) cycles += 2; - } break; case 3: // SET y, r[z] - set(y, R(z, a)); + R(z, a, set(y, R(z, a))); cycles += 2; - if (z == 6) { - m_bus.fireWriteBusEvent(); + if (z == 6) cycles += 2; - } break; default: __assume(0); @@ -544,26 +547,24 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) { } cycles += 2; break; - case 4: // 8-bit INC - increment(f, R(y, a)); // INC r + case 4: { // 8-bit INC + auto operand = R(y, a); + increment(f, operand); + R(y, a, operand); cycles++; - if (y == 6) { - m_bus.fireWriteBusEvent(); - cycles += 2; - } - break; - case 5: // 8-bit DEC - decrement(f, R(y, a)); // DEC r - cycles++; - if (y == 6) { - m_bus.fireWriteBusEvent(); - cycles += 2; - } - break; - case 6: // 8-bit load immediate - R(y, a) = fetchByte(); if (y == 6) - m_bus.fireWriteBusEvent(); + cycles += 2; + break; + } case 5: { // 8-bit DEC + auto operand = R(y, a); + decrement(f, operand); + R(y, a, operand); + cycles++; + if (y == 6) + cycles += 2; + break; + } case 6: // 8-bit load immediate + R(y, a, fetchByte()); // LD r,n cycles += 2; break; case 7: // Assorted operations on accumulator/flags @@ -603,14 +604,9 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) { if (z == 6 && y == 6) { // Exception (replaces LD (HL), (HL)) halt(); } else { - R(y, a) = R(z, a); - if ((y == 6) || (z == 6)) { // M operations - if (y == 6) - m_bus.fireWriteBusEvent(); - else - m_bus.fireReadBusEvent(); + R(y, a, R(z, a)); + if ((y == 6) || (z == 6)) // M operations cycles++; - } } cycles++; break; @@ -644,10 +640,8 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) { __assume(0); } cycles++; - if (z == 6) { - m_bus.fireReadBusEvent(); + if (z == 6) cycles++; - } break; case 3: switch (z) { diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 35a7ee2..4ebdabe 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -40,11 +40,6 @@ namespace EightBit { CF = Bit0, // Carry }; - enum BusDirection { - Read, - Write - }; - MOS6502(Memory& memory); virtual ~MOS6502(); @@ -156,86 +151,118 @@ namespace EightBit { #pragma endregion Addresses -#pragma region References +#pragma region Addressing modes, read - uint8_t& AM_A() { - m_busRW = false; + uint8_t AM_A() { return A(); } - uint8_t& AM_Immediate() { - m_busRW = false; - fetchByte(); - return m_memory.reference(); + uint8_t AM_Immediate() { + return fetchByte(); } - uint8_t& AM_Absolute() { - m_busRW = true; + uint8_t AM_Absolute() { Address_Absolute(); - m_memory.ADDRESS() = MEMPTR(); - return m_memory.reference(); + return m_memory.read(MEMPTR()); } - uint8_t& AM_ZeroPage() { - m_busRW = true; + uint8_t AM_ZeroPage() { Address_ZeroPage(); - m_memory.ADDRESS() = MEMPTR(); - return m_memory.reference(); + return m_memory.read(MEMPTR()); } - uint8_t& AM_AbsoluteX(BusDirection direction = BusDirection::Read) { - m_busRW = true; + uint8_t AM_AbsoluteX() { Address_AbsoluteX(); m_memory.ADDRESS() = MEMPTR(); - if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) + if (m_memory.ADDRESS().low == Mask8) ++cycles; - return m_memory.reference(); + return m_memory.read(); } - uint8_t& AM_AbsoluteY(BusDirection direction = BusDirection::Read) { - m_busRW = true; + uint8_t AM_AbsoluteY() { Address_AbsoluteY(); m_memory.ADDRESS() = MEMPTR(); - if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) + if (m_memory.ADDRESS().low == Mask8) ++cycles; - return m_memory.reference(); + return m_memory.read(); } - uint8_t& AM_ZeroPageX() { - m_busRW = true; + uint8_t AM_ZeroPageX() { Address_ZeroPageX(); - m_memory.ADDRESS() = MEMPTR(); - return m_memory.reference(); + return m_memory.read(MEMPTR()); } - uint8_t& AM_ZeroPageY() { - m_busRW = true; + uint8_t AM_ZeroPageY() { Address_ZeroPageY(); - m_memory.ADDRESS() = MEMPTR(); - return m_memory.reference(); + return m_memory.read(MEMPTR()); } - uint8_t& AM_IndexedIndirectX() { - m_busRW = true; + uint8_t AM_IndexedIndirectX() { Address_IndexedIndirectX(); - m_memory.ADDRESS() = MEMPTR(); - return m_memory.reference(); + return m_memory.read(MEMPTR()); } - uint8_t& AM_IndirectIndexedY(BusDirection direction = BusDirection::Read) { - m_busRW = true; + uint8_t AM_IndirectIndexedY() { Address_IndirectIndexedY(); m_memory.ADDRESS() = MEMPTR(); - if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8)) + if (m_memory.ADDRESS().low == Mask8) ++cycles; - return m_memory.reference(); + return m_memory.read(); } -#pragma endregion References +#pragma endregion Addressing modes, read + +#pragma region Addressing modes, write + + void AM_A(uint8_t value) { + A() = value; + } + + void AM_Absolute(uint8_t value) { + Address_Absolute(); + m_memory.write(MEMPTR(), value); + } + + void AM_ZeroPage(uint8_t value) { + Address_ZeroPage(); + m_memory.write(MEMPTR(), value); + } + + void AM_AbsoluteX(uint8_t value) { + Address_AbsoluteX(); + m_memory.write(MEMPTR(), value); + } + + void AM_AbsoluteY(uint8_t value) { + Address_AbsoluteY(); + m_memory.write(MEMPTR(), value); + } + + void AM_ZeroPageX(uint8_t value) { + Address_ZeroPageX(); + m_memory.write(MEMPTR(), value); + } + + void AM_ZeroPageY(uint8_t value) { + Address_ZeroPageY(); + m_memory.write(MEMPTR(), value); + } + + void AM_IndexedIndirectX(uint8_t value) { + Address_IndexedIndirectX(); + m_memory.write(MEMPTR(), value); + } + + void AM_IndirectIndexedY(uint8_t value) { + Address_IndirectIndexedY(); + m_memory.write(MEMPTR(), value); + } + +#pragma endregion Addressing modes, write #pragma region 6502 addressing mode switching - uint8_t& AM_00(int bbb, BusDirection direction = BusDirection::Read) { + uint8_t AM_00(int bbb) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -246,7 +273,7 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(direction); + return AM_AbsoluteX(); case 0b010: case 0b100: case 0b110: @@ -256,7 +283,33 @@ namespace EightBit { } } - uint8_t& AM_01(int bbb, BusDirection direction = BusDirection::Read) { + void AM_00(int bbb, uint8_t value) { + switch (bbb) { + case 0b000: + assert(false); + break; + 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 0b010: + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + } + + uint8_t AM_01(int bbb) { switch (bbb) { case 0b000: return AM_IndexedIndirectX(); @@ -267,19 +320,50 @@ namespace EightBit { case 0b011: return AM_Absolute(); case 0b100: - return AM_IndirectIndexedY(direction); + return AM_IndirectIndexedY(); case 0b101: return AM_ZeroPageX(); case 0b110: - return AM_AbsoluteY(direction); + return AM_AbsoluteY(); case 0b111: - return AM_AbsoluteX(direction); + return AM_AbsoluteX(); default: __assume(0); } } - uint8_t& AM_10(int bbb, BusDirection direction = BusDirection::Read) { + uint8_t AM_01(int bbb, uint8_t value) { + switch (bbb) { + case 0b000: + AM_IndexedIndirectX(value); + break; + case 0b001: + AM_ZeroPage(value); + break; + case 0b010: + assert(false); + 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; + default: + __assume(0); + } + } + + uint8_t AM_10(int bbb) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -292,7 +376,36 @@ namespace EightBit { case 0b101: return AM_ZeroPageX(); case 0b111: - return AM_AbsoluteX(direction); + return AM_AbsoluteX(); + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + return 0xff; + } + + void AM_10(int bbb, uint8_t value) { + switch (bbb) { + case 0b000: + assert(false); + break; + case 0b001: + AM_ZeroPage(value); + break; + case 0b010: + AM_A(value); + break; + case 0b011: + AM_Absolute(value); + break; + case 0b101: + AM_ZeroPageX(value); + break; + case 0b111: + AM_AbsoluteX(value); + break; case 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -301,7 +414,7 @@ namespace EightBit { } } - uint8_t& AM_10_x(int bbb, BusDirection direction = BusDirection::Read) { + uint8_t AM_10_x(int bbb) { switch (bbb) { case 0b000: return AM_Immediate(); @@ -314,7 +427,35 @@ namespace EightBit { case 0b101: return AM_ZeroPageY(); case 0b111: - return AM_AbsoluteY(direction); + return AM_AbsoluteY(); + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + } + + void AM_10_x(int bbb, uint8_t value) { + switch (bbb) { + case 0b000: + assert(false); + break; + 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 0b100: case 0b110: throw std::domain_error("Illegal addressing mode"); @@ -327,59 +468,40 @@ 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); + auto operand = AM_10(bbb); + ASL(operand); + AM_10(bbb, operand); } void ROL(int bbb) { - auto& reference = AM_10(bbb, BusDirection::Write); - firePendingBusEvents(BusDirection::Read); - ROL(reference); - firePendingBusEvents(BusDirection::Write); + auto operand = AM_10(bbb); + ROL(operand); + AM_10(bbb, operand); } void LSR(int bbb) { - auto& reference = AM_10(bbb, BusDirection::Write); - firePendingBusEvents(BusDirection::Read); - LSR(reference); - firePendingBusEvents(BusDirection::Write); + auto operand = AM_10(bbb); + LSR(operand); + AM_10(bbb, operand); } void ROR(int bbb) { - auto& reference = AM_10(bbb, BusDirection::Write); - firePendingBusEvents(BusDirection::Read); - ROR(reference); - firePendingBusEvents(BusDirection::Write); + auto operand = AM_10(bbb); + ROR(operand); + AM_10(bbb, operand); } void DEC(int bbb) { - auto& reference = AM_10(bbb, BusDirection::Write); - firePendingBusEvents(BusDirection::Read); - adjustNZ(--reference); - firePendingBusEvents(BusDirection::Write); + auto operand = AM_10(bbb); + adjustNZ(--operand); + AM_10(bbb, operand); } void INC(int bbb) { - auto& reference = AM_10(bbb, BusDirection::Write); - firePendingBusEvents(BusDirection::Read); - adjustNZ(++reference); - firePendingBusEvents(BusDirection::Write); + auto operand = AM_10(bbb); + adjustNZ(++operand); + AM_10(bbb, operand); } void ROR(uint8_t& output); @@ -431,7 +553,5 @@ namespace EightBit { std::array m_timings; std::array m_decodedOpcodes; - - bool m_busRW; }; } \ No newline at end of file diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 90742e5..22f09e8 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -135,7 +135,6 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // BIT BIT(AM_00(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; } break; @@ -193,8 +192,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { adjustNZ(A() = Y()); break; default: // STY - AM_00(decoded.bbb, BusDirection::Write) = Y(); - firePendingBusEvents(BusDirection::Write); + AM_00(decoded.bbb, Y()); break; } break; @@ -211,7 +209,6 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // LDY adjustNZ(Y() = AM_00(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; } break; @@ -228,7 +225,6 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // CPY CMP(Y(), AM_00(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; } break; @@ -245,7 +241,6 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // CPX CMP(X(), AM_00(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; } break; @@ -255,35 +250,27 @@ int EightBit::MOS6502::execute(uint8_t cell) { switch (decoded.aaa) { case 0b000: // ORA adjustNZ(A() |= AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b001: // AND adjustNZ(A() &= AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b010: // EOR adjustNZ(A() ^= AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b011: // ADC ADC(AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b100: // STA - AM_01(decoded.bbb, BusDirection::Write) = A(); - firePendingBusEvents(BusDirection::Write); + AM_01(decoded.bbb, A()); break; case 0b101: // LDA adjustNZ(A() = AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b110: // CMP CMP(A(), AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; case 0b111: // SBC SBC(AM_01(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; default: __assume(0); @@ -312,8 +299,7 @@ int EightBit::MOS6502::execute(uint8_t cell) { S() = X(); break; default: // STX - AM_10_x(decoded.bbb, BusDirection::Write) = X(); - firePendingBusEvents(BusDirection::Write); + AM_10_x(decoded.bbb, X()); break; } break; @@ -324,7 +310,6 @@ int EightBit::MOS6502::execute(uint8_t cell) { break; default: // LDX adjustNZ(X() = AM_10_x(decoded.bbb)); - firePendingBusEvents(BusDirection::Read); break; } break; diff --git a/M6502/test_M6502/Board.cpp b/M6502/test_M6502/Board.cpp index 14768b4..5404d60 100644 --- a/M6502/test_M6502/Board.cpp +++ b/M6502/test_M6502/Board.cpp @@ -113,7 +113,7 @@ void Board::Memory_ReadByte_Input(const EightBit::AddressEventArgs& e) { auto cell = e.getCell(); if (cell != 0) { assert(address == m_memory.ADDRESS().word); - m_memory.reference() = 0; + m_memory.write(0); } } } @@ -132,8 +132,6 @@ void Board::Cpu_ExecutedInstruction_Poll(const EightBit::MOS6502& cpu) { } void Board::pollKeyboard() { - if (_kbhit()) { - m_memory.ADDRESS().word = m_configuration.getInputAddress(); - m_memory.reference() = _getch(); - } + if (_kbhit()) + m_memory.write(m_configuration.getInputAddress(), _getch()); } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index 1520e88..715b932 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -55,10 +55,8 @@ void Fuse::TestRunner::initialiseMemory() { for (auto memoryDatum : m_test.memoryData) { auto address = memoryDatum.address; auto bytes = memoryDatum.bytes; - for (int i = 0; i < bytes.size(); ++i) { - m_memory.ADDRESS().word = address + i; - m_memory.reference() = bytes[i]; - } + for (int i = 0; i < bytes.size(); ++i) + m_memory.write(address + i, bytes[i]); } } diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 27b3118..8feee7a 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "IntelProcessor.h" #include "InputOutput.h" @@ -136,12 +137,16 @@ namespace EightBit { return IntelProcessor::fetchExecute(); } - uint8_t& DISPLACED() { - m_memory.ADDRESS().word = MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement; - return m_memory.reference(); + uint16_t displacedAddress() { + assert(m_displaced); + return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement; } - uint8_t& R(int r, uint8_t& a) { + void fetchDisplacement() { + m_displacement = fetchByte(); + } + + uint8_t R(int r, uint8_t a) { switch (r) { case 0: return B(); @@ -156,12 +161,7 @@ namespace EightBit { case 5: return HL2().low; case 6: - if (!m_displaced) { - m_memory.ADDRESS() = HL(); - return m_memory.reference(); - } - m_displacement = fetchByte(); - return DISPLACED(); + return m_memory.read(m_displaced ? displacedAddress() : HL().word); case 7: return a; default: @@ -170,7 +170,38 @@ namespace EightBit { throw std::logic_error("Unhandled registry mechanism"); } - uint8_t& R2(int r, uint8_t& a) { + void R(int r, uint8_t& a, uint8_t value) { + switch (r) { + case 0: + B() = value; + break; + case 1: + C() = value; + break; + case 2: + D() = value; + break; + case 3: + E() = value; + break; + case 4: + HL2().high = value; + break; + case 5: + HL2().low = value; + break; + case 6: + m_memory.write(m_displaced ? displacedAddress() : HL().word, value); + break; + case 7: + a = value; + break; + default: + __assume(0); + } + } + + uint8_t R2(int r, const uint8_t& a) { switch (r) { case 0: return B(); @@ -185,8 +216,7 @@ namespace EightBit { case 5: return L(); case 6: - m_memory.ADDRESS() = HL(); - return m_memory.reference(); + return m_memory.read(HL()); case 7: return a; default: @@ -195,6 +225,37 @@ namespace EightBit { throw std::logic_error("Unhandled registry mechanism"); } + void R2(int r, uint8_t& a, uint8_t value) { + switch (r) { + case 0: + B() = value; + break; + case 1: + C() = value; + break; + case 2: + D() = value; + break; + case 3: + E() = value; + break; + case 4: + H() = value; + break; + case 5: + L() = value; + break; + case 6: + m_memory.write(HL(), value); + break; + case 7: + a = value; + break; + default: + __assume(0); + } + } + register16_t& RP(int rp) { __assume(rp < 4); __assume(rp >= 0); @@ -286,18 +347,18 @@ namespace EightBit { static void orr(uint8_t& f, uint8_t& operand, uint8_t value); static void compare(uint8_t& f, uint8_t check, uint8_t value); - static uint8_t& rlc(uint8_t& f, uint8_t& operand); - static uint8_t& rrc(uint8_t& f, uint8_t& operand); - static uint8_t& rl(uint8_t& f, uint8_t& operand); - static uint8_t& rr(uint8_t& f, uint8_t& operand); - static uint8_t& sla(uint8_t& f, uint8_t& operand); - static uint8_t& sra(uint8_t& f, uint8_t& operand); - static uint8_t& sll(uint8_t& f, uint8_t& operand); - static uint8_t& srl(uint8_t& f, uint8_t& operand); + static uint8_t rlc(uint8_t& f, uint8_t operand); + static uint8_t rrc(uint8_t& f, uint8_t operand); + static uint8_t rl(uint8_t& f, uint8_t operand); + static uint8_t rr(uint8_t& f, uint8_t operand); + static uint8_t sla(uint8_t& f, uint8_t operand); + static uint8_t sra(uint8_t& f, uint8_t operand); + static uint8_t sll(uint8_t& f, uint8_t operand); + static uint8_t srl(uint8_t& f, uint8_t operand); - static uint8_t& bit(uint8_t& f, int n, uint8_t& operand); - static uint8_t& res(int n, uint8_t& operand); - static uint8_t& set(int n, uint8_t& operand); + static uint8_t bit(uint8_t& f, int n, uint8_t operand); + static uint8_t res(int n, uint8_t operand); + static uint8_t set(int n, uint8_t operand); static void daa(uint8_t& a, uint8_t& f); diff --git a/Z80/src/Disassembler.cpp b/Z80/src/Disassembler.cpp index d738a75..ae57228 100644 --- a/Z80/src/Disassembler.cpp +++ b/Z80/src/Disassembler.cpp @@ -181,15 +181,14 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, const Z80& const auto& memory = cpu.getMemory(); auto opcode = memory.peek(pc); - // hex opcode - output << hex(opcode); + const auto& decoded = cpu.getDecodedOpcode(opcode); - auto x = (opcode & 0b11000000) >> 6; - auto y = (opcode & 0b111000) >> 3; - auto z = (opcode & 0b111); + auto x = decoded.x; + auto y = decoded.y; + auto z = decoded.z; - auto p = (y & 0b110) >> 1; - auto q = (y & 1); + auto p = decoded.p; + auto q = decoded.q; auto immediate = memory.peek(pc + 1); auto absolute = memory.peekWord(pc + 1); @@ -199,6 +198,8 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, const Z80& auto dumpCount = 0; + output << hex(opcode); + std::string specification = ""; if (m_prefixCB) diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index b685cfb..c3f4cfa 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -361,7 +361,7 @@ void EightBit::Z80::compare(uint8_t& f, uint8_t check, uint8_t value) { #pragma region Shift and rotate -uint8_t& EightBit::Z80::rlc(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::rlc(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit7); operand = _rotl8(operand, 1); @@ -369,7 +369,7 @@ uint8_t& EightBit::Z80::rlc(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::rrc(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::rrc(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = _rotr8(operand, 1); @@ -377,7 +377,7 @@ uint8_t& EightBit::Z80::rrc(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::rl(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::rl(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); const auto carry = f & CF; setFlag(f, CF, operand & Bit7); @@ -386,7 +386,7 @@ uint8_t& EightBit::Z80::rl(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::rr(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::rr(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); const auto carry = f & CF; setFlag(f, CF, operand & Bit0); @@ -397,7 +397,7 @@ uint8_t& EightBit::Z80::rr(uint8_t& f, uint8_t& operand) { // -uint8_t& EightBit::Z80::sla(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::sla(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit7); operand <<= 1; @@ -405,7 +405,7 @@ uint8_t& EightBit::Z80::sla(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::sra(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::sra(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = (operand >> 1) | operand & Bit7; @@ -413,7 +413,7 @@ uint8_t& EightBit::Z80::sra(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::sll(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::sll(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit7); operand = (operand << 1) | Bit0; @@ -421,7 +421,7 @@ uint8_t& EightBit::Z80::sll(uint8_t& f, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::srl(uint8_t& f, uint8_t& operand) { +uint8_t EightBit::Z80::srl(uint8_t& f, uint8_t operand) { clearFlag(f, NF | HC); setFlag(f, CF, operand & Bit0); operand = (operand >> 1) & ~Bit7; @@ -434,7 +434,7 @@ uint8_t& EightBit::Z80::srl(uint8_t& f, uint8_t& operand) { #pragma region BIT/SET/RES -uint8_t& EightBit::Z80::bit(uint8_t& f, int n, uint8_t& operand) { +uint8_t EightBit::Z80::bit(uint8_t& f, int n, uint8_t operand) { setFlag(f, HC); clearFlag(f, NF); const auto discarded = operand & (1 << n); @@ -443,12 +443,12 @@ uint8_t& EightBit::Z80::bit(uint8_t& f, int n, uint8_t& operand) { return operand; } -uint8_t& EightBit::Z80::res(int n, uint8_t& operand) { - return operand &= ~(1 << n); +uint8_t EightBit::Z80::res(int n, uint8_t operand) { + return operand & ~(1 << n); } -uint8_t& EightBit::Z80::set(int n, uint8_t& operand) { - return operand |= (1 << n); +uint8_t EightBit::Z80::set(int n, uint8_t operand) { + return operand | (1 << n); } #pragma endregion BIT/SET/RES @@ -516,13 +516,12 @@ void EightBit::Z80::ccf(uint8_t a, uint8_t& f) { } void EightBit::Z80::xhtl(register16_t& operand) { - m_memory.ADDRESS() = SP(); - MEMPTR().low = m_memory.reference(); - m_memory.reference() = operand.low; + MEMPTR().low = m_memory.read(SP()); + m_memory.write(operand.low); operand.low = MEMPTR().low; m_memory.ADDRESS().word++; - MEMPTR().high = m_memory.reference(); - m_memory.reference() = operand.high; + MEMPTR().high = m_memory.read(); + m_memory.write(operand.high); operand.high = MEMPTR().high; } @@ -534,9 +533,7 @@ void EightBit::Z80::xhtl(register16_t& operand) { void EightBit::Z80::blockCompare(uint8_t a, uint8_t& f) { - m_memory.ADDRESS() = HL(); - - const auto value = m_memory.reference(); + const auto value = m_memory.read(HL()); uint8_t result = a - value; setFlag(f, PF, --BC().word); @@ -586,11 +583,9 @@ bool EightBit::Z80::cpdr(uint8_t a, uint8_t& f) { #pragma region Block load instructions void EightBit::Z80::blockLoad(uint8_t a, uint8_t& f, register16_t source, register16_t destination) { - m_memory.ADDRESS() = source; - auto value = m_memory.reference(); - m_memory.ADDRESS() = destination; - m_memory.reference() = value; - auto xy = a + value; + const auto value = m_memory.read(source); + m_memory.write(destination, value); + const auto xy = a + value; setFlag(f, XF, xy & 8); setFlag(f, YF, xy & 2); clearFlag(f, NF | HC); @@ -634,8 +629,7 @@ void EightBit::Z80::ini(uint8_t& f) { MEMPTR().word++; readPort(); auto value = m_memory.DATA(); - m_memory.ADDRESS().word = HL().word++; - m_memory.reference() = value; + m_memory.write(HL().word++, value); decrement(f, B()); setFlag(f, NF); } @@ -645,8 +639,7 @@ void EightBit::Z80::ind(uint8_t& f) { MEMPTR().word--; readPort(); auto value = m_memory.DATA(); - m_memory.ADDRESS().word = HL().word--; - m_memory.reference() = value; + m_memory.write(HL().word--, value); decrement(f, B()); setFlag(f, NF); } @@ -666,8 +659,8 @@ bool EightBit::Z80::indr(uint8_t& f) { #pragma region Block output instructions void EightBit::Z80::blockOut(uint8_t& f) { - auto value = m_memory.reference(); - m_memory.ADDRESS().word = BC().word; + auto value = m_memory.read(); + m_memory.ADDRESS() = BC(); writePort(); decrement(f, B()); setFlag(f, NF, value & Bit7); @@ -705,8 +698,9 @@ bool EightBit::Z80::otdr(uint8_t& f) { void EightBit::Z80::rrd(uint8_t& a, uint8_t& f) { MEMPTR() = HL(); - auto memory = memptrReference(); - m_memory.reference() = promoteNibble(a) | highNibble(memory); + memptrReference(); + auto memory = m_memory.read(); + m_memory.write(promoteNibble(a) | highNibble(memory)); a = (a & 0xf0) | lowNibble(memory); adjustSZPXY(f, a); clearFlag(f, NF | HC); @@ -714,8 +708,9 @@ void EightBit::Z80::rrd(uint8_t& a, uint8_t& f) { void EightBit::Z80::rld(uint8_t& a, uint8_t& f) { MEMPTR() = HL(); - auto memory = memptrReference(); - m_memory.reference() = promoteNibble(memory) | lowNibble(a); + memptrReference(); + auto memory = m_memory.read(); + m_memory.write(promoteNibble(memory) | lowNibble(a)); a = (a & 0xf0) | highNibble(memory); adjustSZPXY(f, a); clearFlag(f, NF | HC); @@ -799,42 +794,48 @@ void EightBit::Z80::executeCB(int x, int y, int z) { auto& a = A(); auto& f = F(); switch (x) { - case 0: // rot[y] r[z] + case 0: { // rot[y] r[z] + auto operand = m_displaced ? m_memory.read(displacedAddress()) : R(z, a); switch (y) { case 0: - adjustSZP(f, m_displaced ? R2(z, a) = rlc(f, DISPLACED()) : rlc(f, R(z, a))); + operand = rlc(f, operand); break; case 1: - adjustSZP(f, m_displaced ? R2(z, a) = rrc(f, DISPLACED()) : rrc(f, R(z, a))); + operand = rrc(f, operand); break; case 2: - adjustSZP(f, m_displaced ? R2(z, a) = rl(f, DISPLACED()) : rl(f, R(z, a))); + operand = rl(f, operand); break; case 3: - adjustSZP(f, m_displaced ? R2(z, a) = rr(f, DISPLACED()) : rr(f, R(z, a))); + operand = rr(f, operand); break; case 4: - adjustSZP(f, m_displaced ? R2(z, a) = sla(f, DISPLACED()) : sla(f, R(z, a))); + operand = sla(f, operand); break; case 5: - adjustSZP(f, m_displaced ? R2(z, a) = sra(f, DISPLACED()) : sra(f, R(z, a))); + operand = sra(f, operand); break; case 6: - adjustSZP(f, m_displaced ? R2(z, a) = sll(f, DISPLACED()) : sll(f, R(z, a))); + operand = sll(f, operand); break; case 7: - adjustSZP(f, m_displaced ? R2(z, a) = srl(f, DISPLACED()) : srl(f, R(z, a))); + operand = srl(f, operand); break; } - cycles += 8; - if (!m_displaced) { + adjustSZP(f, operand); + if (m_displaced) { + if (z != 6) + R2(z, a, operand); + m_memory.write(operand); + cycles += 15; + } else { + R(z, a, operand); if (z == 6) cycles += 7; - } else { - cycles += 15; } + cycles += 8; break; - case 1: // BIT y, r[z] + } case 1: // BIT y, r[z] cycles += 8; if (!m_displaced) { auto operand = bit(f, y, R(z, a)); @@ -845,7 +846,7 @@ void EightBit::Z80::executeCB(int x, int y, int z) { adjustXY(f, operand); } } else { - bit(f, y, DISPLACED()); + bit(f, y, m_memory.read(displacedAddress())); adjustXY(f, MEMPTR().high); cycles += 12; } @@ -853,22 +854,28 @@ void EightBit::Z80::executeCB(int x, int y, int z) { case 2: // RES y, r[z] cycles += 8; if (!m_displaced) { - res(y, R(z, a)); + R(z, a, res(y, R(z, a))); if (z == 6) cycles += 7; } else { - R2(z, a) = res(y, DISPLACED()); + auto operand = m_memory.read(displacedAddress()); + operand = res(y, operand); + m_memory.write(operand); + R2(z, a, operand); cycles += 15; } break; case 3: // SET y, r[z] cycles += 8; if (!m_displaced) { - set(y, R(z, a)); + R(z, a, set(y, R(z, a))); if (z == 6) cycles += 7; } else { - R2(z, a) = set(y, DISPLACED()); + auto operand = m_memory.read(displacedAddress()); + operand = set(y, operand); + m_memory.write(operand); + R2(z, a, operand); cycles += 15; } break; @@ -892,7 +899,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) { MEMPTR().word++; readPort(); if (y != 6) // IN r[y],(C) - R(y, a) = m_memory.DATA(); + R(y, a, m_memory.DATA()); adjustSZPXY(f, m_memory.DATA()); clearFlag(f, NF | HC); cycles += 12; @@ -1169,12 +1176,14 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { switch (p) { case 0: // LD (BC),A MEMPTR() = BC(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 7; break; case 1: // LD (DE),A MEMPTR() = DE(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 7; break; case 2: // LD (nn),HL @@ -1184,7 +1193,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { break; case 3: // LD (nn),A fetchWord(); - MEMPTR().high = memptrReference() = a; + memptrReference(); + m_memory.write(MEMPTR().high = a); cycles += 13; break; default: @@ -1195,12 +1205,14 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { switch (p) { case 0: // LD A,(BC) MEMPTR() = BC(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 7; break; case 1: // LD A,(DE) MEMPTR() = DE(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 7; break; case 2: // LD HL,(nn) @@ -1210,7 +1222,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { break; case 3: // LD A,(nn) fetchWord(); - a = memptrReference(); + memptrReference(); + a = m_memory.read(); cycles += 13; break; default: @@ -1234,36 +1247,45 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { } cycles += 6; break; - case 4: // 8-bit INC - increment(f, R(y, a)); // INC r + case 4: { // 8-bit INC + if (m_displaced && (y == 6)) + fetchDisplacement(); + auto operand = R(y, a); + increment(f, operand); + R(y, a, operand); cycles += 4; break; - case 5: // 8-bit DEC - decrement(f, R(y, a)); // DEC r + } case 5: { // 8-bit DEC + if (m_displaced && (y == 6)) + fetchDisplacement(); + auto operand = R(y, a); + decrement(f, operand); + R(y, a, operand); cycles += 4; if (y == 6) cycles += 7; break; - case 6: { // 8-bit load immediate - auto& r = R(y, a); // LD r,n - r = fetchByte(); + } case 6: // 8-bit load immediate + if (m_displaced && (y == 6)) + fetchDisplacement(); + R(y, a, fetchByte()); // LD r,n cycles += 7; if (y == 6) cycles += 3; break; - } case 7: // Assorted operations on accumulator/flags + case 7: // Assorted operations on accumulator/flags switch (y) { case 0: - rlc(f, a); + a = rlc(f, a); break; case 1: - rrc(f, a); + a = rrc(f, a); break; case 2: - rl(f, a); + a = rl(f, a); break; case 3: - rr(f, a); + a = rr(f, a); break; case 4: daa(a, f); @@ -1293,6 +1315,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { bool normal = true; if (m_displaced) { if (z == 6) { + fetchDisplacement(); switch (y) { case 4: H() = R(z, a); @@ -1305,26 +1328,29 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { } } if (y == 6) { + fetchDisplacement(); switch (z) { case 4: - R(y, a) = H(); + R(y, a, H()); normal = false; break; case 5: - R(y, a) = L(); + R(y, a, L()); normal = false; break; } } } if (normal) - R(y, a) = R(z, a); + R(y, a, R(z, a)); if ((y == 6) || (z == 6)) // M operations cycles += 3; } cycles += 4; break; case 2: // Operate on accumulator and register/memory location + if (m_displaced && (z == 6)) + fetchDisplacement(); switch (y) { case 0: // ADD A,r add(f, a, R(z, a)); @@ -1410,7 +1436,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { case 1: // CB prefix m_prefixCB = true; if (m_displaced) - m_displacement = fetchByte(); + fetchDisplacement(); fetchExecute(); break; case 2: // OUT (n),A diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index c3d4984..a2daa5d 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -20,8 +20,7 @@ void Board::initialise() { //m_memory.loadRam(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics //m_memory.loadRam(romDirectory + "/TEST.COM", 0x100); // Microcosm - m_memory.ADDRESS().word = 5; - m_memory.reference() = 0xc9; // ret + m_memory.write(5, 0xc9); // ret m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1)); if (m_configuration.isProfileMode()) { diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index a26d735..a47153d 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -120,8 +120,7 @@ namespace EightBit { } virtual void push(uint8_t value) { - m_memory.ADDRESS().word = --SP().word; - m_memory.reference() = value; + m_memory.write(--SP().word, value); } void pushWord(const register16_t& value) { @@ -130,8 +129,7 @@ namespace EightBit { } virtual uint8_t pop() { - m_memory.ADDRESS().word = SP().word++; - return m_memory.reference(); + return m_memory.read(SP().word++); } void popWord(register16_t& output) { @@ -145,22 +143,23 @@ namespace EightBit { // - uint8_t& memptrReference() { + void memptrReference() { m_memory.ADDRESS() = MEMPTR(); MEMPTR().word++; - return m_memory.reference(); } virtual void getWordViaMemptr(register16_t& value) { - value.low = memptrReference(); + memptrReference(); + value.low = m_memory.read(); m_memory.ADDRESS().word++; - value.high = m_memory.reference(); + value.high = m_memory.read(); } virtual void setWordViaMemptr(register16_t value) { - memptrReference() = value.low; + memptrReference(); + m_memory.write(value.low); m_memory.ADDRESS().word++; - m_memory.reference() = value.high; + m_memory.write(value.high); } // diff --git a/inc/Memory.h b/inc/Memory.h index cbb3f8e..90dd4d7 100644 --- a/inc/Memory.h +++ b/inc/Memory.h @@ -56,19 +56,10 @@ namespace EightBit { virtual uint8_t peek(uint16_t address) const; virtual uint16_t peekWord(uint16_t address) const; - virtual uint8_t& reference() { - auto effective = effectiveAddress(ADDRESS().word); - return m_locked[effective] ? placeDATA(m_bus[effective]) : referenceDATA(m_bus[effective]); - } - virtual int effectiveAddress(int address) const { return address & m_addressMask; } - void fireReadBusEvent() { - ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA())); - } - uint8_t read() { auto content = reference(); fireReadBusEvent(); @@ -80,8 +71,9 @@ namespace EightBit { return read(); } - void fireWriteBusEvent() { - WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + uint8_t read(register16_t address) { + ADDRESS() = address; + return read(); } void write(uint8_t value) { @@ -94,6 +86,11 @@ namespace EightBit { write(value); } + void write(register16_t address, uint8_t value) { + ADDRESS() = address; + write(value); + } + void clear(); void loadRom(const std::string& path, uint16_t offset); void loadRam(const std::string& path, uint16_t offset); @@ -111,6 +108,19 @@ namespace EightBit { register16_t m_address; uint8_t* m_data; + void fireReadBusEvent() { + ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + + void fireWriteBusEvent() { + WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + + virtual uint8_t& reference() { + auto effective = effectiveAddress(ADDRESS().word); + return m_locked[effective] ? placeDATA(m_bus[effective]) : referenceDATA(m_bus[effective]); + } + int loadMemory(const std::string& path, uint16_t offset); }; } \ No newline at end of file diff --git a/inc/Processor.h b/inc/Processor.h index 0cf7151..fba4ae8 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -75,8 +75,7 @@ namespace EightBit { int cycles; virtual uint8_t fetchByte() { - m_memory.ADDRESS().word = PC().word++; - return m_memory.reference(); + return m_memory.read(PC().word++); } virtual void fetchWord(register16_t& output) {