cpu/decoder - Implement PREFIX (bit shift & bit ops)

This commit is contained in:
madmaurice 2023-08-29 21:00:37 +02:00
parent cf54c7ec5f
commit 50cac936b9

View file

@ -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)