1 // 2 // Copyright © 2020 Intel Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError}; 8 use crate::arch::x86::emulator::CpuStateManager; 9 use crate::arch::x86::Exception; 10 use iced_x86::*; 11 12 pub mod cmp; 13 pub mod mov; 14 pub mod movs; 15 pub mod or; 16 pub mod stos; 17 18 fn get_op<T: CpuStateManager>( 19 insn: &Instruction, 20 op_index: u32, 21 op_size: usize, 22 state: &T, 23 platform: &dyn PlatformEmulator<CpuState = T>, 24 ) -> Result<u64, PlatformError> { 25 if insn.op_count() < op_index + 1 { 26 return Err(PlatformError::InvalidOperand(anyhow!( 27 "Invalid operand {:?}", 28 op_index 29 ))); 30 } 31 32 if !matches!(op_size, 1 | 2 | 4 | 8) { 33 return Err(PlatformError::InvalidOperand(anyhow!( 34 "Invalid operand size {:?}", 35 op_size 36 ))); 37 } 38 39 let value = match insn 40 .try_op_kind(op_index) 41 .map_err(|e| PlatformError::InvalidOperand(e.into()))? 42 { 43 OpKind::Register => state.read_reg( 44 insn.try_op_register(op_index) 45 .map_err(|e| PlatformError::InvalidOperand(e.into()))?, 46 )?, 47 OpKind::Memory => { 48 let addr = memory_operand_address(insn, state, false)?; 49 let mut memory: [u8; 8] = [0; 8]; 50 platform.read_memory(addr, &mut memory[0..op_size])?; 51 <u64>::from_le_bytes(memory) 52 } 53 OpKind::Immediate8 => insn.immediate8() as u64, 54 OpKind::Immediate8to16 => insn.immediate8to16() as u64, 55 OpKind::Immediate8to32 => insn.immediate8to32() as u64, 56 OpKind::Immediate8to64 => insn.immediate8to64() as u64, 57 OpKind::Immediate16 => insn.immediate16() as u64, 58 OpKind::Immediate32 => insn.immediate32() as u64, 59 OpKind::Immediate32to64 => insn.immediate32to64() as u64, 60 OpKind::Immediate64 => insn.immediate64(), 61 k => return Err(PlatformError::InvalidOperand(anyhow!("{:?}", k))), 62 }; 63 64 Ok(value) 65 } 66 67 fn set_op<T: CpuStateManager>( 68 insn: &Instruction, 69 op_index: u32, 70 op_size: usize, 71 state: &mut T, 72 platform: &mut dyn PlatformEmulator<CpuState = T>, 73 value: u64, 74 ) -> Result<(), PlatformError> { 75 if insn.op_count() < op_index + 1 { 76 return Err(PlatformError::InvalidOperand(anyhow!( 77 "Invalid operand {:?}", 78 op_index 79 ))); 80 } 81 82 if !matches!(op_size, 1 | 2 | 4 | 8) { 83 return Err(PlatformError::InvalidOperand(anyhow!( 84 "Invalid operand size {:?}", 85 op_size 86 ))); 87 } 88 89 match insn 90 .try_op_kind(op_index) 91 .map_err(|e| PlatformError::InvalidOperand(e.into()))? 92 { 93 OpKind::Register => state.write_reg( 94 insn.try_op_register(op_index) 95 .map_err(|e| PlatformError::InvalidOperand(e.into()))?, 96 value, 97 )?, 98 OpKind::Memory => { 99 let addr = memory_operand_address(insn, state, true)?; 100 platform.write_memory(addr, &value.to_le_bytes()[..op_size])?; 101 } 102 k => return Err(PlatformError::InvalidOperand(anyhow!("{:?}", k))), 103 }; 104 105 Ok(()) 106 } 107 108 // Returns the linear a.k.a. virtual address for a memory operand. 109 fn memory_operand_address<T: CpuStateManager>( 110 insn: &Instruction, 111 state: &T, 112 write: bool, 113 ) -> Result<u64, PlatformError> { 114 let mut address: u64 = 0; 115 116 if insn.memory_base() != iced_x86::Register::None { 117 let base: u64 = state.read_reg(insn.memory_base())?; 118 address += base; 119 } 120 121 if insn.memory_index() != iced_x86::Register::None { 122 let mut index: u64 = state.read_reg(insn.memory_index())?; 123 index *= insn.memory_index_scale() as u64; 124 125 address += index; 126 } 127 128 address = address.wrapping_add(insn.memory_displacement64()); 129 130 // Translate to a linear address. 131 state.linearize(insn.memory_segment(), address, write) 132 } 133 134 pub trait InstructionHandler<T: CpuStateManager> { 135 fn emulate( 136 &self, 137 insn: &Instruction, 138 state: &mut T, 139 platform: &mut dyn PlatformEmulator<CpuState = T>, 140 ) -> Result<(), EmulationError<Exception>>; 141 } 142 143 macro_rules! insn_format { 144 ($insn:ident) => {{ 145 let mut output = String::new(); 146 let mut formatter = FastFormatter::new(); 147 formatter 148 .options_mut() 149 .set_space_after_operand_separator(true); 150 formatter.format(&$insn, &mut output); 151 152 output 153 }}; 154 } 155