diff --git a/src/emu/flags.rs b/src/emu/flags.rs index d67bd31..225d6af 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -1,7 +1,5 @@ use std::fmt::{Debug, Formatter}; -use emu::operands::OperandWidth; - const CF_BIT: u8 = 0; // Carry Flag const PF_BIT: u8 = 2; // Parity Flag const AF_BIT: u8 = 4; // Adjust Flag @@ -30,10 +28,8 @@ pub struct Flags { // ALU state for lazy flag evaluation flag_op: FlagOp, - dst: u16, - src: u16, res: u16, - sign_bit_mask: u16, + sign_mask: u16, } impl Flags { @@ -61,31 +57,26 @@ impl Flags { pub fn sf(&self) -> bool { match self.flag_op { FlagOp::Eager => { self.res & 1 << SF_BIT != 0 }, - _ => { self.res & self.sign_bit_mask != 0 }, + _ => { self.res & self.sign_mask != 0 }, } } pub fn of(&self) -> bool { match self.flag_op { FlagOp::Eager => { self.res & 1 << OF_BIT != 0 }, - FlagOp::DEC => { self.res == self.sign_bit_mask - 1 }, - FlagOp::INC => { self.res == self.sign_bit_mask }, - FlagOp::SHIFT => { 0 != self.sign_bit_mask & (self.dst ^ self.res) }, - FlagOp::SUB => { 0 != self.sign_bit_mask & // In the (maybe) sign bit... - (self.src ^ self.dst) & // ...operands have different signs... - (self.dst ^ self.res) /* ...and result sign-bit changed */ }, + FlagOp::DEC => { self.res == self.sign_mask - 1 }, + FlagOp::INC => { self.res == self.sign_mask }, + FlagOp::SHIFT { dst } => { 0 != self.sign_mask & (dst ^ self.res) }, + FlagOp::SUB { dst, src } => { 0 != self.sign_mask & // In the (maybe) sign bit... + (src ^ dst) & // ...operands have different signs... + (dst ^ self.res) }, /* ...and result sign-bit changed */ } } - pub fn update(&mut self, op: FlagOp, dst: u16, src: u16, res: u16, op_width: OperandWidth) { + pub fn update(&mut self, op: FlagOp, res: u16, sign_mask: u16) { self.flag_op = op; - self.dst = dst; - self.src = src; self.res = res; - self.sign_bit_mask = match op_width { - OperandWidth::Byte => 0x80, - OperandWidth::Word => 0x8000, - } + self.sign_mask = sign_mask; } // The rotate ops update OF don't touch PF/AF/ZF/SF so we make @@ -105,8 +96,8 @@ pub enum FlagOp { Eager, // precomputed into result, for POPF or anything that changes only some flags DEC, INC, - SHIFT, - SUB, + SHIFT { dst: u16 }, + SUB { dst: u16, src: u16 }, } impl Default for FlagOp { @@ -122,10 +113,8 @@ impl From for Flags { df: flags & 1 << DF_BIT != 0, flag_op: FlagOp::Eager, - dst: 0, - src: 0, res: flags, - sign_bit_mask: 0, + sign_mask: 0, } } } diff --git a/src/emu/operands.rs b/src/emu/operands.rs index 4cc9138..df2d7cf 100644 --- a/src/emu/operands.rs +++ b/src/emu/operands.rs @@ -18,7 +18,6 @@ pub trait Operand: Copy + 'static + std::ops::Shr { type Signed: nt::ops::checked::CheckedShr; - const WIDTH: OperandWidth; const HI_BIT_MASK: Self; const BITS: Self; @@ -27,14 +26,8 @@ pub trait Operand: Copy + 'static + fn from_signed(src: Self::Signed) -> Self; } -pub enum OperandWidth { - Byte, - Word -} - impl Operand for u8 { type Signed = i8; - const WIDTH: OperandWidth = OperandWidth::Byte; const HI_BIT_MASK: u8 = 0x80; const BITS: u8 = 8; @@ -53,7 +46,6 @@ impl Operand for u8 { impl Operand for u16 { type Signed = i16; - const WIDTH: OperandWidth = OperandWidth::Word; const HI_BIT_MASK: u16 = 0x8000; const BITS: u16 = 16; diff --git a/src/emu/operations.rs b/src/emu/operations.rs index ea2ab29..a926ed3 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -76,7 +76,7 @@ pub fn cmp(flags: &mut Flags, dst: impl RValue, src: impl RValue< let (dst, src) = (dst.read(), src.read()); let (res, carry) = dst.overflowing_sub(&src); flags.cf = carry; - flags.update(FlagOp::SUB, dst.into(), src.into(), res.into(), T::WIDTH); + flags.update(FlagOp::SUB { dst: dst.into(), src: src.into() }, res.into(), T::HI_BIT_MASK.into()); } pub fn cmps(flags: &mut Flags, @@ -102,14 +102,14 @@ pub fn dec>(flags: &mut Flags, mut dst: LVal) { let dst_before = dst.read(); let res = dst_before.wrapping_sub(&T::one()); dst.write(res); - flags.update(FlagOp::DEC, dst_before.into(), 0, res.into(), T::WIDTH); + flags.update(FlagOp::DEC, res.into(), T::HI_BIT_MASK.into()); } pub fn inc>(flags: &mut Flags, mut dst: LVal) { let dst_before = dst.read(); let res = dst_before.wrapping_add(&T::one()); dst.write(res); - flags.update(FlagOp::INC, dst_before.into(), 0, res.into(), T::WIDTH); + flags.update(FlagOp::INC, res.into(), T::HI_BIT_MASK.into()); } pub fn int(cpu: &mut i8088, bus: &mut Bus, num: u8) { @@ -389,7 +389,7 @@ where T: Operand, Some(carrymask) => dst_before & carrymask != T::zero(), None => sign_bit }; - flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH); + flags.update(FlagOp::SHIFT { dst: dst_before.into() }, res.into(), T::HI_BIT_MASK.into()); } pub fn scas(flags: &mut Flags, @@ -430,7 +430,7 @@ where T: Operand, Some(carrymask) => dst_before & carrymask != T::zero(), None => false }; - flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH); + flags.update(FlagOp::SHIFT { dst: dst_before.into() }, res.into(), T::HI_BIT_MASK.into()); } // See comments on sar() @@ -453,7 +453,7 @@ where T: Operand, Some(carrymask) => dst_before & carrymask != T::zero(), None => false }; - flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH); + flags.update(FlagOp::SHIFT { dst: dst_before.into() }, res.into(), T::HI_BIT_MASK.into()); } pub fn stos(flags: &Flags,