diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 3fb99285eff1..5d3d752cf30d 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -627,6 +627,18 @@ fn pulley_emit

( RawInst::PushFrame | RawInst::StackAlloc32 { .. } => { sink.add_trap(ir::TrapCode::STACK_OVERFLOW); } + RawInst::XDiv32U { .. } + | RawInst::XDiv64U { .. } + | RawInst::XRem32U { .. } + | RawInst::XRem64U { .. } => { + sink.add_trap(ir::TrapCode::INTEGER_DIVISION_BY_ZERO); + } + RawInst::XDiv32S { .. } + | RawInst::XDiv64S { .. } + | RawInst::XRem32S { .. } + | RawInst::XRem64S { .. } => { + sink.add_trap(ir::TrapCode::INTEGER_OVERFLOW); + } _ => {} } super::generated::emit(raw, sink) diff --git a/cranelift/codegen/src/isa/pulley_shared/lower.isle b/cranelift/codegen/src/isa/pulley_shared/lower.isle index 144915384cd2..e96862716fd9 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower.isle +++ b/cranelift/codegen/src/isa/pulley_shared/lower.isle @@ -191,10 +191,25 @@ (rule (lower (has_type $I64 (isub a b))) (pulley_xsub64 a b)) -;;;; Rules for `idiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Rules for `sdiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(rule (lower (has_type $I32 (sdiv a b))) - (pulley_xdiv32_s a b)) +(rule (lower (has_type $I32 (sdiv a b))) (pulley_xdiv32_s a b)) +(rule (lower (has_type $I64 (sdiv a b))) (pulley_xdiv64_s a b)) + +;;;; Rules for `srem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (has_type $I32 (srem a b))) (pulley_xrem32_s a b)) +(rule (lower (has_type $I64 (srem a b))) (pulley_xrem64_s a b)) + +;;;; Rules for `udiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (has_type $I32 (udiv a b))) (pulley_xdiv32_u a b)) +(rule (lower (has_type $I64 (udiv a b))) (pulley_xdiv64_u a b)) + +;;;; Rules for `urem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (has_type $I32 (urem a b))) (pulley_xrem32_u a b)) +(rule (lower (has_type $I64 (urem a b))) (pulley_xrem64_u a b)) ;;;; Rules for `ishl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/crates/wast-util/src/lib.rs b/crates/wast-util/src/lib.rs index 262dde6e8872..2feadf5bbfac 100644 --- a/crates/wast-util/src/lib.rs +++ b/crates/wast-util/src/lib.rs @@ -399,7 +399,6 @@ impl WastTest { "misc_testsuite/call_indirect.wast", "misc_testsuite/component-model/fused.wast", "misc_testsuite/component-model/strings.wast", - "misc_testsuite/div-rem.wast", "misc_testsuite/embenchen_fannkuch.wast", "misc_testsuite/embenchen_fasta.wast", "misc_testsuite/embenchen_ifs.wast", diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index 4a667dfef1ef..44e7ae3a44eb 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -1572,6 +1572,90 @@ impl OpVisitor for Interpreter<'_> { } } + fn xdiv64_s(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_i64(); + let b = self.state[operands.src2].get_i64(); + match a.checked_div(b) { + Some(result) => { + self.state[operands.dst].set_i64(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xdiv32_u(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_u32(); + let b = self.state[operands.src2].get_u32(); + match a.checked_div(b) { + Some(result) => { + self.state[operands.dst].set_u32(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xdiv64_u(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_u64(); + let b = self.state[operands.src2].get_u64(); + match a.checked_div(b) { + Some(result) => { + self.state[operands.dst].set_u64(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xrem32_s(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_i32(); + let b = self.state[operands.src2].get_i32(); + match a.checked_rem(b) { + Some(result) => { + self.state[operands.dst].set_i32(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xrem64_s(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_i64(); + let b = self.state[operands.src2].get_i64(); + match a.checked_rem(b) { + Some(result) => { + self.state[operands.dst].set_i64(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xrem32_u(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_u32(); + let b = self.state[operands.src2].get_u32(); + match a.checked_rem(b) { + Some(result) => { + self.state[operands.dst].set_u32(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + + fn xrem64_u(&mut self, operands: BinaryOperands) -> ControlFlow { + let a = self.state[operands.src1].get_u64(); + let b = self.state[operands.src2].get_u64(); + match a.checked_rem(b) { + Some(result) => { + self.state[operands.dst].set_u64(result); + ControlFlow::Continue(()) + } + None => self.done_trap::(), + } + } + fn xand32(&mut self, operands: BinaryOperands) -> ControlFlow { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); diff --git a/pulley/src/lib.rs b/pulley/src/lib.rs index cb805af65460..466ab221cd59 100644 --- a/pulley/src/lib.rs +++ b/pulley/src/lib.rs @@ -332,9 +332,30 @@ macro_rules! for_each_op { /// `dst = sext(low32(src))` sext32 = Sext32 { dst: XReg, src: XReg }; - /// `dst = src1 / src2` (signed) + /// `low32(dst) = low32(src1) / low32(src2)` (signed) xdiv32_s = XDiv32S { operands: BinaryOperands }; + /// `dst = src1 / src2` (signed) + xdiv64_s = XDiv64S { operands: BinaryOperands }; + + /// `low32(dst) = low32(src1) / low32(src2)` (unsigned) + xdiv32_u = XDiv32U { operands: BinaryOperands }; + + /// `dst = src1 / src2` (unsigned) + xdiv64_u = XDiv64U { operands: BinaryOperands }; + + /// `low32(dst) = low32(src1) % low32(src2)` (signed) + xrem32_s = XRem32S { operands: BinaryOperands }; + + /// `dst = src1 / src2` (signed) + xrem64_s = XRem64S { operands: BinaryOperands }; + + /// `low32(dst) = low32(src1) % low32(src2)` (unsigned) + xrem32_u = XRem32U { operands: BinaryOperands }; + + /// `dst = src1 / src2` (unsigned) + xrem64_u = XRem64U { operands: BinaryOperands }; + /// `low32(dst) = low32(src1) & low32(src2)` xand32 = XAnd32 { operands: BinaryOperands }; /// `dst = src1 & src2`