extra instructions + fix caps on flags

This commit is contained in:
Alex Janka 2023-02-01 20:04:05 +11:00
parent fffb6e0278
commit 7460d31913
3 changed files with 70 additions and 39 deletions

View file

@ -1,4 +1,4 @@
use crate::processor::{get_bit, Direction, SplitRegister, CPU, FLAGS}; use crate::processor::{get_bit, Direction, Flags, Reg8, SplitRegister, CPU};
impl CPU { impl CPU {
pub(crate) fn add(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn add(&mut self, first: u8, second: u8) -> u8 {
@ -6,7 +6,7 @@ impl CPU {
} }
pub(crate) fn adc(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn adc(&mut self, first: u8, second: u8) -> u8 {
let val = second + self.get_flag(FLAGS::Carry); let val = second + self.get_flag(Flags::Carry);
self.add_u8s(first, val) self.add_u8s(first, val)
} }
@ -15,24 +15,46 @@ impl CPU {
} }
pub(crate) fn sbc(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn sbc(&mut self, first: u8, second: u8) -> u8 {
let val = second + self.get_flag(FLAGS::Carry); let val = second + self.get_flag(Flags::Carry);
self.sub_u8s(first, val) self.sub_u8s(first, val)
} }
pub(crate) fn inc(&mut self, val: u8) -> u8 { pub(crate) fn inc(&mut self, reg: Reg8) {
self.add_u8s(val, 0x1) let result = self.reg.get_8(reg).wrapping_add(0x1);
self.clear_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
Flags::HalfCarry,
(((self.reg.get_8(reg) & 0xF).wrapping_add(0x1 & 0xF)) & 0x10) == 0x10,
);
self.reg.set_8(reg, result);
} }
pub(crate) fn dec(&mut self, val: u8) -> u8 { pub(crate) fn dec(&mut self, reg: Reg8) {
self.sub_u8s(val, 0x1) let result = self.reg.get_8(reg).wrapping_sub(0x1);
self.set_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
Flags::HalfCarry,
(((self.reg.get_8(reg) & 0xF).wrapping_sub(0x1 & 0xF)) & 0x10) == 0x10,
);
self.reg.set_8(reg, result);
}
pub(crate) fn inc_pair(&mut self, val: u16) -> u16 {
val.wrapping_add(0x1)
}
pub(crate) fn dec_pair(&mut self, val: u16) -> u16 {
val.wrapping_sub(0x1)
} }
pub(crate) fn rlc(&mut self, byte: u8) -> u8 { pub(crate) fn rlc(&mut self, byte: u8) -> u8 {
self.rotate_c(byte, Direction::Left) self.rotate_with_carry(byte, Direction::Left)
} }
pub(crate) fn rrc(&mut self, byte: u8) -> u8 { pub(crate) fn rrc(&mut self, byte: u8) -> u8 {
self.rotate_c(byte, Direction::Right) self.rotate_with_carry(byte, Direction::Right)
} }
pub(crate) fn rl(&mut self, byte: u8) -> u8 { pub(crate) fn rl(&mut self, byte: u8) -> u8 {
@ -66,4 +88,8 @@ impl CPU {
self.reg.pc.set_high(0x0); self.reg.pc.set_high(0x0);
self.reg.pc.set_low(address); self.reg.pc.set_low(address);
} }
pub(crate) fn jr(&mut self, jump: i8) {
self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into());
}
} }

View file

