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 {
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 {
let val = second + self.get_flag(FLAGS::Carry);
let val = second + self.get_flag(Flags::Carry);
self.add_u8s(first, val)
}
@ -15,24 +15,46 @@ impl CPU {
}
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)
}
pub(crate) fn inc(&mut self, val: u8) -> u8 {
self.add_u8s(val, 0x1)
pub(crate) fn inc(&mut self, reg: Reg8) {
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 {
self.sub_u8s(val, 0x1)
pub(crate) fn dec(&mut self, reg: Reg8) {
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 {
self.rotate_c(byte, Direction::Left)
self.rotate_with_carry(byte, Direction::Left)
}
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 {
@ -66,4 +88,8 @@ impl CPU {
self.reg.pc.set_high(0x0);
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 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,
};
@ -38,23 +38,23 @@ impl CPU {
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);
if carry {
rotated += get_rotation_carry(&direction);
self.set_flag(FLAGS::Carry);
self.set_flag(Flags::Carry);
}
return rotated;
}
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);
if old_carry > 0 {
rotated += get_rotation_carry(&direction);
}
if carry {
self.set_flag(FLAGS::Carry);
self.set_flag(Flags::Carry);
}
return rotated;
}
@ -62,16 +62,16 @@ impl CPU {
pub(crate) fn shift(&mut self, byte: u8, direction: Direction) -> u8 {
let (rotated, carry) = rotate(byte, &direction);
if carry {
self.set_flag(FLAGS::Carry);
self.set_flag(Flags::Carry);
}
return rotated;
}
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) {
0x1
} else {
@ -79,8 +79,12 @@ impl CPU {
}
}
pub(crate) fn set_flag(&mut self, flag: FLAGS) {
if flag == FLAGS::Zero {
pub(crate) fn is_flag(&mut self, flag: Flags) -> bool {
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!(
@ -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
.af
.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
.af
.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 {
self.set_flag(flag)
} else {
@ -118,11 +122,11 @@ impl CPU {
pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
FLAGS::HalfCarry,
Flags::HalfCarry,
(((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10,
);
return result;
@ -130,11 +134,11 @@ impl CPU {
pub(crate) fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
self.clear_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
FLAGS::HalfCarry,
Flags::HalfCarry,
(((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000,
);
return result;
@ -142,11 +146,11 @@ impl CPU {
pub(crate) fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
self.set_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
FLAGS::HalfCarry,
Flags::HalfCarry,
(((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10,
);
return result;
@ -154,11 +158,11 @@ impl CPU {
pub(crate) fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::NSubtract);
self.set_or_clear_flag(FLAGS::Carry, carry);
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
self.set_flag(Flags::NSubtract);
self.set_or_clear_flag(Flags::Carry, carry);
self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag(
FLAGS::HalfCarry,
Flags::HalfCarry,
(((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000,
);
return result;

View file

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