From 8b12ed23e8088faf86f73a238f7d049fa07e3d43 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 10 Nov 2018 20:29:27 +0000 Subject: [PATCH 1/7] Add (currently disabled) disassembler to the 6809 unit test runner. Signed-off-by: Adrian Conlon --- MC6809/unittest/Board.cpp | 16 +++++++++++++++- MC6809/unittest/Board.h | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/MC6809/unittest/Board.cpp b/MC6809/unittest/Board.cpp index efb4514..dbab8f1 100644 --- a/MC6809/unittest/Board.cpp +++ b/MC6809/unittest/Board.cpp @@ -2,7 +2,8 @@ #include "Board.h" Board::Board() -: m_cpu(EightBit::mc6809(*this)) { +: m_cpu(EightBit::mc6809(*this)), + m_disassembler(*this, m_cpu) { } void Board::initialise() { @@ -10,8 +11,21 @@ void Board::initialise() { CPU().raise(CPU().NMI()); CPU().raise(CPU().FIRQ()); CPU().reset(); + + //CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); + //CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1)); } EightBit::MemoryMapping Board::mapping(uint16_t) { return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; } + +void Board::Cpu_ExecutingInstruction_Debug(EightBit::mc6809&) { + m_disassembleAt = CPU().PC(); + m_ignoreDisassembly = m_disassembler.ignore(); +} + +void Board::Cpu_ExecutedInstruction_Debug(EightBit::mc6809&) { + if (!m_ignoreDisassembly) + std::cout << m_disassembler.trace(m_disassembleAt) << " " << std::endl; +} diff --git a/MC6809/unittest/Board.h b/MC6809/unittest/Board.h index 3253bd1..f71d359 100644 --- a/MC6809/unittest/Board.h +++ b/MC6809/unittest/Board.h @@ -3,6 +3,7 @@ #include #include #include +#include class Board : public EightBit::Bus { public: @@ -18,4 +19,12 @@ protected: private: EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM EightBit::mc6809 m_cpu; + EightBit::Disassembly m_disassembler; + + // The m_disassembleAt and m_ignoreDisassembly are used to skip pin events + EightBit::register16_t m_disassembleAt = 0x0000; + bool m_ignoreDisassembly = false; + + void Cpu_ExecutingInstruction_Debug(EightBit::mc6809&); + void Cpu_ExecutedInstruction_Debug(EightBit::mc6809&); }; From b82ca402bfc5cf617d33142b8a904bd5dad7a8df Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 10 Nov 2018 20:30:38 +0000 Subject: [PATCH 2/7] Add 6809 BGT tests. Signed-off-by: Adrian Conlon --- MC6809/unittest/mc6809_tests.cpp | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/MC6809/unittest/mc6809_tests.cpp b/MC6809/unittest/mc6809_tests.cpp index 0d19f68..928a11f 100644 --- a/MC6809/unittest/mc6809_tests.cpp +++ b/MC6809/unittest/mc6809_tests.cpp @@ -822,3 +822,72 @@ TEST_CASE("Subtract Memory from Register", "[SUB][SUBA]") { REQUIRE(cpu.cycles() == 4); } } + +TEST_CASE(" Branch if Greater Than Zero", "[BGT]") { + + Board board; + board.initialise(); + auto& cpu = board.CPU(); + cpu.step(); // Step over the reset + + board.poke(0, 0x2e); // BGT + board.poke(1, 0x03); + board.poke(2, 0x86); // LDA #1 + board.poke(3, 0x01); + board.poke(4, 0x12); // NOP + board.poke(5, 0x86); // LDA #2 + board.poke(6, 0x02); + board.poke(7, 0x12); // NOP + + SECTION("BGT1") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::ZF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } + + cpu.reset(); + cpu.step(); + + SECTION("BGT2") { + REQUIRE(cpu.PC() == 0); + cpu.CC() = 0; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 2); + } + + cpu.reset(); + cpu.step(); + + SECTION("BGT3") { + REQUIRE(cpu.PC() == 0); + cpu.CC() = EightBit::mc6809::NF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } + + cpu.reset(); + cpu.step(); + + SECTION("BGT4") { + REQUIRE(cpu.PC() == 0); + cpu.CC() = EightBit::mc6809::NF | EightBit::mc6809::VF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 2); + } + + cpu.reset(); + cpu.step(); + + SECTION("BGT5") { + REQUIRE(cpu.PC() == 0); + cpu.CC() = EightBit::mc6809::ZF | EightBit::mc6809::NF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } +} From b926f4b7f10562d046a02c2846bd063b710c3363 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 10 Nov 2018 20:31:14 +0000 Subject: [PATCH 3/7] Simplify 6809 conditionals a little. Signed-off-by: Adrian Conlon --- MC6809/inc/mc6809.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h index c81b7cb..718473e 100644 --- a/MC6809/inc/mc6809.h +++ b/MC6809/inc/mc6809.h @@ -274,11 +274,11 @@ namespace EightBit { auto carry() const { return CC() & CF; } auto halfCarry() const { return CC() & HF; } - auto LS() const { return carry() | (zero() >> 2); } // (C OR Z) + auto LS() const { return carry() || zero(); } // (C OR Z) auto HI() const { return !LS(); } // !(C OR Z) auto LT() const { return (negative() >> 3) ^ (overflow() >> 1); } // (N XOR V) auto GE() const { return !LT(); } // !(N XOR V) - auto LE() const { return (zero() >> 2) | ((negative() >> 3) ^ (overflow() >> 1)); } // (Z OR (N XOR V)) + auto LE() const { return zero() || LT(); } // (Z OR (N XOR V)) auto GT() const { return !LE(); } // !(Z OR (N XOR V)) // Branching From f29c5712266a8107909d25d786143975370cb2ec Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 10 Nov 2018 20:48:43 +0000 Subject: [PATCH 4/7] Add tests for BHI BLE on the 6809 Signed-off-by: Adrian Conlon --- MC6809/unittest/mc6809_tests.cpp | 94 ++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/MC6809/unittest/mc6809_tests.cpp b/MC6809/unittest/mc6809_tests.cpp index 928a11f..ea8438c 100644 --- a/MC6809/unittest/mc6809_tests.cpp +++ b/MC6809/unittest/mc6809_tests.cpp @@ -891,3 +891,97 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") { REQUIRE(cpu.A() == 1); } } + +TEST_CASE(" Branch if Higher", "[BHI]") { + + Board board; + board.initialise(); + auto& cpu = board.CPU(); + cpu.step(); // Step over the reset + + board.poke(0, 0x22); // BHI + board.poke(1, 0x03); + board.poke(2, 0x86); // LDA #1 + board.poke(3, 0x01); + board.poke(4, 0x12); // NOP + board.poke(5, 0x86); // LDA #2 + board.poke(6, 0x02); + board.poke(7, 0x12); // NOP + + SECTION("BHI1") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::ZF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } +} + +TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") { + + Board board; + board.initialise(); + auto& cpu = board.CPU(); + cpu.step(); // Step over the reset + + board.poke(0, 0x2f); // BLE + board.poke(1, 0x03); + board.poke(2, 0x86); // LDA #1 + board.poke(3, 0x01); + board.poke(4, 0x12); // NOP + board.poke(5, 0x86); // LDA #2 + board.poke(6, 0x02); + board.poke(7, 0x12); // NOP + + SECTION("BLE1") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::ZF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 2); + } + + cpu.reset(); + cpu.step(); + + SECTION("BLE2") { + cpu.A() = 0; + cpu.CC() = 0; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } + + cpu.reset(); + cpu.step(); + + SECTION("BLE3") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::NF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 2); + } + + cpu.reset(); + cpu.step(); + + SECTION("BLE4") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::NF | EightBit::mc6809::VF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 1); + } + + cpu.reset(); + cpu.step(); + + SECTION("BLE5") { + cpu.A() = 0; + cpu.CC() = EightBit::mc6809::ZF | EightBit::mc6809::NF; + cpu.step(); + cpu.step(); + REQUIRE(cpu.A() == 2); + } +} From fdbb28828f8a262d358dff5d7bce10719e1fbd16 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 11 Nov 2018 16:48:44 +0000 Subject: [PATCH 5/7] Apply the concept of powered components to the "board" Signed-off-by: Adrian Conlon --- Intel8080/test/Board.cpp | 16 ++++-- Intel8080/test/Board.h | 4 +- Intel8080/test/test.cpp | 6 +- LR35902/fusetest_LR35902/FuseTestRunner.cpp | 63 +++++++++++---------- LR35902/fusetest_LR35902/FuseTestRunner.h | 10 ++-- M6502/test/Board.cpp | 14 ++++- M6502/test/Board.h | 4 +- M6502/test/test.cpp | 3 +- MC6809/test/Board.cpp | 21 +++++-- MC6809/test/Board.h | 4 +- MC6809/test/test.cpp | 4 +- MC6809/unittest/Board.cpp | 10 +++- MC6809/unittest/Board.h | 4 +- MC6809/unittest/mc6809_tests.cpp | 32 +++++------ Z80/fusetest_Z80/FuseTestRunner.cpp | 13 ++++- Z80/fusetest_Z80/FuseTestRunner.h | 5 +- Z80/test/Board.cpp | 24 +++++--- Z80/test/Board.h | 4 +- Z80/test/test.cpp | 3 +- inc/Bus.h | 7 +++ inc/TestHarness.h | 8 +-- src/Bus.cpp | 6 ++ 22 files changed, 171 insertions(+), 94 deletions(-) diff --git a/Intel8080/test/Board.cpp b/Intel8080/test/Board.cpp index 20de798..cab3490 100644 --- a/Intel8080/test/Board.cpp +++ b/Intel8080/test/Board.cpp @@ -10,6 +10,17 @@ Board::Board(const Configuration& configuration) m_disassembler(*this) { } +void Board::powerOn() { + EightBit::Bus::powerOn(); + CPU().powerOn(); + CPU().reset(); +} + +void Board::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + void Board::initialise() { auto romDirectory = m_configuration.getRomDirectory(); @@ -29,9 +40,6 @@ void Board::initialise() { m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); } - CPU().powerOn(); - CPU().reset(); - poke(0, 0xc3); // JMP CPU().pokeWord(1, m_configuration.getStartAddress()); @@ -42,7 +50,7 @@ void Board::Cpu_ExecutingInstruction_Cpm(EightBit::Intel8080& cpu) { switch (cpu.PC().word) { case 0x0: // CP/M warm start if (++m_warmstartCount == 3) { - CPU().powerOff(); + powerOff(); if (m_configuration.isProfileMode()) { m_profiler.dump(); } diff --git a/Intel8080/test/Board.h b/Intel8080/test/Board.h index c6f2152..bf81c42 100644 --- a/Intel8080/test/Board.h +++ b/Intel8080/test/Board.h @@ -17,9 +17,11 @@ public: EightBit::Intel8080& CPU() { return m_cpu; } const EightBit::Intel8080& CPU() const { return m_cpu; } - void initialise(); + virtual void powerOn() final; + virtual void powerOff() final; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final { return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; } diff --git a/Intel8080/test/test.cpp b/Intel8080/test/test.cpp index 7653e58..7e667ec 100644 --- a/Intel8080/test/test.cpp +++ b/Intel8080/test/test.cpp @@ -8,14 +8,12 @@ int main(int, char*[]) { Configuration configuration; #ifdef _DEBUG - //configuration.setDebugMode(true); + configuration.setDebugMode(true); configuration.setProfileMode(true); #endif - //configuration.setDebugMode(true); EightBit::TestHarness harness(configuration); - harness.initialise(); - harness.runLoop(); + harness.run(); return 0; } \ No newline at end of file diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.cpp b/LR35902/fusetest_LR35902/FuseTestRunner.cpp index 6f7c0ac..c1a5c70 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.cpp +++ b/LR35902/fusetest_LR35902/FuseTestRunner.cpp @@ -4,34 +4,39 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expected) : m_test(test), - m_expected(expected), - m_ram(0x10000), - m_cpu(*this), - m_failed(false), - m_unimplemented(false) { + m_expected(expected) { } // -void Fuse::TestRunner::initialise() { - m_cpu.powerOn(); - disableGameRom(); +void Fuse::TestRunner::powerOn() { + EightBit::Bus::powerOn(); + CPU().powerOn(); initialiseRegisters(); initialiseMemory(); } +void Fuse::TestRunner::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + +void Fuse::TestRunner::initialise() { + disableGameRom(); +} + 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]; + CPU().AF() = inputRegisters[Fuse::RegisterState::AF]; + CPU().BC() = inputRegisters[Fuse::RegisterState::BC]; + CPU().DE() = inputRegisters[Fuse::RegisterState::DE]; + CPU().HL() = inputRegisters[Fuse::RegisterState::HL]; - m_cpu.SP() = inputRegisters[Fuse::RegisterState::SP]; - m_cpu.PC() = inputRegisters[Fuse::RegisterState::PC]; + CPU().SP() = inputRegisters[Fuse::RegisterState::SP]; + CPU().PC() = inputRegisters[Fuse::RegisterState::PC]; } void Fuse::TestRunner::initialiseMemory() { @@ -82,13 +87,13 @@ void Fuse::TestRunner::checkregisters() { const auto& expectedState = m_expected.registerState; const auto& expectedRegisters = expectedState.registers; - auto af = m_cpu.AF() == expectedRegisters[Fuse::RegisterState::AF]; - auto bc = m_cpu.BC() == expectedRegisters[Fuse::RegisterState::BC]; - auto de = m_cpu.DE() == expectedRegisters[Fuse::RegisterState::DE]; - auto hl = m_cpu.HL() == expectedRegisters[Fuse::RegisterState::HL]; + auto af = CPU().AF() == expectedRegisters[Fuse::RegisterState::AF]; + auto bc = CPU().BC() == expectedRegisters[Fuse::RegisterState::BC]; + auto de = CPU().DE() == expectedRegisters[Fuse::RegisterState::DE]; + auto hl = CPU().HL() == expectedRegisters[Fuse::RegisterState::HL]; - auto sp = m_cpu.SP() == expectedRegisters[Fuse::RegisterState::SP]; - auto pc = m_cpu.PC() == expectedRegisters[Fuse::RegisterState::PC]; + auto sp = CPU().SP() == expectedRegisters[Fuse::RegisterState::SP]; + auto pc = CPU().PC() == expectedRegisters[Fuse::RegisterState::PC]; auto success = af && bc && de && hl @@ -100,12 +105,12 @@ void Fuse::TestRunner::checkregisters() { if (!af) { auto expectedA = expectedRegisters[Fuse::RegisterState::AF].high; - auto gotA = m_cpu.A(); + auto gotA = CPU().A(); if (expectedA != gotA) dumpDifference("A", gotA, expectedA); auto expectedF = expectedRegisters[Fuse::RegisterState::AF].low; - auto gotF = m_cpu.F(); + auto gotF = CPU().F(); if (expectedF != gotF) { std::cerr << "**** F, Expected: " @@ -118,31 +123,31 @@ void Fuse::TestRunner::checkregisters() { if (!bc) { auto expectedWord = expectedRegisters[Fuse::RegisterState::BC]; - auto actualWord = m_cpu.BC(); + auto actualWord = CPU().BC(); dumpDifference("B", "C", actualWord, expectedWord); } if (!de) { auto expectedWord = expectedRegisters[Fuse::RegisterState::DE]; - auto actualWord = m_cpu.DE(); + auto actualWord = CPU().DE(); dumpDifference("D", "E", actualWord, expectedWord); } if (!hl) { auto expectedWord = expectedRegisters[Fuse::RegisterState::HL]; - auto actualWord = m_cpu.HL(); + auto actualWord = CPU().HL(); dumpDifference("H", "L", actualWord, expectedWord); } if (!sp) { auto expectedWord = expectedRegisters[Fuse::RegisterState::SP]; - auto actualWord = m_cpu.SP(); + auto actualWord = CPU().SP(); dumpDifference("SPH", "SPL", actualWord, expectedWord); } if (!pc) { auto expectedWord = expectedRegisters[Fuse::RegisterState::PC]; - auto actualWord = m_cpu.PC(); + auto actualWord = CPU().PC(); dumpDifference("PCH", "PCL", actualWord, expectedWord); } } @@ -177,10 +182,10 @@ void Fuse::TestRunner::checkMemory() { void Fuse::TestRunner::run() { - initialise(); + powerOn(); auto allowedCycles = m_test.registerState.tstates; try { - m_cpu.run(allowedCycles); + CPU().run(allowedCycles); check(); } catch (std::logic_error& error) { m_unimplemented = true; diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.h b/LR35902/fusetest_LR35902/FuseTestRunner.h index e4b1634..f8e0e51 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.h +++ b/LR35902/fusetest_LR35902/FuseTestRunner.h @@ -16,11 +16,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::GameBoy::LR35902 m_cpu; + EightBit::Ram m_ram = 0x10000; void initialise(); void initialiseRegisters(); @@ -47,5 +46,8 @@ namespace Fuse { void run(); bool failed() const { return m_failed; } bool unimplemented() const { return m_unimplemented; } + + virtual void powerOn() final; + virtual void powerOff() final; }; } \ No newline at end of file diff --git a/M6502/test/Board.cpp b/M6502/test/Board.cpp index 6d94049..0eb15da 100644 --- a/M6502/test/Board.cpp +++ b/M6502/test/Board.cpp @@ -13,6 +13,16 @@ Board::Board(const Configuration& configuration) m_disassembler(*this, m_cpu, m_symbols), m_profiler(m_cpu, m_disassembler, m_symbols) {} +void Board::powerOn() { + EightBit::Bus::powerOn(); + CPU().powerOn(); +} + +void Board::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + void Board::initialise() { auto programFilename = m_configuration.getProgram(); @@ -57,8 +67,6 @@ void Board::initialise() { m_pollCounter = 0; m_pollInterval = m_configuration.getPollInterval(); - CPU().powerOn(); - poke(0x00, 0x4c); CPU().pokeWord(1, m_configuration.getStartAddress()); } @@ -77,7 +85,7 @@ void Board::Cpu_ExecutedInstruction_StopLoop(EightBit::MOS6502& cpu) { if (m_oldPC != pc) { m_oldPC = pc; } else { - CPU().powerOff(); + powerOff(); auto test = peek(0x0200); std::cout << std::endl << "** Test=" << std::hex << (int)test; } diff --git a/M6502/test/Board.h b/M6502/test/Board.h index fd1f7ba..b6e20c0 100644 --- a/M6502/test/Board.h +++ b/M6502/test/Board.h @@ -17,9 +17,11 @@ public: EightBit::MOS6502& CPU() { return m_cpu; } - void initialise(); + virtual void powerOn() final; + virtual void powerOff() final; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final { return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; } diff --git a/M6502/test/test.cpp b/M6502/test/test.cpp index d00de09..b61ee6e 100644 --- a/M6502/test/test.cpp +++ b/M6502/test/test.cpp @@ -16,8 +16,7 @@ int main(int argc, char* argv[]) { #endif EightBit::TestHarness harness(configuration); - harness.initialise(); - harness.runLoop(); + harness.run(); return 0; } \ No newline at end of file diff --git a/MC6809/test/Board.cpp b/MC6809/test/Board.cpp index df1c62e..35af48b 100644 --- a/MC6809/test/Board.cpp +++ b/MC6809/test/Board.cpp @@ -7,11 +7,9 @@ Board::Board(const Configuration& configuration) m_disassembler(*this, m_cpu) { } -void Board::initialise() { +void Board::powerOn() { - // Load our BASIC interpreter - const auto directory = m_configuration.getRomDirectory() + "\\"; - loadHexFile(directory + "ExBasROM.hex"); + EightBit::Bus::powerOn(); // Get the CPU ready for action CPU().powerOn(); @@ -26,6 +24,19 @@ void Board::initialise() { ACIA().lower(ACIA().CTS()); ACIA().powerOn(); accessAcia(); +} + +void Board::powerOff() { + ACIA().powerOff(); + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + +void Board::initialise() { + + // Load our BASIC interpreter + const auto directory = m_configuration.getRomDirectory() + "\\"; + loadHexFile(directory + "ExBasROM.hex"); // Once the reset has completed, we can wire the ACIA event handlers... ACIA().Transmitting.connect(std::bind(&Board::Acia_Transmitting, this, std::placeholders::_1)); @@ -95,7 +106,7 @@ void Board::Cpu_ExecutedInstruction_Terminator(EightBit::mc6809&) { assert(CPU().cycles() > 0); m_totalCycleCount += CPU().cycles(); if (m_totalCycleCount > Configuration::TerminationCycles) - CPU().powerOff(); + powerOff(); } void Board::Cpu_ExecutedInstruction_Acia(EightBit::mc6809&) { diff --git a/MC6809/test/Board.h b/MC6809/test/Board.h index 04ad606..f07f9e7 100644 --- a/MC6809/test/Board.h +++ b/MC6809/test/Board.h @@ -19,9 +19,11 @@ public: auto& CPU() { return m_cpu; } auto& ACIA() { return m_acia; } - void initialise(); + virtual void powerOn() final; + virtual void powerOff() final; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final; private: diff --git a/MC6809/test/test.cpp b/MC6809/test/test.cpp index 13bf177..0bf1724 100644 --- a/MC6809/test/test.cpp +++ b/MC6809/test/test.cpp @@ -13,11 +13,9 @@ int main(int argc, char* argv[]) { #ifdef _DEBUG configuration.setDebugMode(true); #endif - //configuration.setDebugMode(true); EightBit::TestHarness harness(configuration); - harness.initialise(); - harness.runLoop(); + harness.run(); return 0; } \ No newline at end of file diff --git a/MC6809/unittest/Board.cpp b/MC6809/unittest/Board.cpp index dbab8f1..cf5955b 100644 --- a/MC6809/unittest/Board.cpp +++ b/MC6809/unittest/Board.cpp @@ -6,12 +6,20 @@ Board::Board() m_disassembler(*this, m_cpu) { } -void Board::initialise() { +void Board::powerOn() { + EightBit::Bus::powerOn(); CPU().powerOn(); CPU().raise(CPU().NMI()); CPU().raise(CPU().FIRQ()); CPU().reset(); +} +void Board::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + +void Board::initialise() { //CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); //CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1)); } diff --git a/MC6809/unittest/Board.h b/MC6809/unittest/Board.h index f71d359..fc8bba2 100644 --- a/MC6809/unittest/Board.h +++ b/MC6809/unittest/Board.h @@ -11,9 +11,11 @@ public: EightBit::mc6809& CPU() { return m_cpu; } - void initialise(); + virtual void powerOn() final; + virtual void powerOff() final; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final; private: diff --git a/MC6809/unittest/mc6809_tests.cpp b/MC6809/unittest/mc6809_tests.cpp index ea8438c..7bd5862 100644 --- a/MC6809/unittest/mc6809_tests.cpp +++ b/MC6809/unittest/mc6809_tests.cpp @@ -9,7 +9,7 @@ TEST_CASE("Add Accumulator B to Index Register X Unsigned", "[ABX]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -70,7 +70,7 @@ TEST_CASE("Add Accumulator B to Index Register X Unsigned", "[ABX]") { TEST_CASE("Add Memory Plus Carry to Accumulator", "[ADC][ADCA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -153,7 +153,7 @@ TEST_CASE("Add Memory Plus Carry to Accumulator", "[ADC][ADCA]") { TEST_CASE("Add Memory to Accumulator", "[ADD][ADDA][ADDB][ADDD]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -350,7 +350,7 @@ TEST_CASE("Add Memory to Accumulator", "[ADD][ADDA][ADDB][ADDD]") { TEST_CASE("Logical AND Accumulator", "[AND][ANDA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -370,7 +370,7 @@ TEST_CASE("Logical AND Accumulator", "[AND][ANDA]") { TEST_CASE("Shift Accumulator or Memory Byte Left", "[ASL][ASLA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -389,7 +389,7 @@ TEST_CASE("Shift Accumulator or Memory Byte Left", "[ASL][ASLA]") { TEST_CASE("Shift Accumulator or Memory Byte Right", "[ASR][ASRA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -408,7 +408,7 @@ TEST_CASE("Shift Accumulator or Memory Byte Right", "[ASR][ASRA]") { TEST_CASE("Bit Test", "[BIT][BITA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -427,7 +427,7 @@ TEST_CASE("Bit Test", "[BIT][BITA]") { TEST_CASE("Clear Accumulator or Memory", "[CLR][CLRA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -447,7 +447,7 @@ TEST_CASE("Clear Accumulator or Memory", "[CLR][CLRA]") { TEST_CASE("Compare Memory with a Register", "[CMP][CMPA][CMPB][CMPX]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -544,7 +544,7 @@ TEST_CASE("Compare Memory with a Register", "[CMP][CMPA][CMPB][CMPX]") { TEST_CASE("Decrement Accumulator or Memory", "[DEC][DECA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -593,7 +593,7 @@ TEST_CASE("Decrement Accumulator or Memory", "[DEC][DECA]") { TEST_CASE("Increment Accumulator or Memory Location by 1", "[INC][INCA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -640,7 +640,7 @@ TEST_CASE("Increment Accumulator or Memory Location by 1", "[INC][INCA]") { TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][SBCB]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -729,7 +729,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S TEST_CASE("Subtract Memory from Register", "[SUB][SUBA]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -826,7 +826,7 @@ TEST_CASE("Subtract Memory from Register", "[SUB][SUBA]") { TEST_CASE(" Branch if Greater Than Zero", "[BGT]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -895,7 +895,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") { TEST_CASE(" Branch if Higher", "[BHI]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset @@ -920,7 +920,7 @@ TEST_CASE(" Branch if Higher", "[BHI]") { TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") { Board board; - board.initialise(); + board.powerOn(); auto& cpu = board.CPU(); cpu.step(); // Step over the reset diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index 04d942e..dee822b 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -10,9 +10,18 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte // -void Fuse::TestRunner::initialise() { +void Fuse::TestRunner::powerOn() { + EightBit::Bus::powerOn(); m_cpu.powerOn(); initialiseRegisters(); +} + +void Fuse::TestRunner::powerOff() { + m_cpu.powerOff(); + EightBit::Bus::powerOff(); +} + +void Fuse::TestRunner::initialise() { initialiseMemory(); } @@ -319,7 +328,7 @@ void Fuse::TestRunner::checkMemory() { void Fuse::TestRunner::run() { - initialise(); + powerOn(); auto allowedCycles = m_test.registerState.tstates; try { m_cpu.run(allowedCycles); diff --git a/Z80/fusetest_Z80/FuseTestRunner.h b/Z80/fusetest_Z80/FuseTestRunner.h index f49a36e..14e31d5 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.h +++ b/Z80/fusetest_Z80/FuseTestRunner.h @@ -21,7 +21,6 @@ namespace Fuse { EightBit::InputOutput m_ports; EightBit::Z80 m_cpu; - void initialise(); void initialiseRegisters(); void initialiseMemory(); @@ -36,6 +35,7 @@ namespace Fuse { EightBit::register16_t actual, EightBit::register16_t expected) const; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final { return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; } @@ -46,5 +46,8 @@ namespace Fuse { void run(); bool failed() const { return m_failed; } bool unimplemented() const { return m_unimplemented; } + + virtual void powerOn() final; + virtual void powerOff() final; }; } \ No newline at end of file diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index cc5f41e..ad1ee69 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -10,6 +10,19 @@ Board::Board(const Configuration& configuration) m_profiler(m_cpu, m_disassembler) { } +void Board::powerOn() { + + EightBit::Bus::powerOn(); + + CPU().powerOn(); + CPU().reset(); +} + +void Board::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + void Board::initialise() { auto romDirectory = m_configuration.getRomDirectory(); @@ -29,23 +42,18 @@ void Board::initialise() { m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); } - CPU().powerOn(); - CPU().reset(); - poke(0, 0xc3); // JMP - poke(1, m_configuration.getStartAddress().low); - poke(2, m_configuration.getStartAddress().high); - + CPU().pokeWord(1, m_configuration.getStartAddress()); poke(5, 0xc9); // ret } void Board::Cpu_ExecutingInstruction_Cpm(EightBit::Z80& cpu) { if (UNLIKELY(EightBit::Chip::lowered(cpu.HALT()))) - CPU().powerOff(); + powerOff(); switch (cpu.PC().word) { case 0x0: // CP/M warm start if (++m_warmstartCount == 3) { - CPU().powerOff(); + powerOff(); if (m_configuration.isProfileMode()) { m_profiler.dump(); } diff --git a/Z80/test/Board.h b/Z80/test/Board.h index 21ee4b7..edd1c2b 100644 --- a/Z80/test/Board.h +++ b/Z80/test/Board.h @@ -18,9 +18,11 @@ public: EightBit::Z80& CPU() { return m_cpu; } - void initialise(); + virtual void powerOn() final; + virtual void powerOff() final; protected: + virtual void initialise() final; virtual EightBit::MemoryMapping mapping(uint16_t address) final { return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; } diff --git a/Z80/test/test.cpp b/Z80/test/test.cpp index a44f12f..3adafec 100644 --- a/Z80/test/test.cpp +++ b/Z80/test/test.cpp @@ -14,8 +14,7 @@ int main(int, char*[]) { #endif EightBit::TestHarness harness(configuration); - harness.initialise(); - harness.runLoop(); + harness.run(); return 0; } \ No newline at end of file diff --git a/inc/Bus.h b/inc/Bus.h index 43e788d..aa06139 100644 --- a/inc/Bus.h +++ b/inc/Bus.h @@ -47,7 +47,12 @@ namespace EightBit { write(value); } + virtual void powerOn(); + virtual void powerOff(); + protected: + virtual void initialise() = 0; + virtual MemoryMapping mapping(uint16_t address) = 0; uint8_t& reference(uint16_t address); auto& reference(const register16_t address) { return reference(address.word); } @@ -56,6 +61,8 @@ namespace EightBit { static std::map> parseHexFile(std::string path); void loadHexFile(std::string path); + + private: uint8_t m_data = 0xff; register16_t m_address = 0xffff; diff --git a/inc/TestHarness.h b/inc/TestHarness.h index ea4b626..b787a05 100644 --- a/inc/TestHarness.h +++ b/inc/TestHarness.h @@ -55,11 +55,13 @@ namespace EightBit { return (long long)floating; } - void runLoop() { + void run() { m_startTime = now(); m_totalCycles = m_instructions = 0L; m_startHostCycles = currentHostCycles(); + m_board.powerOn(); + auto& cpu = m_board.CPU(); while (LIKELY(cpu.powered())) { @@ -71,10 +73,6 @@ namespace EightBit { m_finishTime = now(); } - void initialise() { - m_board.initialise(); - } - private: BoardT m_board; long long m_totalCycles = 0; diff --git a/src/Bus.cpp b/src/Bus.cpp index 03b080d..4c671d7 100644 --- a/src/Bus.cpp +++ b/src/Bus.cpp @@ -8,6 +8,12 @@ #include #include +void EightBit::Bus::powerOn() { + initialise(); +} + +void EightBit::Bus::powerOff() {} + uint8_t EightBit::Bus::read() { ReadingByte.fire(EventArgs::empty()); const auto returned = DATA() = reference(); From e326490cd9b8f27ec96446f57fb1cf7544f0e312 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 11 Nov 2018 16:49:21 +0000 Subject: [PATCH 6/7] Correct typographical mistake in MC6850 documentation. Signed-off-by: Adrian Conlon --- MC6850/inc/MC6850.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC6850/inc/MC6850.h b/MC6850/inc/MC6850.h index b899293..b784b7a 100644 --- a/MC6850/inc/MC6850.h +++ b/MC6850/inc/MC6850.h @@ -46,7 +46,7 @@ namespace EightBit { // +--------+------------------+------------------+--------------------+-----------------------+ // * Leading bit = LSB = Bit 0 // ** Data bit will be zero in 7-bit plus parity modes - // *** Data bit is "don't case" in 7-bit plus parity modes + // *** Data bit is "don't care" in 7-bit plus parity modes enum ControlRegisters { CR0 = 0b1, // Counter divide From 68b352d1dfcfc7aa34377d74495bc29f575b9a2e Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Mon, 12 Nov 2018 00:38:03 +0000 Subject: [PATCH 7/7] Wire the GameBoy board like a piece of powered hardware. Signed-off-by: Adrian Conlon --- LR35902/inc/GameBoyBus.h | 3 +++ LR35902/src/GameBoyBus.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/LR35902/inc/GameBoyBus.h b/LR35902/inc/GameBoyBus.h index 1a48ca0..b783750 100644 --- a/LR35902/inc/GameBoyBus.h +++ b/LR35902/inc/GameBoyBus.h @@ -36,6 +36,9 @@ namespace EightBit { Bus() noexcept; + virtual void powerOn() override; + virtual void powerOff() override; + auto& CPU() { return m_cpu; } auto& VRAM() { return m_videoRam; } auto& OAMRAM() { return m_oamRam; } diff --git a/LR35902/src/GameBoyBus.cpp b/LR35902/src/GameBoyBus.cpp index abdfc61..be4fb94 100644 --- a/LR35902/src/GameBoyBus.cpp +++ b/LR35902/src/GameBoyBus.cpp @@ -8,6 +8,17 @@ EightBit::GameBoy::Bus::Bus() noexcept WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1)); } +void EightBit::GameBoy::Bus::powerOn() { + EightBit::Bus::powerOn(); + CPU().powerOn(); + reset(); +} + +void EightBit::GameBoy::Bus::powerOff() { + CPU().powerOff(); + EightBit::Bus::powerOff(); +} + void EightBit::GameBoy::Bus::reset() { IO().reset(); LR35902::lower(CPU().RESET());