GameBoy Emulator 1
Game Boy emulator core and tooling
Loading...
Searching...
No Matches
op_0F.cpp
1#include "../../../../../include/ProcessingUnit.hpp"
2#include "../../../../../include/opcodes.hpp"
3#include "../../../../../include/mmu.hpp"
4
5constexpr int machine_cycles = 4;
6#define totalMachineCycles(n) ((n) * machine_cycles)
7
8#define DUMMY(name) int name(ProcessingUnit&, MMU&) { return totalMachineCycles(1); }
9
10int op_ldh_a_a8(ProcessingUnit& cpu, MMU& mmu) // 0xF0
11{
12 u8 a8 = mmu.read(cpu.inc_pc());
13
14 u16 target = 0xFF00 | a8;
15 cpu.reg(ProcessingUnit::Register::A) = mmu.read(target);
16
17 return totalMachineCycles(3);
18}
19
20int op_pop_af(ProcessingUnit& cpu, MMU& mmu) // 0xF1
21{
22 u8 lb = mmu.read(cpu.get_sp());
23 u8 masked_lb = lb & 0xF0;
24
25 cpu.reg(ProcessingUnit::Register::F) = masked_lb;
26 cpu.set_sp(cpu.get_sp() + 1);
27
28 u8 hb = mmu.read(cpu.get_sp());
29 cpu.reg(ProcessingUnit::Register::A) = hb;
30 cpu.set_sp(cpu.get_sp() + 1);
31
32 return totalMachineCycles(3);
33}
34
35int op_ld_a_c_f2(ProcessingUnit& cpu, MMU& mmu) // 0xF2
36{
37 u8 value = cpu.reg(ProcessingUnit::Register::C);
38 u16 target = 0xFF00 | value;
39
40 u8 result = mmu.read(target);
41
42 cpu.reg(ProcessingUnit::Register::A) = result;
43
44 return totalMachineCycles(2);
45}
46
47int op_di(ProcessingUnit& cpu, MMU& mmu) // 0xF3
48{
49 cpu.setIME(false);
50 return totalMachineCycles(1);
51}
52
53int op_illegal_f4(ProcessingUnit& cpu, MMU& mmu) // 0xF4
54{
55 throw std::runtime_error("Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
56}
57
58int op_push_af(ProcessingUnit& cpu, MMU& mmu) // 0xF5
59{
60 u8 value_a = cpu.reg(ProcessingUnit::Register::A);
61 u8 value_f = cpu.reg(ProcessingUnit::Register::F);
62
63 cpu.set_sp(cpu.get_sp() - 1);
64 mmu.write(cpu.get_sp(), value_a);
65
66 cpu.set_sp(cpu.get_sp() - 1);
67 mmu.write(cpu.get_sp(), value_f);
68
69 return totalMachineCycles(4);
70}
71
72int op_or_d8(ProcessingUnit& cpu, MMU& mmu) // 0xF6
73{
74 u8 value = mmu.read(cpu.inc_pc());
75
76 u8 result = cpu.reg(ProcessingUnit::Register::A) | value;
77 cpu.reg(ProcessingUnit::Register::A) = result;
78
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);
83
84 return totalMachineCycles(2);
85}
86
87int op_rst_30(ProcessingUnit& cpu, MMU& mmu) // 0xF7
88{
89 u16 pc = cpu.get_pc();
90
91 cpu.set_sp(cpu.get_sp() - 1);
92 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
93
94 cpu.set_sp(cpu.get_sp() - 1);
95 mmu.write(cpu.get_sp(), pc & 0xFF);
96
97 cpu.set_pc(0x30);
98
99 return totalMachineCycles(4);
100}
101
102int op_ld_hl_sp_e8(ProcessingUnit& cpu, MMU& mmu) // 0xF8
103{
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);
108
109 cpu.reg(ProcessingUnit::Register::H) = static_cast<u8>((result >> 8) & 0xFF);
110 cpu.reg(ProcessingUnit::Register::L) = static_cast<u8>(result & 0xFF);
111
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);
116
117 return totalMachineCycles(3);
118}
119
120int op_ld_sp_hl(ProcessingUnit& cpu, MMU& mmu) // 0xF9
121{
122 cpu.set_sp(cpu.get_hl());
123 return totalMachineCycles(2);
124}
125
126int op_ld_a_a16(ProcessingUnit& cpu, MMU& mmu) // 0xFA
127{
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);
131
132 cpu.reg(ProcessingUnit::Register::A) = mmu.read(addr);
133
134 return totalMachineCycles(4);
135}
136
137int op_ei(ProcessingUnit& cpu, MMU& mmu) // 0xFB
138{
139 cpu.setIME(true);
140 return totalMachineCycles(1);
141}
142int op_illegal_fc(ProcessingUnit& cpu, MMU& mmu) // 0xFC
143{
144 throw std::runtime_error("Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
145}
146
147int op_illegal_fd(ProcessingUnit& cpu, MMU& mmu) // 0xFD
148{
149 throw std::runtime_error("Unimplemented opcode at PC: 0x" + std::to_string(cpu.last_pc));
150}
151
152int op_cp_d8(ProcessingUnit& cpu, MMU& mmu) // 0xFE
153{
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);
158
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);
163
164 return totalMachineCycles(2);
165}
166
167int op_rst_38(ProcessingUnit& cpu, MMU& mmu) // 0xFF
168{
169 const u16 pc = cpu.get_pc();
170
171 cpu.set_sp(cpu.get_sp() - 1);
172 mmu.write(cpu.get_sp(), (pc >> 8) & 0xFF);
173
174 cpu.set_sp(cpu.get_sp() - 1);
175 mmu.write(cpu.get_sp(), pc & 0xFF);
176
177 cpu.set_pc(0x38);
178
179 return totalMachineCycles(4);
180}
Definition mmu.hpp:12