summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/rockboy/cpu.c')
-rw-r--r--apps/plugins/rockboy/cpu.c880
1 files changed, 880 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/cpu.c b/apps/plugins/rockboy/cpu.c
new file mode 100644
index 0000000000..44a870a6eb
--- /dev/null
+++ b/apps/plugins/rockboy/cpu.c
@@ -0,0 +1,880 @@
1
2
3
4#include "rockmacros.h"
5#include "defs.h"
6#include "regs.h"
7#include "hw.h"
8#include "cpu.h"
9#include "lcdc.h"
10#include "mem.h"
11#include "fastmem.h"
12#include "cpuregs.h"
13#include "cpucore.h"
14
15#ifdef USE_ASM
16#include "asm.h"
17#endif
18
19
20struct cpu cpu;
21
22
23
24
25#define ZFLAG(n) ( (n) ? 0 : FZ )
26
27
28#define PUSH(w) ( (SP -= 2), (writew(xSP, (w))) )
29#define POP(w) ( ((w) = readw(xSP)), (SP += 2) )
30
31
32#define FETCH_OLD ( mbc.rmap[PC>>12] \
33? mbc.rmap[PC>>12][PC++] \
34: mem_read(PC++) )
35
36#define FETCH (readb(PC++))
37
38
39#define INC(r) { ((r)++); \
40F = (F & (FL|FC)) | incflag_table[(r)]; }
41
42#define DEC(r) { ((r)--); \
43F = (F & (FL|FC)) | decflag_table[(r)]; }
44
45#define INCW(r) ( (r)++ )
46
47#define DECW(r) ( (r)-- )
48
49#define ADD(n) { \
50W(acc) = (un16)A + (un16)(n); \
51F = (ZFLAG(LB(acc))) \
52| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
53| (HB(acc) << 4); \
54A = LB(acc); }
55
56#define ADC(n) { \
57W(acc) = (un16)A + (un16)(n) + (un16)((F&FC)>>4); \
58F = (ZFLAG(LB(acc))) \
59| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
60| (HB(acc) << 4); \
61A = LB(acc); }
62
63#define ADDW(n) { \
64DW(acc) = (un32)HL + (un32)(n); \
65F = (F & (FZ)) \
66| (FH & ((H ^ ((n)>>8) ^ HB(acc)) << 1)) \
67| (acc.b[HI][LO] << 4); \
68HL = W(acc); }
69
70#define ADDSP(n) { \
71DW(acc) = (un32)SP + (un32)(n8)(n); \
72F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
73| (acc.b[HI][LO] << 4); \
74SP = W(acc); }
75
76#define LDHLSP(n) { \
77DW(acc) = (un32)SP + (un32)(n8)(n); \
78F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
79| (acc.b[HI][LO] << 4); \
80HL = W(acc); }
81
82#define CP(n) { \
83W(acc) = (un16)A - (un16)(n); \
84F = FN \
85| (ZFLAG(LB(acc))) \
86| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
87| ((un8)(-(n8)HB(acc)) << 4); }
88
89#define SUB(n) { CP((n)); A = LB(acc); }
90
91#define SBC(n) { \
92W(acc) = (un16)A - (un16)(n) - (un16)((F&FC)>>4); \
93F = FN \
94| (ZFLAG((n8)LB(acc))) \
95| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
96| ((un8)(-(n8)HB(acc)) << 4); \
97A = LB(acc); }
98
99#define AND(n) { A &= (n); \
100F = ZFLAG(A) | FH; }
101
102#define XOR(n) { A ^= (n); \
103F = ZFLAG(A); }
104
105#define OR(n) { A |= (n); \
106F = ZFLAG(A); }
107
108#define RLCA(r) { (r) = ((r)>>7) | ((r)<<1); \
109F = (((r)&0x01)<<4); }
110
111#define RRCA(r) { (r) = ((r)<<7) | ((r)>>1); \
112F = (((r)&0x80)>>3); }
113
114#define RLA(r) { \
115LB(acc) = (((r)&0x80)>>3); \
116(r) = ((r)<<1) | ((F&FC)>>4); \
117F = LB(acc); }
118
119#define RRA(r) { \
120LB(acc) = (((r)&0x01)<<4); \
121(r) = ((r)>>1) | ((F&FC)<<3); \
122F = LB(acc); }
123
124#define RLC(r) { RLCA(r); F |= ZFLAG(r); }
125#define RRC(r) { RRCA(r); F |= ZFLAG(r); }
126#define RL(r) { RLA(r); F |= ZFLAG(r); }
127#define RR(r) { RRA(r); F |= ZFLAG(r); }
128
129#define SLA(r) { \
130LB(acc) = (((r)&0x80)>>3); \
131(r) <<= 1; \
132F = ZFLAG((r)) | LB(acc); }
133
134#define SRA(r) { \
135LB(acc) = (((r)&0x01)<<4); \
136(r) = (un8)(((n8)(r))>>1); \
137F = ZFLAG((r)) | LB(acc); }
138
139#define SRL(r) { \
140LB(acc) = (((r)&0x01)<<4); \
141(r) >>= 1; \
142F = ZFLAG((r)) | LB(acc); }
143
144#define CPL(r) { \
145(r) = ~(r); \
146F |= (FH|FN); }
147
148#define SCF { F = (F & (FZ)) | FC; }
149
150#define CCF { F = (F & (FZ|FC)) ^ FC; }
151
152#define DAA { \
153A += (LB(acc) = daa_table[((((int)F)&0x70)<<4) | A]); \
154F = (F & (FN)) | ZFLAG(A) | daa_carry_table[LB(acc)>>2]; }
155
156#define SWAP(r) { \
157(r) = swap_table[(r)]; \
158F = ZFLAG((r)); }
159
160#define BIT(n,r) { F = (F & FC) | ZFLAG(((r) & (1 << (n)))) | FH; }
161#define RES(n,r) { (r) &= ~(1 << (n)); }
162#define SET(n,r) { (r) |= (1 << (n)); }
163
164#define CB_REG_CASES(r, n) \
165case 0x00|(n): RLC(r); break; \
166case 0x08|(n): RRC(r); break; \
167case 0x10|(n): RL(r); break; \
168case 0x18|(n): RR(r); break; \
169case 0x20|(n): SLA(r); break; \
170case 0x28|(n): SRA(r); break; \
171case 0x30|(n): SWAP(r); break; \
172case 0x38|(n): SRL(r); break; \
173case 0x40|(n): BIT(0, r); break; \
174case 0x48|(n): BIT(1, r); break; \
175case 0x50|(n): BIT(2, r); break; \
176case 0x58|(n): BIT(3, r); break; \
177case 0x60|(n): BIT(4, r); break; \
178case 0x68|(n): BIT(5, r); break; \
179case 0x70|(n): BIT(6, r); break; \
180case 0x78|(n): BIT(7, r); break; \
181case 0x80|(n): RES(0, r); break; \
182case 0x88|(n): RES(1, r); break; \
183case 0x90|(n): RES(2, r); break; \
184case 0x98|(n): RES(3, r); break; \
185case 0xA0|(n): RES(4, r); break; \
186case 0xA8|(n): RES(5, r); break; \
187case 0xB0|(n): RES(6, r); break; \
188case 0xB8|(n): RES(7, r); break; \
189case 0xC0|(n): SET(0, r); break; \
190case 0xC8|(n): SET(1, r); break; \
191case 0xD0|(n): SET(2, r); break; \
192case 0xD8|(n): SET(3, r); break; \
193case 0xE0|(n): SET(4, r); break; \
194case 0xE8|(n): SET(5, r); break; \
195case 0xF0|(n): SET(6, r); break; \
196case 0xF8|(n): SET(7, r); break;
197
198
199#define ALU_CASES(base, imm, op, label) \
200case (imm): b = FETCH; goto label; \
201case (base): b = B; goto label; \
202case (base)+1: b = C; goto label; \
203case (base)+2: b = D; goto label; \
204case (base)+3: b = E; goto label; \
205case (base)+4: b = H; goto label; \
206case (base)+5: b = L; goto label; \
207case (base)+6: b = readb(HL); goto label; \
208case (base)+7: b = A; \
209label: op(b); break;
210
211
212
213
214
215
216
217
218#define JR ( PC += 1+(n8)readb(PC) )
219#define JP ( PC = readw(PC) )
220
221#define CALL ( PUSH(PC+2), JP )
222
223#define NOJR ( clen--, PC++ )
224#define NOJP ( clen--, PC+=2 )
225#define NOCALL ( clen-=3, PC+=2 )
226#define NORET ( clen-=3 )
227
228#define RST(n) { PUSH(PC); PC = (n); }
229
230#define RET ( POP(PC) )
231
232#define EI ( IMA = 1 )
233#define DI ( cpu.halt = IMA = IME = 0 )
234
235
236
237#define PRE_INT ( DI, PUSH(PC) )
238#define THROW_INT(n) ( (IF &= ~(1<<(n))), (PC = 0x40+((n)<<3)) )
239
240
241
242
243void cpu_reset(void)
244{
245 cpu.speed = 0;
246 cpu.halt = 0;
247 cpu.div = 0;
248 cpu.tim = 0;
249 cpu.lcdc = 40;
250
251 IME = 0;
252 IMA = 0;
253
254 PC = 0x0100;
255 SP = 0xFFFE;
256 AF = 0x01B0;
257 BC = 0x0013;
258 DE = 0x00D8;
259 HL = 0x014D;
260
261 if (hw.cgb) A = 0x11;
262 if (hw.gba) B = 0x01;
263}
264
265
266void div_advance(int cnt)
267{
268 cpu.div += (cnt<<1);
269 if (cpu.div >= 256)
270 {
271 R_DIV += (cpu.div >> 8);
272 cpu.div &= 0xff;
273 }
274}
275
276void timer_advance(int cnt)
277{
278 int unit, tima;
279
280 if (!(R_TAC & 0x04)) return;
281
282 unit = ((-R_TAC) & 3) << 1;
283 cpu.tim += (cnt<<unit);
284
285 if (cpu.tim >= 512)
286 {
287 tima = R_TIMA + (cpu.tim >> 9);
288 cpu.tim &= 0x1ff;
289 if (tima >= 256)
290 {
291 hw_interrupt(IF_TIMER, IF_TIMER);
292 hw_interrupt(0, IF_TIMER);
293 }
294 while (tima >= 256)
295 tima = tima - 256 + R_TMA;
296 R_TIMA = tima;
297 }
298}
299
300void lcdc_advance(int cnt)
301{
302 cpu.lcdc -= cnt;
303 if (cpu.lcdc <= 0) lcdc_trans();
304}
305
306void sound_advance(int cnt)
307{
308 cpu.snd += cnt;
309}
310
311void cpu_timers(int cnt)
312{
313 div_advance(cnt << cpu.speed);
314 timer_advance(cnt << cpu.speed);
315 lcdc_advance(cnt);
316 sound_advance(cnt);
317}
318
319int cpu_idle(int max)
320{
321 int cnt, unit;
322
323 if (!(cpu.halt && IME)) return 0;
324 if (R_IF & R_IE)
325 {
326 cpu.halt = 0;
327 return 0;
328 }
329
330 /* Make sure we don't miss lcdc status events! */
331 if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu.lcdc))
332 max = cpu.lcdc;
333
334 /* If timer interrupt cannot happen, this is very simple! */
335 if (!((R_IE & IF_TIMER) && (R_TAC & 0x04)))
336 {
337 cpu_timers(max);
338 return max;
339 }
340
341 /* Figure out when the next timer interrupt will happen */
342 unit = ((-R_TAC) & 3) << 1;
343 cnt = (511 - cpu.tim + (1<<unit)) >> unit;
344 cnt += (255 - R_TIMA) << (9 - unit);
345
346 if (max < cnt)
347 cnt = max;
348
349 cpu_timers(cnt);
350 return cnt;
351}
352
353#ifndef ASM_CPU_EMULATE
354
355extern int debug_trace;
356
357int cpu_emulate(int cycles)
358{
359 int i;
360 byte op, cbop;
361 int clen;
362 static union reg acc;
363 static byte b;
364 static word w;
365
366 i = cycles;
367next:
368 if ((clen = cpu_idle(i)))
369 {
370 i -= clen;
371 if (i > 0) goto next;
372 return cycles-i;
373 }
374
375 if (IME && (IF & IE))
376 {
377 PRE_INT;
378 switch ((byte)(IF & IE))
379 {
380 case 0x01: case 0x03: case 0x05: case 0x07:
381 case 0x09: case 0x0B: case 0x0D: case 0x0F:
382 case 0x11: case 0x13: case 0x15: case 0x17:
383 case 0x19: case 0x1B: case 0x1D: case 0x1F:
384 THROW_INT(0); break;
385 case 0x02: case 0x06: case 0x0A: case 0x0E:
386 case 0x12: case 0x16: case 0x1A: case 0x1E:
387 THROW_INT(1); break;
388 case 0x04: case 0x0C: case 0x14: case 0x1C:
389 THROW_INT(2); break;
390 case 0x08: case 0x18:
391 THROW_INT(3); break;
392 case 0x10:
393 THROW_INT(4); break;
394 }
395 }
396 IME = IMA;
397
398// if (debug_trace) debug_disassemble(PC, 1);
399
400 op = FETCH;
401 clen = cycles_table[op];
402
403 switch(op)
404 {
405 case 0x00: /* NOP */
406 case 0x40: /* LD B,B */
407 case 0x49: /* LD C,C */
408 case 0x52: /* LD D,D */
409 case 0x5B: /* LD E,E */
410 case 0x64: /* LD H,H */
411 case 0x6D: /* LD L,L */
412 case 0x7F: /* LD A,A */
413 break;
414
415 case 0x41: /* LD B,C */
416 B = C; break;
417 case 0x42: /* LD B,D */
418 B = D; break;
419 case 0x43: /* LD B,E */
420 B = E; break;
421 case 0x44: /* LD B,H */
422 B = H; break;
423 case 0x45: /* LD B,L */
424 B = L; break;
425 case 0x46: /* LD B,(HL) */
426 B = readb(xHL); break;
427 case 0x47: /* LD B,A */
428 B = A; break;
429
430 case 0x48: /* LD C,B */
431 C = B; break;
432 case 0x4A: /* LD C,D */
433 C = D; break;
434 case 0x4B: /* LD C,E */
435 C = E; break;
436 case 0x4C: /* LD C,H */
437 C = H; break;
438 case 0x4D: /* LD C,L */
439 C = L; break;
440 case 0x4E: /* LD C,(HL) */
441 C = readb(xHL); break;
442 case 0x4F: /* LD C,A */
443 C = A; break;
444
445 case 0x50: /* LD D,B */
446 D = B; break;
447 case 0x51: /* LD D,C */
448 D = C; break;
449 case 0x53: /* LD D,E */
450 D = E; break;
451 case 0x54: /* LD D,H */
452 D = H; break;
453 case 0x55: /* LD D,L */
454 D = L; break;
455 case 0x56: /* LD D,(HL) */
456 D = readb(xHL); break;
457 case 0x57: /* LD D,A */
458 D = A; break;
459
460 case 0x58: /* LD E,B */
461 E = B; break;
462 case 0x59: /* LD E,C */
463 E = C; break;
464 case 0x5A: /* LD E,D */
465 E = D; break;
466 case 0x5C: /* LD E,H */
467 E = H; break;
468 case 0x5D: /* LD E,L */
469 E = L; break;
470 case 0x5E: /* LD E,(HL) */
471 E = readb(xHL); break;
472 case 0x5F: /* LD E,A */
473 E = A; break;
474
475 case 0x60: /* LD H,B */
476 H = B; break;
477 case 0x61: /* LD H,C */
478 H = C; break;
479 case 0x62: /* LD H,D */
480 H = D; break;
481 case 0x63: /* LD H,E */
482 H = E; break;
483 case 0x65: /* LD H,L */
484 H = L; break;
485 case 0x66: /* LD H,(HL) */
486 H = readb(xHL); break;
487 case 0x67: /* LD H,A */
488 H = A; break;
489
490 case 0x68: /* LD L,B */
491 L = B; break;
492 case 0x69: /* LD L,C */
493 L = C; break;
494 case 0x6A: /* LD L,D */
495 L = D; break;
496 case 0x6B: /* LD L,E */
497 L = E; break;
498 case 0x6C: /* LD L,H */
499 L = H; break;
500 case 0x6E: /* LD L,(HL) */
501 L = readb(xHL); break;
502 case 0x6F: /* LD L,A */
503 L = A; break;
504
505 case 0x70: /* LD (HL),B */
506 b = B; goto __LD_HL;
507 case 0x71: /* LD (HL),C */
508 b = C; goto __LD_HL;
509 case 0x72: /* LD (HL),D */
510 b = D; goto __LD_HL;
511 case 0x73: /* LD (HL),E */
512 b = E; goto __LD_HL;
513 case 0x74: /* LD (HL),H */
514 b = H; goto __LD_HL;
515 case 0x75: /* LD (HL),L */
516 b = L; goto __LD_HL;
517 case 0x77: /* LD (HL),A */
518 b = A;
519 __LD_HL:
520 writeb(xHL,b);
521 break;
522
523 case 0x78: /* LD A,B */
524 A = B; break;
525 case 0x79: /* LD A,C */
526 A = C; break;
527 case 0x7A: /* LD A,D */
528 A = D; break;
529 case 0x7B: /* LD A,E */
530 A = E; break;
531 case 0x7C: /* LD A,H */
532 A = H; break;
533 case 0x7D: /* LD A,L */
534 A = L; break;
535 case 0x7E: /* LD A,(HL) */
536 A = readb(xHL); break;
537
538 case 0x01: /* LD BC,imm */
539 BC = readw(xPC); PC += 2; break;
540 case 0x11: /* LD DE,imm */
541 DE = readw(xPC); PC += 2; break;
542 case 0x21: /* LD HL,imm */
543 HL = readw(xPC); PC += 2; break;
544 case 0x31: /* LD SP,imm */
545 SP = readw(xPC); PC += 2; break;
546
547 case 0x02: /* LD (BC),A */
548 writeb(xBC, A); break;
549 case 0x0A: /* LD A,(BC) */
550 A = readb(xBC); break;
551 case 0x12: /* LD (DE),A */
552 writeb(xDE, A); break;
553 case 0x1A: /* LD A,(DE) */
554 A = readb(xDE); break;
555
556 case 0x22: /* LDI (HL),A */
557 writeb(xHL, A); HL++; break;
558 case 0x2A: /* LDI A,(HL) */
559 A = readb(xHL); HL++; break;
560 case 0x32: /* LDD (HL),A */
561 writeb(xHL, A); HL--; break;
562 case 0x3A: /* LDD A,(HL) */
563 A = readb(xHL); HL--; break;
564
565 case 0x06: /* LD B,imm */
566 B = FETCH; break;
567 case 0x0E: /* LD C,imm */
568 C = FETCH; break;
569 case 0x16: /* LD D,imm */
570 D = FETCH; break;
571 case 0x1E: /* LD E,imm */
572 E = FETCH; break;
573 case 0x26: /* LD H,imm */
574 H = FETCH; break;
575 case 0x2E: /* LD L,imm */
576 L = FETCH; break;
577 case 0x36: /* LD (HL),imm */
578 b = FETCH; writeb(xHL, b); break;
579 case 0x3E: /* LD A,imm */
580 A = FETCH; break;
581
582 case 0x08: /* LD (imm),SP */
583 writew(readw(xPC), SP); PC += 2; break;
584 case 0xEA: /* LD (imm),A */
585 writeb(readw(xPC), A); PC += 2; break;
586
587 case 0xE0: /* LDH (imm),A */
588 writehi(FETCH, A); break;
589 case 0xE2: /* LDH (C),A */
590 writehi(C, A); break;
591 case 0xF0: /* LDH A,(imm) */
592 A = readhi(FETCH); break;
593 case 0xF2: /* LDH A,(C) (undocumented) */
594 A = readhi(C); break;
595
596
597 case 0xF8: /* LD HL,SP+imm */
598 b = FETCH; LDHLSP(b); break;
599 case 0xF9: /* LD SP,HL */
600 SP = HL; break;
601 case 0xFA: /* LD A,(imm) */
602 A = readb(readw(xPC)); PC += 2; break;
603
604 ALU_CASES(0x80, 0xC6, ADD, __ADD)
605 ALU_CASES(0x88, 0xCE, ADC, __ADC)
606 ALU_CASES(0x90, 0xD6, SUB, __SUB)
607 ALU_CASES(0x98, 0xDE, SBC, __SBC)
608 ALU_CASES(0xA0, 0xE6, AND, __AND)
609 ALU_CASES(0xA8, 0xEE, XOR, __XOR)
610 ALU_CASES(0xB0, 0xF6, OR, __OR)
611 ALU_CASES(0xB8, 0xFE, CP, __CP)
612
613 case 0x09: /* ADD HL,BC */
614 w = BC; goto __ADDW;
615 case 0x19: /* ADD HL,DE */
616 w = DE; goto __ADDW;
617 case 0x39: /* ADD HL,SP */
618 w = SP; goto __ADDW;
619 case 0x29: /* ADD HL,HL */
620 w = HL;
621 __ADDW:
622 ADDW(w);
623 break;
624
625 case 0x04: /* INC B */
626 INC(B); break;
627 case 0x0C: /* INC C */
628 INC(C); break;
629 case 0x14: /* INC D */
630 INC(D); break;
631 case 0x1C: /* INC E */
632 INC(E); break;
633 case 0x24: /* INC H */
634 INC(H); break;
635 case 0x2C: /* INC L */
636 INC(L); break;
637 case 0x34: /* INC (HL) */
638 b = readb(xHL);
639 INC(b);
640 writeb(xHL, b);
641 break;
642 case 0x3C: /* INC A */
643 INC(A); break;
644
645 case 0x03: /* INC BC */
646 INCW(BC); break;
647 case 0x13: /* INC DE */
648 INCW(DE); break;
649 case 0x23: /* INC HL */
650 INCW(HL); break;
651 case 0x33: /* INC SP */
652 INCW(SP); break;
653
654 case 0x05: /* DEC B */
655 DEC(B); break;
656 case 0x0D: /* DEC C */
657 DEC(C); break;
658 case 0x15: /* DEC D */
659 DEC(D); break;
660 case 0x1D: /* DEC E */
661 DEC(E); break;
662 case 0x25: /* DEC H */
663 DEC(H); break;
664 case 0x2D: /* DEC L */
665 DEC(L); break;
666 case 0x35: /* DEC (HL) */
667 b = readb(xHL);
668 DEC(b);
669 writeb(xHL, b);
670 break;
671 case 0x3D: /* DEC A */
672 DEC(A); break;
673
674 case 0x0B: /* DEC BC */
675 DECW(BC); break;
676 case 0x1B: /* DEC DE */
677 DECW(DE); break;
678 case 0x2B: /* DEC HL */
679 DECW(HL); break;
680 case 0x3B: /* DEC SP */
681 DECW(SP); break;
682
683 case 0x07: /* RLCA */
684 RLCA(A); break;
685 case 0x0F: /* RRCA */
686 RRCA(A); break;
687 case 0x17: /* RLA */
688 RLA(A); break;
689 case 0x1F: /* RRA */
690 RRA(A); break;
691
692 case 0x27: /* DAA */
693 DAA; break;
694 case 0x2F: /* CPL */
695 CPL(A); break;
696
697 case 0x18: /* JR */
698 __JR:
699 JR; break;
700 case 0x20: /* JR NZ */
701 if (!(F&FZ)) goto __JR; NOJR; break;
702 case 0x28: /* JR Z */
703 if (F&FZ) goto __JR; NOJR; break;
704 case 0x30: /* JR NC */
705 if (!(F&FC)) goto __JR; NOJR; break;
706 case 0x38: /* JR C */
707 if (F&FC) goto __JR; NOJR; break;
708
709 case 0xC3: /* JP */
710 __JP:
711 JP; break;
712 case 0xC2: /* JP NZ */
713 if (!(F&FZ)) goto __JP; NOJP; break;
714 case 0xCA: /* JP Z */
715 if (F&FZ) goto __JP; NOJP; break;
716 case 0xD2: /* JP NC */
717 if (!(F&FC)) goto __JP; NOJP; break;
718 case 0xDA: /* JP C */
719 if (F&FC) goto __JP; NOJP; break;
720 case 0xE9: /* JP HL */
721 PC = HL; break;
722
723 case 0xC9: /* RET */
724 __RET:
725 RET; break;
726 case 0xC0: /* RET NZ */
727 if (!(F&FZ)) goto __RET; NORET; break;
728 case 0xC8: /* RET Z */
729 if (F&FZ) goto __RET; NORET; break;
730 case 0xD0: /* RET NC */
731 if (!(F&FC)) goto __RET; NORET; break;
732 case 0xD8: /* RET C */
733 if (F&FC) goto __RET; NORET; break;
734 case 0xD9: /* RETI */
735 IME = IMA = 1; goto __RET;
736
737 case 0xCD: /* CALL */
738 __CALL:
739 CALL; break;
740 case 0xC4: /* CALL NZ */
741 if (!(F&FZ)) goto __CALL; NOCALL; break;
742 case 0xCC: /* CALL Z */
743 if (F&FZ) goto __CALL; NOCALL; break;
744 case 0xD4: /* CALL NC */
745 if (!(F&FC)) goto __CALL; NOCALL; break;
746 case 0xDC: /* CALL C */
747 if (F&FC) goto __CALL; NOCALL; break;
748
749 case 0xC7: /* RST 0 */
750 b = 0x00; goto __RST;
751 case 0xCF: /* RST 8 */
752 b = 0x08; goto __RST;
753 case 0xD7: /* RST 10 */
754 b = 0x10; goto __RST;
755 case 0xDF: /* RST 18 */
756 b = 0x18; goto __RST;
757 case 0xE7: /* RST 20 */
758 b = 0x20; goto __RST;
759 case 0xEF: /* RST 28 */
760 b = 0x28; goto __RST;
761 case 0xF7: /* RST 30 */
762 b = 0x30; goto __RST;
763 case 0xFF: /* RST 38 */
764 b = 0x38;
765 __RST:
766 RST(b); break;
767
768 case 0xC1: /* POP BC */
769 POP(BC); break;
770 case 0xC5: /* PUSH BC */
771 PUSH(BC); break;
772 case 0xD1: /* POP DE */
773 POP(DE); break;
774 case 0xD5: /* PUSH DE */
775 PUSH(DE); break;
776 case 0xE1: /* POP HL */
777 POP(HL); break;
778 case 0xE5: /* PUSH HL */
779 PUSH(HL); break;
780 case 0xF1: /* POP AF */
781 POP(AF); break;
782 case 0xF5: /* PUSH AF */
783 PUSH(AF); break;
784
785 case 0xE8: /* ADD SP,imm */
786 b = FETCH; ADDSP(b); break;
787
788 case 0xF3: /* DI */
789 DI; break;
790 case 0xFB: /* EI */
791 EI; break;
792
793 case 0x37: /* SCF */
794 SCF; break;
795 case 0x3F: /* CCF */
796 CCF; break;
797
798 case 0x10: /* STOP */
799 PC++;
800 if (R_KEY1 & 1)
801 {
802 cpu.speed = cpu.speed ^ 1;
803 R_KEY1 = (R_KEY1 & 0x7E) | (cpu.speed << 7);
804 break;
805 }
806 /* NOTE - we do not implement dmg STOP whatsoever */
807 break;
808
809 case 0x76: /* HALT */
810 cpu.halt = 1;
811 break;
812
813 case 0xCB: /* CB prefix */
814 cbop = FETCH;
815 clen = cb_cycles_table[cbop];
816 switch (cbop)
817 {
818 CB_REG_CASES(B, 0);
819 CB_REG_CASES(C, 1);
820 CB_REG_CASES(D, 2);
821 CB_REG_CASES(E, 3);
822 CB_REG_CASES(H, 4);
823 CB_REG_CASES(L, 5);
824 CB_REG_CASES(A, 7);
825 default:
826 b = readb(xHL);
827 switch(cbop)
828 {
829 CB_REG_CASES(b, 6);
830 }
831 if ((cbop & 0xC0) != 0x40) /* exclude BIT */
832 writeb(xHL, b);
833 break;
834 }
835 break;
836
837 default:
838 die(
839 "invalid opcode 0x%02X at address 0x%04X, rombank = %d\n",
840 op, (PC-1) & 0xffff, mbc.rombank);
841 break;
842 }
843
844 clen <<= 1;
845 div_advance(clen);
846 timer_advance(clen);
847 clen >>= cpu.speed;
848 lcdc_advance(clen);
849 sound_advance(clen);
850
851 i -= clen;
852 if (i > 0) goto next;
853 return cycles-i;
854}
855
856#endif /* ASM_CPU_EMULATE */
857
858
859#ifndef ASM_CPU_STEP
860
861int cpu_step(int max)
862{
863 int cnt;
864 if ((cnt = cpu_idle(max))) return cnt;
865 return cpu_emulate(1);
866}
867
868#endif /* ASM_CPU_STEP */
869
870
871
872
873
874
875
876
877
878
879
880