use crate::arch::x86::{DecodedInsn, Mnemonic, format_intel};
use crate::ast::Stmt;
use super::{Candidate, Pattern, PatternCtx};
pub struct Imul;
impl Pattern for Imul {
fn name(&self) -> &'static str {
"imul"
}
fn tentative(
&self,
ctx: &PatternCtx,
insns: &[DecodedInsn],
start: usize,
) -> Option<Candidate> {
let ins = insns.get(start)?;
if ins.iced.mnemonic() != Mnemonic::Imul {
return None;
}
let op_count = ins.iced.op_count();
let full = format_intel(&ins.iced);
let rest = full.strip_prefix("imul ")?;
let parts: Vec<&str> = rest.split(',').map(str::trim).collect();
let sp = ctx.sp_delta_at.get(&ins.iced.ip()).copied();
let parts: Vec<String> = parts
.iter()
.map(|p| crate::arch::x86::rename_operand_in_ctx(p, sp))
.collect();
let (dst, src) = match op_count {
2 => {
if parts.len() != 2 {
return None;
}
let dst = parts[0].clone();
let src = format!("{} * {}", parts[0], parts[1]);
(dst, src)
}
3 => {
if parts.len() != 3 {
return None;
}
let dst = parts[0].clone();
let src = format!("{} * {}", parts[1], parts[2]);
(dst, src)
}
_ => return None,
};
Some(Candidate {
pattern: self.name(),
start,
consumed: 1,
priority: 50,
stmts: vec![Stmt::Move {
dst,
src,
bytes: ins.original_bytes.clone(),
}],
})
}
}