From fb6ba43ff17231274198a0fc80c0bbd887d35d26 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sat, 27 Aug 2022 12:53:34 +0200 Subject: [PATCH] Emulator: Implement RL/RR opcodes --- src/cpu-prefix.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++ src/cpu.cpp | 6 ++-- src/cpu.h | 2 ++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/cpu-prefix.cpp b/src/cpu-prefix.cpp index 1781407..1d5205e 100644 --- a/src/cpu-prefix.cpp +++ b/src/cpu-prefix.cpp @@ -28,6 +28,12 @@ void CPU::prefix() else if (opcode >= 0x08 && opcode <= 0x0f) { rrc(); } + else if (opcode >= 0x10 && opcode <= 0x17) { + rl(); + } + else if (opcode >= 0x18 && opcode <= 0x1f) { + rr(); + } else if (opcode >= 0x30 && opcode <= 0x3f) { swap(); } @@ -385,6 +391,47 @@ void CPU::swap() } } +void CPU::rl() +{ + auto rotate_left_carry = [this](uint32_t& register_) -> void { + // RL r8, flags: Z 0 0 C + m_wait_cycles += 8; + + // Copy bit 7 into carry flag + uint32_t old_carry = m_cf != 0; + m_cf = (register_ & 0x80) == 0x80; + + // Rotate register r8 left through carry + register_ = (old_carry | (register_ << 1)) & 0xff; + + // Set other flags + m_zf = register_ == 0; + m_nf = 0; + m_hf = 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x10: /* RL B */ rotate_left_carry(m_b); break; + case 0x11: /* RL C */ rotate_left_carry(m_c); break; + case 0x12: /* RL D */ rotate_left_carry(m_d); break; + case 0x13: /* RL E */ rotate_left_carry(m_e); break; + case 0x14: /* RL H */ rotate_left_carry(m_h); break; + case 0x15: /* RL L */ rotate_left_carry(m_l); break; + case 0x16: /* RL (HL) */ { + m_wait_cycles += 8; // + 8 = 16 total + + uint32_t data = read(hl()); + rotate_left_carry(data); + write(hl(), data); + break; + } + case 0x17: /* RL A */ rotate_left_carry(m_a); break; + default: + VERIFY_NOT_REACHED(); + } +} + void CPU::rlc() { auto rotate_left = [this](uint32_t& register_) -> void { @@ -426,6 +473,47 @@ void CPU::rlc() } } +void CPU::rr() +{ + auto rotate_right_carry = [this](uint32_t& register_) -> void { + // RR r8, flags: Z 0 0 C + m_wait_cycles += 8; + + // Copy bit 0 into carry flag + uint32_t old_carry = m_cf != 0; + m_cf = (register_ & 0x01) == 0x01; + + // Rotate register r8 right through carry + register_ = ((register_ >> 1) | (old_carry << 7)) & 0xff; + + // Set other flags + m_zf = register_ == 0; + m_nf = 0; + m_hf = 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x18: /* RR B */ rotate_right_carry(m_b); break; + case 0x19: /* RR C */ rotate_right_carry(m_c); break; + case 0x1a: /* RR D */ rotate_right_carry(m_d); break; + case 0x1b: /* RR E */ rotate_right_carry(m_e); break; + case 0x1c: /* RR H */ rotate_right_carry(m_h); break; + case 0x1d: /* RR L */ rotate_right_carry(m_l); break; + case 0x1e: /* RR (HL) */ { + m_wait_cycles += 8; // + 8 = 16 total + + uint32_t data = read(hl()); + rotate_right_carry(data); + write(hl(), data); + break; + } + case 0x1f: /* RR A */ rotate_right_carry(m_a); break; + default: + VERIFY_NOT_REACHED(); + } +} + void CPU::rrc() { auto rotate_right = [this](uint32_t& register_) -> void { diff --git a/src/cpu.cpp b/src/cpu.cpp index da99b53..7487856 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -703,8 +703,9 @@ void CPU::ra() // └─────────┘ // A + // Copy bit 7 into carry flag uint32_t old_carry = m_cf != 0; - m_cf = (m_a & 0x80) == 0x80; // Copy bit 7 into carry flag + m_cf = (m_a & 0x80) == 0x80; // Rotate register A left through carry m_a = old_carry | (m_a << 1); @@ -719,8 +720,9 @@ void CPU::ra() // └─────────┘ // A + // Copy bit 0 into carry flag uint32_t old_carry = m_cf != 0; - m_cf = (m_a & 0x1) == 0x1; // Copy bit 0 into carry flag + m_cf = (m_a & 0x1) == 0x1; // Rotate register A right through carry m_a = (m_a >> 1) | (old_carry << 7); diff --git a/src/cpu.h b/src/cpu.h index 42bfc7f..d8afc1b 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -50,7 +50,9 @@ public: // Bit Shift Instructions void ra(); + void rl(); void rlc(); + void rr(); void rrc(); // -------------------------------------