From 4d954f5c0e5ec06b00544e1611810154ff837806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Cabrera?= Date: Mon, 20 Feb 2023 12:52:06 -0500 Subject: [PATCH] winch: Add support for `.rem_*` WebAssembly instructions (#5823) This commit adds support for i32 and i64 remainder instructions for x64. --- winch/codegen/src/isa/aarch64/masm.rs | 6 +++- winch/codegen/src/isa/x64/asm.rs | 31 ++++++++++++++++- winch/codegen/src/isa/x64/masm.rs | 24 ++++++++++++- winch/codegen/src/masm.rs | 11 ++++++ winch/codegen/src/visitor.rs | 34 ++++++++++++++++++- .../filetests/x64/i32_rems/const.wat | 25 ++++++++++++++ .../filetests/x64/i32_rems/one_zero.wat | 25 ++++++++++++++ .../filetests/x64/i32_rems/overflow.wat | 25 ++++++++++++++ .../filetests/x64/i32_rems/params.wat | 29 ++++++++++++++++ .../filetests/x64/i32_rems/zero_zero.wat | 25 ++++++++++++++ .../filetests/x64/i32_remu/const.wat | 21 ++++++++++++ .../filetests/x64/i32_remu/one_zero.wat | 21 ++++++++++++ .../filetests/x64/i32_remu/params.wat | 25 ++++++++++++++ .../filetests/x64/i32_remu/signed.wat | 21 ++++++++++++ .../filetests/x64/i32_remu/zero_zero.wat | 21 ++++++++++++ .../filetests/x64/i64_rems/const.wat | 25 ++++++++++++++ .../filetests/x64/i64_rems/one_zero.wat | 25 ++++++++++++++ .../filetests/x64/i64_rems/overflow.wat | 26 ++++++++++++++ .../filetests/x64/i64_rems/params.wat | 29 ++++++++++++++++ .../filetests/x64/i64_rems/zero_zero.wat | 25 ++++++++++++++ .../filetests/x64/i64_remu/const.wat | 21 ++++++++++++ .../filetests/x64/i64_remu/one_zero.wat | 21 ++++++++++++ .../filetests/x64/i64_remu/params.wat | 25 ++++++++++++++ .../filetests/x64/i64_remu/signed.wat | 21 ++++++++++++ .../filetests/x64/i64_remu/zero_zero.wat | 21 ++++++++++++ 25 files changed, 579 insertions(+), 4 deletions(-) create mode 100644 winch/filetests/filetests/x64/i32_rems/const.wat create mode 100644 winch/filetests/filetests/x64/i32_rems/one_zero.wat create mode 100644 winch/filetests/filetests/x64/i32_rems/overflow.wat create mode 100644 winch/filetests/filetests/x64/i32_rems/params.wat create mode 100644 winch/filetests/filetests/x64/i32_rems/zero_zero.wat create mode 100644 winch/filetests/filetests/x64/i32_remu/const.wat create mode 100644 winch/filetests/filetests/x64/i32_remu/one_zero.wat create mode 100644 winch/filetests/filetests/x64/i32_remu/params.wat create mode 100644 winch/filetests/filetests/x64/i32_remu/signed.wat create mode 100644 winch/filetests/filetests/x64/i32_remu/zero_zero.wat create mode 100644 winch/filetests/filetests/x64/i64_rems/const.wat create mode 100644 winch/filetests/filetests/x64/i64_rems/one_zero.wat create mode 100644 winch/filetests/filetests/x64/i64_rems/overflow.wat create mode 100644 winch/filetests/filetests/x64/i64_rems/params.wat create mode 100644 winch/filetests/filetests/x64/i64_rems/zero_zero.wat create mode 100644 winch/filetests/filetests/x64/i64_remu/const.wat create mode 100644 winch/filetests/filetests/x64/i64_remu/one_zero.wat create mode 100644 winch/filetests/filetests/x64/i64_remu/params.wat create mode 100644 winch/filetests/filetests/x64/i64_remu/signed.wat create mode 100644 winch/filetests/filetests/x64/i64_remu/zero_zero.wat diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index 89efe72cc6..e44c6c471c 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -7,7 +7,7 @@ use crate::{ abi::local::LocalSlot, codegen::CodeGenContext, isa::reg::Reg, - masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm}, + masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind}, }; use cranelift_codegen::{settings, Final, MachBufferFinalized}; @@ -156,6 +156,10 @@ impl Masm for MacroAssembler { todo!() } + fn rem(&mut self, _context: &mut CodeGenContext, _kind: RemKind, _size: OperandSize) { + todo!() + } + fn zero(&mut self, reg: Reg) { self.asm.load_constant(0, reg); } diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs index 5b2286404b..03bddaac62 100644 --- a/winch/codegen/src/isa/x64/asm.rs +++ b/winch/codegen/src/isa/x64/asm.rs @@ -2,7 +2,7 @@ use crate::{ isa::reg::Reg, - masm::{DivKind, OperandSize}, + masm::{DivKind, OperandSize, RemKind}, }; use cranelift_codegen::{ isa::x64::{ @@ -73,6 +73,15 @@ impl From for DivOrRemKind { } } +impl From for DivOrRemKind { + fn from(kind: RemKind) -> Self { + match kind { + RemKind::Signed => DivOrRemKind::SignedRem, + RemKind::Unsigned => DivOrRemKind::UnsignedRem, + } + } +} + /// Low level assembler implementation for x64. pub(crate) struct Assembler { /// The machine instruction buffer. @@ -299,6 +308,26 @@ impl Assembler { }); } + /// Signed/unsigned remainder. + /// + /// Emits a sequence of instructions to ensure the correctness of the + /// division invariants and ultimately calculate the remainder. + /// This function assumes that the + /// caller has correctly allocated the dividend as `(rdx:rax)` and + /// accounted for the remainder to be stored in `rdx`. + pub fn rem(&mut self, divisor: Reg, dst: (Reg, Reg), kind: RemKind, size: OperandSize) { + self.emit(Inst::CheckedDivOrRemSeq { + kind: kind.into(), + size: size.into(), + divisor: divisor.into(), + dividend_lo: dst.0.into(), + dividend_hi: dst.1.into(), + dst_quotient: dst.0.into(), + dst_remainder: dst.1.into(), + tmp: None, + }); + } + /// Multiply immediate and register. pub fn mul_ir(&mut self, imm: i32, dst: Reg, size: OperandSize) { let imm = RegMemImm::imm(imm as u32); diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs index 758e72fa5c..e4bc0db62d 100644 --- a/winch/codegen/src/isa/x64/masm.rs +++ b/winch/codegen/src/isa/x64/masm.rs @@ -4,7 +4,7 @@ use super::{ regs::{self, rbp, rsp}, }; use crate::isa::reg::Reg; -use crate::masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm}; +use crate::masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind}; use crate::{abi::LocalSlot, codegen::CodeGenContext, stack::Val}; use cranelift_codegen::{isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized}; @@ -174,6 +174,28 @@ impl Masm for MacroAssembler { context.stack.push(Val::reg(rax)); } + fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize) { + // Allocate rdx:rax. + let rdx = context.gpr(regs::rdx(), self); + let rax = context.gpr(regs::rax(), self); + + // Allocate the divisor, which can be any gpr. + let divisor = context.pop_to_reg(self, size); + + // Mark rax as allocatable. + context.regalloc.free_gpr(rax); + // Move the top value to rax. + let rax = context.pop_to_named_reg(self, rax, size); + self.asm.rem(divisor, (rax, rdx), kind, size); + + // Free the divisor and rax. + context.free_gpr(divisor); + context.free_gpr(rax); + + // Push the remainder. + context.stack.push(Val::reg(rdx)); + } + fn epilogue(&mut self, locals_size: u32) { assert!(self.sp_offset == locals_size); diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index 1f4507be59..f23e31917a 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -13,6 +13,14 @@ pub(crate) enum DivKind { Unsigned, } +/// Remainder kind. +pub(crate) enum RemKind { + /// Signed remainder. + Signed, + /// Unsigned remainder. + Unsigned, +} + /// Operand size, in bits. #[derive(Copy, Clone, Eq, PartialEq)] pub(crate) enum OperandSize { @@ -116,6 +124,9 @@ pub(crate) trait MacroAssembler { /// functions. fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize); + /// Calculate remainder. + fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize); + /// Push the register to the stack, returning the offset. fn push(&mut self, src: Reg) -> u32; diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index 072c704041..331d0b76d5 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -5,7 +5,7 @@ //! machine code emitter. use crate::codegen::CodeGen; -use crate::masm::{DivKind, MacroAssembler, OperandSize, RegImm}; +use crate::masm::{DivKind, MacroAssembler, OperandSize, RegImm, RemKind}; use crate::stack::Val; use wasmparser::ValType; use wasmparser::VisitOperator; @@ -41,6 +41,10 @@ macro_rules! def_unsupported { (emit I32DivU $($rest:tt)*) => {}; (emit I64DivS $($rest:tt)*) => {}; (emit I64DivU $($rest:tt)*) => {}; + (emit I64RemU $($rest:tt)*) => {}; + (emit I64RemS $($rest:tt)*) => {}; + (emit I32RemU $($rest:tt)*) => {}; + (emit I32RemS $($rest:tt)*) => {}; (emit I64Mul $($rest:tt)*) => {}; (emit I64Sub $($rest:tt)*) => {}; (emit LocalGet $($rest:tt)*) => {}; @@ -134,6 +138,34 @@ where self.masm.div(&mut self.context, Unsigned, S64); } + fn visit_i32_rem_s(&mut self) { + use OperandSize::*; + use RemKind::*; + + self.masm.rem(&mut self.context, Signed, S32); + } + + fn visit_i32_rem_u(&mut self) { + use OperandSize::*; + use RemKind::*; + + self.masm.rem(&mut self.context, Unsigned, S32); + } + + fn visit_i64_rem_s(&mut self) { + use OperandSize::*; + use RemKind::*; + + self.masm.rem(&mut self.context, Signed, S64); + } + + fn visit_i64_rem_u(&mut self) { + use OperandSize::*; + use RemKind::*; + + self.masm.rem(&mut self.context, Unsigned, S64); + } + fn visit_end(&mut self) {} fn visit_local_get(&mut self, index: u32) { diff --git a/winch/filetests/filetests/x64/i32_rems/const.wat b/winch/filetests/filetests/x64/i32_rems/const.wat new file mode 100644 index 0000000000..1dc8224b72 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_rems/const.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 7) + (i32.const 5) + (i32.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b905000000 mov ecx, 5 +;; 9: b807000000 mov eax, 7 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: 83f9ff cmp ecx, -1 +;; 1c: 0f850a000000 jne 0x2c +;; 22: b800000000 mov eax, 0 +;; 27: e903000000 jmp 0x2f +;; 2c: 99 cdq +;; 2d: f7f9 idiv ecx +;; 2f: 4889d0 mov rax, rdx +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i32_rems/one_zero.wat b/winch/filetests/filetests/x64/i32_rems/one_zero.wat new file mode 100644 index 0000000000..bc7804ede1 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_rems/one_zero.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 1) + (i32.const 0) + (i32.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b900000000 mov ecx, 0 +;; 9: b801000000 mov eax, 1 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: 83f9ff cmp ecx, -1 +;; 1c: 0f850a000000 jne 0x2c +;; 22: b800000000 mov eax, 0 +;; 27: e903000000 jmp 0x2f +;; 2c: 99 cdq +;; 2d: f7f9 idiv ecx +;; 2f: 4889d0 mov rax, rdx +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i32_rems/overflow.wat b/winch/filetests/filetests/x64/i32_rems/overflow.wat new file mode 100644 index 0000000000..7211182b2f --- /dev/null +++ b/winch/filetests/filetests/x64/i32_rems/overflow.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 0x80000000) + (i32.const -1) + (i32.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b9ffffffff mov ecx, 0xffffffff +;; 9: b800000080 mov eax, 0x80000000 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: 83f9ff cmp ecx, -1 +;; 1c: 0f850a000000 jne 0x2c +;; 22: b800000000 mov eax, 0 +;; 27: e903000000 jmp 0x2f +;; 2c: 99 cdq +;; 2d: f7f9 idiv ecx +;; 2f: 4889d0 mov rax, rdx +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i32_rems/params.wat b/winch/filetests/filetests/x64/i32_rems/params.wat new file mode 100644 index 0000000000..d91d3937e9 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_rems/params.wat @@ -0,0 +1,29 @@ +;;! target = "x86_64" + +(module + (func (param i32) (param i32) (result i32) + (local.get 0) + (local.get 1) + (i32.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 897c2404 mov dword ptr [rsp + 4], edi +;; c: 893424 mov dword ptr [rsp], esi +;; f: 8b0c24 mov ecx, dword ptr [rsp] +;; 12: 8b442404 mov eax, dword ptr [rsp + 4] +;; 16: 83f900 cmp ecx, 0 +;; 19: 0f8502000000 jne 0x21 +;; 1f: 0f0b ud2 +;; 21: 83f9ff cmp ecx, -1 +;; 24: 0f850a000000 jne 0x34 +;; 2a: b800000000 mov eax, 0 +;; 2f: e903000000 jmp 0x37 +;; 34: 99 cdq +;; 35: f7f9 idiv ecx +;; 37: 4889d0 mov rax, rdx +;; 3a: 4883c408 add rsp, 8 +;; 3e: 5d pop rbp +;; 3f: c3 ret diff --git a/winch/filetests/filetests/x64/i32_rems/zero_zero.wat b/winch/filetests/filetests/x64/i32_rems/zero_zero.wat new file mode 100644 index 0000000000..dd56aff9b0 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_rems/zero_zero.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 0) + (i32.const 0) + (i32.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b900000000 mov ecx, 0 +;; 9: b800000000 mov eax, 0 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: 83f9ff cmp ecx, -1 +;; 1c: 0f850a000000 jne 0x2c +;; 22: b800000000 mov eax, 0 +;; 27: e903000000 jmp 0x2f +;; 2c: 99 cdq +;; 2d: f7f9 idiv ecx +;; 2f: 4889d0 mov rax, rdx +;; 32: 5d pop rbp +;; 33: c3 ret diff --git a/winch/filetests/filetests/x64/i32_remu/const.wat b/winch/filetests/filetests/x64/i32_remu/const.wat new file mode 100644 index 0000000000..65dc05cef9 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_remu/const.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 7) + (i32.const 5) + (i32.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b905000000 mov ecx, 5 +;; 9: b807000000 mov eax, 7 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: ba00000000 mov edx, 0 +;; 1e: f7f1 div ecx +;; 20: 4889d0 mov rax, rdx +;; 23: 5d pop rbp +;; 24: c3 ret diff --git a/winch/filetests/filetests/x64/i32_remu/one_zero.wat b/winch/filetests/filetests/x64/i32_remu/one_zero.wat new file mode 100644 index 0000000000..9a482a68f5 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_remu/one_zero.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 1) + (i32.const 0) + (i32.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b900000000 mov ecx, 0 +;; 9: b801000000 mov eax, 1 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: ba00000000 mov edx, 0 +;; 1e: f7f1 div ecx +;; 20: 4889d0 mov rax, rdx +;; 23: 5d pop rbp +;; 24: c3 ret diff --git a/winch/filetests/filetests/x64/i32_remu/params.wat b/winch/filetests/filetests/x64/i32_remu/params.wat new file mode 100644 index 0000000000..743ce4446d --- /dev/null +++ b/winch/filetests/filetests/x64/i32_remu/params.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (param i32) (param i32) (result i32) + (local.get 0) + (local.get 1) + (i32.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 897c2404 mov dword ptr [rsp + 4], edi +;; c: 893424 mov dword ptr [rsp], esi +;; f: 8b0c24 mov ecx, dword ptr [rsp] +;; 12: 8b442404 mov eax, dword ptr [rsp + 4] +;; 16: 83f900 cmp ecx, 0 +;; 19: 0f8502000000 jne 0x21 +;; 1f: 0f0b ud2 +;; 21: ba00000000 mov edx, 0 +;; 26: f7f1 div ecx +;; 28: 4889d0 mov rax, rdx +;; 2b: 4883c408 add rsp, 8 +;; 2f: 5d pop rbp +;; 30: c3 ret diff --git a/winch/filetests/filetests/x64/i32_remu/signed.wat b/winch/filetests/filetests/x64/i32_remu/signed.wat new file mode 100644 index 0000000000..c29c66e5c5 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_remu/signed.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const -1) + (i32.const -1) + (i32.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b9ffffffff mov ecx, 0xffffffff +;; 9: b8ffffffff mov eax, 0xffffffff +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: ba00000000 mov edx, 0 +;; 1e: f7f1 div ecx +;; 20: 4889d0 mov rax, rdx +;; 23: 5d pop rbp +;; 24: c3 ret diff --git a/winch/filetests/filetests/x64/i32_remu/zero_zero.wat b/winch/filetests/filetests/x64/i32_remu/zero_zero.wat new file mode 100644 index 0000000000..671840c328 --- /dev/null +++ b/winch/filetests/filetests/x64/i32_remu/zero_zero.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i32) + (i32.const 0) + (i32.const 0) + (i32.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: b900000000 mov ecx, 0 +;; 9: b800000000 mov eax, 0 +;; e: 83f900 cmp ecx, 0 +;; 11: 0f8502000000 jne 0x19 +;; 17: 0f0b ud2 +;; 19: ba00000000 mov edx, 0 +;; 1e: f7f1 div ecx +;; 20: 4889d0 mov rax, rdx +;; 23: 5d pop rbp +;; 24: c3 ret diff --git a/winch/filetests/filetests/x64/i64_rems/const.wat b/winch/filetests/filetests/x64/i64_rems/const.wat new file mode 100644 index 0000000000..4eb4e83520 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_rems/const.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 7) + (i64.const 5) + (i64.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c105000000 mov rcx, 5 +;; b: 48c7c007000000 mov rax, 7 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: 4883f9ff cmp rcx, -1 +;; 22: 0f850a000000 jne 0x32 +;; 28: b800000000 mov eax, 0 +;; 2d: e905000000 jmp 0x37 +;; 32: 4899 cqo +;; 34: 48f7f9 idiv rcx +;; 37: 4889d0 mov rax, rdx +;; 3a: 5d pop rbp +;; 3b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_rems/one_zero.wat b/winch/filetests/filetests/x64/i64_rems/one_zero.wat new file mode 100644 index 0000000000..dc748d6221 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_rems/one_zero.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 1) + (i64.const 0) + (i64.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c100000000 mov rcx, 0 +;; b: 48c7c001000000 mov rax, 1 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: 4883f9ff cmp rcx, -1 +;; 22: 0f850a000000 jne 0x32 +;; 28: b800000000 mov eax, 0 +;; 2d: e905000000 jmp 0x37 +;; 32: 4899 cqo +;; 34: 48f7f9 idiv rcx +;; 37: 4889d0 mov rax, rdx +;; 3a: 5d pop rbp +;; 3b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_rems/overflow.wat b/winch/filetests/filetests/x64/i64_rems/overflow.wat new file mode 100644 index 0000000000..33bd76cddd --- /dev/null +++ b/winch/filetests/filetests/x64/i64_rems/overflow.wat @@ -0,0 +1,26 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 0x8000000000000000) + (i64.const -1) + (i64.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c1ffffffff mov rcx, 0xffffffffffffffff +;; b: 48b80000000000000080 +;; movabs rax, 0x8000000000000000 +;; 15: 4883f900 cmp rcx, 0 +;; 19: 0f8502000000 jne 0x21 +;; 1f: 0f0b ud2 +;; 21: 4883f9ff cmp rcx, -1 +;; 25: 0f850a000000 jne 0x35 +;; 2b: b800000000 mov eax, 0 +;; 30: e905000000 jmp 0x3a +;; 35: 4899 cqo +;; 37: 48f7f9 idiv rcx +;; 3a: 4889d0 mov rax, rdx +;; 3d: 5d pop rbp +;; 3e: c3 ret diff --git a/winch/filetests/filetests/x64/i64_rems/params.wat b/winch/filetests/filetests/x64/i64_rems/params.wat new file mode 100644 index 0000000000..5fc16387e8 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_rems/params.wat @@ -0,0 +1,29 @@ +;;! target = "x86_64" + +(module + (func (param i64) (param i64) (result i64) + (local.get 0) + (local.get 1) + (i64.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 48893424 mov qword ptr [rsp], rsi +;; 11: 488b0c24 mov rcx, qword ptr [rsp] +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 4883f900 cmp rcx, 0 +;; 1e: 0f8502000000 jne 0x26 +;; 24: 0f0b ud2 +;; 26: 4883f9ff cmp rcx, -1 +;; 2a: 0f850a000000 jne 0x3a +;; 30: b800000000 mov eax, 0 +;; 35: e905000000 jmp 0x3f +;; 3a: 4899 cqo +;; 3c: 48f7f9 idiv rcx +;; 3f: 4889d0 mov rax, rdx +;; 42: 4883c410 add rsp, 0x10 +;; 46: 5d pop rbp +;; 47: c3 ret diff --git a/winch/filetests/filetests/x64/i64_rems/zero_zero.wat b/winch/filetests/filetests/x64/i64_rems/zero_zero.wat new file mode 100644 index 0000000000..ad5a74bdc1 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_rems/zero_zero.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 0) + (i64.const 0) + (i64.rem_s) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c100000000 mov rcx, 0 +;; b: 48c7c000000000 mov rax, 0 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: 4883f9ff cmp rcx, -1 +;; 22: 0f850a000000 jne 0x32 +;; 28: b800000000 mov eax, 0 +;; 2d: e905000000 jmp 0x37 +;; 32: 4899 cqo +;; 34: 48f7f9 idiv rcx +;; 37: 4889d0 mov rax, rdx +;; 3a: 5d pop rbp +;; 3b: c3 ret diff --git a/winch/filetests/filetests/x64/i64_remu/const.wat b/winch/filetests/filetests/x64/i64_remu/const.wat new file mode 100644 index 0000000000..c139c6d72d --- /dev/null +++ b/winch/filetests/filetests/x64/i64_remu/const.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 7) + (i64.const 5) + (i64.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c105000000 mov rcx, 5 +;; b: 48c7c007000000 mov rax, 7 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: ba00000000 mov edx, 0 +;; 23: 48f7f1 div rcx +;; 26: 4889d0 mov rax, rdx +;; 29: 5d pop rbp +;; 2a: c3 ret diff --git a/winch/filetests/filetests/x64/i64_remu/one_zero.wat b/winch/filetests/filetests/x64/i64_remu/one_zero.wat new file mode 100644 index 0000000000..2c79349fa3 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_remu/one_zero.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 1) + (i64.const 0) + (i64.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c100000000 mov rcx, 0 +;; b: 48c7c001000000 mov rax, 1 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: ba00000000 mov edx, 0 +;; 23: 48f7f1 div rcx +;; 26: 4889d0 mov rax, rdx +;; 29: 5d pop rbp +;; 2a: c3 ret diff --git a/winch/filetests/filetests/x64/i64_remu/params.wat b/winch/filetests/filetests/x64/i64_remu/params.wat new file mode 100644 index 0000000000..e37f955349 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_remu/params.wat @@ -0,0 +1,25 @@ +;;! target = "x86_64" + +(module + (func (param i64) (param i64) (result i64) + (local.get 0) + (local.get 1) + (i64.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi +;; d: 48893424 mov qword ptr [rsp], rsi +;; 11: 488b0c24 mov rcx, qword ptr [rsp] +;; 15: 488b442408 mov rax, qword ptr [rsp + 8] +;; 1a: 4883f900 cmp rcx, 0 +;; 1e: 0f8502000000 jne 0x26 +;; 24: 0f0b ud2 +;; 26: ba00000000 mov edx, 0 +;; 2b: 48f7f1 div rcx +;; 2e: 4889d0 mov rax, rdx +;; 31: 4883c410 add rsp, 0x10 +;; 35: 5d pop rbp +;; 36: c3 ret diff --git a/winch/filetests/filetests/x64/i64_remu/signed.wat b/winch/filetests/filetests/x64/i64_remu/signed.wat new file mode 100644 index 0000000000..b0b4cdce9a --- /dev/null +++ b/winch/filetests/filetests/x64/i64_remu/signed.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const -1) + (i64.const -1) + (i64.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c1ffffffff mov rcx, 0xffffffffffffffff +;; b: 48c7c0ffffffff mov rax, 0xffffffffffffffff +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: ba00000000 mov edx, 0 +;; 23: 48f7f1 div rcx +;; 26: 4889d0 mov rax, rdx +;; 29: 5d pop rbp +;; 2a: c3 ret diff --git a/winch/filetests/filetests/x64/i64_remu/zero_zero.wat b/winch/filetests/filetests/x64/i64_remu/zero_zero.wat new file mode 100644 index 0000000000..7fbf7a9ae8 --- /dev/null +++ b/winch/filetests/filetests/x64/i64_remu/zero_zero.wat @@ -0,0 +1,21 @@ +;;! target = "x86_64" + +(module + (func (result i64) + (i64.const 0) + (i64.const 0) + (i64.rem_u) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 48c7c100000000 mov rcx, 0 +;; b: 48c7c000000000 mov rax, 0 +;; 12: 4883f900 cmp rcx, 0 +;; 16: 0f8502000000 jne 0x1e +;; 1c: 0f0b ud2 +;; 1e: ba00000000 mov edx, 0 +;; 23: 48f7f1 div rcx +;; 26: 4889d0 mov rax, rdx +;; 29: 5d pop rbp +;; 2a: c3 ret