diff --git a/Gaming/inc/Game.h b/Gaming/inc/Game.h index c0d1fec..8cfa49a 100644 --- a/Gaming/inc/Game.h +++ b/Gaming/inc/Game.h @@ -23,7 +23,7 @@ namespace Gaming { virtual ~Game(); virtual void runLoop(); - void raisePOWER() override; + void raisePOWER() noexcept override; protected: [[nodiscard]] virtual float fps() const noexcept = 0; diff --git a/Gaming/src/Game.cpp b/Gaming/src/Game.cpp index a3a9c4e..a6ee8e5 100644 --- a/Gaming/src/Game.cpp +++ b/Gaming/src/Game.cpp @@ -25,7 +25,7 @@ int Game::displayHeight() const noexcept { return rasterHeight(); } -void Game::raisePOWER() { +void Game::raisePOWER() noexcept { Device::raisePOWER(); diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index f2f790a..c66538e 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -32,8 +32,8 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - virtual int execute() final; - virtual int step() final; + int execute() noexcept final; + int step() noexcept final; [[nodiscard]] const register16_t& AF() const noexcept final; [[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); } @@ -51,14 +51,14 @@ namespace EightBit { [[nodiscard]] bool requestingWrite() noexcept { return lowered(WR()); } protected: - void handleRESET() final; - void handleINT() final; + void handleRESET() noexcept final; + void handleINT() noexcept final; - void memoryWrite() final; - uint8_t memoryRead() final; + void memoryWrite() noexcept final; + uint8_t memoryRead() noexcept final; - void busWrite() final; - uint8_t busRead() final; + void busWrite() noexcept final; + uint8_t busRead() noexcept final; private: bool m_requestIO = false; diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index cbe164f..9fa596e 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -37,39 +37,39 @@ const EightBit::register16_t& EightBit::Intel8080::HL() const noexcept { return hl; } -void EightBit::Intel8080::memoryWrite() { +void EightBit::Intel8080::memoryWrite() noexcept { requestMemory(); IntelProcessor::memoryWrite(); releaseMemory(); } -uint8_t EightBit::Intel8080::memoryRead() { +uint8_t EightBit::Intel8080::memoryRead() noexcept { requestMemory(); const auto returned = IntelProcessor::memoryRead(); releaseMemory(); return returned; } -void EightBit::Intel8080::busWrite() { +void EightBit::Intel8080::busWrite() noexcept { requestWrite(); IntelProcessor::busWrite(); releaseWrite(); } -uint8_t EightBit::Intel8080::busRead() { +uint8_t EightBit::Intel8080::busRead() noexcept { requestRead(); const auto returned = IntelProcessor::busRead(); releaseRead(); return returned; } -void EightBit::Intel8080::handleRESET() { +void EightBit::Intel8080::handleRESET() noexcept { IntelProcessor::handleRESET(); di(); tick(3); } -void EightBit::Intel8080::handleINT() { +void EightBit::Intel8080::handleINT() noexcept { IntelProcessor::handleINT(); raiseHALT(); if (m_interruptEnable) { @@ -310,7 +310,7 @@ uint8_t EightBit::Intel8080::portRead() { return returned; } -int EightBit::Intel8080::step() { +int EightBit::Intel8080::step() noexcept { ExecutingInstruction.fire(*this); resetCycles(); if (LIKELY(powered())) { @@ -328,7 +328,7 @@ int EightBit::Intel8080::step() { return cycles(); } -int EightBit::Intel8080::execute() { +int EightBit::Intel8080::execute() noexcept { const auto& decoded = getDecodedOpcode(opcode()); diff --git a/Intel8080/test/Board.cpp b/Intel8080/test/Board.cpp index e78de3f..2799beb 100644 --- a/Intel8080/test/Board.cpp +++ b/Intel8080/test/Board.cpp @@ -10,14 +10,14 @@ Board::Board(const Configuration& configuration) m_disassembler(*this) { } -void Board::raisePOWER() { +void Board::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseRESET(); CPU().raiseINT(); } -void Board::lowerPOWER() { +void Board::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/Intel8080/test/Board.h b/Intel8080/test/Board.h index b765e4b..ba86b67 100644 --- a/Intel8080/test/Board.h +++ b/Intel8080/test/Board.h @@ -17,8 +17,8 @@ public: EightBit::Intel8080& CPU() { return m_cpu; } const EightBit::Intel8080& CPU() const { return m_cpu; } - virtual void raisePOWER() final; - virtual void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; virtual void initialise() final; diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.cpp b/LR35902/fusetest_LR35902/FuseTestRunner.cpp index 65ed458..037a69f 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.cpp +++ b/LR35902/fusetest_LR35902/FuseTestRunner.cpp @@ -9,7 +9,7 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte // -void Fuse::TestRunner::raisePOWER() { +void Fuse::TestRunner::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseRESET(); @@ -18,7 +18,7 @@ void Fuse::TestRunner::raisePOWER() { initialiseMemory(); } -void Fuse::TestRunner::lowerPOWER() { +void Fuse::TestRunner::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.h b/LR35902/fusetest_LR35902/FuseTestRunner.h index 8603301..d378639 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.h +++ b/LR35902/fusetest_LR35902/FuseTestRunner.h @@ -46,8 +46,8 @@ namespace Fuse { bool failed() const { return m_failed; } bool unimplemented() const { return m_unimplemented; } - virtual void raisePOWER() final; - virtual void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; void initialise(); }; diff --git a/LR35902/inc/GameBoyBus.h b/LR35902/inc/GameBoyBus.h index 38b1aca..261d433 100644 --- a/LR35902/inc/GameBoyBus.h +++ b/LR35902/inc/GameBoyBus.h @@ -36,8 +36,8 @@ namespace EightBit { Bus() noexcept; - virtual void raisePOWER() override; - virtual void lowerPOWER() override; + void raisePOWER() noexcept override; + void lowerPOWER() noexcept override; [[nodiscard]] auto& CPU() noexcept { return m_cpu; } [[nodiscard]] auto& VRAM() noexcept { return m_videoRam; } diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index 4839350..b4b7c0d 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -47,22 +47,22 @@ namespace EightBit { void tickMachine() { tick(4); MachineTicked.fire(); } protected: - int execute() final; - int step() final; + int execute() noexcept final; + int step() noexcept final; - void handleRESET() final; - void handleINT() final; + void handleRESET() noexcept final; + void handleINT() noexcept final; - void memoryWrite() final; - uint8_t memoryRead() final; + void memoryWrite() noexcept final; + uint8_t memoryRead() noexcept final; - void pushWord(register16_t value) final; + void pushWord(register16_t value) noexcept final; - void jr(int8_t offset) final; - int jumpConditional(int condition) final; - int returnConditional(int condition) final; - int jrConditional(int condition) final; - void ret() final; + void jr(int8_t offset) noexcept final; + int jumpConditional(int condition) noexcept final; + int returnConditional(int condition) noexcept final; + int jrConditional(int condition) noexcept final; + void ret() noexcept final; private: Bus& m_bus; diff --git a/LR35902/src/GameBoyBus.cpp b/LR35902/src/GameBoyBus.cpp index b8b147f..a27e4dd 100644 --- a/LR35902/src/GameBoyBus.cpp +++ b/LR35902/src/GameBoyBus.cpp @@ -8,14 +8,14 @@ EightBit::GameBoy::Bus::Bus() noexcept WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1)); } -void EightBit::GameBoy::Bus::raisePOWER() { +void EightBit::GameBoy::Bus::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseINT(); reset(); } -void EightBit::GameBoy::Bus::lowerPOWER() { +void EightBit::GameBoy::Bus::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 50a7b0c..5149742 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -31,59 +31,59 @@ const EightBit::register16_t& EightBit::GameBoy::LR35902::HL() const noexcept { return hl; } -void EightBit::GameBoy::LR35902::handleRESET() { +void EightBit::GameBoy::LR35902::handleRESET() noexcept { IntelProcessor::handleRESET(); di(); SP() = Mask16 - 1; tickMachine(4); } -void EightBit::GameBoy::LR35902::handleINT() { +void EightBit::GameBoy::LR35902::handleINT() noexcept { IntelProcessor::handleINT(); raiseHALT(); di(); restart(BUS().DATA()); } -void EightBit::GameBoy::LR35902::memoryWrite() { +void EightBit::GameBoy::LR35902::memoryWrite() noexcept { tickMachine(); IntelProcessor::memoryWrite(); } -uint8_t EightBit::GameBoy::LR35902::memoryRead() { +uint8_t EightBit::GameBoy::LR35902::memoryRead() noexcept { tickMachine(); return IntelProcessor::memoryRead(); } -void EightBit::GameBoy::LR35902::pushWord(register16_t value) { +void EightBit::GameBoy::LR35902::pushWord(register16_t value) noexcept { tickMachine(); IntelProcessor::pushWord(value); } -void EightBit::GameBoy::LR35902::jr(int8_t offset) { +void EightBit::GameBoy::LR35902::jr(int8_t offset) noexcept { IntelProcessor::jr(offset); tickMachine(); } -int EightBit::GameBoy::LR35902::jumpConditional(const int condition) { +int EightBit::GameBoy::LR35902::jumpConditional(const int condition) noexcept { if (IntelProcessor::jumpConditional(condition)) tickMachine(); return condition; } -int EightBit::GameBoy::LR35902::returnConditional(const int condition) { +int EightBit::GameBoy::LR35902::returnConditional(const int condition) noexcept { IntelProcessor::returnConditional(condition); tickMachine(); return condition; } -int EightBit::GameBoy::LR35902::jrConditional(const int condition) { +int EightBit::GameBoy::LR35902::jrConditional(const int condition) noexcept { if (!IntelProcessor::jrConditional(condition)) tickMachine(); return condition; } -void EightBit::GameBoy::LR35902::ret() { +void EightBit::GameBoy::LR35902::ret() noexcept { IntelProcessor::ret(); tickMachine(); } @@ -435,7 +435,7 @@ uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept { return enabledInterrupts() & flaggedInterrupts(); } -int EightBit::GameBoy::LR35902::step() { +int EightBit::GameBoy::LR35902::step() noexcept { ExecutingInstruction.fire(*this); m_prefixCB = false; @@ -470,7 +470,7 @@ int EightBit::GameBoy::LR35902::step() { return cycles(); } -int EightBit::GameBoy::LR35902::execute() { +int EightBit::GameBoy::LR35902::execute() noexcept { const auto& decoded = getDecodedOpcode(opcode()); @@ -486,8 +486,7 @@ int EightBit::GameBoy::LR35902::execute() { else executeCB(x, y, z, p, q); - if (UNLIKELY(cycles() == 0)) - throw std::logic_error("Unhandled opcode"); + assert(cycles() > 0); return cycles(); } @@ -802,14 +801,14 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in IntelProcessor::memoryWrite(IoRegisters::BASE + C(), A()); break; case 5: // GB: LD (nn),A - BUS().ADDRESS() = MEMPTR() = fetchWord(); - IntelProcessor::memoryWrite(A()); + MEMPTR() = BUS().ADDRESS() = fetchWord(); + IntelProcessor::memoryWrite(A()); break; case 6: // GB: LD A,(FF00 + C) A() = IntelProcessor::memoryRead(IoRegisters::BASE + C()); break; case 7: // GB: LD A,(nn) - BUS().ADDRESS() = MEMPTR() = fetchWord(); + MEMPTR() = BUS().ADDRESS() = fetchWord(); A() = memoryRead(); break; default: diff --git a/M6502/HarteTest_6502/TestRunner.cpp b/M6502/HarteTest_6502/TestRunner.cpp index 15117d6..f175339 100644 --- a/M6502/HarteTest_6502/TestRunner.cpp +++ b/M6502/HarteTest_6502/TestRunner.cpp @@ -7,7 +7,7 @@ EightBit::MemoryMapping TestRunner::mapping(const uint16_t address) noexcept { return { RAM(), 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; } -void TestRunner::raisePOWER() { +void TestRunner::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseRESET(); @@ -17,7 +17,7 @@ void TestRunner::raisePOWER() { CPU().raiseRDY(); } -void TestRunner::lowerPOWER() { +void TestRunner::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/M6502/HarteTest_6502/TestRunner.h b/M6502/HarteTest_6502/TestRunner.h index 2bc2a01..874aed8 100644 --- a/M6502/HarteTest_6502/TestRunner.h +++ b/M6502/HarteTest_6502/TestRunner.h @@ -15,8 +15,8 @@ protected: public: TestRunner(); - void raisePOWER() final; - void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; void initialise() final; diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index f1e05dd..20ac98f 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -38,8 +38,8 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - int execute() final; - [[nodiscard]] int step() final; + int execute() noexcept final; + [[nodiscard]] int step() noexcept final; [[nodiscard]] constexpr auto& X() noexcept { return x; } [[nodiscard]] constexpr auto& Y() noexcept { return y; } @@ -50,11 +50,11 @@ namespace EightBit { [[nodiscard]] constexpr const auto& P() const noexcept { return p; } protected: - void handleRESET() final; - void handleINT() final; + void handleRESET() noexcept final; + void handleINT() noexcept final; - void busWrite() final; - [[nodiscard]] uint8_t busRead() final; + void busWrite() noexcept final; + [[nodiscard]] uint8_t busRead() noexcept final; [[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0) noexcept; [[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data) noexcept; @@ -71,16 +71,16 @@ namespace EightBit { const uint8_t RSTvector = 0xfc; // RST vector const uint8_t NMIvector = 0xfa; // NMI vector - void handleNMI(); - void handleSO(); + void handleNMI() noexcept; + void handleSO() noexcept; void interrupt(); - void push(uint8_t value) final; - [[nodiscard]] uint8_t pop() final; + void push(uint8_t value) noexcept final; + [[nodiscard]] uint8_t pop() noexcept final; // Dummy stack push, used during RESET - void dummyPush(uint8_t value); + void dummyPush(uint8_t value) noexcept; // Addressing modes diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 465727c..fac850b 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -20,7 +20,7 @@ DEFINE_PIN_LEVEL_CHANGERS(SYNC, MOS6502); DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502); DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502); -int EightBit::MOS6502::step() { +int EightBit::MOS6502::step() noexcept { resetCycles(); ExecutingInstruction.fire(*this); if (LIKELY(powered())) { @@ -46,25 +46,25 @@ int EightBit::MOS6502::step() { // Interrupt (etc.) handlers -void EightBit::MOS6502::handleSO() { +void EightBit::MOS6502::handleSO() noexcept { raiseSO(); P() |= VF; } -void EightBit::MOS6502::handleRESET() { +void EightBit::MOS6502::handleRESET() noexcept { raiseRESET(); m_handlingRESET = true; opcode() = 0x00; // BRK } -void EightBit::MOS6502::handleNMI() { +void EightBit::MOS6502::handleNMI() noexcept { raiseNMI(); m_handlingNMI = true; opcode() = 0x00; // BRK } -void EightBit::MOS6502::handleINT() { +void EightBit::MOS6502::handleINT() noexcept { raiseINT(); m_handlingINT = true; opcode() = 0x00; // BRK @@ -92,13 +92,13 @@ void EightBit::MOS6502::interrupt() { // -void EightBit::MOS6502::busWrite() { +void EightBit::MOS6502::busWrite() noexcept { tick(); lowerRW(); Processor::busWrite(); } -uint8_t EightBit::MOS6502::busRead() { +uint8_t EightBit::MOS6502::busRead() noexcept { tick(); raiseRW(); return Processor::busRead(); @@ -106,7 +106,7 @@ uint8_t EightBit::MOS6502::busRead() { // -int EightBit::MOS6502::execute() { +int EightBit::MOS6502::execute() noexcept { raiseSYNC(); // Instruction fetch has now completed @@ -391,15 +391,15 @@ int EightBit::MOS6502::execute() { //// -void EightBit::MOS6502::push(uint8_t value) { +void EightBit::MOS6502::push(uint8_t value) noexcept { setBytePaged(1, S()--, value); } -uint8_t EightBit::MOS6502::pop() { +uint8_t EightBit::MOS6502::pop() noexcept { return getBytePaged(1, ++S()); } -void EightBit::MOS6502::dummyPush(const uint8_t value) { +void EightBit::MOS6502::dummyPush(const uint8_t value) noexcept { tick(); BUS().DATA() = value; BUS().ADDRESS() = { S()--, 1 }; diff --git a/M6502/test/Board.cpp b/M6502/test/Board.cpp index 6ed4310..b0c15aa 100644 --- a/M6502/test/Board.cpp +++ b/M6502/test/Board.cpp @@ -10,7 +10,7 @@ Board::Board(const Configuration& configuration) : m_configuration(configuration) {} -void Board::raisePOWER() { +void Board::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseRESET(); @@ -20,7 +20,7 @@ void Board::raisePOWER() { CPU().raiseRDY(); } -void Board::lowerPOWER() { +void Board::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/M6502/test/Board.h b/M6502/test/Board.h index 8d8b09d..260b82b 100644 --- a/M6502/test/Board.h +++ b/M6502/test/Board.h @@ -17,10 +17,10 @@ public: EightBit::MOS6502& CPU() { return m_cpu; } - virtual void raisePOWER() final; - virtual void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; - virtual void initialise() final; + void initialise() final; protected: virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final { diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h index 6763a75..d5ade08 100644 --- a/MC6809/inc/mc6809.h +++ b/MC6809/inc/mc6809.h @@ -66,8 +66,8 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - int execute() final; - [[nodiscard]] int step() final; + int execute() noexcept final; + [[nodiscard]] int step() noexcept final; [[nodiscard]] constexpr auto& D() noexcept { return m_d; } [[nodiscard]] constexpr auto& A() noexcept { return D().high; } @@ -111,21 +111,21 @@ namespace EightBit { protected: // Default push/pop handlers - void push(uint8_t value) final; - [[nodiscard]] uint8_t pop() final; + void push(uint8_t value) noexcept final; + [[nodiscard]] uint8_t pop() noexcept final; // Interrupt (etc.) handlers - void handleRESET() final; - void handleINT() final; + void handleRESET() noexcept final; + void handleINT() noexcept final; // Bus reader/writers - void busWrite() final; - uint8_t busRead() final; + void busWrite() noexcept final; + uint8_t busRead() noexcept final; - void call(register16_t destination) final; - void ret() final; + void call(register16_t destination) noexcept final; + void ret() noexcept final; private: const uint8_t RESETvector = 0xfe; // RESET vector diff --git a/MC6809/src/mc6809.cpp b/MC6809/src/mc6809.cpp index ba067d8..9aa780e 100644 --- a/MC6809/src/mc6809.cpp +++ b/MC6809/src/mc6809.cpp @@ -20,7 +20,7 @@ DEFINE_PIN_LEVEL_CHANGERS(BA, mc6809); DEFINE_PIN_LEVEL_CHANGERS(BS, mc6809); DEFINE_PIN_LEVEL_CHANGERS(RW, mc6809); -int EightBit::mc6809::step() { +int EightBit::mc6809::step() noexcept { resetCycles(); ExecutingInstruction.fire(*this); if (LIKELY(powered())) { @@ -49,7 +49,7 @@ void EightBit::mc6809::handleHALT() { raiseBS(); } -void EightBit::mc6809::handleRESET() { +void EightBit::mc6809::handleRESET() noexcept { BigEndianProcessor::handleRESET(); memoryRead({ RESETvector, 0xff }); raiseNMI(); @@ -80,7 +80,7 @@ void EightBit::mc6809::handleNMI() { eat(); } -void EightBit::mc6809::handleINT() { +void EightBit::mc6809::handleINT() noexcept { BigEndianProcessor::handleINT(); lowerBA(); raiseBS(); @@ -111,13 +111,13 @@ void EightBit::mc6809::handleFIRQ() { // -void EightBit::mc6809::busWrite() { +void EightBit::mc6809::busWrite() noexcept { tick(); lowerRW(); Processor::busWrite(); } -uint8_t EightBit::mc6809::busRead() { +uint8_t EightBit::mc6809::busRead() noexcept { tick(); raiseRW(); return Processor::busRead(); @@ -125,21 +125,21 @@ uint8_t EightBit::mc6809::busRead() { // -void EightBit::mc6809::call(register16_t destination) { +void EightBit::mc6809::call(register16_t destination) noexcept { memoryRead(destination); eat(); BigEndianProcessor::pushWord(PC()); jump(destination); } -void EightBit::mc6809::ret() { +void EightBit::mc6809::ret() noexcept { BigEndianProcessor::ret(); eat(); } // -int EightBit::mc6809::execute() { +int EightBit::mc6809::execute() noexcept { lowerBA(); lowerBS(); const bool prefixed = m_prefix10 || m_prefix11; @@ -628,11 +628,11 @@ void EightBit::mc6809::execute11() { // -void EightBit::mc6809::push(const uint8_t value) { +void EightBit::mc6809::push(const uint8_t value) noexcept { pushS(value); } -uint8_t EightBit::mc6809::pop() { +uint8_t EightBit::mc6809::pop() noexcept { return popS(); } diff --git a/MC6809/test/Board.cpp b/MC6809/test/Board.cpp index 30c5c24..bd1a814 100644 --- a/MC6809/test/Board.cpp +++ b/MC6809/test/Board.cpp @@ -4,7 +4,7 @@ Board::Board(const Configuration& configuration) : m_configuration(configuration) {} -void Board::raisePOWER() { +void Board::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); @@ -26,7 +26,7 @@ void Board::raisePOWER() { accessAcia(); } -void Board::lowerPOWER() { +void Board::lowerPOWER() noexcept { if (m_configuration.isProfileMode()) { m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) { diff --git a/MC6809/test/Board.h b/MC6809/test/Board.h index 8763a28..4eb68a2 100644 --- a/MC6809/test/Board.h +++ b/MC6809/test/Board.h @@ -20,8 +20,8 @@ public: auto& CPU() { return m_cpu; } auto& ACIA() { return m_acia; } - void raisePOWER() final; - void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; virtual void initialise() final; diff --git a/MC6809/unittest/Board.cpp b/MC6809/unittest/Board.cpp index 3e43d95..d1219ff 100644 --- a/MC6809/unittest/Board.cpp +++ b/MC6809/unittest/Board.cpp @@ -3,7 +3,7 @@ Board::Board() {} -void Board::raisePOWER() { +void Board::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); @@ -16,7 +16,7 @@ void Board::raisePOWER() { CPU().raiseHALT(); } -void Board::lowerPOWER() { +void Board::lowerPOWER() noexcept { CPU().lowerPOWER(); EightBit::Bus::lowerPOWER(); } diff --git a/MC6809/unittest/Board.h b/MC6809/unittest/Board.h index 535cf3c..f7d405a 100644 --- a/MC6809/unittest/Board.h +++ b/MC6809/unittest/Board.h @@ -11,8 +11,8 @@ public: constexpr EightBit::mc6809& CPU() noexcept { return m_cpu; } - void raisePOWER() final; - void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; protected: void initialise() final; diff --git a/Z80/fusetest_Z80/FuseExpectedTestResult.cpp b/Z80/fusetest_Z80/FuseExpectedTestResult.cpp index bc25428..676731a 100644 --- a/Z80/fusetest_Z80/FuseExpectedTestResult.cpp +++ b/Z80/fusetest_Z80/FuseExpectedTestResult.cpp @@ -45,4 +45,15 @@ void Fuse::ExpectedTestResult::read(std::ifstream& file) { memoryData.push_back(datum); } } while (!line.empty()); -} \ No newline at end of file +} + +// returns a vector of: address, expected, actual +std::vector> Fuse::ExpectedTestResult::findDifferences(const EightBit::Memory& memory) const { + std::vector> returned; + for (const auto& memoryDatum : memoryData) { + const auto found = memoryDatum.findDifferences(memory); + if (!found.empty()) + returned.insert(returned.end(), found.begin(), found.end()); + } + return returned; +} diff --git a/Z80/fusetest_Z80/FuseExpectedTestResult.h b/Z80/fusetest_Z80/FuseExpectedTestResult.h index 29bf4ee..ff33567 100644 --- a/Z80/fusetest_Z80/FuseExpectedTestResult.h +++ b/Z80/fusetest_Z80/FuseExpectedTestResult.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "FuseTestEvents.h" #include "FuseRegisterState.h" @@ -23,5 +24,8 @@ namespace Fuse { : finish(false) {} void read(std::ifstream& file); + + // returns a vector of: address, expected, actual + std::vector> findDifferences(const EightBit::Memory& memory) const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseMemoryDatum.cpp b/Z80/fusetest_Z80/FuseMemoryDatum.cpp index 871e8ef..e55d408 100644 --- a/Z80/fusetest_Z80/FuseMemoryDatum.cpp +++ b/Z80/fusetest_Z80/FuseMemoryDatum.cpp @@ -17,4 +17,21 @@ void Fuse::MemoryDatum::read(std::ifstream& file) { if (!completed) bytes.push_back(byte); } while (!completed); -} \ No newline at end of file +} + +void Fuse::MemoryDatum::transfer(EightBit::Memory& memory) const { + memory.load(bytes, address); +} + +// returns a vector of: address, expected, actual +std::vector> Fuse::MemoryDatum::findDifferences(const EightBit::Memory& memory) const { + std::vector> returned; + for (int i = 0; i < bytes.size(); ++i) { + const auto expected = bytes[i]; + int address = this->address + i; + const auto actual = memory.peek(address); + if (expected != actual) + returned.push_back({ address, expected, actual }); + } + return returned;; +} diff --git a/Z80/fusetest_Z80/FuseMemoryDatum.h b/Z80/fusetest_Z80/FuseMemoryDatum.h index 0cf4c33..0a6ac77 100644 --- a/Z80/fusetest_Z80/FuseMemoryDatum.h +++ b/Z80/fusetest_Z80/FuseMemoryDatum.h @@ -3,6 +3,9 @@ #include #include #include +#include + +#include namespace Fuse { class MemoryDatum { @@ -19,5 +22,10 @@ namespace Fuse { bool finished() const { return finish; } void read(std::ifstream& file); + + void transfer(EightBit::Memory& memory) const; + + // returns a vector of: address, expected, actual + std::vector> findDifferences(const EightBit::Memory& memory) const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseRegisterState.cpp b/Z80/fusetest_Z80/FuseRegisterState.cpp index b0e3db3..430ddad 100644 --- a/Z80/fusetest_Z80/FuseRegisterState.cpp +++ b/Z80/fusetest_Z80/FuseRegisterState.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "FuseRegisterState.h" +#include + Fuse::RegisterState::RegisterState() : registers(NUMBER_OF_REGISTERS) { } @@ -11,10 +13,10 @@ void Fuse::RegisterState::read(std::ifstream& file) { } void Fuse::RegisterState::readExternal(std::ifstream& file) { - for (int idx = 0; idx < registers.size(); ++idx) { + for (auto& r : registers) { int input; file >> input; - registers[idx] = input; + r = input; } } @@ -30,3 +32,31 @@ void Fuse::RegisterState::readInternal(std::ifstream& file) { file >> tstates; file >> std::hex; } + +void Fuse::RegisterState::transfer(EightBit::Z80& cpu) const { + + cpu.AF() = registers[AF_]; + cpu.BC() = registers[BC_]; + cpu.DE() = registers[DE_]; + cpu.HL() = registers[HL_]; + cpu.exx(); + cpu.exxAF(); + cpu.AF() = registers[AF]; + cpu.BC() = registers[BC]; + cpu.DE() = registers[DE]; + cpu.HL() = registers[HL]; + + cpu.IX() = registers[IX]; + cpu.IY() = registers[IY]; + + cpu.SP() = registers[SP]; + cpu.PC() = registers[PC]; + + cpu.MEMPTR() = registers[MEMPTR]; + + cpu.IV() = i; + cpu.REFRESH() = r; + cpu.IFF1() = iff1; + cpu.IFF2() = iff2; + cpu.IM() = im; +} diff --git a/Z80/fusetest_Z80/FuseRegisterState.h b/Z80/fusetest_Z80/FuseRegisterState.h index 70d4a96..a25d6c2 100644 --- a/Z80/fusetest_Z80/FuseRegisterState.h +++ b/Z80/fusetest_Z80/FuseRegisterState.h @@ -1,11 +1,14 @@ #pragma once #include -#include #include #include +namespace EightBit { + class Z80; +} + namespace Fuse { class RegisterState { public: @@ -13,11 +16,11 @@ namespace Fuse { AF, BC, DE, HL, AF_, BC_, DE_, HL_, IX, IY, SP, PC, MEMPTR, NUMBER_OF_REGISTERS }; std::vector registers; - int i, r; - bool iff1, iff2; - int im; - bool halted; - int tstates; + int i = -1, r = -1; + bool iff1 = false, iff2 = false; + int im = -1; + bool halted = false; + int tstates = -1; public: RegisterState(); @@ -25,5 +28,7 @@ namespace Fuse { void read(std::ifstream& file); void readInternal(std::ifstream& file); void readExternal(std::ifstream& file); + + void transfer(EightBit::Z80& cpu) const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTest.cpp b/Z80/fusetest_Z80/FuseTest.cpp index 1a8ca4a..c991325 100644 --- a/Z80/fusetest_Z80/FuseTest.cpp +++ b/Z80/fusetest_Z80/FuseTest.cpp @@ -23,3 +23,12 @@ void Fuse::Test::read(std::ifstream& file) { memoryData.push_back(memoryDatum); } while (!complete); } + +void Fuse::Test::transferMemory(EightBit::Memory& memory) const { + for (const auto& memoryDatum : memoryData) + memoryDatum.transfer(memory); +} + +void Fuse::Test::transferRegisters(EightBit::Z80 & cpu) const { + registerState.transfer(cpu); +} diff --git a/Z80/fusetest_Z80/FuseTest.h b/Z80/fusetest_Z80/FuseTest.h index 35aa4cd..ca763f4 100644 --- a/Z80/fusetest_Z80/FuseTest.h +++ b/Z80/fusetest_Z80/FuseTest.h @@ -7,6 +7,9 @@ #include "FuseMemoryDatum.h" #include "FuseRegisterState.h" +#include +#include + namespace Fuse { class Test { public: @@ -16,5 +19,8 @@ namespace Fuse { bool finish = false; void read(std::ifstream& file); + + void transferMemory(EightBit::Memory& memory) const; + void transferRegisters(EightBit::Z80& cpu) const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTestEvent.cpp b/Z80/fusetest_Z80/FuseTestEvent.cpp index 57cc271..c49fc69 100644 --- a/Z80/fusetest_Z80/FuseTestEvent.cpp +++ b/Z80/fusetest_Z80/FuseTestEvent.cpp @@ -1,6 +1,18 @@ #include "stdafx.h" #include "FuseTestEvent.h" +#include + +#include + +bool Fuse::TestEvent::operator==(const TestEvent& rhs) const { + const auto equalCycles = cycles == rhs.cycles; + const auto equalSpecifier = specifier == rhs.specifier; + const auto equalAddress = address == rhs.address; + const auto equalValue = value == rhs.value; + return equalCycles && equalSpecifier && equalAddress && equalValue; +} + void Fuse::TestEvent::read(std::ifstream& file) { auto prior = file.tellg(); @@ -31,4 +43,14 @@ void Fuse::TestEvent::read(std::ifstream& file) { if (!valid) { file.seekg(prior); } +} + +void Fuse::TestEvent::dump() const { + std::cerr << " Event issue " << + "Cycles = " << cycles << + ", Specifier = " << specifier << + ", Address = " << EightBit::Disassembler::hex((uint16_t)address); + if (!boost::algorithm::ends_with(specifier, "C")) + std::cerr << ", Value=" << EightBit::Disassembler::hex((uint8_t)value); + std::cerr << std::endl; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTestEvent.h b/Z80/fusetest_Z80/FuseTestEvent.h index 8ea1c65..f65fb4c 100644 --- a/Z80/fusetest_Z80/FuseTestEvent.h +++ b/Z80/fusetest_Z80/FuseTestEvent.h @@ -12,9 +12,12 @@ namespace Fuse { TestEvent() : valid(false), - cycles(-1), address(-1), value(-1) { - } + cycles(-1), address(-1), value(-1) {} + + bool operator==(const TestEvent& rhs) const; void read(std::ifstream& file); + + void dump() const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTestEvents.cpp b/Z80/fusetest_Z80/FuseTestEvents.cpp index 081393b..a3e1788 100644 --- a/Z80/fusetest_Z80/FuseTestEvents.cpp +++ b/Z80/fusetest_Z80/FuseTestEvents.cpp @@ -1,6 +1,15 @@ #include "stdafx.h" #include "FuseTestEvents.h" +bool Fuse::TestEvents::operator==(const TestEvents& rhs) const { + auto unequal = events.size() != rhs.events.size(); + for (int i = 0; !unequal && (i < events.size()); ++i) { + const auto equal = events[i] == rhs.events[i]; + unequal = !equal; + } + return !unequal; +} + void Fuse::TestEvents::read(std::ifstream& file) { bool complete = false; do { @@ -11,3 +20,8 @@ void Fuse::TestEvents::read(std::ifstream& file) { events.push_back(event); } while (!complete); } + +void Fuse::TestEvents::dump() const { + for (const auto& event : events) + event.dump(); +} diff --git a/Z80/fusetest_Z80/FuseTestEvents.h b/Z80/fusetest_Z80/FuseTestEvents.h index 9463cdb..0ef4bfa 100644 --- a/Z80/fusetest_Z80/FuseTestEvents.h +++ b/Z80/fusetest_Z80/FuseTestEvents.h @@ -8,6 +8,10 @@ namespace Fuse { public: std::vector events; + bool operator==(const TestEvents& rhs) const; + void read(std::ifstream& file); + + void dump() const; }; } \ No newline at end of file diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index 3c3ede0..156b432 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -51,16 +51,16 @@ void Fuse::TestRunner::addActualEvent(const std::string& specifier) { // -void Fuse::TestRunner::raisePOWER() { +void Fuse::TestRunner::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); m_cpu.raisePOWER(); m_cpu.raiseRESET(); m_cpu.raiseINT(); m_cpu.raiseNMI(); - initialiseRegisters(); + m_test.transferRegisters(m_cpu); } -void Fuse::TestRunner::lowerPOWER() { +void Fuse::TestRunner::lowerPOWER() noexcept { m_cpu.lowerPOWER(); EightBit::Bus::lowerPOWER(); } @@ -99,47 +99,7 @@ EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) noexcept { } void Fuse::TestRunner::initialise() { - initialiseMemory(); -} - -void Fuse::TestRunner::initialiseRegisters() { - - const auto& testState = m_test.registerState; - const auto& inputRegisters = testState.registers; - - m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF_]; - m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC_]; - m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE_]; - m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL_]; - m_cpu.exx(); - m_cpu.exxAF(); - m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF]; - m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC]; - m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE]; - m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL]; - - m_cpu.IX() = inputRegisters[Fuse::RegisterState::IX]; - m_cpu.IY() = inputRegisters[Fuse::RegisterState::IY]; - - m_cpu.SP() = inputRegisters[Fuse::RegisterState::SP]; - m_cpu.PC() = inputRegisters[Fuse::RegisterState::PC]; - - m_cpu.MEMPTR() = inputRegisters[Fuse::RegisterState::MEMPTR]; - - m_cpu.IV() = testState.i; - m_cpu.REFRESH() = testState.r; - m_cpu.IFF1() = testState.iff1; - m_cpu.IFF2() = testState.iff2; - m_cpu.IM() = testState.im; -} - -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_ram.poke(address + i, bytes[i]); - } + m_test.transferMemory(m_ram); } // @@ -378,51 +338,26 @@ void Fuse::TestRunner::checkRegisters() { } void Fuse::TestRunner::checkMemory() { - - bool first = true; - - for (auto memoryDatum : m_result.memoryData) { - auto bytes = memoryDatum.bytes; - for (int i = 0; i < bytes.size(); ++i) { - auto expected = bytes[i]; - uint16_t address = memoryDatum.address + i; - auto actual = m_ram.peek(address); - if (expected != actual) { - m_failed = true; - if (first) { - first = false; - std::cerr << "**** Failed test (Memory): " << m_test.description << std::endl; - } - std::cerr - << "**** Difference: " - << "Address: " << EightBit::Disassembler::hex(address) - << " Expected: " << EightBit::Disassembler::hex(expected) - << " Actual: " << EightBit::Disassembler::hex(actual) - << std::endl; - } + const auto differences = m_result.findDifferences(m_ram); + const auto failure = !differences.empty(); + if (failure) { + m_failed = true; + std::cerr << "**** Failed test (Memory): " << m_test.description << std::endl; + for (const auto& difference : differences) { + const auto [address, expected, actual] = difference; + std::cerr + << "**** Difference: " + << "Address: " << EightBit::Disassembler::hex((uint16_t)address) + << " Expected: " << EightBit::Disassembler::hex((uint8_t)expected) + << " Actual: " << EightBit::Disassembler::hex((uint8_t)actual) + << std::endl; } } } void Fuse::TestRunner::checkEvents() { - const auto& expectations = m_expectedEvents.events; - const auto& actuals = m_actualEvents.events; - - auto eventFailure = expectations.size() != actuals.size(); - for (auto i = 0; !eventFailure && (i < expectations.size()); ++i) { - - const auto& expectation = expectations[i]; - const auto& actual = actuals[i]; - - const auto equalCycles = expectation.cycles == actual.cycles; - const auto equalSpecifier = expectation.specifier == actual.specifier; - const auto equalAddress = expectation.address == actual.address; - const auto equalValue = expectation.value == actual.value; - - const auto equal = equalCycles && equalSpecifier && equalAddress && equalValue; - eventFailure = !equal; - } + auto eventFailure = m_expectedEvents != m_actualEvents; if (eventFailure) { dumpExpectedEvents(); @@ -435,28 +370,12 @@ void Fuse::TestRunner::checkEvents() { void Fuse::TestRunner::dumpExpectedEvents() const { std::cerr << "++++ Dumping expected events:" << std::endl; - dumpEvents(m_expectedEvents.events); + m_expectedEvents.dump(); } void Fuse::TestRunner::dumpActualEvents() const { std::cerr << "++++ Dumping actual events:" << std::endl; - dumpEvents(m_actualEvents.events); -} - -void Fuse::TestRunner::dumpEvents(const std::vector& events) { - for (const auto& event : events) { - dumpEvent(event); - } -} - -void Fuse::TestRunner::dumpEvent(const TestEvent& event) { - std::cerr << " Event issue " << - "Cycles = " << event.cycles << - ", Specifier = " << event.specifier << - ", Address = " << EightBit::Disassembler::hex((uint16_t)event.address); - if (!boost::algorithm::ends_with(event.specifier, "C")) - std::cerr << ", Value=" << EightBit::Disassembler::hex((uint8_t)event.value); - std::cerr << std::endl; + m_actualEvents.dump(); } void Fuse::TestRunner::run() { diff --git a/Z80/fusetest_Z80/FuseTestRunner.h b/Z80/fusetest_Z80/FuseTestRunner.h index 4ceba2f..e05b4e8 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.h +++ b/Z80/fusetest_Z80/FuseTestRunner.h @@ -26,9 +26,6 @@ namespace Fuse { int m_totalCycles; - void initialiseRegisters(); - void initialiseMemory(); - void check(); void checkRegisters(); void checkMemory(); @@ -44,9 +41,6 @@ namespace Fuse { void dumpExpectedEvents() const; void dumpActualEvents() const; - static void dumpEvents(const std::vector& events); - static void dumpEvent(const TestEvent& event); - protected: virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final; @@ -57,9 +51,9 @@ namespace Fuse { bool failed() const { return m_failed; } bool unimplemented() const { return m_unimplemented; } - virtual void raisePOWER() final; - virtual void lowerPOWER() final; + void raisePOWER() noexcept final; + void lowerPOWER() noexcept final; - virtual void initialise() final; + void initialise() final; }; } \ No newline at end of file diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 8d6b6a8..524208b 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -89,8 +89,8 @@ namespace EightBit { Signal WritingIO; Signal WrittenIO; - int execute() final; - int step() final; + int execute() noexcept final; + int step() noexcept final; [[nodiscard]] const register16_t& AF() const noexcept final; [[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); } @@ -101,15 +101,15 @@ namespace EightBit { [[nodiscard]] const register16_t& HL() const noexcept final; [[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); } - [[nodiscard]] const auto& IX() const noexcept { return m_ix; } + [[nodiscard]] constexpr const auto& IX() const noexcept { return m_ix; } NON_CONST_REGISTOR_ACCESSOR(IX); - [[nodiscard]] auto& IXH() noexcept { return IX().high; } - [[nodiscard]] auto& IXL() noexcept { return IX().low; } + [[nodiscard]] constexpr auto& IXH() noexcept { return IX().high; } + [[nodiscard]] constexpr auto& IXL() noexcept { return IX().low; } - [[nodiscard]] const auto& IY() const noexcept { return m_iy; } + [[nodiscard]] constexpr const auto& IY() const noexcept { return m_iy; } NON_CONST_REGISTOR_ACCESSOR(IY); - [[nodiscard]] auto& IYH() noexcept { return IY().high; } - [[nodiscard]] auto& IYL() noexcept { return IY().low; } + [[nodiscard]] constexpr auto& IYH() noexcept { return IY().high; } + [[nodiscard]] constexpr auto& IYL() noexcept { return IY().low; } // ** From the Z80 CPU User Manual // Memory Refresh(R) Register.The Z80 CPU contains a memory refresh counter, @@ -144,19 +144,19 @@ namespace EightBit { [[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); } protected: - void handleRESET() final; - void handleINT() final; + void handleRESET() noexcept final; + void handleINT() noexcept final; - void pushWord(register16_t destination) final; + void pushWord(register16_t destination) noexcept final; - void memoryWrite() final; - uint8_t memoryRead() final; + void memoryWrite() noexcept final; + uint8_t memoryRead() noexcept final; - void busWrite() final; - uint8_t busRead() final; + void busWrite() noexcept final; + uint8_t busRead() noexcept final; - void jr(int8_t offset) final; - int jrConditional(int condition) final; + void jr(int8_t offset) noexcept final; + int jrConditional(int condition) noexcept final; private: enum { BC_IDX, DE_IDX, HL_IDX }; @@ -184,136 +184,376 @@ namespace EightBit { int8_t m_displacement = 0; - void handleNMI(); + void handleNMI() noexcept; - void resetPrefixes() 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]] uint16_t displacedAddress() noexcept; - void fetchDisplacement(); - [[nodiscard]] uint8_t fetchOpCode(); - uint8_t readBusDataM1(); + [[nodiscard]] constexpr uint16_t displacedAddress() noexcept { + const auto address = (m_prefixDD ? IX() : IY()).word + m_displacement; + MEMPTR().word = address; + return address; + } + + void fetchDisplacement() noexcept; + [[nodiscard]] uint8_t fetchOpCode() noexcept; + + uint8_t readBusDataM1() noexcept; typedef std::function addresser_t; - void loadAccumulatorIndirect(addresser_t addresser); - void storeAccumulatorIndirect(addresser_t addresser); + void loadAccumulatorIndirect(addresser_t addresser) noexcept; + void storeAccumulatorIndirect(addresser_t addresser) noexcept; typedef std::function reader_t; - void readInternalRegister(reader_t reader); + void readInternalRegister(reader_t reader) noexcept; [[nodiscard]] register16_t& HL2() noexcept; [[nodiscard]] register16_t& RP(int rp) noexcept; [[nodiscard]] register16_t& RP2(int rp) noexcept; - [[nodiscard]] uint8_t R(int r); - void R(int r, uint8_t value); - void R2(int r, uint8_t value); + [[nodiscard]] uint8_t R(int r) noexcept; + void R(int r, uint8_t value) noexcept; + void R2(int r, uint8_t value) noexcept; - [[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept; - [[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept; - [[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept; - [[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept; - [[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept; - [[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept; + [[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept { + return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation)); + } - [[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept; + [[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept { + return setBit(f, HC, calculateHalfCarrySub(before, value, calculation)); + } - static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept; + [[nodiscard]] static constexpr auto adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept { + const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative); + return setBit(f, VF, overflow); + } - void executeCB(int x, int y, int z); - void executeED(int x, int y, int z, int p, int q); - void executeOther(int x, int y, int z, int p, int q); + [[nodiscard]] static constexpr auto adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept { + return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF); + } - [[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept; + [[nodiscard]] static constexpr auto adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept { + const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative); + return setBit(f, VF, overflow); + } + + [[nodiscard]] static constexpr auto adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept { + return adjustOverflowSub(f, before & SF, value & SF, calculation & SF); + } + + [[nodiscard]] static constexpr bool convertCondition(uint8_t f, int flag) noexcept { + switch (flag) { + case 0: + return !(f & ZF); + case 1: + return f & ZF; + case 2: + return !(f & CF); + case 3: + return f & CF; + case 4: + return !(f & PF); + case 5: + return f & PF; + case 6: + return !(f & SF); + case 7: + return f & SF; + default: + UNREACHABLE; + } + } + + static constexpr auto subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept { + const register16_t subtraction = operand - value - carry; + const auto result = subtraction.low; + + f = adjustHalfCarrySub(f, operand, value, result); + f = adjustOverflowSub(f, operand, value, result); + + f = setBit(f, NF); + f = setBit(f, CF, subtraction.high & CF); + f = adjustSZ(f, result); + + return result; + } + + 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]] static constexpr auto increment(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF); + const uint8_t result = operand + 1; + f = adjustSZXY(f, result); + f = setBit(f, VF, result == Bit7); + f = clearBit(f, HC, lowNibble(result)); + return result; + } + + [[nodiscard]] static constexpr auto decrement(uint8_t& f, uint8_t operand) noexcept { + f = setBit(f, NF); + f = clearBit(f, HC, lowNibble(operand)); + const uint8_t result = operand - 1; + f = adjustSZXY(f, result); + f = setBit(f, VF, result == Mask7); + return result; + } void di() noexcept; void ei() noexcept; - void retn(); - void reti(); + void retn() noexcept; + void reti() noexcept; - void returnConditionalFlag(uint8_t f, int flag); - void jrConditionalFlag(uint8_t f, int flag); - void callConditionalFlag(uint8_t f, int flag); - void jumpConditionalFlag(uint8_t f, int flag); + void returnConditionalFlag(uint8_t f, int flag) noexcept; + void jrConditionalFlag(uint8_t f, int flag) noexcept; + void callConditionalFlag(uint8_t f, int flag) noexcept; + void jumpConditionalFlag(uint8_t f, int flag) noexcept; - [[nodiscard]] register16_t sbc(uint8_t& f, register16_t operand, register16_t value); - [[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value); - [[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0); + [[nodiscard]] register16_t sbc(uint8_t& f, register16_t operand, register16_t value) noexcept; + [[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value) noexcept; + [[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0) noexcept; - [[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept; - [[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept; - [[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept; - [[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept; - [[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept; - [[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept; - [[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept; - static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept; + [[nodiscard]] static constexpr auto add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept { + const register16_t addition = operand + value + carry; + const auto result = addition.low; - [[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept; + f = adjustHalfCarryAdd(f, operand, value, result); + f = adjustOverflowAdd(f, operand, value, result); - static void bit(uint8_t& f, int n, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept; + f = clearBit(f, NF); + f = setBit(f, CF, addition.high & CF); + f = adjustSZXY(f, result); - [[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept; + return result; + } - static void scf(uint8_t& f, uint8_t operand) noexcept; - static void ccf(uint8_t& f, uint8_t operand) noexcept; - [[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept; + [[nodiscard]] static constexpr auto adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + return add(f, operand, value, f & CF); + } - void xhtl(register16_t& exchange); + [[nodiscard]] static constexpr auto sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept { + const auto subtraction = subtract(f, operand, value, carry); + f = adjustSZXY(f, subtraction); + return subtraction; + } - void blockCompare(uint8_t& f, uint8_t value, register16_t source, register16_t& counter); + [[nodiscard]] static constexpr auto sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + return sub(f, operand, value, f & CF); + } - void cpi(uint8_t& f, uint8_t value); - [[nodiscard]] bool cpir(uint8_t& f, uint8_t value); + [[nodiscard]] static constexpr auto andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + f = setBit(f, HC); + f = clearBit(f, CF | NF); + const uint8_t result = operand & value; + f = adjustSZPXY(f, result); + return result; + } - void cpd(uint8_t& f, uint8_t value); - [[nodiscard]] bool cpdr(uint8_t& f, uint8_t value); + [[nodiscard]] static constexpr auto xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + f = clearBit(f, HC | CF | NF); + const uint8_t result = operand ^ value; + f = adjustSZPXY(f, result); + return result; + } - void blockLoad(uint8_t& f, uint8_t a, register16_t source, register16_t destination, register16_t& counter); + [[nodiscard]] static constexpr auto orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + f = clearBit(f, HC | CF | NF); + const uint8_t result = operand | value; + f = adjustSZPXY(f, result); + return result; + } - void ldi(uint8_t& f, uint8_t a); - [[nodiscard]] bool ldir(uint8_t& f, uint8_t a); + static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept { + subtract(f, operand, value); + f = adjustXY(f, value); + } - void ldd(uint8_t& f, uint8_t a); - [[nodiscard]] bool lddr(uint8_t& f, uint8_t a); + [[nodiscard]] static constexpr auto rlc(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + const auto carry = operand & Bit7; + f = setBit(f, CF, carry); + const uint8_t result = (operand << 1) | (carry >> 7); + f = adjustXY(f, result); + return result; + } - void blockIn(register16_t& source, register16_t destination); + [[nodiscard]] static constexpr auto rrc(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + const auto carry = operand & Bit0; + f = setBit(f, CF, carry); + const uint8_t result = (operand >> 1) | (carry << 7); + f = adjustXY(f, result); + return result; + } - void ini(); - [[nodiscard]] bool inir(); + [[nodiscard]] static constexpr auto rl(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + const auto carry = f & CF; + f = setBit(f, CF, operand & Bit7); + const uint8_t result = (operand << 1) | carry; + f = adjustXY(f, result); + return result; + } - void ind(); - [[nodiscard]] bool indr(); + [[nodiscard]] static constexpr auto rr(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + const auto carry = f & CF; + f = setBit(f, CF, operand & Bit0); + const uint8_t result = (operand >> 1) | (carry << 7); + f = adjustXY(f, result); + return result; + } - void blockOut(register16_t source, register16_t& destination); + [[nodiscard]] static constexpr auto sla(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + f = setBit(f, CF, operand & Bit7); + const uint8_t result = operand << 1; + f = adjustXY(f, result); + return result; + } - void outi(); - [[nodiscard]] bool otir(); + [[nodiscard]] static constexpr auto sra(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + f = setBit(f, CF, operand & Bit0); + const uint8_t result = (operand >> 1) | (operand & Bit7); + f = adjustXY(f, result); + return result; + } - void outd(); - [[nodiscard]] bool otdr(); + [[nodiscard]] static constexpr auto sll(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + f = setBit(f, CF, operand & Bit7); + const uint8_t result = (operand << 1) | Bit0; + f = adjustXY(f, result); + return result; + } - [[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand) noexcept; + [[nodiscard]] static constexpr auto srl(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF | HC); + f = setBit(f, CF, operand & Bit0); + const uint8_t result = (operand >> 1) & ~Bit7; + f = adjustXY(f, result); + f = setBit(f, ZF, result); + return result; + } - void rrd(uint8_t& f, register16_t address, uint8_t& update); - void rld(uint8_t& f, register16_t address, uint8_t& update); + static constexpr void bit(uint8_t& f, int n, uint8_t operand) noexcept { + f = setBit(f, HC); + f = clearBit(f, NF); + const auto discarded = operand & Chip::bit(n); + f = adjustSZ(f, discarded); + f = clearBit(f, PF, discarded); + } - void portWrite(uint8_t port); - void portWrite(); + [[nodiscard]] static constexpr auto res(int n, uint8_t operand) noexcept { return clearBit(operand, Chip::bit(n)); } + [[nodiscard]] static constexpr auto set(int n, uint8_t operand) noexcept { return setBit(operand, Chip::bit(n)); } - uint8_t portRead(uint8_t port); - uint8_t portRead(); + [[nodiscard]] static constexpr auto daa(uint8_t& f, uint8_t operand) noexcept { + const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9); + const auto highAdjust = (f & CF) || (operand > 0x99); + + auto updated = operand; + if (f & NF) { + if (lowAdjust) + updated -= 6; + if (highAdjust) + updated -= 0x60; + } else { + if (lowAdjust) + updated += 6; + if (highAdjust) + updated += 0x60; + } + + f = (f & (CF | NF)) | (operand > 0x99 ? CF : 0) | ((operand ^ updated) & HC); + + f = adjustSZPXY(f, updated); + + return updated; + } + + static constexpr void scf(uint8_t& f, uint8_t operand) noexcept { + f = setBit(f, CF); + f = clearBit(f, HC | NF); + f = adjustXY(f, operand); + } + + static constexpr void ccf(uint8_t& f, uint8_t operand) noexcept { + f = clearBit(f, NF); + const auto carry = f & CF; + f = setBit(f, HC, carry); + f = clearBit(f, CF, carry); + f = adjustXY(f, operand); + } + + [[nodiscard]] static constexpr auto cpl(uint8_t& f, uint8_t operand) noexcept { + f = setBit(f, HC | NF); + const uint8_t result = ~operand; + f = adjustXY(f, result); + return result; + } + + void xhtl(register16_t& exchange) noexcept; + + void blockCompare(uint8_t& f, uint8_t value, register16_t source, register16_t& counter) noexcept; + + void cpi(uint8_t& f, uint8_t value) noexcept; + [[nodiscard]] bool cpir(uint8_t& f, uint8_t value) noexcept; + + void cpd(uint8_t& f, uint8_t value) noexcept; + [[nodiscard]] bool cpdr(uint8_t& f, uint8_t value) noexcept; + + void blockLoad(uint8_t& f, uint8_t a, register16_t source, register16_t destination, register16_t& counter) noexcept; + + void ldi(uint8_t& f, uint8_t a) noexcept; + [[nodiscard]] bool ldir(uint8_t& f, uint8_t a) noexcept; + + void ldd(uint8_t& f, uint8_t a) noexcept; + [[nodiscard]] bool lddr(uint8_t& f, uint8_t a) noexcept; + + void blockIn(register16_t& source, register16_t destination) noexcept; + + void ini() noexcept; + [[nodiscard]] bool inir() noexcept; + + void ind() noexcept; + [[nodiscard]] bool indr() noexcept; + + void blockOut(register16_t source, register16_t& destination) noexcept; + + void outi() noexcept; + [[nodiscard]] bool otir() noexcept; + + void outd() noexcept; + [[nodiscard]] bool otdr() noexcept; + + [[nodiscard]] static constexpr auto neg(uint8_t& f, uint8_t operand) noexcept { + f = setBit(f, PF, operand == Bit7); + f = setBit(f, CF, operand); + f = setBit(f, NF); + + const uint8_t result = (~operand + 1); // two's complement + + f = adjustHalfCarrySub(f, 0U, operand, result); + f = adjustOverflowSub(f, 0U, operand, result); + + f = adjustSZXY(f, result); + + return result; + } + + void rrd(uint8_t& f, register16_t address, uint8_t& update) noexcept; + void rld(uint8_t& f, register16_t address, uint8_t& update) noexcept; + + void portWrite(uint8_t port) noexcept; + void portWrite() noexcept; + + uint8_t portRead(uint8_t port) noexcept; + uint8_t portRead() noexcept; }; } \ No newline at end of file diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 21e7137..7fa2189 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -46,8 +46,6 @@ EightBit::Z80::Z80(const Z80& rhs) m_ix = rhs.m_ix; m_iy = rhs.m_iy; - m_refresh = rhs.m_refresh; - iv = rhs.iv; m_interruptMode = rhs.m_interruptMode; m_iff1 = rhs.m_iff1; @@ -131,23 +129,24 @@ const EightBit::register16_t& EightBit::Z80::HL() const noexcept { return m_registers[m_registerSet][HL_IDX]; } -void EightBit::Z80::pushWord(const register16_t destination) { +void EightBit::Z80::pushWord(const register16_t destination) noexcept { tick(); IntelProcessor::pushWord(destination); } -void EightBit::Z80::memoryWrite() { +void EightBit::Z80::memoryWrite() noexcept { class _Writer final { Z80& m_parent; public: - _Writer(Z80& parent) : m_parent(parent) { + _Writer(Z80& parent) noexcept + : m_parent(parent) { m_parent.WritingMemory.fire(); m_parent.tick(2); m_parent.lowerMREQ(); } - ~_Writer() { + ~_Writer() noexcept { m_parent.raiseMREQ(); m_parent.WrittenMemory.fire(); } @@ -157,12 +156,13 @@ void EightBit::Z80::memoryWrite() { IntelProcessor::memoryWrite(); } -uint8_t EightBit::Z80::memoryRead() { +uint8_t EightBit::Z80::memoryRead() noexcept { class _Reader final { Z80& m_parent; public: - _Reader(Z80& parent) : m_parent(parent) { + _Reader(Z80& parent) noexcept + : m_parent(parent) { m_parent.ReadingMemory.fire(); if (lowered(m_parent.M1())) m_parent.tick(); @@ -170,7 +170,7 @@ uint8_t EightBit::Z80::memoryRead() { m_parent.lowerMREQ(); } - ~_Reader() { + ~_Reader() noexcept { m_parent.raiseMREQ(); m_parent.ReadMemory.fire(); } @@ -180,27 +180,28 @@ uint8_t EightBit::Z80::memoryRead() { return IntelProcessor::memoryRead(); } -void EightBit::Z80::busWrite() { +void EightBit::Z80::busWrite() noexcept { tick(); _ActivateWR writer(*this); IntelProcessor::busWrite(); } -uint8_t EightBit::Z80::busRead() { +uint8_t EightBit::Z80::busRead() noexcept { tick(); _ActivateRD reader(*this); return IntelProcessor::busRead(); } -void EightBit::Z80::handleRESET() { +void EightBit::Z80::handleRESET() noexcept { IntelProcessor::handleRESET(); di(); - IV() = REFRESH() = 0; + IV() = 0; + REFRESH() = 0; SP().word = AF().word = Mask16; tick(3); } -void EightBit::Z80::handleNMI() { +void EightBit::Z80::handleNMI() noexcept { raiseNMI(); raiseHALT(); IFF2() = IFF1(); @@ -209,7 +210,7 @@ void EightBit::Z80::handleNMI() { restart(0x66); } -void EightBit::Z80::handleINT() { +void EightBit::Z80::handleINT() noexcept { IntelProcessor::handleINT(); tick(2); // 2 extra clock cycles introduced to allow the bus to settle uint8_t data; @@ -242,112 +243,45 @@ void EightBit::Z80::ei() noexcept { IFF1() = IFF2() = true; } -uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF); - const uint8_t result = operand + 1; - f = adjustSZXY(f, result); - f = setBit(f, VF, result == Bit7); - f = clearBit(f, HC, lowNibble(result)); - return result; -} - -uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) noexcept { - f = setBit(f, NF); - f = clearBit(f, HC, lowNibble(operand)); - const uint8_t result = operand - 1; - f = adjustSZXY(f, result); - f = setBit(f, VF, result == Mask7); - return result; -} - -uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept { - return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation)); -} - -uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept { - return setBit(f, HC, calculateHalfCarrySub(before, value, calculation)); -} - -uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept { - return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF); -} - -uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept { - const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative); - return setBit(f, VF, overflow); -} - -uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept { - return adjustOverflowSub(f, before & SF, value & SF, calculation & SF); -} - -uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept { - const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative); - return setBit(f, VF, overflow); -} - -bool EightBit::Z80::convertCondition(const uint8_t f, int flag) noexcept { - switch (flag) { - case 0: - return !(f & ZF); - case 1: - return f & ZF; - case 2: - return !(f & CF); - case 3: - return f & CF; - case 4: - return !(f & PF); - case 5: - return f & PF; - case 6: - return !(f & SF); - case 7: - return f & SF; - default: - UNREACHABLE; - } -} - -void EightBit::Z80::returnConditionalFlag(const uint8_t f, const int flag) { +void EightBit::Z80::returnConditionalFlag(const uint8_t f, const int flag) noexcept { tick(); if (convertCondition(f, flag)) ret(); } -void EightBit::Z80::jrConditionalFlag(const uint8_t f, const int flag) { +void EightBit::Z80::jrConditionalFlag(const uint8_t f, const int flag) noexcept { jrConditional(convertCondition(f, flag)); } -void EightBit::Z80::jumpConditionalFlag(const uint8_t f, const int flag) { +void EightBit::Z80::jumpConditionalFlag(const uint8_t f, const int flag) noexcept { jumpConditional(convertCondition(f, flag)); } -void EightBit::Z80::callConditionalFlag(const uint8_t f, const int flag) { +void EightBit::Z80::callConditionalFlag(const uint8_t f, const int flag) noexcept { callConditional(convertCondition(f, flag)); } -void EightBit::Z80::retn() { +void EightBit::Z80::retn() noexcept { ret(); IFF1() = IFF2(); } -void EightBit::Z80::reti() { +void EightBit::Z80::reti() noexcept { retn(); } -void EightBit::Z80::jr(int8_t offset) { +void EightBit::Z80::jr(int8_t offset) noexcept { IntelProcessor::jr(offset); tick(5); } -int EightBit::Z80::jrConditional(const int condition) { +int EightBit::Z80::jrConditional(const int condition) noexcept { if (!IntelProcessor::jrConditional(condition)) tick(3); return condition; } -EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand, const register16_t value) { +EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand, const register16_t value) noexcept { const auto subtraction = operand.word - value.word - (f & CF); const register16_t result = subtraction; @@ -371,7 +305,7 @@ EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand return result; } -EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand, const register16_t value) { +EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand, const register16_t value) noexcept { const auto result = add(f, operand, value, f & CF); f = clearBit(f, ZF, result.word); @@ -386,7 +320,7 @@ EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand return result; } -EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand, const register16_t value, int carry) { +EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand, const register16_t value, int carry) noexcept { const int addition = operand.word + value.word + carry; const register16_t result = addition; @@ -402,227 +336,7 @@ EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand return result; } -uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept { - - const register16_t addition = operand + value + carry; - const auto result = addition.low; - - f = adjustHalfCarryAdd(f, operand, value, result); - f = adjustOverflowAdd(f, operand, value, result); - - f = clearBit(f, NF); - f = setBit(f, CF, addition.high & CF); - f = adjustSZXY(f, result); - - return result; -} - -uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept { - return add(f, operand, value, f & CF); -} - -uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept { - - const register16_t subtraction = operand - value - carry; - const auto result = subtraction.low; - - f = adjustHalfCarrySub(f, operand, value, result); - f = adjustOverflowSub(f, operand, value, result); - - f = setBit(f, NF); - f = setBit(f, CF, subtraction.high & CF); - f = adjustSZ(f, result); - - return result; -} - -uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept { - const auto subtraction = subtract(f, operand, value, carry); - f = adjustXY(f, subtraction); - return subtraction; -} - -uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept { - return sub(f, operand, value, f & CF); -} - -uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept { - f = setBit(f, HC); - f = clearBit(f, CF | NF); - const uint8_t result = operand & value; - f = adjustSZPXY(f, result); - return result; -} - -uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept { - f = clearBit(f, HC | CF | NF); - const uint8_t result = operand ^ value; - f = adjustSZPXY(f, result); - return result; -} - -uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept { - f = clearBit(f, HC | CF | NF); - const uint8_t result = operand | value; - f = adjustSZPXY(f, result); - return result; -} - -void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept { - subtract(f, operand, value); - f = adjustXY(f, value); -} - -uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - const auto carry = operand & Bit7; - f = setBit(f, CF, carry); - const uint8_t result = (operand << 1) | (carry >> 7); - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - const auto carry = operand & Bit0; - f = setBit(f, CF, carry); - const uint8_t result = (operand >> 1) | (carry << 7); - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - const auto carry = f & CF; - f = setBit(f, CF, operand & Bit7); - const uint8_t result = (operand << 1) | carry; - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - const auto carry = f & CF; - f = setBit(f, CF, operand & Bit0); - const uint8_t result = (operand >> 1) | (carry << 7); - f = adjustXY(f, result); - return result; -} - -// - -uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - f = setBit(f, CF, operand & Bit7); - const uint8_t result = operand << 1; - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - f = setBit(f, CF, operand & Bit0); - const uint8_t result = (operand >> 1) | (operand & Bit7); - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - f = setBit(f, CF, operand & Bit7); - const uint8_t result = (operand << 1) | Bit0; - f = adjustXY(f, result); - return result; -} - -uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF | HC); - f = setBit(f, CF, operand & Bit0); - const uint8_t result = (operand >> 1) & ~Bit7; - f = adjustXY(f, result); - f = setBit(f, ZF, result); - return result; -} - -void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) noexcept { - f = setBit(f, HC); - f = clearBit(f, NF); - const auto discarded = operand & Chip::bit(n); - f = adjustSZ(f, discarded); - f = clearBit(f, PF, discarded); -} - -uint8_t EightBit::Z80::res(const int n, const uint8_t operand) noexcept { - return clearBit(operand, Chip::bit(n)); -} - -uint8_t EightBit::Z80::set(const int n, const uint8_t operand) noexcept { - return setBit(operand, Chip::bit(n)); -} - -uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) noexcept { - - f = setBit(f, PF, operand == Bit7); - f = setBit(f, CF, operand); - f = setBit(f, NF); - - const uint8_t result = (~operand + 1); // two's complement - - f = adjustHalfCarrySub(f, 0U, operand, result); - f = adjustOverflowSub(f, 0U, operand, result); - - f = adjustSZXY(f, result); - - return result; -} - -uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) noexcept { - - const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9); - const auto highAdjust = (f & CF) || (operand > 0x99); - - auto updated = operand; - if (f & NF) { - if (lowAdjust) - updated -= 6; - if (highAdjust) - updated -= 0x60; - } else { - if (lowAdjust) - updated += 6; - if (highAdjust) - updated += 0x60; - } - - f = (f & (CF | NF)) | (operand > 0x99 ? CF : 0) | ((operand ^ updated) & HC); - - f = adjustSZPXY(f, updated); - - return updated; -} - -uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) noexcept { - f = setBit(f, HC | NF); - const uint8_t result = ~operand; - f = adjustXY(f, result); - return result; -} - -void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) noexcept { - f = setBit(f, CF); - f = clearBit(f, HC | NF); - f = adjustXY(f, operand); -} - -void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) noexcept { - f = clearBit(f, NF); - const auto carry = f & CF; - f = setBit(f, HC, carry); - f = clearBit(f, CF, carry); - f = adjustXY(f, operand); -} - -void EightBit::Z80::xhtl(register16_t& exchange) { +void EightBit::Z80::xhtl(register16_t& exchange) noexcept { MEMPTR().low = IntelProcessor::memoryRead(SP()); ++BUS().ADDRESS(); MEMPTR().high = memoryRead(); @@ -635,7 +349,7 @@ void EightBit::Z80::xhtl(register16_t& exchange) { tick(2); } -void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) { +void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) noexcept { const auto contents = IntelProcessor::memoryRead(source); uint8_t result = value - contents; @@ -654,27 +368,27 @@ void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register tick(5); } -void EightBit::Z80::cpi(uint8_t& f, uint8_t value) { +void EightBit::Z80::cpi(uint8_t& f, uint8_t value) noexcept { blockCompare(f, value, HL()++, BC()); ++MEMPTR(); } -void EightBit::Z80::cpd(uint8_t& f, uint8_t value) { +void EightBit::Z80::cpd(uint8_t& f, uint8_t value) noexcept { blockCompare(f, value, HL()--, BC()); --MEMPTR(); } -bool EightBit::Z80::cpir(uint8_t& f, uint8_t value) { +bool EightBit::Z80::cpir(uint8_t& f, uint8_t value) noexcept { cpi(f, value); return (f & PF) && !(f & ZF); // See CPI } -bool EightBit::Z80::cpdr(uint8_t& f, uint8_t value) { +bool EightBit::Z80::cpdr(uint8_t& f, uint8_t value) noexcept { cpd(f, value); return (f & PF) && !(f & ZF); // See CPD } -void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) { +void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) noexcept { const auto value = IntelProcessor::memoryRead(source); IntelProcessor::memoryWrite(destination); const auto xy = a + value; @@ -685,25 +399,25 @@ void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t so tick(2); } -void EightBit::Z80::ldd(uint8_t& f, const uint8_t a) { +void EightBit::Z80::ldd(uint8_t& f, const uint8_t a) noexcept { blockLoad(f, a, HL()--, DE()--, BC()); } -void EightBit::Z80::ldi(uint8_t& f, const uint8_t a) { +void EightBit::Z80::ldi(uint8_t& f, const uint8_t a) noexcept { blockLoad(f, a, HL()++, DE()++, BC()); } -bool EightBit::Z80::ldir(uint8_t& f, const uint8_t a) { +bool EightBit::Z80::ldir(uint8_t& f, const uint8_t a) noexcept { ldi(f, a); return !!(f & PF); // See LDI } -bool EightBit::Z80::lddr(uint8_t& f, const uint8_t a) { +bool EightBit::Z80::lddr(uint8_t& f, const uint8_t a) noexcept { ldd(f, a); return !!(f & PF); // See LDD } -void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) { +void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) noexcept { MEMPTR() = BUS().ADDRESS() = source; tick(); portRead(); @@ -713,27 +427,27 @@ void EightBit::Z80::blockIn(register16_t& source, const register16_t destination F() = setBit(F(), NF); } -void EightBit::Z80::ini() { +void EightBit::Z80::ini() noexcept { blockIn(BC(), HL()++); ++MEMPTR(); } -void EightBit::Z80::ind() { +void EightBit::Z80::ind() noexcept { blockIn(BC(), HL()--); --MEMPTR(); } -bool EightBit::Z80::inir() { +bool EightBit::Z80::inir() noexcept { ini(); return !(F() & ZF); // See INI } -bool EightBit::Z80::indr() { +bool EightBit::Z80::indr() noexcept { ind(); return !(F() & ZF); // See IND } -void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) { +void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) noexcept { tick(); const auto value = IntelProcessor::memoryRead(source); destination.high = decrement(F(), destination.high); @@ -745,27 +459,27 @@ void EightBit::Z80::blockOut(const register16_t source, register16_t& destinatio F() = adjustParity(F(), ((value + L()) & Mask3) ^ B()); } -void EightBit::Z80::outi() { +void EightBit::Z80::outi() noexcept { blockOut(HL()++, BC()); ++MEMPTR(); } -void EightBit::Z80::outd() { +void EightBit::Z80::outd() noexcept { blockOut(HL()--, BC()); --MEMPTR(); } -bool EightBit::Z80::otir() { +bool EightBit::Z80::otir() noexcept { outi(); return !(F() & ZF); // See OUTI } -bool EightBit::Z80::otdr() { +bool EightBit::Z80::otdr() noexcept { outd(); return !(F() & ZF); // See OUTD } -void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) { +void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) noexcept { (MEMPTR() = BUS().ADDRESS() = address)++; const auto memory = memoryRead(); tick(4); @@ -775,7 +489,7 @@ void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) { f = clearBit(f, NF | HC); } -void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) { +void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) noexcept { (MEMPTR() = BUS().ADDRESS() = address)++; const auto memory = memoryRead(); tick(4); @@ -785,23 +499,24 @@ void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) { f = clearBit(f, NF | HC); } -void EightBit::Z80::portWrite(const uint8_t port) { +void EightBit::Z80::portWrite(const uint8_t port) noexcept { MEMPTR() = BUS().ADDRESS() = { port, A() }; BUS().DATA() = A(); portWrite(); ++MEMPTR().low; } -void EightBit::Z80::portWrite() { +void EightBit::Z80::portWrite() noexcept { class _Writer final { Z80& m_parent; public: - _Writer(Z80& parent) : m_parent(parent) { + _Writer(Z80& parent) noexcept + : m_parent(parent) { m_parent.WritingIO.fire(); } - ~_Writer() { + ~_Writer() noexcept { m_parent.WrittenIO.fire(); m_parent.tick(3); } @@ -812,22 +527,23 @@ void EightBit::Z80::portWrite() { busWrite(); } -uint8_t EightBit::Z80::portRead(const uint8_t port) { +uint8_t EightBit::Z80::portRead(const uint8_t port) noexcept { MEMPTR() = BUS().ADDRESS() = { port, A() }; ++MEMPTR().low; return portRead(); } -uint8_t EightBit::Z80::portRead() { +uint8_t EightBit::Z80::portRead() noexcept { class _Reader final { Z80& m_parent; public: - _Reader(Z80& parent) : m_parent(parent) { + _Reader(Z80& parent) noexcept + : m_parent(parent) { m_parent.ReadingIO.fire(); } - ~_Reader() { + ~_Reader() noexcept { m_parent.ReadIO.fire(); m_parent.tick(3); } @@ -840,23 +556,13 @@ uint8_t EightBit::Z80::portRead() { // -void EightBit::Z80::resetPrefixes() noexcept { - m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; -} - -// - -uint16_t EightBit::Z80::displacedAddress() noexcept { - return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement; -} - -void EightBit::Z80::fetchDisplacement() { +void EightBit::Z80::fetchDisplacement() noexcept { m_displacement = fetchByte(); } // -uint8_t EightBit::Z80::readBusDataM1() { +uint8_t EightBit::Z80::readBusDataM1() noexcept { _ActivateM1 m1(*this); return BUS().DATA(); } @@ -888,7 +594,7 @@ uint8_t EightBit::Z80::readBusDataM1() { // received from the memory is ignored and an NOP instruction is forced internally to the // CPU.The HALT acknowledge signal is active during this time indicating that the processor // is in the HALT state -uint8_t EightBit::Z80::fetchOpCode() { +uint8_t EightBit::Z80::fetchOpCode() noexcept { uint8_t returned; { _ActivateM1 m1(*this); @@ -907,18 +613,18 @@ uint8_t EightBit::Z80::fetchOpCode() { return returned; } -void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) { +void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept { (MEMPTR() = BUS().ADDRESS() = addresser())++; A() = memoryRead(); } -void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) { +void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept { (MEMPTR() = BUS().ADDRESS() = addresser())++; MEMPTR().high = BUS().DATA() = A(); memoryWrite(); } -void EightBit::Z80::readInternalRegister(reader_t reader) { +void EightBit::Z80::readInternalRegister(reader_t reader) noexcept { F() = adjustSZXY(F(), A() = reader()); F() = clearBit(F(), NF | HC); F() = setBit(F(), PF, IFF2()); @@ -963,7 +669,7 @@ EightBit::register16_t& EightBit::Z80::RP2(const int rp) noexcept { } } -uint8_t EightBit::Z80::R(const int r) { +uint8_t EightBit::Z80::R(const int r) noexcept { switch (r) { case 0: return B(); @@ -986,7 +692,7 @@ uint8_t EightBit::Z80::R(const int r) { } } -void EightBit::Z80::R(const int r, const uint8_t value) { +void EightBit::Z80::R(const int r, const uint8_t value) noexcept { switch (r) { case 0: B() = value; @@ -1017,7 +723,7 @@ void EightBit::Z80::R(const int r, const uint8_t value) { } } -void EightBit::Z80::R2(const int r, const uint8_t value) { +void EightBit::Z80::R2(const int r, const uint8_t value) noexcept { switch (r) { case 0: B() = value; @@ -1048,7 +754,7 @@ void EightBit::Z80::R2(const int r, const uint8_t value) { } } -int EightBit::Z80::step() { +int EightBit::Z80::step() noexcept { resetCycles(); ExecutingInstruction.fire(*this); if (LIKELY(powered())) { @@ -1075,7 +781,7 @@ int EightBit::Z80::step() { return cycles(); } -int EightBit::Z80::execute() { +int EightBit::Z80::execute() noexcept { const auto& decoded = getDecodedOpcode(opcode()); @@ -1097,7 +803,7 @@ int EightBit::Z80::execute() { return cycles(); } -void EightBit::Z80::executeCB(const int x, const int y, const int z) { +void EightBit::Z80::executeCB(const int x, const int y, const int z) noexcept { const bool memoryZ = z == 6; const bool indirect = (!displaced() && memoryZ) || displaced(); @@ -1170,7 +876,7 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) { } } -void EightBit::Z80::executeED(const int x, const int y, const int z, const int p, const int q) { +void EightBit::Z80::executeED(const int x, const int y, const int z, const int p, const int q) noexcept { switch (x) { case 0: @@ -1385,7 +1091,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p } } -void EightBit::Z80::executeOther(const int x, const int y, const int z, const int p, const int q) { +void EightBit::Z80::executeOther(const int x, const int y, const int z, const int p, const int q) noexcept { const bool memoryY = y == 6; const bool memoryZ = z == 6; switch (x) { diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index f086bc9..fe4c845 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -4,7 +4,7 @@ Board::Board(const Configuration& configuration) : m_configuration(configuration) {} -void Board::raisePOWER() { +void Board::raisePOWER() noexcept { EightBit::Bus::raisePOWER(); CPU().raisePOWER(); CPU().raiseRESET(); diff --git a/Z80/test/Board.h b/Z80/test/Board.h index 6cf9d13..b78d942 100644 --- a/Z80/test/Board.h +++ b/Z80/test/Board.h @@ -18,7 +18,7 @@ public: EightBit::Z80& CPU() noexcept { return m_cpu; } - void raisePOWER() final; + void raisePOWER() noexcept final; void lowerPOWER() noexcept final; void initialise() final; diff --git a/inc/BigEndianProcessor.h b/inc/BigEndianProcessor.h index b462e1f..9d3faa8 100644 --- a/inc/BigEndianProcessor.h +++ b/inc/BigEndianProcessor.h @@ -16,15 +16,15 @@ namespace EightBit { protected: BigEndianProcessor(Bus& memory); - [[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(uint8_t page, uint8_t offset) override; - void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override; + [[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override; + void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override; - [[nodiscard]] register16_t fetchWord() final; + [[nodiscard]] register16_t fetchWord() noexcept final; - void pushWord(register16_t value) final; - [[nodiscard]] register16_t popWord() final; + void pushWord(register16_t value) noexcept final; + [[nodiscard]] register16_t popWord() noexcept final; }; } diff --git a/inc/Bus.h b/inc/Bus.h index ec15630..cdec80d 100644 --- a/inc/Bus.h +++ b/inc/Bus.h @@ -33,21 +33,21 @@ namespace EightBit { virtual 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(); + [[nodiscard]] uint8_t read() noexcept; template [[nodiscard]] auto read(const T address) { ADDRESS() = address; return read(); } - void write(); - void write(uint8_t value); - template void write(const T offset, const uint8_t value) { + void write() noexcept; + void write(uint8_t value) noexcept; + template void write(const T offset, const uint8_t value) noexcept { ADDRESS() = offset; write(value); } - virtual void raisePOWER(); - virtual void lowerPOWER(); + virtual void raisePOWER() noexcept; + virtual void lowerPOWER() noexcept; virtual void initialise() = 0; diff --git a/inc/ClockedChip.h b/inc/ClockedChip.h index 979579f..c5c5693 100644 --- a/inc/ClockedChip.h +++ b/inc/ClockedChip.h @@ -16,13 +16,17 @@ namespace EightBit { [[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; } - void tick(int extra); - void tick(); + void tick(int extra = 1) noexcept { + for (int i = 0; i < extra; ++i) { + ++m_cycles; + Ticked.fire(); + } + } protected: ClockedChip() noexcept = default; - void resetCycles() noexcept; + constexpr void resetCycles() noexcept { m_cycles = 0; } private: int m_cycles = 0; diff --git a/inc/Device.h b/inc/Device.h index d9bd85b..e1d63cd 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 ()); \ diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index 4baaff7..0498beb 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -10,7 +10,7 @@ #include "EightBitCompilerDefinitions.h" #define NON_CONST_ACCESSOR(accessor, type) \ - [[nodiscard]] auto& accessor() noexcept { \ + [[nodiscard]] constexpr auto& accessor() noexcept { \ const auto& consted = *this; \ const auto& reference = consted.accessor(); \ return const_cast(reference); \ @@ -140,25 +140,25 @@ namespace EightBit { return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation); } - void handleRESET() override; + void handleRESET() noexcept 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; // - [[nodiscard]] register16_t getWord() final; - void setWord(register16_t value) final; + [[nodiscard]] register16_t getWord() noexcept final; + void setWord(register16_t value) noexcept final; // - virtual void restart(uint8_t address); - virtual int callConditional(int condition); - virtual int jumpConditional(int condition); - virtual int returnConditional(int condition); - virtual void jr(int8_t offset); - virtual int jrConditional(int condition); - void ret() override; + virtual void restart(uint8_t address) noexcept; + virtual int callConditional(int condition) noexcept; + virtual int jumpConditional(int condition) noexcept; + virtual int returnConditional(int condition) noexcept; + virtual void jr(int8_t offset) noexcept; + virtual int jrConditional(int condition) noexcept; + void ret() noexcept override; void resetWorkingRegisters(); diff --git a/inc/LittleEndianProcessor.h b/inc/LittleEndianProcessor.h index 1da3158..1ba3c63 100644 --- a/inc/LittleEndianProcessor.h +++ b/inc/LittleEndianProcessor.h @@ -17,15 +17,15 @@ namespace EightBit { protected: LittleEndianProcessor(Bus& memory); - [[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(uint8_t page, uint8_t offset) override; - void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override; + [[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override; + void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override; - [[nodiscard]] register16_t fetchWord() final; + [[nodiscard]] register16_t fetchWord() noexcept final; - 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 a5832c7..3901053 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -29,10 +29,10 @@ namespace EightBit { [[nodiscard]] constexpr auto& PC() noexcept { return m_pc; } [[nodiscard]] constexpr const auto& PC() const noexcept { return m_pc; } - int run(int limit); - virtual int step() = 0; - virtual int execute() = 0; - int execute(uint8_t value); + int run(int limit) noexcept; + virtual int step() noexcept = 0; + virtual int execute() noexcept = 0; + int execute(uint8_t value) noexcept; [[nodiscard]] virtual register16_t peekWord(register16_t address) noexcept = 0; virtual void pokeWord(register16_t address, register16_t value) noexcept = 0; @@ -46,44 +46,44 @@ 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; - uint8_t getBytePaged(uint8_t page, uint8_t offset); - void setBytePaged(uint8_t page, uint8_t offset, uint8_t value); + uint8_t getBytePaged(uint8_t page, uint8_t offset) noexcept; + void setBytePaged(uint8_t page, uint8_t offset, uint8_t value) noexcept; - uint8_t fetchByte(); + uint8_t fetchByte() 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]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) = 0; - virtual void setWordPaged(uint8_t page, uint8_t offset, register16_t value) = 0; + [[nodiscard]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept = 0; + virtual void setWordPaged(uint8_t page, uint8_t offset, 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; - 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/Signal.h b/inc/Signal.h index 699ba58..e566da2 100644 --- a/inc/Signal.h +++ b/inc/Signal.h @@ -17,7 +17,7 @@ namespace EightBit { m_delegates.push_back(functor); } - void fire(T& e = EventArgs::empty()) const { + void fire(T& e = EventArgs::empty()) const noexcept { for (auto& delegate : m_delegates) delegate(e); } diff --git a/inc/TestHarness.h b/inc/TestHarness.h index cbdf8e9..20cb7cc 100644 --- a/inc/TestHarness.h +++ b/inc/TestHarness.h @@ -17,9 +17,8 @@ namespace EightBit { template class TestHarness final { public: - TestHarness(const ConfigurationT& configuration) - : m_board(configuration) { - } + TestHarness(const ConfigurationT& configuration) noexcept + : m_board(configuration) {} ~TestHarness() { std::cout << std::dec << std::endl; @@ -55,7 +54,7 @@ namespace EightBit { return (long long)floating; } - void run() { + void run() noexcept { m_startTime = now(); m_totalCycles = m_instructions = 0L; m_startHostCycles = currentHostCycles(); diff --git a/src/BigEndianProcessor.cpp b/src/BigEndianProcessor.cpp index 53d8a99..eeebb90 100644 --- a/src/BigEndianProcessor.cpp +++ b/src/BigEndianProcessor.cpp @@ -4,44 +4,44 @@ EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) : Processor(memory) {} -EightBit::register16_t EightBit::BigEndianProcessor::getWord() { +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(const uint8_t page, const uint8_t offset) { +EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept { const auto high = getBytePaged(page, offset); ++BUS().ADDRESS().low; const auto low = memoryRead(); return { low, high }; } -void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { +void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept { setBytePaged(page, offset, value.high); ++BUS().ADDRESS().low; memoryWrite(value.low); } -EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() { +EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept { const auto high = fetchByte(); const auto low = fetchByte(); return { low, high }; } -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 1924b79..812868f 100644 --- a/src/Bus.cpp +++ b/src/Bus.cpp @@ -4,24 +4,24 @@ #include "../inc/IntelHexFile.h" #include "../inc/EightBitCompilerDefinitions.h" -void EightBit::Bus::raisePOWER() {} +void EightBit::Bus::raisePOWER() noexcept {} -void EightBit::Bus::lowerPOWER() {} +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(); } -void EightBit::Bus::write(const uint8_t value) { +void EightBit::Bus::write(const uint8_t value) noexcept { DATA() = value; write(); } diff --git a/src/ClockedChip.cpp b/src/ClockedChip.cpp index 145d757..bb34757 100644 --- a/src/ClockedChip.cpp +++ b/src/ClockedChip.cpp @@ -6,20 +6,6 @@ EightBit::ClockedChip::ClockedChip(const ClockedChip& rhs) m_cycles = rhs.m_cycles; } -void EightBit::ClockedChip::tick(const int extra) { - for (int i = 0; i < extra; ++i) - tick(); -} - -void EightBit::ClockedChip::tick() { - ++m_cycles; - Ticked.fire(); -} - -void EightBit::ClockedChip::resetCycles() noexcept { - m_cycles = 0; -} - bool EightBit::ClockedChip::operator==(const EightBit::ClockedChip& rhs) const { return Device::operator==(rhs) diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp index b2e9baa..56dba9e 100644 --- a/src/IntelProcessor.cpp +++ b/src/IntelProcessor.cpp @@ -34,59 +34,59 @@ void EightBit::IntelProcessor::resetWorkingRegisters() { DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor); -void EightBit::IntelProcessor::handleRESET() { +void EightBit::IntelProcessor::handleRESET() noexcept { Processor::handleRESET(); PC() = 0; } -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::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 { call(MEMPTR() = { address, 0 }); } -int EightBit::IntelProcessor::callConditional(const int condition) { +int EightBit::IntelProcessor::callConditional(const int condition) noexcept { MEMPTR() = fetchWord(); if (condition) call(MEMPTR()); return condition; } -int EightBit::IntelProcessor::jumpConditional(const int condition) { +int EightBit::IntelProcessor::jumpConditional(const int condition) noexcept { MEMPTR() = fetchWord(); if (condition) jump(MEMPTR()); return condition; } -int EightBit::IntelProcessor::returnConditional(const int condition) { +int EightBit::IntelProcessor::returnConditional(const int condition) noexcept { if (condition) ret(); return condition; } -void EightBit::IntelProcessor::jr(const int8_t offset) { +void EightBit::IntelProcessor::jr(const int8_t offset) noexcept { jump(MEMPTR() = PC() + offset); } -int EightBit::IntelProcessor::jrConditional(const int condition) { +int EightBit::IntelProcessor::jrConditional(const int condition) noexcept { const auto offsetAddress = PC()++; if (condition) { const auto offset = memoryRead(offsetAddress); @@ -95,7 +95,7 @@ int EightBit::IntelProcessor::jrConditional(const int condition) { return condition; } -void EightBit::IntelProcessor::ret() { +void EightBit::IntelProcessor::ret() noexcept { Processor::ret(); MEMPTR() = PC(); } diff --git a/src/LittleEndianProcessor.cpp b/src/LittleEndianProcessor.cpp index 271778a..3472b6a 100644 --- a/src/LittleEndianProcessor.cpp +++ b/src/LittleEndianProcessor.cpp @@ -7,44 +7,44 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) : 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(const uint8_t page, const uint8_t offset) { +EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept { const auto low = getBytePaged(page, offset); ++BUS().ADDRESS().low; const auto high = memoryRead(); return { low, high }; } -void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { +void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept { setBytePaged(page, offset, value.low); ++BUS().ADDRESS().low; memoryWrite(value.high); } -EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() { +EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept { const auto low = fetchByte(); const auto high = fetchByte(); return { low, high }; } -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 e2b21b5..adbafb2 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -16,80 +16,80 @@ EightBit::Processor::Processor(const Processor& rhs) 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(); } -uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) { +uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) noexcept { return memoryRead(register16_t(offset, page)); } -void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) { +void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) noexcept { memoryWrite(register16_t(offset, page), value); } -uint8_t EightBit::Processor::fetchByte() { +uint8_t EightBit::Processor::fetchByte() noexcept { return memoryRead(PC()++); } -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); } -int EightBit::Processor::run(const int limit) { +int EightBit::Processor::run(const int limit) noexcept { int current = 0; while (LIKELY(powered() && (current < limit))) current += step(); return current; } -int EightBit::Processor::execute(const uint8_t value) { +int EightBit::Processor::execute(const uint8_t value) noexcept { opcode() = value; return execute(); } @@ -98,12 +98,12 @@ void EightBit::Processor::jump(const register16_t destination) noexcept { 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()); }