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::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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue