diff --git a/Z80/HarteTest_Z80/TestRunner.cpp b/Z80/HarteTest_Z80/TestRunner.cpp index 14a0ccb..7e60a9d 100644 --- a/Z80/HarteTest_Z80/TestRunner.cpp +++ b/Z80/HarteTest_Z80/TestRunner.cpp @@ -20,4 +20,4 @@ void TestRunner::lowerPOWER() noexcept { EightBit::Bus::lowerPOWER(); } -void TestRunner::initialise() {} +void TestRunner::initialise() noexcept {} diff --git a/Z80/HarteTest_Z80/TestRunner.h b/Z80/HarteTest_Z80/TestRunner.h index 0dea53e..af55c84 100644 --- a/Z80/HarteTest_Z80/TestRunner.h +++ b/Z80/HarteTest_Z80/TestRunner.h @@ -19,7 +19,7 @@ public: void raisePOWER() noexcept final; void lowerPOWER() noexcept final; - void initialise() final; + void initialise() noexcept final; [[nodiscard]] constexpr auto& RAM() noexcept { return m_ram; } [[nodiscard]] constexpr auto& ports() noexcept { return m_ports; } diff --git a/Z80/inc/Disassembler.h b/Z80/inc/Disassembler.h index a016d7d..4892aa9 100644 --- a/Z80/inc/Disassembler.h +++ b/Z80/inc/Disassembler.h @@ -10,7 +10,7 @@ namespace EightBit { class Disassembler final { public: - Disassembler(Bus& bus) noexcept; + Disassembler(Bus& bus); static std::string state(Z80& cpu); std::string disassemble(Z80& cpu); diff --git a/Z80/inc/Profiler.h b/Z80/inc/Profiler.h index 5f7975f..9fdfa80 100644 --- a/Z80/inc/Profiler.h +++ b/Z80/inc/Profiler.h @@ -27,21 +27,21 @@ namespace EightBit { [[nodiscard]] constexpr const auto& instructions() const { return m_instructions; } [[nodiscard]] constexpr const auto& addresses() const { return m_addresses; } - [[nodiscard]] constexpr auto instructions_available() const noexcept { + [[nodiscard]] constexpr auto instructions_available() const { const auto found = std::find_if( instructions().begin(), instructions().end(), [](const auto& value) { return value != 0; }); return found != instructions().end(); } - [[nodiscard]] constexpr auto addresses_available() const noexcept { + [[nodiscard]] constexpr auto addresses_available() const { const auto found = std::find_if( addresses().begin(), addresses().end(), [](const auto& value) { return value != 0; }); return found != addresses().end(); } - [[nodiscard]] constexpr auto available() const noexcept { + [[nodiscard]] constexpr auto available() const { return instructions_available() || addresses_available(); } diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 95a7622..19ab26e 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -29,14 +29,6 @@ namespace EightBit { DECLARE_PIN_OUTPUT(RD) DECLARE_PIN_OUTPUT(WR) - private: - DEFINE_PIN_ACTIVATOR_LOW(RFSH) - DEFINE_PIN_ACTIVATOR_LOW(M1) - DEFINE_PIN_ACTIVATOR_LOW(MREQ) - DEFINE_PIN_ACTIVATOR_LOW(IORQ) - DEFINE_PIN_ACTIVATOR_LOW(RD) - DEFINE_PIN_ACTIVATOR_LOW(WR) - public: struct refresh_t { @@ -70,30 +62,24 @@ namespace EightBit { CF = Bit0, }; - Z80(Bus& bus, InputOutput& ports); + Z80(Bus& bus, InputOutput& ports) noexcept; - Z80(const Z80& rhs); - bool operator==(const Z80& rhs) const; + Z80(const Z80& rhs) noexcept; + bool operator==(const Z80& rhs) const noexcept; void execute() noexcept final; void poweredStep() noexcept final; - [[nodiscard]] const register16_t& AF() const noexcept final; - [[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); } - [[nodiscard]] const register16_t& BC() const noexcept final; - [[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); } - [[nodiscard]] const register16_t& DE() const noexcept final; - [[nodiscard]] auto& DE() noexcept { return IntelProcessor::DE(); } - [[nodiscard]] const register16_t& HL() const noexcept final; - [[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); } + [[nodiscard]] register16_t& AF() noexcept final; + [[nodiscard]] register16_t& BC() noexcept final; + [[nodiscard]] register16_t& DE() noexcept final; + [[nodiscard]] register16_t& HL() noexcept final; - [[nodiscard]] constexpr const auto& IX() const noexcept { return m_ix; } - NON_CONST_REGISTOR_ACCESSOR(IX); + [[nodiscard]] constexpr auto& IX() noexcept { return m_ix; } [[nodiscard]] constexpr auto& IXH() noexcept { return IX().high; } [[nodiscard]] constexpr auto& IXL() noexcept { return IX().low; } - [[nodiscard]] constexpr const auto& IY() const noexcept { return m_iy; } - NON_CONST_REGISTOR_ACCESSOR(IY); + [[nodiscard]] constexpr auto& IY() noexcept { return m_iy; } [[nodiscard]] constexpr auto& IYH() noexcept { return IY().high; } [[nodiscard]] constexpr auto& IYL() noexcept { return IY().low; } @@ -109,16 +95,11 @@ namespace EightBit { // programmer. During refresh, the contents of the I Register are placed on the upper eight // bits of the address bus. [[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; } - [[nodiscard]] constexpr auto REFRESH() const noexcept { return m_refresh; } [[nodiscard]] constexpr auto& IV() noexcept { return iv; } - [[nodiscard]] constexpr auto IV() const noexcept { return iv; } [[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; } - [[nodiscard]] constexpr auto IM() const noexcept { return m_interruptMode; } [[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; } - [[nodiscard]] constexpr auto IFF1() const noexcept { return m_iff1; } [[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; } - [[nodiscard]] constexpr auto IFF2() const noexcept { return m_iff2; } [[nodiscard]] constexpr auto& Q() noexcept { return m_q; } @@ -131,18 +112,20 @@ namespace EightBit { [[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); } [[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); } + [[nodiscard]] constexpr auto fetchingOpCode() const noexcept { return lowered(M1()); } + protected: void handleRESET() noexcept final; void handleINT() noexcept final; - void memoryUpdate(int ticks) noexcept; + void memoryUpdate(int ticks = 1) noexcept; void memoryWrite() noexcept final; uint8_t memoryRead() noexcept final; void refreshMemory() noexcept; void jumpRelative(int8_t offset) noexcept final; - void call(register16_t destination) final; + void call(register16_t destination) noexcept final; private: bool m_interruptPending = false; @@ -181,23 +164,17 @@ namespace EightBit { void handleNMI() noexcept; - constexpr void resetPrefixes() noexcept { - m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; - } - [[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; } [[nodiscard]] constexpr void displaceAddress() noexcept { const auto& index_register = m_prefixDD ? IX() : IY(); - const auto address = index_register.word + m_displacement; - MEMPTR().word = address; - BUS().ADDRESS() = MEMPTR(); + BUS().ADDRESS() = MEMPTR() = index_register.word + m_displacement; } void fetchDisplacement() noexcept; [[nodiscard]] uint8_t fetchInstruction() noexcept final; - uint8_t readDataUnderInterrupt(); + uint8_t readDataUnderInterrupt() noexcept; typedef std::function addresser_t; void loadAccumulatorIndirect(addresser_t addresser) noexcept; @@ -339,70 +316,17 @@ namespace EightBit { return adjustOverflowSub(input, signTest(before), signTest(value), signTest(calculation)); } - [[nodiscard]] bool convertCondition(int flag) noexcept override { - switch (flag) { - case 0: - return zero() == 0; - case 1: - return zero() != 0; - case 2: - return carry() == 0; - case 3: - return carry() != 0; - case 4: - return parity() == 0; - case 5: - return parity() != 0; - case 6: - return sign() == 0; - case 7: - return sign() != 0; - default: - UNREACHABLE; - } - } - - auto subtract(uint8_t value, int carry = 0) noexcept { - - const auto operand = A(); - - const register16_t subtraction = operand - value - carry; - const auto result = subtraction.low; - - adjustHalfCarrySub(operand, value, result); - adjustOverflowSub(operand, value, result); - - setBit(NF); - setBit(CF, carryTest(subtraction.high)); - adjustSZ(result); - - return result; - } + [[nodiscard]] bool convertCondition(int flag) noexcept final; void executeCB(int x, int y, int z) noexcept; void executeED(int x, int y, int z, int p, int q) noexcept; void executeOther(int x, int y, int z, int p, int q) noexcept; - [[nodiscard]] auto increment(uint8_t operand) noexcept { - clearBit(NF); - const uint8_t result = operand + 1; - adjustSZXY(result); - setBit(VF, result == Bit7); - clearBit(HC, lowNibble(result)); - return result; - } + [[nodiscard]] uint8_t increment(uint8_t operand) noexcept; + [[nodiscard]] uint8_t decrement(uint8_t operand) noexcept; - [[nodiscard]] auto decrement(uint8_t operand) noexcept { - setBit(NF); - clearBit(HC, lowNibble(operand)); - const uint8_t result = operand - 1; - adjustSZXY(result); - setBit(VF, result == Mask7); - return result; - } - - void disableInterrupts() override; - void enableInterrupts() override; + void disableInterrupts() noexcept final; + void enableInterrupts() noexcept final; void retn() noexcept; void reti() noexcept; @@ -413,178 +337,35 @@ namespace EightBit { void adc(register16_t value) noexcept; void add(register16_t value, int carry = 0) noexcept; - void add(uint8_t value, int carry = 0) noexcept { + void add(uint8_t value, int carry = 0) noexcept; + void adc(uint8_t value) noexcept; + void sub(uint8_t value, int carry = 0) noexcept; + uint8_t subtract(uint8_t value, int carry = 0) noexcept; + void sbc(uint8_t value) noexcept; - const auto operand = A(); + void andr(uint8_t value) noexcept; + void xorr(uint8_t value) noexcept; + void orr(uint8_t value) noexcept; + void compare(uint8_t value) noexcept; - intermediate() = operand + value + carry; - const auto result = intermediate().low; + [[nodiscard]] uint8_t rlc(uint8_t operand) noexcept; + [[nodiscard]] uint8_t rrc(uint8_t operand) noexcept; + [[nodiscard]] uint8_t rl(uint8_t operand) noexcept; + [[nodiscard]] uint8_t rr(uint8_t operand) noexcept; + [[nodiscard]] uint8_t sla(uint8_t operand) noexcept; + [[nodiscard]] uint8_t sra(uint8_t operand) noexcept; + [[nodiscard]] uint8_t sll(uint8_t operand) noexcept; + [[nodiscard]] uint8_t srl(uint8_t operand) noexcept; - adjustHalfCarryAdd(operand, value, result); - adjustOverflowAdd(operand, value, result); - - clearBit(NF); - setBit(CF, carryTest(intermediate().high)); - adjustSZXY(result); - - A() = result; - } - - void adc(uint8_t value) noexcept { - add(value, carry()); - } - - void sub(uint8_t value, int carry = 0) noexcept { - adjustSZXY(A() = subtract(value, carry)); - } - - void sbc(uint8_t value) noexcept { - sub(value, carry()); - } - - [[nodiscard]] void andr(uint8_t value) noexcept { - setBit(HC); - clearBit(CF | NF); - adjustSZPXY(A() &= value); - } - - [[nodiscard]] void xorr(uint8_t value) noexcept { - clearBit(HC | CF | NF); - adjustSZPXY(A() ^= value); - } - - [[nodiscard]] void orr(uint8_t value) noexcept { - clearBit(HC | CF | NF); - adjustSZPXY(A() |= value); - } - - void compare(uint8_t value) noexcept { - subtract(value); - adjustXY(value); - } - - [[nodiscard]] auto rlc(uint8_t operand) noexcept { - clearBit(NF | HC); - const auto carry = operand & Bit7; - setBit(CF, carry); - const uint8_t result = (operand << 1) | (carry >> 7); - adjustXY(result); - return result; - } - - [[nodiscard]] auto rrc(uint8_t operand) noexcept { - clearBit(NF | HC); - const auto carry = operand & Bit0; - setBit(CF, carry); - const uint8_t result = (operand >> 1) | (carry << 7); - adjustXY(result); - return result; - } - - [[nodiscard]] auto rl(uint8_t operand) noexcept { - clearBit(NF | HC); - const auto carrying = carry(); - setBit(CF, operand & Bit7); - const uint8_t result = (operand << 1) | carrying; - adjustXY(result); - return result; - } - - [[nodiscard]] auto rr(uint8_t operand) noexcept { - clearBit(NF | HC); - const auto carrying = carry(); - setBit(CF, operand & Bit0); - const uint8_t result = (operand >> 1) | (carrying << 7); - adjustXY(result); - return result; - } - - [[nodiscard]] auto sla(uint8_t operand) noexcept { - clearBit(NF | HC); - setBit(CF, operand & Bit7); - const uint8_t result = operand << 1; - adjustXY(result); - return result; - } - - [[nodiscard]] auto sra(uint8_t operand) noexcept { - clearBit(NF | HC); - setBit(CF, operand & Bit0); - const uint8_t result = (operand >> 1) | (operand & Bit7); - adjustXY(result); - return result; - } - - [[nodiscard]] auto sll(uint8_t operand) noexcept { - clearBit(NF | HC); - setBit(CF, operand & Bit7); - const uint8_t result = (operand << 1) | Bit0; - adjustXY(result); - return result; - } - - [[nodiscard]] auto srl(uint8_t operand) noexcept { - clearBit(NF | HC); - setBit(CF, operand & Bit0); - const uint8_t result = (operand >> 1) & ~Bit7; - adjustXY(result); - setBit(ZF, result); - return result; - } - - void bit(int n, uint8_t operand) noexcept { - setBit(HC); - clearBit(NF); - const auto discarded = operand & Chip::bit(n); - adjustSZ(discarded); - clearBit(PF, discarded); - } + void bit(int n, uint8_t operand) noexcept; [[nodiscard]] static constexpr auto res(int n, uint8_t operand) noexcept { return Chip::clearBit(operand, Chip::bit(n)); } [[nodiscard]] static constexpr auto set(int n, uint8_t operand) noexcept { return Chip::setBit(operand, Chip::bit(n)); } - [[nodiscard]] void daa() noexcept { - - auto updated = A(); - - const auto lowAdjust = halfCarry() || (lowNibble(A()) > 9); - const auto highAdjust = carry() || (A() > 0x99); - - if (subtracting()) { - if (lowAdjust) - updated -= 6; - if (highAdjust) - updated -= 0x60; - } else { - if (lowAdjust) - updated += 6; - if (highAdjust) - updated += 0x60; - } - - adjustStatusFlags((F() & (CF | NF) | (A() > 0x99 ? CF : 0) | halfCarryTest(A() ^ updated))); - adjustSZPXY(A() = updated); - } - - void scf() noexcept { - setBit(CF); - clearBit(HC | NF); - adjustXY((Q() ^ F()) | A()); - } - - void ccf() noexcept { - clearBit(NF); - const auto carrying = carry(); - setBit(HC, carrying); - clearBit(CF, carrying); - adjustXY(((Q() ^ F()) | A())); - } - - void cpl() noexcept final { - setBit(HC | NF); - IntelProcessor::cpl(); - adjustXY(A()); - } + void daa() noexcept; + void scf() noexcept; + void ccf() noexcept; + void cpl() noexcept final; void xhtl(register16_t& exchange) noexcept; @@ -605,7 +386,7 @@ namespace EightBit { void lddr() noexcept; void repeatBlockInstruction() noexcept; - void adjustBlockRepeatFlagsIO(); + void adjustBlockRepeatFlagsIO() noexcept; void adjustBlockInputOutputFlags(int basis) noexcept; void adjustBlockInFlagsIncrement() noexcept; void adjustBlockInFlagsDecrement() noexcept; @@ -627,21 +408,7 @@ namespace EightBit { void outd() noexcept; void otdr() noexcept; - void neg() noexcept { - - setBit(PF, A() == Bit7); - setBit(CF, A()); - setBit(NF); - - auto original = A(); - - A() = (~A() + 1); // two's complement - - adjustHalfCarrySub(0U, original, A()); - adjustOverflowSub(0U, original, A()); - - adjustSZXY(A()); - } + void neg() noexcept; void rrd(register16_t address, uint8_t& update) noexcept; void rld(register16_t address, uint8_t& update) noexcept; diff --git a/Z80/src/Disassembler.cpp b/Z80/src/Disassembler.cpp index 5e35419..1ca2487 100644 --- a/Z80/src/Disassembler.cpp +++ b/Z80/src/Disassembler.cpp @@ -8,7 +8,7 @@ #include "../inc/Z80.h" -EightBit::Disassembler::Disassembler(Bus& bus) noexcept +EightBit::Disassembler::Disassembler(Bus& bus) : m_bus(bus) { // Disable exceptions where too many format arguments are available m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 3cbc60f..07eb183 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -3,7 +3,7 @@ // based on http://www.z80.info/decoding.htm -EightBit::Z80::Z80(Bus& bus, InputOutput& ports) +EightBit::Z80::Z80(Bus& bus, InputOutput& ports) noexcept : IntelProcessor(bus), m_ports(ports) { RaisedPOWER.connect([this](EventArgs) { @@ -45,24 +45,19 @@ EightBit::Z80::Z80(Bus& bus, InputOutput& ports) }); } -EightBit::Z80::Z80(const Z80& rhs) +EightBit::Z80::Z80(const Z80& rhs) noexcept : IntelProcessor(rhs), - m_ports(rhs.m_ports) { - - m_registers = rhs.m_registers; - m_registerSet = rhs.m_registerSet; - - m_accumulatorFlags = rhs.m_accumulatorFlags; - m_accumulatorFlagsSet = rhs.m_accumulatorFlagsSet; - - m_ix = rhs.m_ix; - m_iy = rhs.m_iy; - - iv = rhs.iv; - m_interruptMode = rhs.m_interruptMode; - m_iff1 = rhs.m_iff1; - m_iff2 = rhs.m_iff2; - + m_ports(rhs.m_ports), + m_registers(rhs.m_registers), + m_registerSet(rhs.m_registerSet), + m_accumulatorFlags(rhs.m_accumulatorFlags), + m_accumulatorFlagsSet(rhs.m_accumulatorFlagsSet), + m_ix(rhs.m_ix), + m_iy(rhs.m_iy), + iv(rhs.iv), + m_interruptMode(rhs.m_interruptMode), + m_iff1(rhs.m_iff1), + m_iff2(rhs.m_iff2) { RFSH() = rhs.RFSH(); NMI() = rhs.NMI(); M1() = rhs.M1(); @@ -72,47 +67,47 @@ EightBit::Z80::Z80(const Z80& rhs) WR() = rhs.WR(); } -bool EightBit::Z80::operator==(const EightBit::Z80& rhs) const { +bool EightBit::Z80::operator==(const EightBit::Z80& rhs) const noexcept { const auto base = IntelProcessor::operator==(rhs); + auto& left = const_cast(*this); + auto& right = const_cast(rhs); + const auto pins = - RFSH() == rhs.RFSH() - && NMI() == rhs.NMI() - && M1() == rhs.M1() - && MREQ() == rhs.MREQ() - && IORQ() == rhs.IORQ() - && RD() == rhs.RD() - && WR() == rhs.WR(); + left.RFSH() == right.RFSH() + && left.NMI() == right.NMI() + && left.M1() == right.M1() + && left.MREQ() == right.MREQ() + && left.IORQ() == right.IORQ() + && left.RD() == right.RD() + && left.WR() == right.WR(); - auto* z80 = const_cast(this); - auto& z80_rhs = const_cast(rhs); + left.exxAF(); + right.exxAF(); + const auto af = left.AF() == right.AF(); + left.exxAF(); + right.exxAF(); - z80->exxAF(); - z80_rhs.exxAF(); - const auto af = AF() == rhs.AF(); - z80->exxAF(); - z80_rhs.exxAF(); - - z80->exx(); - z80_rhs.exx(); + left.exx(); + right.exx(); const auto pairs = - BC() == rhs.BC() - && DE() == rhs.DE() - && HL() == rhs.HL(); - z80->exx(); - z80_rhs.exx(); + left.BC() == right.BC() + && left.DE() == right.DE() + && left.HL() == right.HL(); + left.exx(); + right.exx(); const auto indices = - IX() == rhs.IX() - && IY() == rhs.IY(); + left.IX() == right.IX() + && left.IY() == right.IY(); const auto miscellaneous = - REFRESH() == rhs.REFRESH() - && IV() == rhs.IV() - && IM() == rhs.IM() - && IFF1() == rhs.IFF1() - && IFF2() == rhs.IFF2(); + left.REFRESH() == right.REFRESH() + && left.IV() == right.IV() + && left.IM() == right.IM() + && left.IFF1() == right.IFF1() + && left.IFF2() == right.IFF2(); return base && pins && af && pairs && indices && miscellaneous; } @@ -125,19 +120,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80); DEFINE_PIN_LEVEL_CHANGERS(RD, Z80); DEFINE_PIN_LEVEL_CHANGERS(WR, Z80); -const EightBit::register16_t& EightBit::Z80::AF() const noexcept { +EightBit::register16_t& EightBit::Z80::AF() noexcept { return m_accumulatorFlags[m_accumulatorFlagsSet]; } -const EightBit::register16_t& EightBit::Z80::BC() const noexcept { +EightBit::register16_t& EightBit::Z80::BC() noexcept { return m_registers[m_registerSet][BC_IDX]; } -const EightBit::register16_t& EightBit::Z80::DE() const noexcept { +EightBit::register16_t& EightBit::Z80::DE() noexcept { return m_registers[m_registerSet][DE_IDX]; } -const EightBit::register16_t& EightBit::Z80::HL() const noexcept { +EightBit::register16_t& EightBit::Z80::HL() noexcept { return m_registers[m_registerSet][HL_IDX]; } @@ -156,11 +151,11 @@ void EightBit::Z80::memoryUpdate(int ticks) noexcept { } void EightBit::Z80::memoryWrite() noexcept { - memoryUpdate(1); + memoryUpdate(); } void EightBit::Z80::refreshMemory() noexcept { - assert(lowered(M1()) && "M1 must be lowered to refresh memory"); + assert(fetchingOpCode() && "M1 must be lowered to refresh memory"); BUS().ADDRESS() = { REFRESH(), IV() }; lowerRFSH(); tick(); @@ -175,14 +170,14 @@ uint8_t EightBit::Z80::memoryRead() noexcept { lowerMREQ(); lowerRD(); tick(); - const auto data = IntelProcessor::memoryRead(); + IntelProcessor::memoryRead(); raiseRD(); raiseMREQ(); - if (lowered(M1())) + if (fetchingOpCode()) refreshMemory(); tick(); ReadMemory.fire(); - return data; + return BUS().DATA(); } void EightBit::Z80::handleRESET() noexcept { @@ -204,9 +199,9 @@ void EightBit::Z80::handleNMI() noexcept { restart(0x66); } -uint8_t EightBit::Z80::readDataUnderInterrupt() { +uint8_t EightBit::Z80::readDataUnderInterrupt() noexcept { lowerM1(); - tick(3); + tick(2); lowerIORQ(); tick(); const auto data = BUS().DATA(); @@ -215,6 +210,7 @@ uint8_t EightBit::Z80::readDataUnderInterrupt() { refreshMemory(); assert(cycles() == 5); raiseM1(); + tick(); return data; } @@ -222,8 +218,9 @@ void EightBit::Z80::handleINT() noexcept { IntelProcessor::handleINT(); - const auto data = readDataUnderInterrupt(); tick(); + + const auto data = readDataUnderInterrupt(); assert(cycles() == 6); switch (IM()) { @@ -235,24 +232,46 @@ void EightBit::Z80::handleINT() noexcept { assert(cycles() == 13); break; case 2: - tick(); MEMPTR() = Processor::getWordPaged(IV(), data); call(MEMPTR()); - assert(cycles() == 13); + assert(cycles() == 19); break; default: UNREACHABLE; } } -void EightBit::Z80::disableInterrupts() { +void EightBit::Z80::disableInterrupts() noexcept { IFF1() = IFF2() = false; } -void EightBit::Z80::enableInterrupts() { +void EightBit::Z80::enableInterrupts() noexcept { IFF1() = IFF2() = true; } +bool EightBit::Z80::convertCondition(int flag) noexcept { + switch (flag) { + case 0: + return zero() == 0; + case 1: + return zero() != 0; + case 2: + return carry() == 0; + case 3: + return carry() != 0; + case 4: + return parity() == 0; + case 5: + return parity() != 0; + case 6: + return sign() == 0; + case 7: + return sign() != 0; + default: + UNREACHABLE; + } +} + void EightBit::Z80::returnConditionalFlag(const int flag) noexcept { const auto condition = convertCondition(flag); tick(); @@ -269,8 +288,7 @@ void EightBit::Z80::reti() noexcept { retn(); } - -void EightBit::Z80::call(register16_t destination) { +void EightBit::Z80::call(register16_t destination) noexcept { tick(); Processor::call(destination); } @@ -280,6 +298,70 @@ void EightBit::Z80::jumpRelative(int8_t offset) noexcept { tick(5); } +uint8_t EightBit::Z80::increment(uint8_t operand) noexcept { + clearBit(NF); + const uint8_t result = operand + 1; + adjustSZXY(result); + setBit(VF, result == Bit7); + clearBit(HC, lowNibble(result)); + return result; +} + +uint8_t EightBit::Z80::decrement(uint8_t operand) noexcept { + setBit(NF); + clearBit(HC, lowNibble(operand)); + const uint8_t result = operand - 1; + adjustSZXY(result); + setBit(VF, result == Mask7); + return result; +} + +void EightBit::Z80::add(uint8_t value, int carry) noexcept { + + const auto operand = A(); + + intermediate() = operand + value + carry; + const auto result = intermediate().low; + + adjustHalfCarryAdd(operand, value, result); + adjustOverflowAdd(operand, value, result); + + clearBit(NF); + setBit(CF, carryTest(intermediate().high)); + adjustSZXY(result); + + A() = result; +} + +void EightBit::Z80::adc(uint8_t value) noexcept { + add(value, carry()); +} + +void EightBit::Z80::sub(uint8_t value, int carry) noexcept { + adjustSZXY(A() = subtract(value, carry)); +} + +void EightBit::Z80::sbc(uint8_t value) noexcept { + sub(value, carry()); +} + +uint8_t EightBit::Z80::subtract(uint8_t value, int carry) noexcept { + + const auto operand = A(); + + const register16_t subtraction = operand - value - carry; + const auto result = subtraction.low; + + adjustHalfCarrySub(operand, value, result); + adjustOverflowSub(operand, value, result); + + setBit(NF); + setBit(CF, carryTest(subtraction.high)); + adjustSZ(result); + + return result; +} + void EightBit::Z80::sbc(const register16_t value) noexcept { const auto operand = HL2(); @@ -303,6 +385,7 @@ void EightBit::Z80::sbc(const register16_t value) noexcept { MEMPTR() = operand + 1; HL2() = intermediate(); + tick(7); } void EightBit::Z80::adc(const register16_t value) noexcept { @@ -324,7 +407,7 @@ void EightBit::Z80::add(const register16_t value, int carry) noexcept { const auto operand = HL2(); const auto addition = operand.word + value.word + carry; - intermediate().word = addition; + intermediate() = addition; clearBit(NF); setBit(CF, addition & Bit16); @@ -334,6 +417,7 @@ void EightBit::Z80::add(const register16_t value, int carry) noexcept { MEMPTR() = operand + 1; HL2() = intermediate(); + tick(7); } void EightBit::Z80::xhtl(register16_t& exchange) noexcept { @@ -346,19 +430,177 @@ void EightBit::Z80::xhtl(register16_t& exchange) noexcept { --BUS().ADDRESS(); BUS().DATA() = exchange.low; exchange.low = MEMPTR().low; - memoryUpdate(1); + memoryUpdate(); tick(2); } +void EightBit::Z80::andr(uint8_t value) noexcept { + setBit(HC); + clearBit(CF | NF); + adjustSZPXY(A() &= value); +} + +void EightBit::Z80::xorr(uint8_t value) noexcept { + clearBit(HC | CF | NF); + adjustSZPXY(A() ^= value); +} + +void EightBit::Z80::orr(uint8_t value) noexcept { + clearBit(HC | CF | NF); + adjustSZPXY(A() |= value); +} + +void EightBit::Z80::compare(uint8_t value) noexcept { + subtract(value); + adjustXY(value); +} + +uint8_t EightBit::Z80::rlc(uint8_t operand) noexcept { + clearBit(NF | HC); + const auto carry = operand & Bit7; + setBit(CF, carry); + const uint8_t result = (operand << 1) | (carry >> 7); + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::rrc(uint8_t operand) noexcept { + clearBit(NF | HC); + const auto carry = operand & Bit0; + setBit(CF, carry); + const uint8_t result = (operand >> 1) | (carry << 7); + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::rl(uint8_t operand) noexcept { + clearBit(NF | HC); + const auto carrying = carry(); + setBit(CF, operand & Bit7); + const uint8_t result = (operand << 1) | carrying; + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::rr(uint8_t operand) noexcept { + clearBit(NF | HC); + const auto carrying = carry(); + setBit(CF, operand & Bit0); + const uint8_t result = (operand >> 1) | (carrying << 7); + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::sla(uint8_t operand) noexcept { + clearBit(NF | HC); + setBit(CF, operand & Bit7); + const uint8_t result = operand << 1; + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::sra(uint8_t operand) noexcept { + clearBit(NF | HC); + setBit(CF, operand & Bit0); + const uint8_t result = (operand >> 1) | (operand & Bit7); + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::sll(uint8_t operand) noexcept { + clearBit(NF | HC); + setBit(CF, operand & Bit7); + const uint8_t result = (operand << 1) | Bit0; + adjustXY(result); + return result; +} + +uint8_t EightBit::Z80::srl(uint8_t operand) noexcept { + clearBit(NF | HC); + setBit(CF, operand & Bit0); + const uint8_t result = (operand >> 1) & ~Bit7; + adjustXY(result); + setBit(ZF, result); + return result; +} + +void EightBit::Z80::bit(int n, uint8_t operand) noexcept { + setBit(HC); + clearBit(NF); + const auto discarded = operand & Chip::bit(n); + adjustSZ(discarded); + clearBit(PF, discarded); +} + +void EightBit::Z80::daa() noexcept { + + auto updated = A(); + + const auto lowAdjust = halfCarry() || (lowNibble(A()) > 9); + const auto highAdjust = carry() || (A() > 0x99); + + if (subtracting()) { + if (lowAdjust) + updated -= 6; + if (highAdjust) + updated -= 0x60; + } else { + if (lowAdjust) + updated += 6; + if (highAdjust) + updated += 0x60; + } + + adjustStatusFlags((F() & (CF | NF) | (A() > 0x99 ? CF : 0) | halfCarryTest(A() ^ updated))); + adjustSZPXY(A() = updated); +} + +void EightBit::Z80::scf() noexcept { + setBit(CF); + clearBit(HC | NF); + adjustXY((Q() ^ F()) | A()); +} + +void EightBit::Z80::ccf() noexcept { + clearBit(NF); + const auto carrying = carry(); + setBit(HC, carrying); + clearBit(CF, carrying); + adjustXY(((Q() ^ F()) | A())); +} + +void EightBit::Z80::cpl() noexcept { + setBit(HC | NF); + IntelProcessor::cpl(); + adjustXY(A()); +} + +void EightBit::Z80::neg() noexcept { + + setBit(PF, A() == Bit7); + setBit(CF, A()); + setBit(NF); + + auto original = A(); + + A() = (~A() + 1); // two's complement + + adjustHalfCarrySub(0U, original, A()); + adjustOverflowSub(0U, original, A()); + + adjustSZXY(A()); +} + + void EightBit::Z80::blockCompare() noexcept { - const auto data = IntelProcessor::memoryRead(HL()); - uint8_t result = A() - data; + IntelProcessor::memoryRead(HL()); + uint8_t result = A() - BUS().DATA(); setBit(PF, --BC().word); adjustSZ(result); - adjustHalfCarrySub(A(), data, result); + adjustHalfCarrySub(A(), BUS().DATA(), result); setBit(NF); result -= (halfCarry() >> 4); @@ -395,15 +637,15 @@ void EightBit::Z80::cpdr() noexcept { repeatBlockInstruction(); tick(5); } else { - MEMPTR().word = PC().word - 2; + MEMPTR() = PC().word - 2; tick(2); } } void EightBit::Z80::blockLoad() noexcept { - const auto data = IntelProcessor::memoryRead(HL()); + IntelProcessor::memoryRead(HL()); IntelProcessor::memoryWrite(DE()); - const auto xy = A() + data; + const auto xy = A() + BUS().DATA(); setBit(XF, xy & Bit3); setBit(YF, xy & Bit1); clearBit(NF | HC); @@ -443,7 +685,7 @@ void EightBit::Z80::repeatBlockInstruction() noexcept { adjustXY(PC().high); } -void EightBit::Z80::adjustBlockRepeatFlagsIO() { +void EightBit::Z80::adjustBlockRepeatFlagsIO() noexcept { if (carry() != 0) { const auto negative = signTest(BUS().DATA()) != 0; const uint8_t direction = B() + (negative ? -1 : +1); @@ -461,11 +703,11 @@ void EightBit::Z80::adjustBlockInputOutputFlags(int basis) noexcept { } void EightBit::Z80::adjustBlockInFlagsIncrement() noexcept { - adjustBlockInputOutputFlags((C() + 1) + BUS().DATA()); + adjustBlockInputOutputFlags((uint8_t)(C() + 1) + BUS().DATA()); } void EightBit::Z80::adjustBlockInFlagsDecrement() noexcept { - adjustBlockInputOutputFlags((C() - 1) + BUS().DATA()); + adjustBlockInputOutputFlags((uint8_t)(C() - 1) + BUS().DATA()); } void EightBit::Z80::adjustBlockOutFlags() noexcept { @@ -478,7 +720,7 @@ void EightBit::Z80::blockIn() noexcept { tick(); readPort(BC()); BUS().ADDRESS() = HL(); - memoryUpdate(1); + memoryUpdate(); adjustSZXY(--B()); setBit(NF, BUS().DATA() & SF); } @@ -555,7 +797,8 @@ void EightBit::Z80::otdr() noexcept { } void EightBit::Z80::rrd(register16_t address, uint8_t& update) noexcept { - (MEMPTR() = BUS().ADDRESS() = address)++; + MEMPTR() = BUS().ADDRESS() = address; + ++MEMPTR(); const auto memory = memoryRead(); tick(4); IntelProcessor::memoryWrite(promoteNibble(update) | highNibble(memory)); @@ -565,7 +808,8 @@ void EightBit::Z80::rrd(register16_t address, uint8_t& update) noexcept { } void EightBit::Z80::rld(register16_t address, uint8_t& update) noexcept { - (MEMPTR() = BUS().ADDRESS() = address)++; + MEMPTR() = BUS().ADDRESS() = address; + ++MEMPTR(); const auto memory = memoryRead(); tick(4); IntelProcessor::memoryWrite(promoteNibble(memory) | lowNibble(update)); @@ -663,12 +907,14 @@ uint8_t EightBit::Z80::fetchInstruction() noexcept { } void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept { - (MEMPTR() = BUS().ADDRESS() = addresser())++; + MEMPTR() = BUS().ADDRESS() = addresser(); + ++MEMPTR(); A() = memoryRead(); } void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept { - (MEMPTR() = BUS().ADDRESS() = addresser())++; + MEMPTR() = BUS().ADDRESS() = addresser(); + ++MEMPTR(); MEMPTR().high = BUS().DATA() = A(); memoryWrite(); } @@ -677,12 +923,13 @@ void EightBit::Z80::readInternalRegister(reader_t reader) noexcept { adjustSZXY(A() = reader()); clearBit(NF | HC); setBit(PF, IFF2()); + tick(); } EightBit::register16_t& EightBit::Z80::HL2() noexcept { - if (UNLIKELY(m_prefixDD)) + if (m_prefixDD) return IX(); - if (UNLIKELY(m_prefixFD)) + if (m_prefixFD) return IY(); return HL(); } @@ -755,7 +1002,6 @@ uint8_t& EightBit::Z80::R(const int r, MemoryMapping::AccessLevel access) noexce } void EightBit::Z80::R(const int r, const uint8_t value, const int ticks) noexcept { - R(r, MemoryMapping::AccessLevel::WriteOnly) = value; if (r == 6) memoryUpdate(ticks); @@ -944,7 +1190,6 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p default: UNREACHABLE; } - tick(7); break; case 3: // Retrieve/store register pair from/to immediate address BUS().ADDRESS() = fetchWord(); @@ -1004,11 +1249,9 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p break; case 2: // LD A,I readInternalRegister([this]() { return IV(); }); - tick(); break; case 3: // LD A,R readInternalRegister([this]() { return REFRESH(); }); - tick(); break; case 4: // RRD rrd(HL(), A()); @@ -1135,7 +1378,6 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in break; case 1: // ADD HL,rp add(RP(p)); - tick(7); break; default: UNREACHABLE; diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index 6caa002..3fa31f8 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -17,7 +17,7 @@ void Board::lowerPOWER() noexcept { EightBit::Bus::lowerPOWER(); } -void Board::initialise() { +void Board::initialise() noexcept { auto romDirectory = m_configuration.getRomDirectory(); m_ram.load(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew diff --git a/Z80/test/Board.h b/Z80/test/Board.h index c9318ab..22c71c9 100644 --- a/Z80/test/Board.h +++ b/Z80/test/Board.h @@ -16,12 +16,12 @@ class Board : public EightBit::Bus { public: Board(const Configuration& configuration); - EightBit::Z80& CPU() noexcept { return m_cpu; } + EightBit::Z80& CPU() { return m_cpu; } void raisePOWER() noexcept final; void lowerPOWER() noexcept final; - void initialise() final; + void initialise() noexcept final; protected: EightBit::MemoryMapping mapping(uint16_t address) noexcept final { diff --git a/inc/BigEndianProcessor.h b/inc/BigEndianProcessor.h index ddb917c..dc37ce9 100644 --- a/inc/BigEndianProcessor.h +++ b/inc/BigEndianProcessor.h @@ -8,7 +8,8 @@ namespace EightBit { class BigEndianProcessor : public Processor { public: - virtual ~BigEndianProcessor() noexcept {}; + virtual ~BigEndianProcessor() noexcept = default; + BigEndianProcessor(const BigEndianProcessor& rhs) noexcept; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final; void pokeWord(register16_t address, register16_t value) noexcept final; @@ -16,15 +17,15 @@ namespace EightBit { protected: BigEndianProcessor(Bus& memory) noexcept; - [[nodiscard]] register16_t getWord() override; - void setWord(register16_t value) override; + [[nodiscard]] register16_t getWord() noexcept override; + void setWord(register16_t value) noexcept override; - [[nodiscard]] register16_t getWordPaged() override; - void setWordPaged(register16_t value) override; + [[nodiscard]] register16_t getWordPaged() noexcept override; + void setWordPaged(register16_t value) noexcept override; - [[nodiscard]] register16_t fetchWord() final; + [[nodiscard]] register16_t fetchWord() noexcept override; - void pushWord(register16_t value) final; - [[nodiscard]] register16_t popWord() final; + void pushWord(register16_t value) noexcept override; + [[nodiscard]] register16_t popWord() noexcept override; }; } diff --git a/inc/Bus.h b/inc/Bus.h index 325d1bc..ae3a3c2 100644 --- a/inc/Bus.h +++ b/inc/Bus.h @@ -26,20 +26,20 @@ namespace EightBit { [[nodiscard]] constexpr auto DATA() const noexcept { return m_data; } [[nodiscard]] constexpr auto& DATA() noexcept { return m_data; } - [[nodiscard]] virtual uint8_t peek(const uint16_t address) noexcept { return reference(address); } + [[nodiscard]] uint8_t peek(const uint16_t address) noexcept { return reference(address); } [[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); } void poke(const uint8_t value) noexcept { reference() = value; } - virtual void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; } + void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; } void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); } - [[nodiscard]] uint8_t read(); - void write(); + [[nodiscard]] uint8_t read() noexcept; + void write() noexcept; virtual void raisePOWER() noexcept; virtual void lowerPOWER() noexcept; - virtual void initialise() = 0; + virtual void initialise() noexcept = 0; protected: [[nodiscard]] uint8_t& reference(uint16_t address) noexcept; diff --git a/inc/ClockedChip.h b/inc/ClockedChip.h index f28e38d..8cb8f81 100644 --- a/inc/ClockedChip.h +++ b/inc/ClockedChip.h @@ -14,12 +14,12 @@ namespace EightBit { [[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; } - void tick() { + void tick() noexcept { ++m_cycles; Ticked.fire(); } - void tick(int extra) { + void tick(int extra) noexcept { for (int i = 0; i < extra; ++i) tick(); } diff --git a/inc/Device.h b/inc/Device.h index 62ec1a5..65236a9 100644 --- a/inc/Device.h +++ b/inc/Device.h @@ -10,17 +10,17 @@ Signal Lowered ## name; #define DECLARE_PIN_LEVEL_RAISE(name) \ - virtual void raise ## name(); + virtual void raise ## name() noexcept; #define DECLARE_PIN_LEVEL_LOWER(name) \ - virtual void lower ## name(); + virtual void lower ## name() noexcept; #define DECLARE_PIN_LEVEL_CHANGERS(name) \ DECLARE_PIN_LEVEL_RAISE(name) \ DECLARE_PIN_LEVEL_LOWER(name) #define DEFINE_PIN_LEVEL_RAISE(name, within) \ - void EightBit:: within ::raise ## name() { \ + void EightBit:: within ::raise ## name() noexcept { \ if (lowered( name ())) { \ Raising ## name.fire(); \ raise( name ()); \ @@ -29,7 +29,7 @@ } #define DEFINE_PIN_LEVEL_LOWER(name, within) \ - void EightBit:: within ::lower ## name() { \ + void EightBit:: within ::lower ## name() noexcept { \ if (raised( name ())) { \ Lowering ## name.fire(); \ lower( name ()); \ @@ -44,25 +44,6 @@ #define DECLARE_PIN_MEMBER(name) \ PinLevel m_## name ## _Line = PinLevel::Low; -#define DEFINE_PIN_ACTIVATOR(name, on, off) \ - template class _Activate ## name final { \ - T& m_parent; \ - public: \ - _Activate ## name(T& parent) noexcept \ - : m_parent(parent) { \ - m_parent. on ## name(); \ - } \ - ~_Activate ## name() noexcept { \ - m_parent. off ## name(); \ - } \ - }; - -#define DEFINE_PIN_ACTIVATOR_LOW(name) \ - DEFINE_PIN_ACTIVATOR(name, lower, raise) - -#define DEFINE_PIN_ACTIVATOR_HIGH(name) \ - DEFINE_PIN_ACTIVATOR(name, raise, lower) - #define DECLARE_PIN(name, visibility) \ public: \ DECLARE_PIN_SIGNALS(name) \ @@ -114,6 +95,6 @@ namespace EightBit { [[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); } protected: - Device() noexcept {}; + Device() noexcept = default; }; } diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index 80b903a..d66c921 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -9,16 +9,6 @@ #include "Signal.h" #include "EightBitCompilerDefinitions.h" -#define NON_CONST_ACCESSOR(accessor, type) \ - [[nodiscard]] constexpr auto& accessor() noexcept { \ - const auto& consted = *this; \ - const auto& reference = consted.accessor(); \ - return const_cast(reference); \ - } - -#define NON_CONST_REGISTOR_ACCESSOR(accessor) \ - NON_CONST_ACCESSOR(accessor, register16_t) - namespace EightBit { class Bus; @@ -52,35 +42,32 @@ namespace EightBit { } [[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; } - [[nodiscard]] constexpr auto MEMPTR() const noexcept { return m_memptr; } - [[nodiscard]] constexpr auto& SP() noexcept { return m_sp; } - [[nodiscard]] register16_t SP() const noexcept { return m_sp; } - [[nodiscard]] virtual const register16_t& AF() const noexcept = 0; - NON_CONST_REGISTOR_ACCESSOR(AF); + [[nodiscard]] virtual register16_t& AF() noexcept = 0; [[nodiscard]] auto& A() noexcept { return AF().high; } [[nodiscard]] auto& F() noexcept { return AF().low; } - [[nodiscard]] virtual const register16_t& BC() const noexcept = 0; - NON_CONST_REGISTOR_ACCESSOR(BC); + [[nodiscard]] virtual register16_t& BC() noexcept = 0; [[nodiscard]] auto& B() noexcept { return BC().high; } [[nodiscard]] auto& C() noexcept { return BC().low; } - [[nodiscard]] virtual const register16_t& DE() const noexcept = 0; - NON_CONST_REGISTOR_ACCESSOR(DE); + [[nodiscard]] virtual register16_t& DE() noexcept = 0; [[nodiscard]] auto& D() noexcept { return DE().high; } [[nodiscard]] auto& E() noexcept { return DE().low; } - [[nodiscard]] virtual const register16_t& HL() const noexcept = 0; - NON_CONST_REGISTOR_ACCESSOR(HL); + [[nodiscard]] virtual register16_t& HL() noexcept = 0; [[nodiscard]] auto& H() noexcept { return HL().high; } [[nodiscard]] auto& L() noexcept { return HL().low; } DECLARE_PIN_OUTPUT(HALT) + public: + [[nodiscard]] constexpr bool halted() const noexcept { return lowered(HALT()); } + [[nodiscard]] constexpr bool proceeding() const noexcept { return !halted(); } + protected: - IntelProcessor(Bus& bus); + IntelProcessor(Bus& bus) noexcept; template [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept { return setBit(f, T::SF, value & T::SF); @@ -138,65 +125,51 @@ namespace EightBit { return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation); } - virtual void disableInterrupts() = 0; + virtual void disableInterrupts() noexcept = 0; + virtual void enableInterrupts() noexcept = 0; - virtual void enableInterrupts() = 0; + void handleRESET() noexcept override; + void handleINT() noexcept override; - void handleRESET() override; - void handleINT() override; - - void push(uint8_t value) final; - [[nodiscard]] uint8_t pop() final; + void push(uint8_t value) noexcept final; + [[nodiscard]] uint8_t pop() noexcept final; // - register16_t& incrementPC() override; - uint8_t fetchInstruction() override; + register16_t& incrementPC() noexcept override; + uint8_t fetchInstruction() noexcept override; // - [[nodiscard]] register16_t getWord() final; - void setWord(register16_t value) final; + [[nodiscard]] register16_t getWord() noexcept final; + void setWord(register16_t value) noexcept final; // - void restart(uint8_t address); - void callConditional(bool condition); - virtual void jumpConditional(bool condition); - void jumpRelativeConditional(bool condition); - virtual void returnConditional(bool condition); - void jumpIndirect(); - void jump(); - void callIndirect(); - void call(); - virtual void call(register16_t destination); + void restart(uint8_t address) noexcept; + void callConditional(bool condition) noexcept; + virtual void jumpConditional(bool condition) noexcept; + void jumpRelativeConditional(bool condition) noexcept; + virtual void returnConditional(bool condition) noexcept; + void jumpIndirect() noexcept; + void jump() noexcept; + void callIndirect() noexcept; + void call() noexcept; + virtual void call(register16_t destination) noexcept; virtual void jumpRelative(int8_t offset) noexcept; - void jumpRelative(uint8_t offset) noexcept { jumpRelative((int8_t)offset); } - void ret() override; + void jumpRelative(uint8_t offset) noexcept { jumpRelative(static_cast(offset)); } + void ret() noexcept override; void resetWorkingRegisters() noexcept; [[nodiscard]] virtual bool convertCondition(int flag) noexcept = 0; - virtual void jumpConditionalFlag(int flag) { - jumpConditional(convertCondition(flag)); - } + virtual void jumpConditionalFlag(int flag) noexcept; + virtual void jumpRelativeConditionalFlag(int flag) noexcept; + virtual void returnConditionalFlag(int flag) noexcept; + virtual void callConditionalFlag(int flag) noexcept; - virtual void jumpRelativeConditionalFlag(int flag) { - jumpRelativeConditional(convertCondition(flag)); - } - - virtual void returnConditionalFlag(int flag) { - returnConditional(convertCondition(flag)); - } - - virtual void callConditionalFlag(int flag) { - callConditional(convertCondition(flag)); - } - - virtual void cpl() noexcept { - A() = ~A(); - } + virtual void cpl() noexcept; private: static std::array m_halfCarryTableAdd; diff --git a/inc/LittleEndianProcessor.h b/inc/LittleEndianProcessor.h index bc68936..190d6c4 100644 --- a/inc/LittleEndianProcessor.h +++ b/inc/LittleEndianProcessor.h @@ -8,6 +8,7 @@ namespace EightBit { class LittleEndianProcessor : public Processor { public: + virtual ~LittleEndianProcessor() noexcept = default; LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final; @@ -16,15 +17,15 @@ namespace EightBit { protected: LittleEndianProcessor(Bus& memory) noexcept; - [[nodiscard]] register16_t getWord() override; - void setWord(register16_t value) override; + [[nodiscard]] register16_t getWord() noexcept override; + void setWord(register16_t value) noexcept override; - [[nodiscard]] register16_t getWordPaged() override; - void setWordPaged(register16_t value) override; + [[nodiscard]] register16_t getWordPaged() noexcept override; + void setWordPaged(register16_t value) noexcept override; - [[nodiscard]] register16_t fetchWord() final; + [[nodiscard]] register16_t fetchWord() noexcept override; - void pushWord(register16_t value) override; - [[nodiscard]] register16_t popWord() override; + void pushWord(register16_t value) noexcept override; + [[nodiscard]] register16_t popWord() noexcept override; }; } diff --git a/inc/Processor.h b/inc/Processor.h index 43a484d..a245d0d 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -57,53 +57,53 @@ namespace EightBit { [[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; } [[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; } - virtual void handleRESET(); - virtual void handleINT(); + virtual void handleRESET() noexcept; + virtual void handleINT() noexcept; - void memoryWrite(register16_t address, uint8_t data); - void memoryWrite(register16_t address); - void memoryWrite(uint8_t data); - virtual void memoryWrite(); - virtual void busWrite(); + void memoryWrite(register16_t address, uint8_t data) noexcept; + void memoryWrite(register16_t address) noexcept; + void memoryWrite(uint8_t data) noexcept; + virtual void memoryWrite() noexcept; + virtual void busWrite() noexcept; - uint8_t memoryRead(register16_t address); - virtual uint8_t memoryRead(); - virtual uint8_t busRead(); + uint8_t memoryRead(register16_t address) noexcept; + virtual uint8_t memoryRead() noexcept; + virtual uint8_t busRead() noexcept; - virtual register16_t& incrementPC(); - virtual register16_t& decrementPC(); + virtual register16_t& incrementPC() noexcept; + virtual register16_t& decrementPC() noexcept; - virtual void immediateAddress(); + virtual void immediateAddress() noexcept; - uint8_t fetchByte(); - virtual uint8_t fetchInstruction(); + uint8_t fetchByte() noexcept; + virtual uint8_t fetchInstruction() noexcept; - [[nodiscard]] virtual register16_t getWord() = 0; - virtual void setWord(register16_t value) = 0; + [[nodiscard]] virtual register16_t getWord() noexcept = 0; + virtual void setWord(register16_t value) noexcept = 0; - [[nodiscard]] register16_t getWordPaged(register16_t address); - [[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset); - [[nodiscard]] virtual register16_t getWordPaged() = 0; - void setWordPaged(register16_t address, register16_t value); - void setWordPaged(uint8_t page, uint8_t offset, register16_t value); - virtual void setWordPaged(register16_t value) = 0; + [[nodiscard]] register16_t getWordPaged(register16_t address) noexcept; + [[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept; + [[nodiscard]] virtual register16_t getWordPaged() noexcept = 0; + void setWordPaged(register16_t address, register16_t value) noexcept; + void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept; + virtual void setWordPaged(register16_t value) noexcept = 0; - [[nodiscard]] virtual register16_t fetchWord() = 0; + [[nodiscard]] virtual register16_t fetchWord() noexcept = 0; - virtual void push(uint8_t value) = 0; - [[nodiscard]] virtual uint8_t pop() = 0; + virtual void push(uint8_t value) noexcept = 0; + [[nodiscard]] virtual uint8_t pop() noexcept = 0; - virtual void pushWord(register16_t value) = 0; - [[nodiscard]] virtual register16_t popWord() = 0; + virtual void pushWord(register16_t value) noexcept = 0; + [[nodiscard]] virtual register16_t popWord() noexcept = 0; - [[nodiscard]] register16_t getWord(register16_t address); - void setWord(register16_t address, register16_t value); + [[nodiscard]] register16_t getWord(register16_t address) noexcept; + void setWord(register16_t address, register16_t value) noexcept; void jump(const register16_t destination) noexcept; void jump(uint16_t destination) noexcept; - virtual void call(register16_t destination); - virtual void ret(); + virtual void call(register16_t destination) noexcept; + virtual void ret() noexcept; private: Bus& m_bus; diff --git a/inc/Ram.h b/inc/Ram.h index 2a09e1a..296e0ec 100644 --- a/inc/Ram.h +++ b/inc/Ram.h @@ -8,7 +8,7 @@ namespace EightBit { class Ram : public Rom { public: Ram(size_t size = 0) noexcept; - virtual ~Ram() = default; + virtual ~Ram() noexcept = default; [[nodiscard]] uint8_t& reference(uint16_t address) noexcept final; void poke(uint16_t address, uint8_t value) noexcept final; diff --git a/inc/Rom.h b/inc/Rom.h index 556e5b6..6ca9ce0 100644 --- a/inc/Rom.h +++ b/inc/Rom.h @@ -26,10 +26,10 @@ namespace EightBit { static int load(std::string path, std::vector& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); Rom(size_t size = 0) noexcept; - Rom(const Rom& rhs); - virtual ~Rom() = default; - Rom& operator=(const Rom& rhs); - bool operator==(const Rom& rhs) const; + Rom(const Rom& rhs) noexcept; + virtual ~Rom() noexcept = default; + Rom& operator=(const Rom& rhs) noexcept; + bool operator==(const Rom& rhs) const noexcept; [[nodiscard]] uint16_t size() const noexcept final; diff --git a/inc/Signal.h b/inc/Signal.h index 699ba58..68a3fbb 100644 --- a/inc/Signal.h +++ b/inc/Signal.h @@ -17,9 +17,11 @@ namespace EightBit { m_delegates.push_back(functor); } - void fire(T& e = EventArgs::empty()) const { - for (auto& delegate : m_delegates) - delegate(e); + void fire(T& e = EventArgs::empty()) const noexcept { + const auto firing = !m_delegates.empty(); + if (firing) + for (auto& delegate : m_delegates) + delegate(e); } }; } diff --git a/src/BigEndianProcessor.cpp b/src/BigEndianProcessor.cpp index fd93bfc..7c8145d 100644 --- a/src/BigEndianProcessor.cpp +++ b/src/BigEndianProcessor.cpp @@ -4,44 +4,47 @@ EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) noexcept : Processor(memory) {} -EightBit::register16_t EightBit::BigEndianProcessor::getWord() { +EightBit::BigEndianProcessor::BigEndianProcessor(const BigEndianProcessor& rhs) noexcept +: Processor(rhs) {} + +EightBit::register16_t EightBit::BigEndianProcessor::getWord() noexcept { const auto high = memoryRead(); ++BUS().ADDRESS(); const auto low = memoryRead(); return { low, high }; } -void EightBit::BigEndianProcessor::setWord(const register16_t value) { +void EightBit::BigEndianProcessor::setWord(const register16_t value) noexcept { memoryWrite(value.high); ++BUS().ADDRESS(); memoryWrite(value.low); } -EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() { +EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() noexcept { const auto high = memoryRead(); ++BUS().ADDRESS().low; const auto low = memoryRead(); return { low, high }; } -void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) { +void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) noexcept { memoryWrite(value.high); ++BUS().ADDRESS().low; memoryWrite(value.low); } -EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() { - const auto high = fetchByte(); - const auto low = fetchByte(); - return { low, high }; +EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept { + intermediate().high = fetchByte(); + intermediate().low = fetchByte(); + return intermediate(); } -void EightBit::BigEndianProcessor::pushWord(const register16_t value) { +void EightBit::BigEndianProcessor::pushWord(const register16_t value) noexcept { push(value.low); push(value.high); } -EightBit::register16_t EightBit::BigEndianProcessor::popWord() { +EightBit::register16_t EightBit::BigEndianProcessor::popWord() noexcept { const auto high = pop(); const auto low = pop(); return { low, high }; diff --git a/src/Bus.cpp b/src/Bus.cpp index fc08715..85342b7 100644 --- a/src/Bus.cpp +++ b/src/Bus.cpp @@ -8,14 +8,14 @@ void EightBit::Bus::raisePOWER() noexcept {} void EightBit::Bus::lowerPOWER() noexcept {} -uint8_t EightBit::Bus::read() { +uint8_t EightBit::Bus::read() noexcept { ReadingByte.fire(); const auto returned = DATA() = reference(); ReadByte.fire(); return returned; } -void EightBit::Bus::write() { +void EightBit::Bus::write() noexcept { WritingByte.fire(); reference() = DATA(); WrittenByte.fire(); diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp index d56909e..3a81eb5 100644 --- a/src/IntelProcessor.cpp +++ b/src/IntelProcessor.cpp @@ -4,7 +4,7 @@ std::array EightBit::IntelProcessor::m_halfCarryTableAdd = { { 0, 0, 1, 0, 1, 0, 1, 1 } }; std::array EightBit::IntelProcessor::m_halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } }; -EightBit::IntelProcessor::IntelProcessor(Bus& bus) +EightBit::IntelProcessor::IntelProcessor(Bus& bus) noexcept : LittleEndianProcessor(bus) { for (int i = 0; i < 0x100; ++i) m_decodedOpcodes.at(i) = i; @@ -17,11 +17,9 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus) } EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs) noexcept -: LittleEndianProcessor(rhs) { - - m_sp = rhs.m_sp; - m_memptr = rhs.m_memptr; - +: LittleEndianProcessor(rhs), + m_sp(rhs.m_sp), + m_memptr(rhs.m_memptr) { HALT() = rhs.HALT(); } @@ -31,73 +29,72 @@ void EightBit::IntelProcessor::resetWorkingRegisters() noexcept { DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor); -void EightBit::IntelProcessor::handleRESET() { +void EightBit::IntelProcessor::handleRESET() noexcept { Processor::handleRESET(); disableInterrupts(); Processor::jump(0); } -void EightBit::IntelProcessor::handleINT() { +void EightBit::IntelProcessor::handleINT() noexcept { Processor::handleINT(); - disableInterrupts(); raiseHALT(); + disableInterrupts(); } -void EightBit::IntelProcessor::push(const uint8_t value) { +void EightBit::IntelProcessor::push(const uint8_t value) noexcept { memoryWrite(--SP(), value); } -uint8_t EightBit::IntelProcessor::pop() { +uint8_t EightBit::IntelProcessor::pop() noexcept { return memoryRead(SP()++); } - -EightBit::register16_t& EightBit::IntelProcessor::incrementPC() { - if (raised(HALT())) +EightBit::register16_t& EightBit::IntelProcessor::incrementPC() noexcept { + if (proceeding()) Processor::incrementPC(); return PC(); } -uint8_t EightBit::IntelProcessor::fetchInstruction() { +uint8_t EightBit::IntelProcessor::fetchInstruction() noexcept { const auto data = fetchByte(); - return lowered(HALT()) ? (uint8_t)0 : data; + return proceeding() ? data : (uint8_t)0; } -EightBit::register16_t EightBit::IntelProcessor::getWord() { +EightBit::register16_t EightBit::IntelProcessor::getWord() noexcept { const auto returned = LittleEndianProcessor::getWord(); MEMPTR() = BUS().ADDRESS(); return returned; } -void EightBit::IntelProcessor::setWord(const register16_t value) { +void EightBit::IntelProcessor::setWord(const register16_t value) noexcept { LittleEndianProcessor::setWord(value); MEMPTR() = BUS().ADDRESS(); } -void EightBit::IntelProcessor::restart(const uint8_t address) { +void EightBit::IntelProcessor::restart(const uint8_t address) noexcept { MEMPTR() = { address, 0 }; call(); } -void EightBit::IntelProcessor::callConditional(bool condition) { +void EightBit::IntelProcessor::callConditional(bool condition) noexcept { MEMPTR() = fetchWord(); if (condition) call(); } -void EightBit::IntelProcessor::jumpConditional(bool condition) { +void EightBit::IntelProcessor::jumpConditional(bool condition) noexcept { MEMPTR() = fetchWord(); if (condition) jump(); } -void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) { +void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) noexcept { const auto offset = fetchByte(); if (condition) jumpRelative(offset); } -void EightBit::IntelProcessor::returnConditional(bool condition) { +void EightBit::IntelProcessor::returnConditional(bool condition) noexcept { if (condition) ret(); } @@ -107,42 +104,63 @@ void EightBit::IntelProcessor::jumpRelative(const int8_t offset) noexcept { jump(); } - -void EightBit::IntelProcessor::ret() { +void EightBit::IntelProcessor::ret() noexcept { LittleEndianProcessor::ret(); MEMPTR() = PC(); } -void EightBit::IntelProcessor::jumpIndirect() { +void EightBit::IntelProcessor::jumpIndirect() noexcept { MEMPTR() = fetchWord(); jump(); } -void EightBit::IntelProcessor::jump() { +void EightBit::IntelProcessor::jump() noexcept { Processor::jump(MEMPTR()); } -void EightBit::IntelProcessor::callIndirect() { +void EightBit::IntelProcessor::callIndirect() noexcept { MEMPTR() = fetchWord(); call(); } -void EightBit::IntelProcessor::call() { +void EightBit::IntelProcessor::call() noexcept { call(MEMPTR()); } -void EightBit::IntelProcessor::call(register16_t destination) { +void EightBit::IntelProcessor::call(register16_t destination) noexcept { Processor::call(destination); } +void EightBit::IntelProcessor::jumpConditionalFlag(int flag) noexcept { + jumpConditional(convertCondition(flag)); +} + +void EightBit::IntelProcessor::jumpRelativeConditionalFlag(int flag) noexcept { + jumpRelativeConditional(convertCondition(flag)); +} + +void EightBit::IntelProcessor::returnConditionalFlag(int flag) noexcept { + returnConditional(convertCondition(flag)); +} + +void EightBit::IntelProcessor::callConditionalFlag(int flag) noexcept { + callConditional(convertCondition(flag)); +} + +void EightBit::IntelProcessor::cpl() noexcept { + A() = ~A(); +} + bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept { + auto& left = const_cast(*this); + auto& right = const_cast(rhs); return LittleEndianProcessor::operator==(rhs) - && HALT() == rhs.HALT() - && MEMPTR() == rhs.MEMPTR() - && SP() == rhs.SP() - && AF() == rhs.AF() - && BC() == rhs.BC() - && DE() == rhs.DE() - && HL() == rhs.HL(); + && left.HALT() == right.HALT() + && left.MEMPTR() == right.MEMPTR() + && left.SP() == right.SP() + && left.AF() == right.AF() + && left.BC() == right.BC() + && left.DE() == right.DE() + && left.HL() == right.HL(); } diff --git a/src/LittleEndianProcessor.cpp b/src/LittleEndianProcessor.cpp index feaaa17..4a41b77 100644 --- a/src/LittleEndianProcessor.cpp +++ b/src/LittleEndianProcessor.cpp @@ -7,44 +7,44 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) noexcept EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept : Processor(rhs) {} -EightBit::register16_t EightBit::LittleEndianProcessor::getWord() { +EightBit::register16_t EightBit::LittleEndianProcessor::getWord() noexcept { const auto low = memoryRead(); ++BUS().ADDRESS(); const auto high = memoryRead(); return { low, high }; } -void EightBit::LittleEndianProcessor::setWord(const register16_t value) { +void EightBit::LittleEndianProcessor::setWord(const register16_t value) noexcept { memoryWrite(value.low); ++BUS().ADDRESS(); memoryWrite(value.high); } -EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() { +EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() noexcept { const auto low = memoryRead(); ++BUS().ADDRESS().low; const auto high = memoryRead(); return { low, high }; } -void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) { +void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) noexcept { memoryWrite(value.low); ++BUS().ADDRESS().low; memoryWrite(value.high); } -EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() { +EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept { intermediate().low = fetchByte(); intermediate().high = fetchByte(); return intermediate(); } -void EightBit::LittleEndianProcessor::pushWord(const register16_t value) { +void EightBit::LittleEndianProcessor::pushWord(const register16_t value) noexcept { push(value.high); push(value.low); } -EightBit::register16_t EightBit::LittleEndianProcessor::popWord() { +EightBit::register16_t EightBit::LittleEndianProcessor::popWord() noexcept { const auto low = pop(); const auto high = pop(); return { low, high }; diff --git a/src/Processor.cpp b/src/Processor.cpp index dfaa1b7..f8b9211 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -7,109 +7,109 @@ EightBit::Processor::Processor(Bus& bus) noexcept EightBit::Processor::Processor(const Processor& rhs) noexcept : ClockedChip(rhs), - m_bus(rhs.m_bus) { + m_bus(rhs.m_bus), + m_opcode(rhs.m_opcode), + m_pc(rhs.m_pc), + m_intermediate(rhs.m_intermediate) { RESET() = rhs.RESET(); INT() = rhs.INT(); - PC() = rhs.PC(); } DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor) DEFINE_PIN_LEVEL_CHANGERS(INT, Processor) -void EightBit::Processor::handleRESET() { +void EightBit::Processor::handleRESET() noexcept { raiseRESET(); } -void EightBit::Processor::handleINT() { +void EightBit::Processor::handleINT() noexcept { raiseINT(); } -void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) { +void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) noexcept { BUS().ADDRESS() = address; memoryWrite(data); } -void EightBit::Processor::memoryWrite(const register16_t address) { +void EightBit::Processor::memoryWrite(const register16_t address) noexcept { BUS().ADDRESS() = address; memoryWrite(); } -void EightBit::Processor::memoryWrite(const uint8_t data) { +void EightBit::Processor::memoryWrite(const uint8_t data) noexcept { BUS().DATA() = data; memoryWrite(); } -void EightBit::Processor::memoryWrite() { +void EightBit::Processor::memoryWrite() noexcept { busWrite(); } -void EightBit::Processor::busWrite() { +void EightBit::Processor::busWrite() noexcept { BUS().write(); } -uint8_t EightBit::Processor::memoryRead(const register16_t address) { +uint8_t EightBit::Processor::memoryRead(const register16_t address) noexcept { BUS().ADDRESS() = address; return memoryRead(); } -uint8_t EightBit::Processor::memoryRead() { +uint8_t EightBit::Processor::memoryRead() noexcept { return busRead(); } -uint8_t EightBit::Processor::busRead() { +uint8_t EightBit::Processor::busRead() noexcept { return BUS().read(); } -EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) { +EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) noexcept { BUS().ADDRESS() = address; return getWordPaged(); } -EightBit::register16_t EightBit::Processor::getWordPaged(const uint8_t page, const uint8_t offset) { +EightBit::register16_t EightBit::Processor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept { BUS().ADDRESS() = { offset, page }; return getWordPaged(); } -void EightBit::Processor::setWordPaged(register16_t address, const register16_t value) { +void EightBit::Processor::setWordPaged(register16_t address, const register16_t value) noexcept { BUS().ADDRESS() = address; setWordPaged(value); } -void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { +void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept { BUS().ADDRESS() = { offset, page }; setWordPaged(value); } -EightBit::register16_t& EightBit::Processor::incrementPC() { - PC()++; - return PC(); +EightBit::register16_t& EightBit::Processor::incrementPC() noexcept { + return ++PC(); } -EightBit::register16_t& EightBit::Processor::decrementPC() { - PC()--; - return PC(); +EightBit::register16_t& EightBit::Processor::decrementPC() noexcept { + return --PC(); } -void EightBit::Processor::immediateAddress() { +void EightBit::Processor::immediateAddress() noexcept { BUS().ADDRESS() = PC(); incrementPC(); } -uint8_t EightBit::Processor::fetchByte() { +uint8_t EightBit::Processor::fetchByte() noexcept { immediateAddress(); return memoryRead(); } -uint8_t EightBit::Processor::fetchInstruction() { +uint8_t EightBit::Processor::fetchInstruction() noexcept { return fetchByte(); } -EightBit::register16_t EightBit::Processor::getWord(const register16_t address) { +EightBit::register16_t EightBit::Processor::getWord(const register16_t address) noexcept { BUS().ADDRESS() = address; return getWord(); } -void EightBit::Processor::setWord(const register16_t address, const register16_t value) { +void EightBit::Processor::setWord(const register16_t address, const register16_t value) noexcept { BUS().ADDRESS() = address; setWord(value); } @@ -120,7 +120,7 @@ int EightBit::Processor::step() noexcept { if (LIKELY(powered())) poweredStep(); ExecutedInstruction.fire(); - ASSUME(cycles() > 0); + // ASSUME(cycles() > 0); Not if unpowered!! return cycles(); } @@ -141,15 +141,15 @@ void EightBit::Processor::jump(const register16_t destination) noexcept { } void EightBit::Processor::jump(const uint16_t destination) noexcept { - PC().word = destination; + PC() = destination; } -void EightBit::Processor::call(const register16_t destination) { +void EightBit::Processor::call(const register16_t destination) noexcept { pushWord(PC()); jump(destination); } -void EightBit::Processor::ret() { +void EightBit::Processor::ret() noexcept { jump(popWord()); } diff --git a/src/Rom.cpp b/src/Rom.cpp index 24cf331..4a2264b 100644 --- a/src/Rom.cpp +++ b/src/Rom.cpp @@ -3,7 +3,7 @@ #include -bool EightBit::Rom::operator==(const Rom& rhs) const { +bool EightBit::Rom::operator==(const Rom& rhs) const noexcept { return BYTES() == rhs.BYTES(); } @@ -48,10 +48,10 @@ void EightBit::Rom::poke(const uint16_t address, const uint8_t value) noexcept { EightBit::Rom::Rom(const size_t size) noexcept : m_bytes(size) {} -EightBit::Rom::Rom(const Rom& rhs) +EightBit::Rom::Rom(const Rom& rhs) noexcept : m_bytes(rhs.m_bytes) {} -EightBit::Rom& EightBit::Rom::operator=(const Rom& rhs) { +EightBit::Rom& EightBit::Rom::operator=(const Rom& rhs) noexcept { if (this != &rhs) m_bytes = rhs.m_bytes; return *this;