diff --git a/cpu/decoder.cpp b/cpu/decoder.cpp index 9898da0..b9b84b3 100644 --- a/cpu/decoder.cpp +++ b/cpu/decoder.cpp @@ -181,6 +181,104 @@ void Cpu::executeInstruction() u16 rst_addr = op & 0x38; doCall(rst_addr); } + else if(op == 0xCB) // PREFIX + { + currentpc = state.PC; + opcode_t prefix_op = readPC8(); + +#if 0 + printf("@0x%04x: CB opcode %02X\n", currentpc, prefix_op); +#endif + + u8 reg = prefix_op & 0x7; + + u8 data; + switch(reg) + { + case 0x6: data = bus->read8(state.HL); mcycles = 3; break; + default: data = state.reg8(reg); mcycles = 2; break; + } + + // For BIT, RES, SET + u8 bit = (prefix_op >> 3) & 0x7; + + switch(prefix_op & 0xC0) + { + case 0x00: + switch(prefix_op & 0xF1) + { + case 0x00: // RLC + { + bool msb_set = (data & 0x80); + data = (data << 1) | (msb_set ? 0x1 : 0x0); + state.carry = msb_set; + } + break; + case 0x08: // RRC + { + bool lsb_set = (data & 0x01); + data = (data >> 1) | (lsb_set ? 0x80 : 0x00); + state.carry = lsb_set; + } + break; + case 0x10: // RL + { + bool msb_set = (data & 0x80); + data = (data << 1) | (state.carry ? 0x1 : 0x0); + state.carry = msb_set; + } + break; + case 0x18: // RR + { + bool lsb_set = (data & 0x01) != 0; + data = (data >> 1) | (state.carry ? 0x80 : 0x00); + state.carry = lsb_set; + } + break; + case 0x20: // SLA + state.carry = (data & 0x80); + data = (data << 1); + break; + case 0x28: // SRA + state.carry = (data & 0x01); + data = (data >> 1) | (data & 0x80); + break; + case 0x30: // SWAP + data = ((data >> 4) & 0x0F) | ((data << 4) & 0xF0); + break; + case 0x38: // SRL + state.carry = (data & 0x01); + data = (data >> 1); + break; + } + state.halfcarry = false; + state.subtract = false; + state.zero = (data == 0); + break; + case 0x40: // BIT + { + state.zero = (data & (1 << bit)) == 0; + state.subtract = false; + state.halfcarry = true; + } + break; + case 0x80: // RES + data &= ~(1 << bit); + break; + case 0xC0: // SET + data |= (1 << bit); + break; + } + // All ops except for BIT write the data back to where it came from + if ((prefix_op & 0xC0) != 0x40) + { + switch(reg) + { + case 0x6: bus->write8(state.HL, data); mcycles = 4; break; + default: state.reg8(reg) = data; break; + } + } + } else { switch(op)