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