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