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 u8 a8 = mmu.read(cpu.inc_pc());
14 u16 target = 0xFF00 | a8;
15 cpu.reg(ProcessingUnit::Register::A) = mmu.read(target);
17 return totalMachineCycles(3);
22 u8 lb = mmu.read(cpu.get_sp());
23 u8 masked_lb = lb & 0xF0;
25 cpu.reg(ProcessingUnit::Register::F) = masked_lb;
26 cpu.set_sp(cpu.get_sp() + 1);
28 u8 hb = mmu.read(cpu.get_sp());
29 cpu.reg(ProcessingUnit::Register::A) = hb;
30 cpu.set_sp(cpu.get_sp() + 1);
32 return totalMachineCycles(3);
37 u8 value = cpu.reg(ProcessingUnit::Register::C);
38 u16 target = 0xFF00 | value;
40 u8 result = mmu.read(target);
42 cpu.reg(ProcessingUnit::Register::A) = result;
44 return totalMachineCycles(2);
50 return totalMachineCycles(1);
55 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
60 u8 value_a = cpu.reg(ProcessingUnit::Register::A);
61 u8 value_f = cpu.reg(ProcessingUnit::Register::F);
63 cpu.set_sp(cpu.get_sp() - 1);
64 mmu.write(cpu.get_sp(), value_a);
66 cpu.set_sp(cpu.get_sp() - 1);
67 mmu.write(cpu.get_sp(), value_f);
69 return totalMachineCycles(4);
74 u8 value = mmu.read(cpu.inc_pc());
76 u8 result = cpu.reg(ProcessingUnit::Register::A) | value;
77 cpu.reg(ProcessingUnit::Register::A) = result;
79 cpu.setFlag(ProcessingUnit::Flag::Z, result == 0);
80 cpu.setFlag(ProcessingUnit::Flag::N,
false);
81 cpu.setFlag(ProcessingUnit::Flag::H,
false);
82 cpu.setFlag(ProcessingUnit::Flag::C,
false);
84 return totalMachineCycles(2);
89 u16 pc = cpu.get_pc();
91 cpu.set_sp(cpu.get_sp() - 1);
92 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
94 cpu.set_sp(cpu.get_sp() - 1);
95 mmu.write(cpu.get_sp(), pc & 0xFF);
99 return totalMachineCycles(4);
104 const u16 sp = cpu.get_sp();
105 const u8 offset_raw = mmu.read(cpu.inc_pc());
106 const auto offset =
static_cast<int8_t
>(offset_raw);
107 const u16 result =
static_cast<u16
>(sp + offset);
109 cpu.reg(ProcessingUnit::Register::H) =
static_cast<u8
>((result >> 8) & 0xFF);
110 cpu.reg(ProcessingUnit::Register::L) =
static_cast<u8
>(result & 0xFF);
112 cpu.setFlag(ProcessingUnit::Flag::Z,
false);
113 cpu.setFlag(ProcessingUnit::Flag::N,
false);
114 cpu.setFlag(ProcessingUnit::Flag::H, ((sp & 0x0F) + (offset_raw & 0x0F)) > 0x0F);
115 cpu.setFlag(ProcessingUnit::Flag::C, ((sp & 0xFF) + (offset_raw & 0xFF)) > 0xFF);
117 return totalMachineCycles(3);
122 cpu.set_sp(cpu.get_hl());
123 return totalMachineCycles(2);
128 const u8 lo = mmu.read(cpu.inc_pc());
129 const u8 hi = mmu.read(cpu.inc_pc());
130 const u16 addr =
static_cast<u16
>((hi << 8) | lo);
132 cpu.reg(ProcessingUnit::Register::A) = mmu.read(addr);
134 return totalMachineCycles(4);
140 return totalMachineCycles(1);
144 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
149 throw std::runtime_error(
"Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
154 const u8 a = cpu.reg(ProcessingUnit::Register::A);
155 const u8 d8 = mmu.read(cpu.inc_pc());
156 const int result = a - d8;
157 const int half_carry = (a & 0x0F) - (d8 & 0x0F);
159 cpu.setFlag(ProcessingUnit::Flag::Z, (result & 0xFF) == 0);
160 cpu.setFlag(ProcessingUnit::Flag::N,
true);
161 cpu.setFlag(ProcessingUnit::Flag::H, half_carry < 0);
162 cpu.setFlag(ProcessingUnit::Flag::C, result < 0);
164 return totalMachineCycles(2);
169 const u16 pc = cpu.get_pc();
171 cpu.set_sp(cpu.get_sp() - 1);
172 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
174 cpu.set_sp(cpu.get_sp() - 1);
175 mmu.write(cpu.get_sp(), pc & 0xFF);
179 return totalMachineCycles(4);