From df8acbfa3271dc0dd85b73210ca7a57995684379 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Wed, 18 Jan 2023 13:14:22 +1100 Subject: [PATCH] rotate instructions --- src/processor.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/processor.rs b/src/processor.rs index 3f9c1e5..09ba232 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -13,6 +13,11 @@ enum FLAGS { C = 4, } +enum Direction { + Left, + Right, +} + pub struct CPU { pub memory: Memory, pub state: State, @@ -43,7 +48,9 @@ impl CPU { self.state.bc.as_u8s.left = self.sub_u8s(self.state.bc.as_u8s.left, 1) }, 0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(), - 0x07 => panic!("RCLA rotate instruction: 0x07"), + 0x07 => unsafe { + self.state.af.as_u8s.left = self.rlc(self.state.af.as_u8s.left, Direction::Left) + }, 0x08 => unsafe { let address = self.ld_immediate_word().as_u16; let word = self.state.sp; @@ -61,7 +68,9 @@ impl CPU { self.state.bc.as_u8s.right = self.sub_u8s(self.state.bc.as_u8s.right, 0x1) }, 0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(), - 0x0F => panic!("RRCA rotate instruction: 0x0F"), + 0x0F => unsafe { + self.state.af.as_u8s.left = self.rlc(self.state.af.as_u8s.left, Direction::Right) + }, 0x10 => panic!("STOP instruction"), 0x11 => self.state.de = self.ld_immediate_word(), 0x12 => unsafe { @@ -77,7 +86,9 @@ impl CPU { self.state.de.as_u8s.left = self.sub_u8s(self.state.de.as_u8s.left, 0x1) }, 0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(), - 0x17 => panic!("RLA rotate instruction: 0x17"), + 0x17 => unsafe { + self.state.af.as_u8s.left = self.rl(self.state.af.as_u8s.left, Direction::Left); + }, 0x18 => unsafe { let t = (as_signed(self.ld_immediate_byte()) as i16) as u16; self.state.pc.as_u16 = self.add_u16s(self.state.pc.as_u16, t) @@ -97,7 +108,9 @@ impl CPU { self.state.de.as_u8s.right = self.sub_u8s(self.state.de.as_u8s.right, 1) }, 0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(), - 0x1F => panic!("RRA rotate instruction: 0x1F"), + 0x1F => unsafe { + self.state.af.as_u8s.left = self.rl(self.state.af.as_u8s.left, Direction::Right); + }, 0x20 => { let jump_size = self.ld_immediate_byte(); if self.get_flag(FLAGS::Z) == 0 { @@ -846,6 +859,9 @@ impl CPU { fn cb_subop(&mut self, subop: u8) { match subop { + 0x11 => unsafe { + self.state.bc.as_u8s.right = self.rl(self.state.bc.as_u8s.right, Direction::Left) + }, 0x7C => unsafe { self.set_or_clear_flag(FLAGS::Z, !get_bit(self.state.hl.as_u8s.left, 7)) }, @@ -861,6 +877,27 @@ impl CPU { }; } + fn rlc(&mut self, byte: u8, direction: Direction) -> u8 { + let (mut rotated, carry) = rotate(byte, &direction); + if carry { + rotated += get_rotation_carry(&direction); + self.set_flag(FLAGS::C); + } + return rotated; + } + + fn rl(&mut self, byte: u8, direction: Direction) -> u8 { + let old_carry = self.get_flag(FLAGS::C); + let (mut rotated, carry) = rotate(byte, &direction); + if old_carry > 0 { + rotated += get_rotation_carry(&direction); + } + if carry { + self.set_flag(FLAGS::C); + } + return rotated; + } + fn rst(&mut self, address: u16) { self.push(self.state.pc); self.state.pc.as_u8s.left = 0x0; @@ -1003,3 +1040,25 @@ fn get_bit(byte: u8, flag: u8) -> bool { let got = byte & mask; return got > 0x0; } + +fn rotate(byte: u8, direction: &Direction) -> (u8, bool) { + match direction { + Direction::Left => { + let carry = get_bit(byte, 7); + let r = byte << 1; + return (r, carry); + } + Direction::Right => { + let carry = get_bit(byte, 0); + let r = byte >> 1; + return (r, carry); + } + } +} + +fn get_rotation_carry(direction: &Direction) -> u8 { + match direction { + Direction::Left => 0b1, + Direction::Right => 0b10000000, + } +}