Make open() posix compliant api-wise. A few calls (those with O_CREAT) need the addit...
[kugel-rb.git] / apps / plugins / rockboy / cpu.c
blobe1d1324c4b9762e4fdcbbbb7fd01037f1abe8447
1 #include "rockmacros.h"
2 #include "defs.h"
3 #include "regs.h"
4 #include "hw.h"
5 #include "cpu-gb.h"
6 #include "lcdc.h"
7 #include "mem.h"
8 #include "fastmem.h"
9 #include "cpuregs.h"
10 #include "cpucore.h"
12 #ifdef USE_ASM
13 #include "asm.h"
14 #endif
17 struct cpu cpu IBSS_ATTR;
20 #define ZFLAG(n) ( (n) ? 0 : FZ )
23 #define PUSH(w) ( (SP -= 2), (writew(xSP, (w))) )
24 #define POP(w) ( ((w) = readw(xSP)), (SP += 2) )
26 #define FETCH (readb(PC++))
29 #define INC(r) { ((r)++); \
30 F = (F & (FL|FC)) | incflag_table[(r)]; }
32 #define DEC(r) { ((r)--); \
33 F = (F & (FL|FC)) | decflag_table[(r)]; }
35 #define INCW(r) ( (r)++ )
37 #define DECW(r) ( (r)-- )
39 #define ADD(n) { \
40 W(acc) = (un32)A + (un32)(n); \
41 F = (ZFLAG(LB(acc))) \
42 | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
43 | (HB(acc) << 4); \
44 A = LB(acc); }
46 #define ADC(n) { \
47 W(acc) = (un32)A + (un32)(n) + (un32)((F&FC)>>4); \
48 F = (ZFLAG(LB(acc))) \
49 | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
50 | (HB(acc) << 4); \
51 A = LB(acc); }
53 #define ADDW(n) { \
54 DW(acc) = (un32)HL + (un32)(n); \
55 F = (F & (FZ)) \
56 | (FH & ((H ^ ((n)>>8) ^ HB(acc)) << 1)) \
57 | (acc.b[HI][LO] << 4); \
58 HL = W(acc); }
60 #define ADDSP(n) { \
61 DW(acc) = (un32)SP + (un32)(n8)(n); \
62 F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
63 | (acc.b[HI][LO] << 4); \
64 SP = W(acc); }
66 #define LDHLSP(n) { \
67 DW(acc) = (un32)SP + (un32)(n8)(n); \
68 F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
69 | (acc.b[HI][LO] << 4); \
70 HL = W(acc); }
72 #define CP(n) { \
73 W(acc) = (un32)A - (un32)(n); \
74 F = FN \
75 | (ZFLAG(LB(acc))) \
76 | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
77 | ((un8)(-(n8)HB(acc)) << 4); }
79 #define SUB(n) { CP((n)); A = LB(acc); }
81 #define SBC(n) { \
82 W(acc) = (un32)A - (un32)(n) - (un32)((F&FC)>>4); \
83 F = FN \
84 | (ZFLAG((n8)LB(acc))) \
85 | (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
86 | ((un8)(-(n8)HB(acc)) << 4); \
87 A = LB(acc); }
89 #define AND(n) { A &= (n); \
90 F = ZFLAG(A) | FH; }
92 #define XOR(n) { A ^= (n); \
93 F = ZFLAG(A); }
95 #define OR(n) { A |= (n); \
96 F = ZFLAG(A); }
98 #define RLCA(r) { (r) = ((r)>>7) | ((r)<<1); \
99 F = (((r)&0x01)<<4); }
101 #define RRCA(r) { (r) = ((r)<<7) | ((r)>>1); \
102 F = (((r)&0x80)>>3); }
104 #define RLA(r) { \
105 LB(acc) = (((r)&0x80)>>3); \
106 (r) = ((r)<<1) | ((F&FC)>>4); \
107 F = LB(acc); }
109 #define RRA(r) { \
110 LB(acc) = (((r)&0x01)<<4); \
111 (r) = ((r)>>1) | ((F&FC)<<3); \
112 F = LB(acc); }
114 #define RLC(r) { RLCA(r); F |= ZFLAG(r); }
115 #define RRC(r) { RRCA(r); F |= ZFLAG(r); }
116 #define RL(r) { RLA(r); F |= ZFLAG(r); }
117 #define RR(r) { RRA(r); F |= ZFLAG(r); }
119 #define SLA(r) { \
120 LB(acc) = (((r)&0x80)>>3); \
121 (r) <<= 1; \
122 F = ZFLAG((r)) | LB(acc); }
124 #define SRA(r) { \
125 LB(acc) = (((r)&0x01)<<4); \
126 (r) = (un8)(((n8)(r))>>1); \
127 F = ZFLAG((r)) | LB(acc); }
129 #define SRL(r) { \
130 LB(acc) = (((r)&0x01)<<4); \
131 (r) >>= 1; \
132 F = ZFLAG((r)) | LB(acc); }
134 #define CPL(r) { \
135 (r) = ~(r); \
136 F |= (FH|FN); }
138 #define SCF { F = (F & (FZ)) | FC; }
140 #define CCF { F = (F & (FZ|FC)) ^ FC; }
142 #define DAA { \
143 A += (LB(acc) = daa_table[((((int)F)&0x70)<<4) | A]); \
144 F = (F & (FN)) | ZFLAG(A) | daa_carry_table[LB(acc)>>2]; }
146 #define SWAP(r) { \
147 (r) = swap_table[(r)]; \
148 F = ZFLAG((r)); }
150 #define BIT(n,r) { F = (F & FC) | ZFLAG(((r) & BIT_N(n))) | FH; }
151 #define RES(n,r) { (r) &= ~BIT_N(n); }
152 #define SET(n,r) { (r) |= BIT_N(n); }
154 #define CB_REG_CASES(r, n) \
155 case 0x00|(n): RLC(r); break; \
156 case 0x08|(n): RRC(r); break; \
157 case 0x10|(n): RL(r); break; \
158 case 0x18|(n): RR(r); break; \
159 case 0x20|(n): SLA(r); break; \
160 case 0x28|(n): SRA(r); break; \
161 case 0x30|(n): SWAP(r); break; \
162 case 0x38|(n): SRL(r); break; \
163 case 0x40|(n): BIT(0, r); break; \
164 case 0x48|(n): BIT(1, r); break; \
165 case 0x50|(n): BIT(2, r); break; \
166 case 0x58|(n): BIT(3, r); break; \
167 case 0x60|(n): BIT(4, r); break; \
168 case 0x68|(n): BIT(5, r); break; \
169 case 0x70|(n): BIT(6, r); break; \
170 case 0x78|(n): BIT(7, r); break; \
171 case 0x80|(n): RES(0, r); break; \
172 case 0x88|(n): RES(1, r); break; \
173 case 0x90|(n): RES(2, r); break; \
174 case 0x98|(n): RES(3, r); break; \
175 case 0xA0|(n): RES(4, r); break; \
176 case 0xA8|(n): RES(5, r); break; \
177 case 0xB0|(n): RES(6, r); break; \
178 case 0xB8|(n): RES(7, r); break; \
179 case 0xC0|(n): SET(0, r); break; \
180 case 0xC8|(n): SET(1, r); break; \
181 case 0xD0|(n): SET(2, r); break; \
182 case 0xD8|(n): SET(3, r); break; \
183 case 0xE0|(n): SET(4, r); break; \
184 case 0xE8|(n): SET(5, r); break; \
185 case 0xF0|(n): SET(6, r); break; \
186 case 0xF8|(n): SET(7, r); break;
189 #define ALU_CASES(base, imm, op, label) \
190 case (imm): b = FETCH; goto label; \
191 case (base): b = B; goto label; \
192 case (base)+1: b = C; goto label; \
193 case (base)+2: b = D; goto label; \
194 case (base)+3: b = E; goto label; \
195 case (base)+4: b = H; goto label; \
196 case (base)+5: b = L; goto label; \
197 case (base)+6: b = readb(HL); goto label; \
198 case (base)+7: b = A; \
199 label: op(b); break;
208 #define JR ( PC += 1+(n8)readb(PC) )
209 #define JP ( PC = readw(PC) )
211 #define CALL ( PUSH(PC+2), JP )
213 #define NOJR ( clen--, PC++ )
214 #define NOJP ( clen--, PC+=2 )
215 #define NOCALL ( clen-=3, PC+=2 )
216 #define NORET ( clen-=3 )
218 #define RST(n) { PUSH(PC); PC = (n); }
220 #define RET ( POP(PC) )
222 #define EI ( IMA = 1 )
223 #define DI ( IMA = IME = 0 )
227 #define PRE_INT ( DI, PUSH(PC) )
228 #define THROW_INT(n) ( (IF &= ~BIT_N(n)), (PC = 0x40+((n)<<3)) )
230 #ifdef DYNAREC
231 un32 reg_backup[16];
232 struct dynarec_block *address_map[1<<HASH_SIGNIFICANT_LOWER_BITS];
233 extern void *dynapointer;
234 int blockcount;
235 #define MAXBLOCK 6
236 #endif
240 void cpu_reset(void)
242 union reg acc;
243 #ifdef DYNAREC
244 int i;
245 dynapointer=0;
246 #endif
247 cpu.speed = 0;
248 cpu.halt = 0;
249 cpu.div = 0;
250 cpu.tim = 0;
251 cpu.lcdc = 40;
253 IME = 0;
254 IMA = 0;
256 PC = 0x0100;
257 SP = 0xFFFE;
258 W(acc) = 0x01B0;
259 A=HB(acc);
260 F=LB(acc);
261 W(acc) = 0x0013;
262 B=HB(acc);
263 C=LB(acc);
264 W(acc) = 0x00D8;
265 D=HB(acc);
266 E=LB(acc);
267 HL = 0x014D;
269 if (hw.cgb) A = 0x11;
270 #ifdef DYNAREC
271 for(i=0;i<(1<<HASH_SIGNIFICANT_LOWER_BITS);i++)
272 address_map[i]=0;
273 #endif
276 static void div_advance(int cnt) ICODE_ATTR;
277 static void div_advance(int cnt)
279 cpu.div += (cnt<<1);
280 if (cpu.div >> 8)
282 R_DIV += (cpu.div >> 8);
283 cpu.div &= 0xff;
287 static void timer_advance(int cnt) ICODE_ATTR;
288 static void timer_advance(int cnt)
290 int unit, tima;
292 if (!(R_TAC & 0x04)) return;
294 unit = ((-R_TAC) & 3) << 1;
295 cpu.tim += (cnt<<unit);
297 if (cpu.tim >> 9)
299 tima = R_TIMA + (cpu.tim >> 9);
300 cpu.tim &= 0x1ff;
301 if (tima >> 8)
303 hw_interrupt(IF_TIMER, IF_TIMER);
304 hw_interrupt(0, IF_TIMER);
306 while (tima >> 8)
307 tima = tima - 256 + R_TMA;
308 R_TIMA = tima;
312 static void lcdc_advance(int cnt) ICODE_ATTR;
313 static void lcdc_advance(int cnt)
315 cpu.lcdc -= cnt;
316 if (cpu.lcdc <= 0) lcdc_trans();
319 static void sound_advance(int cnt) ICODE_ATTR;
320 static void sound_advance(int cnt)
322 cpu.snd += cnt;
325 void cpu_timers(int cnt)
327 div_advance(cnt << cpu.speed);
328 timer_advance(cnt << cpu.speed);
329 lcdc_advance(cnt);
330 if(options.sound)
331 sound_advance(cnt);
334 static int cpu_idle(int max)
336 int cnt, unit;
338 if (!(cpu.halt && IME)) return 0;
339 if (R_IF & R_IE)
341 cpu.halt = 0;
342 return 0;
345 /* Make sure we don't miss lcdc status events! */
346 if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu.lcdc))
347 max = cpu.lcdc;
349 /* If timer interrupt cannot happen, this is very simple! */
350 if (!((R_IE & IF_TIMER) && (R_TAC & 0x04)))
352 cpu_timers(max);
353 return max;
356 /* Figure out when the next timer interrupt will happen */
357 unit = ((-R_TAC) & 3) << 1;
358 cnt = (511 - cpu.tim + BIT_N(unit)) >> unit;
359 cnt += (255 - R_TIMA) << (9 - unit);
361 if (max < cnt)
362 cnt = max;
364 cpu_timers(cnt);
365 return cnt;
368 #ifndef ASM_CPU_EMULATE
370 extern int debug_trace;
372 int cpu_emulate(int cycles)
374 int i;
375 static byte op IBSS_ATTR;
376 static byte cbop IBSS_ATTR;
377 int clen;
378 static union reg acc IBSS_ATTR;
379 static byte b IBSS_ATTR;
380 static word w IBSS_ATTR;
382 i = cycles;
383 next:
384 #ifdef DYNAREC
385 if(shut)
386 return cycles-i;
387 #endif
388 if ((clen = cpu_idle(i)))
390 i -= clen;
391 if (i > 0) goto next;
392 return cycles-i;
395 if (IME && (IF & IE))
397 PRE_INT;
398 switch ((byte)(IF & IE))
400 case 0x01: case 0x03: case 0x05: case 0x07:
401 case 0x09: case 0x0B: case 0x0D: case 0x0F:
402 case 0x11: case 0x13: case 0x15: case 0x17:
403 case 0x19: case 0x1B: case 0x1D: case 0x1F:
404 THROW_INT(0); break;
405 case 0x02: case 0x06: case 0x0A: case 0x0E:
406 case 0x12: case 0x16: case 0x1A: case 0x1E:
407 THROW_INT(1); break;
408 case 0x04: case 0x0C: case 0x14: case 0x1C:
409 THROW_INT(2); break;
410 case 0x08: case 0x18:
411 THROW_INT(3); break;
412 case 0x10:
413 THROW_INT(4); break;
416 IME = IMA;
418 /* if (debug_trace) debug_disassemble(PC, 1); */
419 #ifdef DYNAREC
420 if(PC&0x8000) {
421 #endif
422 op = FETCH;
423 clen = cycles_table[op];
425 switch(op)
427 case 0x00: /* NOP */
428 case 0x40: /* LD B,B */
429 case 0x49: /* LD C,C */
430 case 0x52: /* LD D,D */
431 case 0x5B: /* LD E,E */
432 case 0x64: /* LD H,H */
433 case 0x6D: /* LD L,L */
434 case 0x7F: /* LD A,A */
435 break;
437 case 0x41: /* LD B,C */
438 B = C; break;
439 case 0x42: /* LD B,D */
440 B = D; break;
441 case 0x43: /* LD B,E */
442 B = E; break;
443 case 0x44: /* LD B,H */
444 B = H; break;
445 case 0x45: /* LD B,L */
446 B = L; break;
447 case 0x46: /* LD B,(HL) */
448 B = readb(xHL); break;
449 case 0x47: /* LD B,A */
450 B = A; break;
452 case 0x48: /* LD C,B */
453 C = B; break;
454 case 0x4A: /* LD C,D */
455 C = D; break;
456 case 0x4B: /* LD C,E */
457 C = E; break;
458 case 0x4C: /* LD C,H */
459 C = H; break;
460 case 0x4D: /* LD C,L */
461 C = L; break;
462 case 0x4E: /* LD C,(HL) */
463 C = readb(xHL); break;
464 case 0x4F: /* LD C,A */
465 C = A; break;
467 case 0x50: /* LD D,B */
468 D = B; break;
469 case 0x51: /* LD D,C */
470 D = C; break;
471 case 0x53: /* LD D,E */
472 D = E; break;
473 case 0x54: /* LD D,H */
474 D = H; break;
475 case 0x55: /* LD D,L */
476 D = L; break;
477 case 0x56: /* LD D,(HL) */
478 D = readb(xHL); break;
479 case 0x57: /* LD D,A */
480 D = A; break;
482 case 0x58: /* LD E,B */
483 E = B; break;
484 case 0x59: /* LD E,C */
485 E = C; break;
486 case 0x5A: /* LD E,D */
487 E = D; break;
488 case 0x5C: /* LD E,H */
489 E = H; break;
490 case 0x5D: /* LD E,L */
491 E = L; break;
492 case 0x5E: /* LD E,(HL) */
493 E = readb(xHL); break;
494 case 0x5F: /* LD E,A */
495 E = A; break;
497 case 0x60: /* LD H,B */
498 H = B; break;
499 case 0x61: /* LD H,C */
500 H = C; break;
501 case 0x62: /* LD H,D */
502 H = D; break;
503 case 0x63: /* LD H,E */
504 H = E; break;
505 case 0x65: /* LD H,L */
506 H = L; break;
507 case 0x66: /* LD H,(HL) */
508 H = readb(xHL); break;
509 case 0x67: /* LD H,A */
510 H = A; break;
512 case 0x68: /* LD L,B */
513 L = B; break;
514 case 0x69: /* LD L,C */
515 L = C; break;
516 case 0x6A: /* LD L,D */
517 L = D; break;
518 case 0x6B: /* LD L,E */
519 L = E; break;
520 case 0x6C: /* LD L,H */
521 L = H; break;
522 case 0x6E: /* LD L,(HL) */
523 L = readb(xHL); break;
524 case 0x6F: /* LD L,A */
525 L = A; break;
527 case 0x70: /* LD (HL),B */
528 b = B; goto __LD_HL;
529 case 0x71: /* LD (HL),C */
530 b = C; goto __LD_HL;
531 case 0x72: /* LD (HL),D */
532 b = D; goto __LD_HL;
533 case 0x73: /* LD (HL),E */
534 b = E; goto __LD_HL;
535 case 0x74: /* LD (HL),H */
536 b = H; goto __LD_HL;
537 case 0x75: /* LD (HL),L */
538 b = L; goto __LD_HL;
539 case 0x77: /* LD (HL),A */
540 b = A;
541 __LD_HL:
542 writeb(xHL,b);
543 break;
545 case 0x78: /* LD A,B */
546 A = B; break;
547 case 0x79: /* LD A,C */
548 A = C; break;
549 case 0x7A: /* LD A,D */
550 A = D; break;
551 case 0x7B: /* LD A,E */
552 A = E; break;
553 case 0x7C: /* LD A,H */
554 A = H; break;
555 case 0x7D: /* LD A,L */
556 A = L; break;
557 case 0x7E: /* LD A,(HL) */
558 A = readb(xHL); break;
560 case 0x01: /* LD BC,imm */
561 #ifdef DYNAREC
562 W(acc) = readw(xPC);
563 B=HB(acc);
564 C=LB(acc);
565 #else
566 BC = readw(xPC);
567 #endif
568 PC += 2;
569 break;
570 case 0x11: /* LD DE,imm */
571 #ifdef DYNAREC
572 W(acc) = readw(xPC);
573 D=HB(acc);
574 E=LB(acc);
575 #else
576 DE = readw(xPC);
577 #endif
578 PC += 2;
579 break;
580 case 0x21: /* LD HL,imm */
581 HL = readw(xPC); PC += 2; break;
582 case 0x31: /* LD SP,imm */
583 SP = readw(xPC); PC += 2; break;
585 case 0x02: /* LD (BC),A */
586 writeb(xBC, A); break;
587 case 0x0A: /* LD A,(BC) */
588 A = readb(xBC); break;
589 case 0x12: /* LD (DE),A */
590 writeb(xDE, A); break;
591 case 0x1A: /* LD A,(DE) */
592 A = readb(xDE); break;
594 case 0x22: /* LDI (HL),A */
595 writeb(xHL, A); HL++; break;
596 case 0x2A: /* LDI A,(HL) */
597 A = readb(xHL); HL++; break;
598 case 0x32: /* LDD (HL),A */
599 writeb(xHL, A); HL--; break;
600 case 0x3A: /* LDD A,(HL) */
601 A = readb(xHL); HL--; break;
603 case 0x06: /* LD B,imm */
604 B = FETCH; break;
605 case 0x0E: /* LD C,imm */
606 C = FETCH; break;
607 case 0x16: /* LD D,imm */
608 D = FETCH; break;
609 case 0x1E: /* LD E,imm */
610 E = FETCH; break;
611 case 0x26: /* LD H,imm */
612 H = FETCH; break;
613 case 0x2E: /* LD L,imm */
614 L = FETCH; break;
615 case 0x36: /* LD (HL),imm */
616 b = FETCH; writeb(xHL, b); break;
617 case 0x3E: /* LD A,imm */
618 A = FETCH; break;
620 case 0x08: /* LD (imm),SP */
621 writew(readw(xPC), SP); PC += 2; break;
622 case 0xEA: /* LD (imm),A */
623 writeb(readw(xPC), A); PC += 2; break;
625 case 0xE0: /* LDH (imm),A */
626 writehi(FETCH, A); break;
627 case 0xE2: /* LDH (C),A */
628 writehi(C, A); break;
629 case 0xF0: /* LDH A,(imm) */
630 A = readhi(FETCH); break;
631 case 0xF2: /* LDH A,(C) (undocumented) */
632 A = readhi(C); break;
635 case 0xF8: /* LD HL,SP+imm */
636 b = FETCH; LDHLSP(b); break;
637 case 0xF9: /* LD SP,HL */
638 SP = HL; break;
639 case 0xFA: /* LD A,(imm) */
640 A = readb(readw(xPC)); PC += 2; break;
642 ALU_CASES(0x80, 0xC6, ADD, __ADD)
643 ALU_CASES(0x88, 0xCE, ADC, __ADC)
644 ALU_CASES(0x90, 0xD6, SUB, __SUB)
645 ALU_CASES(0x98, 0xDE, SBC, __SBC)
646 ALU_CASES(0xA0, 0xE6, AND, __AND)
647 ALU_CASES(0xA8, 0xEE, XOR, __XOR)
648 ALU_CASES(0xB0, 0xF6, OR, __OR)
649 ALU_CASES(0xB8, 0xFE, CP, __CP)
651 case 0x09: /* ADD HL,BC */
652 w = BC; goto __ADDW;
653 case 0x19: /* ADD HL,DE */
654 w = DE; goto __ADDW;
655 case 0x39: /* ADD HL,SP */
656 w = SP; goto __ADDW;
657 case 0x29: /* ADD HL,HL */
658 w = HL;
659 __ADDW:
660 ADDW(w);
661 break;
663 case 0x04: /* INC B */
664 INC(B); break;
665 case 0x0C: /* INC C */
666 INC(C); break;
667 case 0x14: /* INC D */
668 INC(D); break;
669 case 0x1C: /* INC E */
670 INC(E); break;
671 case 0x24: /* INC H */
672 INC(H); break;
673 case 0x2C: /* INC L */
674 INC(L); break;
675 case 0x34: /* INC (HL) */
676 b = readb(xHL);
677 INC(b);
678 writeb(xHL, b);
679 break;
680 case 0x3C: /* INC A */
681 INC(A); break;
683 case 0x03: /* INC BC */
684 #ifdef DYNAREC
685 W(acc)=((B<<8)|C)+1;
686 B=HB(acc);
687 C=LB(acc);
688 #else
689 INCW(BC);
690 #endif
691 break;
692 case 0x13: /* INC DE */
693 #ifdef DYNAREC
694 W(acc)=((D<<8)|E)+1;
695 D=HB(acc);
696 E=LB(acc);
697 #else
698 INCW(DE);
699 #endif
700 break;
701 case 0x23: /* INC HL */
702 INCW(HL); break;
703 case 0x33: /* INC SP */
704 INCW(SP); break;
706 case 0x05: /* DEC B */
707 DEC(B); break;
708 case 0x0D: /* DEC C */
709 DEC(C); break;
710 case 0x15: /* DEC D */
711 DEC(D); break;
712 case 0x1D: /* DEC E */
713 DEC(E); break;
714 case 0x25: /* DEC H */
715 DEC(H); break;
716 case 0x2D: /* DEC L */
717 DEC(L); break;
718 case 0x35: /* DEC (HL) */
719 b = readb(xHL);
720 DEC(b);
721 writeb(xHL, b);
722 break;
723 case 0x3D: /* DEC A */
724 DEC(A); break;
726 case 0x0B: /* DEC BC */
727 #ifdef DYNAREC
728 W(acc)=((B<<8)|C)-1;
729 B=HB(acc);
730 C=LB(acc);
731 #else
732 DECW(BC);
733 #endif
734 break;
735 case 0x1B: /* DEC DE */
736 #ifdef DYNAREC
737 W(acc)=((D<<8)|E)-1;
738 D=HB(acc);
739 E=LB(acc);
740 #else
741 DECW(DE);
742 #endif
743 break;
744 case 0x2B: /* DEC HL */
745 DECW(HL); break;
746 case 0x3B: /* DEC SP */
747 DECW(SP); break;
749 case 0x07: /* RLCA */
750 RLCA(A); break;
751 case 0x0F: /* RRCA */
752 RRCA(A); break;
753 case 0x17: /* RLA */
754 RLA(A); break;
755 case 0x1F: /* RRA */
756 RRA(A); break;
758 case 0x27: /* DAA */
759 DAA; break;
760 case 0x2F: /* CPL */
761 CPL(A); break;
763 case 0x18: /* JR */
764 __JR:
765 JR; break;
766 case 0x20: /* JR NZ */
767 if (!(F&FZ)) goto __JR; NOJR; break;
768 case 0x28: /* JR Z */
769 if (F&FZ) goto __JR; NOJR; break;
770 case 0x30: /* JR NC */
771 if (!(F&FC)) goto __JR; NOJR; break;
772 case 0x38: /* JR C */
773 if (F&FC) goto __JR; NOJR; break;
775 case 0xC3: /* JP */
776 __JP:
777 JP; break;
778 case 0xC2: /* JP NZ */
779 if (!(F&FZ)) goto __JP; NOJP; break;
780 case 0xCA: /* JP Z */
781 if (F&FZ) goto __JP; NOJP; break;
782 case 0xD2: /* JP NC */
783 if (!(F&FC)) goto __JP; NOJP; break;
784 case 0xDA: /* JP C */
785 if (F&FC) goto __JP; NOJP; break;
786 case 0xE9: /* JP HL */
787 PC = HL; break;
789 case 0xC9: /* RET */
790 __RET:
791 RET; break;
792 case 0xC0: /* RET NZ */
793 if (!(F&FZ)) goto __RET; NORET; break;
794 case 0xC8: /* RET Z */
795 if (F&FZ) goto __RET; NORET; break;
796 case 0xD0: /* RET NC */
797 if (!(F&FC)) goto __RET; NORET; break;
798 case 0xD8: /* RET C */
799 if (F&FC) goto __RET; NORET; break;
800 case 0xD9: /* RETI */
801 IME = IMA = 1; goto __RET;
803 case 0xCD: /* CALL */
804 __CALL:
805 CALL; break;
806 case 0xC4: /* CALL NZ */
807 if (!(F&FZ)) goto __CALL; NOCALL; break;
808 case 0xCC: /* CALL Z */
809 if (F&FZ) goto __CALL; NOCALL; break;
810 case 0xD4: /* CALL NC */
811 if (!(F&FC)) goto __CALL; NOCALL; break;
812 case 0xDC: /* CALL C */
813 if (F&FC) goto __CALL; NOCALL; break;
815 case 0xC7: /* RST 0 */
816 b = 0x00; goto __RST;
817 case 0xCF: /* RST 8 */
818 b = 0x08; goto __RST;
819 case 0xD7: /* RST 10 */
820 b = 0x10; goto __RST;
821 case 0xDF: /* RST 18 */
822 b = 0x18; goto __RST;
823 case 0xE7: /* RST 20 */
824 b = 0x20; goto __RST;
825 case 0xEF: /* RST 28 */
826 b = 0x28; goto __RST;
827 case 0xF7: /* RST 30 */
828 b = 0x30; goto __RST;
829 case 0xFF: /* RST 38 */
830 b = 0x38;
831 __RST:
832 RST(b); break;
834 case 0xC1: /* POP BC */
835 #ifdef DYNAREC
836 POP(W(acc));
837 B=HB(acc);
838 C=LB(acc);
839 #else
840 POP(BC);
841 #endif
842 break;
843 case 0xC5: /* PUSH BC */
844 PUSH(BC); break;
845 case 0xD1: /* POP DE */
846 #ifdef DYNAREC
847 POP(W(acc));
848 D=HB(acc);
849 E=LB(acc);
850 #else
851 POP(DE);
852 #endif
853 break;
854 case 0xD5: /* PUSH DE */
855 PUSH(DE); break;
856 case 0xE1: /* POP HL */
857 POP(HL); break;
858 case 0xE5: /* PUSH HL */
859 PUSH(HL); break;
860 case 0xF1: /* POP AF */
861 #ifdef DYNAREC
862 POP(W(acc));
863 A=HB(acc);
864 F=LB(acc);
865 #else
866 POP(AF);
867 break;
868 #endif
869 case 0xF5: /* PUSH AF */
870 PUSH(AF); break;
872 case 0xE8: /* ADD SP,imm */
873 b = FETCH; ADDSP(b); break;
875 case 0xF3: /* DI */
876 DI; break;
877 case 0xFB: /* EI */
878 EI; break;
880 case 0x37: /* SCF */
881 SCF; break;
882 case 0x3F: /* CCF */
883 CCF; break;
885 case 0x10: /* STOP */
886 PC++;
887 if (R_KEY1 & 1)
889 cpu.speed ^= 1;
890 R_KEY1 = (R_KEY1 & 0x7E) | (cpu.speed << 7);
891 break;
893 /* NOTE - we do not implement dmg STOP whatsoever */
894 break;
896 case 0x76: /* HALT */
897 cpu.halt = 1;
898 break;
900 case 0xCB: /* CB prefix */
901 cbop = FETCH;
902 clen = cb_cycles_table[cbop];
903 switch (cbop)
905 CB_REG_CASES(B, 0);
906 CB_REG_CASES(C, 1);
907 CB_REG_CASES(D, 2);
908 CB_REG_CASES(E, 3);
909 CB_REG_CASES(H, 4);
910 CB_REG_CASES(L, 5);
911 CB_REG_CASES(A, 7);
912 default:
913 b = readb(xHL);
914 switch(cbop)
916 CB_REG_CASES(b, 6);
918 if ((cbop & 0xC0) != 0x40) /* exclude BIT */
919 writeb(xHL, b);
920 break;
922 break;
924 default:
925 die(
926 "invalid opcode 0x%02X at address 0x%04X, rombank = %d\n",
927 op, (PC-1) & 0xffff, mbc.rombank);
928 break;
930 #ifdef DYNAREC
932 else
933 { /* ROM, dynarec. */
934 struct dynarec_block *p=0,*b=address_map[PC&HASH_BITMASK];
935 char meow[500];
936 byte *ptr=mbc.rmap[PC>>12];
937 snprintf(meow,499,"PC: 0x%x 0x%x a: 0x%x\n",
938 ptr,PC, b ? b->address.d : 0);
939 rb->splash(HZ*2,meow);
940 while(b&&b->address.d!=((unsigned int)(ptr)+PC))
942 p=b;
943 b=b->next;
945 if(b)
946 { /* call block */
947 int fd;
948 blockcount++;
949 snprintf(meow,499,"/dyna_0x%x_run.rb",PC);
950 fd=open(meow,O_WRONLY|O_CREAT|O_TRUNC, 0666);
951 if(fd>=0)
953 fdprintf(fd,"Block 0x%x Blockcount: %d\n",PC,blockcount);
954 fdprintf(fd,"before: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
955 cpu.a,cpu.b,cpu.c,cpu.d,cpu.e,cpu.hl,cpu.f,cpu.sp,cpu.pc,
956 cpu.ime);
957 if(blockcount<MAXBLOCK)
959 asm volatile ("movem.l (%0),%%d1-%%d7/%%a0-%%a1\n\t"
960 "jsr (%1)\n\t"
961 "movem.l %%d1-%%d7/%%a0-%%a1,(%0)\n\t"
963 : "a" (&cpu.a), "a" (b->block)
964 : "d0", "d1", "d2", "d3", "d4", "d5", "d6",
965 "d7", "a0","a1", "a2","a3","a4");
966 clen=blockclen;
967 fdprintf(fd,"after: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
968 cpu.a,cpu.b,cpu.c,cpu.d,cpu.e,cpu.hl,cpu.f,cpu.sp,
969 cpu.pc,cpu.ime);
971 else
972 die("end");
973 close(fd);
976 else
977 { /* Hash miss -> not found -> recompile block and add it */
978 struct dynarec_block *newblock;
979 newblock=malloc(sizeof(struct dynarec_block));
980 memset(newblock,0,sizeof(struct dynarec_block));
981 newblock->address.d=(unsigned int)(ptr)+PC;
982 dynamic_recompile(newblock);
983 if(p)
984 p->next=newblock;
985 else
986 address_map[PC&HASH_BITMASK]=newblock;
989 #endif
993 clen <<= 1;
994 div_advance(clen);
995 timer_advance(clen);
996 clen >>= cpu.speed;
997 lcdc_advance(clen);
998 if(options.sound)
999 sound_advance(clen);
1001 i -= clen;
1002 if (i > 0) goto next;
1003 return cycles-i;
1006 #endif /* ASM_CPU_EMULATE */