1use crate::{
2 cpu::Cpu,
3 peripherals::{Cable, Joypad, Lcd, Speaker},
4};
5
6pub fn invalid() {
8 log::error!("Encountered an invalid instruction.");
9 panic!("Aborting");
10}
11
12pub fn jp<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, addr: u16)
14where
15 L: Lcd,
16 S: Speaker,
17 J: Joypad,
18 C: Cable,
19{
20 cpu.regs.set_pc(addr);
21}
22
23pub fn jr<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: i8)
25where
26 L: Lcd,
27 S: Speaker,
28 J: Joypad,
29 C: Cable,
30{
31 cpu.regs.set_pc(cpu.regs.pc().wrapping_add(val as u16));
32}
33
34pub fn call<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, addr: u16)
36where
37 L: Lcd,
38 S: Speaker,
39 J: Joypad,
40 C: Cable,
41{
42 cpu.stack_push(cpu.regs.pc());
43 jp(cpu, addr);
44}
45
46pub fn ret<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>)
48where
49 L: Lcd,
50 S: Speaker,
51 J: Joypad,
52 C: Cable,
53{
54 let addr = cpu.stack_pop();
55 jp(cpu, addr);
56}
57
58pub fn daa<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>)
61where
62 L: Lcd,
63 S: Speaker,
64 J: Joypad,
65 C: Cable,
66{
67 let mut res = cpu.regs.a() as u16;
68 if !cpu.regs.flags().n() {
69 if cpu.regs.flags().h() || (res & 0x0f) > 0x09 {
70 res = res.wrapping_add(0x06);
71 }
72 if cpu.regs.flags().c() || res > 0x9f {
73 res = res.wrapping_add(0x60);
74 cpu.regs.flags_mut().set_c(true);
75 }
76 } else {
77 if cpu.regs.flags().h() {
78 res = res.wrapping_sub(0x06);
79 }
80 if cpu.regs.flags().c() {
81 res = res.wrapping_sub(0x60);
82 }
83 }
84
85 cpu.regs.flags_mut().set_z(res as u8 == 0);
86 cpu.regs.flags_mut().set_h(false);
87
88 cpu.regs.set_a(res as u8);
89}
90
91pub fn cpl<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>)
94where
95 L: Lcd,
96 S: Speaker,
97 J: Joypad,
98 C: Cable,
99{
100 cpu.regs.flags_mut().set_n(true);
101 cpu.regs.flags_mut().set_h(true);
102
103 cpu.regs.set_a(!cpu.regs.a());
104}
105
106pub fn scf<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>)
109where
110 L: Lcd,
111 S: Speaker,
112 J: Joypad,
113 C: Cable,
114{
115 cpu.regs.flags_mut().set_n(false);
116 cpu.regs.flags_mut().set_h(false);
117 cpu.regs.flags_mut().set_c(true);
118}
119
120pub fn ccf<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>)
123where
124 L: Lcd,
125 S: Speaker,
126 J: Joypad,
127 C: Cable,
128{
129 let c = cpu.regs.flags().c();
130
131 cpu.regs.flags_mut().set_n(false);
132 cpu.regs.flags_mut().set_h(false);
133 cpu.regs.flags_mut().set_c(!c);
134}
135
136pub fn inc<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
139where
140 L: Lcd,
141 S: Speaker,
142 J: Joypad,
143 C: Cable,
144{
145 let res = val.wrapping_add(1);
146
147 cpu.regs.flags_mut().set_z(res == 0);
148 cpu.regs.flags_mut().set_n(false);
149 cpu.regs.flags_mut().set_h((val & 0x0f) == 0x0f);
150
151 res
152}
153
154pub fn dec<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
157where
158 L: Lcd,
159 S: Speaker,
160 J: Joypad,
161 C: Cable,
162{
163 let res = val.wrapping_sub(1);
164
165 cpu.regs.flags_mut().set_z(res == 0);
166 cpu.regs.flags_mut().set_n(true);
167 cpu.regs.flags_mut().set_h((val & 0x0f) == 0x00);
168
169 res
170}
171
172pub fn add<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
175where
176 L: Lcd,
177 S: Speaker,
178 J: Joypad,
179 C: Cable,
180{
181 let a = cpu.regs.a();
182 let res = a as u16 + val as u16;
183
184 cpu.regs.flags_mut().set_z(res as u8 == 0);
185 cpu.regs.flags_mut().set_n(false);
186 cpu.regs.flags_mut().set_h((a & 0x0f) + (val & 0x0f) > 0x0f);
187 cpu.regs.flags_mut().set_c(res > 0xff);
188
189 cpu.regs.set_a(res as u8);
190}
191
192pub fn add_hl<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u16)
195where
196 L: Lcd,
197 S: Speaker,
198 J: Joypad,
199 C: Cable,
200{
201 let hl = cpu.regs.hl();
202 let res = hl as u32 + val as u32;
203
204 cpu.regs.flags_mut().set_n(false);
205 cpu.regs
206 .flags_mut()
207 .set_h((hl & 0xfff) + (val & 0xfff) > 0xfff);
208 cpu.regs.flags_mut().set_c(res > 0xffff);
209
210 cpu.regs.set_hl(res as u16);
211}
212
213pub fn add_sp<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: i8) -> u16
216where
217 L: Lcd,
218 S: Speaker,
219 J: Joypad,
220 C: Cable,
221{
222 let uval = val as u16;
223 let sp = cpu.regs.sp();
224 let res = sp.wrapping_add(uval);
225
226 cpu.regs.flags_mut().set_z(false);
227 cpu.regs.flags_mut().set_n(false);
228 cpu.regs
229 .flags_mut()
230 .set_h((sp & 0x0f) + (uval & 0x0f) > 0x0f);
231 cpu.regs
232 .flags_mut()
233 .set_c((sp & 0xff) + (uval & 0xff) > 0xff);
234
235 res
236}
237
238pub fn adc<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
241where
242 L: Lcd,
243 S: Speaker,
244 J: Joypad,
245 C: Cable,
246{
247 let a = cpu.regs.a();
248 let c = cpu.regs.flags().c() as u8;
249 let res = a as u16 + val as u16 + c as u16;
250
251 cpu.regs.flags_mut().set_z(res as u8 == 0);
252 cpu.regs.flags_mut().set_n(false);
253 cpu.regs
254 .flags_mut()
255 .set_h((a & 0x0f) + (val & 0x0f) + c > 0x0f);
256 cpu.regs.flags_mut().set_c(res > 0xff);
257
258 cpu.regs.set_a(res as u8);
259}
260
261pub fn sub<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
264where
265 L: Lcd,
266 S: Speaker,
267 J: Joypad,
268 C: Cable,
269{
270 let a = cpu.regs.a();
271 let res = a.wrapping_sub(val);
272
273 cpu.regs.flags_mut().set_z(res == 0);
274 cpu.regs.flags_mut().set_n(true);
275 cpu.regs.flags_mut().set_h((a & 0x0f) < (val & 0x0f));
276 cpu.regs.flags_mut().set_c(a < val);
277
278 cpu.regs.set_a(res);
279}
280
281pub fn sbc<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
284where
285 L: Lcd,
286 S: Speaker,
287 J: Joypad,
288 C: Cable,
289{
290 let a = cpu.regs.a();
291 let c = cpu.regs.flags().c() as u8;
292 let res = (a as u16).wrapping_sub(val as u16).wrapping_sub(c as u16);
293
294 cpu.regs.flags_mut().set_z(res as u8 == 0);
295 cpu.regs.flags_mut().set_n(true);
296 cpu.regs.flags_mut().set_h((a & 0x0f) < ((val & 0x0f) + c));
297 cpu.regs.flags_mut().set_c(res > 0xff);
298
299 cpu.regs.set_a(res as u8);
300}
301
302pub fn and<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
305where
306 L: Lcd,
307 S: Speaker,
308 J: Joypad,
309 C: Cable,
310{
311 let a = cpu.regs.a();
312 let res = a & val;
313
314 cpu.regs.flags_mut().set_z(res == 0);
315 cpu.regs.flags_mut().set_n(false);
316 cpu.regs.flags_mut().set_h(true);
317 cpu.regs.flags_mut().set_c(false);
318
319 cpu.regs.set_a(res);
320}
321
322pub fn xor<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
325where
326 L: Lcd,
327 S: Speaker,
328 J: Joypad,
329 C: Cable,
330{
331 let a = cpu.regs.a();
332 let res = a ^ val;
333
334 cpu.regs.flags_mut().set_z(res == 0);
335 cpu.regs.flags_mut().set_n(false);
336 cpu.regs.flags_mut().set_h(false);
337 cpu.regs.flags_mut().set_c(false);
338
339 cpu.regs.set_a(res);
340}
341
342pub fn or<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
345where
346 L: Lcd,
347 S: Speaker,
348 J: Joypad,
349 C: Cable,
350{
351 let a = cpu.regs.a();
352 let res = a | val;
353
354 cpu.regs.flags_mut().set_z(res == 0);
355 cpu.regs.flags_mut().set_n(false);
356 cpu.regs.flags_mut().set_h(false);
357 cpu.regs.flags_mut().set_c(false);
358
359 cpu.regs.set_a(res);
360}
361
362pub fn cp<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8)
366where
367 L: Lcd,
368 S: Speaker,
369 J: Joypad,
370 C: Cable,
371{
372 let a = cpu.regs.a();
373
374 cpu.regs.flags_mut().set_z(a == val);
375 cpu.regs.flags_mut().set_n(true);
376 cpu.regs.flags_mut().set_h((a & 0x0f) < (val & 0x0f));
377 cpu.regs.flags_mut().set_c(a < val);
378}
379
380pub fn rlc<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
383where
384 L: Lcd,
385 S: Speaker,
386 J: Joypad,
387 C: Cable,
388{
389 let bit = val >> 7;
390 let res = (val << 1) | bit;
391
392 cpu.regs.flags_mut().set_z(res == 0);
393 cpu.regs.flags_mut().set_n(false);
394 cpu.regs.flags_mut().set_h(false);
395 cpu.regs.flags_mut().set_c(bit != 0);
396
397 res
398}
399
400pub fn rrc<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
403where
404 L: Lcd,
405 S: Speaker,
406 J: Joypad,
407 C: Cable,
408{
409 let bit = val & 0x01;
410 let res = (val >> 1) | (bit << 7);
411
412 cpu.regs.flags_mut().set_z(res == 0);
413 cpu.regs.flags_mut().set_n(false);
414 cpu.regs.flags_mut().set_h(false);
415 cpu.regs.flags_mut().set_c(bit != 0);
416
417 res
418}
419
420pub fn rl<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
423where
424 L: Lcd,
425 S: Speaker,
426 J: Joypad,
427 C: Cable,
428{
429 let c = cpu.regs.flags().c() as u8;
430 let bit = val >> 7;
431 let res = (val << 1) | c;
432
433 cpu.regs.flags_mut().set_z(res == 0);
434 cpu.regs.flags_mut().set_n(false);
435 cpu.regs.flags_mut().set_h(false);
436 cpu.regs.flags_mut().set_c(bit != 0);
437
438 res
439}
440
441pub fn rr<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
444where
445 L: Lcd,
446 S: Speaker,
447 J: Joypad,
448 C: Cable,
449{
450 let c = cpu.regs.flags().c() as u8;
451 let bit = val & 0x01;
452 let res = (val >> 1) | (c << 7);
453
454 cpu.regs.flags_mut().set_z(res == 0);
455 cpu.regs.flags_mut().set_n(false);
456 cpu.regs.flags_mut().set_h(false);
457 cpu.regs.flags_mut().set_c(bit != 0);
458
459 res
460}
461
462pub fn sla<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
466where
467 L: Lcd,
468 S: Speaker,
469 J: Joypad,
470 C: Cable,
471{
472 let bit = val >> 7;
473 let res = val << 1;
474
475 cpu.regs.flags_mut().set_z(res == 0);
476 cpu.regs.flags_mut().set_n(false);
477 cpu.regs.flags_mut().set_h(false);
478 cpu.regs.flags_mut().set_c(bit != 0);
479
480 res
481}
482
483pub fn sra<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
487where
488 L: Lcd,
489 S: Speaker,
490 J: Joypad,
491 C: Cable,
492{
493 let bit = val & 0x01;
494 let res = (val & 0x80) | (val >> 1);
495
496 cpu.regs.flags_mut().set_z(res == 0);
497 cpu.regs.flags_mut().set_n(false);
498 cpu.regs.flags_mut().set_h(false);
499 cpu.regs.flags_mut().set_c(bit != 0);
500
501 res
502}
503
504pub fn swap<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
507where
508 L: Lcd,
509 S: Speaker,
510 J: Joypad,
511 C: Cable,
512{
513 let res = (val << 4) | (val >> 4);
514
515 cpu.regs.flags_mut().set_z(res == 0);
516 cpu.regs.flags_mut().set_n(false);
517 cpu.regs.flags_mut().set_h(false);
518 cpu.regs.flags_mut().set_c(false);
519
520 res
521}
522
523pub fn srl<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, val: u8) -> u8
527where
528 L: Lcd,
529 S: Speaker,
530 J: Joypad,
531 C: Cable,
532{
533 let bit = val & 0x01;
534 let res = val >> 1;
535
536 cpu.regs.flags_mut().set_z(res == 0);
537 cpu.regs.flags_mut().set_n(false);
538 cpu.regs.flags_mut().set_h(false);
539 cpu.regs.flags_mut().set_c(bit != 0);
540
541 res
542}
543
544pub fn bit<L, S, J, C>(cpu: &mut Cpu<L, S, J, C>, bit: u8, val: u8)
548where
549 L: Lcd,
550 S: Speaker,
551 J: Joypad,
552 C: Cable,
553{
554 cpu.regs.flags_mut().set_z((val & (1 << bit)) == 0);
555 cpu.regs.flags_mut().set_n(false);
556 cpu.regs.flags_mut().set_h(true);
557}
558
559pub fn res(bit: u8, val: u8) -> u8 {
562 val & !(1 << bit)
563}
564
565pub fn set(bit: u8, val: u8) -> u8 {
568 val | (1 << bit)
569}