diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 5ffeffb..e5b6410 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use super::byteorder::{ByteOrder, LittleEndian}; -use emu::operands::{FarPtr, Reg, RegHi, RegLo}; +use emu::operands::{FarPtr, Reg, RegHalf, RegHi, RegLo}; use emu::operations as ops; use emu::flags::Flags; use emu::pc::Bus; @@ -270,27 +270,19 @@ macro_rules! step { } }; (@r8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $($modrm_rest:tt),*)) => { { - let modrm_shift = $modrm_val >> 3; // TODO: Should these also be passed into the macro like the modrm specs? - if modrm_shift & 0x4 == 0 { - let reg = match modrm_shift & 0x3 { - 0 => RegLo { reg: &$cpu.a }, - 1 => RegLo { reg: &$cpu.c }, - 2 => RegLo { reg: &$cpu.d }, - 3 => RegLo { reg: &$cpu.b }, - _ => unreachable!() - }; - step!(@arg $cookie, reg) - } else { - let reg = match modrm_shift & 0x3 { - 0 => RegHi { reg: &$cpu.a }, - 1 => RegHi { reg: &$cpu.c }, - 2 => RegHi { reg: &$cpu.d }, - 3 => RegHi { reg: &$cpu.b }, - _ => unreachable!() - }; - step!(@arg $cookie, reg) - } + let reg = match $modrm_val >> 3 & 0x7 { + 0 => RegHalf::Lo(RegLo { reg: &$cpu.a }), + 1 => RegHalf::Lo(RegLo { reg: &$cpu.c }), + 2 => RegHalf::Lo(RegLo { reg: &$cpu.d }), + 3 => RegHalf::Lo(RegLo { reg: &$cpu.b }), + 4 => RegHalf::Hi(RegHi { reg: &$cpu.a }), + 5 => RegHalf::Hi(RegHi { reg: &$cpu.c }), + 6 => RegHalf::Hi(RegHi { reg: &$cpu.d }), + 7 => RegHalf::Hi(RegHi { reg: &$cpu.b }), + _ => unreachable!() + }; + step!(@arg $cookie, reg) } }; (@reg=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { diff --git a/src/emu/operands.rs b/src/emu/operands.rs index 1dc8bd6..cedb356 100644 --- a/src/emu/operands.rs +++ b/src/emu/operands.rs @@ -177,6 +177,29 @@ impl RValue for RegLo<'_> { } } +pub enum RegHalf<'a> { + Hi(RegHi<'a>), + Lo(RegLo<'a>) +} + +impl LValue for RegHalf<'_> { + fn write(&mut self, val: u8) { + match self { + RegHalf::Hi(hi) => hi.write(val), + RegHalf::Lo(lo) => lo.write(val) + } + } +} + +impl RValue for RegHalf<'_> { + fn read(&self) -> u8 { + match self { + RegHalf::Hi(hi) => hi.read(), + RegHalf::Lo(lo) => lo.read() + } + } +} + pub enum DynLValue<'a> { Reg(Reg<'a>), FarPtr { segment: u16, offset: u16 },