emu: don't macro recur on every @r8/r16 value
Avoids O(M*N) codegen blowup when paired with a modrm arg. Probably want to do the same thing to the modrm op directives but those cases are little more tricky and this alone gets rid of much of the pain.
This commit is contained in:
@@ -179,27 +179,27 @@ macro_rules! step {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(@form=byte0 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@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) => {
|
(@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) => {
|
(@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) => {
|
(@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) => {
|
(@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) => {
|
(@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) => {
|
(@mem $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
@@ -253,35 +253,45 @@ macro_rules! step {
|
|||||||
continue $prefix_loop;
|
continue $prefix_loop;
|
||||||
};
|
};
|
||||||
|
|
||||||
(@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_rest: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 {
|
let reg = match $modrm_val >> 3 & 0x7 {
|
||||||
0 => step!(@arg $cookie, Reg { reg: &$cpu.a } ),
|
0 => Reg { reg: &$cpu.a },
|
||||||
1 => step!(@arg $cookie, Reg { reg: &$cpu.c } ),
|
1 => Reg { reg: &$cpu.c },
|
||||||
2 => step!(@arg $cookie, Reg { reg: &$cpu.d } ),
|
2 => Reg { reg: &$cpu.d },
|
||||||
3 => step!(@arg $cookie, Reg { reg: &$cpu.b } ),
|
3 => Reg { reg: &$cpu.b },
|
||||||
4 => step!(@arg $cookie, Reg { reg: &$cpu.sp } ),
|
4 => Reg { reg: &$cpu.sp },
|
||||||
5 => step!(@arg $cookie, Reg { reg: &$cpu.bp } ),
|
5 => Reg { reg: &$cpu.bp },
|
||||||
6 => step!(@arg $cookie, Reg { reg: &$cpu.si } ),
|
6 => Reg { reg: &$cpu.si },
|
||||||
7 => step!(@arg $cookie, Reg { reg: &$cpu.di } ),
|
7 => Reg { reg: &$cpu.di },
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
};
|
step!(@arg $cookie, reg)
|
||||||
|
} };
|
||||||
|
|
||||||
(@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_rest:tt),*)) => { {
|
||||||
|
let modrm_shift = $modrm_val >> 3;
|
||||||
// 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 {
|
if modrm_shift & 0x4 == 0 {
|
||||||
0 => step!(@arg $cookie, RegLo { reg: &$cpu.a } ),
|
let reg = match modrm_shift & 0x3 {
|
||||||
1 => step!(@arg $cookie, RegLo { reg: &$cpu.c } ),
|
0 => RegLo { reg: &$cpu.a },
|
||||||
2 => step!(@arg $cookie, RegLo { reg: &$cpu.d } ),
|
1 => RegLo { reg: &$cpu.c },
|
||||||
3 => step!(@arg $cookie, RegLo { reg: &$cpu.b } ),
|
2 => RegLo { reg: &$cpu.d },
|
||||||
4 => step!(@arg $cookie, RegHi { reg: &$cpu.a } ),
|
3 => RegLo { reg: &$cpu.b },
|
||||||
5 => step!(@arg $cookie, RegHi { reg: &$cpu.c } ),
|
|
||||||
6 => step!(@arg $cookie, RegHi { reg: &$cpu.d } ),
|
|
||||||
7 => step!(@arg $cookie, RegHi { reg: &$cpu.b } ),
|
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
step!(@arg $cookie, reg)
|
||||||
|
} else {
|
||||||
|
let reg = match modrm_shift & 0x3 {
|
||||||
|
0 => RegHi { reg: &$cpu.a },
|
||||||
|
1 => RegHi { reg: &$cpu.c },
|
||||||
|
2 => RegHi { reg: &$cpu.d },
|
||||||
|
3 => RegHi { reg: &$cpu.b },
|
||||||
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
step!(@arg $cookie, reg)
|
||||||
|
}
|
||||||
|
} };
|
||||||
|
|
||||||
(@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, Reg { reg: &$cpu.$reg });
|
step!(@arg $cookie, Reg { reg: &$cpu.$reg });
|
||||||
|
|||||||
Reference in New Issue
Block a user