Skip to content

Commit

Permalink
pulley: More division/remainder instructions
Browse files Browse the repository at this point in the history
Gets a few misc tests passing

cc bytecodealliance#9783
  • Loading branch information
alexcrichton committed Dec 11, 2024
1 parent 8c321f7 commit 5c77791
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 5 deletions.
12 changes: 12 additions & 0 deletions cranelift/codegen/src/isa/pulley_shared/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,18 @@ fn pulley_emit<P>(
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)
Expand Down
21 changes: 18 additions & 3 deletions cranelift/codegen/src/isa/pulley_shared/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -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 `srem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(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` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
1 change: 0 additions & 1 deletion crates/wast-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
84 changes: 84 additions & 0 deletions pulley/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,90 @@ impl OpVisitor for Interpreter<'_> {
}
}

fn xdiv64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XDiv64S>(),
}
}

fn xdiv32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XDiv32U>(),
}
}

fn xdiv64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XDiv64U>(),
}
}

fn xrem32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XRem32S>(),
}
}

fn xrem64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XRem64S>(),
}
}

fn xrem32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XRem32U>(),
}
}

fn xrem64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
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::<crate::XRem64U>(),
}
}

fn xand32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_u32();
let b = self.state[operands.src2].get_u32();
Expand Down
23 changes: 22 additions & 1 deletion pulley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<XReg> };

/// `dst = src1 / src2` (signed)
xdiv64_s = XDiv64S { operands: BinaryOperands<XReg> };

/// `low32(dst) = low32(src1) / low32(src2)` (unsigned)
xdiv32_u = XDiv32U { operands: BinaryOperands<XReg> };

/// `dst = src1 / src2` (unsigned)
xdiv64_u = XDiv64U { operands: BinaryOperands<XReg> };

/// `low32(dst) = low32(src1) % low32(src2)` (signed)
xrem32_s = XRem32S { operands: BinaryOperands<XReg> };

/// `dst = src1 / src2` (signed)
xrem64_s = XRem64S { operands: BinaryOperands<XReg> };

/// `low32(dst) = low32(src1) % low32(src2)` (unsigned)
xrem32_u = XRem32U { operands: BinaryOperands<XReg> };

/// `dst = src1 / src2` (unsigned)
xrem64_u = XRem64U { operands: BinaryOperands<XReg> };

/// `low32(dst) = low32(src1) & low32(src2)`
xand32 = XAnd32 { operands: BinaryOperands<XReg> };
/// `dst = src1 & src2`
Expand Down

0 comments on commit 5c77791

Please sign in to comment.