From 3fc3b95bbdf47529cf2282419fc626f5c572cf4c Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Mon, 2 Mar 2026 10:49:50 +0000 Subject: [PATCH] A step closer to the .net implementation --- Z80/inc/Z80.h | 8 ++++-- Z80/src/Z80.cpp | 70 ++++++++++++++++++++++++++--------------------- inc/Processor.h | 3 +- src/Processor.cpp | 10 +++++++ 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 85ab1db..72097c2 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -76,7 +76,7 @@ namespace EightBit { bool operator==(const Z80& rhs) const; void execute() noexcept final; - int step() noexcept final; + void poweredStep() noexcept final; [[nodiscard]] const register16_t& AF() const noexcept final; [[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); } @@ -147,6 +147,10 @@ namespace EightBit { int jrConditional(int condition) noexcept final; private: + bool m_interruptPending = false; + bool m_nonMaskableInterruptPending = false; + bool m_resetPending = false; + InputOutput& m_ports; enum { BC_IDX, DE_IDX, HL_IDX }; @@ -193,7 +197,7 @@ namespace EightBit { } void fetchDisplacement() noexcept; - [[nodiscard]] uint8_t fetchOpCode() noexcept; + [[nodiscard]] uint8_t fetchInstruction() noexcept; uint8_t readBusDataM1() noexcept; diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 5fbe294..d85393a 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -26,13 +26,23 @@ EightBit::Z80::Z80(Bus& bus, InputOutput& ports) IX() = IY() = Mask16; resetWorkingRegisters(); - - resetPrefixes(); }); RaisedM1.connect([this](EventArgs) { ++REFRESH(); }); + + LoweredRESET.connect([this](EventArgs) { + m_resetPending = true; + }); + + LoweredNMI.connect([this](EventArgs) { + m_nonMaskableInterruptPending = true; + }); + + LoweredINT.connect([this](EventArgs) { + m_interruptPending = true; + }); } EightBit::Z80::Z80(const Z80& rhs) @@ -660,7 +670,7 @@ uint8_t EightBit::Z80::readBusDataM1() noexcept { // 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() noexcept { +uint8_t EightBit::Z80::fetchInstruction() noexcept { uint8_t returned; { _ActivateM1 m1(*this); @@ -820,32 +830,30 @@ void EightBit::Z80::R2(const int r, const uint8_t value) noexcept { } } -int EightBit::Z80::step() noexcept { - resetCycles(); - ExecutingInstruction.fire(); - if (LIKELY(powered())) { - resetPrefixes(); - bool handled = false; - if (lowered(RESET())) { - handleRESET(); - handled = true; - } else if (lowered(NMI())) { - handleNMI(); - handled = true; - } else if (lowered(INT())) { - raiseINT(); - raiseHALT(); - if (IFF1()) { - handleINT(); - handled = true; - } +void EightBit::Z80::poweredStep() noexcept { + + m_modifiedF = 0; + m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; + + if (m_resetPending) { + m_resetPending = false; + handleRESET(); + return; + } else if (m_nonMaskableInterruptPending) { + m_nonMaskableInterruptPending = false; + handleNMI(); + return; + } else if (m_interruptPending) { + m_interruptPending = false; + if (IFF1()) { + handleINT(); + return; } - if (!handled) - IntelProcessor::execute(fetchOpCode()); } - ExecutedInstruction.fire(); - ASSUME(cycles() > 0); - return cycles(); + + IntelProcessor::execute(fetchInstruction()); + + Q() = m_modifiedF; } void EightBit::Z80::execute() noexcept { @@ -1419,7 +1427,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in fetchDisplacement(); IntelProcessor::execute(fetchByte()); } else { - IntelProcessor::execute(fetchOpCode()); + IntelProcessor::execute(fetchInstruction()); } break; case 2: // OUT (n),A @@ -1460,15 +1468,15 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in break; case 1: // DD prefix m_prefixDD = true; - IntelProcessor::execute(fetchOpCode()); + IntelProcessor::execute(fetchInstruction()); break; case 2: // ED prefix m_prefixED = true; - IntelProcessor::execute(fetchOpCode()); + IntelProcessor::execute(fetchInstruction()); break; case 3: // FD prefix m_prefixFD = true; - IntelProcessor::execute(fetchOpCode()); + IntelProcessor::execute(fetchInstruction()); break; default: UNREACHABLE; diff --git a/inc/Processor.h b/inc/Processor.h index e03c635..f620f41 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -40,7 +40,8 @@ namespace EightBit { [[nodiscard]] constexpr const auto& intermediate() const noexcept { return m_intermediate; } int run(int limit) noexcept; - virtual int step() noexcept = 0; + virtual int step() noexcept; + virtual void poweredStep() noexcept = 0; virtual void execute() noexcept = 0; void execute(uint8_t value) noexcept; diff --git a/src/Processor.cpp b/src/Processor.cpp index adbd22d..d4d3d38 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -94,6 +94,16 @@ void EightBit::Processor::setWord(const register16_t address, const register16_t setWord(value); } +int EightBit::Processor::step() noexcept { + resetCycles(); + ExecutingInstruction.fire(); + if (LIKELY(powered())) + poweredStep(); + ExecutedInstruction.fire(); + ASSUME(cycles() > 0); + return cycles(); +} + int EightBit::Processor::run(const int limit) noexcept { int current = 0; while (LIKELY(powered() && (current < limit)))