GameBoy Emulator 1
Game Boy emulator core and tooling
Loading...
Searching...
No Matches
op_01.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_stop(ProcessingUnit& cpu, MMU& mmu) // 0x10
11{
12 cpu.setStop(true);
13 return totalMachineCycles(1);
14}
15
16int op_ld_de_d16(ProcessingUnit &cpu, MMU &mmu) // 0x11
17{
18 const u8 lo = mmu.read(cpu.inc_pc());
19 const u8 hi = mmu.read(cpu.inc_pc());
20
21 cpu.reg(ProcessingUnit::Register::D) = hi;
22 cpu.reg(ProcessingUnit::Register::E) = lo;
23
24 return totalMachineCycles(3);
25}
26
27int op_ld_de_a(ProcessingUnit &cpu, MMU &mmu) // 0x12
28{
29 const u16 addr = cpu.get_de(); // DE contains the target address
30 const u8 value = cpu.reg(ProcessingUnit::Register::A);
31
32 mmu.write(addr, value);
33
34 return totalMachineCycles(2);
35}
36
37int op_inc_de(ProcessingUnit& cpu, MMU& mmu) // 0x13
38{
39 const u16 newValue = cpu.get_de() + 1;
40
41 cpu.reg(ProcessingUnit::Register::D) = (newValue >> 8) & 0xFF;
42 cpu.reg(ProcessingUnit::Register::E) = newValue & 0xFF;
43
44 return totalMachineCycles(2);
45}
46
47int op_inc_d(ProcessingUnit& cpu, MMU& mmu) // 0x14
48{
49 const u8 oldValue = cpu.reg(ProcessingUnit::Register::D);
50 const u8 newValue = oldValue + 1;
51 cpu.reg(ProcessingUnit::Register::D) = newValue;
52 cpu.setFlag(ProcessingUnit::Flag::Z, newValue == 0);
53 cpu.setFlag(ProcessingUnit::Flag::N, false);
54 cpu.setFlag(ProcessingUnit::Flag::H, (oldValue & 0x0F) == 0x0F);
55 return totalMachineCycles(1);
56}
57
58int op_dec_d(ProcessingUnit& cpu, MMU& mmu) // 0x15
59{
60 const u8 oldValue = cpu.reg(ProcessingUnit::Register::D);
61 const u8 newValue = oldValue - 1;
62 cpu.reg(ProcessingUnit::Register::D) = newValue;
63 cpu.setFlag(ProcessingUnit::Flag::Z, newValue == 0);
64 cpu.setFlag(ProcessingUnit::Flag::N, true);
65 cpu.setFlag(ProcessingUnit::Flag::H, (oldValue & 0x0F) == 0x00);
66 return totalMachineCycles(1);
67}
68
69int op_ld_d_d8(ProcessingUnit& cpu, MMU& mmu) // 0x16
70{
71 const u8 newValue = mmu.read(cpu.inc_pc());
72
73 cpu.reg(ProcessingUnit::Register::D) = newValue;
74
75 return totalMachineCycles(2);
76}
77
78int op_rla(ProcessingUnit& cpu, MMU& mmu) // 0x17
79{
80 const u8 a = cpu.reg(ProcessingUnit::Register::A);
81 const bool carryIn = cpu.get_flag_c();
82
83 const u8 carryOut = (a >> 7) & 1;
84 const u8 result = static_cast<u8>((a << 1) | (carryIn ? 1 : 0));
85
86 cpu.reg(ProcessingUnit::Register::A) = result;
87
88 cpu.setFlag(ProcessingUnit::Flag::Z, false);
89 cpu.setFlag(ProcessingUnit::Flag::N, false);
90 cpu.setFlag(ProcessingUnit::Flag::H, false);
91 cpu.setFlag(ProcessingUnit::Flag::C, carryOut);
92
93 return totalMachineCycles(1);
94}
95
96int op_jr_r8(ProcessingUnit& cpu, MMU& mmu) // 0x18
97{
98 const int8_t offset = static_cast<int8_t>(mmu.read(cpu.inc_pc()));
99 const u16 target = static_cast<u16>(cpu.get_pc() + offset);
100
101 cpu.set_pc(target);
102
103 return totalMachineCycles(3);
104}
105
106int op_add_hl_de(ProcessingUnit& cpu, MMU& mmu) // 0x19
107{
108 const u16 hl = cpu.get_hl();
109 const u16 de = cpu.get_de();
110 const u32 sum = static_cast<u32>(hl) + de;
111
112 cpu.reg(ProcessingUnit::Register::H) = static_cast<u8>((sum >> 8) & 0xFF);
113 cpu.reg(ProcessingUnit::Register::L) = static_cast<u8>(sum & 0xFF);
114
115 cpu.setFlag(ProcessingUnit::Flag::N, false);
116 cpu.setFlag(ProcessingUnit::Flag::H, ((hl & 0x0FFF) + (de & 0x0FFF)) > 0x0FFF);
117 cpu.setFlag(ProcessingUnit::Flag::C, sum > 0xFFFF);
118
119 return totalMachineCycles(2);
120}
121
122int op_ld_a_de(ProcessingUnit& cpu, MMU& mmu) // 0x1A
123{
124 cpu.reg(ProcessingUnit::Register::A) = mmu.read(cpu.get_de());
125
126 return totalMachineCycles(2);
127}
128
129int op_dec_de(ProcessingUnit& cpu, MMU& mmu) // 0x1B
130{
131 const u16 newValue = cpu.get_de() - 1;
132
133 cpu.reg(ProcessingUnit::Register::D) = static_cast<u8>((newValue >> 8) & 0xFF);
134 cpu.reg(ProcessingUnit::Register::E) = static_cast<u8>(newValue & 0xFF);
135
136 return totalMachineCycles(2);
137}
138
139int op_inc_e(ProcessingUnit& cpu, MMU& mmu) // 0x1C
140{
141 const u8 oldValue = cpu.reg(ProcessingUnit::Register::E);
142 const u8 newValue = oldValue + 1;
143 cpu.reg(ProcessingUnit::Register::E) = newValue;
144
145 cpu.setFlag(ProcessingUnit::Flag::Z, newValue == 0);
146 cpu.setFlag(ProcessingUnit::Flag::N, false);
147 cpu.setFlag(ProcessingUnit::Flag::H, (oldValue & 0x0F) == 0x0F);
148
149 return totalMachineCycles(1);
150}
151
152int op_dec_e(ProcessingUnit& cpu, MMU& mmu) // 0x1D
153{
154 const u8 oldValue = cpu.reg(ProcessingUnit::Register::E);
155 const u8 newValue = oldValue - 1;
156 cpu.reg(ProcessingUnit::Register::E) = newValue;
157
158 cpu.setFlag(ProcessingUnit::Flag::Z, newValue == 0);
159 cpu.setFlag(ProcessingUnit::Flag::N, true);
160 cpu.setFlag(ProcessingUnit::Flag::H, (oldValue & 0x0F) == 0x00);
161
162 return totalMachineCycles(1);
163}
164
165int op_ld_e_d8(ProcessingUnit& cpu, MMU& mmu) // 0x1E
166{
167 cpu.reg(ProcessingUnit::Register::E) = mmu.read(cpu.inc_pc());
168
169 return totalMachineCycles(2);
170}
171
172int op_rra(ProcessingUnit& cpu, MMU& mmu) // 0x1F
173{
174 const u8 a = cpu.reg(ProcessingUnit::Register::A);
175 const bool carryIn = cpu.get_flag_c();
176
177 const u8 carryOut = a & 1;
178 const u8 result = static_cast<u8>((a >> 1) | (carryIn ? 0x80 : 0x00));
179
180 cpu.reg(ProcessingUnit::Register::A) = result;
181
182 cpu.setFlag(ProcessingUnit::Flag::Z, false);
183 cpu.setFlag(ProcessingUnit::Flag::N, false);
184 cpu.setFlag(ProcessingUnit::Flag::H, false);
185 cpu.setFlag(ProcessingUnit::Flag::C, carryOut);
186
187 return totalMachineCycles(1);
188}
Definition mmu.hpp:12