@ -1,7 +1,7 @@
use std::ops::{BitAnd, BitOr, BitXor}; use std::ops::{BitAnd, BitOr, BitXor};
use crate::{ use crate::{
processor::{get_bit, get_rotation_carry, rotate, Direction, SplitRegister, CPU, FLAGS}, processor::{get_bit, get_rotation_carry, rotate, Direction, Flags, SplitRegister, CPU},
verbose_println, verbose_println,
}; };
@ -38,23 +38,23 @@ impl CPU {
word word
} }
pub(crate) fn rotate_c(&mut self, byte: u8, direction: Direction) -> u8 { pub(crate) fn rotate_with_carry(&mut self, byte: u8, direction: Direction) -> u8 {
let (mut rotated, carry) = rotate(byte, &direction); let (mut rotated, carry) = rotate(byte, &direction);
if carry { if carry {
rotated += get_rotation_carry(&direction); rotated += get_rotation_carry(&direction);
self.set_flag(FLAGS::Carry); self.set_flag(Flags::Carry);
} }
return rotated; return rotated;
} }
pub(crate) fn rotate(&mut self, byte: u8, direction: Direction) -> u8 { pub(crate) fn rotate(&mut self, byte: u8, direction: Direction) -> u8 {
let old_carry = self.get_flag(FLAGS::Carry); let old_carry = self.get_flag(Flags::Carry);
let (mut rotated, carry) = rotate(byte, &direction); let (mut rotated, carry) = rotate(byte, &direction);
if old_carry > 0 { if old_carry > 0 {
rotated += get_rotation_carry(&direction); rotated += get_rotation_carry(&direction);
} }
if carry { if carry {
self.set_flag(FLAGS::Carry); self.set_flag(Flags::Carry);
} }
return rotated; return rotated;
} }
@ -62,16 +62,16 @@ impl CPU {
pub(crate) fn shift(&mut self, byte: u8, direction: Direction) -> u8 { pub(crate) fn shift(&mut self, byte: u8, direction: Direction) -> u8 {
let (rotated, carry) = rotate(byte, &direction); let (rotated, carry) = rotate(byte, &direction);
if carry { if carry {
self.set_flag(FLAGS::Carry); self.set_flag(Flags::Carry);
} }
return rotated; return rotated;
} }
pub(crate) fn bit(&mut self, byte: u8, bit: u8) { pub(crate) fn bit(&mut self, byte: u8, bit: u8) {
self.set_or_clear_flag(FLAGS::Zero, !get_bit(byte, bit)); self.set_or_clear_flag(Flags::Zero, !get_bit(byte, bit));
} }
pub(crate) fn get_flag(&mut self, flag: FLAGS) -> u8 { pub(crate) fn get_flag(&mut self, flag: Flags) -> u8 {
if get_bit(self.reg.af.get_low(), flag as u8) { if get_bit(self.reg.af.get_low(), flag as u8) {
0x1 0x1
} else { } else {
@ -79,8 +79,12 @@ impl CPU {
} }
} }
pub(crate) fn set_flag(&mut self, flag: FLAGS) { pub(crate) fn is_flag(&mut self, flag: Flags) -> bool {
if flag == FLAGS::Zero { get_bit(self.reg.af.get_low(), flag as u8)
}
pub(crate) fn set_flag(&mut self, flag: Flags) {
if flag == Flags::Zero {
verbose_println!("setting z flag"); verbose_println!("setting z flag");
} }
verbose_println!( verbose_println!(
@ -96,19 +100,19 @@ impl CPU {
); );
} }
pub(crate) fn clear_flag(&mut self, flag: FLAGS) { pub(crate) fn clear_flag(&mut self, flag: Flags) {
self.reg self.reg
.af .af
.set_low(self.reg.af.get_low().bitand(!(1 << flag as u8))); .set_low(self.reg.af.get_low().bitand(!(1 << flag as u8)));
} }
pub(crate) fn toggle_flag(&mut self, flag: FLAGS) { pub(crate) fn toggle_flag(&mut self, flag: Flags) {
self.reg self.reg
.af .af
.set_low(self.reg.af.get_low().bitxor(1 << flag as u8)); .set_low(self.reg.af.get_low().bitxor(1 << flag as u8));
} }
pub(crate) fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) { pub(crate) fn set_or_clear_flag(&mut self, flag: Flags, state: bool) {
if state { if state {
self.set_flag(flag) self.set_flag(flag)
} else { } else {
@ -118,11 +122,11 @@ impl CPU {
pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_add(second); let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::NSubtract); self.clear_flag(Flags::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry); self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0); self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag( self.set_or_clear_flag(
FLAGS::HalfCarry, Flags::HalfCarry,
(((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10, (((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10,
); );
return result; return result;
@ -130,11 +134,11 @@ impl CPU {
pub(crate) fn add_u16s(&mut self, first: u16, second: u16) -> u16 { pub(crate) fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_add(second); let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::NSubtract); self.clear_flag(Flags::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry); self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0); self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag( self.set_or_clear_flag(
FLAGS::HalfCarry, Flags::HalfCarry,
(((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000, (((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000,
); );
return result; return result;
@ -142,11 +146,11 @@ impl CPU {
pub(crate) fn sub_u8s(&mut self, first: u8, second: u8) -> u8 { pub(crate) fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_sub(second); let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::NSubtract); self.set_flag(Flags::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry); self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0); self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag( self.set_or_clear_flag(
FLAGS::HalfCarry, Flags::HalfCarry,
(((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10, (((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10,
); );
return result; return result;
@ -154,11 +158,11 @@ impl CPU {
pub(crate) fn sub_u16s(&mut self, first: u16, second: u16) -> u16 { pub(crate) fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_sub(second); let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::NSubtract); self.set_flag(Flags::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry); self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0); self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag( self.set_or_clear_flag(
FLAGS::HalfCarry, Flags::HalfCarry,
(((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000, (((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000,
); );
return result; return result;

View file

@ -6,7 +6,7 @@ mod instructions;
mod opcodes; mod opcodes;
#[derive(PartialEq)] #[derive(PartialEq)]
pub(crate) enum FLAGS { pub(crate) enum Flags {
Zero = 7, Zero = 7,
NSubtract = 6, NSubtract = 6,
HalfCarry = 5, HalfCarry = 5,
@ -45,6 +45,7 @@ impl CPU {
} }
} }
#[derive(Clone, Copy)]
pub enum Reg8 { pub enum Reg8 {
A, A,
F, F,