extra instructions + fix caps on flags
This commit is contained in:
parent
fffb6e0278
commit
7460d31913
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue