emu: Use type arguments instead of PhantomData to disambiguate
Allows elision of op directive when operands are of unambiguous width
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use std::cell::Cell;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use super::byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
@@ -63,34 +62,45 @@ pub enum RepPrefix {
|
||||
|
||||
macro_rules! step {
|
||||
// Base case: all args processed and ready to call op
|
||||
(@code ( $($done:tt)* ),
|
||||
(@code $(form=($($tyargs:tt),*),)? ( $($done:tt)* ),
|
||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
||||
()) => {
|
||||
ops::$name($($done),*);
|
||||
ops::$name$(::<$($tyargs),*>)?($($done),*);
|
||||
};
|
||||
|
||||
// Inductive case: decode next arg to be placed in list
|
||||
(@code ( $($done:tt)* ),
|
||||
(@code $(form=$form:tt,)? ( $($done:tt)* ),
|
||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
||||
($next:ident $(= $nextrhs:tt)? $($rest:ident $(= $restrhs:tt)?)*)) => {
|
||||
step!(@$next$(= $nextrhs)?
|
||||
// "cookie" tt to be passed thru to @arg so we have all the args for the recursive step
|
||||
( ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ($($rest $(= $restrhs)?)*) ),
|
||||
( $(form=$form,)? ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ($($rest $(= $restrhs)?)*) ),
|
||||
$cpu, $bus, $prefix, $modrm)
|
||||
};
|
||||
|
||||
// accept an argument from a decoder and recur to look for next arg
|
||||
(@arg ( ($($done:tt)*), $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
|
||||
$name:ident, $cycles:literal, $rest:tt )
|
||||
(@arg ( $(form=$form:tt,)? ($($done:tt)*),
|
||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
||||
$rest:tt )
|
||||
$(, $arg:expr)?) => {
|
||||
step!(@code ($($done)* $($arg)?), $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
|
||||
step!(@code $(form=$form,)? ($($done)* $($arg)?), $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
|
||||
};
|
||||
|
||||
// decoder deferring to sub-decoders, push them onto the decoder stack to process next
|
||||
(@push ( $done:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal, ( $($rest:tt)* ) ),
|
||||
( $($args:tt)* )) => {
|
||||
step!(@code $done, $cpu, $bus, $prefix, $modrm, $name, $cycles, ( $($args)* $($rest)* ))
|
||||
(@push ( $(form=$form:tt,)? ($($done:tt)*),
|
||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal, ( $($rest:tt)* ) ),
|
||||
( $($args:tt)* )) => {
|
||||
step!(@code $(form=$form,)? ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ( $($args)* $($rest)* ))
|
||||
};
|
||||
|
||||
// Set the type arguments for operations that cannot infer width
|
||||
(@form ( $done:tt,
|
||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
||||
$rest:tt ),
|
||||
form=$form:tt) => {
|
||||
step!(@code form=$form, $done, $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
|
||||
};
|
||||
|
||||
// Argument Decoders
|
||||
|
||||
(@addr $cookie:tt, $cpu:expr, $bus:expr,
|
||||
@@ -192,6 +202,14 @@ macro_rules! step {
|
||||
step!(@arg $cookie, &mut $cpu.flags)
|
||||
};
|
||||
|
||||
(@form=unary_byte $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||
step!(@form $cookie, form=(u8, _));
|
||||
};
|
||||
|
||||
(@form=unary_word $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||
step!(@form $cookie, form=(u16, _));
|
||||
};
|
||||
|
||||
(@mem $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||
step!(@arg $cookie, &mut $bus.ram)
|
||||
};
|
||||
@@ -327,14 +345,6 @@ 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),
|
||||
@@ -416,22 +426,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,
|
||||
0x40 => inc[flags, reg=a] / 3,
|
||||
0x41 => inc[flags, reg=c] / 3,
|
||||
0x42 => inc[flags, reg=d] / 3,
|
||||
0x43 => inc[flags, reg=b] / 3,
|
||||
0x44 => inc[flags, reg=sp] / 3,
|
||||
0x45 => inc[flags, reg=bp] / 3,
|
||||
0x46 => inc[flags, reg=si] / 3,
|
||||
0x47 => inc[flags, reg=di] / 3,
|
||||
0x48 => dec[flags, reg=a] / 3,
|
||||
0x49 => dec[flags, reg=c] / 3,
|
||||
0x4A => dec[flags, reg=d] / 3,
|
||||
0x4B => dec[flags, reg=b] / 3,
|
||||
0x4C => dec[flags, reg=sp] / 3,
|
||||
0x4D => dec[flags, reg=bp] / 3,
|
||||
0x4E => dec[flags, reg=si] / 3,
|
||||
0x4F => dec[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,
|
||||
@@ -524,10 +534,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
|
||||
0xFE: { 00 => inc[form=unary_byte, flags, modrm8] / "3/23+", // INC r/m8
|
||||
08 => dec[form=unary_byte, flags, modrm8] / "3/23+", }, // DEC r/m8
|
||||
0xFF: { 00 => inc[form=unary_word, flags, modrm16] / "3/23+", // INC r/m16
|
||||
08 => dec[form=unary_word, flags, modrm16] / "3/23+", // DEC r/m16
|
||||
30 => push_modrm[unsafe_bus_maybe, regval=ss, reg=sp, modrm16] / "15/24+" },
|
||||
},
|
||||
modrm: {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::convert::Into;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use emu::dos;
|
||||
use emu::i8088::{Flags, RepPrefix, i8088};
|
||||
@@ -137,17 +136,13 @@ 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,
|
||||
mut dst: impl LValue<T>) {
|
||||
pub fn dec<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
||||
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,
|
||||
mut dst: impl LValue<T>) {
|
||||
pub fn inc<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user