From 1edabd79f32990a04ae03a8396bd3e1b045e7757 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 10 Dec 2017 21:41:48 +0000 Subject: [PATCH] More pinout oriented method of executing instructions (especially interrupts) Signed-off-by: Adrian Conlon --- Intel8080/inc/Intel8080.h | 26 ++++++------- Intel8080/src/Intel8080.cpp | 11 ++++-- Intel8080/test/Board.cpp | 21 +++++------ Intel8080/test/Board.h | 2 +- LR35902/fusetest_LR35902/FuseTestRunner.cpp | 3 +- LR35902/inc/LR35902.h | 31 +++++++++------- LR35902/src/GameBoyBus.cpp | 2 +- LR35902/src/LR35902.cpp | 40 +++++++++++++------- M6502/inc/mos6502.h | 27 ++++++-------- M6502/src/mos6502.cpp | 41 ++++++++++++++------- M6502/test_M6502/Board.cpp | 30 +++++++-------- Z80/fusetest_Z80/FuseTestRunner.cpp | 8 +--- Z80/fusetest_Z80/FuseTestRunner.h | 6 +-- Z80/inc/Z80.h | 23 +++++------- Z80/src/Z80.cpp | 36 ++++++++++-------- Z80/test/Board.cpp | 8 ++-- inc/IntelProcessor.h | 19 ++++------ inc/Processor.h | 40 ++++++++++++++------ inc/TestHarness.h | 5 ++- src/IntelProcessor.cpp | 7 +--- src/Processor.cpp | 11 ++++-- 21 files changed, 217 insertions(+), 180 deletions(-) diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 061a5cf..199b610 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -12,7 +12,7 @@ #include namespace EightBit { - class Intel8080 : public IntelProcessor { + class Intel8080 final : public IntelProcessor { public: enum StatusBits { SF = Bit7, @@ -26,28 +26,26 @@ namespace EightBit { Signal ExecutingInstruction; - bool& INT() { return m_intLine; } + virtual int execute(uint8_t opcode) final; + virtual int step() final; - virtual int execute(uint8_t opcode); - int step(); + virtual register16_t& AF() final; + virtual register16_t& BC() final; + virtual register16_t& DE() final; + virtual register16_t& HL() final; - virtual register16_t& AF() override; - virtual register16_t& BC() override; - virtual register16_t& DE() override; - virtual register16_t& HL() override; - - virtual void reset() override; + protected: + virtual void reset() final; private: bool m_interruptEnable = false; - bool m_intLine = false; InputOutput& m_ports; register16_t af; - register16_t bc; - register16_t de; - register16_t hl; + register16_t bc = { { 0xff, 0xff } }; + register16_t de = { { 0xff, 0xff } }; + register16_t hl = { { 0xff, 0xff } }; uint8_t R(int r, uint8_t a) { switch (r) { diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index 1f92a0b..276d390 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -4,7 +4,6 @@ EightBit::Intel8080::Intel8080(Bus& bus, InputOutput& ports) : IntelProcessor(bus), m_ports(ports) { - bc.word = de.word = hl.word = Mask16; } EightBit::register16_t& EightBit::Intel8080::AF() { @@ -27,7 +26,6 @@ EightBit::register16_t& EightBit::Intel8080::HL() { void EightBit::Intel8080::reset() { IntelProcessor::reset(); - INT() = false; di(); } @@ -272,13 +270,16 @@ int EightBit::Intel8080::step() { ExecutingInstruction.fire(*this); resetCycles(); if (LIKELY(powered())) { - if (UNLIKELY(INT())) { - INT() = false; + if (UNLIKELY(lowered(INT()))) { + raise(HALT()); + raise(INT()); if (m_interruptEnable) { di(); return execute(BUS().DATA()); } } + if (UNLIKELY(lowered(HALT()))) + return execute(0); // NOP return execute(fetchByte()); } return cycles(); @@ -326,6 +327,8 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) { add(f, HL(), RP(p)); addCycles(11); break; + default: + UNREACHABLE; } break; case 2: // Indirect loading diff --git a/Intel8080/test/Board.cpp b/Intel8080/test/Board.cpp index 01b3ebf..d0c5dfc 100644 --- a/Intel8080/test/Board.cpp +++ b/Intel8080/test/Board.cpp @@ -6,7 +6,6 @@ Board::Board(const Configuration& configuration) : m_configuration(configuration), - m_ram(0x10000), m_cpu(EightBit::Intel8080(*this, m_ports)) { } @@ -30,15 +29,15 @@ void Board::initialise() { m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); } - m_cpu.initialise(); - m_cpu.PC() = m_configuration.getStartAddress(); + CPU().powerOn(); + CPU().PC() = m_configuration.getStartAddress(); } void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) { - auto pc = m_cpu.PC(); + auto pc = CPU().PC(); switch (pc.word) { case 0x0: // CP/M warm start - m_cpu.halt(); + CPU().powerOff(); if (m_configuration.isProfileMode()) { m_profiler.dump(); } @@ -52,15 +51,15 @@ void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) { } void Board::bdos() { - auto c = m_cpu.C(); + auto c = CPU().C(); switch (c) { case 0x2: { - auto character = m_cpu.E(); + auto character = CPU().E(); std::cout << character; break; } case 0x9: - for (uint16_t i = m_cpu.DE().word; peek(i) != '$'; ++i) { + for (uint16_t i = CPU().DE().word; peek(i) != '$'; ++i) { std::cout << peek(i); } break; @@ -69,7 +68,7 @@ void Board::bdos() { void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) { - const auto pc = m_cpu.PC(); + const auto pc = CPU().PC(); m_profiler.addAddress(pc.word); m_profiler.addInstruction(peek(pc.word)); @@ -78,8 +77,8 @@ void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) { void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080&) { std::cerr - << EightBit::Disassembler::state(m_cpu) + << EightBit::Disassembler::state(CPU()) << "\t" - << m_disassembler.disassemble(m_cpu) + << m_disassembler.disassemble(CPU()) << '\n'; } diff --git a/Intel8080/test/Board.h b/Intel8080/test/Board.h index 67c0cfd..840fccd 100644 --- a/Intel8080/test/Board.h +++ b/Intel8080/test/Board.h @@ -26,7 +26,7 @@ protected: private: const Configuration& m_configuration; - EightBit::Ram m_ram; + EightBit::Ram m_ram = 0x10000; EightBit::InputOutput m_ports; EightBit::Intel8080 m_cpu; EightBit::Disassembler m_disassembler; diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.cpp b/LR35902/fusetest_LR35902/FuseTestRunner.cpp index 9705a43..759f19c 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.cpp +++ b/LR35902/fusetest_LR35902/FuseTestRunner.cpp @@ -9,16 +9,15 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte m_cpu(*this), m_failed(false), m_unimplemented(false) { - m_cpu.initialise(); } // void Fuse::TestRunner::initialise() { + m_cpu.powerOn(); disableGameRom(); initialiseRegisters(); initialiseMemory(); - m_cpu.powerOn(); } void Fuse::TestRunner::initialiseRegisters() { diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index 2c71c51..abb44ff 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -12,7 +12,7 @@ namespace EightBit { class Bus; - class LR35902 : public IntelProcessor { + class LR35902 final : public IntelProcessor { public: enum StatusBits { ZF = Bit7, @@ -30,30 +30,29 @@ namespace EightBit { return cycles() * 4; } - virtual register16_t& AF() override { + virtual register16_t& AF() final { 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 void reset() override; + virtual register16_t& BC() final { return bc; } + virtual register16_t& DE() final { return de; } + virtual register16_t& HL() final { return hl; } int singleStep(); protected: - virtual int execute(uint8_t opcode); - int step(); + virtual void reset() final; + virtual int execute(uint8_t opcode) final; + virtual int step() final; private: Bus& m_bus; - register16_t af; - register16_t bc; - register16_t de; - register16_t hl; + register16_t af = { { 0xff, 0xff } }; + register16_t bc = { { 0xff, 0xff } }; + register16_t de = { { 0xff, 0xff } }; + register16_t hl = { { 0xff, 0xff } }; bool m_ime = false; bool m_stopped = false; @@ -80,6 +79,8 @@ namespace EightBit { return getByte(HL()); case 7: return a; + default: + UNREACHABLE; } throw std::logic_error("Unhandled registry mechanism"); } @@ -110,6 +111,8 @@ namespace EightBit { case 7: a = value; break; + default: + UNREACHABLE; } } @@ -157,7 +160,7 @@ namespace EightBit { static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0); - int interrupt(uint8_t value); +// int interrupt(uint8_t value); void executeCB(int x, int y, int z, int p, int q); void executeOther(int x, int y, int z, int p, int q); diff --git a/LR35902/src/GameBoyBus.cpp b/LR35902/src/GameBoyBus.cpp index 11b66c9..8576eb5 100644 --- a/LR35902/src/GameBoyBus.cpp +++ b/LR35902/src/GameBoyBus.cpp @@ -12,7 +12,7 @@ EightBit::GameBoy::Bus::Bus() void EightBit::GameBoy::Bus::reset() { IO().reset(); - CPU().initialise(); + LR35902::lower(CPU().RESET()); } void EightBit::GameBoy::Bus::loadBootRom(const std::string& path) { diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index e66253f..95c54b8 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -24,12 +24,6 @@ void EightBit::GameBoy::LR35902::ei() { IME() = true; } -int EightBit::GameBoy::LR35902::interrupt(uint8_t value) { - di(); - restart(value); - return 4; -} - void EightBit::GameBoy::LR35902::increment(uint8_t& f, uint8_t& operand) { clearFlag(f, NF); adjustZero(f, ++operand); @@ -304,19 +298,24 @@ int EightBit::GameBoy::LR35902::singleStep() { } if (ime && (masked & IoRegisters::Interrupts::VerticalBlank)) { - current += interrupt(0x40); + lower(INT()); + BUS().placeDATA(0x40); } else if (ime && (masked & IoRegisters::Interrupts::DisplayControlStatus)) { - current += interrupt(0x48); + lower(INT()); + BUS().placeDATA(0x48); } else if (ime && (masked & IoRegisters::Interrupts::TimerOverflow)) { - current += interrupt(0x50); + lower(INT()); + BUS().placeDATA(0x50); } else if (ime && (masked & IoRegisters::Interrupts::SerialTransfer)) { - current += interrupt(0x58); + lower(INT()); + BUS().placeDATA(0x58); } else if (ime && (masked & IoRegisters::Interrupts::KeypadPressed)) { - current += interrupt(0x60); - } else { - current += halted() ? 1 : step(); + lower(INT()); + BUS().placeDATA(0x60); } + current += step(); + m_bus.IO().checkTimers(current); m_bus.IO().transferDma(); @@ -327,7 +326,20 @@ int EightBit::GameBoy::LR35902::step() { ExecutingInstruction.fire(*this); m_prefixCB = false; resetCycles(); - const auto ran = execute(fetchByte()); + int ran = 0; + if (LIKELY(powered())) { + if (UNLIKELY(lowered(INT()))) { + raise(HALT()); + raise(INT()); + di(); + restart(BUS().DATA()); + ran = 4; + } else if (UNLIKELY(lowered(HALT()))) { + ran = execute(0); // NOP + } else { + ran = execute(fetchByte()); + } + } ExecutedInstruction.fire(*this); return ran; } diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 12e7964..c1cb236 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -11,17 +11,15 @@ #include namespace EightBit { - class MOS6502 : public Processor { + class MOS6502 final : public Processor { public: struct opcode_decoded_t { - int aaa; - int bbb; - int cc; + int aaa = 0; + int bbb = 0; + int cc = 0; - opcode_decoded_t() { - aaa = bbb = cc = 0; - } + opcode_decoded_t() {} opcode_decoded_t(uint8_t opcode) { aaa = (opcode & 0b11100000) >> 5; // 0 - 7 @@ -46,11 +44,8 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - virtual void triggerIRQ(); - virtual void triggerNMI(); - - virtual int execute(uint8_t opcode); - int step(); + virtual int execute(uint8_t opcode) final; + virtual int step() final; uint8_t& X() { return x; } uint8_t& Y() { return y; } @@ -58,10 +53,12 @@ namespace EightBit { uint8_t& S() { return s; } uint8_t& P() { return p; } - virtual void initialise() override; - virtual void reset() override; + protected: + virtual void reset() final; private: + void interrupt(uint16_t vector); + void adjustZero(uint8_t datum) { clearFlag(P(), ZF, datum); } void adjustNegative(uint8_t datum) { setFlag(P(), NF, datum & NF); } @@ -77,8 +74,6 @@ namespace EightBit { virtual void push(uint8_t value) final; virtual uint8_t pop() final; - 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 7728e22..3e8c2a9 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -22,11 +22,7 @@ EightBit::MOS6502::MOS6502(Bus& bus) /* E */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, /* F */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, }; -} -void EightBit::MOS6502::initialise() { - - Processor::initialise(); for (int i = 0; i < 0x100; ++i) m_decodedOpcodes[i] = i; @@ -41,22 +37,40 @@ void EightBit::MOS6502::initialise() { int EightBit::MOS6502::step() { ExecutingInstruction.fire(*this); resetCycles(); - auto returned = execute(fetchByte()); - ExecutedInstruction.fire(*this); + auto returned = 0; + if (LIKELY(powered())) { + if (UNLIKELY(lowered(NMI()))) { + raise(NMI()); + interrupt(NMIvector); + returned = 4; // ?? TBC + } else if (UNLIKELY(lowered(INT()))) { + raise(INT()); + interrupt(IRQvector); + returned = 4; // ?? TBC + } else if (UNLIKELY(lowered(HALT()))) { + execute(0); // NOP ?? + returned = 4; // ?? TBC + } + + + returned = execute(fetchByte()); + ExecutedInstruction.fire(*this); + } return returned; } void EightBit::MOS6502::reset() { + Processor::reset(); getWord(RSTvector, PC()); } -void EightBit::MOS6502::triggerIRQ() { - interrupt(IRQvector); -} - -void EightBit::MOS6502::triggerNMI() { - interrupt(NMIvector); -} +//void EightBit::MOS6502::triggerIRQ() { +// interrupt(IRQvector); +//} +// +//void EightBit::MOS6502::triggerNMI() { +// interrupt(NMIvector); +//} void EightBit::MOS6502::getWord(register16_t& output) { output.low = getByte(); @@ -75,6 +89,7 @@ void EightBit::MOS6502::getWord(const register16_t& offset, register16_t& output } void EightBit::MOS6502::interrupt(uint16_t vector) { + raise(HALT()); pushWord(PC()); push(P()); setFlag(P(), IF); diff --git a/M6502/test_M6502/Board.cpp b/M6502/test_M6502/Board.cpp index 95e1da4..6455339 100644 --- a/M6502/test_M6502/Board.cpp +++ b/M6502/test_M6502/Board.cpp @@ -34,16 +34,16 @@ void Board::initialise() { } if (m_configuration.isProfileMode()) { - m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Profile, this, std::placeholders::_1)); + CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Profile, this, std::placeholders::_1)); } if (m_configuration.isDebugMode()) { - m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); + CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); } switch (m_configuration.getStopCondition()) { case Configuration::StopCondition::Loop: - m_cpu.ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_StopLoop, this, std::placeholders::_1)); + CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_StopLoop, this, std::placeholders::_1)); break; case Configuration::StopCondition::Halt: break; @@ -53,7 +53,7 @@ void Board::initialise() { if (m_configuration.allowInput()) { ReadingByte.connect(std::bind(&Board::Memory_ReadingByte_Input, this, std::placeholders::_1)); - m_cpu.ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Poll, this, std::placeholders::_1)); + CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Poll, this, std::placeholders::_1)); } if (m_configuration.allowOutput()) @@ -62,13 +62,13 @@ void Board::initialise() { m_pollCounter = 0; m_pollInterval = m_configuration.getPollInterval(); - m_cpu.initialise(); - m_cpu.PC().word = m_configuration.getStartAddress(); + CPU().powerOn(); + CPU().PC().word = m_configuration.getStartAddress(); } void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) { - const auto pc = m_cpu.PC(); + const auto pc = CPU().PC(); //m_profiler.addAddress(pc.word, m_cpu.); //m_profiler.addInstruction(m_memory.peek(pc.word)); @@ -76,9 +76,9 @@ void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) { void Board::Cpu_ExecutedInstruction_StopLoop(const EightBit::MOS6502& cpu) { - auto pc = m_cpu.PC().word; + auto pc = CPU().PC().word; if (m_oldPC == pc) { - m_cpu.halt(); + CPU().powerOff(); auto test = peek(0x0200); std::cout << std::endl << "** Test=" << std::hex << (int)test; } else { @@ -88,17 +88,17 @@ void Board::Cpu_ExecutedInstruction_StopLoop(const EightBit::MOS6502& cpu) { void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) { - auto address = m_cpu.PC().word; + auto address = CPU().PC().word; auto cell = peek(address); std::cout << std::hex; std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":"; - std::cout << "P=" << m_disassembler.dump_Flags(m_cpu.P()) << ", "; + std::cout << "P=" << m_disassembler.dump_Flags(CPU().P()) << ", "; std::cout << std::setw(2) << std::setfill('0'); - std::cout << "A=" << (int)m_cpu.A() << ", "; - std::cout << "X=" << (int)m_cpu.X() << ", "; - std::cout << "Y=" << (int)m_cpu.Y() << ", "; - std::cout << "S=" << (int)m_cpu.S() << "\t"; + std::cout << "A=" << (int)CPU().A() << ", "; + std::cout << "X=" << (int)CPU().X() << ", "; + std::cout << "Y=" << (int)CPU().Y() << ", "; + std::cout << "S=" << (int)CPU().S() << "\t"; std::cout << m_disassembler.disassemble(address); diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index f335bb4..5671162 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -5,19 +5,15 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expected) : m_test(test), m_expected(expected), - m_ram(0x10000), - m_cpu(*this, m_ports), - m_failed(false), - m_unimplemented(false) { - m_cpu.initialise(); + m_cpu(*this, m_ports) { } // void Fuse::TestRunner::initialise() { + m_cpu.powerOn(); initialiseRegisters(); initialiseMemory(); - m_cpu.powerOn(); } void Fuse::TestRunner::initialiseRegisters() { diff --git a/Z80/fusetest_Z80/FuseTestRunner.h b/Z80/fusetest_Z80/FuseTestRunner.h index 57618d5..67c6516 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.h +++ b/Z80/fusetest_Z80/FuseTestRunner.h @@ -14,10 +14,10 @@ namespace Fuse { const Test& m_test; const ExpectedTestResult& m_expected; - bool m_failed; - bool m_unimplemented; + bool m_failed = false; + bool m_unimplemented = false; - EightBit::Ram m_ram; + EightBit::Ram m_ram = 0x10000; EightBit::InputOutput m_ports; EightBit::Z80 m_cpu; diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index e89a30a..63d7edc 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -12,7 +12,7 @@ #include namespace EightBit { - class Z80 : public IntelProcessor { + class Z80 final : public IntelProcessor { public: struct refresh_t { @@ -50,16 +50,15 @@ namespace EightBit { Signal ExecutingInstruction; - bool& INT() { return m_intLine; } - bool& NMI() { return m_nmiLine; } + PinLevel& M1() { return m_m1Line; } // Out virtual int execute(uint8_t opcode) final; virtual int step() final; - virtual register16_t& AF() override; - virtual register16_t& BC() override; - virtual register16_t& DE() override; - virtual register16_t& HL() override; + virtual register16_t& AF() final; + virtual register16_t& BC() final; + virtual register16_t& DE() final; + virtual register16_t& HL() final; register16_t& IX() { return m_ix; } uint8_t& IXH() { return IX().high; } @@ -75,8 +74,6 @@ namespace EightBit { bool& IFF1() { return m_iff1; } bool& IFF2() { return m_iff2; } - bool& M1() { return m1; } - void exx() { m_registerSet ^= 1; } @@ -85,11 +82,11 @@ namespace EightBit { m_accumulatorFlagsSet = !m_accumulatorFlagsSet; } - virtual void reset() override; + protected: + virtual void reset() final; private: - bool m_intLine = false; - bool m_nmiLine = false; + PinLevel m_m1Line = Low; InputOutput& m_ports; @@ -111,8 +108,6 @@ namespace EightBit { bool m_iff1 = false; bool m_iff2 = false; - bool m1 = false; - bool m_prefixCB = false; bool m_prefixDD = false; bool m_prefixED = false; diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index d4acfb4..7cf39d1 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -28,7 +28,8 @@ void EightBit::Z80::reset() { IntelProcessor::reset(); - INT() = NMI() = false; + raise(M1()); + di(); IM() = 0; @@ -651,15 +652,18 @@ int EightBit::Z80::step() { m_displaced = m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; resetCycles(); if (LIKELY(powered())) { - M1() = true; - if (UNLIKELY(NMI())) { - NMI() = IFF1() = false; + lower(M1()); + if (UNLIKELY(lowered(NMI()))) { + raise(HALT()); + raise(NMI()); + IFF1() = false; restart(0x66); addCycles(13); return cycles(); } - if (UNLIKELY(INT())) { - INT() = false; + if (UNLIKELY(lowered(INT()))) { + raise(HALT()); + raise(INT()); if (IFF1()) { di(); switch (IM()) { @@ -670,9 +674,9 @@ int EightBit::Z80::step() { addCycles(13); return cycles(); case 2: - pushWord(PC()); - PC().low = BUS().DATA(); - PC().high = IV(); + MEMPTR().low = BUS().DATA(); + MEMPTR().high = IV(); + call(); addCycles(19); return cycles(); default: @@ -680,6 +684,8 @@ int EightBit::Z80::step() { } } } + if (UNLIKELY(lowered(HALT()))) + return execute(0); // NOP return execute(fetchByte()); } return cycles(); @@ -687,12 +693,12 @@ int EightBit::Z80::step() { int EightBit::Z80::execute(const uint8_t opcode) { - if (UNLIKELY(!M1())) + if (UNLIKELY(raised(M1()))) throw std::logic_error("M1 cannot be high"); if (LIKELY(!(m_prefixCB && m_displaced))) { ++REFRESH(); - M1() = false; + raise(M1()); } const auto& decoded = getDecodedOpcode(opcode); @@ -1371,7 +1377,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in m_prefixCB = true; if (UNLIKELY(m_displaced)) fetchDisplacement(); - M1() = true; + lower(M1()); execute(fetchByte()); break; case 2: // OUT (n),A @@ -1422,17 +1428,17 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in break; case 1: // DD prefix m_displaced = m_prefixDD = true; - M1() = true; + lower(M1()); execute(fetchByte()); break; case 2: // ED prefix m_prefixED = true; - M1() = true; + lower(M1()); execute(fetchByte()); break; case 3: // FD prefix m_displaced = m_prefixFD = true; - M1() = true; + lower(M1()); execute(fetchByte()); break; default: diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index 4b05897..6579e48 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -30,15 +30,17 @@ void Board::initialise() { m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); } - m_cpu.initialise(); - m_cpu.PC() = m_configuration.getStartAddress(); + CPU().powerOn(); + CPU().PC() = m_configuration.getStartAddress(); } void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) { + if (UNLIKELY(EightBit::Processor::lowered(m_cpu.HALT()))) + m_cpu.powerOff(); auto pc = m_cpu.PC(); switch (pc.word) { case 0x0: // CP/M warm start - m_cpu.halt(); + m_cpu.powerOff(); if (m_configuration.isProfileMode()) { m_profiler.dump(); } diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index db36e3a..1054ee0 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -15,15 +15,13 @@ namespace EightBit { public: struct opcode_decoded_t { - int x; - int y; - int z; - int p; - int q; + int x = 0; + int y = 0; + int z = 0; + int p = 0; + int q = 0; - opcode_decoded_t() { - x = y = z = p = q = 0; - } + opcode_decoded_t() {} opcode_decoded_t(uint8_t opcode) { x = (opcode & 0b11000000) >> 6; // 0 - 3 @@ -38,9 +36,6 @@ namespace EightBit { return m_decodedOpcodes[i]; } - virtual void initialise() override; - virtual void reset() override; - register16_t& SP() { return m_sp; } virtual register16_t& AF() = 0; @@ -63,6 +58,8 @@ namespace EightBit { IntelProcessor(Bus& bus); virtual ~IntelProcessor() = default; + virtual void reset() override; + template static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, T::SF, value & T::SF); } diff --git a/inc/Processor.h b/inc/Processor.h index 6fdd763..198e79d 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -49,6 +49,15 @@ namespace EightBit { Mask16 = Bit16 - 1 }; + enum PinLevel { + Low, High + }; + + static bool raised(PinLevel line) { return line == High; } + static void raise(PinLevel& line) { line = High; } + static bool lowered(PinLevel line) { return line == Low; } + static void lower(PinLevel& line) { line = Low; } + static int highNibble(int value) { return value >> 4; } static int lowNibble(int value) { return value & Mask4; } @@ -60,16 +69,15 @@ namespace EightBit { register16_t& PC() { return m_pc; } register16_t& MEMPTR() { return m_memptr; } - bool halted() const { return m_halted; } - void halt() { --PC().word; m_halted = true; } - void proceed() { ++PC().word; m_halted = false; } + PinLevel& RESET() { return m_resetLine; } // In + PinLevel& HALT() { return m_haltLine; } // Out + PinLevel& INT() { return m_intLine; } // In + PinLevel& NMI() { return m_nmiLine; } // In + PinLevel& POWER() { return m_powerLine; } // In - bool powered() const { return m_power; } - void powerOn() { m_power = true; } - void powerOff() { m_power = false; } - - virtual void initialise(); - virtual void reset(); + bool powered() { return raised(POWER()); } + void powerOn() { raise(POWER()); raise(HALT()); reset(); } + void powerOff() { lower(POWER()); } int run(int limit); virtual int singleStep(); @@ -92,6 +100,12 @@ namespace EightBit { Processor(Bus& memory); virtual ~Processor() = default; + virtual void reset(); + + bool halted() { return lowered(HALT()); } + void halt() { --PC().word; lower(HALT()); } + void proceed() { ++PC().word; raise(HALT()); } + virtual uint8_t fetchByte(); virtual void fetchWord(register16_t& output); @@ -142,7 +156,11 @@ namespace EightBit { int m_cycles = 0; register16_t m_pc = { { 0, 0 } }; register16_t m_memptr = { { 0, 0 } }; - bool m_halted = false; - bool m_power = false; + + PinLevel m_intLine = Low; + PinLevel m_nmiLine = Low; + PinLevel m_haltLine = Low; + PinLevel m_resetLine = Low; + PinLevel m_powerLine = Low; }; } diff --git a/inc/TestHarness.h b/inc/TestHarness.h index 4138a38..62b77f3 100644 --- a/inc/TestHarness.h +++ b/inc/TestHarness.h @@ -4,6 +4,8 @@ #include #include +#include "EightBitCompilerDefinitions.h" + #ifdef _MSC_VER #include #endif @@ -63,9 +65,8 @@ namespace EightBit { m_startHostCycles = currentHostCycles(); auto& cpu = m_board.CPU(); - cpu.powerOn(); - while (!cpu.halted()) { + while (LIKELY(cpu.powered())) { m_totalCycles += cpu.step(); ++m_instructions; } diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp index 00bb89a..58fd3bb 100644 --- a/src/IntelProcessor.cpp +++ b/src/IntelProcessor.cpp @@ -3,13 +3,8 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus) : Processor(bus) { -} - -void EightBit::IntelProcessor::initialise() { - Processor::initialise(); - for (int i = 0; i < 0x100; ++i) { + for (int i = 0; i < 0x100; ++i) m_decodedOpcodes[i] = i; - } } void EightBit::IntelProcessor::reset() { diff --git a/src/Processor.cpp b/src/Processor.cpp index f692162..8dc25d4 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -6,13 +6,14 @@ EightBit::Processor::Processor(Bus& bus) } void EightBit::Processor::reset() { + if (lowered(POWER())) + throw std::logic_error("POWER cannot be low"); + raise(INT()); + raise(NMI()); + raise(RESET()); PC().word = MEMPTR().word = 0; } -void EightBit::Processor::initialise() { - reset(); -} - int EightBit::Processor::run(int limit) { int current = 0; while (LIKELY(powered()) && current < limit) { @@ -22,6 +23,8 @@ int EightBit::Processor::run(int limit) { } int EightBit::Processor::singleStep() { + if (UNLIKELY(lowered(RESET()))) + reset(); return step(); }