emu: INC/DEC opcodes. width={byte,word} argtypes for disambig

Also made all LValues also RValues for brevity (so INC/DEC don't have
to bound their destination arguments by both, but this is not required
if it causes problems for some reason down the road).
This commit is contained in:
2021-03-19 00:07:49 -07:00
parent c8d6a3312a
commit ff7e8a7fb9
3 changed files with 50 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
use std::cell::Cell;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use super::byteorder::{ByteOrder, LittleEndian};
@@ -297,6 +298,14 @@ macro_rules! step {
step!(@arg $cookie, $segment.unwrap())
} };
(@width=byte $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@arg $cookie, PhantomData::<u8>);
};
(@width=word $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@arg $cookie, PhantomData::<u16>);
};
// Group Decoder
(@group $cpu:expr, $bus:expr, $prefix:tt,
($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt),
@@ -378,6 +387,22 @@ impl i8088 {
0x3C => cmp[flags, reglo=a, d8] / "3/24+",
0x3D => cmp[flags, reg=a, d16] / "3/24+",
0x3E => nop[seg=ds, prefix] / 2,
0x40 => inc[width=word, flags, reg=a] / 3,
0x41 => inc[width=word, flags, reg=c] / 3,
0x42 => inc[width=word, flags, reg=d] / 3,
0x43 => inc[width=word, flags, reg=b] / 3,
0x44 => inc[width=word, flags, reg=sp] / 3,
0x45 => inc[width=word, flags, reg=bp] / 3,
0x46 => inc[width=word, flags, reg=si] / 3,
0x47 => inc[width=word, flags, reg=di] / 3,
0x48 => dec[width=word, flags, reg=a] / 3,
0x49 => dec[width=word, flags, reg=c] / 3,
0x4A => dec[width=word, flags, reg=d] / 3,
0x4B => dec[width=word, flags, reg=b] / 3,
0x4C => dec[width=word, flags, reg=sp] / 3,
0x4D => dec[width=word, flags, reg=bp] / 3,
0x4E => dec[width=word, flags, reg=si] / 3,
0x4F => dec[width=word, flags, reg=di] / 3,
0x50 => push[bus, regval=ss, reg=sp, regval=a] / 15,
0x51 => push[bus, regval=ss, reg=sp, regval=c] / 15,
0x52 => push[bus, regval=ss, reg=sp, regval=d] / 15,
@@ -469,6 +494,10 @@ impl i8088 {
0xE8 => call[reg=ip, bus, regval=ss, reg=sp, rel16] / 23,
0xF2 => nop[rep=NotEqual, prefix] / 0, // REPNE/REPNZ
0xF3 => nop[rep=Equal, prefix] / 0, // REP/REPE/REPZ
0xFE: { 00 => inc[width=byte, flags, modrm8] / "3/23+", // INC r/m8
08 => dec[width=byte, flags, modrm8] / "3/23+", }, // DEC r/m8
0xFF: { 00 => inc[width=word, flags, modrm16] / "3/23+", // INC r/m16
08 => dec[width=word, flags, modrm16] / "3/23+", }, // DEC r/m16
},
modrm: {
0x00 => seg=ds, displace0=(b+si) / M 7,

View File

@@ -7,6 +7,7 @@ use emu::pc::Bus;
pub trait Operand: Copy +
nt::Num +
nt::ops::overflowing::OverflowingAdd +
nt::ops::overflowing::OverflowingSub +
std::ops::BitAnd<Output = Self> +
std::ops::BitXor<Output = Self> {
@@ -28,7 +29,7 @@ impl Operand for u16 {
}
}
pub trait LValue<T> {
pub trait LValue<T>: RValue<T> {
fn write(&mut self, val: T);
}

View File

@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::marker::PhantomData;
use emu::dos;
use emu::i8088::{Flags, RepPrefix, i8088};
@@ -69,8 +70,8 @@ macro_rules! update_flags {
// Entry Point
($flags:expr, $t:ty, $eval:expr $(, $flagnames:ident)* ) => { {
let (dst, carry) = $eval;
update_flags!(@recur $flags, $t, dst, carry $(, $flagnames)*);
let (dst, _carry) = $eval; // _carry used iff CF flag being updated
update_flags!(@recur $flags, $t, dst, _carry $(, $flagnames)*);
dst
} }
}
@@ -135,6 +136,22 @@ pub fn cmpsw(flags: &mut Flags,
});
}
pub fn dec<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
flags: &mut Flags,
dst: &mut impl LValue<T>) {
let res = update_flags!(flags, T, dst.read().overflowing_sub(&T::one()), sf, zf, af, pf);
flags.of = res == T::HI_BIT_MASK - T::one();
dst.write(res);
}
pub fn inc<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
flags: &mut Flags,
dst: &mut impl LValue<T>) {
let res = update_flags!(flags, T, dst.read().overflowing_add(&T::one()), sf, zf, af, pf);
flags.of = res == T::HI_BIT_MASK;
dst.write(res);
}
pub fn int(cpu: &mut i8088, bus: &mut Bus, num: &u8) {
match num {
0x21 => dos::interrupt(cpu, bus),