18 enum { rB, rC, rD, rE, rH, rL, rHL, rA, rF = rHL };
19 #define BC() (r[rB] << 8 | r[rC])
20 #define DE() (r[rD] << 8 | r[rE])
21 #define HL() (r[rH] << 8 | r[rL])
23 Var cpuvars[] = { ARR(r), VAR(ime), VAR(pc), VAR(curpc), VAR(sp), VAR(halt), {nil, 0, 0} };
37 return u | memread(pc++) << 8;
49 memwrite(--sp, u >> 8);
65 return v | memread(sp++) << 8;
71 return memread(n) | memread(n+1) << 8;
75 write16(u16int n, u16int v)
82 move(u8int dst, u8int src)
89 memwrite(HL(), r[src]);
93 r[dst] = memread(HL());
101 alu(u8int op, u8int n)
109 case 8: u = fetch8(); t = 8; break;
121 v4 = (r[rA] & 0x0f) + (u & 0x0f);
125 v4 = (r[rA] & 0x0f) + (u & 0x0f) + (r[rF] >> 4 & 1);
126 v = r[rA] + u + (r[rF] >> 4 & 1);
130 v4 = (r[rA] & 0x0f) + (~u & 0x0f) + 1;
131 v = r[rA] + (u ^ 0xff) + 1;
134 v4 = (r[rA] & 0x0f) + (~u & 0x0f) + (~r[rF] >> 4 & 1);
135 v = r[rA] + (u ^ 0xff) + (~r[rF] >> 4 & 1);
137 case 4: v = r[rA] & u; break;
138 case 5: v = r[rA] ^ u; break;
139 case 6: v = r[rA] | u; break;
149 }else if(op < 4 || op == 7){
164 branch(int cc, int t)
191 r[rF] = r[rF] & FLAGC | FLAGN;
204 r[rF] &= ~(FLAGN|FLAGC|FLAGH);
206 if((v & 0x10000) != 0)
208 if((HL() & 0xfff) + (u & 0xfff) >= 0x1000)
220 v = HL() + u + (r[rF] & FLAGC);
221 v4 = (HL() & 0xfff) + (u & 0xfff) + (r[rF] & FLAGC);
223 if((v & 0x10000) != 0)
225 if((v4 & 0x1000) != 0)
238 v = HL() + (u16int)~u + (~r[rF] & FLAGC);
239 v4 = (HL() & 0xfff) + (~u & 0xfff) + (~r[rF] & FLAGC);
241 if((v & 0x10000) == 0)
243 if((v4 & 0x1000) == 0)
264 call(u16int a, int cc)
270 return cc < 0 ? 16 : 24;
276 u8int op, v, n, m, c;
295 default: r[rF] = v >> 3 & 0x10; v = v << 1 | v >> 7; break;
296 case 1: r[rF] = v << 4 & 0x10; v = v >> 1 | v << 7; break;
297 case 2: r[rF] = v >> 3 & 0x10; v = v << 1 | c; break;
298 case 3: r[rF] = v << 4 & 0x10; v = v >> 1 | c << 7; break;
299 case 4: r[rF] = v >> 3 & 0x10; v = v << 1; break;
300 case 5: r[rF] = v << 4 & 0x10; v = v & 0x80 | v >> 1; break;
301 case 6: r[rF] = 0; v = v << 4 | v >> 4; break;
302 case 7: r[rF] = v << 4 & 0x10; v >>= 1; break;
308 r[rF] = r[rF] & ~(FLAGN|FLAGZ) | FLAGH;
336 if((mode & COL) == COL)
350 if((reg[IF] & reg[IE]) != 0)
354 if((reg[IF] & reg[IE]) != 0 && ime != 0){
357 v4 = reg[IF] & reg[IE];
360 for(pc = 0x40; v4 != 1; pc += 8)
367 print("%.4x %.2x AF %.2x%.2x BC %.2x%.2x DE %.2x%.2x HL %.2x%.2x SP %.4x\n", curpc, op, r[rA], r[rF], r[rB], r[rC], r[rD], r[rE], r[rH], r[rL], sp);
369 case 1: return move(op >> 3 & 7, op & 7);
370 case 2: return alu(op >> 3 & 7, op & 7);
375 if((mode & CGB) != 0 && (reg[KEY1] & 1) != 0){
376 reg[DIV] += divclock - clock >> 7 - ((mode & TURBO) != 0);
379 timertac(reg[TAC], 1);
383 print("STOP ignored (pc=%.4ux)\n", curpc);
385 case 0x20: return branch((r[rF] & FLAGZ) == 0, 0);
386 case 0x30: return branch((r[rF] & FLAGC) == 0, 0);
387 case 0x01: r[rC] = fetch8(); r[rB] = fetch8(); return 12;
388 case 0x11: r[rE] = fetch8(); r[rD] = fetch8(); return 12;
389 case 0x21: r[rL] = fetch8(); r[rH] = fetch8(); return 12;
390 case 0x31: sp = fetch16(); return 12;
391 case 0x02: memwrite(BC(), r[rA]); return 8;
392 case 0x12: memwrite(DE(), r[rA]); return 8;
393 case 0x22: memwrite(HL(), r[rA]); if(++r[rL] == 0) r[rH]++; return 8;
394 case 0x32: memwrite(HL(), r[rA]); if(r[rL]-- == 0) r[rH]--; return 8;
395 case 0x03: if(++r[rC] == 0) r[rB]++; return 8;
396 case 0x13: if(++r[rE] == 0) r[rD]++; return 8;
397 case 0x23: if(++r[rL] == 0) r[rH]++; return 8;
398 case 0x33: sp++; return 8;
399 case 0x04: inc(r[rB]++); return 4;
400 case 0x14: inc(r[rD]++); return 4;
401 case 0x24: inc(r[rH]++); return 4;
402 case 0x34: memwrite(HL(), inc(memread(HL()))); return 12;
403 case 0x05: dec(r[rB]--); return 4;
404 case 0x15: dec(r[rD]--); return 4;
405 case 0x25: dec(r[rH]--); return 4;
406 case 0x35: memwrite(HL(), dec(memread(HL()))); return 12;
407 case 0x06: r[rB] = fetch8(); return 8;
408 case 0x16: r[rD] = fetch8(); return 8;
409 case 0x26: r[rH] = fetch8(); return 8;
410 case 0x36: memwrite(HL(), fetch8()); return 12;
412 r[rF] = r[rA] >> 3 & 0x10;
413 r[rA] = r[rA] << 1 | r[rA] >> 7;
417 r[rF] = r[rA] >> 3 & 0x10;
418 r[rA] = r[rA] << 1 | v;
421 if(r[rA] > 0x99 && (r[rF] & FLAGN) == 0 || (r[rF] & FLAGC) != 0){
428 if((r[rA] & 0xf) > 9 && (r[rF] & FLAGN) == 0 || (r[rF] & FLAGH) != 0)
430 if((r[rF] & FLAGN) != 0)
434 r[rF] &= ~(FLAGZ|FLAGH);
438 case 0x37: r[rF] = r[rF] & ~(FLAGN | FLAGH) | FLAGC; return 4;
439 case 0x08: write16(fetch16(), sp); return 20;
440 case 0x18: return branch(1, 0);
441 case 0x28: return branch((r[rF] & FLAGZ) != 0, 0);
442 case 0x38: return branch((r[rF] & FLAGC) != 0, 0);
443 case 0x09: return addhl(BC());
444 case 0x19: return addhl(DE());
445 case 0x29: return addhl(HL());
446 case 0x39: return addhl(sp);
447 case 0x0a: r[rA] = memread(BC()); return 8;
448 case 0x1a: r[rA] = memread(DE()); return 8;
449 case 0x2a: r[rA] = memread(HL()); if(++r[rL] == 0) r[rH]++; return 8;
450 case 0x3a: r[rA] = memread(HL()); if(r[rL]-- == 0) r[rH]--; return 8;
451 case 0x0b: if(r[rC]-- == 0) r[rB]--; return 8;
452 case 0x1b: if(r[rE]-- == 0) r[rD]--; return 8;
453 case 0x2b: if(r[rL]-- == 0) r[rH]--; return 8;
454 case 0x3b: sp--; return 8;
455 case 0x0c: inc(r[rC]++); return 4;
456 case 0x1c: inc(r[rE]++); return 4;
457 case 0x2c: inc(r[rL]++); return 4;
458 case 0x3c: inc(r[rA]++); return 4;
459 case 0x0d: dec(r[rC]--); return 4;
460 case 0x1d: dec(r[rE]--); return 4;
461 case 0x2d: dec(r[rL]--); return 4;
462 case 0x3d: dec(r[rA]--); return 4;
463 case 0x0e: r[rC] = fetch8(); return 8;
464 case 0x1e: r[rE] = fetch8(); return 8;
465 case 0x2e: r[rL] = fetch8(); return 8;
466 case 0x3e: r[rA] = fetch8(); return 8;
468 r[rF] = r[rA] << 4 & 0x10;
469 r[rA] = r[rA] >> 1 | r[rA] << 7;
472 v = r[rF] << 3 & 0x80;
473 r[rF] = r[rA] << 4 & 0x10;
474 r[rA] = r[rA] >> 1 | v;
477 r[rF] |= FLAGN|FLAGH;
481 r[rF] = r[rF] & ~(FLAGN|FLAGH) ^ FLAGC;
483 case 0xc0: if((r[rF] & FLAGZ) == 0) {pc = pop16(); return 20;} return 8;
484 case 0xd0: if((r[rF] & FLAGC) == 0) {pc = pop16(); return 20;} return 8;
485 case 0xe0: memwrite(0xff00 | fetch8(), r[rA]); return 12;
486 case 0xf0: r[rA] = memread(0xff00 | fetch8()); return 12;
487 case 0xc1: r[rC] = pop8(); r[rB] = pop8(); return 12;
488 case 0xd1: r[rE] = pop8(); r[rD] = pop8(); return 12;
489 case 0xe1: r[rL] = pop8(); r[rH] = pop8(); return 12;
490 case 0xf1: r[rF] = pop8() & 0xf0; r[rA] = pop8(); return 12;
491 case 0xc2: return jump((r[rF] & FLAGZ) == 0);
492 case 0xd2: return jump((r[rF] & FLAGC) == 0);
493 case 0xe2: memwrite(0xff00 | r[rC], r[rA]); return 8;
494 case 0xf2: r[rA] = memread(0xff00 | r[rC]); return 8;
495 case 0xc3: return jump(1);
496 case 0xf3: ime = 0; return 4;
497 case 0xc4: return call(fetch16(), (r[rF] & FLAGZ) == 0);
498 case 0xd4: return call(fetch16(), (r[rF] & FLAGC) == 0);
499 case 0xc5: push8(r[rB]); push8(r[rC]); return 16;
500 case 0xd5: push8(r[rD]); push8(r[rE]); return 16;
501 case 0xe5: push8(r[rH]); push8(r[rL]); return 16;
502 case 0xf5: push8(r[rA]); push8(r[rF]); return 16;
503 case 0xc6: return alu(0, 8);
504 case 0xd6: return alu(2, 8);
505 case 0xe6: return alu(4, 8);
506 case 0xf6: return alu(6, 8);
507 case 0xc7: return call(0x00, -1);
508 case 0xd7: return call(0x10, -1);
509 case 0xe7: return call(0x20, -1);
510 case 0xf7: return call(0x30, -1);
511 case 0xc8: if((r[rF] & FLAGZ) != 0) {pc = pop16(); return 20;} return 8;
512 case 0xd8: if((r[rF] & FLAGC) != 0) {pc = pop16(); return 20;} return 8;
513 case 0xe8: case 0xf8:
516 v4 = (sp & 0xf) + (s & 0xf);
517 w = (sp & 0xff) + (s & 0xff);
531 case 0xc9: pc = pop16(); return 16;
532 case 0xd9: pc = pop16(); ime = 1; return 16;
533 case 0xe9: pc = HL(); return 4;
534 case 0xf9: sp = HL(); return 8;
535 case 0xca: return jump((r[rF] & FLAGZ) != 0);
536 case 0xda: return jump((r[rF] & FLAGC) != 0);
537 case 0xea: memwrite(fetch16(), r[rA]); return 16;
538 case 0xfa: r[rA] = memread(fetch16()); return 16;
539 case 0xcb: return bits();
540 case 0xfb: ime = 1; return 4;
541 case 0xcc: return call(fetch16(), (r[rF] & FLAGZ) != 0);
542 case 0xdc: return call(fetch16(), (r[rF] & FLAGC) != 0);
543 case 0xcd: return call(fetch16(), 1);
544 case 0xce: return alu(1, 8);
545 case 0xde: return alu(3, 8);
546 case 0xee: return alu(5, 8);
547 case 0xfe: return alu(7, 8);
548 case 0xcf: return call(0x08, -1);
549 case 0xdf: return call(0x18, -1);
550 case 0xef: return call(0x28, -1);
551 case 0xff: return call(0x38, -1);
553 sysfatal("undefined opcode %#.2x at pc=%#.4x", op, curpc);