1use super::opcode::Opcode;
2use super::environment::Environment;
3use super::registers::{Flag, Reg16, Reg8};
4
5pub fn build_ld_r_r(dst: Reg8, src: Reg8, _special: bool) -> Opcode {
54 if src != Reg8::_HL && dst != Reg8::_HL
55 && src != Reg8::H && dst != Reg8::H
56 && src != Reg8::L && dst != Reg8::L {
57 Opcode::new(
59 format!("LD {dst}, {src}"),
60 move |env: &mut Environment| {
61 let value = env.state.reg.get8(src);
62 env.state.reg.set8(dst, value);
63 if dst == Reg8::A && (src == Reg8::I || src == Reg8::R) {
64 env.state.reg.update_p_flag_with_iff2();
66 }
67 }
68 )
69 } else {
70 Opcode::new(
72 format!("LD {dst}, {src}"),
73 move |env: &mut Environment| {
74 let value = if dst == Reg8::_HL {
80 env.state.reg.get8(src)
81 } else {
82 env.reg8_ext(src)
83 };
84 if src == Reg8::_HL {
85 env.state.reg.set8(dst, value);
86 } else {
87 env.set_reg(dst, value);
88 }
89 }
90 )
91 }
92}
93
94pub fn build_ld_r_n(r: Reg8) -> Opcode {
95 Opcode::new(
96 format!("LD {r}, n"),
97 move |env: &mut Environment| {
98 let value = env.advance_pc();
99 env.set_reg(r, value);
100 }
101 )
102}
103
104pub fn build_ld_a_prr(rr: Reg16) -> Opcode {
105 Opcode::new(
107 format!("LD A, ({rr:?})"),
108 move |env: &mut Environment| {
109 let address = env.state.reg.get16(rr);
110 let value = env.sys.peek(address);
111 env.state.reg.set_a(value);
112 }
113 )
114}
115
116pub fn build_ld_a_pnn() -> Opcode {
117 Opcode::new(
118 "LD A, (nn)".to_string(),
119 |env: &mut Environment| {
120 let address = env.advance_immediate16();
121 let value = env.sys.peek(address);
122 env.state.reg.set_a(value);
123 }
124 )
125}
126
127pub fn build_ld_prr_a(rr: Reg16) -> Opcode {
128 Opcode::new(
130 format!("LD ({rr:?}), A"),
131 move |env: &mut Environment| {
132 let value = env.state.reg.a();
133 let address = env.state.reg.get16(rr);
134 env.sys.poke(address, value);
135 }
136 )
137}
138
139pub fn build_ld_pnn_a() -> Opcode {
140 Opcode::new(
141 "LD (nn), A".to_string(),
142 |env: &mut Environment| {
143 let value = env.state.reg.a();
144 let address = env.advance_immediate16();
145 env.sys.poke(address, value);
146 }
147 )
148}
149
150
151pub fn build_ld_rr_nn(rr: Reg16) -> Opcode {
153 Opcode::new(
154 format!("LD {rr:?}, nn"),
155 move |env: &mut Environment| {
156 let value = env.advance_immediate16();
157 env.set_reg16(rr, value);
158 }
159 )
160}
161
162pub fn build_ld_sp_hl() -> Opcode {
163 Opcode::new(
164 "LD SP, HL".to_string(),
165 |env: &mut Environment| {
166 let value = env.reg16_ext(Reg16::HL);
167 env.set_reg16(Reg16::SP, value);
168 }
169 )
170}
171
172pub fn build_ld_pnn_rr(rr: Reg16, _fast: bool) -> Opcode {
173 Opcode::new(
174 format!("LD (nn), {rr:?}"),
175 move |env: &mut Environment| {
176 let address = env.advance_immediate16();
177 let value = env.reg16_ext(rr);
178 env.sys.poke16(address, value);
179 }
180 )
181}
182
183pub fn build_ld_rr_pnn(rr: Reg16, _fast: bool) -> Opcode {
184 Opcode::new(
185 format!("LD {rr:?}, (nn)"),
186 move |env: &mut Environment| {
187 let address = env.advance_immediate16();
188 let value = env.sys.peek16(address);
189 env.set_reg16(rr, value);
190 }
191 )
192}
193
194pub fn build_ex_af() -> Opcode {
195 Opcode::new(
196 "EX AF, AF'".to_string(),
197 |env: &mut Environment| {
198 env.state.reg.swap(Reg16::AF);
199 }
200 )
201}
202
203pub fn build_exx() -> Opcode {
204 Opcode::new(
205 "EXX".to_string(),
206 |env: &mut Environment| {
207 env.state.reg.swap(Reg16::BC);
208 env.state.reg.swap(Reg16::DE);
209 env.state.reg.swap(Reg16::HL); }
211 )
212}
213
214pub fn build_ex_de_hl() -> Opcode {
215 Opcode::new(
216 "EX DE, HL".to_string(),
217 |env: &mut Environment| {
218 let temp = env.state.reg.get16(Reg16::HL); env.state.reg.set16(Reg16::HL, env.state.reg.get16(Reg16::DE));
220 env.state.reg.set16(Reg16::DE, temp);
221 }
222 )
223}
224
225pub fn build_ex_psp_hl() -> Opcode {
226 Opcode::new(
227 "EX (SP), HL".to_string(),
228 |env: &mut Environment| {
229 let address = env.state.reg.get16(Reg16::SP);
230
231 let temp = env.reg16_ext(Reg16::HL);
232 env.set_reg16(Reg16::HL, env.sys.peek16(address));
233 env.sys.poke16(address, temp);
234 }
235 )
236}
237
238pub fn build_ld_block((inc, repeat, postfix) : (bool, bool, &'static str)) -> Opcode {
239 Opcode::new(
240 format!("LD{postfix}"),
241 move |env: &mut Environment| {
242 let value = env.reg8_ext(Reg8::_HL);
243 let address = env.state.reg.get16(Reg16::DE);
244 env.sys.poke(address, value);
245
246 env.state.reg.inc_dec16(Reg16::DE, inc);
247 env.state.reg.inc_dec16(Reg16::HL, inc);
248 let bc = env.state.reg.inc_dec16(Reg16::BC, false );
249
250 let n = value.wrapping_add(env.state.reg.a());
252 env.state.reg.update_undocumented_flags_block(n);
253 env.state.reg.clear_flag(Flag::N);
254 env.state.reg.clear_flag(Flag::H);
255 env.state.reg.put_flag(Flag::P, bc != 0);
256 if repeat && bc != 0 {
259 env.set_branch_taken();
261 let pc = env.state.reg.pc().wrapping_sub(2);
262 env.state.reg.set_pc(pc);
263 }
264 }
265 )
266}