diff --git a/src/cpu.cpp b/src/cpu.cpp index 0cefaf7..f511501 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -#include // uint8_t, uint32_t +#include // int32_t, uint8_t, uint32_t #include "cpu.h" #include "emu.h" @@ -25,7 +25,7 @@ CPU::CPU(uint32_t frequency) , m_l(0x0d) // , m_pc(0x100) , m_pc(0x0) - , m_sp(0xffe) + , m_sp(0xfffe) // Flags , m_zf(0x1) , m_nf(0x0) @@ -48,22 +48,24 @@ CPU::CPU(uint32_t frequency) // Add opcode functions to lookup table m_opcode_lookup_table.emplace(0xc6, std::bind(&CPU::add, this)); - m_opcode_lookup_table.emplace(0x08, std::bind(&CPU::ldStack, this)); - m_opcode_lookup_table.emplace(0x31, std::bind(&CPU::ldStack, this)); - m_opcode_lookup_table.emplace(0xf8, std::bind(&CPU::ldStack, this)); - m_opcode_lookup_table.emplace(0xf9, std::bind(&CPU::ldStack, this)); + m_opcode_lookup_table.emplace(0x01, std::bind(&CPU::ld16, this)); + m_opcode_lookup_table.emplace(0x11, std::bind(&CPU::ld16, this)); + m_opcode_lookup_table.emplace(0x21, std::bind(&CPU::ld16, this)); + m_opcode_lookup_table.emplace(0x31, std::bind(&CPU::ld16, this)); } CPU::~CPU() { } +// ----------------------------------------- + void CPU::update() { m_wait_cycles--; if (m_wait_cycles <= 0) { // Read next opcode - uint8_t opcode = Emu::the().bootrom()[m_pc]; + uint8_t opcode = peekBootrom(); m_opcode_lookup_table[opcode](); } @@ -72,8 +74,8 @@ void CPU::update() void CPU::add() { - uint8_t opcode = Emu::the().bootrom()[m_pc]; - uint8_t immediate = Emu::the().bootrom()[m_pc + 1]; + uint8_t opcode = consumeBootrom(); + uint8_t immediate = consumeBootrom(); switch (opcode) { case 0xc6: // ADD A,d8 // Program counter +2 @@ -99,21 +101,59 @@ void CPU::add() } } -void CPU::ldStack() +void CPU::ld16() { - print("Calling stack LD\n"); - - uint8_t opcode = Emu::the().bootrom()[m_pc]; + uint8_t opcode = consumeBootrom(); switch (opcode) { - case 0x08: + case 0x01: { + m_wait_cycles += 12; + setBc(immediate16()); break; - case 0x31: + } + case 0x11: + m_wait_cycles += 12; + setDe(immediate16()); break; - case 0xf8: + case 0x21: + m_wait_cycles += 12; + setHl(immediate16()); break; - case 0xf9: + case 0x31: { + m_wait_cycles += 12; + m_sp = immediate16(); break; + } default: VERIFY_NOT_REACHED(); } } + +// ----------------------------------------- + +uint8_t CPU::peekBootrom(int32_t offset) const +{ + return Emu::the().bootrom()[m_pc + offset]; +} + +uint8_t CPU::consumeBootrom() +{ + return Emu::the().bootrom()[m_pc++]; +} + +void CPU::setBc(uint32_t value) +{ + m_b = value >> 8; + m_c = value; +} + +void CPU::setDe(uint32_t value) +{ + m_d = value >> 8; + m_e = value; +} + +void CPU::setHl(uint32_t value) +{ + m_h = value >> 8; + m_l = value; +} diff --git a/src/cpu.h b/src/cpu.h index b32d558..b5a5a45 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -7,8 +7,8 @@ #pragma once -#include // int8_t, uint8_t, uint32_t -#include // function +#include // int8_t, int32_t, uint8_t, uint32_t +#include // std::function #include #include "processing-unit.h" @@ -20,27 +20,51 @@ public: void update() override; - // 8-bit Arithmetic and Logic Instructions + // ------------------------------------- + // Arithmetic and Logic Instructions + // 8-bit void add(); - // 16-bit Arithmetic Instructions + // 16-bit + // ------------------------------------- // Bit Operations Instructions + // ------------------------------------- // Bit Shift Instructions + // ------------------------------------- // Load Instructions + // 8-bit + + // 16-bit + void ld16(); + + // ------------------------------------- // Jumps and Subroutines + // ------------------------------------- // Stack Operations Instructions - void ldStack(); - + // ------------------------------------- // Miscellaneous Instructions private: + uint8_t peekBootrom(int32_t offset = 0) const; + uint8_t consumeBootrom(); + + uint32_t immediate16() { return (consumeBootrom() << 8) | consumeBootrom(); } + + void setBc(uint32_t value); + void setDe(uint32_t value); + void setHl(uint32_t value); + + uint32_t bc() const { return m_b << 8 | m_c; } + uint32_t de() const { return m_b << 8 | m_c; } + uint32_t hl() const { return m_b << 8 | m_c; } + // Registers uint32_t m_a { 0 }; // Accumulator uint32_t m_b { 0 }; // B