0xff まで • 256個の case 文 1,300行ぐらい • 実際は少し工夫してるのでもう少し少ない • 工夫しない方が速いことも • 全命令だと3,000行弱 • ひたすら地道に書いた • これからやる方はイチから書くのはお勧めしない • ツライだけで(30個ぐらい以降は)あまり楽しくない • 既存の実装をベースに書くのがオススメ 30 void OpCode::execute(uint8_t opCode){ if ((opCode >> 6) == 0b01 && (opCode & 0b00111000) != 0b00110000 && (opCode & 0b00000111) != 0b00000110){ // ld r, r' Log::execute(this->_cpu, opCode, "ld r, r'"); uint8_t *reg = this->targetRegister(opCode, 3); uint8_t *reg_dash = this->targetRegister(opCode, 0); *reg = *reg_dash; Log::dump_registers(this->_cpu); return; } switch (opCode){ case 0x00: // nop Log::execute(this->_cpu, opCode, "nop"); break; case 0x01: // ld bc, nn Log::execute(this->_cpu, opCode, "ld bc, nn"); this->_cpu->registers.c = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->registers.b = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1); this->_cpu->special_registers.pc += 2; break; case 0x02: { // ld (bc), a Log::execute(this->_cpu, opCode, "ld (bc), a"); Mcycle::m3(this->_cpu, this->_cpu->registers.bc(), this->_cpu->registers.a); break; } case 0x03: // inc bc Log::execute(this->_cpu, opCode, "inc bc"); this->_cpu->registers.bc(this->_cpu->registers.bc() + 1); break; case 0x04: // inc r case 0x0C: case 0x14: case 0x1C: case 0x24: case 0x2C: case 0x3C: { Log::execute(this->_cpu, opCode, "inc r"); uint8_t *reg = this->targetRegister(opCode, 3); this->setFlagsByIncrement(*reg); (*reg)++; break; } case 0x05: // dec r case 0x0D: case 0x15: case 0x1D: case 0x25: case 0x2D: case 0x3D: { Log::execute(this->_cpu, opCode, "dec r"); uint8_t *reg = this->targetRegister(opCode, 3); this->setFlagsByDecrement(*reg); (*reg)--; break; } case 0x06: // ld r, n case 0x0e: case 0x16: case 0x1e: case 0x26: case 0x2e: case 0x3e: { Log::execute(this->_cpu, opCode, "ld r, n"); uint8_t* reg = this->targetRegister(opCode, 3); *reg = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; break; } case 0x07: { // rlca Log::execute(this->_cpu, opCode, "rlca"); bool carry_bit = (this->_cpu->registers.a >> 7); this->_cpu->registers.a = (this->_cpu->registers.a << 1) | carry_bit; this->_cpu->registers.FC_Carry = carry_bit; this->_cpu->registers.FH_HalfCarry = false; this->_cpu->registers.FN_Subtract = false; break; } case 0x08: { // ex af, af' Log::execute(this->_cpu, opCode, "ex af, af'"); uint16_t af = this->_cpu->registers.af(); this->_cpu->registers.af(this->_cpu->registers_alternate.af()); this->_cpu->registers_alternate.af(af); break; } case 0x09: // add hl, rr case 0x19: case 0x29: case 0x39: { Log::execute(this->_cpu, opCode, "add hl, rr"); uint16_t value; switch (opCode){ // NOLINT(hicpp-multiway-paths-covered) case 0x09: value = this->_cpu->registers.bc(); break; case 0x19: value = this->_cpu->registers.de(); break; case 0x29: value = this->_cpu->registers.hl(); break; case 0x39: value = this->_cpu->special_registers.sp; break; } this->setFlagsByAdd16(this->_cpu->registers.hl(), value); this->_cpu->registers.hl(this->_cpu->registers.hl() + value); break; } case 0x0A: // ld a,(bc) Log::execute(this->_cpu, opCode, "ld a,(bc)"); this->_cpu->registers.a = Mcycle::m2(this->_cpu, this->_cpu->registers.bc()); break; case 0x0B: // dec bc Log::execute(this->_cpu, opCode, "dec bc"); this->_cpu->registers.bc(this->_cpu->registers.bc() - 1); break; case 0x0F: { // rrca Log::execute(this->_cpu, opCode, "rrca"); bool carry_bit = ((this->_cpu->registers.a & 1) > 0); this->_cpu->registers.a = (this->_cpu->registers.a >> 1) + ((this->_cpu->registers.a & 1) << 7); this->_cpu->registers.FH_HalfCarry = false; this->_cpu->registers.FN_Subtract = false; this->_cpu->registers.FC_Carry = carry_bit; break; } case 0x10: { // djnz n Log::execute(this->_cpu, opCode, "djnz n"); this->_cpu->registers.b--; if (this->_cpu->registers.b != 0){ auto diff = (int8_t)Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; } else { this->_cpu->special_registers.pc++; } break; } case 0x11: // ld de, nn Log::execute(this->_cpu, opCode, "ld de, nn"); this->_cpu->registers.e = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->registers.d = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1); this->_cpu->special_registers.pc += 2; break; case 0x12: // ld (de),a Log::execute(this->_cpu, opCode, "ld (de),a"); Mcycle::m3(this->_cpu, this->_cpu->registers.de(), this->_cpu->registers.a); break; case 0x13: // inc de Log::execute(this->_cpu, opCode, "inc de"); this->_cpu->registers.de(this->_cpu->registers.de() + 1); break; case 0x17: { // rla Log::execute(this->_cpu, opCode, "rla"); bool carry_flg = this->_cpu->registers.FC_Carry; this->_cpu->registers.FC_Carry = this->_cpu->registers.a >> 7; this->_cpu->registers.a = (this->_cpu->registers.a << 1) | carry_flg; this->_cpu->registers.FN_Subtract = false; this->_cpu->registers.FH_HalfCarry = false; break; } case 0x18: { // jr n Log::execute(this->_cpu, opCode, "jr n"); auto diff = (int8_t)(Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; break; } case 0x1A: // ld a,(de) Log::execute(this->_cpu, opCode, "ld a,(de)"); this->_cpu->registers.a = Mcycle::m2(this->_cpu, this->_cpu->registers.de()); break; case 0x1B: // dec de Log::execute(this->_cpu, opCode, "dec de"); this->_cpu->registers.de(this->_cpu->registers.de() - 1); break; case 0x1F: { // rra Log::execute(this->_cpu, opCode, "rra"); bool carry_flg = this->_cpu->registers.FC_Carry; this->_cpu->registers.FC_Carry = this->_cpu->registers.a & 1; this->_cpu->registers.a = (this->_cpu->registers.a >> 1) | (carry_flg << 7); this->_cpu->registers.FN_Subtract = false; this->_cpu->registers.FH_HalfCarry = false; break; } case 0x20: // jr nz, n Log::execute(this->_cpu, opCode, "jr nz, n"); if (! this->_cpu->registers.FZ_Zero){ auto diff = (int8_t)(Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; } else { this->_cpu->special_registers.pc++; } break; case 0x21: // ld hl, nn Log::execute(this->_cpu, opCode, "ld hl, nn"); this->_cpu->registers.hl( Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8) ); this->_cpu->special_registers.pc += 2; break; case 0x22: { // ld (nn), hl Log::execute(this->_cpu, opCode, "ld (nn), hl"); uint16_t addr = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); Mcycle::m3(this->_cpu, addr, this->_cpu->registers.l); Mcycle::m3(this->_cpu, addr + 1, this->_cpu->registers.h); this->_cpu->special_registers.pc += 2; break; } case 0x23: // inc hl Log::execute(this->_cpu, opCode, "inc hl"); this->_cpu->registers.hl(this->_cpu->registers.hl() + 1); break; case 0x27: { // daa Log::execute(this->_cpu, opCode, "daa"); uint8_t cr = 0; if ((this->_cpu->registers.a & 0x0f) > 0x09 || this->_cpu->registers.FH_HalfCarry){ cr += 0x06; } if (this->_cpu->registers.a > 0x99 || this->_cpu->registers.FC_Carry){ cr += 0x60; this->_cpu->registers.FC_Carry = true; } if (this->_cpu->registers.FN_Subtract){ this->_cpu->registers.FH_HalfCarry = this->_cpu->registers.FH_HalfCarry && (this->_cpu->registers.a & 0x0f) < 0x06; this->_cpu->registers.a -= cr; } else { this->_cpu->registers.FH_HalfCarry = (this->_cpu->registers.a & 0x0f) > 0x09; this->_cpu->registers.a += cr; } this->_cpu->registers.FS_Sign = this->_cpu->registers.a >> 7; this->_cpu->registers.FZ_Zero = this->_cpu->registers.a == 0; this->_cpu->registers.FPV_ParityOverflow = (OpCode::count1(this->_cpu->registers.a) % 2 == 0); break; } case 0x28: // jr z, n Log::execute(this->_cpu, opCode, "jr z, n"); if (this->_cpu->registers.FZ_Zero){ auto diff = (int8_t)(Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; } else { this->_cpu->special_registers.pc++; } break; case 0x2A: { // ld hl, (nn) Log::execute(this->_cpu, opCode, "ld hl, (nn)"); uint16_t addr = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); this->_cpu->special_registers.pc += 2; this->_cpu->registers.l = Mcycle::m2(this->_cpu, addr); this->_cpu->registers.h = Mcycle::m2(this->_cpu, addr + 1); Log::dump_registers(this->_cpu); break; } case 0x2B: // dec hl Log::execute(this->_cpu, opCode, "dec hl"); this->_cpu->registers.hl(this->_cpu->registers.hl() - 1); break; case 0x2F: // cpl Log::execute(this->_cpu, opCode, "cpl"); this->_cpu->registers.a ^= 0xff; this->_cpu->registers.FN_Subtract = true; this->_cpu->registers.FH_HalfCarry = true; break; case 0x30: // jr nc, n Log::execute(this->_cpu, opCode, "jr nc, n"); if (!this->_cpu->registers.FC_Carry){ auto diff = (int8_t)(Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; } else { this->_cpu->special_registers.pc++; } break; case 0x31: // ld sp, nn Log::execute(this->_cpu, opCode, "ld sp, nn"); this->_cpu->special_registers.sp = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); this->_cpu->special_registers.pc += 2; break; case 0x32: { // ld (nn), a Log::execute(this->_cpu, opCode, "ld (nn), a"); uint16_t addr = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); Mcycle::m3(this->_cpu, addr, this->_cpu->registers.a); this->_cpu->special_registers.pc += 2; break; } case 0x33: // inc sp Log::execute(this->_cpu, opCode, "inc sp"); this->_cpu->special_registers.sp++; break; case 0x34: { // inc (hl) Log::execute(this->_cpu, opCode, "inc (hl)"); uint16_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByIncrement(value); Mcycle::m3(this->_cpu, this->_cpu->registers.hl(), value + 1); break; } case 0x35: { // dec (hl) Log::execute(this->_cpu, opCode, "dec (hl)"); uint16_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByDecrement(value); Mcycle::m3(this->_cpu, this->_cpu->registers.hl(), value - 1); break; } case 0x36: // ld (hl), n Log::execute(this->_cpu, opCode, "ld (hl), n"); Mcycle::m3(this->_cpu, this->_cpu->registers.hl(), Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; break; case 0x37: // scf Log::execute(this->_cpu, opCode, "scf"); this->_cpu->registers.FC_Carry = true; this->_cpu->registers.FN_Subtract = false; this->_cpu->registers.FH_HalfCarry = false; break; case 0x38: // jr c, n Log::execute(this->_cpu, opCode, "jr c, n"); if (this->_cpu->registers.FC_Carry) { auto diff = (int8_t)(Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc)); this->_cpu->special_registers.pc++; this->_cpu->special_registers.pc += diff; } else { this->_cpu->special_registers.pc++; } break; case 0x3A: { // ld a, (nn) Log::execute(this->_cpu, opCode, "ld a, (nn)"); uint16_t addr = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); this->_cpu->special_registers.pc += 2; this->_cpu->registers.a = Mcycle::m2(this->_cpu, addr); Log::dump_registers(this->_cpu); break; } case 0x3B: // dec sp Log::execute(this->_cpu, opCode, "dec sp"); this->_cpu->special_registers.sp--; break; case 0x3F: { // ccf Log::execute(this->_cpu, opCode, "ccf"); bool saved_carry = this->_cpu->registers.FC_Carry; this->_cpu->registers.FC_Carry = !this->_cpu->registers.FC_Carry; this->_cpu->registers.FN_Subtract = false; this->_cpu->registers.FH_HalfCarry = saved_carry; break; } case 0x46: // ld r, (hl) case 0x4E: case 0x56: case 0x5E: case 0x66: case 0x6E: { Log::execute(this->_cpu, opCode, "ld r, (hl)"); uint8_t *reg = this->targetRegister(opCode, 3); *reg = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); break; } case 0x70: // ld (hl), r case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x77: Log::execute(this->_cpu, opCode, "ld (hl), r"); Mcycle::m3(this->_cpu, this->_cpu->registers.hl(), *(this->targetRegister(opCode, 0))); break; case 0x76: // halt Log::execute(this->_cpu, opCode, "halt"); this->_cpu->halt = true; break; case 0x7E: // ld a,(hl) Log::execute(this->_cpu, opCode, "ld a,(hl)"); this->_cpu->registers.a = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); break; case 0x80: // add a, r case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x87: { Log::execute(this->_cpu, opCode, "add a, r"); uint8_t* reg = this->targetRegister(opCode, 0); this->setFlagsByAddition(this->_cpu->registers.a, *reg, 0); this->_cpu->registers.a += *reg; break; } case 0x86: { // add a, (hl) Log::execute(this->_cpu, opCode, "add a, (hl)"); uint16_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByAddition(this->_cpu->registers.a, value, 0); this->_cpu->registers.a += value; break; } case 0x88: // adc a, r case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8F: { Log::execute(this->_cpu, opCode, "adc a, r"); uint8_t* reg = this->targetRegister(opCode, 0); uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsByAddition(this->_cpu->registers.a, *reg, carry); this->_cpu->registers.a += *reg + carry; break; } case 0x8E: { // adc a, (hl) Log::execute(this->_cpu, opCode, "adc a, (hl)"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsByAddition(this->_cpu->registers.a, value, carry); this->_cpu->registers.a += value + carry; break; } case 0x90: // sub r case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x97: { Log::execute(this->_cpu, opCode, "sub r"); uint8_t* reg = this->targetRegister(opCode, 0); this->setFlagsBySubtract(this->_cpu->registers.a, *reg, 0); this->_cpu->registers.a -= *reg; break; } case 0x96: { // sub (hl) Log::execute(this->_cpu, opCode, "sub (hl)"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsBySubtract(this->_cpu->registers.a, value, 0); this->_cpu->registers.a -= value; break; } case 0x98: // sbc a, r case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9F: { Log::execute(this->_cpu, opCode, "sbc a, r"); uint8_t* reg = this->targetRegister(opCode, 0); uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsBySubtract(this->_cpu->registers.a, *reg, carry); this->_cpu->registers.a -= *reg + carry; break; } case 0x9E: { // sbc a,(hl) Log::execute(this->_cpu, opCode, "sbc a,(hl)"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsBySubtract(this->_cpu->registers.a, value, carry); this->_cpu->registers.a -= value + carry; break; } case 0xA0: // and r case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA7: { Log::execute(this->_cpu, opCode, "and r"); uint8_t* reg = this->targetRegister(opCode, 0); this->_cpu->registers.a &= *reg; this->setFlagsByLogical(true); break; } case 0xA6: // and (hl) Log::execute(this->_cpu, opCode, "and (hl)"); this->_cpu->registers.a &= Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByLogical(true); break; case 0xA8: // xor r case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAF: { Log::execute(this->_cpu, opCode, "xor r"); uint8_t* reg = this->targetRegister(opCode, 0); this->_cpu->registers.a ^= *reg; this->setFlagsByLogical(false); break; } case 0xAE: // xor (hl) Log::execute(this->_cpu, opCode, "xor (hl)"); this->_cpu->registers.a ^= Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByLogical(false); break; case 0xB0: // or r case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB7: { Log::execute(this->_cpu, opCode, "or r"); uint8_t* reg = this->targetRegister(opCode, 0); this->_cpu->registers.a |= *reg; this->setFlagsByLogical(false); break; } case 0xB6: // or (hl) Log::execute(this->_cpu, opCode, "or (hl)"); this->_cpu->registers.a |= Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsByLogical(false); break; case 0xB8: // cp r case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBF: Log::execute(this->_cpu, opCode, "cp r"); this->setFlagsBySubtract(this->_cpu->registers.a, *(this->targetRegister(opCode, 0)), 0); break; case 0xBE: { // cp (hl) Log::execute(this->_cpu, opCode, "cp (hl)"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->registers.hl()); this->setFlagsBySubtract(this->_cpu->registers.a, value, 0); break; } case 0xC0: // ret nz Log::execute(this->_cpu, opCode, "ret nz"); if (!this->_cpu->registers.FZ_Zero) { executeRet(); } break; case 0xC1: // pop bc Log::execute(this->_cpu, opCode, "pop bc"); this->_cpu->registers.c = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp); this->_cpu->registers.b = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp + 1); this->_cpu->special_registers.sp += 2; Log::dump_registers(this->_cpu); break; case 0xC2: // jp nz, nn Log::execute(this->_cpu, opCode, "jp nz, nn"); if (!this->_cpu->registers.FZ_Zero) { this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xC3: // jp nn Log::execute(this->_cpu, opCode, "jp nn"); this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); break; case 0xC4: // call nz, nn Log::execute(this->_cpu, opCode, "call nz, nn"); if (!this->_cpu->registers.FZ_Zero) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xC5: // push bc Log::execute(this->_cpu, opCode, "push bc"); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.b); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.c); Log::dump_registers(this->_cpu); break; case 0xC6: { // add a, n Log::execute(this->_cpu, opCode, "add a, n"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->setFlagsByAddition(this->_cpu->registers.a, value, 0); this->_cpu->registers.a += value; break; } case 0xC7: // rst n (n = 0 - 7) case 0xCF: case 0xD7: case 0xDF: case 0xE7: case 0xEF: case 0xF7: case 0xFF: Log::execute(this->_cpu, opCode, "rst n (n = 0 - 7)"); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->special_registers.pc >> 8); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->special_registers.pc & 0xff); this->_cpu->special_registers.pc = (opCode & 0b00111000); break; case 0xC8: // ret z Log::execute(this->_cpu, opCode, "ret z"); if (this->_cpu->registers.FZ_Zero) { executeRet(); } break; case 0xC9: // ret Log::execute(this->_cpu, opCode, "ret"); executeRet(); break; case 0xCA: // jp z, nn Log::execute(this->_cpu, opCode, "jp z, nn"); if (this->_cpu->registers.FZ_Zero) { this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xCB: { // BITS Log::execute(this->_cpu, opCode, "BITS"); uint8_t opcode = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; executeCb(opcode); break; } case 0xCC: // call z, nn Log::execute(this->_cpu, opCode, "call z, nn"); if (this->_cpu->registers.FZ_Zero) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xCD: { // call nn Log::execute(this->_cpu, opCode, "call nn"); this->executeCall(); break; } case 0xCE: { // adc a, n Log::execute(this->_cpu, opCode, "adc a, n"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsByAddition(this->_cpu->registers.a, value, carry); this->_cpu->registers.a += value + carry; break; } case 0xD0: // ret nc Log::execute(this->_cpu, opCode, "ret nc"); if (!this->_cpu->registers.FC_Carry) { executeRet(); } break; case 0xD1: // pop de Log::execute(this->_cpu, opCode, "pop de"); this->_cpu->registers.e = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp); this->_cpu->registers.d = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp + 1); this->_cpu->special_registers.sp += 2; Log::dump_registers(this->_cpu); break; case 0xD2: // jp nc, nn Log::execute(this->_cpu, opCode, "jp nc, nn"); if (!this->_cpu->registers.FC_Carry) { this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xD3: { // out (n),a Log::execute(this->_cpu, opCode, "out (n),a"); uint8_t port = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc += 1; Mcycle::out(this->_cpu, port, this->_cpu->registers.a, this->_cpu->registers.a); break; } case 0xD4: // call nc, nn Log::execute(this->_cpu, opCode, "call nc, nn"); if (!this->_cpu->registers.FC_Carry) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xD5: // push de Log::execute(this->_cpu, opCode, "push de"); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.d); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.e); Log::dump_registers(this->_cpu); break; case 0xD6: { // sub n Log::execute(this->_cpu, opCode, "sub n"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->setFlagsBySubtract(this->_cpu->registers.a, value, 0); this->_cpu->registers.a -= value; break; } case 0xD8: // ret c Log::execute(this->_cpu, opCode, "ret c"); if (this->_cpu->registers.FC_Carry) { executeRet(); } break; case 0xD9: { // exx Log::execute(this->_cpu, opCode, "exx"); uint16_t temp; temp = this->_cpu->registers.bc(); this->_cpu->registers.bc(this->_cpu->registers_alternate.bc()); this->_cpu->registers_alternate.bc(temp); temp = this->_cpu->registers.de(); this->_cpu->registers.de(this->_cpu->registers_alternate.de()); this->_cpu->registers_alternate.de(temp); temp = this->_cpu->registers.hl(); this->_cpu->registers.hl(this->_cpu->registers_alternate.hl()); this->_cpu->registers_alternate.hl(temp); break; } case 0xDA: // jp c, nn Log::execute(this->_cpu, opCode, "jp c, nn"); if (this->_cpu->registers.FC_Carry) { this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xDB: { // in a, (n) Log::execute(this->_cpu, opCode, "in a, (n)"); uint8_t port = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->_cpu->registers.a = Mcycle::in(this->_cpu, port, this->_cpu->registers.a); break; } case 0xDC: // call c, nn Log::execute(this->_cpu, opCode, "call c, nn"); if (this->_cpu->registers.FC_Carry) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xDD: { // IX Log::execute(this->_cpu, opCode, "IX"); uint8_t opcode = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; executeDd(opcode); break; } case 0xDE: { // sbc a, n Log::execute(this->_cpu, opCode, "sbc a, n"); uint8_t value = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; uint8_t carry = this->_cpu->registers.carry_by_val(); this->setFlagsBySubtract(this->_cpu->registers.a, value, carry); this->_cpu->registers.a -= value + carry; break; } case 0xE0: // ret po Log::execute(this->_cpu, opCode, "ret po"); if (! this->_cpu->registers.FPV_ParityOverflow){ executeRet(); } break; case 0xE1: // pop hl Log::execute(this->_cpu, opCode, "pop hl"); this->_cpu->registers.hl( Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp + 1) << 8) ); this->_cpu->special_registers.sp += 2; Log::dump_registers(this->_cpu); break; case 0xE2: // jp po, nn Log::execute(this->_cpu, opCode, "jp po, nn"); if (! this->_cpu->registers.FPV_ParityOverflow){ this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xE3: { // ex (sp), hl Log::execute(this->_cpu, opCode, "ex (sp), hl"); uint16_t mem_value = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp + 1) << 8); uint16_t temp_hl = this->_cpu->registers.hl(); this->_cpu->registers.hl(mem_value); Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, temp_hl & 0xff); Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp + 1, temp_hl >> 8); break; } case 0xE4: // call po, nn Log::execute(this->_cpu, opCode, "call po, nn"); if (! this->_cpu->registers.FPV_ParityOverflow) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xE5: // push hl Log::execute(this->_cpu, opCode, "push hl"); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.hl() >> 8); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.hl() & 0xff); Log::dump_registers(this->_cpu); break; case 0xE6: // and n Log::execute(this->_cpu, opCode, "and n"); this->_cpu->registers.a &= Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->setFlagsByLogical(true); break; case 0xE8: // ret pe Log::execute(this->_cpu, opCode, "ret pe"); if (this->_cpu->registers.FPV_ParityOverflow) { executeRet(); } break; case 0xE9: // jp (hl) Log::execute(this->_cpu, opCode, "jp (hl)"); this->_cpu->special_registers.pc = this->_cpu->registers.hl(); break; case 0xEA: // jp pe, nn Log::execute(this->_cpu, opCode, "jp pe, nn"); if (this->_cpu->registers.FPV_ParityOverflow) { this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xEB: { // ex de,hl Log::execute(this->_cpu, opCode, "ex de,hl"); uint16_t de = this->_cpu->registers.de(); this->_cpu->registers.de(this->_cpu->registers.hl()); this->_cpu->registers.hl(de); break; } case 0xEC: // call pe, nn Log::execute(this->_cpu, opCode, "call pe, nn"); if (this->_cpu->registers.FPV_ParityOverflow) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xED: { // EXTD Log::execute(this->_cpu, opCode, "EXTD"); uint8_t opcode = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; executeEd(opcode); break; } case 0xEE: // xor n Log::execute(this->_cpu, opCode, "xor n"); this->_cpu->registers.a ^= Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->setFlagsByLogical(false); break; case 0xF0: // ret p Log::execute(this->_cpu, opCode, "ret p"); if (! this->_cpu->registers.FS_Sign){ executeRet(); } break; case 0xF1: // pop af Log::execute(this->_cpu, opCode, "pop af"); this->_cpu->registers.f(Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp)); this->_cpu->registers.a = Mcycle::m2(this->_cpu, this->_cpu->special_registers.sp + 1); this->_cpu->special_registers.sp += 2; Log::dump_registers(this->_cpu); break; case 0xF2: // jp p, nn Log::execute(this->_cpu, opCode, "jp p, nn"); if (! this->_cpu->registers.FS_Sign){ this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xF3: // di Log::execute(this->_cpu, opCode, "di"); this->_cpu->waitingDI = 1; break; case 0xF4: // call p, nn Log::execute(this->_cpu, opCode, "call p, nn"); if (! this->_cpu->registers.FS_Sign) { this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xF5: // push af Log::execute(this->_cpu, opCode, "push af"); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.a); this->_cpu->special_registers.sp--; Mcycle::m3(this->_cpu, this->_cpu->special_registers.sp, this->_cpu->registers.f()); Log::dump_registers(this->_cpu); break; case 0xF6: // or n Log::execute(this->_cpu, opCode, "or n"); this->_cpu->registers.a |= Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; this->setFlagsByLogical(false); break; case 0xF8: // ret m Log::execute(this->_cpu, opCode, "ret m"); if (this->_cpu->registers.FS_Sign){ executeRet(); } break; case 0xF9: // ld sp,hl Log::execute(this->_cpu, opCode, "ld sp,hl"); this->_cpu->special_registers.sp = this->_cpu->registers.hl(); break; case 0xFA: // jp m, nn Log::execute(this->_cpu, opCode, "jp m, nn"); if (this->_cpu->registers.FS_Sign){ this->_cpu->special_registers.pc = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc) + (Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc + 1) << 8); } else { this->_cpu->special_registers.pc += 2; } break; case 0xFB: // ei Log::execute(this->_cpu, opCode, "ei"); this->_cpu->waitingEI = 2; break; case 0xFC: // call m, nn Log::execute(this->_cpu, opCode, "call m, nn"); if (this->_cpu->registers.FS_Sign){ this->executeCall(); } else { this->_cpu->special_registers.pc += 2; } break; case 0xFD: { // IY Log::execute(this->_cpu, opCode, "IY"); uint8_t opcode = Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc); this->_cpu->special_registers.pc++; executeFd(opcode); break; } case 0xFE: { // cp n Log::execute(this->_cpu, opCode, "cp n"); this->setFlagsBySubtract(this->_cpu->registers.a, Mcycle::m2(this->_cpu, this->_cpu->special_registers.pc), 0); this->_cpu->special_registers.pc++; break; } default: char error[100]; sprintf(error, "Invalid op code: %02x", opCode); Log::error(this->_cpu, error); throw std::runtime_error(error); } }