diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 281e97a..b0208ca 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -21,9 +21,9 @@ namespace EightBit { Signal ExecutingInstruction; bool isInterruptable() const; - int interrupt(uint8_t value); + virtual int execute(uint8_t opcode); int step(); virtual register16_t& AF() override { @@ -32,17 +32,9 @@ namespace EightBit { return af; } - virtual register16_t& BC() override { - return bc; - } - - virtual register16_t& DE() override { - return de; - } - - virtual register16_t& HL() override { - return hl; - } + virtual register16_t& BC() override { return bc; } + virtual register16_t& DE() override { return de; } + virtual register16_t& HL() override { return hl; } virtual void initialise(); @@ -159,11 +151,9 @@ namespace EightBit { static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0); - virtual int execute(uint8_t opcode); void execute(int x, int y, int z, int p, int q); static void increment(uint8_t& f, uint8_t& operand); - static void decrement(uint8_t& f, uint8_t& operand); bool returnConditionalFlag(uint8_t& f, int flag); diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index aab027f..5341558 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" #include "Intel8080.h" -#include "Memory.h" -#include "Disassembler.h" +#pragma region Reset and initialisation EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports) : IntelProcessor(memory), @@ -16,6 +15,8 @@ void EightBit::Intel8080::initialise() { AF().word = BC().word = DE().word = HL().word = 0; } +#pragma endregion Reset and initialisation + #pragma region Interrupt routines void EightBit::Intel8080::di() { @@ -279,12 +280,18 @@ void EightBit::Intel8080::in() { #pragma endregion I/O instructions +#pragma region Controlled instruction execution + int EightBit::Intel8080::step() { ExecutingInstruction.fire(*this); cycles = 0; return fetchExecute(); } +#pragma endregion Controlled instruction execution + +#pragma region Instruction decode and execution + int EightBit::Intel8080::execute(uint8_t opcode) { const auto& decoded = getDecodedOpcode(opcode); @@ -639,3 +646,5 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { break; } } + +#pragma endregion Instruction decode and execution diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index ca02dc2..3364387 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -21,31 +21,14 @@ namespace EightBit { Signal ExecutingInstruction; - void stop() { m_stopped = true; } - void start() { m_stopped = false; } - bool stopped() const { return m_stopped; } - - bool& IME() { return m_ime; } - - void di(); - void ei(); - virtual register16_t& AF() override { af.low &= 0xf0; return af; } - virtual register16_t& BC() override { - return bc; - } - - virtual register16_t& DE() override { - return de; - } - - virtual register16_t& HL() override { - return hl; - } + virtual register16_t& BC() override { return bc; } + virtual register16_t& DE() override { return de; } + virtual register16_t& HL() override { return hl; } virtual void reset(); virtual void initialise(); @@ -53,23 +36,11 @@ namespace EightBit { static int framesPerSecond() { return 60; } static int cyclesPerFrame() { return cyclesPerSecond() / framesPerSecond(); } - int runRasterLines() { - m_bus.resetLY(); - int cycles = 0; - for (int line = 0; line < Display::RasterHeight; ++line) - cycles += runRasterLine(); - return cycles; - } + int runRasterLines(); + int runRasterLine(); + int runVerticalBlankLines(); - int runVerticalBlankLines() { - m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank); - int cycles = 0; - for (int line = 0; line < (Bus::TotalLineCount - Display::RasterHeight); ++line) - cycles += runRasterLine(); - return cycles; - } - - int run(int limit); + int singleStep(); protected: virtual int execute(uint8_t opcode); @@ -84,21 +55,14 @@ namespace EightBit { register16_t hl; bool m_ime; + bool m_stopped; bool m_prefixCB; - bool m_stopped; - static int cyclesPerSecond() { return 4 * 1024 * 1024; } static int cyclesPerLine() { return cyclesPerFrame() / Bus::TotalLineCount; } - int runRasterLine() { - auto cycles = run(cyclesPerLine()); - m_bus.incrementLY(); - if ((m_bus.peekRegister(Bus::STAT) & Processor::Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY))) - m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); - return cycles; - } + bool& IME() { return m_ime; } uint8_t R(int r, uint8_t& a) { switch (r) { @@ -203,6 +167,13 @@ namespace EightBit { static void increment(uint8_t& f, uint8_t& operand); static void decrement(uint8_t& f, uint8_t& operand); + void stop() { m_stopped = true; } + void start() { m_stopped = false; } + bool stopped() const { return m_stopped; } + + void di(); + void ei(); + void reti(); bool jrConditionalFlag(uint8_t& f, int flag); diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 91a0640..c74e9ca 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -2,13 +2,14 @@ #include "LR35902.h" // based on http://www.z80.info/decoding.htm -// Half carry flag help from https://github.com/oubiwann/z80 + +#pragma region Reset and initialisation EightBit::LR35902::LR35902(Bus& memory) -: IntelProcessor(memory), - m_bus(memory), - m_ime(false), - m_prefixCB(false) { + : IntelProcessor(memory), + m_bus(memory), + m_ime(false), + m_prefixCB(false) { } void EightBit::LR35902::reset() { @@ -29,6 +30,8 @@ void EightBit::LR35902::initialise() { m_prefixCB = false; } +#pragma endregion Reset and initialisation + #pragma region Interrupt routines void EightBit::LR35902::di() { @@ -328,40 +331,66 @@ void EightBit::LR35902::ccf(uint8_t& a, uint8_t& f) { #pragma endregion Miscellaneous instructions -int EightBit::LR35902::run(int limit) { +#pragma region Controlled instruction execution + +int EightBit::LR35902::runRasterLines() { + m_bus.resetLY(); + int cycles = 0; + for (int line = 0; line < Display::RasterHeight; ++line) + cycles += runRasterLine(); + return cycles; +} + +int EightBit::LR35902::runRasterLine() { + auto cycles = run(cyclesPerLine()); + m_bus.incrementLY(); + if ((m_bus.peekRegister(Bus::STAT) & Processor::Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY))) + m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); + return cycles; +} + +int EightBit::LR35902::runVerticalBlankLines() { + m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank); + int cycles = 0; + for (int line = 0; line < (Bus::TotalLineCount - Display::RasterHeight); ++line) + cycles += runRasterLine(); + return cycles; +} + +int EightBit::LR35902::singleStep() { + int current = 0; - do { - auto interruptEnable = m_bus.peekRegister(Bus::IE); - auto interruptFlags = m_bus.peekRegister(Bus::IF); - auto ime = IME(); - auto masked = interruptEnable & interruptFlags; - if (masked) { - if (ime) { - m_bus.pokeRegister(Bus::IF, 0); - } else { - if (isHalted()) - proceed(); - } - } + auto interruptEnable = m_bus.peekRegister(Bus::IE); + auto interruptFlags = m_bus.peekRegister(Bus::IF); + auto ime = IME(); - if (ime && (masked & Bus::Interrupts::VerticalBlank)) { - current += interrupt(0x40); - } else if (ime && (masked & Bus::Interrupts::DisplayControlStatus)) { - current += interrupt(0x48); - } else if (ime && (masked & Bus::Interrupts::TimerOverflow)) { - current += interrupt(0x50); - } else if (ime && (masked & Bus::Interrupts::SerialTransfer)) { - current += interrupt(0x58); - } else if (ime && (masked & Bus::Interrupts::Keypad)) { - current += interrupt(0x60); + auto masked = interruptEnable & interruptFlags; + if (masked) { + if (ime) { + m_bus.pokeRegister(Bus::IF, 0); } else { - current += isHalted() ? 1 : step(); + if (isHalted()) + proceed(); } + } - m_bus.checkTimers(current); + if (ime && (masked & Bus::Interrupts::VerticalBlank)) { + current += interrupt(0x40); + } else if (ime && (masked & Bus::Interrupts::DisplayControlStatus)) { + current += interrupt(0x48); + } else if (ime && (masked & Bus::Interrupts::TimerOverflow)) { + current += interrupt(0x50); + } else if (ime && (masked & Bus::Interrupts::SerialTransfer)) { + current += interrupt(0x58); + } else if (ime && (masked & Bus::Interrupts::Keypad)) { + current += interrupt(0x60); + } else { + current += isHalted() ? 1 : step(); + } + + m_bus.checkTimers(current); - } while (current < limit); return current; } @@ -372,6 +401,10 @@ int EightBit::LR35902::step() { return fetchExecute(); } +#pragma endregion Controlled instruction execution + +#pragma region Instruction decode and execution + int EightBit::LR35902::execute(uint8_t opcode) { const auto& decoded = getDecodedOpcode(opcode); @@ -864,4 +897,6 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) { } break; } -} \ No newline at end of file +} + +#pragma endregion Instruction decode and execution diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 549c6bb..7a7819a 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -42,11 +42,16 @@ namespace EightBit { }; MOS6502(Memory& memory); - virtual ~MOS6502(); Signal ExecutingInstruction; Signal ExecutedInstruction; + virtual void triggerIRQ(); + virtual void triggerNMI(); + + virtual int execute(uint8_t opcode); + int step(); + uint8_t& X() { return x; } uint8_t& Y() { return y; } uint8_t& A() { return a; } @@ -54,23 +59,8 @@ namespace EightBit { uint8_t& P() { return p; } virtual void initialise(); - - virtual int step(); - virtual void reset(); - virtual void triggerIRQ(); - virtual void triggerNMI(); - - void getWord(register16_t& output); - void getWord(uint16_t offset, register16_t& output); - void getWord(const register16_t& offset, register16_t& output); - - protected: - virtual void interrupt(uint16_t vector); - - virtual int execute(uint8_t opcode); - private: void adjustZero(uint8_t datum) { clearFlag(P(), ZF, datum); } void adjustNegative(uint8_t datum) { setFlag(P(), NF, datum & NF); } @@ -80,9 +70,15 @@ namespace EightBit { adjustNegative(datum); } + void getWord(register16_t& output); + void getWord(uint16_t offset, register16_t& output); + void getWord(const register16_t& offset, register16_t& output); + virtual void push(uint8_t value) override; virtual uint8_t pop() override; + void interrupt(uint16_t vector); + #pragma region 6502 addressing modes #pragma region Addresses diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 73e68c2..13e5759 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -24,9 +24,6 @@ EightBit::MOS6502::MOS6502(Memory& memory) }; } -EightBit::MOS6502::~MOS6502() { -} - void EightBit::MOS6502::initialise() { Processor::initialise(); diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index 7fab149..de6932a 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -326,10 +326,7 @@ void Fuse::TestRunner::run() { initialise(); auto allowedCycles = m_test.registerState.tstates; try { - auto cycles = 0; - do { - cycles += m_cpu.step(); - } while (allowedCycles > cycles); + m_cpu.run(allowedCycles); check(); } catch (std::logic_error& error) { m_unimplemented = true; diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 85a6a23..37bc9cf 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -46,9 +46,6 @@ namespace EightBit { Signal ExecutingInstruction; - void di(); - void ei(); - int interruptMaskable(uint8_t value) { return interrupt(true, value); } int interruptMaskable() { return interruptMaskable(0); } int interruptNonMaskable() { return interrupt(false, 0); } @@ -102,6 +99,12 @@ namespace EightBit { virtual void initialise(); protected: + virtual int fetchExecute() override { + M1() = true; + return IntelProcessor::fetchExecute(); + } + + private: InputOutput& m_ports; enum { BC_IDX, DE_IDX, HL_IDX }; @@ -132,11 +135,6 @@ namespace EightBit { int8_t m_displacement; bool m_displaced; - virtual int fetchExecute() override{ - M1() = true; - return IntelProcessor::fetchExecute(); - } - uint16_t displacedAddress() { assert(m_displaced); return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement; @@ -326,6 +324,9 @@ namespace EightBit { static void increment(uint8_t& f, uint8_t& operand); static void decrement(uint8_t& f, uint8_t& operand); + void di(); + void ei(); + void retn(); void reti(); diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 51751b4..8fd1939 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -2,7 +2,8 @@ #include "Z80.h" // based on http://www.z80.info/decoding.htm -// Half carry flag help from https://github.com/oubiwann/z80 + +#pragma region Reset and initialisation EightBit::Z80::Z80(Memory& memory, InputOutput& ports) : IntelProcessor(memory), @@ -63,6 +64,8 @@ void EightBit::Z80::initialise() { m_prefixFD = false; } +#pragma endregion Reset and initialisation + #pragma region Interrupt routines void EightBit::Z80::di() { @@ -748,6 +751,8 @@ void EightBit::Z80::readPort() { #pragma endregion I/O instructions +#pragma region Controlled instruction execution + int EightBit::Z80::step() { ExecutingInstruction.fire(*this); m_displaced = m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; @@ -755,6 +760,10 @@ int EightBit::Z80::step() { return fetchExecute(); } +#pragma endregion Controlled instruction execution + +#pragma region Instruction decode and execution + int EightBit::Z80::execute(uint8_t opcode) { if (!M1()) @@ -1547,4 +1556,6 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) { } break; } -} \ No newline at end of file +} + +#pragma endregion Instruction decode and execution diff --git a/inc/Processor.h b/inc/Processor.h index 32a931f..bff86f0 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -65,6 +65,10 @@ namespace EightBit { void reset(); + virtual int run(int limit); + virtual int singleStep(); + virtual int step() = 0; + virtual int execute(uint8_t opcode) = 0; protected: diff --git a/src/Processor.cpp b/src/Processor.cpp index 19d952d..53f10fa 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -15,3 +15,15 @@ void EightBit::Processor::reset() { void EightBit::Processor::initialise() { reset(); } + +int EightBit::Processor::run(int limit) { + int current = 0; + do { + current += singleStep(); + } while (current < limit); + return current; +} + +int EightBit::Processor::singleStep() { + return step(); +}