1fe540122SSamuel Ortiz // 2fe540122SSamuel Ortiz // Copyright © 2020 Intel Corporation 3fe540122SSamuel Ortiz // 4fe540122SSamuel Ortiz // SPDX-License-Identifier: Apache-2.0 5fe540122SSamuel Ortiz // 6fe540122SSamuel Ortiz 7fe540122SSamuel Ortiz #![allow(non_camel_case_types)] 8fe540122SSamuel Ortiz 9fe540122SSamuel Ortiz // 10fe540122SSamuel Ortiz // MOV-Move 11fe540122SSamuel Ortiz // SDM Volume 1, Chapter 4.3 12fe540122SSamuel Ortiz // Copies the second operand (source operand) to the first operand (destination operand). 13fe540122SSamuel Ortiz // 14fe540122SSamuel Ortiz 15fe540122SSamuel Ortiz use crate::arch::x86::emulator::instructions::*; 16fe540122SSamuel Ortiz 17fe540122SSamuel Ortiz macro_rules! mov_rm_r { 18fe540122SSamuel Ortiz ($bound:ty) => { 19fe540122SSamuel Ortiz fn emulate( 20fe540122SSamuel Ortiz &self, 21fe540122SSamuel Ortiz insn: &Instruction, 22fe540122SSamuel Ortiz state: &mut T, 23c8b65549SWei Liu platform: &mut dyn PlatformEmulator<CpuState = T>, 24fe540122SSamuel Ortiz ) -> Result<(), EmulationError<Exception>> { 250c3ef986SWei Liu let src_reg_value = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform) 26fe540122SSamuel Ortiz .map_err(EmulationError::PlatformEmulationError)?; 27fe540122SSamuel Ortiz 280c3ef986SWei Liu set_op( 290c3ef986SWei Liu &insn, 300c3ef986SWei Liu 0, 310c3ef986SWei Liu std::mem::size_of::<$bound>(), 320c3ef986SWei Liu state, 330c3ef986SWei Liu platform, 340c3ef986SWei Liu src_reg_value, 350c3ef986SWei Liu ) 3666b00166SWei Liu .map_err(EmulationError::PlatformEmulationError)?; 37fe540122SSamuel Ortiz 38fe540122SSamuel Ortiz Ok(()) 39fe540122SSamuel Ortiz } 40fe540122SSamuel Ortiz }; 41fe540122SSamuel Ortiz } 42fe540122SSamuel Ortiz 43fe540122SSamuel Ortiz macro_rules! mov_rm_imm { 440c3ef986SWei Liu ($bound:ty) => { 45fe540122SSamuel Ortiz fn emulate( 46fe540122SSamuel Ortiz &self, 47fe540122SSamuel Ortiz insn: &Instruction, 48fe540122SSamuel Ortiz state: &mut T, 49c8b65549SWei Liu platform: &mut dyn PlatformEmulator<CpuState = T>, 50fe540122SSamuel Ortiz ) -> Result<(), EmulationError<Exception>> { 510c3ef986SWei Liu let imm = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform) 5266b00166SWei Liu .map_err(EmulationError::PlatformEmulationError)?; 5366b00166SWei Liu 540c3ef986SWei Liu set_op( 550c3ef986SWei Liu &insn, 560c3ef986SWei Liu 0, 570c3ef986SWei Liu std::mem::size_of::<$bound>(), 580c3ef986SWei Liu state, 590c3ef986SWei Liu platform, 600c3ef986SWei Liu imm, 610c3ef986SWei Liu ) 620c3ef986SWei Liu .map_err(EmulationError::PlatformEmulationError)?; 63fe540122SSamuel Ortiz 64fe540122SSamuel Ortiz Ok(()) 65fe540122SSamuel Ortiz } 66fe540122SSamuel Ortiz }; 67fe540122SSamuel Ortiz } 68fe540122SSamuel Ortiz 695ada3f59SSamuel Ortiz macro_rules! movzx { 7049214cf0SWei Liu ($dest_op_size:ty, $src_op_size:ty) => { 71fe540122SSamuel Ortiz fn emulate( 72fe540122SSamuel Ortiz &self, 73fe540122SSamuel Ortiz insn: &Instruction, 74fe540122SSamuel Ortiz state: &mut T, 75c8b65549SWei Liu platform: &mut dyn PlatformEmulator<CpuState = T>, 76fe540122SSamuel Ortiz ) -> Result<(), EmulationError<Exception>> { 775ada3f59SSamuel Ortiz let src_value = get_op( 785ada3f59SSamuel Ortiz &insn, 795ada3f59SSamuel Ortiz 1, 805ada3f59SSamuel Ortiz std::mem::size_of::<$src_op_size>(), 815ada3f59SSamuel Ortiz state, 825ada3f59SSamuel Ortiz platform, 835ada3f59SSamuel Ortiz ) 84fe540122SSamuel Ortiz .map_err(EmulationError::PlatformEmulationError)?; 85fe540122SSamuel Ortiz 860c3ef986SWei Liu set_op( 870c3ef986SWei Liu &insn, 880c3ef986SWei Liu 0, 895ada3f59SSamuel Ortiz std::mem::size_of::<$dest_op_size>(), 900c3ef986SWei Liu state, 910c3ef986SWei Liu platform, 920c3ef986SWei Liu src_value, 930c3ef986SWei Liu ) 94fe540122SSamuel Ortiz .map_err(EmulationError::PlatformEmulationError)?; 95fe540122SSamuel Ortiz 96fe540122SSamuel Ortiz Ok(()) 97fe540122SSamuel Ortiz } 98fe540122SSamuel Ortiz }; 99fe540122SSamuel Ortiz } 100fe540122SSamuel Ortiz 1015ada3f59SSamuel Ortiz // MOV r/rm is a special case of MOVZX, where both operands have the same size. 1025ada3f59SSamuel Ortiz macro_rules! mov_r_rm { 1035ada3f59SSamuel Ortiz ($op_size:ty) => { 1045ada3f59SSamuel Ortiz movzx!($op_size, $op_size); 1055ada3f59SSamuel Ortiz }; 1065ada3f59SSamuel Ortiz } 1075ada3f59SSamuel Ortiz 108fe540122SSamuel Ortiz macro_rules! mov_r_imm { 1090c3ef986SWei Liu ($bound:ty) => { 110fe540122SSamuel Ortiz fn emulate( 111fe540122SSamuel Ortiz &self, 112fe540122SSamuel Ortiz insn: &Instruction, 113fe540122SSamuel Ortiz state: &mut T, 1140c3ef986SWei Liu platform: &mut dyn PlatformEmulator<CpuState = T>, 115fe540122SSamuel Ortiz ) -> Result<(), EmulationError<Exception>> { 1160c3ef986SWei Liu let imm = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform) 1170c3ef986SWei Liu .map_err(EmulationError::PlatformEmulationError)?; 1180c3ef986SWei Liu 1190c3ef986SWei Liu set_op( 1200c3ef986SWei Liu &insn, 1210c3ef986SWei Liu 0, 1220c3ef986SWei Liu std::mem::size_of::<$bound>(), 1230c3ef986SWei Liu state, 1240c3ef986SWei Liu platform, 1250c3ef986SWei Liu imm, 1260c3ef986SWei Liu ) 127fe540122SSamuel Ortiz .map_err(EmulationError::PlatformEmulationError)?; 128fe540122SSamuel Ortiz 129fe540122SSamuel Ortiz Ok(()) 130fe540122SSamuel Ortiz } 131fe540122SSamuel Ortiz }; 132fe540122SSamuel Ortiz } 133fe540122SSamuel Ortiz 13490ae4676SWei Liu pub struct Mov_r8_rm8; 135fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r8_rm8 { 136fe540122SSamuel Ortiz mov_r_rm!(u8); 137fe540122SSamuel Ortiz } 138fe540122SSamuel Ortiz 13990ae4676SWei Liu pub struct Mov_r8_imm8; 140fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r8_imm8 { 141fe540122SSamuel Ortiz mov_r_imm!(u8); 142fe540122SSamuel Ortiz } 143fe540122SSamuel Ortiz 14490ae4676SWei Liu pub struct Mov_r16_rm16; 145fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r16_rm16 { 146fe540122SSamuel Ortiz mov_r_rm!(u16); 147fe540122SSamuel Ortiz } 148fe540122SSamuel Ortiz 14990ae4676SWei Liu pub struct Mov_r16_imm16; 150fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r16_imm16 { 151fe540122SSamuel Ortiz mov_r_imm!(u16); 152fe540122SSamuel Ortiz } 153fe540122SSamuel Ortiz 15490ae4676SWei Liu pub struct Mov_r32_rm32; 155fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r32_rm32 { 156fe540122SSamuel Ortiz mov_r_rm!(u32); 157fe540122SSamuel Ortiz } 158fe540122SSamuel Ortiz 15990ae4676SWei Liu pub struct Mov_r32_imm32; 160fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r32_imm32 { 161fe540122SSamuel Ortiz mov_r_imm!(u32); 162fe540122SSamuel Ortiz } 163fe540122SSamuel Ortiz 16490ae4676SWei Liu pub struct Mov_r64_rm64; 165fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r64_rm64 { 166fe540122SSamuel Ortiz mov_r_rm!(u64); 167fe540122SSamuel Ortiz } 168fe540122SSamuel Ortiz 16990ae4676SWei Liu pub struct Mov_r64_imm64; 170fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_r64_imm64 { 171fe540122SSamuel Ortiz mov_r_imm!(u64); 172fe540122SSamuel Ortiz } 173fe540122SSamuel Ortiz 17490ae4676SWei Liu pub struct Mov_rm8_imm8; 175fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm8_imm8 { 176fe540122SSamuel Ortiz mov_rm_imm!(u8); 177fe540122SSamuel Ortiz } 178fe540122SSamuel Ortiz 17990ae4676SWei Liu pub struct Mov_rm8_r8; 180fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm8_r8 { 181fe540122SSamuel Ortiz mov_rm_r!(u8); 182fe540122SSamuel Ortiz } 183fe540122SSamuel Ortiz 18490ae4676SWei Liu pub struct Mov_rm16_imm16; 185fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm16_imm16 { 186fe540122SSamuel Ortiz mov_rm_imm!(u16); 187fe540122SSamuel Ortiz } 188fe540122SSamuel Ortiz 18990ae4676SWei Liu pub struct Mov_rm16_r16; 190fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm16_r16 { 191fe540122SSamuel Ortiz mov_rm_r!(u16); 192fe540122SSamuel Ortiz } 193fe540122SSamuel Ortiz 19490ae4676SWei Liu pub struct Mov_rm32_imm32; 195fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm32_imm32 { 196fe540122SSamuel Ortiz mov_rm_imm!(u32); 197fe540122SSamuel Ortiz } 198fe540122SSamuel Ortiz 19990ae4676SWei Liu pub struct Mov_rm32_r32; 200fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm32_r32 { 201fe540122SSamuel Ortiz mov_rm_r!(u32); 202fe540122SSamuel Ortiz } 203fe540122SSamuel Ortiz 20490ae4676SWei Liu pub struct Mov_rm64_imm32; 205fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm64_imm32 { 2060c3ef986SWei Liu mov_rm_imm!(u32); 207fe540122SSamuel Ortiz } 208fe540122SSamuel Ortiz 20990ae4676SWei Liu pub struct Mov_rm64_r64; 210fe540122SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Mov_rm64_r64 { 211fe540122SSamuel Ortiz mov_rm_r!(u64); 212fe540122SSamuel Ortiz } 213fe540122SSamuel Ortiz 2145ada3f59SSamuel Ortiz // MOVZX 2155ada3f59SSamuel Ortiz pub struct Movzx_r16_rm8; 2165ada3f59SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r16_rm8 { 2175ada3f59SSamuel Ortiz movzx!(u16, u8); 2185ada3f59SSamuel Ortiz } 2195ada3f59SSamuel Ortiz 2205ada3f59SSamuel Ortiz pub struct Movzx_r32_rm8; 2215ada3f59SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r32_rm8 { 2225ada3f59SSamuel Ortiz movzx!(u32, u8); 2235ada3f59SSamuel Ortiz } 2245ada3f59SSamuel Ortiz 2255ada3f59SSamuel Ortiz pub struct Movzx_r64_rm8; 2265ada3f59SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r64_rm8 { 2275ada3f59SSamuel Ortiz movzx!(u64, u8); 2285ada3f59SSamuel Ortiz } 2295ada3f59SSamuel Ortiz 2305ada3f59SSamuel Ortiz pub struct Movzx_r32_rm16; 2315ada3f59SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r32_rm16 { 2325ada3f59SSamuel Ortiz movzx!(u32, u16); 2335ada3f59SSamuel Ortiz } 2345ada3f59SSamuel Ortiz 2355ada3f59SSamuel Ortiz pub struct Movzx_r64_rm16; 2365ada3f59SSamuel Ortiz impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r64_rm16 { 2375ada3f59SSamuel Ortiz movzx!(u64, u16); 2385ada3f59SSamuel Ortiz } 2395ada3f59SSamuel Ortiz 240442ac905SPhilipp Schuster pub struct Mov_moffs16_AX; 241442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs16_AX { 242442ac905SPhilipp Schuster movzx!(u16, u16); 243442ac905SPhilipp Schuster } 244442ac905SPhilipp Schuster 245442ac905SPhilipp Schuster pub struct Mov_AX_moffs16; 246442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_AX_moffs16 { 247442ac905SPhilipp Schuster movzx!(u16, u16); 248442ac905SPhilipp Schuster } 249442ac905SPhilipp Schuster 250442ac905SPhilipp Schuster pub struct Mov_moffs32_EAX; 251442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs32_EAX { 252442ac905SPhilipp Schuster movzx!(u32, u32); 253442ac905SPhilipp Schuster } 254442ac905SPhilipp Schuster 255442ac905SPhilipp Schuster pub struct Mov_EAX_moffs32; 256442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_EAX_moffs32 { 257442ac905SPhilipp Schuster movzx!(u32, u32); 258442ac905SPhilipp Schuster } 259442ac905SPhilipp Schuster 260442ac905SPhilipp Schuster pub struct Mov_moffs64_RAX; 261442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs64_RAX { 262442ac905SPhilipp Schuster movzx!(u64, u64); 263442ac905SPhilipp Schuster } 264442ac905SPhilipp Schuster 265442ac905SPhilipp Schuster pub struct Mov_RAX_moffs64; 266442ac905SPhilipp Schuster impl<T: CpuStateManager> InstructionHandler<T> for Mov_RAX_moffs64 { 267442ac905SPhilipp Schuster movzx!(u64, u64); 268442ac905SPhilipp Schuster } 269442ac905SPhilipp Schuster 270fe540122SSamuel Ortiz #[cfg(test)] 271fe540122SSamuel Ortiz mod tests { 272fe540122SSamuel Ortiz use super::*; 2735bd63efaSSamuel Ortiz use crate::arch::x86::emulator::mock_vmm::*; 274fe540122SSamuel Ortiz 275fe540122SSamuel Ortiz #[test] 276fe540122SSamuel Ortiz // mov rax,rbx test_mov_r64_r64()2779c5be6f6SRob Bradford fn test_mov_r64_r64() { 278fe540122SSamuel Ortiz let rbx: u64 = 0x8899aabbccddeeff; 279fe540122SSamuel Ortiz let ip: u64 = 0x1000; 280fe540122SSamuel Ortiz let cpu_id = 0; 281fe540122SSamuel Ortiz let insn = [0x48, 0x89, 0xd8]; 2820c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![(Register::RBX, rbx)], None); 283*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 284fe540122SSamuel Ortiz 285fe540122SSamuel Ortiz let rax: u64 = vmm 286fe540122SSamuel Ortiz .cpu_state(cpu_id) 287fe540122SSamuel Ortiz .unwrap() 288fe540122SSamuel Ortiz .read_reg(Register::RAX) 289fe540122SSamuel Ortiz .unwrap(); 290fe540122SSamuel Ortiz assert_eq!(rax, rbx); 291fe540122SSamuel Ortiz } 292fe540122SSamuel Ortiz 293fe540122SSamuel Ortiz #[test] 294fe540122SSamuel Ortiz // mov rax,0x1122334411223344 test_mov_r64_imm64()2959c5be6f6SRob Bradford fn test_mov_r64_imm64() { 296fe540122SSamuel Ortiz let imm64: u64 = 0x1122334411223344; 297fe540122SSamuel Ortiz let ip: u64 = 0x1000; 298fe540122SSamuel Ortiz let cpu_id = 0; 299fe540122SSamuel Ortiz let insn = [0x48, 0xb8, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11]; 3000c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], None); 301*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 302fe540122SSamuel Ortiz 303fe540122SSamuel Ortiz let rax: u64 = vmm 304fe540122SSamuel Ortiz .cpu_state(cpu_id) 305fe540122SSamuel Ortiz .unwrap() 306fe540122SSamuel Ortiz .read_reg(Register::RAX) 307fe540122SSamuel Ortiz .unwrap(); 308fe540122SSamuel Ortiz assert_eq!(rax, imm64); 309fe540122SSamuel Ortiz } 310fe540122SSamuel Ortiz 311fe540122SSamuel Ortiz #[test] 312fe540122SSamuel Ortiz // mov rax, [rax+rax] test_mov_r64_m64()3139c5be6f6SRob Bradford fn test_mov_r64_m64() { 314fe540122SSamuel Ortiz let target_rax: u64 = 0x1234567812345678; 315fe540122SSamuel Ortiz let mut rax: u64 = 0x100; 316fe540122SSamuel Ortiz let ip: u64 = 0x1000; 317fe540122SSamuel Ortiz let cpu_id = 0; 318fe540122SSamuel Ortiz let memory: [u8; 8] = target_rax.to_le_bytes(); 319fe540122SSamuel Ortiz let insn = [0x48, 0x8b, 0x04, 0x00]; 3200c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![(Register::RAX, rax)], Some((rax + rax, &memory))); 321*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 322fe540122SSamuel Ortiz 323fe540122SSamuel Ortiz rax = vmm 324fe540122SSamuel Ortiz .cpu_state(cpu_id) 325fe540122SSamuel Ortiz .unwrap() 326fe540122SSamuel Ortiz .read_reg(Register::RAX) 327fe540122SSamuel Ortiz .unwrap(); 328fe540122SSamuel Ortiz assert_eq!(rax, target_rax); 329fe540122SSamuel Ortiz } 330fe540122SSamuel Ortiz 331fe540122SSamuel Ortiz #[test] 332fe540122SSamuel Ortiz // mov al,0x11 test_mov_r8_imm8()3339c5be6f6SRob Bradford fn test_mov_r8_imm8() { 334fe540122SSamuel Ortiz let imm8: u8 = 0x11; 335fe540122SSamuel Ortiz let ip: u64 = 0x1000; 336fe540122SSamuel Ortiz let cpu_id = 0; 337fe540122SSamuel Ortiz let insn = [0xb0, 0x11]; 3380c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], None); 339*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 340fe540122SSamuel Ortiz 341fe540122SSamuel Ortiz let al = vmm 342fe540122SSamuel Ortiz .cpu_state(cpu_id) 343fe540122SSamuel Ortiz .unwrap() 344fe540122SSamuel Ortiz .read_reg(Register::AL) 345fe540122SSamuel Ortiz .unwrap(); 346fe540122SSamuel Ortiz assert_eq!(al as u8, imm8); 347fe540122SSamuel Ortiz } 348fe540122SSamuel Ortiz 349fe540122SSamuel Ortiz #[test] 350fe540122SSamuel Ortiz // mov eax,0x11 test_mov_r32_imm8()3519c5be6f6SRob Bradford fn test_mov_r32_imm8() { 352fe540122SSamuel Ortiz let imm8: u8 = 0x11; 353fe540122SSamuel Ortiz let ip: u64 = 0x1000; 354fe540122SSamuel Ortiz let cpu_id = 0; 355fe540122SSamuel Ortiz let insn = [0xb8, 0x11, 0x00, 0x00, 0x00]; 3560c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], None); 357*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 358fe540122SSamuel Ortiz 359fe540122SSamuel Ortiz let eax = vmm 360fe540122SSamuel Ortiz .cpu_state(cpu_id) 361fe540122SSamuel Ortiz .unwrap() 362fe540122SSamuel Ortiz .read_reg(Register::EAX) 363fe540122SSamuel Ortiz .unwrap(); 364fe540122SSamuel Ortiz assert_eq!(eax as u8, imm8); 365fe540122SSamuel Ortiz } 366fe540122SSamuel Ortiz 367fe540122SSamuel Ortiz #[test] 368fe540122SSamuel Ortiz // mov rax,0x11223344 test_mov_r64_imm32()3699c5be6f6SRob Bradford fn test_mov_r64_imm32() { 370fe540122SSamuel Ortiz let imm32: u32 = 0x11223344; 371fe540122SSamuel Ortiz let ip: u64 = 0x1000; 372fe540122SSamuel Ortiz let cpu_id = 0; 373fe540122SSamuel Ortiz let insn = [0x48, 0xc7, 0xc0, 0x44, 0x33, 0x22, 0x11]; 3740c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], None); 375*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 376fe540122SSamuel Ortiz 377fe540122SSamuel Ortiz let rax: u64 = vmm 378fe540122SSamuel Ortiz .cpu_state(cpu_id) 379fe540122SSamuel Ortiz .unwrap() 380fe540122SSamuel Ortiz .read_reg(Register::RAX) 381fe540122SSamuel Ortiz .unwrap(); 382fe540122SSamuel Ortiz assert_eq!(rax, imm32 as u64); 383fe540122SSamuel Ortiz } 384fe540122SSamuel Ortiz 385fe540122SSamuel Ortiz #[test] 386fe540122SSamuel Ortiz // mov byte ptr [rax],dh test_mov_m8_r8()3879c5be6f6SRob Bradford fn test_mov_m8_r8() { 388fe540122SSamuel Ortiz let rax: u64 = 0x100; 389fe540122SSamuel Ortiz let dh: u8 = 0x99; 390fe540122SSamuel Ortiz let ip: u64 = 0x1000; 391fe540122SSamuel Ortiz let cpu_id = 0; 392fe540122SSamuel Ortiz let insn = [0x88, 0x30]; 3930c27f69fSRob Bradford let mut vmm = MockVmm::new( 394fe540122SSamuel Ortiz ip, 395a44d96c9SWei Liu vec![(Register::RAX, rax), (Register::DH, dh.into())], 396fe540122SSamuel Ortiz None, 397fe540122SSamuel Ortiz ); 398*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 399fe540122SSamuel Ortiz 400fe540122SSamuel Ortiz let mut memory: [u8; 1] = [0; 1]; 401c8b65549SWei Liu vmm.read_memory(rax, &mut memory).unwrap(); 402fe540122SSamuel Ortiz 403fe540122SSamuel Ortiz assert_eq!(u8::from_le_bytes(memory), dh); 404fe540122SSamuel Ortiz } 405fe540122SSamuel Ortiz 406fe540122SSamuel Ortiz #[test] 407fe540122SSamuel Ortiz // mov dword ptr [rax],esi test_mov_m32_r32()4089c5be6f6SRob Bradford fn test_mov_m32_r32() { 409fe540122SSamuel Ortiz let rax: u64 = 0x100; 410fe540122SSamuel Ortiz let esi: u32 = 0x8899; 411fe540122SSamuel Ortiz let ip: u64 = 0x1000; 412fe540122SSamuel Ortiz let cpu_id = 0; 413fe540122SSamuel Ortiz let insn = [0x89, 0x30]; 4140c27f69fSRob Bradford let mut vmm = MockVmm::new( 415fe540122SSamuel Ortiz ip, 416a44d96c9SWei Liu vec![(Register::RAX, rax), (Register::ESI, esi.into())], 417fe540122SSamuel Ortiz None, 418fe540122SSamuel Ortiz ); 419*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 420fe540122SSamuel Ortiz 421fe540122SSamuel Ortiz let mut memory: [u8; 4] = [0; 4]; 422c8b65549SWei Liu vmm.read_memory(rax, &mut memory).unwrap(); 423fe540122SSamuel Ortiz 424fe540122SSamuel Ortiz assert_eq!(u32::from_le_bytes(memory), esi); 425fe540122SSamuel Ortiz } 426fe540122SSamuel Ortiz 427fe540122SSamuel Ortiz #[test] 428fe540122SSamuel Ortiz // mov dword ptr [rax+0x00000001],edi test_mov_m32imm32_r32()4299c5be6f6SRob Bradford fn test_mov_m32imm32_r32() { 430fe540122SSamuel Ortiz let rax: u64 = 0x100; 431fe540122SSamuel Ortiz let displacement: u64 = 0x1; 432fe540122SSamuel Ortiz let edi: u32 = 0x8899; 433fe540122SSamuel Ortiz let ip: u64 = 0x1000; 434fe540122SSamuel Ortiz let cpu_id = 0; 435fe540122SSamuel Ortiz let insn = [0x89, 0x3c, 0x05, 0x01, 0x00, 0x00, 0x00]; 4360c27f69fSRob Bradford let mut vmm = MockVmm::new( 437fe540122SSamuel Ortiz ip, 438a44d96c9SWei Liu vec![(Register::RAX, rax), (Register::EDI, edi.into())], 439fe540122SSamuel Ortiz None, 440fe540122SSamuel Ortiz ); 441*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 442fe540122SSamuel Ortiz 443fe540122SSamuel Ortiz let mut memory: [u8; 4] = [0; 4]; 444c8b65549SWei Liu vmm.read_memory(rax + displacement, &mut memory).unwrap(); 445fe540122SSamuel Ortiz 446fe540122SSamuel Ortiz assert_eq!(u32::from_le_bytes(memory), edi); 447fe540122SSamuel Ortiz } 448fe540122SSamuel Ortiz 449fe540122SSamuel Ortiz #[test] 450fe540122SSamuel Ortiz // mov eax,dword ptr [rax+10h] test_mov_r32_m32imm32()4519c5be6f6SRob Bradford fn test_mov_r32_m32imm32() { 452fe540122SSamuel Ortiz let rax: u64 = 0x100; 453fe540122SSamuel Ortiz let displacement: u64 = 0x10; 454fe540122SSamuel Ortiz let eax: u32 = 0xaabbccdd; 455fe540122SSamuel Ortiz let memory: [u8; 4] = eax.to_le_bytes(); 456fe540122SSamuel Ortiz let ip: u64 = 0x1000; 457fe540122SSamuel Ortiz let cpu_id = 0; 458fe540122SSamuel Ortiz let insn = [0x8b, 0x40, 0x10]; 4590c27f69fSRob Bradford let mut vmm = MockVmm::new( 460fe540122SSamuel Ortiz ip, 461a44d96c9SWei Liu vec![(Register::RAX, rax)], 462fe540122SSamuel Ortiz Some((rax + displacement, &memory)), 463fe540122SSamuel Ortiz ); 464*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 465fe540122SSamuel Ortiz 466fe540122SSamuel Ortiz let new_eax = vmm 467fe540122SSamuel Ortiz .cpu_state(cpu_id) 468fe540122SSamuel Ortiz .unwrap() 469fe540122SSamuel Ortiz .read_reg(Register::EAX) 470fe540122SSamuel Ortiz .unwrap(); 471fe540122SSamuel Ortiz assert_eq!(new_eax, eax as u64); 472fe540122SSamuel Ortiz } 473fe540122SSamuel Ortiz 474fe540122SSamuel Ortiz #[test] 475fe540122SSamuel Ortiz // mov al,byte ptr [rax+10h] test_mov_r8_m32imm32()4769c5be6f6SRob Bradford fn test_mov_r8_m32imm32() { 477fe540122SSamuel Ortiz let rax: u64 = 0x100; 478fe540122SSamuel Ortiz let displacement: u64 = 0x10; 479fe540122SSamuel Ortiz let al: u8 = 0xaa; 480fe540122SSamuel Ortiz let ip: u64 = 0x1000; 481fe540122SSamuel Ortiz let cpu_id = 0; 482fe540122SSamuel Ortiz let insn = [0x8a, 0x40, 0x10]; 483fe540122SSamuel Ortiz let memory: [u8; 1] = al.to_le_bytes(); 4840c27f69fSRob Bradford let mut vmm = MockVmm::new( 485fe540122SSamuel Ortiz ip, 486a44d96c9SWei Liu vec![(Register::RAX, rax)], 487fe540122SSamuel Ortiz Some((rax + displacement, &memory)), 488fe540122SSamuel Ortiz ); 489*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 490fe540122SSamuel Ortiz 491fe540122SSamuel Ortiz let new_al = vmm 492fe540122SSamuel Ortiz .cpu_state(cpu_id) 493fe540122SSamuel Ortiz .unwrap() 494fe540122SSamuel Ortiz .read_reg(Register::AL) 495fe540122SSamuel Ortiz .unwrap(); 496fe540122SSamuel Ortiz assert_eq!(new_al, al as u64); 497fe540122SSamuel Ortiz } 498fe540122SSamuel Ortiz 499fe540122SSamuel Ortiz #[test] 500fe540122SSamuel Ortiz // mov rax, 0x100 501fe540122SSamuel Ortiz // mov rbx, qword ptr [rax+10h] test_mov_r64_imm64_and_r64_m64()5029c5be6f6SRob Bradford fn test_mov_r64_imm64_and_r64_m64() { 503fe540122SSamuel Ortiz let target_rax: u64 = 0x1234567812345678; 504fe540122SSamuel Ortiz let rax: u64 = 0x100; 505fe540122SSamuel Ortiz let displacement: u64 = 0x10; 506fe540122SSamuel Ortiz let ip: u64 = 0x1000; 507fe540122SSamuel Ortiz let cpu_id = 0; 508fe540122SSamuel Ortiz let memory: [u8; 8] = target_rax.to_le_bytes(); 509fe540122SSamuel Ortiz let insn = [ 510fe540122SSamuel Ortiz 0x48, 0xc7, 0xc0, 0x00, 0x01, 0x00, 0x00, // mov rax, 0x100 511fe540122SSamuel Ortiz 0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h] 512fe540122SSamuel Ortiz ]; 5130c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], Some((rax + displacement, &memory))); 514*297236a7SRuoqing He vmm.emulate_insn(cpu_id, &insn, Some(2)).unwrap(); 515fe540122SSamuel Ortiz 516fe540122SSamuel Ortiz let rbx: u64 = vmm 517fe540122SSamuel Ortiz .cpu_state(cpu_id) 518fe540122SSamuel Ortiz .unwrap() 519fe540122SSamuel Ortiz .read_reg(Register::RBX) 520fe540122SSamuel Ortiz .unwrap(); 521fe540122SSamuel Ortiz assert_eq!(rbx, target_rax); 522fe540122SSamuel Ortiz } 523fe540122SSamuel Ortiz 524fe540122SSamuel Ortiz #[test] 525fe540122SSamuel Ortiz // mov rax, 0x100 526fe540122SSamuel Ortiz // mov rbx, qword ptr [rax+10h] test_mov_r64_imm64_and_r64_m64_first_insn()5279c5be6f6SRob Bradford fn test_mov_r64_imm64_and_r64_m64_first_insn() { 528fe540122SSamuel Ortiz let target_rax: u64 = 0x1234567812345678; 529fe540122SSamuel Ortiz let rax: u64 = 0x100; 530fe540122SSamuel Ortiz let displacement: u64 = 0x10; 531fe540122SSamuel Ortiz let ip: u64 = 0x1000; 532fe540122SSamuel Ortiz let cpu_id = 0; 533fe540122SSamuel Ortiz let memory: [u8; 8] = target_rax.to_le_bytes(); 534fe540122SSamuel Ortiz let insn = [ 535fe540122SSamuel Ortiz 0x48, 0xc7, 0xc0, 0x00, 0x01, 0x00, 0x00, // mov rax, 0x100 536fe540122SSamuel Ortiz 0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h] 537fe540122SSamuel Ortiz ]; 538fe540122SSamuel Ortiz 5390c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], Some((rax + displacement, &memory))); 540fe540122SSamuel Ortiz // Only run the first instruction. 541*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 542fe540122SSamuel Ortiz 543fabd6307SRob Bradford assert_eq!(ip + 7, vmm.cpu_state(cpu_id).unwrap().ip()); 544fe540122SSamuel Ortiz 545fe540122SSamuel Ortiz let new_rax: u64 = vmm 546fe540122SSamuel Ortiz .cpu_state(cpu_id) 547fe540122SSamuel Ortiz .unwrap() 548fe540122SSamuel Ortiz .read_reg(Register::RAX) 549fe540122SSamuel Ortiz .unwrap(); 550fe540122SSamuel Ortiz assert_eq!(rax, new_rax); 551fe540122SSamuel Ortiz } 552fe540122SSamuel Ortiz 553fe540122SSamuel Ortiz #[test] 554fe540122SSamuel Ortiz // mov rax, 0x100 555fe540122SSamuel Ortiz // mov rbx, qword ptr [rax+10h] 556fe540122SSamuel Ortiz // mov rax, 0x200 test_mov_r64_imm64_and_r64_m64_two_insns()5579c5be6f6SRob Bradford fn test_mov_r64_imm64_and_r64_m64_two_insns() { 558fe540122SSamuel Ortiz let target_rax: u64 = 0x1234567812345678; 559fe540122SSamuel Ortiz let rax: u64 = 0x100; 560fe540122SSamuel Ortiz let displacement: u64 = 0x10; 561fe540122SSamuel Ortiz let ip: u64 = 0x1000; 562fe540122SSamuel Ortiz let cpu_id = 0; 563fe540122SSamuel Ortiz let memory: [u8; 8] = target_rax.to_le_bytes(); 564fe540122SSamuel Ortiz let insn = [ 565fe540122SSamuel Ortiz 0x48, 0xc7, 0xc0, 0x00, 0x01, 0x00, 0x00, // mov rax, 0x100 566fe540122SSamuel Ortiz 0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h] 567fe540122SSamuel Ortiz 0x48, 0xc7, 0xc0, 0x00, 0x02, 0x00, 0x00, // mov rax, 0x200 568fe540122SSamuel Ortiz ]; 569fe540122SSamuel Ortiz 5700c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![], Some((rax + displacement, &memory))); 571a3d957baSSamuel Ortiz // Run the 2 first instructions. 572*297236a7SRuoqing He vmm.emulate_insn(cpu_id, &insn, Some(2)).unwrap(); 573fe540122SSamuel Ortiz 574fabd6307SRob Bradford assert_eq!(ip + 7 + 4, vmm.cpu_state(cpu_id).unwrap().ip()); 575fe540122SSamuel Ortiz 576fe540122SSamuel Ortiz let rbx: u64 = vmm 577fe540122SSamuel Ortiz .cpu_state(cpu_id) 578fe540122SSamuel Ortiz .unwrap() 579fe540122SSamuel Ortiz .read_reg(Register::RBX) 580fe540122SSamuel Ortiz .unwrap(); 581fe540122SSamuel Ortiz assert_eq!(rbx, target_rax); 582fe540122SSamuel Ortiz 583fe540122SSamuel Ortiz // Check that rax is still at 0x100 584fe540122SSamuel Ortiz let new_rax: u64 = vmm 585fe540122SSamuel Ortiz .cpu_state(cpu_id) 586fe540122SSamuel Ortiz .unwrap() 587fe540122SSamuel Ortiz .read_reg(Register::RAX) 588fe540122SSamuel Ortiz .unwrap(); 589fe540122SSamuel Ortiz assert_eq!(rax, new_rax); 590fe540122SSamuel Ortiz } 591eee218f1SSamuel Ortiz 592eee218f1SSamuel Ortiz #[test] 593eee218f1SSamuel Ortiz // movzx eax, bl test_movzx_r32_r8l()5949c5be6f6SRob Bradford fn test_movzx_r32_r8l() { 595eee218f1SSamuel Ortiz let bx: u16 = 0x8899; 596eee218f1SSamuel Ortiz let ip: u64 = 0x1000; 597eee218f1SSamuel Ortiz let cpu_id = 0; 598eee218f1SSamuel Ortiz let insn = [0x0f, 0xb6, 0xc3]; 5990c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![(Register::BX, bx as u64)], None); 600*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 601eee218f1SSamuel Ortiz 602eee218f1SSamuel Ortiz let eax: u64 = vmm 603eee218f1SSamuel Ortiz .cpu_state(cpu_id) 604eee218f1SSamuel Ortiz .unwrap() 605eee218f1SSamuel Ortiz .read_reg(Register::EAX) 606eee218f1SSamuel Ortiz .unwrap(); 607eee218f1SSamuel Ortiz assert_eq!(eax, (bx & 0xff) as u64); 608eee218f1SSamuel Ortiz } 609eee218f1SSamuel Ortiz 610eee218f1SSamuel Ortiz #[test] 611eee218f1SSamuel Ortiz // movzx eax, bh test_movzx_r32_r8h()6129c5be6f6SRob Bradford fn test_movzx_r32_r8h() { 613eee218f1SSamuel Ortiz let bx: u16 = 0x8899; 614eee218f1SSamuel Ortiz let ip: u64 = 0x1000; 615eee218f1SSamuel Ortiz let cpu_id = 0; 616eee218f1SSamuel Ortiz let insn = [0x0f, 0xb6, 0xc7]; 6170c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![(Register::BX, bx as u64)], None); 618*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 619eee218f1SSamuel Ortiz 620eee218f1SSamuel Ortiz let eax: u64 = vmm 621eee218f1SSamuel Ortiz .cpu_state(cpu_id) 622eee218f1SSamuel Ortiz .unwrap() 623eee218f1SSamuel Ortiz .read_reg(Register::EAX) 624eee218f1SSamuel Ortiz .unwrap(); 625eee218f1SSamuel Ortiz assert_eq!(eax, (bx >> 8) as u64); 626eee218f1SSamuel Ortiz } 627eee218f1SSamuel Ortiz 628eee218f1SSamuel Ortiz #[test] 629eee218f1SSamuel Ortiz // movzx eax, byte ptr [rbx] test_movzx_r32_m8()6309c5be6f6SRob Bradford fn test_movzx_r32_m8() { 631eee218f1SSamuel Ortiz let rbx: u64 = 0x100; 632eee218f1SSamuel Ortiz let value: u8 = 0xaa; 633eee218f1SSamuel Ortiz let ip: u64 = 0x1000; 634eee218f1SSamuel Ortiz let cpu_id = 0; 635eee218f1SSamuel Ortiz let insn = [0x0f, 0xb7, 0x03]; 636eee218f1SSamuel Ortiz let memory: [u8; 1] = value.to_le_bytes(); 6370c27f69fSRob Bradford let mut vmm = MockVmm::new(ip, vec![(Register::RBX, rbx)], Some((rbx, &memory))); 638*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &insn).unwrap(); 639eee218f1SSamuel Ortiz 640eee218f1SSamuel Ortiz let eax: u64 = vmm 641eee218f1SSamuel Ortiz .cpu_state(cpu_id) 642eee218f1SSamuel Ortiz .unwrap() 643eee218f1SSamuel Ortiz .read_reg(Register::EAX) 644eee218f1SSamuel Ortiz .unwrap(); 645eee218f1SSamuel Ortiz assert_eq!(eax, value as u64); 646eee218f1SSamuel Ortiz } 647442ac905SPhilipp Schuster 648442ac905SPhilipp Schuster #[test] 649442ac905SPhilipp Schuster // movabs ax, ds:0x1337 650442ac905SPhilipp Schuster // movabs eax, ds:0x1337 651442ac905SPhilipp Schuster // movabs rax, ds:0x1337 test_mov_memoff_ax()652442ac905SPhilipp Schuster fn test_mov_memoff_ax() { 653442ac905SPhilipp Schuster let test_inputs: [(Register, &[u8]); 3] = [ 654442ac905SPhilipp Schuster (Register::AX, &[0x66, 0xa1]), 655442ac905SPhilipp Schuster (Register::EAX, &[0xa1]), 656442ac905SPhilipp Schuster (Register::RAX, &[0x48, 0xa1]), 657442ac905SPhilipp Schuster ]; 658442ac905SPhilipp Schuster 659442ac905SPhilipp Schuster // Constructs the instruction with the provided inputs and emulates it. 660442ac905SPhilipp Schuster fn helper(register: Register, instruction_prefix: &[u8]) { 661442ac905SPhilipp Schuster let mem_addr: u64 = 0x1337; 662442ac905SPhilipp Schuster let mem_value: u64 = 0x13371337deadbeef; 663442ac905SPhilipp Schuster let ip: u64 = 0x1000; 664442ac905SPhilipp Schuster let cpu_id = 0; 665442ac905SPhilipp Schuster 666442ac905SPhilipp Schuster let mut instruction_bytes = Vec::new(); 667442ac905SPhilipp Schuster // instruction prefix with specified register 668442ac905SPhilipp Schuster instruction_bytes.extend(instruction_prefix); 669442ac905SPhilipp Schuster // 64-bit memory operand 670442ac905SPhilipp Schuster instruction_bytes.extend([ 671442ac905SPhilipp Schuster mem_addr.to_le_bytes()[0], 672442ac905SPhilipp Schuster mem_addr.to_le_bytes()[1], 673442ac905SPhilipp Schuster 0, 674442ac905SPhilipp Schuster 0, 675442ac905SPhilipp Schuster 0, 676442ac905SPhilipp Schuster 0, 677442ac905SPhilipp Schuster 0, 678442ac905SPhilipp Schuster 0, 679442ac905SPhilipp Schuster ]); 680442ac905SPhilipp Schuster 681442ac905SPhilipp Schuster let memory: [u8; 8] = mem_value.to_le_bytes(); 682442ac905SPhilipp Schuster let mut vmm = MockVmm::new(ip, vec![], Some((mem_addr, &memory))); 683*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &instruction_bytes).unwrap(); 684442ac905SPhilipp Schuster 685442ac905SPhilipp Schuster let ax: u64 = vmm.cpu_state(cpu_id).unwrap().read_reg(register).unwrap(); 686442ac905SPhilipp Schuster 687442ac905SPhilipp Schuster match register { 688442ac905SPhilipp Schuster Register::AX => { 689442ac905SPhilipp Schuster assert_eq!(ax as u16, mem_value as u16); 690442ac905SPhilipp Schuster } 691442ac905SPhilipp Schuster Register::EAX => { 692442ac905SPhilipp Schuster assert_eq!(ax as u32, mem_value as u32); 693442ac905SPhilipp Schuster } 694442ac905SPhilipp Schuster Register::RAX => { 695442ac905SPhilipp Schuster assert_eq!(ax, mem_value); 696442ac905SPhilipp Schuster } 697442ac905SPhilipp Schuster _ => panic!(), 698442ac905SPhilipp Schuster } 699442ac905SPhilipp Schuster } 700442ac905SPhilipp Schuster 701442ac905SPhilipp Schuster for (register, instruction_prefix) in test_inputs { 702442ac905SPhilipp Schuster helper(register, instruction_prefix) 703442ac905SPhilipp Schuster } 704442ac905SPhilipp Schuster } 705442ac905SPhilipp Schuster 706442ac905SPhilipp Schuster #[test] 707442ac905SPhilipp Schuster // movabs ds:0x1337, ax 708442ac905SPhilipp Schuster // movabs ds:0x1337, eax 709442ac905SPhilipp Schuster // movabs ds:0x1337, rax test_mov_ax_memoff()710442ac905SPhilipp Schuster fn test_mov_ax_memoff() { 711442ac905SPhilipp Schuster let test_inputs: [(Register, &[u8]); 3] = [ 712442ac905SPhilipp Schuster (Register::AX, &[0x66, 0xa3]), 713442ac905SPhilipp Schuster (Register::EAX, &[0xa3]), 714442ac905SPhilipp Schuster (Register::RAX, &[0x48, 0xa3]), 715442ac905SPhilipp Schuster ]; 716442ac905SPhilipp Schuster 717442ac905SPhilipp Schuster // Constructs the instruction with the provided inputs and emulates it. 718442ac905SPhilipp Schuster fn helper(register: Register, instruction_prefix: &[u8]) { 719442ac905SPhilipp Schuster let mem_addr: u64 = 0x1337; 720442ac905SPhilipp Schuster let ax: u64 = 0x13371337deadbeef; 721442ac905SPhilipp Schuster let ip: u64 = 0x1000; 722442ac905SPhilipp Schuster let cpu_id = 0; 723442ac905SPhilipp Schuster 724442ac905SPhilipp Schuster let mut instruction_bytes = Vec::new(); 725442ac905SPhilipp Schuster // instruction prefix with specified register 726442ac905SPhilipp Schuster instruction_bytes.extend(instruction_prefix); 727442ac905SPhilipp Schuster // 64-bit memory operand 728442ac905SPhilipp Schuster instruction_bytes.extend([ 729442ac905SPhilipp Schuster mem_addr.to_le_bytes()[0], 730442ac905SPhilipp Schuster mem_addr.to_le_bytes()[1], 731442ac905SPhilipp Schuster 0, 732442ac905SPhilipp Schuster 0, 733442ac905SPhilipp Schuster 0, 734442ac905SPhilipp Schuster 0, 735442ac905SPhilipp Schuster 0, 736442ac905SPhilipp Schuster 0, 737442ac905SPhilipp Schuster ]); 738442ac905SPhilipp Schuster 739442ac905SPhilipp Schuster let mut vmm = MockVmm::new(ip, vec![(Register::RAX, ax)], None); 740*297236a7SRuoqing He vmm.emulate_first_insn(cpu_id, &instruction_bytes).unwrap(); 741442ac905SPhilipp Schuster 742442ac905SPhilipp Schuster match register { 743442ac905SPhilipp Schuster Register::AX => { 744442ac905SPhilipp Schuster let mut memory: [u8; 2] = [0; 2]; 745442ac905SPhilipp Schuster vmm.read_memory(mem_addr, &mut memory).unwrap(); 746442ac905SPhilipp Schuster assert_eq!(u16::from_le_bytes(memory), ax as u16); 747442ac905SPhilipp Schuster } 748442ac905SPhilipp Schuster Register::EAX => { 749442ac905SPhilipp Schuster let mut memory: [u8; 4] = [0; 4]; 750442ac905SPhilipp Schuster vmm.read_memory(mem_addr, &mut memory).unwrap(); 751442ac905SPhilipp Schuster assert_eq!(u32::from_le_bytes(memory), ax as u32); 752442ac905SPhilipp Schuster } 753442ac905SPhilipp Schuster Register::RAX => { 754442ac905SPhilipp Schuster let mut memory: [u8; 8] = [0; 8]; 755442ac905SPhilipp Schuster vmm.read_memory(mem_addr, &mut memory).unwrap(); 756442ac905SPhilipp Schuster assert_eq!(u64::from_le_bytes(memory), ax); 757442ac905SPhilipp Schuster } 758442ac905SPhilipp Schuster _ => panic!(), 759442ac905SPhilipp Schuster } 760442ac905SPhilipp Schuster } 761442ac905SPhilipp Schuster 762442ac905SPhilipp Schuster for (register, instruction_prefix) in test_inputs { 763442ac905SPhilipp Schuster helper(register, instruction_prefix) 764442ac905SPhilipp Schuster } 765442ac905SPhilipp Schuster } 766fe540122SSamuel Ortiz } 767