rotate instructions

This commit is contained in:
Alex Janka 2023-01-18 13:14:22 +11:00
parent d1dae1aa73
commit df8acbfa32

View file

@ -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,
}
}