diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 43d0ff6..642f5e2 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -97,7 +97,7 @@ macro_rules! step { ($segment:ident, $repeat:ident, $prefix_loop:lifetime), $modrm:tt) => { { let a16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, &mut FarPtr { bus: $bus, segment: $segment.unwrap(), offset: a16 } ) + step!(@arg $cookie, FarPtr { bus: $bus, segment: $segment.unwrap(), offset: a16 } ) } }; (@bus $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { @@ -110,47 +110,43 @@ macro_rules! step { (@d8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { { let d8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, &d8) + step!(@arg $cookie, d8) } }; (@d8_as_d16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { { let d8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, &(d8 as u16)) + step!(@arg $cookie, d8 as u16) } }; (@d16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { { let d16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, &d16) + step!(@arg $cookie, d16) } }; (@displace0=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $repeat:ident, $prefix_loop:lifetime), $modrm:tt) => { - step!(@arg $cookie, &mut FarPtr { bus: $bus, - segment: $segment.unwrap(), - offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? }) + step!(@arg $cookie, FarPtr { bus: $bus, + segment: $segment.unwrap(), + offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? }) }; (@displace8=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $repeat:ident, $prefix_loop:lifetime), $modrm:tt) => { { let rel8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus) as i8 as u16; - step!(@arg $cookie, &mut FarPtr { bus: $bus, - segment: $segment.unwrap(), - offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?) - .wrapping_add(rel8) - }) + step!(@arg $cookie, FarPtr { bus: $bus, + segment: $segment.unwrap(), + offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?).wrapping_add(rel8) }) } }; (@displace16=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $repeat:ident, $prefix_loop:lifetime), $modrm:tt) => { { let rel16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, &mut FarPtr { bus: $bus, - segment: $segment.unwrap(), - offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?) - .wrapping_add(rel16) - }) + step!(@arg $cookie, FarPtr { bus: $bus, + segment: $segment.unwrap(), + offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?).wrapping_add(rel16) }) } }; (@flags $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { @@ -211,14 +207,14 @@ macro_rules! step { (@r16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt)) => { // TODO: Should these also be passed into the macro like the modrm specs? match $modrm_val >> 3 & 0x7 { - 0 => step!(@arg $cookie, &mut Reg { reg: &$cpu.a } ), - 1 => step!(@arg $cookie, &mut Reg { reg: &$cpu.c } ), - 2 => step!(@arg $cookie, &mut Reg { reg: &$cpu.d } ), - 3 => step!(@arg $cookie, &mut Reg { reg: &$cpu.b } ), - 4 => step!(@arg $cookie, &mut Reg { reg: &$cpu.sp } ), - 5 => step!(@arg $cookie, &mut Reg { reg: &$cpu.bp } ), - 6 => step!(@arg $cookie, &mut Reg { reg: &$cpu.si } ), - 7 => step!(@arg $cookie, &mut Reg { reg: &$cpu.di } ), + 0 => step!(@arg $cookie, Reg { reg: &$cpu.a } ), + 1 => step!(@arg $cookie, Reg { reg: &$cpu.c } ), + 2 => step!(@arg $cookie, Reg { reg: &$cpu.d } ), + 3 => step!(@arg $cookie, Reg { reg: &$cpu.b } ), + 4 => step!(@arg $cookie, Reg { reg: &$cpu.sp } ), + 5 => step!(@arg $cookie, Reg { reg: &$cpu.bp } ), + 6 => step!(@arg $cookie, Reg { reg: &$cpu.si } ), + 7 => step!(@arg $cookie, Reg { reg: &$cpu.di } ), _ => unreachable!() }; }; @@ -226,28 +222,28 @@ macro_rules! step { (@r8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt)) => { // TODO: Should these also be passed into the macro like the modrm specs? match $modrm_val >> 3 & 0x7 { - 0 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.a } ), - 1 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.c } ), - 2 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.d } ), - 3 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.b } ), - 4 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.a } ), - 5 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.c } ), - 6 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.d } ), - 7 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.b } ), + 0 => step!(@arg $cookie, RegHi { reg: &$cpu.a } ), + 1 => step!(@arg $cookie, RegHi { reg: &$cpu.c } ), + 2 => step!(@arg $cookie, RegHi { reg: &$cpu.d } ), + 3 => step!(@arg $cookie, RegHi { reg: &$cpu.b } ), + 4 => step!(@arg $cookie, RegLo { reg: &$cpu.a } ), + 5 => step!(@arg $cookie, RegLo { reg: &$cpu.c } ), + 6 => step!(@arg $cookie, RegLo { reg: &$cpu.d } ), + 7 => step!(@arg $cookie, RegLo { reg: &$cpu.b } ), _ => unreachable!() }; }; (@reg=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@arg $cookie, &mut Reg { reg: &$cpu.$reg }); + step!(@arg $cookie, Reg { reg: &$cpu.$reg }); }; (@reghi=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@arg $cookie, &mut RegHi { reg: &$cpu.$reg }); + step!(@arg $cookie, RegHi { reg: &$cpu.$reg }); }; (@reglo=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@arg $cookie, &mut RegLo { reg: &$cpu.$reg }); + step!(@arg $cookie, RegLo { reg: &$cpu.$reg }); }; (@regval=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { diff --git a/src/emu/operations.rs b/src/emu/operations.rs index c3265c5..33f1c2a 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -76,7 +76,7 @@ macro_rules! update_flags { } } } -pub fn assert(loc: &impl RValue, val: &impl RValue) { +pub fn assert(loc: impl RValue, val: impl RValue) { assert_eq!(loc.read(), val.read(), "ASSERT instruction failed: {:#2X?} != {:#2X?}", loc.read(), val.read()); println!("ASSERT pass: {:#2X?} == {:#2X?}", loc.read(), val.read()); @@ -86,17 +86,17 @@ pub fn show(cpu: &mut i8088) { println!("{:#X?}", cpu); } -pub fn peek(addr: &(impl Address + RValue)) { +pub fn peek(addr: impl Address + RValue) { println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read()); } -pub fn call(ip: &mut Reg, bus: &mut Bus, ss: u16, sp: &mut Reg, rel16: u16) { +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()); ip.write(target); } -pub fn cmp(flags: &mut Flags, dst: &impl RValue, src: &impl RValue) { +pub fn cmp(flags: &mut Flags, dst: impl RValue, src: impl RValue) { let (dst, src) = (dst.read(), src.read()); let after = update_flags!(flags, T, dst.overflowing_sub(&src), af, cf, pf, sf, zf); flags.of = T::zero() != T::HI_BIT_MASK & // In the (maybe) sign bit... @@ -107,38 +107,38 @@ pub fn cmp(flags: &mut Flags, dst: &impl RValue, src: &impl RValu pub fn cmpsb(flags: &mut Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - es: &mut Reg, - di: &mut Reg) { + mut si: Reg, + es: Reg, + mut di: Reg) { string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf), { let src = >::read(&FarPtr { bus: bus, segment: seg, offset: si.read() }); let dst = >::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() }); - cmp(flags, &dst, &src); + cmp(flags, dst, src); }); } pub fn cmpsw(flags: &mut Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - es: &mut Reg, - di: &mut Reg) { + mut si: Reg, + es: Reg, + mut di: Reg) { string_op!((u16, flags, rep, cx, si=si, di=di, zf=flags.zf), { let src = >::read(&FarPtr { bus: bus, segment: seg, offset: si.read() }); let dst = >::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() }); - cmp(flags, &dst, &src); + cmp(flags, dst, src); }); } pub fn dec(_width: PhantomData, // Needed to disambiguate when dst is a FarPtr flags: &mut Flags, - dst: &mut impl LValue) { + mut dst: 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); @@ -146,124 +146,124 @@ pub fn dec(_width: PhantomData, // Needed to disambiguate when d pub fn inc(_width: PhantomData, // Needed to disambiguate when dst is a FarPtr flags: &mut Flags, - dst: &mut impl LValue) { + mut dst: 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) { +pub fn int(cpu: &mut i8088, bus: &mut Bus, num: u8) { match num { 0x21 => dos::interrupt(cpu, bus), _ => unimplemented!("interrupt: {:02X}\ncpu: {:#X?}", num, cpu) } } -pub fn ja(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn ja(flags: &Flags, mut ip: Reg, rel8: u16) { if !flags.cf && !flags.zf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jae(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jae(flags: &Flags, mut ip: Reg, rel8: u16) { if !flags.cf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jb(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jb(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.cf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jbe(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jbe(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.cf || flags.zf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jcxz(ip: &mut Reg, cx: &mut Reg, rel8: u16) { +pub fn jcxz(mut ip: Reg, cx: Reg, rel8: u16) { if cx.read() == 0 { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jg(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jg(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.zf && flags.sf == flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jge(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jge(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.sf == flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jl(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jl(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.sf != flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jle(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jle(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.zf || flags.sf != flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jmp(ip: &mut Reg, rel: u16) { +pub fn jmp(mut ip: Reg, rel: u16) { ip.write(ip.read().wrapping_add(rel)); } -pub fn jno(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jno(flags: &Flags, mut ip: Reg, rel8: u16) { if !flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jns(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jns(flags: &Flags, mut ip: Reg, rel8: u16) { if !flags.sf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jnz(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jnz(flags: &Flags, mut ip: Reg, rel8: u16) { if !flags.zf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jo(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jo(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.of { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn js(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn js(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.sf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn jz(flags: &Flags, ip: &mut Reg, rel8: u16) { +pub fn jz(flags: &Flags, mut ip: Reg, rel8: u16) { if flags.zf { ip.write(ip.read().wrapping_add(rel8)); } } -pub fn lea(dst: &mut Reg, addr: &FarPtr) { +pub fn lea(mut dst: Reg, addr: FarPtr) { dst.write(addr.offset) } pub fn lodsb(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - al: &mut impl LValue) { + mut si: Reg, + mut al: impl LValue) { string_op!((u8, flags, rep, cx, si=si), { al.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read()); }); @@ -272,27 +272,27 @@ pub fn lodsb(flags: &Flags, pub fn lodsw(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - ax: &mut impl LValue) { + mut si: Reg, + mut ax: impl LValue) { string_op!((u16, flags, rep, cx, si=si), { ax.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read()); }); } -pub fn mov(dst: &mut impl LValue, src: &impl RValue) { +pub fn mov(mut dst: impl LValue, src: impl RValue) { dst.write(src.read()); } pub fn movsb(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - es: &Reg, - di: &mut Reg) { + mut si: Reg, + es: Reg, + mut di: Reg) { string_op!((u8, flags, rep, cx, si=si, di=di), { let src = >::read(&FarPtr { bus: bus, segment: seg, offset: si.read() }); let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() }; @@ -303,11 +303,11 @@ pub fn movsb(flags: &Flags, pub fn movsw(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, + mut cx: Reg, seg: u16, - si: &mut Reg, - es: &Reg, - di: &mut Reg) { + mut si: Reg, + es: Reg, + mut di: Reg) { string_op!((u16, flags, rep, cx, si=si, di=di), { let src = >::read(&FarPtr { bus: bus, segment: seg, offset: si.read() }); let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() }; @@ -317,13 +317,13 @@ pub fn movsw(flags: &Flags, pub fn nop() {} -pub fn pop(bus: &mut Bus, ss: u16, sp: &mut Reg, dst: &mut Reg) { +pub fn pop(bus: &mut Bus, ss: u16, mut sp: Reg, mut dst: Reg) { let ptr = FarPtr { bus: bus, segment: ss, offset: sp.read() }; dst.write(ptr.read()); sp.write(sp.read() + 2); } -pub fn push(bus: &mut Bus, ss: u16, sp: &mut Reg, val: u16) { +pub fn push(bus: &mut Bus, ss: u16, mut sp: Reg, val: u16) { // XXX: Not checking for stack faults or anything sp.write(sp.read() - 2); let mut ptr = FarPtr { bus: bus, segment: ss, offset: sp.read() }; @@ -333,36 +333,38 @@ pub fn push(bus: &mut Bus, ss: u16, sp: &mut Reg, val: u16) { pub fn scasb(flags: &mut Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, - es: &Reg, - di: &mut Reg, - needle: &impl RValue) { + mut cx: Reg, + es: Reg, + mut di: Reg, + needle: impl RValue) { + let needle = needle.read(); string_op!((u8, flags, rep, cx, di=di, zf=flags.zf), { let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() }; - cmp(flags, &elem, needle); + cmp(flags, elem, needle); }); } pub fn scasw(flags: &mut Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, - es: &Reg, - di: &mut Reg, - needle: &impl RValue) { + mut cx: Reg, + es: Reg, + mut di: Reg, + needle: impl RValue) { + 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() }; - cmp(flags, &elem, needle); + cmp(flags, elem, needle); }); } pub fn stosb(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, - es: &Reg, - di: &mut Reg, - val: &impl RValue) { + mut cx: Reg, + es: Reg, + mut di: Reg, + val: impl RValue) { string_op!((u8, flags, rep, cx, di=di), { let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() }; dst.write(val.read()); @@ -372,10 +374,10 @@ pub fn stosb(flags: &Flags, pub fn stosw(flags: &Flags, bus: &mut Bus, rep: RepPrefix, - cx: &mut Reg, - es: &Reg, - di: &mut Reg, - val: &impl RValue) { + mut cx: Reg, + es: Reg, + mut di: Reg, + val: impl RValue) { string_op!((u16, flags, rep, cx, di=di), { let mut dst = FarPtr { bus: bus, segment: es.read(), offset: di.read() }; dst.write(val.read());