mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +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:
@@ -475,32 +475,47 @@ impl CpuStateManager for EmulatorCpuState {
|
|||||||
|
|
||||||
pub struct Emulator<'a, T: CpuStateManager> {
|
pub struct Emulator<'a, T: CpuStateManager> {
|
||||||
platform: &'a mut dyn PlatformEmulator<CpuState = T>,
|
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> {
|
impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
||||||
pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
|
pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
|
||||||
let mut insn_map = InstructionMap::<T>::new();
|
Emulator { platform }
|
||||||
|
}
|
||||||
|
|
||||||
// MOV
|
fn get_handler(code: Code) -> Option<Box<dyn InstructionHandler<T>>> {
|
||||||
insn_add!(insn_map, mov, Mov_r8_imm8);
|
let handler: Option<Box<dyn InstructionHandler<T>>> = gen_handler_match!(
|
||||||
insn_add!(insn_map, mov, Mov_r8_rm8);
|
code,
|
||||||
insn_add!(insn_map, mov, Mov_r16_imm16);
|
(mov, Mov_r8_rm8),
|
||||||
insn_add!(insn_map, mov, Mov_r16_rm16);
|
(mov, Mov_r8_imm8),
|
||||||
insn_add!(insn_map, mov, Mov_r32_imm32);
|
(mov, Mov_r16_imm16),
|
||||||
insn_add!(insn_map, mov, Mov_r32_rm32);
|
(mov, Mov_r16_rm16),
|
||||||
insn_add!(insn_map, mov, Mov_r64_imm64);
|
(mov, Mov_r32_imm32),
|
||||||
insn_add!(insn_map, mov, Mov_r64_rm64);
|
(mov, Mov_r32_rm32),
|
||||||
insn_add!(insn_map, mov, Mov_rm8_imm8);
|
(mov, Mov_r64_imm64),
|
||||||
insn_add!(insn_map, mov, Mov_rm8_r8);
|
(mov, Mov_r64_rm64),
|
||||||
insn_add!(insn_map, mov, Mov_rm16_imm16);
|
(mov, Mov_rm8_imm8),
|
||||||
insn_add!(insn_map, mov, Mov_rm16_r16);
|
(mov, Mov_rm8_r8),
|
||||||
insn_add!(insn_map, mov, Mov_rm32_imm32);
|
(mov, Mov_rm16_imm16),
|
||||||
insn_add!(insn_map, mov, Mov_rm32_r32);
|
(mov, Mov_rm16_r16),
|
||||||
insn_add!(insn_map, mov, Mov_rm64_imm32);
|
(mov, Mov_rm32_imm32),
|
||||||
insn_add!(insn_map, mov, Mov_rm64_r64);
|
(mov, Mov_rm32_r32),
|
||||||
|
(mov, Mov_rm64_imm32),
|
||||||
|
(mov, Mov_rm64_r64)
|
||||||
|
);
|
||||||
|
|
||||||
Emulator { platform, insn_map }
|
handler
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emulate_insn_stream(
|
fn emulate_insn_stream(
|
||||||
@@ -561,9 +576,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emulate the decoded instruction
|
// Emulate the decoded instruction
|
||||||
self.insn_map
|
Emulator::get_handler(insn.code())
|
||||||
.instructions
|
|
||||||
.get(&insn.code())
|
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
EmulationError::UnsupportedInstruction(anyhow!(
|
EmulationError::UnsupportedInstruction(anyhow!(
|
||||||
"{:#x?} {:?} {:?}",
|
"{:#x?} {:?} {:?}",
|
||||||
|
|||||||
Reference in New Issue
Block a user