emu: Pass [LR]Values by value instead of by &mut
I think this made sense originally because registers were being passed as borrows directly out of the cpu struct. Now they have wrappers around Cell refs, and those wrappers can be passed directly.
This commit is contained in:
@@ -97,7 +97,7 @@ macro_rules! step {
|
|||||||
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
||||||
$modrm:tt) => { {
|
$modrm:tt) => { {
|
||||||
let a16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
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) => {
|
(@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) => { {
|
(@d8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { {
|
||||||
let d8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
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) => { {
|
(@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);
|
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) => { {
|
(@d16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { {
|
||||||
let d16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
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,
|
(@displace0=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr,
|
||||||
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
||||||
$modrm:tt) => {
|
$modrm:tt) => {
|
||||||
step!(@arg $cookie, &mut FarPtr { bus: $bus,
|
step!(@arg $cookie, FarPtr { bus: $bus,
|
||||||
segment: $segment.unwrap(),
|
segment: $segment.unwrap(),
|
||||||
offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? })
|
offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? })
|
||||||
};
|
};
|
||||||
|
|
||||||
(@displace8=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr,
|
(@displace8=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr,
|
||||||
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
||||||
$modrm:tt) => { {
|
$modrm:tt) => { {
|
||||||
let rel8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus) as i8 as u16;
|
let rel8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus) as i8 as u16;
|
||||||
step!(@arg $cookie, &mut FarPtr { bus: $bus,
|
step!(@arg $cookie, FarPtr { bus: $bus,
|
||||||
segment: $segment.unwrap(),
|
segment: $segment.unwrap(),
|
||||||
offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?)
|
offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?).wrapping_add(rel8) })
|
||||||
.wrapping_add(rel8)
|
|
||||||
})
|
|
||||||
} };
|
} };
|
||||||
|
|
||||||
(@displace16=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr,
|
(@displace16=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr,
|
||||||
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
($segment:ident, $repeat:ident, $prefix_loop:lifetime),
|
||||||
$modrm:tt) => { {
|
$modrm:tt) => { {
|
||||||
let rel16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
let rel16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
step!(@arg $cookie, &mut FarPtr { bus: $bus,
|
step!(@arg $cookie, FarPtr { bus: $bus,
|
||||||
segment: $segment.unwrap(),
|
segment: $segment.unwrap(),
|
||||||
offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?)
|
offset: ($cpu.$reg1.get() $(+ $cpu.$reg2.get())?).wrapping_add(rel16) })
|
||||||
.wrapping_add(rel16)
|
|
||||||
})
|
|
||||||
} };
|
} };
|
||||||
|
|
||||||
(@flags $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@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)) => {
|
(@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?
|
// TODO: Should these also be passed into the macro like the modrm specs?
|
||||||
match $modrm_val >> 3 & 0x7 {
|
match $modrm_val >> 3 & 0x7 {
|
||||||
0 => step!(@arg $cookie, &mut Reg { reg: &$cpu.a } ),
|
0 => step!(@arg $cookie, Reg { reg: &$cpu.a } ),
|
||||||
1 => step!(@arg $cookie, &mut Reg { reg: &$cpu.c } ),
|
1 => step!(@arg $cookie, Reg { reg: &$cpu.c } ),
|
||||||
2 => step!(@arg $cookie, &mut Reg { reg: &$cpu.d } ),
|
2 => step!(@arg $cookie, Reg { reg: &$cpu.d } ),
|
||||||
3 => step!(@arg $cookie, &mut Reg { reg: &$cpu.b } ),
|
3 => step!(@arg $cookie, Reg { reg: &$cpu.b } ),
|
||||||
4 => step!(@arg $cookie, &mut Reg { reg: &$cpu.sp } ),
|
4 => step!(@arg $cookie, Reg { reg: &$cpu.sp } ),
|
||||||
5 => step!(@arg $cookie, &mut Reg { reg: &$cpu.bp } ),
|
5 => step!(@arg $cookie, Reg { reg: &$cpu.bp } ),
|
||||||
6 => step!(@arg $cookie, &mut Reg { reg: &$cpu.si } ),
|
6 => step!(@arg $cookie, Reg { reg: &$cpu.si } ),
|
||||||
7 => step!(@arg $cookie, &mut Reg { reg: &$cpu.di } ),
|
7 => step!(@arg $cookie, Reg { reg: &$cpu.di } ),
|
||||||
_ => unreachable!()
|
_ => 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)) => {
|
(@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?
|
// TODO: Should these also be passed into the macro like the modrm specs?
|
||||||
match $modrm_val >> 3 & 0x7 {
|
match $modrm_val >> 3 & 0x7 {
|
||||||
0 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.a } ),
|
0 => step!(@arg $cookie, RegHi { reg: &$cpu.a } ),
|
||||||
1 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.c } ),
|
1 => step!(@arg $cookie, RegHi { reg: &$cpu.c } ),
|
||||||
2 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.d } ),
|
2 => step!(@arg $cookie, RegHi { reg: &$cpu.d } ),
|
||||||
3 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.b } ),
|
3 => step!(@arg $cookie, RegHi { reg: &$cpu.b } ),
|
||||||
4 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.a } ),
|
4 => step!(@arg $cookie, RegLo { reg: &$cpu.a } ),
|
||||||
5 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.c } ),
|
5 => step!(@arg $cookie, RegLo { reg: &$cpu.c } ),
|
||||||
6 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.d } ),
|
6 => step!(@arg $cookie, RegLo { reg: &$cpu.d } ),
|
||||||
7 => step!(@arg $cookie, &mut RegLo { reg: &$cpu.b } ),
|
7 => step!(@arg $cookie, RegLo { reg: &$cpu.b } ),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
(@reg=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@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) => {
|
(@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) => {
|
(@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) => {
|
(@regval=$reg:ident $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ macro_rules! update_flags {
|
|||||||
} }
|
} }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert<T: Operand + Debug>(loc: &impl RValue<T>, val: &impl RValue<T>) {
|
pub fn assert<T: Operand + Debug>(loc: impl RValue<T>, val: impl RValue<T>) {
|
||||||
assert_eq!(loc.read(), val.read(),
|
assert_eq!(loc.read(), val.read(),
|
||||||
"ASSERT instruction failed: {:#2X?} != {:#2X?}", loc.read(), val.read());
|
"ASSERT instruction failed: {:#2X?} != {:#2X?}", loc.read(), val.read());
|
||||||
println!("ASSERT pass: {:#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);
|
println!("{:#X?}", cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek(addr: &(impl Address + RValue<u8>)) {
|
pub fn peek(addr: impl Address + RValue<u8>) {
|
||||||
println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read());
|
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);
|
let target = ip.read().wrapping_add(rel16);
|
||||||
push(bus, ss, sp, ip.read());
|
push(bus, ss, sp, ip.read());
|
||||||
ip.write(target);
|
ip.write(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmp<T: Operand>(flags: &mut Flags, dst: &impl RValue<T>, src: &impl RValue<T>) {
|
pub fn cmp<T: Operand>(flags: &mut Flags, dst: impl RValue<T>, src: impl RValue<T>) {
|
||||||
let (dst, src) = (dst.read(), src.read());
|
let (dst, src) = (dst.read(), src.read());
|
||||||
let after = update_flags!(flags, T, dst.overflowing_sub(&src), af, cf, pf, sf, zf);
|
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...
|
flags.of = T::zero() != T::HI_BIT_MASK & // In the (maybe) sign bit...
|
||||||
@@ -107,38 +107,38 @@ pub fn cmp<T: Operand>(flags: &mut Flags, dst: &impl RValue<T>, src: &impl RValu
|
|||||||
pub fn cmpsb(flags: &mut Flags,
|
pub fn cmpsb(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
es: &mut Reg,
|
es: Reg,
|
||||||
di: &mut Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf), {
|
string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf), {
|
||||||
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
||||||
let dst = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
let dst = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
||||||
|
|
||||||
cmp(flags, &dst, &src);
|
cmp(flags, dst, src);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmpsw(flags: &mut Flags,
|
pub fn cmpsw(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
es: &mut Reg,
|
es: Reg,
|
||||||
di: &mut Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u16, flags, rep, cx, si=si, di=di, zf=flags.zf), {
|
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 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() });
|
let dst = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
||||||
|
|
||||||
cmp(flags, &dst, &src);
|
cmp(flags, dst, src);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
|
pub fn dec<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
|
||||||
flags: &mut Flags,
|
flags: &mut Flags,
|
||||||
dst: &mut impl LValue<T>) {
|
mut dst: impl LValue<T>) {
|
||||||
let res = update_flags!(flags, T, dst.read().overflowing_sub(&T::one()), sf, zf, af, pf);
|
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();
|
flags.of = res == T::HI_BIT_MASK - T::one();
|
||||||
dst.write(res);
|
dst.write(res);
|
||||||
@@ -146,124 +146,124 @@ pub fn dec<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when d
|
|||||||
|
|
||||||
pub fn inc<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
|
pub fn inc<T: Operand>(_width: PhantomData<T>, // Needed to disambiguate when dst is a FarPtr
|
||||||
flags: &mut Flags,
|
flags: &mut Flags,
|
||||||
dst: &mut impl LValue<T>) {
|
mut dst: impl LValue<T>) {
|
||||||
let res = update_flags!(flags, T, dst.read().overflowing_add(&T::one()), sf, zf, af, pf);
|
let res = update_flags!(flags, T, dst.read().overflowing_add(&T::one()), sf, zf, af, pf);
|
||||||
flags.of = res == T::HI_BIT_MASK;
|
flags.of = res == T::HI_BIT_MASK;
|
||||||
dst.write(res);
|
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 {
|
match num {
|
||||||
0x21 => dos::interrupt(cpu, bus),
|
0x21 => dos::interrupt(cpu, bus),
|
||||||
_ => unimplemented!("interrupt: {:02X}\ncpu: {:#X?}", num, cpu)
|
_ => 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 {
|
if !flags.cf && !flags.zf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if !flags.cf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.cf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.cf || flags.zf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if cx.read() == 0 {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.zf && flags.sf == flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.sf == flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.sf != flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.zf || flags.sf != flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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));
|
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 {
|
if !flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if !flags.sf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if !flags.zf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.of {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.sf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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 {
|
if flags.zf {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
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)
|
dst.write(addr.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lodsb(flags: &Flags,
|
pub fn lodsb(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
al: &mut impl LValue<u8>) {
|
mut al: impl LValue<u8>) {
|
||||||
string_op!((u8, flags, rep, cx, si=si), {
|
string_op!((u8, flags, rep, cx, si=si), {
|
||||||
al.write(FarPtr { bus: bus, segment: seg, offset: si.read() }.read());
|
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,
|
pub fn lodsw(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
ax: &mut impl LValue<u16>) {
|
mut ax: impl LValue<u16>) {
|
||||||
string_op!((u16, flags, rep, cx, si=si), {
|
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());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mov<T>(dst: &mut impl LValue<T>, src: &impl RValue<T>) {
|
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 movsb(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u8, flags, rep, cx, si=si, di=di), {
|
string_op!((u8, flags, rep, cx, si=si, di=di), {
|
||||||
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
let src = <FarPtr as RValue<u8>>::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() };
|
||||||
@@ -303,11 +303,11 @@ pub fn movsb(flags: &Flags,
|
|||||||
pub fn movsw(flags: &Flags,
|
pub fn movsw(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
seg: u16,
|
seg: u16,
|
||||||
si: &mut Reg,
|
mut si: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u16, flags, rep, cx, si=si, di=di), {
|
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 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() };
|
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 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() };
|
let ptr = FarPtr { bus: bus, segment: ss, offset: sp.read() };
|
||||||
dst.write(ptr.read());
|
dst.write(ptr.read());
|
||||||
sp.write(sp.read() + 2);
|
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
|
// XXX: Not checking for stack faults or anything
|
||||||
sp.write(sp.read() - 2);
|
sp.write(sp.read() - 2);
|
||||||
let mut ptr = FarPtr { bus: bus, segment: ss, offset: sp.read() };
|
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,
|
pub fn scasb(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg,
|
mut di: Reg,
|
||||||
needle: &impl RValue<u8>) {
|
needle: impl RValue<u8>) {
|
||||||
|
let needle = needle.read();
|
||||||
string_op!((u8, flags, rep, cx, di=di, zf=flags.zf), {
|
string_op!((u8, 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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scasw(flags: &mut Flags,
|
pub fn scasw(flags: &mut Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg,
|
mut di: Reg,
|
||||||
needle: &impl RValue<u16>) {
|
needle: impl RValue<u16>) {
|
||||||
|
let needle = needle.read();
|
||||||
string_op!((u16, flags, rep, cx, di=di, zf=flags.zf), {
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stosb(flags: &Flags,
|
pub fn stosb(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg,
|
mut di: Reg,
|
||||||
val: &impl RValue<u8>) {
|
val: impl RValue<u8>) {
|
||||||
string_op!((u8, flags, rep, cx, di=di), {
|
string_op!((u8, 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());
|
||||||
@@ -372,10 +374,10 @@ pub fn stosb(flags: &Flags,
|
|||||||
pub fn stosw(flags: &Flags,
|
pub fn stosw(flags: &Flags,
|
||||||
bus: &mut Bus,
|
bus: &mut Bus,
|
||||||
rep: RepPrefix,
|
rep: RepPrefix,
|
||||||
cx: &mut Reg,
|
mut cx: Reg,
|
||||||
es: &Reg,
|
es: Reg,
|
||||||
di: &mut Reg,
|
mut di: Reg,
|
||||||
val: &impl RValue<u16>) {
|
val: impl RValue<u16>) {
|
||||||
string_op!((u16, flags, rep, cx, di=di), {
|
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