diff --git a/hypervisor/src/arch/x86/emulator/instructions/movs.rs b/hypervisor/src/arch/x86/emulator/instructions/movs.rs index 4ba8eed3d..084032041 100644 --- a/hypervisor/src/arch/x86/emulator/instructions/movs.rs +++ b/hypervisor/src/arch/x86/emulator/instructions/movs.rs @@ -90,6 +90,11 @@ impl InstructionHandler for Movsd_m32_m32 { movs!(u32); } +pub struct Movsw_m16_m16; +impl InstructionHandler for Movsw_m16_m16 { + movs!(u16); +} + #[cfg(test)] mod tests { #![allow(unused_mut)] @@ -148,4 +153,66 @@ mod tests { vmm.read_memory(0x8 + 8, &mut data).unwrap(); assert_eq!(0x0, ::from_le_bytes(data)); } + + #[test] + fn test_rep_movsw_m16_m16() { + let ip: u64 = 0x1000; + let memory: [u8; 24] = [ + 0x78, 0x56, 0x34, 0x12, // 0x12345678 + 0xdd, 0xcc, 0xbb, 0xaa, // 0xaabbccdd + 0xa5, 0x5a, 0xa5, 0x5a, // 0x5aa55aa5 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + ]; + let insn = [0x66, 0xf3, 0xa5]; // rep movsw + let regs = vec![(Register::ECX, 6), (Register::ESI, 0), (Register::EDI, 0xc)]; + let mut data = [0u8; 2]; + + let mut vmm = MockVmm::new(ip, regs, Some((0, &memory))); + + assert!(vmm.emulate_first_insn(0, &insn).is_ok()); + + vmm.read_memory(0xc, &mut data).unwrap(); + assert_eq!(0x5678, ::from_le_bytes(data)); + vmm.read_memory(0xc + 2, &mut data).unwrap(); + assert_eq!(0x1234, ::from_le_bytes(data)); + vmm.read_memory(0xc + 4, &mut data).unwrap(); + assert_eq!(0xccdd, ::from_le_bytes(data)); + vmm.read_memory(0xc + 6, &mut data).unwrap(); + assert_eq!(0xaabb, ::from_le_bytes(data)); + vmm.read_memory(0xc + 8, &mut data).unwrap(); + assert_eq!(0x5aa5, ::from_le_bytes(data)); + vmm.read_memory(0xc + 10, &mut data).unwrap(); + assert_eq!(0x5aa5, ::from_le_bytes(data)); + // The rest should be default value 0 from MockVmm + vmm.read_memory(0xc + 12, &mut data).unwrap(); + assert_eq!(0x0, ::from_le_bytes(data)); + } + + #[test] + fn test_movsw_m16_m16() { + let ip: u64 = 0x1000; + let memory: [u8; 4] = [ + 0x78, 0x56, 0x34, 0x12, // 0x12345678 + ]; + let insn = [0x66, 0xa5]; // movsw + let regs = vec![(Register::ESI, 0), (Register::EDI, 0x8)]; + let mut data = [0u8; 2]; + + let mut vmm = MockVmm::new(ip, regs, Some((0, &memory))); + + assert!(vmm.emulate_first_insn(0, &insn).is_ok()); + + vmm.read_memory(0x8, &mut data).unwrap(); + assert_eq!(0x5678, ::from_le_bytes(data)); + // Only two bytes were copied, so the value at 0xa should be zero + vmm.read_memory(0xa, &mut data).unwrap(); + assert_eq!(0x0, ::from_le_bytes(data)); + // The rest should be default value 0 from MockVmm + vmm.read_memory(0x4, &mut data).unwrap(); + assert_eq!(0x0, ::from_le_bytes(data)); + vmm.read_memory(0x8 + 8, &mut data).unwrap(); + assert_eq!(0x0, ::from_le_bytes(data)); + } } diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index c0d2860a5..12c241233 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -526,6 +526,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> { (mov, Movzx_r64_rm16), // MOVS (movs, Movsd_m32_m32), + (movs, Movsw_m16_m16), // OR (or, Or_rm8_r8) );