Add {u,s}{add,sub,mul}_overflow instructions (#5784)
* add `{u,s}{add,sub,mul}_overflow` with interpreter
* add `{u,s}{add,sub,mul}_overflow` for x64
* add `{u,s}{add,sub,mul}_overflow` for aarch64
* 128bit filetests for `{u,s}{add,sub,mul}_overflow`
* `{u,s}{add,sub,mul}_overflow` emit tests for x64
* `{u,s}{add,sub,mul}_overflow` emit tests for aarch64
* Initial review changes
* add `with_flags_extended` helper
* add `with_flags_chained` helper
This commit is contained in:
@@ -101,6 +101,7 @@ impl Inst {
|
||||
| Inst::MovsxRmR { .. }
|
||||
| Inst::MovzxRmR { .. }
|
||||
| Inst::MulHi { .. }
|
||||
| Inst::UMulLo { .. }
|
||||
| Inst::Neg { .. }
|
||||
| Inst::Not { .. }
|
||||
| Inst::Nop { .. }
|
||||
@@ -180,7 +181,6 @@ impl Inst {
|
||||
src: RegMemImm,
|
||||
dst: Writable<Reg>,
|
||||
) -> Self {
|
||||
debug_assert!(size.is_one_of(&[OperandSize::Size32, OperandSize::Size64]));
|
||||
src.assert_regclass_is(RegClass::Int);
|
||||
debug_assert!(dst.to_reg().class() == RegClass::Int);
|
||||
Self::AluRmiR {
|
||||
@@ -657,6 +657,7 @@ impl PrettyPrint for Inst {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn suffix_lqb(size: OperandSize) -> String {
|
||||
match size {
|
||||
OperandSize::Size32 => "l",
|
||||
@@ -691,7 +692,7 @@ impl PrettyPrint for Inst {
|
||||
let src2 = src2.pretty_print(size_bytes, allocs);
|
||||
format!(
|
||||
"{} {}, {}, {}",
|
||||
ljustify2(op.to_string(), suffix_lqb(*size)),
|
||||
ljustify2(op.to_string(), suffix_bwlq(*size)),
|
||||
src1,
|
||||
src2,
|
||||
dst
|
||||
@@ -716,7 +717,7 @@ impl PrettyPrint for Inst {
|
||||
let src1_dst = src1_dst.pretty_print(size_bytes, allocs);
|
||||
format!(
|
||||
"{} {}, {}",
|
||||
ljustify2(op.to_string(), suffix_lqb(*size)),
|
||||
ljustify2(op.to_string(), suffix_bwlq(*size)),
|
||||
src2,
|
||||
src1_dst,
|
||||
)
|
||||
@@ -849,6 +850,24 @@ impl PrettyPrint for Inst {
|
||||
)
|
||||
}
|
||||
|
||||
Inst::UMulLo {
|
||||
size,
|
||||
src1,
|
||||
src2,
|
||||
dst,
|
||||
} => {
|
||||
let src1 = pretty_print_reg(src1.to_reg(), size.to_bytes(), allocs);
|
||||
let dst = pretty_print_reg(dst.to_reg().to_reg(), size.to_bytes(), allocs);
|
||||
let src2 = src2.pretty_print(size.to_bytes(), allocs);
|
||||
format!(
|
||||
"{} {}, {}, {}",
|
||||
ljustify2("mul".to_string(), suffix_bwlq(*size)),
|
||||
src1,
|
||||
src2,
|
||||
dst,
|
||||
)
|
||||
}
|
||||
|
||||
Inst::CheckedSRemSeq {
|
||||
size,
|
||||
divisor,
|
||||
@@ -1854,11 +1873,23 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
|
||||
// method above.
|
||||
match inst {
|
||||
Inst::AluRmiR {
|
||||
src1, src2, dst, ..
|
||||
size,
|
||||
op,
|
||||
src1,
|
||||
src2,
|
||||
dst,
|
||||
..
|
||||
} => {
|
||||
collector.reg_use(src1.to_reg());
|
||||
collector.reg_reuse_def(dst.to_writable_reg(), 0);
|
||||
src2.get_operands(collector);
|
||||
if *size == OperandSize::Size8 && *op == AluRmiROpcode::Mul {
|
||||
// 8-bit imul has RAX as a fixed input/output
|
||||
collector.reg_fixed_use(src1.to_reg(), regs::rax());
|
||||
collector.reg_fixed_def(dst.to_writable_reg(), regs::rax());
|
||||
src2.get_operands(collector);
|
||||
} else {
|
||||
collector.reg_use(src1.to_reg());
|
||||
collector.reg_reuse_def(dst.to_writable_reg(), 0);
|
||||
src2.get_operands(collector);
|
||||
}
|
||||
}
|
||||
Inst::AluConstOp { dst, .. } => collector.reg_def(dst.to_writable_reg()),
|
||||
Inst::AluRM { src1_dst, src2, .. } => {
|
||||
@@ -1925,6 +1956,20 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
|
||||
collector.reg_fixed_def(dst_hi.to_writable_reg(), regs::rdx());
|
||||
src2.get_operands(collector);
|
||||
}
|
||||
Inst::UMulLo {
|
||||
size,
|
||||
src1,
|
||||
src2,
|
||||
dst,
|
||||
..
|
||||
} => {
|
||||
collector.reg_fixed_use(src1.to_reg(), regs::rax());
|
||||
collector.reg_fixed_def(dst.to_writable_reg(), regs::rax());
|
||||
if *size != OperandSize::Size8 {
|
||||
collector.reg_clobbers(PRegSet::empty().with(regs::gpr_preg(regs::ENC_RDX)));
|
||||
}
|
||||
src2.get_operands(collector);
|
||||
}
|
||||
Inst::SignExtendData { size, src, dst } => {
|
||||
match size {
|
||||
OperandSize::Size8 => {
|
||||
|
||||
Reference in New Issue
Block a user