From fac2da9ac4d55f0311b77d4f32834277d7fd9dfd Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 27 Oct 2018 18:41:55 +0100 Subject: [PATCH] Start refactoring CPU cores to use C++17/14 features. (This commit covers the 6502 and Z80) Signed-off-by: Adrian Conlon --- M6502/inc/mos6502.h | 119 +++++++++++++++++++++-------------------- M6502/src/mos6502.cpp | 6 +-- Z80/inc/Z80.h | 120 +++++++++++++++++++++--------------------- Z80/src/Z80.cpp | 45 +++++++--------- 4 files changed, 142 insertions(+), 148 deletions(-) diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 4139800..c827db9 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -63,10 +63,10 @@ namespace EightBit { void interrupt(uint8_t vector); - void adjustZero(uint8_t datum) { clearFlag(P(), ZF, datum); } - void adjustNegative(uint8_t datum) { setFlag(P(), NF, datum & NF); } + void adjustZero(const uint8_t datum) { clearFlag(P(), ZF, datum); } + void adjustNegative(const uint8_t datum) { setFlag(P(), NF, datum & NF); } - void adjustNZ(uint8_t datum) { + void adjustNZ(const uint8_t datum) { adjustZero(datum); adjustNegative(datum); } @@ -76,19 +76,19 @@ namespace EightBit { // Address resolution - register16_t Address_Absolute() { + auto Address_Absolute() { return fetchWord(); } - uint8_t Address_ZeroPage() { + auto Address_ZeroPage() { return fetchByte(); } - register16_t Address_ZeroPageIndirect() { + auto Address_ZeroPageIndirect() { return getWordPaged(0, Address_ZeroPage()); } - register16_t Address_Indirect() { + auto Address_Indirect() { const auto address = Address_Absolute(); return getWordPaged(address.high, address.low); } @@ -101,110 +101,113 @@ namespace EightBit { return Address_ZeroPage() + Y(); } - std::tuple Address_AbsoluteX() { + auto Address_AbsoluteX() { auto address = Address_Absolute(); const auto page = address.high; address += X(); - return std::tuple(address, address.high != page); + return std::make_pair(address, address.high != page); } - std::tuple Address_AbsoluteY() { + auto Address_AbsoluteY() { auto address = Address_Absolute(); const auto page = address.high; address += Y(); - return std::tuple(address, address.high != page); + return std::make_pair(address, address.high != page); } - register16_t Address_IndexedIndirectX() { + auto Address_IndexedIndirectX() { return getWordPaged(0, Address_ZeroPageX()); } - std::tuple Address_IndirectIndexedY() { + auto Address_IndirectIndexedY() { auto address = Address_ZeroPageIndirect(); const auto page = address.high; address += Y(); - return std::tuple(address, address.high != page); + return std::make_pair(address, address.high != page); } // Addressing modes, read - uint8_t AM_Immediate() { + auto AM_Immediate() { return fetchByte(); } - uint8_t AM_Absolute() { + auto AM_Absolute() { return BUS().read(Address_Absolute()); } - uint8_t AM_ZeroPage() { + auto AM_ZeroPage() { return BUS().read(Address_ZeroPage()); } - uint8_t AM_AbsoluteX() { - const auto ap = Address_AbsoluteX(); - if (UNLIKELY(std::get<1>(ap))) + auto AM_AbsoluteX() { + const auto [address, paged] = Address_AbsoluteX(); + if (UNLIKELY(paged)) addCycle(); - return BUS().read(std::get<0>(ap)); + return BUS().read(address); } - uint8_t AM_AbsoluteY() { - const auto ap = Address_AbsoluteY(); - if (UNLIKELY(std::get<1>(ap))) + auto AM_AbsoluteY() { + const auto [address, paged] = Address_AbsoluteY(); + if (UNLIKELY(paged)) addCycle(); - return BUS().read(std::get<0>(ap)); + return BUS().read(address); } - uint8_t AM_ZeroPageX() { + auto AM_ZeroPageX() { return BUS().read(Address_ZeroPageX()); } - uint8_t AM_ZeroPageY() { + auto AM_ZeroPageY() { return BUS().read(Address_ZeroPageY()); } - uint8_t AM_IndexedIndirectX() { + auto AM_IndexedIndirectX() { return BUS().read(Address_IndexedIndirectX()); } - uint8_t AM_IndirectIndexedY() { - const auto ap = Address_IndirectIndexedY(); - if (UNLIKELY(std::get<1>(ap))) + auto AM_IndirectIndexedY() { + const auto [address, paged] = Address_IndirectIndexedY(); + if (UNLIKELY(paged)) addCycle(); - return BUS().read(std::get<0>(ap)); + return BUS().read(address); } // Addressing modes, write - void AM_Absolute(uint8_t value) { + void AM_Absolute(const uint8_t value) { BUS().write(Address_Absolute(), value); } - void AM_ZeroPage(uint8_t value) { + void AM_ZeroPage(const uint8_t value) { BUS().write(Address_ZeroPage(), value); } - void AM_AbsoluteX(uint8_t value) { - BUS().write(std::get<0>(Address_AbsoluteX()), value); + void AM_AbsoluteX(const uint8_t value) { + const auto [address, paged] = Address_AbsoluteX(); + BUS().write(address, value); } - void AM_AbsoluteY(uint8_t value) { - BUS().write(std::get<0>(Address_AbsoluteY()), value); + void AM_AbsoluteY(const uint8_t value) { + const auto [address, paged] = Address_AbsoluteY(); + BUS().write(address, value); } - void AM_ZeroPageX(uint8_t value) { + void AM_ZeroPageX(const uint8_t value) { BUS().write(Address_ZeroPageX(), value); } - void AM_ZeroPageY(uint8_t value) { + void AM_ZeroPageY(const uint8_t value) { BUS().write(Address_ZeroPageY(), value); } - void AM_IndexedIndirectX(uint8_t value) { + void AM_IndexedIndirectX(const uint8_t value) { BUS().write(Address_IndexedIndirectX(), value); } - void AM_IndirectIndexedY(uint8_t value) { - BUS().write(std::get<0>(Address_IndirectIndexedY()), value); + void AM_IndirectIndexedY(const uint8_t value) { + const auto [address, paged] = Address_IndirectIndexedY(); + BUS().write(address, value); } // Operations @@ -219,77 +222,77 @@ namespace EightBit { A() = SBC(A(), value); } - void SLO(uint8_t value) { + void SLO(const uint8_t value) { const auto result = ASL(value); BUS().write(result); ORA(result); } - void SRE(uint8_t value) { + void SRE(const uint8_t value) { const auto result = LSR(value); BUS().write(result); EORA(result); } - void RLA(uint8_t value) { + void RLA(const uint8_t value) { const auto result = ROL(value); BUS().write(result); ANDA(result); } - void RRA(uint8_t value) { + void RRA(const uint8_t value) { const auto result = ROR(value); BUS().write(result); A() = ADC(A(), result); } - void LAX(uint8_t value) { + void LAX(const uint8_t value) { adjustNZ(X() = A() = value); } - void AAC(uint8_t value) { + void AAC(const uint8_t value) { ANDA(value); setFlag(P(), CF, A() & Bit7); } - void ASR(uint8_t value) { + void ASR(const uint8_t value) { A() = LSR(A() & value); } - void ARR(uint8_t value) { + void ARR(const uint8_t value) { } - void ATX(uint8_t value) { + void ATX(const uint8_t value) { ANDA(value); X() = A(); } - void AXS(uint8_t value) { + void AXS(const uint8_t value) { } // - uint8_t DEC(uint8_t value) { + auto DEC(uint8_t value) { const auto result = --value; adjustNZ(result); return result; } - uint8_t INC(uint8_t value) { + auto INC(uint8_t value) { const auto result = ++value; adjustNZ(result); return result; } - void ORA(uint8_t value) { + void ORA(const uint8_t value) { adjustNZ(A() |= value); } - void ANDA(uint8_t value) { + void ANDA(const uint8_t value) { adjustNZ(A() &= value); } - void EORA(uint8_t value) { + void EORA(const uint8_t value) { adjustNZ(A() ^= value); } diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 610ae55..e99b513 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -441,7 +441,7 @@ uint8_t EightBit::MOS6502::SUB_d(const uint8_t operand, const uint8_t data, cons return promoteNibble(high) | lowNibble(low); } -void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) { +void EightBit::MOS6502::CMP(const uint8_t first, const uint8_t second) { const register16_t result = first - second; adjustNZ(result.low); clearFlag(P(), CF, result.high); @@ -487,7 +487,7 @@ uint8_t EightBit::MOS6502::ADD_d(uint8_t operand, uint8_t data, int carry) { //// -void EightBit::MOS6502::Branch(int8_t displacement) { +void EightBit::MOS6502::Branch(const int8_t displacement) { const auto page = PC().high; PC() += displacement; if (UNLIKELY(PC().high != page)) @@ -495,7 +495,7 @@ void EightBit::MOS6502::Branch(int8_t displacement) { addCycle(); } -void EightBit::MOS6502::Branch(bool flag) { +void EightBit::MOS6502::Branch(const bool flag) { const int8_t displacement = AM_Immediate(); if (UNLIKELY(flag)) Branch(displacement); diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index de65207..f4c37b6 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -28,7 +28,7 @@ namespace EightBit { return (high << 7) | variable; } - refresh_t& operator++() { + auto& operator++() { ++variable; return *this; } @@ -51,8 +51,8 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - PinLevel& NMI() { return m_nmiLine; } // In - PinLevel& M1() { return m_m1Line; } // Out + auto& NMI() { return m_nmiLine; } // In + auto& M1() { return m_m1Line; } // Out virtual int execute(uint8_t opcode) final; virtual int step() final; @@ -63,19 +63,19 @@ namespace EightBit { virtual register16_t& DE() final; virtual register16_t& HL() final; - register16_t& IX() { return m_ix; } - uint8_t& IXH() { return IX().high; } - uint8_t& IXL() { return IX().low; } + auto& IX() { return m_ix; } + auto& IXH() { return IX().high; } + auto& IXL() { return IX().low; } - register16_t& IY() { return m_iy; } - uint8_t& IYH() { return IY().high; } - uint8_t& IYL() { return IY().low; } + auto& IY() { return m_iy; } + auto& IYH() { return IY().high; } + auto& IYL() { return IY().low; } - refresh_t& REFRESH() { return m_refresh; } - uint8_t& IV() { return iv; } - int& IM() { return m_interruptMode; } - bool& IFF1() { return m_iff1; } - bool& IFF2() { return m_iff2; } + auto& REFRESH() { return m_refresh; } + auto& IV() { return iv; } + auto& IM() { return m_interruptMode; } + auto& IFF1() { return m_iff1; } + auto& IFF2() { return m_iff2; } void exx() { m_registerSet ^= 1; @@ -132,7 +132,50 @@ namespace EightBit { m_displacement = fetchByte(); } - uint8_t R(const int r) { + auto& HL2() { + if (LIKELY(!m_displaced)) + return HL(); + if (m_prefixDD) + return IX(); + // Must be FD prefix + return IY(); + } + + auto& RP(const int rp) { + ASSUME(rp >= 0); + ASSUME(rp <= 3); + switch (rp) { + case 0: + return BC(); + case 1: + return DE(); + case 2: + return HL2(); + case 3: + return SP(); + default: + UNREACHABLE; + } + } + + auto& RP2(const int rp) { + ASSUME(rp >= 0); + ASSUME(rp <= 3); + switch (rp) { + case 0: + return BC(); + case 1: + return DE(); + case 2: + return HL2(); + case 3: + return AF(); + default: + UNREACHABLE; + } + } + + auto R(const int r) { ASSUME(r >= 0); ASSUME(r <= 7); switch (r) { @@ -190,7 +233,7 @@ namespace EightBit { } } - uint8_t R2(const int r) { + auto R2(const int r) { ASSUME(r >= 0); ASSUME(r <= 7); switch (r) { @@ -248,49 +291,6 @@ namespace EightBit { } } - register16_t& RP(const int rp) { - ASSUME(rp >= 0); - ASSUME(rp <= 3); - switch (rp) { - case 0: - return BC(); - case 1: - return DE(); - case 2: - return HL2(); - case 3: - return SP(); - default: - UNREACHABLE; - } - } - - register16_t& HL2() { - if (LIKELY(!m_displaced)) - return HL(); - if (m_prefixDD) - return IX(); - // Must be FD prefix - return IY(); - } - - register16_t& RP2(const int rp) { - ASSUME(rp >= 0); - ASSUME(rp <= 3); - switch (rp) { - case 0: - return BC(); - case 1: - return DE(); - case 2: - return HL2(); - case 3: - return AF(); - default: - UNREACHABLE; - } - } - static void adjustHalfCarryAdd(uint8_t& f, const uint8_t before, const uint8_t value, const int calculation) { setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation)); } @@ -395,7 +395,7 @@ namespace EightBit { void ind(); bool indr(); - void blockOut(const register16_t source, register16_t& destination); + void blockOut(register16_t source, register16_t& destination); void outi(); bool otir(); diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 03fe34c..b750062 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -38,15 +38,16 @@ void EightBit::Z80::powerOn() { IV() = Mask8; exxAF(); - exx(); + AF() = Mask16; - IX() = IY() = AF() = BC() = DE() = HL() = Mask16; + exx(); + IX() = IY() = BC() = DE() = HL() = Mask16; m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; } void EightBit::Z80::handleRESET() { - Processor::handleRESET(); + IntelProcessor::handleRESET(); di(); addCycles(3); } @@ -60,7 +61,7 @@ void EightBit::Z80::handleNMI() { } void EightBit::Z80::handleINT() { - Processor::handleINT(); + IntelProcessor::handleINT(); raise(HALT()); if (IFF1()) { di(); @@ -73,7 +74,7 @@ void EightBit::Z80::handleINT() { addCycles(13); break; case 2: - call(MEMPTR() = register16_t(BUS().DATA(), IV())); + call(MEMPTR() = { BUS().DATA(), IV() }); addCycles(19); break; default: @@ -599,8 +600,7 @@ bool EightBit::Z80::otdr() { } void EightBit::Z80::rrd() { - MEMPTR() = BUS().ADDRESS() = HL(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = HL(); const auto memory = BUS().read(); BUS().write(promoteNibble(A()) | highNibble(memory)); A() = higherNibble(A()) | lowerNibble(memory); @@ -609,8 +609,7 @@ void EightBit::Z80::rrd() { } void EightBit::Z80::rld() { - MEMPTR() = BUS().ADDRESS() = HL(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = HL(); const auto memory = BUS().read(); BUS().write(promoteNibble(memory) | lowNibble(A())); A() = higherNibble(A()) | highNibble(memory); @@ -619,7 +618,7 @@ void EightBit::Z80::rld() { } void EightBit::Z80::writePort(const uint8_t port) { - MEMPTR() = BUS().ADDRESS() = register16_t(port, A()); + MEMPTR() = BUS().ADDRESS() = { port, A() }; BUS().DATA() = A(); writePort(); ++MEMPTR().low; @@ -630,7 +629,7 @@ void EightBit::Z80::writePort() { } uint8_t EightBit::Z80::readPort(const uint8_t port) { - MEMPTR() = BUS().ADDRESS() = register16_t(port, A()); + MEMPTR() = BUS().ADDRESS() = { port, A() }; ++MEMPTR().low; return readPort(); } @@ -814,8 +813,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p case 1: switch (z) { case 0: // Input from port with 16-bit address - MEMPTR() = BUS().ADDRESS() = BC(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = BC(); readPort(); if (LIKELY(y != 6)) // IN r[y],(C) R(y, BUS().DATA()); @@ -824,8 +822,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p addCycles(12); break; case 1: // Output to port with 16-bit address - MEMPTR() = BUS().ADDRESS() = BC(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = BC(); if (UNLIKELY(y == 6)) // OUT (C),0 BUS().DATA() = 0; else // OUT (C),r[y] @@ -1105,15 +1102,13 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in case 0: switch (p) { case 0: // LD (BC),A - MEMPTR() = BUS().ADDRESS() = BC(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = BC(); MEMPTR().high = BUS().DATA() = A(); BUS().write(); addCycles(7); break; case 1: // LD (DE),A - MEMPTR() = BUS().ADDRESS() = DE(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = DE(); MEMPTR().high = BUS().DATA() = A(); BUS().write(); addCycles(7); @@ -1124,8 +1119,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in addCycles(16); break; case 3: // LD (nn),A - MEMPTR() = BUS().ADDRESS() = fetchWord(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = fetchWord(); MEMPTR().high = BUS().DATA() = A(); BUS().write(); addCycles(13); @@ -1137,14 +1131,12 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in case 1: switch (p) { case 0: // LD A,(BC) - MEMPTR() = BUS().ADDRESS() = BC(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = BC(); A() = BUS().read(); addCycles(7); break; case 1: // LD A,(DE) - MEMPTR() = BUS().ADDRESS() = DE(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = DE(); A() = BUS().read(); addCycles(7); break; @@ -1154,8 +1146,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in addCycles(16); break; case 3: // LD A,(nn) - MEMPTR() = BUS().ADDRESS() = fetchWord(); - ++MEMPTR(); + MEMPTR()++ = BUS().ADDRESS() = fetchWord(); A() = BUS().read(); addCycles(13); break;