diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index 2a820ad00..62735c3a2 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -475,32 +475,47 @@ impl CpuStateManager for EmulatorCpuState { pub struct Emulator<'a, T: CpuStateManager> { platform: &'a mut dyn PlatformEmulator, - insn_map: InstructionMap, +} + +// Reduce repetition, see its invocation in get_handler(). +macro_rules! gen_handler_match { + ($value: ident, $( ($module:ident, $code:ident) ),* ) => { + match $value { + $( + Code::$code => Some(Box::new($module::$code {})), + )* + _ => None, + } + }; } impl<'a, T: CpuStateManager> Emulator<'a, T> { pub fn new(platform: &mut dyn PlatformEmulator) -> Emulator { - let mut insn_map = InstructionMap::::new(); + Emulator { platform } + } - // MOV - insn_add!(insn_map, mov, Mov_r8_imm8); - insn_add!(insn_map, mov, Mov_r8_rm8); - insn_add!(insn_map, mov, Mov_r16_imm16); - insn_add!(insn_map, mov, Mov_r16_rm16); - insn_add!(insn_map, mov, Mov_r32_imm32); - insn_add!(insn_map, mov, Mov_r32_rm32); - insn_add!(insn_map, mov, Mov_r64_imm64); - insn_add!(insn_map, mov, Mov_r64_rm64); - insn_add!(insn_map, mov, Mov_rm8_imm8); - insn_add!(insn_map, mov, Mov_rm8_r8); - insn_add!(insn_map, mov, Mov_rm16_imm16); - insn_add!(insn_map, mov, Mov_rm16_r16); - insn_add!(insn_map, mov, Mov_rm32_imm32); - insn_add!(insn_map, mov, Mov_rm32_r32); - insn_add!(insn_map, mov, Mov_rm64_imm32); - insn_add!(insn_map, mov, Mov_rm64_r64); + fn get_handler(code: Code) -> Option>> { + let handler: Option>> = gen_handler_match!( + code, + (mov, Mov_r8_rm8), + (mov, Mov_r8_imm8), + (mov, Mov_r16_imm16), + (mov, Mov_r16_rm16), + (mov, Mov_r32_imm32), + (mov, Mov_r32_rm32), + (mov, Mov_r64_imm64), + (mov, Mov_r64_rm64), + (mov, Mov_rm8_imm8), + (mov, Mov_rm8_r8), + (mov, Mov_rm16_imm16), + (mov, Mov_rm16_r16), + (mov, Mov_rm32_imm32), + (mov, Mov_rm32_r32), + (mov, Mov_rm64_imm32), + (mov, Mov_rm64_r64) + ); - Emulator { platform, insn_map } + handler } fn emulate_insn_stream( @@ -561,9 +576,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> { } // Emulate the decoded instruction - self.insn_map - .instructions - .get(&insn.code()) + Emulator::get_handler(insn.code()) .ok_or_else(|| { EmulationError::UnsupportedInstruction(anyhow!( "{:#x?} {:?} {:?}",