diff --git a/src/emu/flags.rs b/src/emu/flags.rs index 90bf760..5a61cf0 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -35,9 +35,10 @@ pub struct Flags { impl Flags { pub fn cf(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << CF_BIT != 0 }, - FlagOp::DEC { cf } => { cf }, - FlagOp::INC { cf } => { cf }, + 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 }, @@ -62,49 +63,54 @@ impl Flags { None => false } }, - FlagOp::SUB { cf, .. } => { cf }, + FlagOp::SUB { cf, .. } => cf, } } pub fn pf(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << PF_BIT != 0 }, + FlagOp::Eager { pf, .. } => pf, + FlagOp::POPF => { self.res & 1 << PF_BIT != 0 }, FlagOp::ROL { pf, .. } - | FlagOp::ROR { pf, .. } => { pf }, + | FlagOp::ROR { pf, .. } => pf, _ => { self.res.count_ones() & 1 == 0 }, } } pub fn af(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << AF_BIT != 0 }, + FlagOp::Eager { af, .. } => af, + FlagOp::POPF => { self.res & 1 << AF_BIT != 0 }, FlagOp::ROL { af, .. } - | FlagOp::ROR { af, .. } => { af }, + | FlagOp::ROR { af, .. } => af, _ => { false /* XXX: unimplemented! */ }, } } pub fn zf(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << ZF_BIT != 0 }, + FlagOp::Eager { zf, .. } => zf, + FlagOp::POPF => { self.res & 1 << ZF_BIT != 0 }, FlagOp::ROL { zf, .. } - | FlagOp::ROR { zf, .. } => { zf }, + | FlagOp::ROR { zf, .. } => zf, _ => { self.res == 0 }, } } pub fn sf(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << SF_BIT != 0 }, + FlagOp::Eager { sf, .. } => sf, + FlagOp::POPF => { self.res & 1 << SF_BIT != 0 }, FlagOp::ROL { sf, .. } - | FlagOp::ROR { sf, .. } => { sf }, + | FlagOp::ROR { sf, .. } => sf, _ => { self.res & self.sign_mask != 0 }, } } pub fn of(&self) -> bool { match self.flag_op { - FlagOp::Eager => { self.res & 1 << OF_BIT != 0 }, + 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, .. } @@ -127,9 +133,10 @@ impl Flags { #[derive(Clone, Copy)] pub enum FlagOp { - Eager, // precomputed into result, for e.g. POPF + 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 }, @@ -139,7 +146,14 @@ pub enum FlagOp { } impl Default for FlagOp { - fn default() -> Self { FlagOp::Eager } + fn default() -> Self { + FlagOp::Eager { cf: false, + pf: false, + af: false, + zf: false, + sf: false, + of: false } + } } impl From for Flags { @@ -149,7 +163,7 @@ impl From for Flags { ie: flags & 1 << IF_BIT != 0, df: flags & 1 << DF_BIT != 0, - flag_op: FlagOp::Eager, + flag_op: FlagOp::POPF, res: flags, sign_mask: 0, } diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 62dd8da..09e2c4f 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -548,6 +548,11 @@ impl i8088 { 0xE8 => call[reg=ip, bus, regval=ss, reg=sp, rel16] / 23, 0xF2 => nop[rep=NotEqual, prefix] / 0, // REPNE/REPNZ 0xF3 => nop[rep=Equal, prefix] / 0, // REP/REPE/REPZ + 0xF5 => cmc[flags] / 2, // CMC (Complement Carry Flag) + 0xF8 => clc[flags] / 2, // CLC (Clear Carry Flag) + 0xF9 => stc[flags] / 2, // STC (Set Carry Flag) + 0xFC => cld[flags] / 2, // CLD (Clear Direction Flag) + 0xFD => std[flags] / 2, // STD (Set Direction Flag) 0xFE: { 0x00 => inc[form=byte1, flags, modrm8] / "3/23+", // INC r/m8 0x08 => dec[form=byte1, flags, modrm8] / "3/23+", }, // DEC r/m8 0xFF: { 0x00 => inc[form=word1, flags, modrm16] / "3/23+", // INC r/m16 diff --git a/src/emu/operations.rs b/src/emu/operations.rs index c194a58..894f2e4 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -72,6 +72,30 @@ pub fn call(mut ip: Reg, bus: &mut Bus, ss: u16, sp: Reg, rel16: u16) { ip.write(target); } +pub fn clc(flags: &mut Flags) { + flags.update(FlagOp::Eager { cf: false, + pf: flags.pf(), + af: flags.af(), + zf: flags.zf(), + sf: flags.sf(), + of: flags.of() }, + 0, 0); +} + +pub fn cld(flags: &mut Flags) { + flags.df = false; +} + +pub fn cmc(flags: &mut Flags) { + flags.update(FlagOp::Eager { cf: !flags.cf(), + pf: flags.pf(), + af: flags.af(), + zf: flags.zf(), + sf: flags.sf(), + of: flags.of() }, + 0, 0); +} + 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); @@ -471,6 +495,20 @@ where T: Operand, T::HI_BIT_MASK.into()); } +pub fn stc(flags: &mut Flags) { + flags.update(FlagOp::Eager { cf: true, + pf: flags.pf(), + af: flags.af(), + zf: flags.zf(), + sf: flags.sf(), + of: flags.of() }, + 0, 0); +} + +pub fn std(flags: &mut Flags) { + flags.df = true; +} + pub fn stos(flags: &Flags, bus: &mut Bus, rep: RepPrefix,