diff --git a/x86/src/ops/math.rs b/x86/src/ops/math.rs index 59462d72..91dd71ca 100644 --- a/x86/src/ops/math.rs +++ b/x86/src/ops/math.rs @@ -2,7 +2,10 @@ use super::helpers::*; use crate::{registers::Flags, x86::CPU}; use iced_x86::{Instruction, Register}; use memory::Mem; -use num_traits::ops::overflowing::OverflowingSub; +use num_traits::{ + ops::overflowing::{OverflowingMul, OverflowingSub}, + Signed, +}; /// This trait is implemented for u32/u16/u8 and lets us write operations generically /// over all those bit sizes. @@ -808,9 +811,13 @@ pub fn imul_rm8(cpu: &mut CPU, mem: Mem, instr: &Instruction) { cpu.regs.set16(Register::AX, res); } -fn imul_trunc(x: i32, y: i32, _flags: &mut Flags) -> i32 { - // TODO: flags. - x.wrapping_mul(y) +fn imul_trunc(x: I, y: I, flags: &mut Flags) -> I { + let (result, flag) = x.overflowing_mul(&y); + + flags.set(Flags::OF, flag); + flags.set(Flags::CF, flag); + + result } pub fn imul_r32_rm32(cpu: &mut CPU, mem: Mem, instr: &Instruction) { @@ -834,6 +841,13 @@ pub fn imul_r32_rm32_imm8(cpu: &mut CPU, mem: Mem, instr: &Instruction) { cpu.regs.set32(instr.op0_register(), value as u32); } +pub fn imul_r16_rm16(cpu: &mut CPU, mem: Mem, instr: &Instruction) { + let x = cpu.regs.get16(instr.op0_register()) as i16; + let y = op1_rm16(cpu, mem, instr) as i16; + let value = imul_trunc(x, y, &mut cpu.flags); + cpu.regs.set16(instr.op0_register(), value as u16); +} + pub fn idiv_rm32(cpu: &mut CPU, mem: Mem, instr: &Instruction) { let x = get_edx_eax(cpu) as i64; let y = rm32(cpu, mem, instr).get() as i32 as i64; diff --git a/x86/src/ops/table.rs b/x86/src/ops/table.rs index da2be50c..39a0ea4f 100644 --- a/x86/src/ops/table.rs +++ b/x86/src/ops/table.rs @@ -264,6 +264,7 @@ const OP_TAB: [Option; 2553] = { tab[iced_x86::Code::Imul_r32_rm32 as usize] = Some(imul_r32_rm32); tab[iced_x86::Code::Imul_r32_rm32_imm32 as usize] = Some(imul_r32_rm32_imm32); tab[iced_x86::Code::Imul_r32_rm32_imm8 as usize] = Some(imul_r32_rm32_imm8); + tab[iced_x86::Code::Imul_r16_rm16 as usize] = Some(imul_r16_rm16); tab[iced_x86::Code::Idiv_rm32 as usize] = Some(idiv_rm32); tab[iced_x86::Code::Idiv_rm16 as usize] = Some(idiv_rm16); tab[iced_x86::Code::Idiv_rm8 as usize] = Some(idiv_rm8);