From 5ada3f59c8b7cafff923e7b3032bb6209a6473fc Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 3 Feb 2021 00:02:50 +0100 Subject: [PATCH] hypervisor: emulator: Emulate MOVZX MOV R/RM is a special case of MOVZX, so we generalize the mov_r_rm macro to make it support both instructions. Fixes: #2227 Signed-off-by: Samuel Ortiz --- .../src/arch/x86/emulator/instructions/mov.rs | 49 +++++++++++++++++-- hypervisor/src/arch/x86/emulator/mod.rs | 8 ++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/hypervisor/src/arch/x86/emulator/instructions/mov.rs b/hypervisor/src/arch/x86/emulator/instructions/mov.rs index 2aebe6253..ee696c577 100644 --- a/hypervisor/src/arch/x86/emulator/instructions/mov.rs +++ b/hypervisor/src/arch/x86/emulator/instructions/mov.rs @@ -74,21 +74,27 @@ macro_rules! mov_rm_imm { }; } -macro_rules! mov_r_rm { - ($bound:ty) => { +macro_rules! movzx { + ($src_op_size:ty, $dest_op_size:ty) => { fn emulate( &self, insn: &Instruction, state: &mut T, platform: &mut dyn PlatformEmulator, ) -> Result<(), EmulationError> { - let src_value = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform) - .map_err(EmulationError::PlatformEmulationError)?; + let src_value = get_op( + &insn, + 1, + std::mem::size_of::<$src_op_size>(), + state, + platform, + ) + .map_err(EmulationError::PlatformEmulationError)?; set_op( &insn, 0, - std::mem::size_of::<$bound>(), + std::mem::size_of::<$dest_op_size>(), state, platform, src_value, @@ -102,6 +108,13 @@ macro_rules! mov_r_rm { }; } +// MOV r/rm is a special case of MOVZX, where both operands have the same size. +macro_rules! mov_r_rm { + ($op_size:ty) => { + movzx!($op_size, $op_size); + }; +} + macro_rules! mov_r_imm { ($bound:ty) => { fn emulate( @@ -210,6 +223,32 @@ impl InstructionHandler for Mov_rm64_r64 { mov_rm_r!(u64); } +// MOVZX +pub struct Movzx_r16_rm8; +impl InstructionHandler for Movzx_r16_rm8 { + movzx!(u16, u8); +} + +pub struct Movzx_r32_rm8; +impl InstructionHandler for Movzx_r32_rm8 { + movzx!(u32, u8); +} + +pub struct Movzx_r64_rm8; +impl InstructionHandler for Movzx_r64_rm8 { + movzx!(u64, u8); +} + +pub struct Movzx_r32_rm16; +impl InstructionHandler for Movzx_r32_rm16 { + movzx!(u32, u16); +} + +pub struct Movzx_r64_rm16; +impl InstructionHandler for Movzx_r64_rm16 { + movzx!(u64, u16); +} + #[cfg(test)] mod tests { #![allow(unused_mut)] diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index c26b5faa2..03e2d428a 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -518,7 +518,13 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> { (mov, Mov_rm32_imm32), (mov, Mov_rm32_r32), (mov, Mov_rm64_imm32), - (mov, Mov_rm64_r64) + (mov, Mov_rm64_r64), + // MOVZX + (mov, Movzx_r16_rm8), + (mov, Movzx_r32_rm8), + (mov, Movzx_r64_rm8), + (mov, Movzx_r32_rm16), + (mov, Movzx_r64_rm16) ); handler