emu: NOT/NEG ops
This commit is contained in:
@@ -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 },
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -14,6 +14,7 @@ pub trait Operand: Copy + 'static +
|
||||
nt::ops::checked::CheckedShr<Output = Self> +
|
||||
nt::ops::overflowing::OverflowingSub +
|
||||
nt::ops::wrapping::WrappingAdd +
|
||||
nt::ops::wrapping::WrappingNeg +
|
||||
nt::ops::wrapping::WrappingSub +
|
||||
std::ops::Shl<Output = Self> +
|
||||
std::ops::Shr<Output = Self>
|
||||
|
||||
@@ -294,6 +294,19 @@ where for<'a> FarPtr<'a>: RValue<T> + LValue<T>
|
||||
|
||||
pub fn nop() {}
|
||||
|
||||
pub fn not<T: Operand, LVal: LValue<T>>(mut dst: LVal) {
|
||||
dst.write(!dst.read());
|
||||
}
|
||||
|
||||
pub fn neg<T: Operand, LVal: LValue<T>>(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<LVal: LValue<u16>>(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());
|
||||
|
||||
Reference in New Issue
Block a user