fix: reimplement flags register to be a bitfield

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-15 23:35:20 -05:00
parent f57cf2b312
commit 3b5d94adfc
2 changed files with 157 additions and 139 deletions

View File

@ -1,6 +1,7 @@
use super::bus::Bus; use super::bus::Bus;
use super::instruction::{Cycles, Instruction}; use super::instruction::{Cycles, Instruction};
use super::ppu::PPU; use super::ppu::PPU;
use bitfield::bitfield;
use std::{ use std::{
fmt::{Display, Formatter, Result as FmtResult}, fmt::{Display, Formatter, Result as FmtResult},
io::Write, io::Write,
@ -218,6 +219,14 @@ impl Cpu {
PC => self.reg.pc = value, PC => self.reg.pc = value,
} }
} }
pub fn flags(&self) -> &Flags {
&self.flags
}
pub fn set_flags(&mut self, flags: Flags) {
self.flags = flags;
}
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -255,44 +264,58 @@ struct Registers {
pc: u16, pc: u16,
} }
#[derive(Debug, Copy, Clone, Default)] bitfield! {
pub struct Flags { pub struct Flags(u8);
pub z: bool, // Zero Flag impl Debug;
pub n: bool, // Negative Flag pub z, set_z: 7; // Zero Flag
pub h: bool, // Half-Carry Flag pub n, set_n: 6; // Subtraction Flag
pub c: bool, // Carry Flag pub h, set_h: 5; // Half Carry Flag
pub c, set_c: 4; // Carry Flag
} }
impl Flags { impl Flags {
pub fn update(&mut self, z: bool, n: bool, h: bool, c: bool) { pub fn update(&mut self, z: bool, n: bool, h: bool, c: bool) {
self.z = z; self.set_z(z);
self.n = n; self.set_n(n);
self.h = h; self.set_h(h);
self.c = c; self.set_c(c);
}
}
impl Copy for Flags {}
impl Clone for Flags {
fn clone(&self) -> Self {
*self
}
}
impl Default for Flags {
fn default() -> Self {
Self(0)
} }
} }
impl Display for Flags { impl Display for Flags {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
if self.z { if self.z() {
f.write_str("Z")?; f.write_str("Z")?;
} else { } else {
f.write_str("_")?; f.write_str("_")?;
} }
if self.n { if self.n() {
f.write_str("N")?; f.write_str("N")?;
} else { } else {
f.write_str("_")?; f.write_str("_")?;
} }
if self.h { if self.h() {
f.write_str("H")?; f.write_str("H")?;
} else { } else {
f.write_str("_")?; f.write_str("_")?;
} }
if self.c { if self.c() {
f.write_str("C") f.write_str("C")
} else { } else {
f.write_str("_") f.write_str("_")
@ -300,19 +323,14 @@ impl Display for Flags {
} }
} }
impl From<u8> for Flags { impl From<Flags> for u8 {
fn from(flag: u8) -> Self { fn from(flags: Flags) -> Self {
Self { flags.0
z: (flag >> 7) == 1,
n: ((flag >> 6) & 0x01) == 1,
h: ((flag >> 5) & 0x01) == 1,
c: ((flag >> 4) & 0x01) == 1,
}
} }
} }
impl From<Flags> for u8 { impl From<u8> for Flags {
fn from(flag: Flags) -> Self { fn from(byte: u8) -> Self {
(flag.z as u8) << 7 | (flag.n as u8) << 6 | (flag.h as u8) << 5 | (flag.c as u8) << 4 Self(byte)
} }
} }

View File

@ -300,7 +300,7 @@ impl Instruction {
// JR cc[y - 4], d | If condition is true, then add d to current address and jump // JR cc[y - 4], d | If condition is true, then add d to current address and jump
// JR d | Add d to current address and jump // JR d | Add d to current address and jump
let prev = cpu.register_pair(RegisterPair::PC); let prev = cpu.register_pair(RegisterPair::PC);
let flags: Flags = cpu.register(Register::Flag).into(); let flags: &Flags = cpu.flags();
let new_addr = Self::add_u16_i8_no_flags(prev, offset); let new_addr = Self::add_u16_i8_no_flags(prev, offset);
match cond { match cond {
@ -309,7 +309,7 @@ impl Instruction {
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z { if !flags.z() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, new_addr);
return Cycles::new(12); return Cycles::new(12);
} }
@ -317,21 +317,21 @@ impl Instruction {
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z { if flags.z() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, new_addr);
return Cycles::new(12); return Cycles::new(12);
} }
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c { if !flags.c() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, new_addr);
return Cycles::new(12); return Cycles::new(12);
} }
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c { if flags.c() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, new_addr);
return Cycles::new(12); return Cycles::new(12);
} }
@ -342,7 +342,7 @@ impl Instruction {
Instruction::ADD(lhs, rhs) => match (lhs, rhs) { Instruction::ADD(lhs, rhs) => match (lhs, rhs) {
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => { (MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
// ADD HL, rp[p] | add register pair to HL. // ADD HL, rp[p] | add register pair to HL.
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
match pair { match pair {
RegisterPair::BC RegisterPair::BC
@ -357,12 +357,12 @@ impl Instruction {
} }
_ => unreachable!(), _ => unreachable!(),
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
Cycles::new(8) Cycles::new(8)
} }
(MATHTarget::Register(InstrRegister::A), MATHTarget::Register(reg)) => { (MATHTarget::Register(InstrRegister::A), MATHTarget::Register(reg)) => {
// ADD A, r[z] | Add (A + r[z]) to register A // ADD A, r[z] | Add (A + r[z]) to register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let sum; let sum;
let cycles: Cycles; let cycles: Cycles;
@ -386,12 +386,12 @@ impl Instruction {
} }
cpu.set_register(Register::A, sum); cpu.set_register(Register::A, sum);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
(MATHTarget::RegisterPair(RegisterPair::SP), MATHTarget::ImmediateByte(d)) => { (MATHTarget::RegisterPair(RegisterPair::SP), MATHTarget::ImmediateByte(d)) => {
// ADD SP, d | Add d (is signed) to register pair SP. // ADD SP, d | Add d (is signed) to register pair SP.
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let d = d as i8; let d = d as i8;
let sum = Self::add_u16_i8(cpu.register_pair(RegisterPair::SP), d, &mut flags); let sum = Self::add_u16_i8(cpu.register_pair(RegisterPair::SP), d, &mut flags);
cpu.set_register_pair(RegisterPair::SP, sum); cpu.set_register_pair(RegisterPair::SP, sum);
@ -399,11 +399,11 @@ impl Instruction {
} }
(MATHTarget::Register(InstrRegister::A), MATHTarget::ImmediateByte(n)) => { (MATHTarget::Register(InstrRegister::A), MATHTarget::ImmediateByte(n)) => {
// ADD A, n | Add n to register A // ADD A, n | Add n to register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let sum = Self::add_u8s(cpu.register(Register::A), n, &mut flags); let sum = Self::add_u8s(cpu.register(Register::A), n, &mut flags);
cpu.set_register(Register::A, sum); cpu.set_register(Register::A, sum);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
Cycles::new(8) Cycles::new(8)
} }
_ => unreachable!(), _ => unreachable!(),
@ -412,7 +412,7 @@ impl Instruction {
match registers { match registers {
Registers::Byte(reg) => { Registers::Byte(reg) => {
// INC r[y] | Increment Register // INC r[y] | Increment Register
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let cycles: Cycles; let cycles: Cycles;
match reg { match reg {
@ -436,7 +436,7 @@ impl Instruction {
cycles = Cycles::new(12) cycles = Cycles::new(12)
} }
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Registers::Word(pair) => { Registers::Word(pair) => {
@ -468,7 +468,7 @@ impl Instruction {
} }
Instruction::DEC(Registers::Byte(reg)) => { Instruction::DEC(Registers::Byte(reg)) => {
// DEC r[y] | Decrement Register // DEC r[y] | Decrement Register
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let cycles: Cycles; let cycles: Cycles;
match reg { match reg {
@ -492,92 +492,92 @@ impl Instruction {
cycles = Cycles::new(12); cycles = Cycles::new(12);
} }
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::RLCA => { Instruction::RLCA => {
// Rotate Register A left // Rotate Register A left
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a = cpu.register(Register::A); let a = cpu.register(Register::A);
let msb = a >> 7; let msb = a >> 7;
let rot_a = a.rotate_left(1); let rot_a = a.rotate_left(1);
flags.update(false, false, false, msb == 0x01); flags.update(false, false, false, msb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, rot_a); cpu.set_register(Register::A, rot_a);
Cycles::new(4) Cycles::new(4)
} }
Instruction::RRCA => { Instruction::RRCA => {
// Rotate Register A right // Rotate Register A right
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a = cpu.register(Register::A); let a = cpu.register(Register::A);
let lsb = a & 0x01; let lsb = a & 0x01;
let rot_a = a.rotate_right(1); let rot_a = a.rotate_right(1);
flags.update(false, false, false, lsb == 0x01); flags.update(false, false, false, lsb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, rot_a); cpu.set_register(Register::A, rot_a);
Cycles::new(4) Cycles::new(4)
} }
Instruction::RLA => { Instruction::RLA => {
// Rotate register A left through carry // Rotate register A left through carry
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a = cpu.register(Register::A); let a = cpu.register(Register::A);
let (rot_a, carry) = Self::rl_thru_carry(a, flags.c); let (rot_a, carry) = Self::rl_thru_carry(a, flags.c());
flags.update(false, false, false, carry); flags.update(false, false, false, carry);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, rot_a); cpu.set_register(Register::A, rot_a);
Cycles::new(4) Cycles::new(4)
} }
Instruction::RRA => { Instruction::RRA => {
// Rotate register A right through carry // Rotate register A right through carry
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a = cpu.register(Register::A); let a = cpu.register(Register::A);
let (rot_a, carry) = Self::rr_thru_carry(a, flags.c); let (rot_a, carry) = Self::rr_thru_carry(a, flags.c());
flags.update(false, false, false, carry); flags.update(false, false, false, carry);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, rot_a); cpu.set_register(Register::A, rot_a);
Cycles::new(4) Cycles::new(4)
} }
Instruction::DAA => unimplemented!(), Instruction::DAA => unimplemented!(),
Instruction::CPL => { Instruction::CPL => {
// Compliment A register (inverse) // Compliment A register (inverse)
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a = cpu.register(Register::A); let a = cpu.register(Register::A);
flags.n = true; flags.set_n(true);
flags.h = true; flags.set_h(true);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, !a); // Bitwise not is ! instead of ~ cpu.set_register(Register::A, !a); // Bitwise not is ! instead of ~
Cycles::new(4) Cycles::new(4)
} }
Instruction::SCF => { Instruction::SCF => {
// Set Carry Flag // Set Carry Flag
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
flags.n = false; flags.set_n(false);
flags.h = false; flags.set_h(false);
flags.c = true; flags.set_c(true);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
Cycles::new(4) Cycles::new(4)
} }
Instruction::CCF => { Instruction::CCF => {
// Compliment Carry Flag (inverse) // Compliment Carry Flag (inverse)
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
flags.n = false; flags.set_n(false);
flags.h = false; flags.set_h(false);
flags.c = !flags.c; flags.set_c(!flags.c());
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
Cycles::new(4) Cycles::new(4)
} }
Instruction::HALT => unimplemented!(), Instruction::HALT => unimplemented!(),
@ -585,7 +585,7 @@ impl Instruction {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// ADC A, r[z] | Add register r[z] plus the Carry flag to A // ADC A, r[z] | Add register r[z] plus the Carry flag to A
// FIXME: Do I Add register A as well? // FIXME: Do I Add register A as well?
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let sum; let sum;
@ -599,7 +599,7 @@ impl Instruction {
| InstrRegister::L | InstrRegister::L
| InstrRegister::A => { | InstrRegister::A => {
let value = let value =
cpu.register(Register::try_from(reg).unwrap()) + (flags.c as u8); cpu.register(Register::try_from(reg).unwrap()) + (flags.c() as u8);
sum = Self::add_u8s(a_value, value, &mut flags); sum = Self::add_u8s(a_value, value, &mut flags);
cycles = Cycles::new(4); cycles = Cycles::new(4);
} }
@ -609,17 +609,17 @@ impl Instruction {
cycles = Cycles::new(8); cycles = Cycles::new(8);
} }
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, sum); cpu.set_register(Register::A, sum);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// ADC A, n | Add immediate byte plus the carry flag to A // ADC A, n | Add immediate byte plus the carry flag to A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let value = n + (flags.c as u8); let value = n + (flags.c() as u8);
let sum = Self::add_u8s(cpu.register(Register::A), value, &mut flags); let sum = Self::add_u8s(cpu.register(Register::A), value, &mut flags);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, sum); cpu.set_register(Register::A, sum);
Cycles::new(8) Cycles::new(8)
} }
@ -628,7 +628,7 @@ impl Instruction {
Instruction::SUB(target) => match target { Instruction::SUB(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// SUB r[z] | Subtract the value in register r[z] from register A, then store in A // SUB r[z] | Subtract the value in register r[z] from register A, then store in A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let diff; let diff;
@ -652,16 +652,16 @@ impl Instruction {
} }
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, diff); cpu.set_register(Register::A, diff);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// SUB n | Subtract the immediate byte from register A, then store in A // SUB n | Subtract the immediate byte from register A, then store in A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let diff = Self::sub_u8s(cpu.register(Register::A), n, &mut flags); let diff = Self::sub_u8s(cpu.register(Register::A), n, &mut flags);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, diff); cpu.set_register(Register::A, diff);
Cycles::new(8) Cycles::new(8)
} }
@ -671,7 +671,7 @@ impl Instruction {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// SBC A, r[z] | Subtract the value from register r[z] from A, add the Carry flag and then store in A // SBC A, r[z] | Subtract the value from register r[z] from A, add the Carry flag and then store in A
// FIXME: See ADC, is this a correct understanding of this Instruction // FIXME: See ADC, is this a correct understanding of this Instruction
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let diff; let diff;
@ -685,7 +685,7 @@ impl Instruction {
| InstrRegister::L | InstrRegister::L
| InstrRegister::A => { | InstrRegister::A => {
let value = let value =
cpu.register(Register::try_from(reg).unwrap()) + (flags.c as u8); cpu.register(Register::try_from(reg).unwrap()) + (flags.c() as u8);
diff = Self::sub_u8s(a_value, value, &mut flags); diff = Self::sub_u8s(a_value, value, &mut flags);
cycles = Cycles::new(4); cycles = Cycles::new(4);
} }
@ -697,17 +697,17 @@ impl Instruction {
} }
cpu.set_register(Register::A, diff); cpu.set_register(Register::A, diff);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// SBC A, n | Subtract the value from immediate byte from A, add the carry flag and then store in A // SBC A, n | Subtract the value from immediate byte from A, add the carry flag and then store in A
// FIXME: The Fixme above applies to this variant as well // FIXME: The Fixme above applies to this variant as well
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let value = n + (flags.c as u8); let value = n + (flags.c() as u8);
let diff = Self::sub_u8s(cpu.register(Register::A), value, &mut flags); let diff = Self::sub_u8s(cpu.register(Register::A), value, &mut flags);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, diff); cpu.set_register(Register::A, diff);
Cycles::new(8) Cycles::new(8)
} }
@ -716,7 +716,7 @@ impl Instruction {
Instruction::AND(target) => match target { Instruction::AND(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// AND r[z] | Bitwise AND register r[z] and register A, store in register A // AND r[z] | Bitwise AND register r[z] and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let result; let result;
@ -741,17 +741,17 @@ impl Instruction {
} }
flags.update(result == 0, false, true, false); flags.update(result == 0, false, true, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// AND n | Bitwise AND immediate byte and register A, store in register A // AND n | Bitwise AND immediate byte and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let result = cpu.register(Register::A) & n; let result = cpu.register(Register::A) & n;
flags.update(result == 0, false, true, false); flags.update(result == 0, false, true, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
Cycles::new(8) Cycles::new(8)
} }
@ -760,7 +760,7 @@ impl Instruction {
Instruction::XOR(target) => match target { Instruction::XOR(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// XOR r[z] | Bitwise XOR register r[z] and register A, store in register A // XOR r[z] | Bitwise XOR register r[z] and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let result; let result;
@ -785,17 +785,17 @@ impl Instruction {
} }
flags.update(result == 0, false, false, false); flags.update(result == 0, false, false, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// XOR n | Bitwise XOR immediate byte and register A, store in register A // XOR n | Bitwise XOR immediate byte and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let result = cpu.register(Register::A) ^ n; let result = cpu.register(Register::A) ^ n;
flags.update(result == 0, false, false, false); flags.update(result == 0, false, false, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
Cycles::new(8) Cycles::new(8)
} }
@ -804,7 +804,7 @@ impl Instruction {
Instruction::OR(target) => match target { Instruction::OR(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// OR r[z] | Bitwise OR register r[z] and register A, store in register A // OR r[z] | Bitwise OR register r[z] and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
let result; let result;
@ -829,17 +829,17 @@ impl Instruction {
} }
flags.update(result == 0, false, false, false); flags.update(result == 0, false, false, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// OR n | Bitwise OR on immediate byte n and register A, store in register A // OR n | Bitwise OR on immediate byte n and register A, store in register A
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let result = cpu.register(Register::A) | n; let result = cpu.register(Register::A) | n;
flags.update(result == 0, false, false, false); flags.update(result == 0, false, false, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
Cycles::new(8) Cycles::new(8)
} }
@ -848,7 +848,7 @@ impl Instruction {
Instruction::CP(target) => match target { Instruction::CP(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// CP r[z] | Same behaviour as SUB, except the result is not stored. // CP r[z] | Same behaviour as SUB, except the result is not stored.
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles; let cycles: Cycles;
@ -871,15 +871,15 @@ impl Instruction {
} }
} }
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
// CP n | Same behaviour as SUB, except the result is not stored, // CP n | Same behaviour as SUB, except the result is not stored,
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let _ = Self::sub_u8s(cpu.register(Register::A), n, &mut flags); let _ = Self::sub_u8s(cpu.register(Register::A), n, &mut flags);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
Cycles::new(8) Cycles::new(8)
} }
_ => unreachable!(), _ => unreachable!(),
@ -887,11 +887,11 @@ impl Instruction {
Instruction::RET(cond) => { Instruction::RET(cond) => {
// RET cc[y] | Essentially a POP PC, Return from Subroutine // RET cc[y] | Essentially a POP PC, Return from Subroutine
// RET | Essentially a POP PC, Return from Subroutine // RET | Essentially a POP PC, Return from Subroutine
let flags: Flags = cpu.register(Register::Flag).into(); let flags: &Flags = cpu.flags();
match cond { match cond {
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z { if !flags.z() {
let addr = Self::pop(cpu); let addr = Self::pop(cpu);
cpu.set_register_pair(RegisterPair::PC, addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(20); return Cycles::new(20);
@ -899,7 +899,7 @@ impl Instruction {
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z { if flags.z() {
let addr = Self::pop(cpu); let addr = Self::pop(cpu);
cpu.set_register_pair(RegisterPair::PC, addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(20); return Cycles::new(20);
@ -907,7 +907,7 @@ impl Instruction {
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c { if !flags.c() {
let addr = Self::pop(cpu); let addr = Self::pop(cpu);
cpu.set_register_pair(RegisterPair::PC, addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(20); return Cycles::new(20);
@ -915,7 +915,7 @@ impl Instruction {
Cycles::new(8) Cycles::new(8)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c { if flags.c() {
let addr = Self::pop(cpu); let addr = Self::pop(cpu);
cpu.set_register_pair(RegisterPair::PC, addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(20); return Cycles::new(20);
@ -932,7 +932,7 @@ impl Instruction {
Instruction::LDHL(d) => { Instruction::LDHL(d) => {
// LDHL SP + d | Add SP + d to register HL // LDHL SP + d | Add SP + d to register HL
// LD HL, SP + d | Add SP + d to register HL // LD HL, SP + d | Add SP + d to register HL
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let sum = Self::add_u16_i8(cpu.register_pair(RegisterPair::SP), d, &mut flags); let sum = Self::add_u16_i8(cpu.register_pair(RegisterPair::SP), d, &mut flags);
cpu.set_register_pair(RegisterPair::HL, sum); cpu.set_register_pair(RegisterPair::HL, sum);
Cycles::new(12) Cycles::new(12)
@ -965,32 +965,32 @@ impl Instruction {
JPTarget::ImmediateWord(nn) => { JPTarget::ImmediateWord(nn) => {
// JP cc[y], nn | Store Immediate Word in the Program Counter if cond is met // JP cc[y], nn | Store Immediate Word in the Program Counter if cond is met
// JP nn | Store Immediate Word in the Program Counter // JP nn | Store Immediate Word in the Program Counter
let flags: Flags = cpu.register(Register::Flag).into(); let flags: &Flags = cpu.flags();
match cond { match cond {
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z { if !flags.z() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); return Cycles::new(16);
} }
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z { if flags.z() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); return Cycles::new(16);
} }
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c { if !flags.c() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); return Cycles::new(16);
} }
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c { if flags.c() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); return Cycles::new(16);
} }
@ -1018,12 +1018,12 @@ impl Instruction {
Instruction::CALL(cond, nn) => { Instruction::CALL(cond, nn) => {
// CALL cc[y], nn | Store nn on the stack, then store nn in the program counter if cond is met // CALL cc[y], nn | Store nn on the stack, then store nn in the program counter if cond is met
// CALL nn | Store nn on the stack, then store nn in the program counter // CALL nn | Store nn on the stack, then store nn in the program counter
let flags: Flags = cpu.register(Register::Flag).into(); let flags: &Flags = cpu.flags();
let pc = cpu.register_pair(RegisterPair::PC); let pc = cpu.register_pair(RegisterPair::PC);
match cond { match cond {
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z { if !flags.z() {
Self::push(cpu, pc); Self::push(cpu, pc);
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(24); return Cycles::new(24);
@ -1031,7 +1031,7 @@ impl Instruction {
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z { if flags.z() {
Self::push(cpu, pc); Self::push(cpu, pc);
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(24); return Cycles::new(24);
@ -1039,7 +1039,7 @@ impl Instruction {
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c { if !flags.c() {
Self::push(cpu, pc); Self::push(cpu, pc);
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(24); return Cycles::new(24);
@ -1047,7 +1047,7 @@ impl Instruction {
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c { if flags.c() {
Self::push(cpu, pc); Self::push(cpu, pc);
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(24); return Cycles::new(24);
@ -1081,7 +1081,7 @@ impl Instruction {
} }
Instruction::RLC(reg) => { Instruction::RLC(reg) => {
// RLC r[z] | Rotate register r[z] left // RLC r[z] | Rotate register r[z] left
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let msb; let msb;
let rot_reg; let rot_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1116,12 +1116,12 @@ impl Instruction {
} }
flags.update(rot_reg == 0, false, false, msb == 0x01); flags.update(rot_reg == 0, false, false, msb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::RRC(reg) => { Instruction::RRC(reg) => {
// RRC r[z] | Rotate Register r[z] right // RRC r[z] | Rotate Register r[z] right
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let lsb; let lsb;
let rot_reg; let rot_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1156,12 +1156,12 @@ impl Instruction {
} }
flags.update(rot_reg == 0, false, false, lsb == 0x01); flags.update(rot_reg == 0, false, false, lsb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::RL(reg) => { Instruction::RL(reg) => {
// RL r[z] | Rotate register r[z] left through carry // RL r[z] | Rotate register r[z] left through carry
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let carry; let carry;
let rot_reg; let rot_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1177,7 +1177,7 @@ impl Instruction {
let register = Register::try_from(reg).unwrap(); let register = Register::try_from(reg).unwrap();
let value = cpu.register(register); let value = cpu.register(register);
let (new_reg, new_carry) = Self::rl_thru_carry(value, flags.c); let (new_reg, new_carry) = Self::rl_thru_carry(value, flags.c());
rot_reg = new_reg; rot_reg = new_reg;
carry = new_carry; carry = new_carry;
@ -1188,7 +1188,7 @@ impl Instruction {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
let value = cpu.read_byte(addr); let value = cpu.read_byte(addr);
let (new_reg, new_carry) = Self::rl_thru_carry(value, flags.c); let (new_reg, new_carry) = Self::rl_thru_carry(value, flags.c());
rot_reg = new_reg; rot_reg = new_reg;
carry = new_carry; carry = new_carry;
@ -1198,13 +1198,13 @@ impl Instruction {
} }
flags.update(rot_reg == 0, false, false, carry); flags.update(rot_reg == 0, false, false, carry);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::RR(reg) => { Instruction::RR(reg) => {
// RR r[z] | Rotate register r[z] right through carry // RR r[z] | Rotate register r[z] right through carry
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let carry; let carry;
let rot_reg; let rot_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1220,7 +1220,7 @@ impl Instruction {
let register = Register::try_from(reg).unwrap(); let register = Register::try_from(reg).unwrap();
let value = cpu.register(register); let value = cpu.register(register);
let (new_reg, new_carry) = Self::rr_thru_carry(value, flags.c); let (new_reg, new_carry) = Self::rr_thru_carry(value, flags.c());
rot_reg = new_reg; rot_reg = new_reg;
carry = new_carry; carry = new_carry;
@ -1231,7 +1231,7 @@ impl Instruction {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
let value = cpu.read_byte(addr); let value = cpu.read_byte(addr);
let (new_reg, new_carry) = Self::rr_thru_carry(value, flags.c); let (new_reg, new_carry) = Self::rr_thru_carry(value, flags.c());
rot_reg = new_reg; rot_reg = new_reg;
carry = new_carry; carry = new_carry;
@ -1241,13 +1241,13 @@ impl Instruction {
} }
flags.update(rot_reg == 0, false, false, carry); flags.update(rot_reg == 0, false, false, carry);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::SLA(reg) => { Instruction::SLA(reg) => {
// SLA r[z] | Shift left arithmetic register r[z] // SLA r[z] | Shift left arithmetic register r[z]
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let shift_reg; let shift_reg;
let msb; let msb;
let cycles: Cycles; let cycles: Cycles;
@ -1282,13 +1282,13 @@ impl Instruction {
} }
flags.update(shift_reg == 0, false, false, msb == 0x01); flags.update(shift_reg == 0, false, false, msb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::SRA(reg) => { Instruction::SRA(reg) => {
// SRA r[z] | Shift right arithmetic register r[z] // SRA r[z] | Shift right arithmetic register r[z]
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let shift_reg; let shift_reg;
let lsb; let lsb;
let cycles: Cycles; let cycles: Cycles;
@ -1325,13 +1325,13 @@ impl Instruction {
} }
flags.update(shift_reg == 0, false, false, lsb == 0x01); flags.update(shift_reg == 0, false, false, lsb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::SWAP(reg) => { Instruction::SWAP(reg) => {
// SWAP r[z] | Swap the 4 highest and lowest bits in a byte // SWAP r[z] | Swap the 4 highest and lowest bits in a byte
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let swap_reg; let swap_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1364,13 +1364,13 @@ impl Instruction {
} }
flags.update(swap_reg == 0, false, false, false); flags.update(swap_reg == 0, false, false, false);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::SRL(reg) => { Instruction::SRL(reg) => {
// SRL r[z] | Shift right logic register r[z] // SRL r[z] | Shift right logic register r[z]
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let lsb; let lsb;
let shift_reg; let shift_reg;
let cycles: Cycles; let cycles: Cycles;
@ -1405,13 +1405,13 @@ impl Instruction {
} }
flags.update(shift_reg == 0, false, false, lsb == 0x01); flags.update(shift_reg == 0, false, false, lsb == 0x01);
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
Instruction::BIT(y, reg) => { Instruction::BIT(y, reg) => {
// BIT y, r[z] | Test y is in register r[z] // BIT y, r[z] | Test y is in register r[z]
let mut flags: Flags = cpu.register(Register::Flag).into(); let mut flags: Flags = cpu.flags().clone();
let is_bit_set; let is_bit_set;
let cycles: Cycles; let cycles: Cycles;
match reg { match reg {
@ -1437,8 +1437,8 @@ impl Instruction {
} }
} }
flags.update(!is_bit_set, false, true, flags.c); flags.update(!is_bit_set, false, true, flags.c());
cpu.set_register(Register::Flag, flags.into()); cpu.set_flags(flags);
cycles cycles
} }
@ -1542,7 +1542,7 @@ impl Instruction {
fn sub_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 { fn sub_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 {
let diff = left.wrapping_sub(right); let diff = left.wrapping_sub(right);
flags.update(diff == 0, true, Self::u8_half_carry(left, right), flags.c); flags.update(diff == 0, true, Self::u8_half_carry(left, right), flags.c());
diff diff
} }
@ -1577,7 +1577,7 @@ impl Instruction {
fn add_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 { fn add_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 {
let sum = left.wrapping_add(right); let sum = left.wrapping_add(right);
flags.update(sum == 0, false, Self::u8_half_carry(left, right), flags.c); flags.update(sum == 0, false, Self::u8_half_carry(left, right), flags.c());
sum sum
} }
@ -1599,7 +1599,7 @@ impl Instruction {
flags.update( flags.update(
false, false,
Self::u16_half_carry(left, right), Self::u16_half_carry(left, right),
flags.h, flags.h(),
did_overflow, did_overflow,
); );
sum sum