fix: reimplement flags register to be a bitfield
This commit is contained in:
parent
f57cf2b312
commit
3b5d94adfc
68
src/cpu.rs
68
src/cpu.rs
|
@ -1,6 +1,7 @@
|
|||
use super::bus::Bus;
|
||||
use super::instruction::{Cycles, Instruction};
|
||||
use super::ppu::PPU;
|
||||
use bitfield::bitfield;
|
||||
use std::{
|
||||
fmt::{Display, Formatter, Result as FmtResult},
|
||||
io::Write,
|
||||
|
@ -218,6 +219,14 @@ impl Cpu {
|
|||
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)]
|
||||
|
@ -255,44 +264,58 @@ struct Registers {
|
|||
pc: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct Flags {
|
||||
pub z: bool, // Zero Flag
|
||||
pub n: bool, // Negative Flag
|
||||
pub h: bool, // Half-Carry Flag
|
||||
pub c: bool, // Carry Flag
|
||||
bitfield! {
|
||||
pub struct Flags(u8);
|
||||
impl Debug;
|
||||
pub z, set_z: 7; // Zero Flag
|
||||
pub n, set_n: 6; // Subtraction Flag
|
||||
pub h, set_h: 5; // Half Carry Flag
|
||||
pub c, set_c: 4; // Carry Flag
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
pub fn update(&mut self, z: bool, n: bool, h: bool, c: bool) {
|
||||
self.z = z;
|
||||
self.n = n;
|
||||
self.h = h;
|
||||
self.c = c;
|
||||
self.set_z(z);
|
||||
self.set_n(n);
|
||||
self.set_h(h);
|
||||
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 {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
if self.z {
|
||||
if self.z() {
|
||||
f.write_str("Z")?;
|
||||
} else {
|
||||
f.write_str("_")?;
|
||||
}
|
||||
|
||||
if self.n {
|
||||
if self.n() {
|
||||
f.write_str("N")?;
|
||||
} else {
|
||||
f.write_str("_")?;
|
||||
}
|
||||
|
||||
if self.h {
|
||||
if self.h() {
|
||||
f.write_str("H")?;
|
||||
} else {
|
||||
f.write_str("_")?;
|
||||
}
|
||||
|
||||
if self.c {
|
||||
if self.c() {
|
||||
f.write_str("C")
|
||||
} else {
|
||||
f.write_str("_")
|
||||
|
@ -300,19 +323,14 @@ impl Display for Flags {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u8> for Flags {
|
||||
fn from(flag: u8) -> Self {
|
||||
Self {
|
||||
z: (flag >> 7) == 1,
|
||||
n: ((flag >> 6) & 0x01) == 1,
|
||||
h: ((flag >> 5) & 0x01) == 1,
|
||||
c: ((flag >> 4) & 0x01) == 1,
|
||||
}
|
||||
impl From<Flags> for u8 {
|
||||
fn from(flags: Flags) -> Self {
|
||||
flags.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Flags> for u8 {
|
||||
fn from(flag: Flags) -> Self {
|
||||
(flag.z as u8) << 7 | (flag.n as u8) << 6 | (flag.h as u8) << 5 | (flag.c as u8) << 4
|
||||
impl From<u8> for Flags {
|
||||
fn from(byte: u8) -> Self {
|
||||
Self(byte)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -300,7 +300,7 @@ impl Instruction {
|
|||
// 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
|
||||
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);
|
||||
|
||||
match cond {
|
||||
|
@ -309,7 +309,7 @@ impl Instruction {
|
|||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::NotZero => {
|
||||
if !flags.z {
|
||||
if !flags.z() {
|
||||
cpu.set_register_pair(RegisterPair::PC, new_addr);
|
||||
return Cycles::new(12);
|
||||
}
|
||||
|
@ -317,21 +317,21 @@ impl Instruction {
|
|||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::Zero => {
|
||||
if flags.z {
|
||||
if flags.z() {
|
||||
cpu.set_register_pair(RegisterPair::PC, new_addr);
|
||||
return Cycles::new(12);
|
||||
}
|
||||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::NotCarry => {
|
||||
if !flags.c {
|
||||
if !flags.c() {
|
||||
cpu.set_register_pair(RegisterPair::PC, new_addr);
|
||||
return Cycles::new(12);
|
||||
}
|
||||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::Carry => {
|
||||
if flags.c {
|
||||
if flags.c() {
|
||||
cpu.set_register_pair(RegisterPair::PC, new_addr);
|
||||
return Cycles::new(12);
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ impl Instruction {
|
|||
Instruction::ADD(lhs, rhs) => match (lhs, rhs) {
|
||||
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
|
||||
// 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 {
|
||||
RegisterPair::BC
|
||||
|
@ -357,12 +357,12 @@ impl Instruction {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
Cycles::new(8)
|
||||
}
|
||||
(MATHTarget::Register(InstrRegister::A), MATHTarget::Register(reg)) => {
|
||||
// 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 sum;
|
||||
let cycles: Cycles;
|
||||
|
@ -386,12 +386,12 @@ impl Instruction {
|
|||
}
|
||||
|
||||
cpu.set_register(Register::A, sum);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
(MATHTarget::RegisterPair(RegisterPair::SP), MATHTarget::ImmediateByte(d)) => {
|
||||
// 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 sum = Self::add_u16_i8(cpu.register_pair(RegisterPair::SP), d, &mut flags);
|
||||
cpu.set_register_pair(RegisterPair::SP, sum);
|
||||
|
@ -399,11 +399,11 @@ impl Instruction {
|
|||
}
|
||||
(MATHTarget::Register(InstrRegister::A), MATHTarget::ImmediateByte(n)) => {
|
||||
// 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);
|
||||
|
||||
cpu.set_register(Register::A, sum);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
Cycles::new(8)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -412,7 +412,7 @@ impl Instruction {
|
|||
match registers {
|
||||
Registers::Byte(reg) => {
|
||||
// INC r[y] | Increment Register
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
let cycles: Cycles;
|
||||
|
||||
match reg {
|
||||
|
@ -436,7 +436,7 @@ impl Instruction {
|
|||
cycles = Cycles::new(12)
|
||||
}
|
||||
}
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
Registers::Word(pair) => {
|
||||
|
@ -468,7 +468,7 @@ impl Instruction {
|
|||
}
|
||||
Instruction::DEC(Registers::Byte(reg)) => {
|
||||
// DEC r[y] | Decrement Register
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
let cycles: Cycles;
|
||||
|
||||
match reg {
|
||||
|
@ -492,92 +492,92 @@ impl Instruction {
|
|||
cycles = Cycles::new(12);
|
||||
}
|
||||
}
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
Instruction::RLCA => {
|
||||
// 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 msb = a >> 7;
|
||||
let rot_a = a.rotate_left(1);
|
||||
|
||||
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);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::RRCA => {
|
||||
// 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 lsb = a & 0x01;
|
||||
let rot_a = a.rotate_right(1);
|
||||
|
||||
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);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::RLA => {
|
||||
// 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 (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);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, rot_a);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::RRA => {
|
||||
// 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 (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);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, rot_a);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::DAA => unimplemented!(),
|
||||
Instruction::CPL => {
|
||||
// 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);
|
||||
|
||||
flags.n = true;
|
||||
flags.h = true;
|
||||
flags.set_n(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 ~
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::SCF => {
|
||||
// Set Carry Flag
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
|
||||
flags.n = false;
|
||||
flags.h = false;
|
||||
flags.c = true;
|
||||
flags.set_n(false);
|
||||
flags.set_h(false);
|
||||
flags.set_c(true);
|
||||
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::CCF => {
|
||||
// Compliment Carry Flag (inverse)
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
|
||||
flags.n = false;
|
||||
flags.h = false;
|
||||
flags.c = !flags.c;
|
||||
flags.set_n(false);
|
||||
flags.set_h(false);
|
||||
flags.set_c(!flags.c());
|
||||
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
Cycles::new(4)
|
||||
}
|
||||
Instruction::HALT => unimplemented!(),
|
||||
|
@ -585,7 +585,7 @@ impl Instruction {
|
|||
MATHTarget::Register(reg) => {
|
||||
// ADC A, r[z] | Add register r[z] plus the Carry flag to A
|
||||
// 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 cycles: Cycles;
|
||||
let sum;
|
||||
|
@ -599,7 +599,7 @@ impl Instruction {
|
|||
| InstrRegister::L
|
||||
| InstrRegister::A => {
|
||||
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);
|
||||
cycles = Cycles::new(4);
|
||||
}
|
||||
|
@ -609,17 +609,17 @@ impl Instruction {
|
|||
cycles = Cycles::new(8);
|
||||
}
|
||||
}
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, sum);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// ADC A, n | Add immediate byte plus the carry flag to A
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let value = n + (flags.c as u8);
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
let value = n + (flags.c() as u8);
|
||||
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);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -628,7 +628,7 @@ impl Instruction {
|
|||
Instruction::SUB(target) => match target {
|
||||
MATHTarget::Register(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
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);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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);
|
||||
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, diff);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -671,7 +671,7 @@ impl Instruction {
|
|||
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
|
||||
// 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 cycles: Cycles;
|
||||
let diff;
|
||||
|
@ -685,7 +685,7 @@ impl Instruction {
|
|||
| InstrRegister::L
|
||||
| InstrRegister::A => {
|
||||
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);
|
||||
cycles = Cycles::new(4);
|
||||
}
|
||||
|
@ -697,17 +697,17 @@ impl Instruction {
|
|||
}
|
||||
|
||||
cpu.set_register(Register::A, diff);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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
|
||||
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||
let value = n + (flags.c as u8);
|
||||
let mut flags: Flags = cpu.flags().clone();
|
||||
let value = n + (flags.c() as u8);
|
||||
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);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ impl Instruction {
|
|||
Instruction::AND(target) => match target {
|
||||
MATHTarget::Register(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
let result;
|
||||
|
@ -741,17 +741,17 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(result == 0, false, true, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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;
|
||||
|
||||
flags.update(result == 0, false, true, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -760,7 +760,7 @@ impl Instruction {
|
|||
Instruction::XOR(target) => match target {
|
||||
MATHTarget::Register(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
let result;
|
||||
|
@ -785,17 +785,17 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(result == 0, false, false, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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;
|
||||
|
||||
flags.update(result == 0, false, false, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -804,7 +804,7 @@ impl Instruction {
|
|||
Instruction::OR(target) => match target {
|
||||
MATHTarget::Register(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
let result;
|
||||
|
@ -829,17 +829,17 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(result == 0, false, false, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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;
|
||||
|
||||
flags.update(result == 0, false, false, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cpu.set_register(Register::A, result);
|
||||
Cycles::new(8)
|
||||
}
|
||||
|
@ -848,7 +848,7 @@ impl Instruction {
|
|||
Instruction::CP(target) => match target {
|
||||
MATHTarget::Register(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
|
||||
|
@ -871,15 +871,15 @@ impl Instruction {
|
|||
}
|
||||
}
|
||||
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
MATHTarget::ImmediateByte(n) => {
|
||||
// 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);
|
||||
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
Cycles::new(8)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -887,11 +887,11 @@ impl Instruction {
|
|||
Instruction::RET(cond) => {
|
||||
// RET cc[y] | 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 {
|
||||
JumpCondition::NotZero => {
|
||||
if !flags.z {
|
||||
if !flags.z() {
|
||||
let addr = Self::pop(cpu);
|
||||
cpu.set_register_pair(RegisterPair::PC, addr);
|
||||
return Cycles::new(20);
|
||||
|
@ -899,7 +899,7 @@ impl Instruction {
|
|||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::Zero => {
|
||||
if flags.z {
|
||||
if flags.z() {
|
||||
let addr = Self::pop(cpu);
|
||||
cpu.set_register_pair(RegisterPair::PC, addr);
|
||||
return Cycles::new(20);
|
||||
|
@ -907,7 +907,7 @@ impl Instruction {
|
|||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::NotCarry => {
|
||||
if !flags.c {
|
||||
if !flags.c() {
|
||||
let addr = Self::pop(cpu);
|
||||
cpu.set_register_pair(RegisterPair::PC, addr);
|
||||
return Cycles::new(20);
|
||||
|
@ -915,7 +915,7 @@ impl Instruction {
|
|||
Cycles::new(8)
|
||||
}
|
||||
JumpCondition::Carry => {
|
||||
if flags.c {
|
||||
if flags.c() {
|
||||
let addr = Self::pop(cpu);
|
||||
cpu.set_register_pair(RegisterPair::PC, addr);
|
||||
return Cycles::new(20);
|
||||
|
@ -932,7 +932,7 @@ impl Instruction {
|
|||
Instruction::LDHL(d) => {
|
||||
// LDHL 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);
|
||||
cpu.set_register_pair(RegisterPair::HL, sum);
|
||||
Cycles::new(12)
|
||||
|
@ -965,32 +965,32 @@ impl Instruction {
|
|||
JPTarget::ImmediateWord(nn) => {
|
||||
// JP cc[y], nn | Store Immediate Word in the Program Counter if cond is met
|
||||
// JP nn | Store Immediate Word in the Program Counter
|
||||
let flags: Flags = cpu.register(Register::Flag).into();
|
||||
let flags: &Flags = cpu.flags();
|
||||
|
||||
match cond {
|
||||
JumpCondition::NotZero => {
|
||||
if !flags.z {
|
||||
if !flags.z() {
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(16);
|
||||
}
|
||||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::Zero => {
|
||||
if flags.z {
|
||||
if flags.z() {
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(16);
|
||||
}
|
||||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::NotCarry => {
|
||||
if !flags.c {
|
||||
if !flags.c() {
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(16);
|
||||
}
|
||||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::Carry => {
|
||||
if flags.c {
|
||||
if flags.c() {
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(16);
|
||||
}
|
||||
|
@ -1018,12 +1018,12 @@ impl Instruction {
|
|||
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 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);
|
||||
|
||||
match cond {
|
||||
JumpCondition::NotZero => {
|
||||
if !flags.z {
|
||||
if !flags.z() {
|
||||
Self::push(cpu, pc);
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(24);
|
||||
|
@ -1031,7 +1031,7 @@ impl Instruction {
|
|||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::Zero => {
|
||||
if flags.z {
|
||||
if flags.z() {
|
||||
Self::push(cpu, pc);
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(24);
|
||||
|
@ -1039,7 +1039,7 @@ impl Instruction {
|
|||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::NotCarry => {
|
||||
if !flags.c {
|
||||
if !flags.c() {
|
||||
Self::push(cpu, pc);
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(24);
|
||||
|
@ -1047,7 +1047,7 @@ impl Instruction {
|
|||
Cycles::new(12)
|
||||
}
|
||||
JumpCondition::Carry => {
|
||||
if flags.c {
|
||||
if flags.c() {
|
||||
Self::push(cpu, pc);
|
||||
cpu.set_register_pair(RegisterPair::PC, nn);
|
||||
return Cycles::new(24);
|
||||
|
@ -1081,7 +1081,7 @@ impl Instruction {
|
|||
}
|
||||
Instruction::RLC(reg) => {
|
||||
// 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 rot_reg;
|
||||
let cycles: Cycles;
|
||||
|
@ -1116,12 +1116,12 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(rot_reg == 0, false, false, msb == 0x01);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
Instruction::RRC(reg) => {
|
||||
// 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 rot_reg;
|
||||
let cycles: Cycles;
|
||||
|
@ -1156,12 +1156,12 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(rot_reg == 0, false, false, lsb == 0x01);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
cycles
|
||||
}
|
||||
Instruction::RL(reg) => {
|
||||
// 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 rot_reg;
|
||||
let cycles: Cycles;
|
||||
|
@ -1177,7 +1177,7 @@ impl Instruction {
|
|||
let register = Register::try_from(reg).unwrap();
|
||||
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;
|
||||
carry = new_carry;
|
||||
|
||||
|
@ -1188,7 +1188,7 @@ impl Instruction {
|
|||
let addr = cpu.register_pair(RegisterPair::HL);
|
||||
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;
|
||||
carry = new_carry;
|
||||
|
||||
|
@ -1198,13 +1198,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(rot_reg == 0, false, false, carry);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::RR(reg) => {
|
||||
// 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 rot_reg;
|
||||
let cycles: Cycles;
|
||||
|
@ -1220,7 +1220,7 @@ impl Instruction {
|
|||
let register = Register::try_from(reg).unwrap();
|
||||
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;
|
||||
carry = new_carry;
|
||||
|
||||
|
@ -1231,7 +1231,7 @@ impl Instruction {
|
|||
let addr = cpu.register_pair(RegisterPair::HL);
|
||||
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;
|
||||
carry = new_carry;
|
||||
|
||||
|
@ -1241,13 +1241,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(rot_reg == 0, false, false, carry);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::SLA(reg) => {
|
||||
// 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 msb;
|
||||
let cycles: Cycles;
|
||||
|
@ -1282,13 +1282,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(shift_reg == 0, false, false, msb == 0x01);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::SRA(reg) => {
|
||||
// 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 lsb;
|
||||
let cycles: Cycles;
|
||||
|
@ -1325,13 +1325,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(shift_reg == 0, false, false, lsb == 0x01);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::SWAP(reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
|
||||
|
@ -1364,13 +1364,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(swap_reg == 0, false, false, false);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::SRL(reg) => {
|
||||
// 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 shift_reg;
|
||||
let cycles: Cycles;
|
||||
|
@ -1405,13 +1405,13 @@ impl Instruction {
|
|||
}
|
||||
|
||||
flags.update(shift_reg == 0, false, false, lsb == 0x01);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
Instruction::BIT(y, reg) => {
|
||||
// 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 cycles: Cycles;
|
||||
match reg {
|
||||
|
@ -1437,8 +1437,8 @@ impl Instruction {
|
|||
}
|
||||
}
|
||||
|
||||
flags.update(!is_bit_set, false, true, flags.c);
|
||||
cpu.set_register(Register::Flag, flags.into());
|
||||
flags.update(!is_bit_set, false, true, flags.c());
|
||||
cpu.set_flags(flags);
|
||||
|
||||
cycles
|
||||
}
|
||||
|
@ -1542,7 +1542,7 @@ impl Instruction {
|
|||
fn sub_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1577,7 +1577,7 @@ impl Instruction {
|
|||
fn add_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1599,7 +1599,7 @@ impl Instruction {
|
|||
flags.update(
|
||||
false,
|
||||
Self::u16_half_carry(left, right),
|
||||
flags.h,
|
||||
flags.h(),
|
||||
did_overflow,
|
||||
);
|
||||
sum
|
||||
|
|
Loading…
Reference in New Issue