diff --git a/src/cpu.cpp b/src/cpu.cpp index b91f6bf..527dc70 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -1363,9 +1363,9 @@ void CPU::pop() m_wait_cycles += 12; // Pop register r16 from stack - register_low = read(m_sp); + register_low = read(m_sp); // lsb(r16) m_sp = (m_sp + 1) & 0xffff; - register_high = read(m_sp); + register_high = read(m_sp); // msb(r16) m_sp = (m_sp + 1) & 0xffff; }; @@ -1398,9 +1398,9 @@ void CPU::push() // Push register r16 into stack m_sp = (m_sp - 1) & 0xffff; - write(m_sp, register_ >> 8); + write(m_sp, register_ >> 8); // msb(r16) m_sp = (m_sp - 1) & 0xffff; - write(m_sp, register_ & 0xff); + write(m_sp, register_ & 0xff); // lsb(r16) }; uint8_t opcode = pcRead(); diff --git a/test/testcpu.cpp b/test/testcpu.cpp index 21cdf1f..e079fc3 100644 --- a/test/testcpu.cpp +++ b/test/testcpu.cpp @@ -4,7 +4,10 @@ * SPDX-License-Identifier: MIT */ +#include + #include "cpu.h" +#include "emu.h" #include "macro.h" #include "testcase.h" #include "testsuite.h" @@ -23,6 +26,28 @@ struct CPUTest { } }; +CPU runCPUTest(std::vector test) +{ + CPU cpu(4000000); + + Emu::the().destroy(); + Emu::the().init(8000000); + Emu::the().addProcessingUnit("cpu", &cpu); + Emu::the().addMemorySpace("FULL", 0x0000, 0xffff); + + // Load the test + for (size_t i = 0; i < test.size(); ++i) { + Emu::the().writeMemory(i, test[i]); + } + + // Run the test + while (cpu.pc() < test.size()) { + Emu::the().update(); + } + + return cpu; +} + // ----------------------------------------- TEST_CASE(CPUIsCarry) @@ -55,3 +80,102 @@ TEST_CASE(CPUIsCarry) EXPECT(test.isCarry(0xff, 254, 2) == true); } + +TEST_CASE(CPUAddPlusCarry) +{ + CPU cpu(0); + + // ADC A,E + + std::vector adc_r8 = { + // clang-format off + 0x3e, 0xe1, // LD A,i8 + 0x1e, 0x0f, // LD E,i8 + 0x37, // SCF + 0x8b, // ADC A,E + // clang-format on + }; + cpu = runCPUTest(adc_r8); + EXPECT_EQ(cpu.a(), 0xf1); + EXPECT_EQ(cpu.zf(), 0x0); + EXPECT_EQ(cpu.nf(), 0x0); + EXPECT_EQ(cpu.hf(), 0x1); + EXPECT_EQ(cpu.cf(), 0x0); + + // ADC A,i8 + + std::vector adc_i8 = { + // clang-format off + 0x3e, 0xe1, // LD A,i8 + 0x37, // SCF + 0xce, 0x3b, // ADC A,i8 + // clang-format on + }; + cpu = runCPUTest(adc_i8); + EXPECT_EQ(cpu.a(), 0x1d); + EXPECT_EQ(cpu.zf(), 0x0); + EXPECT_EQ(cpu.nf(), 0x0); + EXPECT_EQ(cpu.hf(), 0x0); + EXPECT_EQ(cpu.cf(), 0x1); + + // ADC A,(HL) + + std::vector adc_hl = { + // clang-format off + 0x3e, 0xe1, // LD A,i8 + 0x36, 0x1e, // LD (HL),i8 + 0x37, // SCF + 0x8e, // ADC A,(HL) + // clang-format on + }; + cpu = runCPUTest(adc_hl); + EXPECT_EQ(cpu.a(), 0x0); + EXPECT_EQ(cpu.zf(), 0x1); + EXPECT_EQ(cpu.nf(), 0x0); + EXPECT_EQ(cpu.hf(), 0x1); + EXPECT_EQ(cpu.cf(), 0x1); +} + +TEST_CASE(CPUSetStackPointer) +{ + std::vector test = { 0x31, 0xfe, 0xff }; // LD SP,i16 + CPU cpu = runCPUTest(test); + EXPECT_EQ(cpu.sp(), 0xfffe); +} + +TEST_CASE(CPUPushToStack) +{ + // PUSH BC + + std::vector push_bc = { + // clang-format off + 0x31, 0xfe, 0xff, // LD SP,i16 + 0x01, 0xfc, 0xff, // LD BC,i16 + 0xc5, // PUSH BC + // clang-format on + }; + CPU cpu = runCPUTest(push_bc); + EXPECT_EQ(cpu.bc(), 0xfffc); + EXPECT_EQ(cpu.sp(), 0xfffc); + EXPECT_EQ(Emu::the().readMemory(0xfffd), 0xff); + EXPECT_EQ(Emu::the().readMemory(0xfffc), 0xfc); +} + +TEST_CASE(CPUPopFromStack) +{ + // POP BC + + std::vector pop_bc = { + // clang-format off + 0x31, 0xfe, 0xff, // LD SP,i16 + 0x11, 0x5f, 0x3c, // LD DE,i16 + 0xd5, // PUSH DE + 0xc1, // POP BC + // clang-format on + }; + CPU cpu = runCPUTest(pop_bc); + EXPECT_EQ(cpu.bc(), 0x3c5f); + EXPECT_EQ(cpu.sp(), 0xfffe); + EXPECT_EQ(Emu::the().readMemory(0xfffd), 0x3c); + EXPECT_EQ(Emu::the().readMemory(0xfffc), 0x5f); +}