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:
2021-04-13 14:39:10 -07:00
parent 663fa40137
commit 7b00a8e708

View File

@@ -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 } ), _ => unreachable!()
6 => step!(@arg $cookie, RegHi { reg: &$cpu.d } ), };
7 => step!(@arg $cookie, RegHi { reg: &$cpu.b } ), step!(@arg $cookie, reg)
_ => unreachable!() } 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 });