1 // 2 // Copyright © 2020 Intel Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 extern crate iced_x86; 8 9 use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError}; 10 use crate::arch::x86::emulator::CpuStateManager; 11 use crate::arch::x86::Exception; 12 use iced_x86::*; 13 use std::collections::HashMap; 14 use std::sync::{Arc, Mutex}; 15 16 pub mod mov; 17 18 // Returns the linear a.k.a. virtual address for a memory operand. 19 fn memory_operand_address<T: CpuStateManager>( 20 insn: &Instruction, 21 state: &T, 22 ) -> Result<u64, PlatformError> { 23 let mut address: u64 = 0; 24 25 // Get the DS or override segment base first 26 let segment_base = state.read_segment(insn.memory_segment())?.base; 27 address += segment_base; 28 29 if insn.memory_base() != iced_x86::Register::None { 30 let base: u64 = state.read_reg(insn.memory_base())?; 31 address += base; 32 } 33 34 if insn.memory_index() != iced_x86::Register::None { 35 let mut index: u64 = state.read_reg(insn.memory_index())?; 36 index *= insn.memory_index_scale() as u64; 37 38 address += index; 39 } 40 41 address += insn.memory_displacement() as u64; 42 43 Ok(address) 44 } 45 46 pub trait InstructionHandler<T: CpuStateManager> { 47 fn emulate( 48 &self, 49 insn: &Instruction, 50 state: &mut T, 51 platform: Arc<Mutex<dyn PlatformEmulator<CpuState = T>>>, 52 ) -> Result<(), EmulationError<Exception>>; 53 } 54 55 pub struct InstructionMap<T: CpuStateManager> { 56 pub instructions: HashMap<Code, Box<Box<dyn InstructionHandler<T> + Sync + Send>>>, 57 } 58 59 impl<T: CpuStateManager> InstructionMap<T> { 60 pub fn new() -> InstructionMap<T> { 61 InstructionMap { 62 instructions: HashMap::new(), 63 } 64 } 65 66 pub fn add_insn( 67 &mut self, 68 insn: Code, 69 insn_handler: Box<dyn InstructionHandler<T> + Sync + Send>, 70 ) { 71 self.instructions.insert(insn, Box::new(insn_handler)); 72 } 73 } 74 75 impl<T: CpuStateManager> Default for InstructionMap<T> { 76 fn default() -> Self { 77 Self::new() 78 } 79 } 80 81 macro_rules! insn_add { 82 ($insn_map:ident, $mnemonic:ident, $code:ident) => { 83 $insn_map.add_insn(Code::$code, Box::new($mnemonic::$code {})); 84 }; 85 } 86