winch: Add support for integer multiplication in x64. (#5769)

This commit adds support for the `<i32|i64>.mul` WebAssembly instructions in x64.
This commit is contained in:
Saúl Cabrera
2023-02-13 16:20:36 -05:00
committed by GitHub
parent 19f337e29b
commit 91c8114f00
21 changed files with 370 additions and 0 deletions

View File

@@ -242,6 +242,50 @@ impl Assembler {
});
}
/// Signed multiplication instruction.
pub fn mul(&mut self, src: Operand, dst: Operand, size: OperandSize) {
match &(src, dst) {
(Operand::Imm(imm), Operand::Reg(dst)) => {
if let Ok(val) = i32::try_from(*imm) {
self.mul_ir(val, *dst, size);
} else {
let scratch = regs::scratch();
self.mov_ir(*imm as u64, scratch, size);
self.mul_rr(scratch, *dst, size);
}
}
(Operand::Reg(src), Operand::Reg(dst)) => self.mul_rr(*src, *dst, size),
_ => panic!(
"Invalid operand combination for mul; src = {:?} dst = {:?}",
src, dst
),
}
}
/// Multiply immediate and register.
pub fn mul_ir(&mut self, imm: i32, dst: Reg, size: OperandSize) {
let imm = RegMemImm::imm(imm as u32);
self.emit(Inst::AluRmiR {
size: size.into(),
op: AluRmiROpcode::Mul,
src1: dst.into(),
src2: GprMemImm::new(imm).expect("valid immediate"),
dst: dst.into(),
});
}
/// Multiply register and register.
pub fn mul_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
self.emit(Inst::AluRmiR {
size: size.into(),
op: AluRmiROpcode::Mul,
src1: dst.into(),
src2: src.into(),
dst: dst.into(),
});
}
/// Add instruction variants.
pub fn add(&mut self, src: Operand, dst: Operand, size: OperandSize) {
match &(src, dst) {