use crate::arch::x86::{DecodedInsn, Mnemonic, format_intel};
use crate::ast::Stmt;
use super::{Candidate, Pattern, PatternCtx};
pub struct SimdExpr;
impl Pattern for SimdExpr {
fn name(&self) -> &'static str {
"simd_expr"
}
fn tentative(
&self,
_ctx: &PatternCtx,
insns: &[DecodedInsn],
start: usize,
) -> Option<Candidate> {
let ins = insns.get(start)?;
let shape = classify(ins.iced.mnemonic())?;
let full = format_intel(&ins.iced);
let (prefix_len, kind) = match shape {
Shape::Move(prefix) => (prefix.len(), Op::Move),
Shape::Binary(prefix, op) => (prefix.len(), Op::Binary(op)),
};
let rest = full.get(prefix_len..)?;
let (dst, src) = super::mov::split_two_operands(&full, &full[..prefix_len])?;
let _ = rest;
let new_src = match kind {
Op::Move => src,
Op::Binary(op) => format!("{dst} {op} {src}"),
};
Some(Candidate {
pattern: self.name(),
start,
consumed: 1,
priority: 30,
stmts: vec![Stmt::Move {
dst,
src: new_src,
bytes: ins.original_bytes.clone(),
}],
})
}
}
enum Shape {
Move(&'static str),
Binary(&'static str, &'static str),
}
enum Op {
Move,
Binary(&'static str),
}
#[allow(clippy::too_many_lines)]
fn classify(m: Mnemonic) -> Option<Shape> {
Some(match m {
Mnemonic::Movq => Shape::Move("movq "),
Mnemonic::Movd => Shape::Move("movd "),
Mnemonic::Movaps => Shape::Move("movaps "),
Mnemonic::Movups => Shape::Move("movups "),
Mnemonic::Movapd => Shape::Move("movapd "),
Mnemonic::Movupd => Shape::Move("movupd "),
Mnemonic::Movdqa => Shape::Move("movdqa "),
Mnemonic::Movdqu => Shape::Move("movdqu "),
Mnemonic::Movss => Shape::Move("movss "),
Mnemonic::Movsd => Shape::Move("movsd "),
Mnemonic::Movhps => Shape::Move("movhps "),
Mnemonic::Movlps => Shape::Move("movlps "),
Mnemonic::Movhpd => Shape::Move("movhpd "),
Mnemonic::Movlpd => Shape::Move("movlpd "),
Mnemonic::Paddb => Shape::Binary("paddb ", "+"),
Mnemonic::Paddw => Shape::Binary("paddw ", "+"),
Mnemonic::Paddd => Shape::Binary("paddd ", "+"),
Mnemonic::Paddq => Shape::Binary("paddq ", "+"),
Mnemonic::Paddsb => Shape::Binary("paddsb ", "+"),
Mnemonic::Paddsw => Shape::Binary("paddsw ", "+"),
Mnemonic::Paddusb => Shape::Binary("paddusb ", "+"),
Mnemonic::Paddusw => Shape::Binary("paddusw ", "+"),
Mnemonic::Psubb => Shape::Binary("psubb ", "-"),
Mnemonic::Psubw => Shape::Binary("psubw ", "-"),
Mnemonic::Psubd => Shape::Binary("psubd ", "-"),
Mnemonic::Psubq => Shape::Binary("psubq ", "-"),
Mnemonic::Psubsb => Shape::Binary("psubsb ", "-"),
Mnemonic::Psubsw => Shape::Binary("psubsw ", "-"),
Mnemonic::Psubusb => Shape::Binary("psubusb ", "-"),
Mnemonic::Psubusw => Shape::Binary("psubusw ", "-"),
Mnemonic::Pmullw => Shape::Binary("pmullw ", "*"),
Mnemonic::Pmulhw => Shape::Binary("pmulhw ", "*"),
Mnemonic::Pmulhuw => Shape::Binary("pmulhuw ", "*"),
Mnemonic::Pmuludq => Shape::Binary("pmuludq ", "*"),
Mnemonic::Pand => Shape::Binary("pand ", "&"),
Mnemonic::Por => Shape::Binary("por ", "|"),
Mnemonic::Pxor => Shape::Binary("pxor ", "^"),
Mnemonic::Pandn => Shape::Binary("pandn ", "& ~"),
Mnemonic::Psllw => Shape::Binary("psllw ", "<<"),
Mnemonic::Pslld => Shape::Binary("pslld ", "<<"),
Mnemonic::Psllq => Shape::Binary("psllq ", "<<"),
Mnemonic::Psrlw => Shape::Binary("psrlw ", ">>"),
Mnemonic::Psrld => Shape::Binary("psrld ", ">>"),
Mnemonic::Psrlq => Shape::Binary("psrlq ", ">>"),
Mnemonic::Psraw => Shape::Binary("psraw ", ">>"),
Mnemonic::Psrad => Shape::Binary("psrad ", ">>"),
Mnemonic::Addss => Shape::Binary("addss ", "+"),
Mnemonic::Addsd => Shape::Binary("addsd ", "+"),
Mnemonic::Addps => Shape::Binary("addps ", "+"),
Mnemonic::Addpd => Shape::Binary("addpd ", "+"),
Mnemonic::Subss => Shape::Binary("subss ", "-"),
Mnemonic::Subsd => Shape::Binary("subsd ", "-"),
Mnemonic::Subps => Shape::Binary("subps ", "-"),
Mnemonic::Subpd => Shape::Binary("subpd ", "-"),
Mnemonic::Mulss => Shape::Binary("mulss ", "*"),
Mnemonic::Mulsd => Shape::Binary("mulsd ", "*"),
Mnemonic::Mulps => Shape::Binary("mulps ", "*"),
Mnemonic::Mulpd => Shape::Binary("mulpd ", "*"),
Mnemonic::Divss => Shape::Binary("divss ", "/"),
Mnemonic::Divsd => Shape::Binary("divsd ", "/"),
Mnemonic::Divps => Shape::Binary("divps ", "/"),
Mnemonic::Divpd => Shape::Binary("divpd ", "/"),
Mnemonic::Xorps => Shape::Binary("xorps ", "^"),
Mnemonic::Xorpd => Shape::Binary("xorpd ", "^"),
Mnemonic::Andps => Shape::Binary("andps ", "&"),
Mnemonic::Andpd => Shape::Binary("andpd ", "&"),
Mnemonic::Orps => Shape::Binary("orps ", "|"),
Mnemonic::Orpd => Shape::Binary("orpd ", "|"),
Mnemonic::Andnps => Shape::Binary("andnps ", "& ~"),
Mnemonic::Andnpd => Shape::Binary("andnpd ", "& ~"),
_ => return None,
})
}