From 19d686e7addc10ff8be76307854878444bb38541 Mon Sep 17 00:00:00 2001 From: Jared Burce Date: Sun, 18 Apr 2021 00:26:50 -0700 Subject: [PATCH] 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. --- src/emu/i8088.rs | 71 +++++++++++++++++++++++++-------------------- src/emu/operands.rs | 1 + 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index e5b6410..7275958 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -46,65 +46,72 @@ 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, - $rest ) { $($conv)+ } ) + ( ($($restdone)+), + $cpu, $bus, $prefix, $modrm, $(name=$name$(<$($tyargs),*>)?,)? $cycles, + $rest ) { $($conv)+ } ) }; // === OP DIRECTIVES === @@ -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=) }; (@form=byte1 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@form $cookie, form=(u8, _)) + step!(@form $cookie, form=) }; (@form=byte3 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@form $cookie, form=(u8, _, _, _)) + step!(@form $cookie, form=) }; (@form=word0 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@form $cookie, form=(u16)) + step!(@form $cookie, form=) }; (@form=word1 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@form $cookie, form=(u16, _)) + step!(@form $cookie, form=) }; (@form=word3 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { - step!(@form $cookie, form=(u16, _, _, _)) + step!(@form $cookie, form=) }; (@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 => { diff --git a/src/emu/operands.rs b/src/emu/operands.rs index cedb356..082db61 100644 --- a/src/emu/operands.rs +++ b/src/emu/operands.rs @@ -216,6 +216,7 @@ impl<'a> From> for DynLValue<'a> { DynLValue::FarPtr { segment: farptr.segment, offset: farptr.offset } } } + impl, T> LValue for &mut LVal { fn write(&mut self, val: T) { (**self).write(val);