From ec0f8bf02e0ccd468147d3563cf87b1d15b2de5f Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sat, 27 Aug 2022 13:43:15 +0200 Subject: [PATCH] Emulator: Implement SLA/SRA/SRL opcodes --- src/cpu-prefix.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 3 + 2 files changed, 154 insertions(+) diff --git a/src/cpu-prefix.cpp b/src/cpu-prefix.cpp index d51dfd5..80c1a29 100644 --- a/src/cpu-prefix.cpp +++ b/src/cpu-prefix.cpp @@ -34,9 +34,18 @@ void CPU::prefix() else if (opcode >= 0x18 && opcode <= 0x1f) { rr(); } + else if (opcode >= 0x20 && opcode <= 0x27) { + sla(); + } + else if (opcode >= 0x28 && opcode <= 0x2f) { + sra(); + } else if (opcode >= 0x30 && opcode <= 0x37) { swap(); } + else if (opcode >= 0x38 && opcode <= 0x3f) { + srl(); + } else if (opcode >= 0x40 && opcode <= 0x7f) { bit(); } @@ -554,3 +563,145 @@ void CPU::rrc() VERIFY_NOT_REACHED(); } } + +void CPU::sla() +{ + auto shift_left_arithmatically = [this](uint32_t& register_) -> void { + // SLA r8, flags: Z 0 0 C + m_wait_cycles += 8; + + // Shift Left Arithmetically register r8 + // ┌─────────┐ + // C <─│7 <── 0│<─ 0 + // └─────────┘ + // r8 + + // Copy bit 7 into carry flag + m_cf = (m_a & 0x80) == 0x80; + + // Shift Left Arithmetically register r8 + register_ = (register_ << 1) & 0xff; + + // Set other flags + m_zf = register_ == 0; + m_nf = 0; + m_hf = 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x20: /* SLA B */ shift_left_arithmatically(m_b); break; + case 0x21: /* SLA C */ shift_left_arithmatically(m_c); break; + case 0x22: /* SLA D */ shift_left_arithmatically(m_d); break; + case 0x23: /* SLA E */ shift_left_arithmatically(m_e); break; + case 0x24: /* SLA H */ shift_left_arithmatically(m_h); break; + case 0x25: /* SLA L */ shift_left_arithmatically(m_l); break; + case 0x26: /* SLA (HL) */ { + m_wait_cycles += 8; // + 8 = 16 total + + // Rotate the byte pointed to by HL right + uint32_t data = read(hl()); + shift_left_arithmatically(data); + write(hl(), data); + break; + } + case 0x27: /* SLA A */ shift_left_arithmatically(m_a); break; + default: + VERIFY_NOT_REACHED(); + } +} + +void CPU::sra() +{ + auto shift_right_arithmatically = [this](uint32_t& register_) -> void { + // SRL r8, flags: Z 0 0 C + m_wait_cycles += 8; + + // Shift Right Arithmatically register r8 + // ┌─────────┐ + // ┌─│7 ──> 0│─> C + // │ └─────────┘ + // │ ^ r8 + // └──┘ + + // Copy bit 0 into carry flag + m_cf = (m_a & 0x01) == 0x01; + + // Shift Right Arithmatically register r8 + register_ = (register_ >> 1) | (register_ & 0x80); // Note: bit 7 remains + + // Set other flags + m_zf = register_ == 0; + m_nf = 0; + m_hf = 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x28: /* SRA B */ shift_right_arithmatically(m_b); break; + case 0x29: /* SRA C */ shift_right_arithmatically(m_c); break; + case 0x2a: /* SRA D */ shift_right_arithmatically(m_d); break; + case 0x2b: /* SRA E */ shift_right_arithmatically(m_e); break; + case 0x2c: /* SRA H */ shift_right_arithmatically(m_h); break; + case 0x2d: /* SRA L */ shift_right_arithmatically(m_l); break; + case 0x2e: /* SRA (HL) */ { + m_wait_cycles += 8; // + 8 = 16 total + + // Rotate the byte pointed to by HL right + uint32_t data = read(hl()); + shift_right_arithmatically(data); + write(hl(), data); + break; + } + case 0x2f: /* SRA A */ shift_right_arithmatically(m_a); break; + default: + VERIFY_NOT_REACHED(); + } +} + +void CPU::srl() +{ + auto shift_right_logically = [this](uint32_t& register_) -> void { + // SRL r8, flags: Z 0 0 C + m_wait_cycles += 8; + + // Shift Right Locically register r8 + // ┌─────────┐ + // 0 ─>│7 ──> 0│─> C + // └─────────┘ + // r8 + + // Copy bit 0 into carry flag + m_cf = (m_a & 0x01) == 0x01; + + // Shift Right Locically register r8 + register_ = (register_ >> 1) & 0x7f; // Note: bit 7 is set to 0 + + // Set other flags + m_zf = register_ == 0; + m_nf = 0; + m_hf = 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x38: /* SRL B */ shift_right_logically(m_b); break; + case 0x39: /* SRL C */ shift_right_logically(m_c); break; + case 0x3a: /* SRL D */ shift_right_logically(m_d); break; + case 0x3b: /* SRL E */ shift_right_logically(m_e); break; + case 0x3c: /* SRL H */ shift_right_logically(m_h); break; + case 0x3d: /* SRL L */ shift_right_logically(m_l); break; + case 0x3e: /* SRL (HL) */ { + m_wait_cycles += 8; // + 8 = 16 total + + // Rotate the byte pointed to by HL right + uint32_t data = read(hl()); + shift_right_logically(data); + write(hl(), data); + break; + } + case 0x3f: /* SRL A */ shift_right_logically(m_a); break; + default: + VERIFY_NOT_REACHED(); + } +} diff --git a/src/cpu.h b/src/cpu.h index d8afc1b..65e148d 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -54,6 +54,9 @@ public: void rlc(); void rr(); void rrc(); + void sla(); + void sra(); + void srl(); // ------------------------------------- // Load Instructions