emu: AND/OR/XOR/TEST ops

This commit is contained in:
2021-04-09 00:38:21 -07:00
parent eca60fbe45
commit 663fa40137
3 changed files with 67 additions and 6 deletions

View File

@@ -40,6 +40,7 @@ impl Flags {
FlagOp::Eager { cf, .. } => cf,
FlagOp::DEC { cf } => cf,
FlagOp::INC { cf } => cf,
FlagOp::LOGIC => false,
FlagOp::NEG { .. } => { self.res != 0 },
FlagOp::POPF => { self.res & 1 << CF_BIT != 0 },
FlagOp::RCL { dst, shamt, bits, old_cf, .. } => {
@@ -101,6 +102,7 @@ impl Flags {
pub fn af(&self) -> bool {
match self.flag_op {
FlagOp::Eager { af, .. } => af,
FlagOp::LOGIC => false, // undefined
FlagOp::POPF => { self.res & 1 << AF_BIT != 0 },
FlagOp::RCL { af, .. }
| FlagOp::RCR { af, .. }
@@ -139,6 +141,7 @@ impl Flags {
FlagOp::Eager { of, .. } => of,
FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 },
FlagOp::INC { .. } => { self.res == self.sign_mask },
FlagOp::LOGIC => false,
FlagOp::NEG { dst } => { self.res == dst && dst != 0 },
FlagOp::POPF => { self.res & 1 << OF_BIT != 0 },
FlagOp::RCL { dst, .. }
@@ -166,6 +169,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 },
LOGIC,
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 },

View File

@@ -46,7 +46,7 @@ pub enum RepPrefix {
macro_rules! step {
// Base case: all args processed and ready to call op
(@code $(form=($($tyargs:tt),*),)? ( $($done:tt)* ),
(@code $(form=($($tyargs:tt),*),)? ( $($done:tt)* ),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
()) => {
ops::$name$(::<$($tyargs),*>)?($($done),*);
@@ -403,13 +403,31 @@ impl i8088 {
opcodes: {
0x06 => push[bus, regval=ss, reg=sp, regval=es] / 14,
0x07 => pop[bus, regval=ss, reg=sp, reg=es] / 12,
0x08 _ => or[flags, modrm8, r8] / "3/24+", // OR r/m8, r8
0x09 _ => or[flags, modrm16, r16] / "3/24+", // OR r/m16, r16
0x0A _ => or[flags, r8, modrm8] / "3/13+", // OR r8, r/m8
0x0B _ => or[flags, r16, modrm16] / "3/13+", // OR r16, r/m16
0x0C => or[flags, reglo=a, d8] / 4, // OR al, d8
0x0D => or[flags, reg=a, d16] / 4, // OR ax, d16
0x0E => push[bus, regval=ss, reg=sp, regval=cs] / 14,
0x16 => push[bus, regval=ss, reg=sp, regval=ss] / 14,
0x17 => pop[bus, regval=ss, reg=sp, reg=ss] / 12,
0x1E => push[bus, regval=ss, reg=sp, regval=ds] / 14,
0x1F => pop[bus, regval=ss, reg=sp, reg=ds] / 12,
0x20 _ => and[flags, modrm8, r8] / "3/24+", // AND r/m8, r8
0x21 _ => and[flags, modrm16, r16] / "3/24+", // AND r/m16, r16
0x22 _ => and[flags, r8, modrm8] / "3/13+", // AND r8, r/m8
0x23 _ => and[flags, r16, modrm16] / "3/13+", // AND r16, r/m16
0x24 => and[flags, reglo=a, d8] / 4, // AND al, d8
0x25 => and[flags, reg=a, d16] / 4, // AND ax, d16
0x26 => nop[seg=es, prefix] / 2,
0x2E => nop[seg=cs, prefix] / 2,
0x30 _ => xor[flags, modrm8, r8] / "3/24+", // XOR r/m8, r8
0x31 _ => xor[flags, modrm16, r16] / "3/24+", // XOR r/m16, r16
0x32 _ => xor[flags, r8, modrm8] / "3/13+", // XOR r8, r/m8
0x33 _ => xor[flags, r16, modrm16] / "3/13+", // XOR r16, r/m16
0x34 => xor[flags, reglo=a, d8] / 4, // XOR al, d8
0x35 => xor[flags, reg=a, d16] / 4, // XOR ax, d16
0x36 => nop[seg=ss, prefix] / 2,
0x38 _ => cmp[flags, modrm8, r8] / "3/24+",
0x39 _ => cmp[flags, modrm16, r16] / "3/24+",
@@ -470,9 +488,20 @@ impl i8088 {
0x7D => jge[flags, reg=ip, rel8] / "16/4", // JNL/JGE rel8
0x7E => jle[flags, reg=ip, rel8] / "16/4", // JLE/JNG rel8
0x7F => jg[flags, reg=ip, rel8] / "16/4", // JNLE/JG rel8
0x80: { 0x38 => cmp[flags, modrm8, d8] / "4/23+", },
0x81: { 0x38 => cmp[flags, modrm16, d16] / "4/23+", },
0x83: { 0x38 => cmp[flags, modrm16, d8_as_d16] / "4/23+", },
0x80: { 0x08 => or[flags, modrm8, d8] / "4/23+", // OR r/m8, d8
0x20 => and[flags, modrm8, d8] / "4/23+", // AND r/m8, d8
0x30 => xor[flags, modrm8, d8] / "4/23+", // XOR r/m8, d8
0x38 => cmp[flags, modrm8, d8] / "4/23+", }, // CMP r/m8, d8
0x81: { 0x08 => or[flags, modrm16, d16] / "4/23+", // OR r/m16, d16
0x20 => and[flags, modrm16, d16] / "4/23+", // AND r/m16, d16
0x30 => xor[flags, modrm16, d16] / "4/23+", // XOR r/m16, d16
0x38 => cmp[flags, modrm16, d16] / "4/23+", }, // CMP r/m16, d16
0x83: { 0x08 => or[flags, modrm16, d8_as_d16] / "4/23+", // OR r/m16, d8
0x20 => and[flags, modrm16, d8_as_d16] / "4/23+", // AND r/m16, d8
0x30 => xor[flags, modrm16, d8_as_d16] / "4/23+", // XOR r/m16, d8
0x38 => cmp[flags, modrm16, d8_as_d16] / "4/23+", }, // CMP r/m16, d8
0x84 _ => test[flags, modrm8, r8] / "3/13+", // TEST r/m8, r8
0x85 _ => test[flags, modrm16, r16] / "3/13+", // TEST r/m16, r16
0x86 _ => xchg[r8, modrm8] / "4/25+", // XCHG r8, r/m8
0x87 _ => xchg[r16, modrm16] / "4/25+", // XCHG r16, r/m16
0x88 _ => mov[modrm8, r8] / "2/13+", // MOV r/m8, r8
@@ -509,6 +538,8 @@ impl i8088 {
0xA5 => movs[form=word0, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "26/9+25n",
0xA6 => cmps[form=byte0, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "22/9+22n",
0xA7 => cmps[form=word0, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "30/9+30n",
0xA8 => test[flags, reglo=a, d8] / 4, // TEST al, d8
0xA9 => test[flags, reg=a, d16] / 4, // TEST ax, d16
0xAA => stos[flags, bus, rep, reg=c, reg=es, reg=di, reglo=a] / "11/9+10n",
0xAB => stos[flags, bus, rep, reg=c, reg=es, reg=di, reg=a] / "15/9+14n",
0xAC => lods[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reglo=a] / "12/9+13n",
@@ -573,9 +604,11 @@ 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
0xF6: { 0x00 => test[flags, modrm8, d8] / "5/11+", // TEST r/m8, d8
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
0xF7: { 0x00 => test[flags, modrm16, d16] / "5/11+", // TEST r/m16, d16
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)

View File

@@ -66,6 +66,12 @@ pub fn peek(addr: impl Address + RValue<u8>) {
println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read());
}
pub fn and<T: Operand>(flags: &mut Flags, mut dst: impl LValue<T>, src: impl RValue<T>) {
let res = dst.read() & src.read();
dst.write(res);
flags.update(FlagOp::LOGIC, res.into(), T::HI_BIT_MASK.into());
}
pub fn call(mut ip: Reg, bus: &mut Bus, ss: u16, sp: Reg, rel16: u16) {
let target = ip.read().wrapping_add(rel16);
push(bus, ss, sp, ip.read());
@@ -332,6 +338,13 @@ pub fn neg<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
T::HI_BIT_MASK.into());
}
pub fn or<T: Operand>(flags: &mut Flags, mut dst: impl LValue<T>, src: impl RValue<T>) {
let res = dst.read() | src.read();
dst.write(res);
flags.update(FlagOp::LOGIC, 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());
@@ -657,8 +670,19 @@ where RVal: RValue<T>,
});
}
pub fn test<T: Operand>(flags: &mut Flags, dst: impl RValue<T>, src: impl RValue<T>) {
let res = dst.read() & src.read();
flags.update(FlagOp::LOGIC, res.into(), T::HI_BIT_MASK.into());
}
pub fn xchg<T, Dst: LValue<T>, Src: LValue<T>>(mut dst: Dst, mut src: Src) {
let tmp = src.read();
src.write(dst.read());
dst.write(tmp);
}
pub fn xor<T: Operand>(flags: &mut Flags, mut dst: impl LValue<T>, src: impl RValue<T>) {
let res = dst.read() ^ src.read();
dst.write(res);
flags.update(FlagOp::LOGIC, res.into(), T::HI_BIT_MASK.into());
}