diff --git a/src/emu/flags.rs b/src/emu/flags.rs index e80c4fa..e40ba07 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -40,6 +40,7 @@ impl Flags { FlagOp::Eager { cf, .. } => cf, FlagOp::DEC { cf } => cf, FlagOp::INC { cf } => cf, + FlagOp::NEG { .. } => { self.res != 0 }, FlagOp::POPF => { self.res & 1 << CF_BIT != 0 }, FlagOp::RCL { dst, shamt, bits, old_cf, .. } => { // for carry-rotate shamt bas been modded to have range [0,bits]. @@ -138,6 +139,7 @@ impl Flags { FlagOp::Eager { of, .. } => of, FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 }, FlagOp::INC { .. } => { self.res == self.sign_mask }, + FlagOp::NEG { dst } => { self.res == dst && dst != 0 }, FlagOp::POPF => { self.res & 1 << OF_BIT != 0 }, FlagOp::RCL { dst, .. } | FlagOp::RCR { dst, .. } @@ -164,6 +166,7 @@ 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 }, + NEG { dst: u16 }, POPF, // flags encoded in result RCL { dst: u16, shamt: u16, bits: u16, old_cf: bool, pf: bool, af: bool, zf: bool, sf: bool }, RCR { dst: u16, shamt: u16, old_cf: bool, pf: bool, af: bool, zf: bool, sf: bool }, diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 89a8c8d..b13ab8d 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -489,7 +489,7 @@ impl i8088 { 0x10 => mov[reg=ss, modrm16] / "2/12+", // MOV ss, r/m16 0x18 => mov[reg=ds, modrm16] / "2/12+", }, // MOV ds, r/m16 0x8F: { 0x00 => pop_modrm[regval=ss, reg=sp, modrm16, convert, bus] / "12/25+" }, // POP r/m16 - 0x90 => nop[] / 3, + 0x90 => nop[] / 3, // NOP 0x91 => xchg[reg=a, reg=c] / 3, // XCHG ax, cx 0x92 => xchg[reg=a, reg=d] / 3, // XCHG ax, dx 0x93 => xchg[reg=a, reg=b] / 3, // XCHG ax, bx @@ -570,6 +570,10 @@ impl i8088 { 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) + 0xF6: { 0x10 => not[form=byte1, modrm8] / "3/24+", // NOT r/m8 + 0x18 => neg[form=byte1, flags, modrm8] / "3/24+" }, // NEG r/m8 + 0xF7: { 0x10 => not[form=word1, modrm16] / "3/24+", // NOT r/m16 + 0x18 => neg[form=word1, flags, modrm16] / "3/24+" }, // NEG r/m16 0xF8 => clc[flags] / 2, // CLC (Clear Carry Flag) 0xF9 => stc[flags] / 2, // STC (Set Carry Flag) 0xFC => cld[flags] / 2, // CLD (Clear Direction Flag) diff --git a/src/emu/operands.rs b/src/emu/operands.rs index 2e17993..1dc8bd6 100644 --- a/src/emu/operands.rs +++ b/src/emu/operands.rs @@ -14,6 +14,7 @@ pub trait Operand: Copy + 'static + nt::ops::checked::CheckedShr + nt::ops::overflowing::OverflowingSub + nt::ops::wrapping::WrappingAdd + + nt::ops::wrapping::WrappingNeg + nt::ops::wrapping::WrappingSub + std::ops::Shl + std::ops::Shr diff --git a/src/emu/operations.rs b/src/emu/operations.rs index d67b337..6475377 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -294,6 +294,19 @@ where for<'a> FarPtr<'a>: RValue + LValue pub fn nop() {} +pub fn not>(mut dst: LVal) { + dst.write(!dst.read()); +} + +pub fn neg>(flags: &mut Flags, mut dst: LVal) { + let dst_before = dst.read(); + let res = dst_before.wrapping_neg(); + dst.write(res); + flags.update(FlagOp::NEG { dst: dst_before.into() }, + res.into(), + T::HI_BIT_MASK.into()); +} + pub fn pop>(bus: &mut Bus, ss: u16, mut sp: Reg, mut dst: LVal) { let ptr = FarPtr { bus: bus, segment: ss, offset: sp.read() }; dst.write(ptr.read());