emu: make string ops generic over operand size
After many attempts, it turns out this is as easy as remembering that where clauses can bound non-parameter types
This commit is contained in:
@@ -190,6 +190,14 @@ macro_rules! step {
|
|||||||
step!(@arg $cookie, &mut $cpu.flags)
|
step!(@arg $cookie, &mut $cpu.flags)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(@form=nullary_byte $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
|
step!(@form $cookie, form=(u8));
|
||||||
|
};
|
||||||
|
|
||||||
|
(@form=nullary_word $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
|
step!(@form $cookie, form=(u16));
|
||||||
|
};
|
||||||
|
|
||||||
(@form=ternary_byte $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@form=ternary_byte $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
step!(@form $cookie, form=(u8, _, _, _));
|
step!(@form $cookie, form=(u8, _, _, _));
|
||||||
};
|
};
|
||||||
@@ -496,16 +504,16 @@ impl i8088 {
|
|||||||
0xA1 => mov[reg=a, addr] / 14,
|
0xA1 => mov[reg=a, addr] / 14,
|
||||||
0xA2 => mov[addr, reglo=a] / 14,
|
0xA2 => mov[addr, reglo=a] / 14,
|
||||||
0xA3 => mov[addr, reg=a] / 14,
|
0xA3 => mov[addr, reg=a] / 14,
|
||||||
0xA4 => movsb[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "18/9+17n",
|
0xA4 => movs[form=nullary_byte, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "18/9+17n",
|
||||||
0xA5 => movsw[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "26/9+25n",
|
0xA5 => movs[form=nullary_word, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "26/9+25n",
|
||||||
0xA6 => cmpsb[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "22/9+22n",
|
0xA6 => cmps[form=nullary_byte, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "22/9+22n",
|
||||||
0xA7 => cmpsw[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "30/9+30n",
|
0xA7 => cmps[form=nullary_word, flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=es, reg=di] / "30/9+30n",
|
||||||
0xAA => stosb[flags, bus, rep, reg=c, reg=es, reg=di, reglo=a] / "11/9+10n",
|
0xAA => stos[flags, bus, rep, reg=c, reg=es, reg=di, reglo=a] / "11/9+10n",
|
||||||
0xAB => stosw[flags, bus, rep, reg=c, reg=es, reg=di, reg=a] / "15/9+14n",
|
0xAB => stos[flags, bus, rep, reg=c, reg=es, reg=di, reg=a] / "15/9+14n",
|
||||||
0xAC => lodsb[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reglo=a] / "12/9+13n",
|
0xAC => lods[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reglo=a] / "12/9+13n",
|
||||||
0xAD => lodsw[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=a] / "16/9+17n",
|
0xAD => lods[flags, bus, rep, reg=c, seg=ds, seg, reg=si, reg=a] / "16/9+17n",
|
||||||
0xAE => scasb[flags, bus, rep, reg=c, reg=es, reg=di, reglo=a] / "15/9+15n",
|
0xAE => scas[flags, bus, rep, reg=c, reg=es, reg=di, reglo=a] / "15/9+15n",
|
||||||
0xAF => scasw[flags, bus, rep, reg=c, reg=es, reg=di, reg=a] / "19/9+19n",
|
0xAF => scas[flags, bus, rep, reg=c, reg=es, reg=di, reg=a] / "19/9+19n",
|
||||||
0xB0 => mov[reglo=a, d8] / 4,
|
0xB0 => mov[reglo=a, d8] / 4,
|
||||||
0xB1 => mov[reglo=c, d8] / 4,
|
0xB1 => mov[reglo=c, d8] / 4,
|
||||||
0xB2 => mov[reglo=d, d8] / 4,
|
0xB2 => mov[reglo=d, d8] / 4,
|
||||||
|
|||||||
@@ -80,33 +80,20 @@ pub fn cmp<T: Operand>(flags: &mut Flags, dst: impl RValue<T>, src: impl RValue<
|
|||||||
flags.update(FlagOp::SUB, dst.into(), src.into(), res.into(), T::WIDTH);
|
flags.update(FlagOp::SUB, dst.into(), src.into(), res.into(), T::WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmpsb(flags: &mut Flags,
|
pub fn cmps<T>(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
mut cx: Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
mut si: Reg,
|
mut si: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg) {
|
mut di: Reg)
|
||||||
string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf()), {
|
where T: Operand + RValue<T>,
|
||||||
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
for<'a> FarPtr<'a>: RValue<T>
|
||||||
let dst = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
{
|
||||||
|
string_op!((T, flags, rep, cx, si=si, di=di, zf=flags.zf()), {
|
||||||
cmp(flags, dst, src);
|
let src = <FarPtr as RValue<T>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
||||||
});
|
let dst = <FarPtr as RValue<T>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cmpsw(flags: &mut Flags,
|
|
||||||
bus: &mut Bus,
|
|
||||||
rep: RepPrefix,
|
|
||||||
mut cx: Reg,
|
|
||||||
seg: u16,
|
|
||||||
mut si: Reg,
|
|
||||||
es: Reg,
|
|
||||||
mut di: Reg) {
|
|
||||||
string_op!((u16, flags, rep, cx, si=si, di=di, zf=flags.zf()), {
|
|
||||||
let src = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
|
||||||
let dst = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
|
||||||
|
|
||||||
cmp(flags, dst, src);
|
cmp(flags, dst, src);
|
||||||
});
|
});
|
||||||
@@ -244,26 +231,16 @@ pub fn lea(mut dst: Reg, addr: FarPtr) {
|
|||||||
dst.write(addr.offset)
|
dst.write(addr.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lodsb(flags: &Flags,
|
pub fn lods<T>(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
mut cx: Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
mut si: Reg,
|
mut si: Reg,
|
||||||
mut al: impl LValue<u8>) {
|
mut ax: impl LValue<T>)
|
||||||
string_op!((u8, flags, rep, cx, si=si), {
|
where for<'a> FarPtr<'a>: RValue<T>
|
||||||
al.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read());
|
{
|
||||||
});
|
string_op!((T, flags, rep, cx, si=si), {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lodsw(flags: &Flags,
|
|
||||||
bus: &mut Bus,
|
|
||||||
rep: RepPrefix,
|
|
||||||
mut cx: Reg,
|
|
||||||
seg: u16,
|
|
||||||
mut si: Reg,
|
|
||||||
mut ax: impl LValue<u16>) {
|
|
||||||
string_op!((u16, flags, rep, cx, si=si), {
|
|
||||||
ax.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read());
|
ax.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -272,33 +249,20 @@ pub fn mov<T>(mut dst: impl LValue<T>, src: impl RValue<T>) {
|
|||||||
dst.write(src.read());
|
dst.write(src.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn movsb(flags: &Flags,
|
pub fn movs<T>(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
mut cx: Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
mut si: Reg,
|
mut si: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg) {
|
mut di: Reg)
|
||||||
string_op!((u8, flags, rep, cx, si=si, di=di), {
|
where for<'a> FarPtr<'a>: RValue<T> + LValue<T>
|
||||||
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
{
|
||||||
|
string_op!((T, flags, rep, cx, si=si, di=di), {
|
||||||
|
let src = <FarPtr as RValue<T>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
||||||
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
||||||
<FarPtr as LValue<u8>>::write(&mut dst, src);
|
<FarPtr as LValue<T>>::write(&mut dst, src);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn movsw(flags: &Flags,
|
|
||||||
bus: &mut Bus,
|
|
||||||
rep: RepPrefix,
|
|
||||||
mut cx: Reg,
|
|
||||||
seg: u16,
|
|
||||||
mut si: Reg,
|
|
||||||
es: Reg,
|
|
||||||
mut di: Reg) {
|
|
||||||
string_op!((u16, flags, rep, cx, si=si, di=di), {
|
|
||||||
let src = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
|
||||||
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
|
||||||
<FarPtr as LValue<u16>>::write(&mut dst, src);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,29 +371,19 @@ where T: Operand,
|
|||||||
flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH);
|
flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scasb(flags: &mut Flags,
|
pub fn scas<T, RVal>(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
mut cx: Reg,
|
mut cx: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg,
|
mut di: Reg,
|
||||||
needle: impl RValue<u8>) {
|
needle: RVal)
|
||||||
|
where RVal: RValue<T>,
|
||||||
|
T: Operand + RValue<T>,
|
||||||
|
for<'a> FarPtr<'a>: RValue<T>
|
||||||
|
{
|
||||||
let needle = needle.read();
|
let needle = needle.read();
|
||||||
string_op!((u8, flags, rep, cx, di=di, zf=flags.zf()), {
|
string_op!((T, flags, rep, cx, di=di, zf=flags.zf()), {
|
||||||
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
|
||||||
cmp(flags, elem, needle);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scasw(flags: &mut Flags,
|
|
||||||
bus: &mut Bus,
|
|
||||||
rep: RepPrefix,
|
|
||||||
mut cx: Reg,
|
|
||||||
es: Reg,
|
|
||||||
mut di: Reg,
|
|
||||||
needle: impl RValue<u16>) {
|
|
||||||
let needle = needle.read();
|
|
||||||
string_op!((u16, flags, rep, cx, di=di, zf=flags.zf()), {
|
|
||||||
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
||||||
cmp(flags, elem, needle);
|
cmp(flags, elem, needle);
|
||||||
});
|
});
|
||||||
@@ -481,27 +435,17 @@ where T: Operand,
|
|||||||
flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH);
|
flags.update(FlagOp::SHIFT, dst_before.into(), src_before.into(), res.into(), T::WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stosb(flags: &Flags,
|
pub fn stos<T, RVal>(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
mut cx: Reg,
|
mut cx: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg,
|
mut di: Reg,
|
||||||
val: impl RValue<u8>) {
|
val: RVal)
|
||||||
string_op!((u8, flags, rep, cx, di=di), {
|
where RVal: RValue<T>,
|
||||||
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
for<'a> FarPtr<'a>: LValue<T>
|
||||||
dst.write(val.read());
|
{
|
||||||
});
|
string_op!((T, flags, rep, cx, di=di), {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stosw(flags: &Flags,
|
|
||||||
bus: &mut Bus,
|
|
||||||
rep: RepPrefix,
|
|
||||||
mut cx: Reg,
|
|
||||||
es: Reg,
|
|
||||||
mut di: Reg,
|
|
||||||
val: impl RValue<u16>) {
|
|
||||||
string_op!((u16, flags, rep, cx, di=di), {
|
|
||||||
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
||||||
dst.write(val.read());
|
dst.write(val.read());
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user