mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-03-20 07:58:55 +00:00
hypervisor: emulator: use static mapping to dispatch emulation
The mapping between code and its handler is static. We can drop the HashMap in favour of a static match expression. This has two benefits: 1. No more memory allocation and deallocation for the HashMap. 2. Shorter look-up time. Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
parent
ffaab46934
commit
ab89b48143
@ -475,32 +475,47 @@ impl CpuStateManager for EmulatorCpuState {
|
||||
|
||||
pub struct Emulator<'a, T: CpuStateManager> {
|
||||
platform: &'a mut dyn PlatformEmulator<CpuState = T>,
|
||||
insn_map: InstructionMap<T>,
|
||||
}
|
||||
|
||||
// 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<CpuState = T>) -> Emulator<T> {
|
||||
let mut insn_map = InstructionMap::<T>::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<Box<dyn InstructionHandler<T>>> {
|
||||
let handler: Option<Box<dyn InstructionHandler<T>>> = 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?} {:?} {:?}",
|
||||
|
Loading…
x
Reference in New Issue
Block a user