use std::fmt::{Debug, Formatter}; const CF_BIT: u8 = 0; // Carry Flag const PF_BIT: u8 = 2; // Parity Flag const AF_BIT: u8 = 4; // Adjust Flag const ZF_BIT: u8 = 6; // Zero Flag const SF_BIT: u8 = 7; // Sign Flag const TF_BIT: u8 = 8; // Trap Flag const IF_BIT: u8 = 9; // Interrupt Enable const DF_BIT: u8 = 10; // Direction Flag const OF_BIT: u8 = 11; // Overflow Flag #[derive(Clone, Copy, Default)] pub struct Flags { // 0: Carry Flag: 1=CY(Carry), 0=NC(No Carry) // 1: Reserved // 2: LAZY Parity Flag: 1=PE(Even), 0=PO(Odd) // 3: Reserved // 4: LAZY Adjust Flag: 1=AC(Aux Carry), 0=NA(No Aux Carry) // 5: Reserved // 6: LAZY Zero Flag: 1=ZR(Zero), 0=NZ(Not Zero) // 7: LAZY Sign Flag: 1=NG(Negative), 0=PL(Positive) pub tf: bool, // 8: Trap Flag pub ie: bool, // 9: (Real name "IF") Interrupt Enable: 1=EI(Enable Interrupt), 0=DI(Disable Interrupt) pub df: bool, // 10: Direction Flag: 1=DN(Down), 0=UP(Up) // 11: LAZY Overflow Flag: 1=OV(Overflow), 0=NV(Not Overflow) // bits 12-15 always 1 // ALU state for lazy flag evaluation flag_op: FlagOp, res: u16, sign_mask: u16, } impl Flags { pub fn cf(&self) -> bool { match self.flag_op { FlagOp::Eager { cf, .. } => cf, FlagOp::DEC { cf } => cf, FlagOp::INC { cf } => cf, FlagOp::POPF => { self.res & 1 << CF_BIT != 0 }, FlagOp::ROL { dst, src, rot_mask, .. } => { dst & (self.sign_mask >> ((src.wrapping_sub(1)) & rot_mask as u16)) != 0 }, FlagOp::ROR { dst, src, rot_mask, .. } => { dst & (1 << ((src.wrapping_sub(1)) & rot_mask as u16)) != 0 }, FlagOp::SAR { dst, src, sign_bit } => { match 1u16.checked_shl(src as u32 - 1) { Some(carrymask) => dst & carrymask != 0, None => sign_bit } }, FlagOp::SHL { dst, src } => { match self.sign_mask.checked_shr(src as u32 - 1) { Some(carrymask) => dst & carrymask != 0, None => false } }, FlagOp::SHR { dst, src } => { match 1u16.checked_shl(src as u32 - 1) { Some(carrymask) => dst & carrymask != 0, None => false } }, FlagOp::SUB { cf, .. } => cf, } } pub fn pf(&self) -> bool { match self.flag_op { FlagOp::Eager { pf, .. } => pf, FlagOp::POPF => { self.res & 1 << PF_BIT != 0 }, FlagOp::ROL { pf, .. } | FlagOp::ROR { pf, .. } => pf, _ => { self.res.count_ones() & 1 == 0 }, } } pub fn af(&self) -> bool { match self.flag_op { FlagOp::Eager { af, .. } => af, FlagOp::POPF => { self.res & 1 << AF_BIT != 0 }, FlagOp::ROL { af, .. } | FlagOp::ROR { af, .. } => af, _ => { false /* XXX: unimplemented! */ }, } } pub fn zf(&self) -> bool { match self.flag_op { FlagOp::Eager { zf, .. } => zf, FlagOp::POPF => { self.res & 1 << ZF_BIT != 0 }, FlagOp::ROL { zf, .. } | FlagOp::ROR { zf, .. } => zf, _ => { self.res == 0 }, } } pub fn sf(&self) -> bool { match self.flag_op { FlagOp::Eager { sf, .. } => sf, FlagOp::POPF => { self.res & 1 << SF_BIT != 0 }, FlagOp::ROL { sf, .. } | FlagOp::ROR { sf, .. } => sf, _ => { self.res & self.sign_mask != 0 }, } } pub fn of(&self) -> bool { match self.flag_op { FlagOp::Eager { of, .. } => of, FlagOp::POPF => { self.res & 1 << OF_BIT != 0 }, FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 }, FlagOp::INC { .. } => { self.res == self.sign_mask }, FlagOp::ROL { dst, .. } | FlagOp::ROR { dst, .. } => { self.sign_mask & (dst ^ self.res) != 0 }, FlagOp::SAR { dst, .. } | FlagOp::SHL { dst, .. } | FlagOp::SHR { 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, res: u16, sign_mask: u16) { self.flag_op = op; self.res = res; self.sign_mask = sign_mask; } } #[derive(Clone, Copy)] pub enum FlagOp { Eager { cf: bool, pf: bool, af: bool, zf: bool, sf: bool, of: bool }, // all flags precomputed DEC { cf: bool }, INC { cf: bool }, POPF, // flags encoded in result ROL { dst: u16, src: u16, rot_mask: u16, cf: bool, pf: bool, af: bool, zf: bool, sf: bool }, ROR { dst: u16, src: u16, rot_mask: u16, cf: bool, pf: bool, af: bool, zf: bool, sf: bool }, SAR { dst: u16, src: u16, sign_bit: bool }, SHL { dst: u16, src: u16 }, SHR { dst: u16, src: u16 }, SUB { dst: u16, src: u16, cf: bool }, } impl Default for FlagOp { fn default() -> Self { FlagOp::Eager { cf: false, pf: false, af: false, zf: false, sf: false, of: false } } } impl From for Flags { fn from(flags: u16) -> Self { Self { tf: flags & 1 << TF_BIT != 0, ie: flags & 1 << IF_BIT != 0, df: flags & 1 << DF_BIT != 0, flag_op: FlagOp::POPF, res: flags, sign_mask: 0, } } } impl From for u16 { fn from(flags: Flags) -> Self { 0b1111_0000_0010_1010 // Not sure what all reserved bits should be, but it shouldn't matter | (flags.cf() as u16) | (flags.pf() as u16) << PF_BIT | (flags.af() as u16) << AF_BIT | (flags.zf() as u16) << ZF_BIT | (flags.sf() as u16) << SF_BIT | (flags.tf as u16) << TF_BIT | (flags.ie as u16) << IF_BIT | (flags.df as u16) << DF_BIT | (flags.of() as u16) << OF_BIT } } impl Debug for Flags { fn fmt(&self, fmt: &mut Formatter) -> Result<(), std::fmt::Error> { use std::fmt::Write; fmt.write_str("[ ")?; for flag in [ (self.cf(), "CF "), (self.pf(), "PF "), (self.af(), "AF "), (self.zf(), "ZF "), (self.sf(), "SF "), (self.tf, "TF "), (self.ie, "IF "), (self.df, "DF "), (self.of(), "OF ") ].iter() { if flag.0 { fmt.write_str(flag.1)? }; } fmt.write_char(']')?; Ok(()) } }