emu: AND/OR/XOR/TEST 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::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 },
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user