1 /*
2 * gbsplay is a Gameboy sound player
3 *
4 * 2003-2005 (C) by Tobias Diedrich <ranma+gbsplay@tdiedrich.de>
5 * Licensed under GNU GPL v1 or, at your option, any later version.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <unistd.h>
13 #include <string.h>
14
15 #include "gbcpu.h"
16
17 #if DEBUG == 1
18 static const char regnames[12] = "BCDEHLFASPPC";
19 static const char *regnamech16[6] = {
20 "BC", "DE", "HL", "AF", "SP", "PC"
21 };
22 static const char *conds[4] = {
23 "NZ", "Z", "NC", "C"
24 };
25 #endif
26
27 struct opinfo;
28
29 typedef void regparm (*ex_fn)(uint32_t op, const struct opinfo *oi);
30
31 struct opinfo {
32 #if DEBUG == 1 || defined(S_SPLINT_S)
33 char *name;
34 #endif
35 ex_fn fn;
36 #if DEBUG == 1
37 char cycles_1;
38 char cycles_2;
39 #endif
40 };
41
42 gbcpu_regs_u gbcpu_regs;
43 long gbcpu_halted;
44 long gbcpu_stopped;
45 long gbcpu_if;
46 long gbcpu_halt_at_pc;
47 long gbcpu_cycles;
48
none_get(uint32_t addr)49 static regparm uint32_t none_get(/*@unused@*/ uint32_t addr)
50 {
51 return 0xff;
52 }
53
none_put(uint32_t addr,uint8_t val)54 static regparm void none_put(/*@unused@*/ uint32_t addr, /*@unused@*/ uint8_t val)
55 {
56 }
57
58 static gbcpu_get_fn getlookup[256] = {
59 &none_get,
60 &none_get,
61 &none_get,
62 &none_get,
63 &none_get,
64 &none_get,
65 &none_get,
66 &none_get,
67 &none_get,
68 &none_get,
69 &none_get,
70 &none_get,
71 &none_get,
72 &none_get,
73 &none_get,
74 &none_get,
75 &none_get,
76 &none_get,
77 &none_get,
78 &none_get,
79 &none_get,
80 &none_get,
81 &none_get,
82 &none_get,
83 &none_get,
84 &none_get,
85 &none_get,
86 &none_get,
87 &none_get,
88 &none_get,
89 &none_get,
90 &none_get,
91 &none_get,
92 &none_get,
93 &none_get,
94 &none_get,
95 &none_get,
96 &none_get,
97 &none_get,
98 &none_get,
99 &none_get,
100 &none_get,
101 &none_get,
102 &none_get,
103 &none_get,
104 &none_get,
105 &none_get,
106 &none_get,
107 &none_get,
108 &none_get,
109 &none_get,
110 &none_get,
111 &none_get,
112 &none_get,
113 &none_get,
114 &none_get,
115 &none_get,
116 &none_get,
117 &none_get,
118 &none_get,
119 &none_get,
120 &none_get,
121 &none_get,
122 &none_get,
123 &none_get,
124 &none_get,
125 &none_get,
126 &none_get,
127 &none_get,
128 &none_get,
129 &none_get,
130 &none_get,
131 &none_get,
132 &none_get,
133 &none_get,
134 &none_get,
135 &none_get,
136 &none_get,
137 &none_get,
138 &none_get,
139 &none_get,
140 &none_get,
141 &none_get,
142 &none_get,
143 &none_get,
144 &none_get,
145 &none_get,
146 &none_get,
147 &none_get,
148 &none_get,
149 &none_get,
150 &none_get,
151 &none_get,
152 &none_get,
153 &none_get,
154 &none_get,
155 &none_get,
156 &none_get,
157 &none_get,
158 &none_get,
159 &none_get,
160 &none_get,
161 &none_get,
162 &none_get,
163 &none_get,
164 &none_get,
165 &none_get,
166 &none_get,
167 &none_get,
168 &none_get,
169 &none_get,
170 &none_get,
171 &none_get,
172 &none_get,
173 &none_get,
174 &none_get,
175 &none_get,
176 &none_get,
177 &none_get,
178 &none_get,
179 &none_get,
180 &none_get,
181 &none_get,
182 &none_get,
183 &none_get,
184 &none_get,
185 &none_get,
186 &none_get,
187 &none_get,
188 &none_get,
189 &none_get,
190 &none_get,
191 &none_get,
192 &none_get,
193 &none_get,
194 &none_get,
195 &none_get,
196 &none_get,
197 &none_get,
198 &none_get,
199 &none_get,
200 &none_get,
201 &none_get,
202 &none_get,
203 &none_get,
204 &none_get,
205 &none_get,
206 &none_get,
207 &none_get,
208 &none_get,
209 &none_get,
210 &none_get,
211 &none_get,
212 &none_get,
213 &none_get,
214 &none_get,
215 &none_get,
216 &none_get,
217 &none_get,
218 &none_get,
219 &none_get,
220 &none_get,
221 &none_get,
222 &none_get,
223 &none_get,
224 &none_get,
225 &none_get,
226 &none_get,
227 &none_get,
228 &none_get,
229 &none_get,
230 &none_get,
231 &none_get,
232 &none_get,
233 &none_get,
234 &none_get,
235 &none_get,
236 &none_get,
237 &none_get,
238 &none_get,
239 &none_get,
240 &none_get,
241 &none_get,
242 &none_get,
243 &none_get,
244 &none_get,
245 &none_get,
246 &none_get,
247 &none_get,
248 &none_get,
249 &none_get,
250 &none_get,
251 &none_get,
252 &none_get,
253 &none_get,
254 &none_get,
255 &none_get,
256 &none_get,
257 &none_get,
258 &none_get,
259 &none_get,
260 &none_get,
261 &none_get,
262 &none_get,
263 &none_get,
264 &none_get,
265 &none_get,
266 &none_get,
267 &none_get,
268 &none_get,
269 &none_get,
270 &none_get,
271 &none_get,
272 &none_get,
273 &none_get,
274 &none_get,
275 &none_get,
276 &none_get,
277 &none_get,
278 &none_get,
279 &none_get,
280 &none_get,
281 &none_get,
282 &none_get,
283 &none_get,
284 &none_get,
285 &none_get,
286 &none_get,
287 &none_get,
288 &none_get,
289 &none_get,
290 &none_get,
291 &none_get,
292 &none_get,
293 &none_get,
294 &none_get,
295 &none_get,
296 &none_get,
297 &none_get,
298 &none_get,
299 &none_get,
300 &none_get,
301 &none_get,
302 &none_get,
303 &none_get,
304 &none_get,
305 &none_get,
306 &none_get,
307 &none_get,
308 &none_get,
309 &none_get,
310 &none_get,
311 &none_get,
312 &none_get,
313 &none_get,
314 &none_get
315 };
316
317 static gbcpu_put_fn putlookup[256] = {
318 &none_put,
319 &none_put,
320 &none_put,
321 &none_put,
322 &none_put,
323 &none_put,
324 &none_put,
325 &none_put,
326 &none_put,
327 &none_put,
328 &none_put,
329 &none_put,
330 &none_put,
331 &none_put,
332 &none_put,
333 &none_put,
334 &none_put,
335 &none_put,
336 &none_put,
337 &none_put,
338 &none_put,
339 &none_put,
340 &none_put,
341 &none_put,
342 &none_put,
343 &none_put,
344 &none_put,
345 &none_put,
346 &none_put,
347 &none_put,
348 &none_put,
349 &none_put,
350 &none_put,
351 &none_put,
352 &none_put,
353 &none_put,
354 &none_put,
355 &none_put,
356 &none_put,
357 &none_put,
358 &none_put,
359 &none_put,
360 &none_put,
361 &none_put,
362 &none_put,
363 &none_put,
364 &none_put,
365 &none_put,
366 &none_put,
367 &none_put,
368 &none_put,
369 &none_put,
370 &none_put,
371 &none_put,
372 &none_put,
373 &none_put,
374 &none_put,
375 &none_put,
376 &none_put,
377 &none_put,
378 &none_put,
379 &none_put,
380 &none_put,
381 &none_put,
382 &none_put,
383 &none_put,
384 &none_put,
385 &none_put,
386 &none_put,
387 &none_put,
388 &none_put,
389 &none_put,
390 &none_put,
391 &none_put,
392 &none_put,
393 &none_put,
394 &none_put,
395 &none_put,
396 &none_put,
397 &none_put,
398 &none_put,
399 &none_put,
400 &none_put,
401 &none_put,
402 &none_put,
403 &none_put,
404 &none_put,
405 &none_put,
406 &none_put,
407 &none_put,
408 &none_put,
409 &none_put,
410 &none_put,
411 &none_put,
412 &none_put,
413 &none_put,
414 &none_put,
415 &none_put,
416 &none_put,
417 &none_put,
418 &none_put,
419 &none_put,
420 &none_put,
421 &none_put,
422 &none_put,
423 &none_put,
424 &none_put,
425 &none_put,
426 &none_put,
427 &none_put,
428 &none_put,
429 &none_put,
430 &none_put,
431 &none_put,
432 &none_put,
433 &none_put,
434 &none_put,
435 &none_put,
436 &none_put,
437 &none_put,
438 &none_put,
439 &none_put,
440 &none_put,
441 &none_put,
442 &none_put,
443 &none_put,
444 &none_put,
445 &none_put,
446 &none_put,
447 &none_put,
448 &none_put,
449 &none_put,
450 &none_put,
451 &none_put,
452 &none_put,
453 &none_put,
454 &none_put,
455 &none_put,
456 &none_put,
457 &none_put,
458 &none_put,
459 &none_put,
460 &none_put,
461 &none_put,
462 &none_put,
463 &none_put,
464 &none_put,
465 &none_put,
466 &none_put,
467 &none_put,
468 &none_put,
469 &none_put,
470 &none_put,
471 &none_put,
472 &none_put,
473 &none_put,
474 &none_put,
475 &none_put,
476 &none_put,
477 &none_put,
478 &none_put,
479 &none_put,
480 &none_put,
481 &none_put,
482 &none_put,
483 &none_put,
484 &none_put,
485 &none_put,
486 &none_put,
487 &none_put,
488 &none_put,
489 &none_put,
490 &none_put,
491 &none_put,
492 &none_put,
493 &none_put,
494 &none_put,
495 &none_put,
496 &none_put,
497 &none_put,
498 &none_put,
499 &none_put,
500 &none_put,
501 &none_put,
502 &none_put,
503 &none_put,
504 &none_put,
505 &none_put,
506 &none_put,
507 &none_put,
508 &none_put,
509 &none_put,
510 &none_put,
511 &none_put,
512 &none_put,
513 &none_put,
514 &none_put,
515 &none_put,
516 &none_put,
517 &none_put,
518 &none_put,
519 &none_put,
520 &none_put,
521 &none_put,
522 &none_put,
523 &none_put,
524 &none_put,
525 &none_put,
526 &none_put,
527 &none_put,
528 &none_put,
529 &none_put,
530 &none_put,
531 &none_put,
532 &none_put,
533 &none_put,
534 &none_put,
535 &none_put,
536 &none_put,
537 &none_put,
538 &none_put,
539 &none_put,
540 &none_put,
541 &none_put,
542 &none_put,
543 &none_put,
544 &none_put,
545 &none_put,
546 &none_put,
547 &none_put,
548 &none_put,
549 &none_put,
550 &none_put,
551 &none_put,
552 &none_put,
553 &none_put,
554 &none_put,
555 &none_put,
556 &none_put,
557 &none_put,
558 &none_put,
559 &none_put,
560 &none_put,
561 &none_put,
562 &none_put,
563 &none_put,
564 &none_put,
565 &none_put,
566 &none_put,
567 &none_put,
568 &none_put,
569 &none_put,
570 &none_put,
571 &none_put,
572 &none_put,
573 &none_put
574 };
575
mem_get(uint32_t addr)576 static inline regparm uint32_t mem_get(uint32_t addr)
577 {
578 gbcpu_get_fn fn = getlookup[(addr >> 8) & 0xff];
579 gbcpu_cycles += 4;
580 return fn(addr);
581 }
582
mem_put(uint32_t addr,uint32_t val)583 static inline regparm void mem_put(uint32_t addr, uint32_t val)
584 {
585 gbcpu_put_fn fn = putlookup[(addr >> 8) & 0xff];
586 gbcpu_cycles += 4;
587 fn(addr, val);
588 }
589
gbcpu_mem_get(uint16_t addr)590 regparm uint8_t gbcpu_mem_get(uint16_t addr)
591 {
592 return mem_get(addr);
593 }
594
gbcpu_mem_put(uint16_t addr,uint8_t val)595 regparm void gbcpu_mem_put(uint16_t addr, uint8_t val)
596 {
597 mem_put(addr, val);
598 }
599
push(uint32_t val)600 static regparm void push(uint32_t val)
601 {
602 uint32_t sp = REGS16_R(gbcpu_regs, SP) - 2;
603 REGS16_W(gbcpu_regs, SP, sp);
604 mem_put(sp, val & 0xff);
605 mem_put(sp+1, val >> 8);
606 }
607
pop(void)608 static regparm uint32_t pop(void)
609 {
610 uint32_t res;
611 uint32_t sp = REGS16_R(gbcpu_regs, SP);
612
613 res = mem_get(sp);
614 res += mem_get(sp+1) << 8;
615 REGS16_W(gbcpu_regs, SP, sp + 2);
616
617 return res;
618 }
619
get_imm8(void)620 static regparm uint32_t get_imm8(void)
621 {
622 uint32_t pc = REGS16_R(gbcpu_regs, PC);
623 uint32_t res;
624 REGS16_W(gbcpu_regs, PC, pc + 1);
625 res = mem_get(pc);
626 DPRINTF("%02x", res);
627 return res;
628 }
629
get_imm16(void)630 static regparm uint32_t get_imm16(void)
631 {
632 uint32_t pc = REGS16_R(gbcpu_regs, PC);
633 uint32_t res;
634 REGS16_W(gbcpu_regs, PC, pc + 2);
635 res = mem_get(pc) + (mem_get(pc+1) << 8);
636 DPRINTF("%04x", res);
637 return res;
638 }
639
print_reg(long i)640 static inline void print_reg(long i)
641 {
642 if (i == 6) DPRINTF("[HL]"); /* indirect memory access by [HL] */
643 else DPRINTF("%c", regnames[i]);
644 }
645
get_reg(long i)646 static regparm uint32_t get_reg(long i)
647 {
648 if (i == 6) /* indirect memory access by [HL] */
649 return mem_get(REGS16_R(gbcpu_regs, HL));
650 return REGS8_R(gbcpu_regs, i);
651 }
652
put_reg(long i,uint32_t val)653 static regparm void put_reg(long i, uint32_t val)
654 {
655 if (i == 6) /* indirect memory access by [HL] */
656 mem_put(REGS16_R(gbcpu_regs, HL), val);
657 else REGS8_W(gbcpu_regs, i, val);
658 }
659
op_unknown(uint32_t op,const struct opinfo * oi)660 static regparm void op_unknown(uint32_t op, /*@unused@*/ const struct opinfo *oi)
661 {
662 fprintf(stderr, "\n\nUnknown opcode %02x.\n", (unsigned char)op);
663 gbcpu_stopped = 1;
664 }
665
op_set(uint32_t op)666 static regparm void op_set(uint32_t op)
667 {
668 long reg = op & 7;
669 unsigned long bit = (op >> 3) & 7;
670
671 DPRINTF("\tSET %ld, ", bit);
672 print_reg(reg);
673 put_reg(reg, get_reg(reg) | (1 << bit));
674 }
675
op_res(uint32_t op)676 static regparm void op_res(uint32_t op)
677 {
678 long reg = op & 7;
679 unsigned long bit = (op >> 3) & 7;
680
681 DPRINTF("\tRES %ld, ", bit);
682 print_reg(reg);
683 put_reg(reg, get_reg(reg) & ~(1 << bit));
684 }
685
op_bit(uint32_t op)686 static regparm void op_bit(uint32_t op)
687 {
688 long reg = op & 7;
689 unsigned long bit = (op >> 3) & 7;
690
691 DPRINTF("\tBIT %ld, ", bit);
692 print_reg(reg);
693 gbcpu_regs.rn.f &= ~NF;
694 gbcpu_regs.rn.f |= HF | ZF;
695 gbcpu_regs.rn.f ^= ((get_reg(reg) << 8) >> (bit+1)) & ZF;
696 }
697
op_rl(uint32_t op,const struct opinfo * oi)698 static regparm void op_rl(uint32_t op, const struct opinfo *oi)
699 {
700 /* C <- rrrrrrrr <-
701 * | |
702 * --------------
703 */
704 long reg = op & 7;
705 uint8_t res, val;
706
707 DPRINTF(" \t%s ", oi->name);
708 print_reg(reg);
709 res = val = get_reg(reg);
710 res = res << 1;
711 res |= (gbcpu_regs.rn.f & CF) >> 4;
712 gbcpu_regs.rn.f = (val >> 7) << 4;
713 if (res == 0) gbcpu_regs.rn.f |= ZF;
714 put_reg(reg, res);
715 }
716
op_rla(uint32_t op,const struct opinfo * oi)717 static regparm void op_rla(/*@unused@*/ uint32_t op, const struct opinfo *oi)
718 {
719 /* C <- aaaaaaaa <-
720 * | |
721 * --------------
722 */
723 uint8_t res;
724
725 DPRINTF(" \t%s", oi->name);
726 res = gbcpu_regs.rn.a;
727 res = res << 1;
728 res |= (gbcpu_regs.rn.f & CF) >> 4;
729 gbcpu_regs.rn.f = (gbcpu_regs.rn.a >> 7) << 4;
730 gbcpu_regs.rn.a = res;
731 }
732
op_rlc(uint32_t op,const struct opinfo * oi)733 static regparm void op_rlc(uint32_t op, const struct opinfo *oi)
734 {
735 /* C <- rrrrrrrr <-
736 * | |
737 * -----------
738 */
739 long reg = op & 7;
740 uint8_t res, val;
741
742 DPRINTF(" \t%s ", oi->name);
743 print_reg(reg);
744 res = val = get_reg(reg);
745 res = res << 1;
746 res |= val >> 7;
747 gbcpu_regs.rn.f = (val >> 7) << 4;
748 if (res == 0) gbcpu_regs.rn.f |= ZF;
749 put_reg(reg, res);
750 }
751
op_rlca(uint32_t op,const struct opinfo * oi)752 static regparm void op_rlca(/*@unused@*/ uint32_t op, const struct opinfo *oi)
753 {
754 /* C <- aaaaaaaa <-
755 * | |
756 * -----------
757 */
758 uint8_t res;
759
760 DPRINTF(" \t%s", oi->name);
761 res = gbcpu_regs.rn.a;
762 res = res << 1;
763 res |= gbcpu_regs.rn.a >> 7;
764 gbcpu_regs.rn.f = (gbcpu_regs.rn.a >> 7) << 4;
765 gbcpu_regs.rn.a = res;
766 }
767
op_sla(uint32_t op,const struct opinfo * oi)768 static regparm void op_sla(uint32_t op, const struct opinfo *oi)
769 {
770 long reg = op & 7;
771 uint8_t res, val;
772
773 DPRINTF(" \t%s ", oi->name);
774 print_reg(reg);
775 res = val = get_reg(reg);
776 res = res << 1;
777 gbcpu_regs.rn.f = (val >> 7) << 4;
778 if (res == 0) gbcpu_regs.rn.f |= ZF;
779 put_reg(reg, res);
780 }
781
op_rr(uint32_t op,const struct opinfo * oi)782 static regparm void op_rr(uint32_t op, const struct opinfo *oi)
783 {
784 long reg = op & 7;
785 uint8_t res, val;
786
787 DPRINTF(" \t%s ", oi->name);
788 print_reg(reg);
789 res = val = get_reg(reg);
790 res = res >> 1;
791 res |= (gbcpu_regs.rn.f & CF) << 3;
792 gbcpu_regs.rn.f = (val & 1) << 4;
793 if (res == 0) gbcpu_regs.rn.f |= ZF;
794 put_reg(reg, res);
795 }
796
op_rra(uint32_t op,const struct opinfo * oi)797 static regparm void op_rra(/*@unused@*/ uint32_t op, const struct opinfo *oi)
798 {
799 uint8_t res;
800
801 DPRINTF(" \t%s", oi->name);
802 res = gbcpu_regs.rn.a;
803 res = res >> 1;
804 res |= (gbcpu_regs.rn.f & CF) << 3;
805 gbcpu_regs.rn.f = (gbcpu_regs.rn.a & 1) << 4;
806 gbcpu_regs.rn.a = res;
807 }
808
op_rrc(uint32_t op,const struct opinfo * oi)809 static regparm void op_rrc(uint32_t op, const struct opinfo *oi)
810 {
811 long reg = op & 7;
812 uint8_t res, val;
813
814 DPRINTF(" \t%s ", oi->name);
815 print_reg(reg);
816 res = val = get_reg(reg);
817 res = res >> 1;
818 res |= val << 7;
819 gbcpu_regs.rn.f = (val & 1) << 4;
820 if (res == 0) gbcpu_regs.rn.f |= ZF;
821 put_reg(reg, res);
822 }
823
op_rrca(uint32_t op,const struct opinfo * oi)824 static regparm void op_rrca(/*@unused@*/ uint32_t op, const struct opinfo *oi)
825 {
826 uint8_t res;
827
828 DPRINTF(" \t%s", oi->name);
829 res = gbcpu_regs.rn.a;
830 res = res >> 1;
831 res |= gbcpu_regs.rn.a << 7;
832 gbcpu_regs.rn.f = (gbcpu_regs.rn.a & 1) << 4;
833 gbcpu_regs.rn.a = res;
834 }
835
op_sra(uint32_t op,const struct opinfo * oi)836 static regparm void op_sra(uint32_t op, const struct opinfo *oi)
837 {
838 long reg = op & 7;
839 uint8_t res, val;
840
841 DPRINTF(" \t%s ", oi->name);
842 print_reg(reg);
843 res = val = get_reg(reg);
844 res = res >> 1;
845 res |= val & 0x80;
846 gbcpu_regs.rn.f = (val & 1) << 4;
847 if (res == 0) gbcpu_regs.rn.f |= ZF;
848 put_reg(reg, res);
849 }
850
op_srl(uint32_t op,const struct opinfo * oi)851 static regparm void op_srl(uint32_t op, const struct opinfo *oi)
852 {
853 long reg = op & 7;
854 uint8_t res, val;
855
856 DPRINTF(" \t%s ", oi->name);
857 print_reg(reg);
858 res = val = get_reg(reg);
859 res = res >> 1;
860 gbcpu_regs.rn.f = (val & 1) << 4;
861 if (res == 0) gbcpu_regs.rn.f |= ZF;
862 put_reg(reg, res);
863 }
864
op_swap(uint32_t op,const struct opinfo * oi)865 static regparm void op_swap(uint32_t op, const struct opinfo *oi)
866 {
867 long reg = op & 7;
868 uint32_t res;
869 uint32_t val;
870
871 DPRINTF(" \t%s ", oi->name);
872 print_reg(reg);
873 val = get_reg(reg);
874 res = (val >> 4) |
875 (val << 4);
876 gbcpu_regs.rn.f = 0;
877 if (res == 0) gbcpu_regs.rn.f |= ZF;
878 put_reg(reg, res);
879 }
880
881 static const struct opinfo cbops[8] = {
882 OPINFO("RLC", &op_rlc, 0, 0), /* opcode cb00-cb07 */
883 OPINFO("RRC", &op_rrc, 0, 0), /* opcode cb08-cb0f */
884 OPINFO("RL", &op_rl, 0, 0), /* opcode cb10-cb17 */
885 OPINFO("RR", &op_rr, 0, 0), /* opcode cb18-cb1f */
886 OPINFO("SLA", &op_sla, 0, 0), /* opcode cb20-cb27 */
887 OPINFO("SRA", &op_sra, 0, 0), /* opcode cb28-cb2f */
888 OPINFO("SWAP", &op_swap, 0, 0), /* opcode cb30-cb37 */
889 OPINFO("SRL", &op_srl, 0, 0), /* opcode cb38-cb3f */
890 };
891
op_cbprefix(uint32_t op,const struct opinfo * oi)892 static regparm void op_cbprefix(uint32_t op, /*@unused@*/ const struct opinfo *oi)
893 {
894 uint16_t pc = REGS16_R(gbcpu_regs, PC);
895
896 REGS16_W(gbcpu_regs, PC, pc + 1);
897 op = mem_get(pc);
898 switch (op >> 6) {
899 case 0: cbops[(op >> 3) & 7].fn(op, &cbops[(op >> 3) & 7]);
900 return;
901 case 1: op_bit(op); return;
902 case 2: op_res(op); return;
903 case 3: op_set(op); return;
904 }
905 fprintf(stderr, "\n\nUnknown CB subopcode %02x.\n", (unsigned char)op);
906 gbcpu_stopped = 1;
907 }
908
op_ld(uint32_t op,const struct opinfo * oi)909 static regparm void op_ld(uint32_t op, const struct opinfo *oi)
910 {
911 long src = op & 7;
912 long dst = (op >> 3) & 7;
913
914 DPRINTF(" \t%s ", oi->name);
915 print_reg(dst);
916 DPRINTF(", ");
917 print_reg(src);
918 put_reg(dst, get_reg(src));
919 }
920
op_ld_imm(uint32_t op,const struct opinfo * oi)921 static regparm void op_ld_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
922 {
923 long ofs = get_imm16();
924
925 DPRINTF(" \t%s A, [0x%04lx]", oi->name, ofs);
926 gbcpu_regs.rn.a = mem_get(ofs);
927 }
928
op_ld_ind16_a(uint32_t op,const struct opinfo * oi)929 static regparm void op_ld_ind16_a(/*@unused@*/ uint32_t op, const struct opinfo *oi)
930 {
931 long ofs = get_imm16();
932
933 DPRINTF(" \t%s [0x%04lx], A", oi->name, ofs);
934 mem_put(ofs, gbcpu_regs.rn.a);
935 }
936
op_ld_ind16_sp(uint32_t op,const struct opinfo * oi)937 static regparm void op_ld_ind16_sp(/*@unused@*/ uint32_t op, const struct opinfo *oi)
938 {
939 long ofs = get_imm16();
940 long sp = REGS16_R(gbcpu_regs, SP);
941
942 DPRINTF(" \t%s [0x%04lx], SP", oi->name, ofs);
943 mem_put(ofs, sp & 0xff);
944 mem_put(ofs+1, sp >> 8);
945 }
946
op_ld_hlsp(uint32_t op,const struct opinfo * oi)947 static regparm void op_ld_hlsp(/*@unused@*/ uint32_t op, const struct opinfo *oi)
948 {
949 int8_t ofs = get_imm8();
950 uint16_t old = REGS16_R(gbcpu_regs, SP);
951 uint16_t new = old + ofs;
952
953 if (ofs>0) DPRINTF(" \t%s HL, SP+0x%02x", oi->name, ofs);
954 else DPRINTF(" \t%s HL, SP-0x%02x", oi->name, -ofs);
955 REGS16_W(gbcpu_regs, HL, new);
956 gbcpu_regs.rn.f = 0;
957 /* flags are based on LOW-BYTE */
958 if ((old & 0xff) > (new & 0xff)) gbcpu_regs.rn.f |= CF;
959 if ((old & 0xf) > (new & 0xf)) gbcpu_regs.rn.f |= HF;
960 // 4 extra cycles.
961 gbcpu_cycles += 4;
962 }
963
op_ld_sphl(uint32_t op,const struct opinfo * oi)964 static regparm void op_ld_sphl(/*@unused@*/ uint32_t op, const struct opinfo *oi)
965 {
966 DPRINTF(" \t%s SP, HL", oi->name);
967 REGS16_W(gbcpu_regs, SP, REGS16_R(gbcpu_regs, HL));
968 // 4 extra cycles.
969 gbcpu_cycles += 4;
970 }
971
op_ld_reg16_imm(uint32_t op,const struct opinfo * oi)972 static regparm void op_ld_reg16_imm(uint32_t op, const struct opinfo *oi)
973 {
974 long val = get_imm16();
975 long reg = (op >> 4) & 3;
976
977 reg += reg > 2; /* skip over AF */
978 DPRINTF(" \t%s %s, 0x%04lx", oi->name, regnamech16[reg], val);
979 REGS16_W(gbcpu_regs, reg, val);
980 }
981
op_ld_reg16_a(uint32_t op,const struct opinfo * oi)982 static regparm void op_ld_reg16_a(uint32_t op, const struct opinfo *oi)
983 {
984 long reg = (op >> 4) & 3;
985 uint16_t r;
986
987 reg -= reg > 2; /* for HL LDD LDI opcodes */
988 if (op & 8) {
989 DPRINTF(" \t%s A, [%s]", oi->name, regnamech16[reg]);
990 gbcpu_regs.rn.a = mem_get(r = REGS16_R(gbcpu_regs, reg));
991 } else {
992 DPRINTF(" \t%s [%s], A", oi->name, regnamech16[reg]);
993 mem_put(r = REGS16_R(gbcpu_regs, reg), gbcpu_regs.rn.a);
994 }
995
996 if (reg == 2) {
997 r += (((op & 0x10) == 0) << 1)-1;
998 REGS16_W(gbcpu_regs, reg, r);
999 }
1000 }
1001
op_ld_reg8_imm(uint32_t op,const struct opinfo * oi)1002 static regparm void op_ld_reg8_imm(uint32_t op, const struct opinfo *oi)
1003 {
1004 long val = get_imm8();
1005 long reg = (op >> 3) & 7;
1006
1007 DPRINTF(" \t%s ", oi->name);
1008 print_reg(reg);
1009 put_reg(reg, val);
1010 DPRINTF(", 0x%02lx", val);
1011 }
1012
op_ldh(uint32_t op,const struct opinfo * oi)1013 static regparm void op_ldh(uint32_t op, const struct opinfo *oi)
1014 {
1015 long ofs = op & 2 ? 0 : get_imm8();
1016
1017 if (op & 0x10) {
1018 DPRINTF(" \t%s A, ", oi->name);
1019 if ((op & 2) == 0) {
1020 DPRINTF("[%02lx]", ofs);
1021 } else {
1022 ofs = gbcpu_regs.rn.c;
1023 DPRINTF("[C]");
1024 }
1025 gbcpu_regs.rn.a = mem_get(0xff00 + ofs);
1026 } else {
1027 if ((op & 2) == 0) {
1028 DPRINTF(" \t%s [%02lx], A", oi->name, ofs);
1029 } else {
1030 ofs = gbcpu_regs.rn.c;
1031 DPRINTF(" \t%s [C], A", oi->name);
1032 }
1033 mem_put(0xff00 + ofs, gbcpu_regs.rn.a);
1034 }
1035 }
1036
op_inc(uint32_t op,const struct opinfo * oi)1037 static regparm void op_inc(uint32_t op, const struct opinfo *oi)
1038 {
1039 long reg = (op >> 3) & 7;
1040 uint8_t res;
1041 uint8_t old;
1042
1043 DPRINTF(" \t%s ", oi->name);
1044 print_reg(reg);
1045 old = res = get_reg(reg);
1046 res++;
1047 put_reg(reg, res);
1048 gbcpu_regs.rn.f &= ~(NF | ZF | HF);
1049 if (res == 0) gbcpu_regs.rn.f |= ZF;
1050 if ((old & 15) > (res & 15)) gbcpu_regs.rn.f |= HF;
1051 }
1052
op_inc16(uint32_t op,const struct opinfo * oi)1053 static regparm void op_inc16(uint32_t op, const struct opinfo *oi)
1054 {
1055 long reg = (op >> 4) & 3;
1056 uint16_t res;
1057 reg += reg > 2; /* skip over AF */
1058 res = REGS16_R(gbcpu_regs, reg);
1059
1060 DPRINTF(" \t%s %s\t", oi->name, regnamech16[reg]);
1061 res++;
1062 REGS16_W(gbcpu_regs, reg, res);
1063 // 16bit ALU op takes 4 extra cycles.
1064 gbcpu_cycles += 4;
1065 }
1066
op_dec(uint32_t op,const struct opinfo * oi)1067 static regparm void op_dec(uint32_t op, const struct opinfo *oi)
1068 {
1069 long reg = (op >> 3) & 7;
1070 uint8_t res;
1071 uint8_t old;
1072
1073 DPRINTF(" \t%s ", oi->name);
1074 print_reg(reg);
1075 old = res = get_reg(reg);
1076 res--;
1077 put_reg(reg, res);
1078 gbcpu_regs.rn.f |= NF;
1079 gbcpu_regs.rn.f &= ~(ZF | HF);
1080 if (res == 0) gbcpu_regs.rn.f |= ZF;
1081 if ((old & 15) < (res & 15)) gbcpu_regs.rn.f |= HF;
1082 }
1083
op_dec16(uint32_t op,const struct opinfo * oi)1084 static regparm void op_dec16(uint32_t op, const struct opinfo *oi)
1085 {
1086 long reg = (op >> 4) & 3;
1087 uint16_t res;
1088 reg += reg > 2; /* skip over AF */
1089 res = REGS16_R(gbcpu_regs, reg);
1090
1091 DPRINTF(" \t%s %s", oi->name, regnamech16[reg]);
1092 res--;
1093 REGS16_W(gbcpu_regs, reg, res);
1094 // 16bit ALU op takes 4 extra cycles.
1095 gbcpu_cycles += 4;
1096 }
1097
op_add_sp_imm(uint32_t op,const struct opinfo * oi)1098 static regparm void op_add_sp_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1099 {
1100 int8_t imm = get_imm8();
1101 uint16_t old = REGS16_R(gbcpu_regs, SP);
1102 uint16_t new = old;
1103
1104 DPRINTF(" \t%s SP, %02x", oi->name, imm);
1105 new += imm;
1106 REGS16_W(gbcpu_regs, SP, new);
1107 gbcpu_regs.rn.f = 0;
1108 /* flags are based on LOW-BYTE */
1109 if ((old & 0xff) > (new & 0xff)) gbcpu_regs.rn.f |= CF;
1110 if ((old & 0xf) > (new & 0xf)) gbcpu_regs.rn.f |= HF;
1111 // 8 extra cycles.
1112 gbcpu_cycles += 8;
1113 }
1114
op_add(uint32_t op,const struct opinfo * oi)1115 static regparm void op_add(uint32_t op, const struct opinfo *oi)
1116 {
1117 uint8_t old = gbcpu_regs.rn.a;
1118 uint8_t new;
1119
1120 DPRINTF(" \t%s A, ", oi->name);
1121 print_reg(op & 7);
1122 gbcpu_regs.rn.a += get_reg(op & 7);
1123 new = gbcpu_regs.rn.a;
1124 gbcpu_regs.rn.f = 0;
1125 if (old > new) gbcpu_regs.rn.f |= CF;
1126 if ((old & 15) > (new & 15)) gbcpu_regs.rn.f |= HF;
1127 if (new == 0) gbcpu_regs.rn.f |= ZF;
1128 }
1129
op_add_imm(uint32_t op,const struct opinfo * oi)1130 static regparm void op_add_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1131 {
1132 uint8_t imm = get_imm8();
1133 uint8_t old = gbcpu_regs.rn.a;
1134 uint8_t new = old;
1135
1136 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1137 new += imm;
1138 gbcpu_regs.rn.a = new;
1139 gbcpu_regs.rn.f = 0;
1140 if (old > new) gbcpu_regs.rn.f |= CF;
1141 if ((old & 15) > (new & 15)) gbcpu_regs.rn.f |= HF;
1142 if (new == 0) gbcpu_regs.rn.f |= ZF;
1143 }
1144
op_add_hl(uint32_t op,const struct opinfo * oi)1145 static regparm void op_add_hl(uint32_t op, const struct opinfo *oi)
1146 {
1147 long reg = (op >> 4) & 3;
1148 uint16_t old = REGS16_R(gbcpu_regs, HL);
1149 uint16_t new = old;
1150
1151 reg += reg > 2; /* skip over AF */
1152 DPRINTF(" \t%s HL, %s", oi->name, regnamech16[reg]);
1153
1154 new += REGS16_R(gbcpu_regs, reg);
1155 REGS16_W(gbcpu_regs, HL, new);
1156
1157 gbcpu_regs.rn.f &= ~(NF | CF | HF);
1158 if (old > new) gbcpu_regs.rn.f |= CF;
1159 if ((old & 0xfff) > (new & 0xfff)) gbcpu_regs.rn.f |= HF;
1160
1161 // 4 extra cycles.
1162 gbcpu_cycles += 4;
1163 }
1164
op_adc(uint32_t op,const struct opinfo * oi)1165 static regparm void op_adc(uint32_t op, const struct opinfo *oi)
1166 {
1167 uint8_t reg = get_reg(op & 7);
1168 uint8_t old = gbcpu_regs.rn.a;
1169 long new = old;
1170 long c = (gbcpu_regs.rn.f & CF) > 0;
1171
1172 DPRINTF(" \t%s A, ", oi->name);
1173 print_reg(op & 7);
1174 new += reg;
1175 new += c;
1176 gbcpu_regs.rn.f = 0;
1177 gbcpu_regs.rn.a = new;
1178 if (new > 0xff) gbcpu_regs.rn.f |= CF;
1179 if ((old & 15) + (reg & 15) + c > 15) gbcpu_regs.rn.f |= HF;
1180 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1181 }
1182
op_adc_imm(uint32_t op,const struct opinfo * oi)1183 static regparm void op_adc_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1184 {
1185 uint8_t imm = get_imm8();
1186 uint8_t old = gbcpu_regs.rn.a;
1187 long new = old;
1188 long c = (gbcpu_regs.rn.f & CF) > 0;
1189
1190 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1191 new += imm;
1192 new += c;
1193 gbcpu_regs.rn.f = 0;
1194 gbcpu_regs.rn.a = new;
1195 if (new > 0xff) gbcpu_regs.rn.f |= CF;
1196 if ((old & 15) + (imm & 15) + c > 15) gbcpu_regs.rn.f |= HF;
1197 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1198 }
1199
op_cp(uint32_t op,const struct opinfo * oi)1200 static regparm void op_cp(uint32_t op, const struct opinfo *oi)
1201 {
1202 uint8_t old = gbcpu_regs.rn.a;
1203 uint8_t new = old;
1204
1205 DPRINTF(" \t%s A, ", oi->name);
1206 print_reg(op & 7);
1207 new -= get_reg(op & 7);
1208 gbcpu_regs.rn.f = NF;
1209 if (old < new) gbcpu_regs.rn.f |= CF;
1210 if ((old & 15) < (new & 15)) gbcpu_regs.rn.f |= HF;
1211 if (new == 0) gbcpu_regs.rn.f |= ZF;
1212 }
1213
op_cp_imm(uint32_t op,const struct opinfo * oi)1214 static regparm void op_cp_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1215 {
1216 uint8_t imm = get_imm8();
1217 uint8_t old = gbcpu_regs.rn.a;
1218 uint8_t new = old;
1219
1220 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1221 new -= imm;
1222 gbcpu_regs.rn.f = NF;
1223 if (old < new) gbcpu_regs.rn.f |= CF;
1224 if ((old & 15) < (new & 15)) gbcpu_regs.rn.f |= HF;
1225 if (new == 0) gbcpu_regs.rn.f |= ZF;
1226 }
1227
op_sub(uint32_t op,const struct opinfo * oi)1228 static regparm void op_sub(uint32_t op, const struct opinfo *oi)
1229 {
1230 uint8_t old = gbcpu_regs.rn.a;
1231 uint8_t new;
1232
1233 DPRINTF(" \t%s A, ", oi->name);
1234 print_reg(op & 7);
1235 gbcpu_regs.rn.a -= get_reg(op & 7);
1236 new = gbcpu_regs.rn.a;
1237 gbcpu_regs.rn.f = NF;
1238 if (old < new) gbcpu_regs.rn.f |= CF;
1239 if ((old & 15) < (new & 15)) gbcpu_regs.rn.f |= HF;
1240 if (new == 0) gbcpu_regs.rn.f |= ZF;
1241 }
1242
op_sub_imm(uint32_t op,const struct opinfo * oi)1243 static regparm void op_sub_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1244 {
1245 uint8_t imm = get_imm8();
1246 uint8_t old = gbcpu_regs.rn.a;
1247 uint8_t new = old;
1248
1249 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1250 new -= imm;
1251 gbcpu_regs.rn.a = new;
1252 gbcpu_regs.rn.f = NF;
1253 if (old < new) gbcpu_regs.rn.f |= CF;
1254 if ((old & 15) < (new & 15)) gbcpu_regs.rn.f |= HF;
1255 if (new == 0) gbcpu_regs.rn.f |= ZF;
1256 }
1257
op_sbc(uint32_t op,const struct opinfo * oi)1258 static regparm void op_sbc(uint32_t op, const struct opinfo *oi)
1259 {
1260 uint8_t reg = get_reg(op & 7);
1261 uint8_t old = gbcpu_regs.rn.a;
1262 long new = old + 0x100;
1263 long c = (gbcpu_regs.rn.f & CF) > 0;
1264
1265 DPRINTF(" \t%s A, ", oi->name);
1266 print_reg(op & 7);
1267 new -= reg;
1268 new -= c;
1269 gbcpu_regs.rn.a = new;
1270 gbcpu_regs.rn.f = NF;
1271 if (new < 0x100) gbcpu_regs.rn.f |= CF;
1272 if ((old & 15) - (reg & 15) - c < 0) gbcpu_regs.rn.f |= HF;
1273 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1274 }
1275
op_sbc_imm(uint32_t op,const struct opinfo * oi)1276 static regparm void op_sbc_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1277 {
1278 uint8_t imm = get_imm8();
1279 uint8_t old = gbcpu_regs.rn.a;
1280 long new = old + 0x100;
1281 long c = (gbcpu_regs.rn.f & CF) > 0;
1282
1283 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1284 new -= imm;
1285 new -= c;
1286 gbcpu_regs.rn.a = new;
1287 gbcpu_regs.rn.f = NF;
1288 if (new < 0x100) gbcpu_regs.rn.f |= CF;
1289 if ((old & 15) - (imm & 15) - c < 0) gbcpu_regs.rn.f |= HF;
1290 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1291 }
1292
op_and(uint32_t op,const struct opinfo * oi)1293 static regparm void op_and(uint32_t op, const struct opinfo *oi)
1294 {
1295 DPRINTF(" \t%s A, ", oi->name);
1296 print_reg(op & 7);
1297 gbcpu_regs.rn.a &= get_reg(op & 7);
1298 gbcpu_regs.rn.f = HF;
1299 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1300 }
1301
op_and_imm(uint32_t op,const struct opinfo * oi)1302 static regparm void op_and_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1303 {
1304 uint8_t imm = get_imm8();
1305
1306 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1307 gbcpu_regs.rn.a &= imm;
1308 gbcpu_regs.rn.f = HF;
1309 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1310 }
1311
op_or(uint32_t op,const struct opinfo * oi)1312 static regparm void op_or(uint32_t op, const struct opinfo *oi)
1313 {
1314 DPRINTF(" \t%s A, ", oi->name);
1315 print_reg(op & 7);
1316 gbcpu_regs.rn.a |= get_reg(op & 7);
1317 gbcpu_regs.rn.f = 0;
1318 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1319 }
1320
op_or_imm(uint32_t op,const struct opinfo * oi)1321 static regparm void op_or_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1322 {
1323 uint8_t imm = get_imm8();
1324
1325 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1326 gbcpu_regs.rn.a |= imm;
1327 gbcpu_regs.rn.f = 0;
1328 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1329 }
1330
op_xor(uint32_t op,const struct opinfo * oi)1331 static regparm void op_xor(uint32_t op, const struct opinfo *oi)
1332 {
1333 DPRINTF(" \t%s A, ", oi->name);
1334 print_reg(op & 7);
1335 gbcpu_regs.rn.a ^= get_reg(op & 7);
1336 gbcpu_regs.rn.f = 0;
1337 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1338 }
1339
op_xor_imm(uint32_t op,const struct opinfo * oi)1340 static regparm void op_xor_imm(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1341 {
1342 uint8_t imm = get_imm8();
1343
1344 DPRINTF(" \t%s A, $0x%02x", oi->name, imm);
1345 gbcpu_regs.rn.a ^= imm;
1346 gbcpu_regs.rn.f = 0;
1347 if (gbcpu_regs.rn.a == 0) gbcpu_regs.rn.f |= ZF;
1348 }
1349
op_push(uint32_t op,const struct opinfo * oi)1350 static regparm void op_push(uint32_t op, const struct opinfo *oi)
1351 {
1352 long reg = op >> 4 & 3;
1353
1354 push(REGS16_R(gbcpu_regs, reg));
1355 // 4 extra cycles.
1356 gbcpu_cycles += 4;
1357 DPRINTF(" \t%s %s\t", oi->name, regnamech16[reg]);
1358 }
1359
op_push_af(uint32_t op,const struct opinfo * oi)1360 static regparm void op_push_af(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1361 {
1362 uint16_t tmp = gbcpu_regs.rn.a << 8;
1363
1364 tmp |= gbcpu_regs.rn.f;
1365 push(tmp);
1366 // 4 extra cycles.
1367 gbcpu_cycles += 4;
1368 DPRINTF(" \t%s %s\t", oi->name, regnamech16[op >> 4 & 3]);
1369 }
1370
op_pop(uint32_t op,const struct opinfo * oi)1371 static regparm void op_pop(uint32_t op, const struct opinfo *oi)
1372 {
1373 long reg = op >> 4 & 3;
1374
1375 REGS16_W(gbcpu_regs, reg, pop());
1376 DPRINTF(" \t%s %s\t", oi->name, regnamech16[reg]);
1377 }
1378
op_pop_af(uint32_t op,const struct opinfo * oi)1379 static regparm void op_pop_af(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1380 {
1381 uint16_t tmp = pop();
1382
1383 gbcpu_regs.rn.f = tmp & 0xf0;
1384 gbcpu_regs.rn.a = tmp >> 8;
1385 DPRINTF(" \t%s %s\t", oi->name, regnamech16[op >> 4 & 3]);
1386 }
1387
op_cpl(uint32_t op,const struct opinfo * oi)1388 static regparm void op_cpl(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1389 {
1390 DPRINTF(" \t%s", oi->name);
1391 gbcpu_regs.rn.a = ~gbcpu_regs.rn.a;
1392 gbcpu_regs.rn.f |= NF | HF;
1393 }
1394
op_ccf(uint32_t op,const struct opinfo * oi)1395 static regparm void op_ccf(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1396 {
1397 DPRINTF(" \t%s", oi->name);
1398 gbcpu_regs.rn.f ^= CF;
1399 gbcpu_regs.rn.f &= ~(NF | HF);
1400 }
1401
op_scf(uint32_t op,const struct opinfo * oi)1402 static regparm void op_scf(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1403 {
1404 DPRINTF(" \t%s", oi->name);
1405 gbcpu_regs.rn.f |= CF;
1406 gbcpu_regs.rn.f &= ~(NF | HF);
1407 }
1408
op_call(uint32_t op,const struct opinfo * oi)1409 static regparm void op_call(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1410 {
1411 uint16_t ofs = get_imm16();
1412
1413 DPRINTF(" \t%s 0x%04x", oi->name, ofs);
1414 push(REGS16_R(gbcpu_regs, PC));
1415 REGS16_W(gbcpu_regs, PC, ofs);
1416 // 4 extra cycles.
1417 gbcpu_cycles += 4;
1418 }
1419
op_call_cond(uint32_t op,const struct opinfo * oi)1420 static regparm void op_call_cond(uint32_t op, const struct opinfo *oi)
1421 {
1422 uint16_t ofs = get_imm16();
1423 long cond = (op >> 3) & 3;
1424
1425 DPRINTF(" \t%s %s 0x%04x", oi->name, conds[cond], ofs);
1426 switch (cond) {
1427 case 0: if ((gbcpu_regs.rn.f & ZF) != 0) return; break;
1428 case 1: if ((gbcpu_regs.rn.f & ZF) == 0) return; break;
1429 case 2: if ((gbcpu_regs.rn.f & CF) != 0) return; break;
1430 case 3: if ((gbcpu_regs.rn.f & CF) == 0) return; break;
1431 }
1432 // A taken call is 4 extra cycles.
1433 gbcpu_cycles += 4;
1434 push(REGS16_R(gbcpu_regs, PC));
1435 REGS16_W(gbcpu_regs, PC, ofs);
1436 }
1437
op_ret(uint32_t op,const struct opinfo * oi)1438 static regparm void op_ret(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1439 {
1440 REGS16_W(gbcpu_regs, PC, pop());
1441 // 4 extra cycles.
1442 gbcpu_cycles += 4;
1443 DPRINTF(" \t%s", oi->name);
1444 }
1445
op_reti(uint32_t op,const struct opinfo * oi)1446 static regparm void op_reti(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1447 {
1448 gbcpu_if = 1;
1449 REGS16_W(gbcpu_regs, PC, pop());
1450 DPRINTF(" \t%s", oi->name);
1451 // 4 extra cycles.
1452 gbcpu_cycles += 4;
1453 }
1454
op_ret_cond(uint32_t op,const struct opinfo * oi)1455 static regparm void op_ret_cond(uint32_t op, const struct opinfo *oi)
1456 {
1457 long cond = (op >> 3) & 3;
1458
1459 // 4 extra cycles.
1460 gbcpu_cycles += 4;
1461 DPRINTF(" \t%s %s", oi->name, conds[cond]);
1462 switch (cond) {
1463 case 0: if ((gbcpu_regs.rn.f & ZF) != 0) return; break;
1464 case 1: if ((gbcpu_regs.rn.f & ZF) == 0) return; break;
1465 case 2: if ((gbcpu_regs.rn.f & CF) != 0) return; break;
1466 case 3: if ((gbcpu_regs.rn.f & CF) == 0) return; break;
1467 }
1468 // 4 extra cycles.
1469 gbcpu_cycles += 4;
1470 REGS16_W(gbcpu_regs, PC, pop());
1471 }
1472
op_halt(uint32_t op,const struct opinfo * oi)1473 static regparm void op_halt(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1474 {
1475 gbcpu_halted = 1;
1476 DPRINTF(" \t%s", oi->name);
1477 }
1478
op_stop(uint32_t op,const struct opinfo * oi)1479 static regparm void op_stop(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1480 {
1481 DPRINTF(" \t%s", oi->name);
1482 }
1483
op_di(uint32_t op,const struct opinfo * oi)1484 static regparm void op_di(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1485 {
1486 gbcpu_if = 0;
1487 DPRINTF(" \t%s", oi->name);
1488 }
1489
op_ei(uint32_t op,const struct opinfo * oi)1490 static regparm void op_ei(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1491 {
1492 gbcpu_if = 1;
1493 DPRINTF(" \t%s", oi->name);
1494 }
1495
op_jr(uint32_t op,const struct opinfo * oi)1496 static regparm void op_jr(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1497 {
1498 int16_t ofs = (int8_t) get_imm8();
1499
1500 if (ofs == -2 && gbcpu_if == 0) {
1501 gbcpu_halted = 1;
1502 }
1503
1504 if (ofs < 0) DPRINTF(" \t%s $-0x%02x", oi->name, -ofs);
1505 else DPRINTF(" \t%s $+0x%02x", oi->name, ofs);
1506 // 4 extra cycles.
1507 gbcpu_cycles += 4;
1508 REGS16_W(gbcpu_regs, PC, REGS16_R(gbcpu_regs, PC) + ofs);
1509 }
1510
op_jr_cond(uint32_t op,const struct opinfo * oi)1511 static regparm void op_jr_cond(uint32_t op, const struct opinfo *oi)
1512 {
1513 int16_t ofs = (int8_t) get_imm8();
1514 long cond = (op >> 3) & 3;
1515
1516 if (ofs < 0) DPRINTF(" \t%s %s $-0x%02x", oi->name, conds[cond], -ofs);
1517 else DPRINTF(" \t%s %s $+0x%02x", oi->name, conds[cond], ofs);
1518 switch (cond) {
1519 case 0: if ((gbcpu_regs.rn.f & ZF) != 0) return; break;
1520 case 1: if ((gbcpu_regs.rn.f & ZF) == 0) return; break;
1521 case 2: if ((gbcpu_regs.rn.f & CF) != 0) return; break;
1522 case 3: if ((gbcpu_regs.rn.f & CF) == 0) return; break;
1523 }
1524 // A taken jump is 4 extra cycles.
1525 gbcpu_cycles += 4;
1526 REGS16_W(gbcpu_regs, PC, REGS16_R(gbcpu_regs, PC) + ofs);
1527 }
1528
op_jp(uint32_t op,const struct opinfo * oi)1529 static regparm void op_jp(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1530 {
1531 uint16_t ofs = get_imm16();
1532
1533 DPRINTF(" \t%s 0x%04x", oi->name, ofs);
1534 // 4 extra cycles.
1535 gbcpu_cycles += 4;
1536 REGS16_W(gbcpu_regs, PC, ofs);
1537 }
1538
op_jp_hl(uint32_t op,const struct opinfo * oi)1539 static regparm void op_jp_hl(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1540 {
1541 DPRINTF(" \t%s HL", oi->name);
1542 REGS16_W(gbcpu_regs, PC, REGS16_R(gbcpu_regs, HL));
1543 }
1544
op_jp_cond(uint32_t op,const struct opinfo * oi)1545 static regparm void op_jp_cond(uint32_t op, const struct opinfo *oi)
1546 {
1547 uint16_t ofs = get_imm16();
1548 long cond = (op >> 3) & 3;
1549
1550 DPRINTF(" \t%s %s 0x%04x", oi->name, conds[cond], ofs);
1551 switch (cond) {
1552 case 0: if ((gbcpu_regs.rn.f & ZF) != 0) return; break;
1553 case 1: if ((gbcpu_regs.rn.f & ZF) == 0) return; break;
1554 case 2: if ((gbcpu_regs.rn.f & CF) != 0) return; break;
1555 case 3: if ((gbcpu_regs.rn.f & CF) == 0) return; break;
1556 }
1557 // A taken jump is 4 extra cycles.
1558 gbcpu_cycles += 4;
1559 REGS16_W(gbcpu_regs, PC, ofs);
1560 }
1561
op_rst(uint32_t op,const struct opinfo * oi)1562 static regparm void op_rst(uint32_t op, const struct opinfo *oi)
1563 {
1564 int16_t ofs = op & 0x38;
1565
1566 DPRINTF(" \t%s 0x%02x", oi->name, ofs);
1567 push(REGS16_R(gbcpu_regs, PC));
1568 REGS16_W(gbcpu_regs, PC, ofs);
1569 // 4 extra cycles.
1570 gbcpu_cycles += 4;
1571 }
1572
op_nop(uint32_t op,const struct opinfo * oi)1573 static regparm void op_nop(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1574 {
1575 DPRINTF(" \t%s", oi->name);
1576 }
1577
op_daa(uint32_t op,const struct opinfo * oi)1578 static regparm void op_daa(/*@unused@*/ uint32_t op, const struct opinfo *oi)
1579 {
1580 long a = gbcpu_regs.rn.a;
1581 long f = gbcpu_regs.rn.f;
1582
1583 if (f & NF) {
1584 if (f & HF) {
1585 a -= 0x06;
1586 a &= 0xff;
1587 }
1588 if (f & CF)
1589 a -= 0x60;
1590 } else {
1591 if (f & HF || (a & 0xf) > 9)
1592 a += 0x06;
1593 if (f & CF || a > 0x9f)
1594 a += 0x60;
1595 }
1596 f &= ~(HF | ZF);
1597
1598 if (a > 0xff)
1599 f |= CF;
1600 a &= 0xff;
1601 if (a == 0)
1602 f |= ZF;
1603
1604 gbcpu_regs.rn.a = (uint8_t)a;
1605 gbcpu_regs.rn.f = (uint8_t)f;
1606 DPRINTF(" \t%s", oi->name);
1607 }
1608
1609 static const struct opinfo ops[256] = {
1610 OPINFO("NOP", &op_nop , 1, 1), /* opcode 00 */
1611 OPINFO("LD", &op_ld_reg16_imm, 3, 3), /* opcode 01 */
1612 OPINFO("LD", &op_ld_reg16_a , 2, 2), /* opcode 02 */
1613 OPINFO("INC", &op_inc16 , 2, 2), /* opcode 03 */
1614 OPINFO("INC", &op_inc , 1, 1), /* opcode 04 */
1615 OPINFO("DEC", &op_dec , 1, 1), /* opcode 05 */
1616 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 06 */
1617 OPINFO("RLCA", &op_rlca , 1, 1), /* opcode 07 */
1618 OPINFO("LD", &op_ld_ind16_sp , 5, 5), /* opcode 08 */
1619 OPINFO("ADD", &op_add_hl , 2, 2), /* opcode 09 */
1620 OPINFO("LD", &op_ld_reg16_a , 2, 2), /* opcode 0a */
1621 OPINFO("DEC", &op_dec16 , 2, 2), /* opcode 0b */
1622 OPINFO("INC", &op_inc , 1, 1), /* opcode 0c */
1623 OPINFO("DEC", &op_dec , 1, 1), /* opcode 0d */
1624 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 0e */
1625 OPINFO("RRCA", &op_rrca , 1, 1), /* opcode 0f */
1626 OPINFO("STOP", &op_stop , 0, 0), /* opcode 10 */
1627 OPINFO("LD", &op_ld_reg16_imm, 3, 3), /* opcode 11 */
1628 OPINFO("LD", &op_ld_reg16_a , 2, 2), /* opcode 12 */
1629 OPINFO("INC", &op_inc16 , 2, 2), /* opcode 13 */
1630 OPINFO("INC", &op_inc , 1, 1), /* opcode 14 */
1631 OPINFO("DEC", &op_dec , 1, 1), /* opcode 15 */
1632 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 16 */
1633 OPINFO("RLA", &op_rla , 1, 1), /* opcode 17 */
1634 OPINFO("JR", &op_jr , 3, 3), /* opcode 18 */
1635 OPINFO("ADD", &op_add_hl , 2, 2), /* opcode 19 */
1636 OPINFO("LD", &op_ld_reg16_a , 2, 2), /* opcode 1a */
1637 OPINFO("DEC", &op_dec16 , 2, 2), /* opcode 1b */
1638 OPINFO("INC", &op_inc , 1, 1), /* opcode 1c */
1639 OPINFO("DEC", &op_dec , 1, 1), /* opcode 1d */
1640 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 1e */
1641 OPINFO("RRA", &op_rra , 1, 1), /* opcode 1f */
1642 OPINFO("JR", &op_jr_cond , 2, 3), /* opcode 20 */
1643 OPINFO("LD", &op_ld_reg16_imm, 3, 3), /* opcode 21 */
1644 OPINFO("LDI", &op_ld_reg16_a , 2, 2), /* opcode 22 */
1645 OPINFO("INC", &op_inc16 , 2, 2), /* opcode 23 */
1646 OPINFO("INC", &op_inc , 1, 1), /* opcode 24 */
1647 OPINFO("DEC", &op_dec , 1, 1), /* opcode 25 */
1648 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 26 */
1649 OPINFO("DAA", &op_daa , 1, 1), /* opcode 27 */
1650 OPINFO("JR", &op_jr_cond , 2, 3), /* opcode 28 */
1651 OPINFO("ADD", &op_add_hl , 2, 2), /* opcode 29 */
1652 OPINFO("LDI", &op_ld_reg16_a , 2, 2), /* opcode 2a */
1653 OPINFO("DEC", &op_dec16 , 2, 2), /* opcode 2b */
1654 OPINFO("INC", &op_inc , 1, 1), /* opcode 2c */
1655 OPINFO("DEC", &op_dec , 1, 1), /* opcode 2d */
1656 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 2e */
1657 OPINFO("CPL", &op_cpl , 1, 1), /* opcode 2f */
1658 OPINFO("JR", &op_jr_cond , 2, 3), /* opcode 30 */
1659 OPINFO("LD", &op_ld_reg16_imm, 3, 3), /* opcode 31 */
1660 OPINFO("LDD", &op_ld_reg16_a , 2, 2), /* opcode 32 */
1661 OPINFO("INC", &op_inc16 , 2, 2), /* opcode 33 */
1662 OPINFO("INC", &op_inc , 3, 3), /* opcode 34 */
1663 OPINFO("DEC", &op_dec , 3, 3), /* opcode 35 */
1664 OPINFO("LD", &op_ld_reg8_imm , 3, 3), /* opcode 36 */
1665 OPINFO("SCF", &op_scf , 1, 1), /* opcode 37 */
1666 OPINFO("JR", &op_jr_cond , 2, 3), /* opcode 38 */
1667 OPINFO("ADD", &op_add_hl , 2, 2), /* opcode 39 */
1668 OPINFO("LDD", &op_ld_reg16_a , 2, 2), /* opcode 3a */
1669 OPINFO("DEC", &op_dec16 , 2, 2), /* opcode 3b */
1670 OPINFO("INC", &op_inc , 1, 1), /* opcode 3c */
1671 OPINFO("DEC", &op_dec , 1, 1), /* opcode 3d */
1672 OPINFO("LD", &op_ld_reg8_imm , 2, 2), /* opcode 3e */
1673 OPINFO("CCF", &op_ccf , 1, 1), /* opcode 3f */
1674 OPINFO("LD", &op_ld , 1, 1), /* opcode 40 */
1675 OPINFO("LD", &op_ld , 1, 1), /* opcode 41 */
1676 OPINFO("LD", &op_ld , 1, 1), /* opcode 42 */
1677 OPINFO("LD", &op_ld , 1, 1), /* opcode 43 */
1678 OPINFO("LD", &op_ld , 1, 1), /* opcode 44 */
1679 OPINFO("LD", &op_ld , 1, 1), /* opcode 45 */
1680 OPINFO("LD", &op_ld , 2, 2), /* opcode 46 */
1681 OPINFO("LD", &op_ld , 1, 1), /* opcode 47 */
1682 OPINFO("LD", &op_ld , 1, 1), /* opcode 48 */
1683 OPINFO("LD", &op_ld , 1, 1), /* opcode 49 */
1684 OPINFO("LD", &op_ld , 1, 1), /* opcode 4a */
1685 OPINFO("LD", &op_ld , 1, 1), /* opcode 4b */
1686 OPINFO("LD", &op_ld , 1, 1), /* opcode 4c */
1687 OPINFO("LD", &op_ld , 1, 1), /* opcode 4d */
1688 OPINFO("LD", &op_ld , 2, 2), /* opcode 4e */
1689 OPINFO("LD", &op_ld , 1, 1), /* opcode 4f */
1690 OPINFO("LD", &op_ld , 1, 1), /* opcode 50 */
1691 OPINFO("LD", &op_ld , 1, 1), /* opcode 51 */
1692 OPINFO("LD", &op_ld , 1, 1), /* opcode 52 */
1693 OPINFO("LD", &op_ld , 1, 1), /* opcode 53 */
1694 OPINFO("LD", &op_ld , 1, 1), /* opcode 54 */
1695 OPINFO("LD", &op_ld , 1, 1), /* opcode 55 */
1696 OPINFO("LD", &op_ld , 2, 2), /* opcode 56 */
1697 OPINFO("LD", &op_ld , 1, 1), /* opcode 57 */
1698 OPINFO("LD", &op_ld , 1, 1), /* opcode 58 */
1699 OPINFO("LD", &op_ld , 1, 1), /* opcode 59 */
1700 OPINFO("LD", &op_ld , 1, 1), /* opcode 5a */
1701 OPINFO("LD", &op_ld , 1, 1), /* opcode 5b */
1702 OPINFO("LD", &op_ld , 1, 1), /* opcode 5c */
1703 OPINFO("LD", &op_ld , 1, 1), /* opcode 5d */
1704 OPINFO("LD", &op_ld , 2, 2), /* opcode 5e */
1705 OPINFO("LD", &op_ld , 1, 1), /* opcode 5f */
1706 OPINFO("LD", &op_ld , 1, 1), /* opcode 60 */
1707 OPINFO("LD", &op_ld , 1, 1), /* opcode 61 */
1708 OPINFO("LD", &op_ld , 1, 1), /* opcode 62 */
1709 OPINFO("LD", &op_ld , 1, 1), /* opcode 63 */
1710 OPINFO("LD", &op_ld , 1, 1), /* opcode 64 */
1711 OPINFO("LD", &op_ld , 1, 1), /* opcode 65 */
1712 OPINFO("LD", &op_ld , 2, 2), /* opcode 66 */
1713 OPINFO("LD", &op_ld , 1, 1), /* opcode 67 */
1714 OPINFO("LD", &op_ld , 1, 1), /* opcode 68 */
1715 OPINFO("LD", &op_ld , 1, 1), /* opcode 69 */
1716 OPINFO("LD", &op_ld , 1, 1), /* opcode 6a */
1717 OPINFO("LD", &op_ld , 1, 1), /* opcode 6b */
1718 OPINFO("LD", &op_ld , 1, 1), /* opcode 6c */
1719 OPINFO("LD", &op_ld , 1, 1), /* opcode 6d */
1720 OPINFO("LD", &op_ld , 2, 2), /* opcode 6e */
1721 OPINFO("LD", &op_ld , 1, 1), /* opcode 6f */
1722 OPINFO("LD", &op_ld , 2, 2), /* opcode 70 */
1723 OPINFO("LD", &op_ld , 2, 2), /* opcode 71 */
1724 OPINFO("LD", &op_ld , 2, 2), /* opcode 72 */
1725 OPINFO("LD", &op_ld , 2, 2), /* opcode 73 */
1726 OPINFO("LD", &op_ld , 2, 2), /* opcode 74 */
1727 OPINFO("LD", &op_ld , 2, 2), /* opcode 75 */
1728 OPINFO("HALT", &op_halt , 0, 0), /* opcode 76 */
1729 OPINFO("LD", &op_ld , 2, 2), /* opcode 77 */
1730 OPINFO("LD", &op_ld , 1, 1), /* opcode 78 */
1731 OPINFO("LD", &op_ld , 1, 1), /* opcode 79 */
1732 OPINFO("LD", &op_ld , 1, 1), /* opcode 7a */
1733 OPINFO("LD", &op_ld , 1, 1), /* opcode 7b */
1734 OPINFO("LD", &op_ld , 1, 1), /* opcode 7c */
1735 OPINFO("LD", &op_ld , 1, 1), /* opcode 7d */
1736 OPINFO("LD", &op_ld , 2, 2), /* opcode 7e */
1737 OPINFO("LD", &op_ld , 1, 1), /* opcode 7f */
1738 OPINFO("ADD", &op_add , 1, 1), /* opcode 80 */
1739 OPINFO("ADD", &op_add , 1, 1), /* opcode 81 */
1740 OPINFO("ADD", &op_add , 1, 1), /* opcode 82 */
1741 OPINFO("ADD", &op_add , 1, 1), /* opcode 83 */
1742 OPINFO("ADD", &op_add , 1, 1), /* opcode 84 */
1743 OPINFO("ADD", &op_add , 1, 1), /* opcode 85 */
1744 OPINFO("ADD", &op_add , 2, 2), /* opcode 86 */
1745 OPINFO("ADD", &op_add , 1, 1), /* opcode 87 */
1746 OPINFO("ADC", &op_adc , 1, 1), /* opcode 88 */
1747 OPINFO("ADC", &op_adc , 1, 1), /* opcode 89 */
1748 OPINFO("ADC", &op_adc , 1, 1), /* opcode 8a */
1749 OPINFO("ADC", &op_adc , 1, 1), /* opcode 8b */
1750 OPINFO("ADC", &op_adc , 1, 1), /* opcode 8c */
1751 OPINFO("ADC", &op_adc , 1, 1), /* opcode 8d */
1752 OPINFO("ADC", &op_adc , 2, 2), /* opcode 8e */
1753 OPINFO("ADC", &op_adc , 1, 1), /* opcode 8f */
1754 OPINFO("SUB", &op_sub , 1, 1), /* opcode 90 */
1755 OPINFO("SUB", &op_sub , 1, 1), /* opcode 91 */
1756 OPINFO("SUB", &op_sub , 1, 1), /* opcode 92 */
1757 OPINFO("SUB", &op_sub , 1, 1), /* opcode 93 */
1758 OPINFO("SUB", &op_sub , 1, 1), /* opcode 94 */
1759 OPINFO("SUB", &op_sub , 1, 1), /* opcode 95 */
1760 OPINFO("SUB", &op_sub , 2, 2), /* opcode 96 */
1761 OPINFO("SUB", &op_sub , 1, 1), /* opcode 97 */
1762 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 98 */
1763 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 99 */
1764 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 9a */
1765 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 9b */
1766 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 9c */
1767 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 9d */
1768 OPINFO("SBC", &op_sbc , 2, 2), /* opcode 9e */
1769 OPINFO("SBC", &op_sbc , 1, 1), /* opcode 9f */
1770 OPINFO("AND", &op_and , 1, 1), /* opcode a0 */
1771 OPINFO("AND", &op_and , 1, 1), /* opcode a1 */
1772 OPINFO("AND", &op_and , 1, 1), /* opcode a2 */
1773 OPINFO("AND", &op_and , 1, 1), /* opcode a3 */
1774 OPINFO("AND", &op_and , 1, 1), /* opcode a4 */
1775 OPINFO("AND", &op_and , 1, 1), /* opcode a5 */
1776 OPINFO("AND", &op_and , 2, 2), /* opcode a6 */
1777 OPINFO("AND", &op_and , 1, 1), /* opcode a7 */
1778 OPINFO("XOR", &op_xor , 1, 1), /* opcode a8 */
1779 OPINFO("XOR", &op_xor , 1, 1), /* opcode a9 */
1780 OPINFO("XOR", &op_xor , 1, 1), /* opcode aa */
1781 OPINFO("XOR", &op_xor , 1, 1), /* opcode ab */
1782 OPINFO("XOR", &op_xor , 1, 1), /* opcode ac */
1783 OPINFO("XOR", &op_xor , 1, 1), /* opcode ad */
1784 OPINFO("XOR", &op_xor , 2, 2), /* opcode ae */
1785 OPINFO("XOR", &op_xor , 1, 1), /* opcode af */
1786 OPINFO("OR", &op_or , 1, 1), /* opcode b0 */
1787 OPINFO("OR", &op_or , 1, 1), /* opcode b1 */
1788 OPINFO("OR", &op_or , 1, 1), /* opcode b2 */
1789 OPINFO("OR", &op_or , 1, 1), /* opcode b3 */
1790 OPINFO("OR", &op_or , 1, 1), /* opcode b4 */
1791 OPINFO("OR", &op_or , 1, 1), /* opcode b5 */
1792 OPINFO("OR", &op_or , 2, 2), /* opcode b6 */
1793 OPINFO("OR", &op_or , 1, 1), /* opcode b7 */
1794 OPINFO("CP", &op_cp , 1, 1), /* opcode b8 */
1795 OPINFO("CP", &op_cp , 1, 1), /* opcode b9 */
1796 OPINFO("CP", &op_cp , 1, 1), /* opcode ba */
1797 OPINFO("CP", &op_cp , 1, 1), /* opcode bb */
1798 OPINFO("CP", &op_cp , 1, 1), /* opcode bc */
1799 OPINFO("CP", &op_cp , 1, 1), /* opcode bd */
1800 OPINFO("CP", &op_cp , 2, 2), /* opcode be */
1801 OPINFO("CP", &op_cp , 1, 1), /* opcode bf */
1802 OPINFO("RET", &op_ret_cond , 2, 5), /* opcode c0 */
1803 OPINFO("POP", &op_pop , 3, 3), /* opcode c1 */
1804 OPINFO("JP", &op_jp_cond , 3, 4), /* opcode c2 */
1805 OPINFO("JP", &op_jp , 4, 4), /* opcode c3 */
1806 OPINFO("CALL", &op_call_cond , 3, 6), /* opcode c4 */
1807 OPINFO("PUSH", &op_push , 4, 4), /* opcode c5 */
1808 OPINFO("ADD", &op_add_imm , 2, 2), /* opcode c6 */
1809 OPINFO("RST", &op_rst , 4, 4), /* opcode c7 */
1810 OPINFO("RET", &op_ret_cond , 2, 5), /* opcode c8 */
1811 OPINFO("RET", &op_ret , 4, 4), /* opcode c9 */
1812 OPINFO("JP", &op_jp_cond , 3, 4), /* opcode ca */
1813 OPINFO("CBPREFIX", &op_cbprefix, 0, 0), /* opcode cb */
1814 OPINFO("CALL", &op_call_cond , 3, 6), /* opcode cc */
1815 OPINFO("CALL", &op_call , 6, 6), /* opcode cd */
1816 OPINFO("ADC", &op_adc_imm , 2, 2), /* opcode ce */
1817 OPINFO("RST", &op_rst , 4, 4), /* opcode cf */
1818 OPINFO("RET", &op_ret_cond , 2, 5), /* opcode d0 */
1819 OPINFO("POP", &op_pop , 3, 3), /* opcode d1 */
1820 OPINFO("JP", &op_jp_cond , 3, 4), /* opcode d2 */
1821 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode d3 */
1822 OPINFO("CALL", &op_call_cond , 3, 6), /* opcode d4 */
1823 OPINFO("PUSH", &op_push , 4, 4), /* opcode d5 */
1824 OPINFO("SUB", &op_sub_imm , 2, 2), /* opcode d6 */
1825 OPINFO("RST", &op_rst , 4, 4), /* opcode d7 */
1826 OPINFO("RET", &op_ret_cond , 2, 5), /* opcode d8 */
1827 OPINFO("RETI", &op_reti , 4, 4), /* opcode d9 */
1828 OPINFO("JP", &op_jp_cond , 3, 4), /* opcode da */
1829 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode db */
1830 OPINFO("CALL", &op_call_cond , 3, 6), /* opcode dc */
1831 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode dd */
1832 OPINFO("SBC", &op_sbc_imm , 2, 2), /* opcode de */
1833 OPINFO("RST", &op_rst , 4, 4), /* opcode df */
1834 OPINFO("LDH", &op_ldh , 3, 3), /* opcode e0 */
1835 OPINFO("POP", &op_pop , 3, 3), /* opcode e1 */
1836 OPINFO("LDH", &op_ldh , 2, 2), /* opcode e2 */
1837 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode e3 */
1838 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode e4 */
1839 OPINFO("PUSH", &op_push , 4, 4), /* opcode e5 */
1840 OPINFO("AND", &op_and_imm , 2, 2), /* opcode e6 */
1841 OPINFO("RST", &op_rst , 4, 4), /* opcode e7 */
1842 OPINFO("ADD", &op_add_sp_imm , 4, 4), /* opcode e8 */
1843 OPINFO("JP", &op_jp_hl , 1, 1), /* opcode e9 */
1844 OPINFO("LD", &op_ld_ind16_a , 4, 4), /* opcode ea */
1845 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode eb */
1846 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode ec */
1847 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode ed */
1848 OPINFO("XOR", &op_xor_imm , 2, 2), /* opcode ee */
1849 OPINFO("RST", &op_rst , 4, 4), /* opcode ef */
1850 OPINFO("LDH", &op_ldh , 3, 3), /* opcode f0 */
1851 OPINFO("POP", &op_pop_af , 3, 3), /* opcode f1 */
1852 OPINFO("LDH", &op_ldh , 2, 2), /* opcode f2 */
1853 OPINFO("DI", &op_di , 1, 1), /* opcode f3 */
1854 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode f4 */
1855 OPINFO("PUSH", &op_push_af , 4, 4), /* opcode f5 */
1856 OPINFO("OR", &op_or_imm , 2, 2), /* opcode f6 */
1857 OPINFO("RST", &op_rst , 4, 4), /* opcode f7 */
1858 OPINFO("LD", &op_ld_hlsp , 3, 3), /* opcode f8 */
1859 OPINFO("LD", &op_ld_sphl , 2, 2), /* opcode f9 */
1860 OPINFO("LD", &op_ld_imm , 4, 4), /* opcode fa */
1861 OPINFO("EI", &op_ei , 1, 1), /* opcode fb */
1862 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode fc */
1863 OPINFO("UNKN", &op_unknown , 0, 0), /* opcode fd */
1864 OPINFO("CP", &op_cp_imm , 2, 2), /* opcode fe */
1865 OPINFO("RST", &op_rst , 4, 4), /* opcode ff */
1866 };
1867
1868 #if DEBUG == 1
1869 static gbcpu_regs_u oldregs;
1870
dump_regs(void)1871 static regparm void dump_regs(void)
1872 {
1873 long i;
1874
1875 DPRINTF("; ");
1876 for (i=0; i<8; i++) {
1877 DPRINTF("%c=%02x ", regnames[i], REGS8_R(gbcpu_regs, i));
1878 }
1879 for (i=5; i<6; i++) {
1880 DPRINTF("%s=%04x ", regnamech16[i], REGS16_R(gbcpu_regs, i));
1881 }
1882 DPRINTF("\n");
1883 oldregs = gbcpu_regs;
1884 }
1885
show_reg_diffs(const struct opinfo * oi)1886 static regparm void show_reg_diffs(const struct opinfo *oi)
1887 {
1888 long i;
1889
1890 DPRINTF("\t\t; ");
1891 for (i=0; i<3; i++) {
1892 if (REGS16_R(gbcpu_regs, i) != REGS16_R(oldregs, i)) {
1893 DPRINTF("%s=%04x ", regnamech16[i], REGS16_R(gbcpu_regs, i));
1894 REGS16_W(oldregs, i, REGS16_R(gbcpu_regs, i));
1895 }
1896 }
1897 for (i=6; i<8; i++) {
1898 if (REGS8_R(gbcpu_regs, i) != REGS8_R(oldregs, i)) {
1899 if (i == 6) { /* Flags */
1900 if (gbcpu_regs.rn.f & ZF) DPRINTF("Z");
1901 else DPRINTF("z");
1902 if (gbcpu_regs.rn.f & NF) DPRINTF("N");
1903 else DPRINTF("n");
1904 if (gbcpu_regs.rn.f & HF) DPRINTF("H");
1905 else DPRINTF("h");
1906 if (gbcpu_regs.rn.f & CF) DPRINTF("C");
1907 else DPRINTF("c");
1908 DPRINTF(" ");
1909 } else {
1910 DPRINTF("%c=%02x ", regnames[i], REGS8_R(gbcpu_regs,i));
1911 }
1912 REGS8_W(oldregs, i, REGS8_R(gbcpu_regs, i));
1913 }
1914 }
1915 for (i=4; i<5; i++) {
1916 if (REGS16_R(gbcpu_regs, i) != REGS16_R(oldregs, i)) {
1917 DPRINTF("%s=%04x ", regnamech16[i], REGS16_R(gbcpu_regs, i));
1918 REGS16_W(oldregs, i, REGS16_R(gbcpu_regs, i));
1919 }
1920 }
1921 DPRINTF(" %ld cycles", gbcpu_cycles);
1922 if (!CYCLES_OK(oi, gbcpu_cycles/4)) {
1923 DPRINTF(", but should be %d or %d!\n", 4*CYCLES1(oi), 4*CYCLES2(oi));
1924 }
1925 DPRINTF("\n");
1926 }
1927 #endif
1928
gbcpu_addmem(uint32_t start,uint32_t end,gbcpu_put_fn putfn,gbcpu_get_fn getfn)1929 regparm void gbcpu_addmem(uint32_t start, uint32_t end, gbcpu_put_fn putfn, gbcpu_get_fn getfn)
1930 {
1931 uint32_t i;
1932
1933 for (i=start; i<=end; i++) {
1934 putlookup[i] = putfn;
1935 getlookup[i] = getfn;
1936 }
1937 }
1938
gbcpu_init(void)1939 regparm void gbcpu_init(void)
1940 {
1941 memset(&gbcpu_regs, 0, sizeof(gbcpu_regs));
1942 gbcpu_halted = 0;
1943 gbcpu_stopped = 0;
1944 gbcpu_if = 0;
1945 gbcpu_halt_at_pc = -1;
1946 DEB(dump_regs());
1947 }
1948
gbcpu_intr(long vec)1949 regparm void gbcpu_intr(long vec)
1950 {
1951 DPRINTF("gbcpu_intr(%04lx)\n", vec);
1952 gbcpu_halted = 0;
1953 gbcpu_if = 0;
1954 push(REGS16_R(gbcpu_regs, PC));
1955 REGS16_W(gbcpu_regs, PC, vec);
1956 }
1957
gbcpu_step(void)1958 regparm long gbcpu_step(void)
1959 {
1960 uint8_t op;
1961
1962 if (!gbcpu_halted) {
1963 op = mem_get(gbcpu_regs.rn.pc++);
1964 gbcpu_cycles = 4;
1965 DPRINTF("%04x: %02x", gbcpu_regs.rn.pc - 1, op);
1966 ops[op].fn(op, &ops[op]);
1967
1968 DEB(show_reg_diffs(&ops[op]));
1969
1970 if (gbcpu_halt_at_pc != -1 &&
1971 REGS16_R(gbcpu_regs, PC) == gbcpu_halt_at_pc) {
1972 DPRINTF("halted at PC %04lx\n", gbcpu_halt_at_pc);
1973 gbcpu_halted = 1;
1974 gbcpu_if = 1;
1975 }
1976 return gbcpu_cycles;
1977 }
1978 if (gbcpu_stopped) return -1;
1979 return 16;
1980 }
1981