emu: make $name optional in step!-internal calls

Gearing up to change modrm code to no longer push its directives onto
the main processing stack. This also necessitates making the
function's $form/width/tyargs-thingy a child of $name.

It might be nice to revisit this at some point if we want to merge all
the different form=word[0,1,2,3] arities together. I had hoped that
FarPtr could become parameterized on its pointee width (u8 or u16) and
that would obviate the need for turbofishing the op function
directly. Unfortunately, the string operations need disambiguation
regardless as they construct their pointers internally. But perhaps
that could've been solved with some PhantomData. Regardless, this kind
of approach becomes more difficult after this commit as the width is
now tied to the function name.
This commit is contained in:
2021-04-18 00:26:50 -07:00
parent c66feda360
commit 19d686e7ad
2 changed files with 40 additions and 32 deletions

View File

@@ -46,64 +46,71 @@ pub enum RepPrefix {
macro_rules! step {
// Base case: all args processed and ready to call op
(@code $(form=($($tyargs:tt),*),)? ( $($done:tt)* ),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
(@code ( $($done:tt)* ),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $cycles:literal,
()) => {
ops::$name$(::<$($tyargs),*>)?($($done),*);
$(ops::$name$(::<$($tyargs),*>)?)?($($done),*);
};
// Inductive case: decode next arg to be placed in list
(@code $(form=$form:tt,)? ( $($done:tt)* ),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
(@code ( $($done:tt)* ),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $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
( $(form=$form,)? ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ($($rest $(= $restrhs)?)*) ),
( ($($done)*), $cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $cycles, ($($rest $(= $restrhs)?)*) ),
$cpu, $bus, $prefix, $modrm)
};
// accept an argument from a decoder and recur to look for next arg
(@arg ( $(form=$form:tt,)? ($($done:tt)*),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
(@arg ( ($($done:tt)*),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $cycles:literal,
$rest:tt )
$(, $arg:expr)?) => {
step!(@code $(form=$form,)? ($($done)* $($arg)?), $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
step!(@code ($($done)* $($arg)?), $cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $cycles, $rest)
};
// decoder deferring to sub-decoders, push them onto the decoder stack to process next
(@push ( $(form=$form:tt,)? ($($done:tt)*),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal, ( $($rest:tt)* ) ),
(@push ( ($($done:tt)*),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $cycles:literal,
( $($rest:tt)* ) ),
( $($args:tt)* )) => {
step!(@code $(form=$form,)? ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ( $($args)* $($rest)* ))
step!(@code ($($done)*), $cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $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,
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, name=$name:ident, $cycles:literal,
$rest:tt ),
form=$form:tt) => {
step!(@code form=$form, $done, $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
form=<$($tyargs:tt),*> ) => {
step!(@code $done, $cpu, $bus, $prefix, $modrm, name=$name<$($tyargs),*>, $cycles, $rest)
};
// Adds tokens to the last argument. Used by @convert to append ".into()" to the last arg
(@append-to-last ($($done:tt)*)
( $(form=$form:tt,)? ($last:tt),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
( ($last:tt),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $cycles:literal,
$rest:tt ) { $($conv:tt)+ } ) => {
step!(@code $(form=$form,)? ($($done)* ($last$($conv)+)),
$cpu, $bus, $prefix, $modrm, $name, $cycles,
step!(@code ($($done)* ($last$($conv)+)),
$cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $cycles,
$rest )
};
// Recursive case for @append-to-last, walks through already
// processed args to find the last one for appending
(@append-to-last ($($done:tt)*)
( $(form=$form:tt,)? ($next:tt $($restdone:tt)+),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
( ($next:tt $($restdone:tt)+),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt,
$(name=$name:ident$(<$($tyargs:tt),*>)?,)? $cycles:literal,
$rest:tt ) { $($conv:tt)+ } ) => {
step!(@append-to-last ($($done)* $next)
( $(form=$form,)? ($($restdone)+),
$cpu, $bus, $prefix, $modrm, $name, $cycles,
( ($($restdone)+),
$cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $cycles,
$rest ) { $($conv)+ } )
};
@@ -179,27 +186,27 @@ macro_rules! step {
};
(@form=byte0 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u8))
step!(@form $cookie, form=<u8>)
};
(@form=byte1 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u8, _))
step!(@form $cookie, form=<u8, _>)
};
(@form=byte3 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u8, _, _, _))
step!(@form $cookie, form=<u8, _, _, _>)
};
(@form=word0 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u16))
step!(@form $cookie, form=<u16>)
};
(@form=word1 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u16, _))
step!(@form $cookie, form=<u16, _>)
};
(@form=word3 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@form $cookie, form=(u16, _, _, _))
step!(@form $cookie, form=<u16, _, _, _>)
};
(@mem $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
@@ -347,7 +354,7 @@ macro_rules! step {
$name:ident[$($args:ident $(= $argrhs:tt)?),*] / $cycles:literal),*$(,)? } ) => { {
let subcode = $modrm_val & 0x38;
match subcode {
$( $subcode => step!(@code (), $cpu, $bus, $prefix, ($modrm_val, $modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
$( $subcode => step!(@code (), $cpu, $bus, $prefix, ($modrm_val, $modrm, $modrm16, $modrm8), name=$name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
_ => unimplemented!("opcode: {:02X} {:02X}({:02X})\ncpu: {:#X?}", $code, $modrm_val, subcode, $cpu)
} }
};
@@ -380,7 +387,7 @@ macro_rules! step {
$( $( $code => {
$( let $ext = (); /* No-op just to trigger expansion. */
modrm_val = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); )?
step!(@code (), $cpu, $bus, (segment, repeat, 'prefix_loop), (modrm_val, $modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*))
step!(@code (), $cpu, $bus, (segment, repeat, 'prefix_loop), (modrm_val, $modrm, $modrm16, $modrm8), name=$name, $cycles, ($($args $(= $argrhs)?)*))
}
)?
$( $code => {

View File

@@ -216,6 +216,7 @@ impl<'a> From<FarPtr<'_>> for DynLValue<'a> {
DynLValue::FarPtr { segment: farptr.segment, offset: farptr.offset }
}
}
impl<LVal: LValue<T>, T> LValue<T> for &mut LVal {
fn write(&mut self, val: T) {
(**self).write(val);