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