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