Emulator: Implement RLC/RRC opcodes
This commit is contained in:
+92
-2
@@ -14,13 +14,21 @@
|
||||
|
||||
void CPU::prefix()
|
||||
{
|
||||
// Skip 0xcb opcode
|
||||
// Note: All these opcodes are considered 2 bytes, as the prefix is included
|
||||
|
||||
// Skip 0xcb prefix opcode
|
||||
m_pc = (m_pc + 1) & 0xffff;
|
||||
|
||||
// Read next opcode
|
||||
uint8_t opcode = read(m_pc);
|
||||
print("running opcode: {:#04x} @ ({:#06x})\n", opcode, m_pc);
|
||||
if (opcode >= 30 && opcode <= 0x3f) {
|
||||
if (opcode >= 0x00 && opcode <= 0x07) {
|
||||
rlc();
|
||||
}
|
||||
else if (opcode >= 0x08 && opcode <= 0x0f) {
|
||||
rrc();
|
||||
}
|
||||
else if (opcode >= 0x30 && opcode <= 0x3f) {
|
||||
swap();
|
||||
}
|
||||
else if (opcode >= 0x40 && opcode <= 0x7f) {
|
||||
@@ -376,3 +384,85 @@ void CPU::swap()
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::rlc()
|
||||
{
|
||||
auto rotate_left = [this](uint32_t& register_) -> void {
|
||||
// RLC r8, flags: Z 0 0 C
|
||||
m_wait_cycles += 8;
|
||||
|
||||
// Copy bit 7 into carry flag
|
||||
m_cf = (register_ & 0x80) == 0x80;
|
||||
|
||||
// Rotate register r8 left
|
||||
register_ = ((register_ >> 7) | (register_ << 1)) & 0xff;
|
||||
|
||||
// Set other flags
|
||||
m_zf = register_ == 0;
|
||||
m_nf = 0;
|
||||
m_hf = 0;
|
||||
};
|
||||
|
||||
uint8_t opcode = pcRead();
|
||||
switch (opcode) {
|
||||
case 0x00: /* RLC B */ rotate_left(m_b); break;
|
||||
case 0x01: /* RLC C */ rotate_left(m_c); break;
|
||||
case 0x02: /* RLC D */ rotate_left(m_d); break;
|
||||
case 0x03: /* RLC E */ rotate_left(m_e); break;
|
||||
case 0x04: /* RLC H */ rotate_left(m_h); break;
|
||||
case 0x05: /* RLC L */ rotate_left(m_l); break;
|
||||
case 0x06: /* RLC (HL) */ {
|
||||
m_wait_cycles += 8; // + 8 = 16 total
|
||||
|
||||
// Rotate the byte pointed to by HL left
|
||||
uint32_t data = read(hl());
|
||||
rotate_left(data);
|
||||
write(hl(), data);
|
||||
break;
|
||||
}
|
||||
case 0x07: /* RLC A */ rotate_left(m_a); break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::rrc()
|
||||
{
|
||||
auto rotate_right = [this](uint32_t& register_) -> void {
|
||||
// RRC r8, flags: Z 0 0 C
|
||||
m_wait_cycles += 8;
|
||||
|
||||
// Copy bit 0 into carry flag
|
||||
m_cf = (register_ & 0x1) == 0x1;
|
||||
|
||||
// Rotate register r8 right
|
||||
register_ = ((register_ >> 1) | (register_ << 7)) & 0xff;
|
||||
|
||||
// Set other flags
|
||||
m_zf = register_ == 0;
|
||||
m_nf = 0;
|
||||
m_hf = 0;
|
||||
};
|
||||
|
||||
uint8_t opcode = pcRead();
|
||||
switch (opcode) {
|
||||
case 0x08: /* RRC B */ rotate_right(m_b); break;
|
||||
case 0x09: /* RRC C */ rotate_right(m_c); break;
|
||||
case 0x0a: /* RRC D */ rotate_right(m_d); break;
|
||||
case 0x0b: /* RRC E */ rotate_right(m_e); break;
|
||||
case 0x0c: /* RRC H */ rotate_right(m_h); break;
|
||||
case 0x0d: /* RRC L */ rotate_right(m_l); break;
|
||||
case 0x0e: /* RRC (HL) */ {
|
||||
m_wait_cycles += 8; // + 8 = 16 total
|
||||
|
||||
// Rotate the byte pointed to by HL right
|
||||
uint32_t data = read(hl());
|
||||
rotate_right(data);
|
||||
write(hl(), data);
|
||||
break;
|
||||
}
|
||||
case 0x0f: /* RRC A */ rotate_right(m_a); break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -666,8 +666,7 @@ void CPU::ra()
|
||||
switch (opcode) {
|
||||
case 0x07: // RLCA
|
||||
|
||||
// Rotates A to the left with bit 7 being moved to bit 0 and also stored
|
||||
// into the carry
|
||||
// Rotates A to the left
|
||||
// ┌──────────────┐
|
||||
// │ ┌─────────┐ │
|
||||
// C <─┴─│7 <── 0│<─┘
|
||||
@@ -678,12 +677,11 @@ void CPU::ra()
|
||||
m_cf = (m_a & 0x80) == 0x80;
|
||||
|
||||
// Rotate register A left
|
||||
m_a = (m_a << 1) | (m_a >> 7);
|
||||
m_a = (m_a >> 7) | (m_a << 1);
|
||||
break;
|
||||
case 0x0f: // RRCA
|
||||
|
||||
// Rotates A to the right with bit 0 being moved to bit 7 and also
|
||||
// stored into the carry
|
||||
// Rotates A to the right
|
||||
// ┌──────────────┐
|
||||
// │ ┌─────────┐ │
|
||||
// └─>│7 ──> 0│─┴─> C
|
||||
@@ -694,12 +692,11 @@ void CPU::ra()
|
||||
m_cf = (m_a & 0x1) == 0x1;
|
||||
|
||||
// Rotate register A right
|
||||
m_a = (m_a << 7) | (m_a >> 1);
|
||||
m_a = (m_a >> 1) | (m_a << 7);
|
||||
break;
|
||||
case 0x17: { // RLA
|
||||
|
||||
// Rotates A to the left with the carry's value put into bit 0 and bit 7
|
||||
// is put into the carry
|
||||
// Rotate register A left through carry
|
||||
// ┌────────────────────┐
|
||||
// │ ┌─────────┐ │
|
||||
// └─ C <──│7 <── 0│<─┘
|
||||
@@ -710,13 +707,12 @@ void CPU::ra()
|
||||
m_cf = (m_a & 0x80) == 0x80; // Copy bit 7 into carry flag
|
||||
|
||||
// Rotate register A left through carry
|
||||
m_a = (m_a << 1) | old_carry;
|
||||
m_a = old_carry | (m_a << 1);
|
||||
break;
|
||||
}
|
||||
case 0x1f: { // RRA
|
||||
|
||||
// Rotates A to the right with the carry's value put into bit 7 and bit 0
|
||||
// is put into the carry
|
||||
// Rotate register A right through carry
|
||||
// ┌────────────────────┐
|
||||
// │ ┌─────────┐ │
|
||||
// └─>│7 ──> 0│──> C ─┘
|
||||
@@ -727,7 +723,7 @@ void CPU::ra()
|
||||
m_cf = (m_a & 0x1) == 0x1; // Copy bit 0 into carry flag
|
||||
|
||||
// Rotate register A right through carry
|
||||
m_a = (old_carry << 7) | (m_a >> 1);
|
||||
m_a = (m_a >> 1) | (old_carry << 7);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user