diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 3f1b8b4..43d0ff6 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -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::); + }; + + (@width=word $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { + step!(@arg $cookie, PhantomData::); + }; + // 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, diff --git a/src/emu/operands.rs b/src/emu/operands.rs index d1751bf..5659f81 100644 --- a/src/emu/operands.rs +++ b/src/emu/operands.rs @@ -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 + std::ops::BitXor { @@ -28,7 +29,7 @@ impl Operand for u16 { } } -pub trait LValue { +pub trait LValue: RValue { fn write(&mut self, val: T); } diff --git a/src/emu/operations.rs b/src/emu/operations.rs index 9dba65a..055a41a 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -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(_width: PhantomData, // Needed to disambiguate when dst is a FarPtr + flags: &mut Flags, + dst: &mut impl LValue) { + 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(_width: PhantomData, // Needed to disambiguate when dst is a FarPtr + flags: &mut Flags, + dst: &mut impl LValue) { + 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),