From 275cab4da412033a190be22ba7a043671f2d18b5 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sat, 27 Aug 2022 12:21:41 +0200 Subject: [PATCH] Emulator: Implement RLC/RRC opcodes --- src/cpu-prefix.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++- src/cpu.cpp | 20 ++++------ src/cpu.h | 2 + 3 files changed, 102 insertions(+), 14 deletions(-) diff --git a/src/cpu-prefix.cpp b/src/cpu-prefix.cpp index ee7905a..1781407 100644 --- a/src/cpu-prefix.cpp +++ b/src/cpu-prefix.cpp @@ -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(); + } +} diff --git a/src/cpu.cpp b/src/cpu.cpp index 1ee5779..da99b53 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -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: diff --git a/src/cpu.h b/src/cpu.h index d68d423..42bfc7f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -50,6 +50,8 @@ public: // Bit Shift Instructions void ra(); + void rlc(); + void rrc(); // ------------------------------------- // Load Instructions