1#include "../../../../../include/ProcessingUnit.hpp"
2#include "../../../../../include/opcodes.hpp"
3#include "../../../../../include/mmu.hpp"
5constexpr int machine_cycles = 4;
6#define totalMachineCycles(n) ((n) * machine_cycles)
8#define DUMMY(name) int name(ProcessingUnit&, MMU&) { return totalMachineCycles(1); }
12 const u8 a8 = mmu.read(cpu.inc_pc());
13 const u16 target = 0xFF00 | a8;
15 mmu.write(target, cpu.reg(ProcessingUnit::Register::A));
17 return totalMachineCycles(3);
22 const u16 sp = cpu.get_sp();
23 const u8 lo = mmu.read(sp);
24 const u8 hi = mmu.read(sp + 1);
26 cpu.reg(ProcessingUnit::Register::L) = lo;
27 cpu.reg(ProcessingUnit::Register::H) = hi;
30 return totalMachineCycles(3);
35 const u16 target = 0xFF00 | cpu.reg(ProcessingUnit::Register::C);
36 mmu.write(target, cpu.reg(ProcessingUnit::Register::A));
38 return totalMachineCycles(2);
43 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
48 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
53 const u8 h = cpu.reg(ProcessingUnit::Register::H);
54 const u8 l = cpu.reg(ProcessingUnit::Register::L);
55 const u16 sp = cpu.get_sp();
61 return totalMachineCycles(4);
66 const u8 d8 = mmu.read(cpu.inc_pc());
67 const u8 result = cpu.reg(ProcessingUnit::Register::A) & d8;
68 cpu.reg(ProcessingUnit::Register::A) = result;
70 cpu.setFlag(ProcessingUnit::Flag::Z, result == 0);
71 cpu.setFlag(ProcessingUnit::Flag::N,
false);
72 cpu.setFlag(ProcessingUnit::Flag::H,
true);
73 cpu.setFlag(ProcessingUnit::Flag::C,
false);
75 return totalMachineCycles(2);
80 const u16 pc = cpu.get_pc();
82 cpu.set_sp(cpu.get_sp() - 1);
83 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
85 cpu.set_sp(cpu.get_sp() - 1);
86 mmu.write(cpu.get_sp(), pc & 0xFF);
90 return totalMachineCycles(4);
95 const u16 sp = cpu.get_sp();
96 const u8 offset_raw = mmu.read(cpu.inc_pc());
97 const auto offset =
static_cast<int8_t
>(offset_raw);
98 const u16 result =
static_cast<u16
>(sp + offset);
102 cpu.setFlag(ProcessingUnit::Flag::Z,
false);
103 cpu.setFlag(ProcessingUnit::Flag::N,
false);
104 cpu.setFlag(ProcessingUnit::Flag::H, ((sp & 0x0F) + (offset_raw & 0x0F)) > 0x0F);
105 cpu.setFlag(ProcessingUnit::Flag::C, ((sp & 0xFF) + (offset_raw & 0xFF)) > 0xFF);
107 return totalMachineCycles(4);
112 cpu.set_pc(cpu.get_hl());
113 return totalMachineCycles(1);
118 const u8 lo = mmu.read(cpu.inc_pc());
119 const u8 hi = mmu.read(cpu.inc_pc());
120 const u16 addr =
static_cast<u16
>((hi << 8) | lo);
122 mmu.write(addr, cpu.reg(ProcessingUnit::Register::A));
124 return totalMachineCycles(4);
129 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
134 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
139 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
144 const u8 d8 = mmu.read(cpu.inc_pc());
145 const u8 result = cpu.reg(ProcessingUnit::Register::A) ^ d8;
146 cpu.reg(ProcessingUnit::Register::A) = result;
148 cpu.setFlag(ProcessingUnit::Flag::Z, result == 0);
149 cpu.setFlag(ProcessingUnit::Flag::N,
false);
150 cpu.setFlag(ProcessingUnit::Flag::H,
false);
151 cpu.setFlag(ProcessingUnit::Flag::C,
false);
153 return totalMachineCycles(2);
158 const u16 pc = cpu.get_pc();
160 cpu.set_sp(cpu.get_sp() - 1);
161 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
163 cpu.set_sp(cpu.get_sp() - 1);
164 mmu.write(cpu.get_sp(), pc & 0xFF);
168 return totalMachineCycles(4);