diff --git a/tests/disas/winch/aarch64/i32_rems/const.wat b/tests/disas/winch/aarch64/i32_rems/const.wat new file mode 100644 index 000000000000..b01e691bae13 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_rems/const.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 7) + (i32.const 5) + (i32.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #5 +;; mov w0, w16 +;; mov x16, #7 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: sxtw x0, w0 +;; sxtw x1, w1 +;; sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_rems/one_zero.wat b/tests/disas/winch/aarch64/i32_rems/one_zero.wat new file mode 100644 index 000000000000..d38495fedd4c --- /dev/null +++ b/tests/disas/winch/aarch64/i32_rems/one_zero.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 1) + (i32.const 0) + (i32.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov w0, w16 +;; mov x16, #1 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: sxtw x0, w0 +;; sxtw x1, w1 +;; sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_rems/overflow.wat b/tests/disas/winch/aarch64/i32_rems/overflow.wat new file mode 100644 index 000000000000..f16ef7bacc85 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_rems/overflow.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 0x80000000) + (i32.const -1) + (i32.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; orr x16, xzr, #0xffffffff +;; mov w0, w16 +;; mov x16, #0x80000000 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: sxtw x0, w0 +;; sxtw x1, w1 +;; sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_rems/params.wat b/tests/disas/winch/aarch64/i32_rems/params.wat new file mode 100644 index 000000000000..84fc8b067816 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_rems/params.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param i32) (param i32) (result i32) + (local.get 0) + (local.get 1) + (i32.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x18 +;; mov x28, sp +;; stur x0, [x28, #0x10] +;; stur x1, [x28, #8] +;; stur w2, [x28, #4] +;; stur w3, [x28] +;; ldur w0, [x28] +;; ldur w1, [x28, #4] +;; cbz x0, #0x58 +;; 34: sxtw x0, w0 +;; sxtw x1, w1 +;; sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_rems/zero_zero.wat b/tests/disas/winch/aarch64/i32_rems/zero_zero.wat new file mode 100644 index 000000000000..d032f4340b24 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_rems/zero_zero.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 0) + (i32.const 0) + (i32.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov w0, w16 +;; mov x16, #0 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: sxtw x0, w0 +;; sxtw x1, w1 +;; sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_remu/const.wat b/tests/disas/winch/aarch64/i32_remu/const.wat new file mode 100644 index 000000000000..7b073a44a039 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_remu/const.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 7) + (i32.const 5) + (i32.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #5 +;; mov w0, w16 +;; mov x16, #7 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: mov w0, w0 +;; mov w1, w1 +;; udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_remu/one_zero.wat b/tests/disas/winch/aarch64/i32_remu/one_zero.wat new file mode 100644 index 000000000000..484229500d98 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_remu/one_zero.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 1) + (i32.const 0) + (i32.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov w0, w16 +;; mov x16, #1 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: mov w0, w0 +;; mov w1, w1 +;; udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_remu/params.wat b/tests/disas/winch/aarch64/i32_remu/params.wat new file mode 100644 index 000000000000..d107b220b14f --- /dev/null +++ b/tests/disas/winch/aarch64/i32_remu/params.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param i32) (param i32) (result i32) + (local.get 0) + (local.get 1) + (i32.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x18 +;; mov x28, sp +;; stur x0, [x28, #0x10] +;; stur x1, [x28, #8] +;; stur w2, [x28, #4] +;; stur w3, [x28] +;; ldur w0, [x28] +;; ldur w1, [x28, #4] +;; cbz x0, #0x58 +;; 34: mov w0, w0 +;; mov w1, w1 +;; udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_remu/signed.wat b/tests/disas/winch/aarch64/i32_remu/signed.wat new file mode 100644 index 000000000000..9f205360ab15 --- /dev/null +++ b/tests/disas/winch/aarch64/i32_remu/signed.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const -1) + (i32.const -1) + (i32.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; orr x16, xzr, #0xffffffff +;; mov w0, w16 +;; orr x16, xzr, #0xffffffff +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: mov w0, w0 +;; mov w1, w1 +;; udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i32_remu/zero_zero.wat b/tests/disas/winch/aarch64/i32_remu/zero_zero.wat new file mode 100644 index 000000000000..4b5b48b8d14a --- /dev/null +++ b/tests/disas/winch/aarch64/i32_remu/zero_zero.wat @@ -0,0 +1,35 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i32) + (i32.const 0) + (i32.const 0) + (i32.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov w0, w16 +;; mov x16, #0 +;; mov w1, w16 +;; cbz x0, #0x58 +;; 34: mov w0, w0 +;; mov w1, w1 +;; udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov w0, w1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 58: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_rems/const.wat b/tests/disas/winch/aarch64/i64_rems/const.wat new file mode 100644 index 000000000000..b5c29486f77e --- /dev/null +++ b/tests/disas/winch/aarch64/i64_rems/const.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 7) + (i64.const 5) + (i64.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #5 +;; mov x0, x16 +;; mov x16, #7 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_rems/one_zero.wat b/tests/disas/winch/aarch64/i64_rems/one_zero.wat new file mode 100644 index 000000000000..144abaaa0f50 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_rems/one_zero.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 1) + (i64.const 0) + (i64.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov x0, x16 +;; mov x16, #1 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_rems/overflow.wat b/tests/disas/winch/aarch64/i64_rems/overflow.wat new file mode 100644 index 000000000000..78b82a695075 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_rems/overflow.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 0x8000000000000000) + (i64.const -1) + (i64.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #-1 +;; mov x0, x16 +;; mov x16, #-0x8000000000000000 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_rems/params.wat b/tests/disas/winch/aarch64/i64_rems/params.wat new file mode 100644 index 000000000000..3022b8adc970 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_rems/params.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param i64) (param i64) (result i64) + (local.get 0) + (local.get 1) + (i64.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x20 +;; mov x28, sp +;; stur x0, [x28, #0x18] +;; stur x1, [x28, #0x10] +;; stur x2, [x28, #8] +;; stur x3, [x28] +;; ldur x0, [x28] +;; ldur x1, [x28, #8] +;; cbz x0, #0x50 +;; 34: sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x20 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_rems/zero_zero.wat b/tests/disas/winch/aarch64/i64_rems/zero_zero.wat new file mode 100644 index 000000000000..59819f6ed1ba --- /dev/null +++ b/tests/disas/winch/aarch64/i64_rems/zero_zero.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 0) + (i64.const 0) + (i64.rem_s) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov x0, x16 +;; mov x16, #0 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: sdiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_remu/const.wat b/tests/disas/winch/aarch64/i64_remu/const.wat new file mode 100644 index 000000000000..07b65bc1a32e --- /dev/null +++ b/tests/disas/winch/aarch64/i64_remu/const.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 7) + (i64.const 5) + (i64.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #5 +;; mov x0, x16 +;; mov x16, #7 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_remu/one_zero.wat b/tests/disas/winch/aarch64/i64_remu/one_zero.wat new file mode 100644 index 000000000000..a9a756cb5684 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_remu/one_zero.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 1) + (i64.const 0) + (i64.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov x0, x16 +;; mov x16, #1 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_remu/params.wat b/tests/disas/winch/aarch64/i64_remu/params.wat new file mode 100644 index 000000000000..b1244e4315d0 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_remu/params.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param i64) (param i64) (result i64) + (local.get 0) + (local.get 1) + (i64.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x20 +;; mov x28, sp +;; stur x0, [x28, #0x18] +;; stur x1, [x28, #0x10] +;; stur x2, [x28, #8] +;; stur x3, [x28] +;; ldur x0, [x28] +;; ldur x1, [x28, #8] +;; cbz x0, #0x50 +;; 34: udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x20 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_remu/signed.wat b/tests/disas/winch/aarch64/i64_remu/signed.wat new file mode 100644 index 000000000000..866d842403a8 --- /dev/null +++ b/tests/disas/winch/aarch64/i64_remu/signed.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const -1) + (i64.const -1) + (i64.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #-1 +;; mov x0, x16 +;; mov x16, #-1 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/tests/disas/winch/aarch64/i64_remu/zero_zero.wat b/tests/disas/winch/aarch64/i64_remu/zero_zero.wat new file mode 100644 index 000000000000..c2d2c6786daf --- /dev/null +++ b/tests/disas/winch/aarch64/i64_remu/zero_zero.wat @@ -0,0 +1,33 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result i64) + (i64.const 0) + (i64.const 0) + (i64.rem_u) + ) +) + +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x10 +;; mov x28, sp +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x16, #0 +;; mov x0, x16 +;; mov x16, #0 +;; mov x1, x16 +;; cbz x0, #0x50 +;; 34: udiv x16, x1, x0 +;; msub x1, x0, x16, x1 +;; mov x0, x1 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 50: .byte 0x1f, 0xc1, 0x00, 0x00 diff --git a/winch/codegen/src/isa/aarch64/asm.rs b/winch/codegen/src/isa/aarch64/asm.rs index 47905aba280d..78a04ae0fa2c 100644 --- a/winch/codegen/src/isa/aarch64/asm.rs +++ b/winch/codegen/src/isa/aarch64/asm.rs @@ -2,7 +2,9 @@ use super::{address::Address, regs}; use crate::aarch64::regs::zero; -use crate::masm::{DivKind, ExtendKind, FloatCmpKind, IntCmpKind, RoundingMode, ShiftKind}; +use crate::masm::{ + DivKind, ExtendKind, FloatCmpKind, IntCmpKind, RemKind, RoundingMode, ShiftKind, +}; use crate::CallingConvention; use crate::{ masm::OperandSize, @@ -462,6 +464,56 @@ impl Assembler { ); } + /// Signed/unsigned remainder operation with three registers. + pub fn rem_rrr( + &mut self, + divisor: Reg, + dividend: Reg, + dest: Writable, + kind: RemKind, + size: OperandSize, + ) { + // Check for division by 0 + self.trapz(divisor, TrapCode::INTEGER_DIVISION_BY_ZERO); + + // `cranelift-codegen` doesn't support emitting u/sdiv for anything but I64, + // we therefore sign-extend the operand. + // see: https://github.com/bytecodealliance/wasmtime/issues/9766 + if size == OperandSize::S32 { + let extend_kind = if kind.is_signed() { + ExtendKind::I64Extend32S + } else { + ExtendKind::I64ExtendI32U + }; + + self.extend(divisor, writable!(divisor), extend_kind); + self.extend(dividend, writable!(dividend), extend_kind); + } + + let op = match kind { + RemKind::Signed => ALUOp::SDiv, + RemKind::Unsigned => ALUOp::UDiv, + }; + + let scratch = regs::scratch(); + self.emit_alu_rrr( + op, + divisor, + dividend, + writable!(scratch.into()), + OperandSize::S64, + ); + + self.emit_alu_rrrr( + ALUOp3::MSub, + scratch, + divisor, + dest.map(Into::into), + dividend, + OperandSize::S64, + ); + } + /// And with three registers. pub fn and_rrr(&mut self, rm: Reg, rn: Reg, rd: WritableReg, size: OperandSize) { self.emit_alu_rrr(ALUOp::And, rm, rn, rd, size); diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index 79d0d388c70b..e4ba5619bcb5 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -483,8 +483,16 @@ impl Masm for MacroAssembler { }) } - fn rem(&mut self, _context: &mut CodeGenContext, _kind: RemKind, _size: OperandSize) { - todo!() + fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize) { + context.binop(self, size, |this, dividend, divisor, size| { + this.asm + .rem_rrr(divisor, dividend, writable!(dividend), kind, size); + match size { + OperandSize::S32 => TypedReg::new(WasmValType::I32, dividend), + OperandSize::S64 => TypedReg::new(WasmValType::I64, dividend), + s => unreachable!("invalid size for remainder: {s:?}"), + } + }) } fn zero(&mut self, reg: WritableReg) { diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index 53e97bca3cef..9cb30372fcf9 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -23,6 +23,7 @@ pub(crate) enum DivKind { } /// Remainder kind. +#[derive(Copy, Clone)] pub(crate) enum RemKind { /// Signed remainder. Signed, @@ -30,6 +31,12 @@ pub(crate) enum RemKind { Unsigned, } +impl RemKind { + pub fn is_signed(&self) -> bool { + matches!(self, Self::Signed) + } +} + #[derive(Eq, PartialEq)] pub(crate) enum MulWideKind { Signed,