From a4a4c94538fc2e83ea376ea0d14f07a29825eec8 Mon Sep 17 00:00:00 2001 From: Edoardo Vacchi Date: Fri, 26 Apr 2024 14:57:49 +0200 Subject: [PATCH] winch(aarch64): abs, ceil, floor, nearest, trunc, neg, sqrt (#8425) * winch(amd64): more fpu Signed-off-by: Edoardo Vacchi * Add tests Signed-off-by: Edoardo Vacchi --------- Signed-off-by: Edoardo Vacchi --- .../winch/aarch64/f32_abs/f32_abs_const.wat | 26 ++++++++++ .../winch/aarch64/f32_abs/f32_abs_param.wat | 25 +++++++++ .../winch/aarch64/f32_ceil/f32_ceil_const.wat | 26 ++++++++++ .../winch/aarch64/f32_ceil/f32_ceil_param.wat | 25 +++++++++ .../aarch64/f32_floor/f32_floor_const.wat | 26 ++++++++++ .../aarch64/f32_floor/f32_floor_param.wat | 25 +++++++++ .../aarch64/f32_nearest/f32_nearest_const.wat | 26 ++++++++++ .../aarch64/f32_nearest/f32_nearest_param.wat | 25 +++++++++ .../winch/aarch64/f32_neg/f32_neg_const.wat | 26 ++++++++++ .../winch/aarch64/f32_neg/f32_neg_param.wat | 25 +++++++++ .../winch/aarch64/f32_sqrt/f32_sqrt_const.wat | 26 ++++++++++ .../winch/aarch64/f32_sqrt/f32_sqrt_param.wat | 25 +++++++++ .../aarch64/f32_trunc/f32_trunc_const.wat | 26 ++++++++++ .../aarch64/f32_trunc/f32_trunc_param.wat | 25 +++++++++ .../winch/aarch64/f64_abs/f64_abs_const.wat | 28 ++++++++++ .../winch/aarch64/f64_abs/f64_abs_param.wat | 25 +++++++++ .../winch/aarch64/f64_ceil/f64_ceil_const.wat | 28 ++++++++++ .../winch/aarch64/f64_ceil/f64_ceil_param.wat | 25 +++++++++ .../aarch64/f64_floor/f64_floor_const.wat | 28 ++++++++++ .../aarch64/f64_floor/f64_floor_param.wat | 25 +++++++++ .../aarch64/f64_nearest/f64_nearest_const.wat | 28 ++++++++++ .../aarch64/f64_nearest/f64_nearest_param.wat | 25 +++++++++ .../winch/aarch64/f64_neg/f64_neg_const.wat | 28 ++++++++++ .../winch/aarch64/f64_neg/f64_neg_param.wat | 25 +++++++++ .../winch/aarch64/f64_sqrt/f64_sqrt_const.wat | 28 ++++++++++ .../winch/aarch64/f64_sqrt/f64_sqrt_param.wat | 25 +++++++++ .../aarch64/f64_trunc/f64_trunc_const.wat | 28 ++++++++++ .../aarch64/f64_trunc/f64_trunc_param.wat | 25 +++++++++ winch/codegen/src/isa/aarch64/asm.rs | 51 ++++++++++++++++++- winch/codegen/src/isa/aarch64/masm.rs | 22 ++++---- winch/codegen/src/masm.rs | 1 + 31 files changed, 791 insertions(+), 11 deletions(-) create mode 100644 tests/disas/winch/aarch64/f32_abs/f32_abs_const.wat create mode 100644 tests/disas/winch/aarch64/f32_abs/f32_abs_param.wat create mode 100644 tests/disas/winch/aarch64/f32_ceil/f32_ceil_const.wat create mode 100644 tests/disas/winch/aarch64/f32_ceil/f32_ceil_param.wat create mode 100644 tests/disas/winch/aarch64/f32_floor/f32_floor_const.wat create mode 100644 tests/disas/winch/aarch64/f32_floor/f32_floor_param.wat create mode 100644 tests/disas/winch/aarch64/f32_nearest/f32_nearest_const.wat create mode 100644 tests/disas/winch/aarch64/f32_nearest/f32_nearest_param.wat create mode 100644 tests/disas/winch/aarch64/f32_neg/f32_neg_const.wat create mode 100644 tests/disas/winch/aarch64/f32_neg/f32_neg_param.wat create mode 100644 tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_const.wat create mode 100644 tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_param.wat create mode 100644 tests/disas/winch/aarch64/f32_trunc/f32_trunc_const.wat create mode 100644 tests/disas/winch/aarch64/f32_trunc/f32_trunc_param.wat create mode 100644 tests/disas/winch/aarch64/f64_abs/f64_abs_const.wat create mode 100644 tests/disas/winch/aarch64/f64_abs/f64_abs_param.wat create mode 100644 tests/disas/winch/aarch64/f64_ceil/f64_ceil_const.wat create mode 100644 tests/disas/winch/aarch64/f64_ceil/f64_ceil_param.wat create mode 100644 tests/disas/winch/aarch64/f64_floor/f64_floor_const.wat create mode 100644 tests/disas/winch/aarch64/f64_floor/f64_floor_param.wat create mode 100644 tests/disas/winch/aarch64/f64_nearest/f64_nearest_const.wat create mode 100644 tests/disas/winch/aarch64/f64_nearest/f64_nearest_param.wat create mode 100644 tests/disas/winch/aarch64/f64_neg/f64_neg_const.wat create mode 100644 tests/disas/winch/aarch64/f64_neg/f64_neg_param.wat create mode 100644 tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_const.wat create mode 100644 tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_param.wat create mode 100644 tests/disas/winch/aarch64/f64_trunc/f64_trunc_const.wat create mode 100644 tests/disas/winch/aarch64/f64_trunc/f64_trunc_param.wat diff --git a/tests/disas/winch/aarch64/f32_abs/f32_abs_const.wat b/tests/disas/winch/aarch64/f32_abs/f32_abs_const.wat new file mode 100644 index 0000000000..cdb3284254 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_abs/f32_abs_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.abs) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; fabs s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_abs/f32_abs_param.wat b/tests/disas/winch/aarch64/f32_abs/f32_abs_param.wat new file mode 100644 index 0000000000..e798ed68f6 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_abs/f32_abs_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.abs) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; fabs s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_ceil/f32_ceil_const.wat b/tests/disas/winch/aarch64/f32_ceil/f32_ceil_const.wat new file mode 100644 index 0000000000..3ad47e206f --- /dev/null +++ b/tests/disas/winch/aarch64/f32_ceil/f32_ceil_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.ceil) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; frintp s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_ceil/f32_ceil_param.wat b/tests/disas/winch/aarch64/f32_ceil/f32_ceil_param.wat new file mode 100644 index 0000000000..b60ee329cf --- /dev/null +++ b/tests/disas/winch/aarch64/f32_ceil/f32_ceil_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.ceil) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; frintp s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_floor/f32_floor_const.wat b/tests/disas/winch/aarch64/f32_floor/f32_floor_const.wat new file mode 100644 index 0000000000..18877fe373 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_floor/f32_floor_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.floor) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; frintm s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_floor/f32_floor_param.wat b/tests/disas/winch/aarch64/f32_floor/f32_floor_param.wat new file mode 100644 index 0000000000..f850d6b29c --- /dev/null +++ b/tests/disas/winch/aarch64/f32_floor/f32_floor_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.floor) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; frintm s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_nearest/f32_nearest_const.wat b/tests/disas/winch/aarch64/f32_nearest/f32_nearest_const.wat new file mode 100644 index 0000000000..fec5431948 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_nearest/f32_nearest_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.nearest) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; frintn s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_nearest/f32_nearest_param.wat b/tests/disas/winch/aarch64/f32_nearest/f32_nearest_param.wat new file mode 100644 index 0000000000..fe716327d7 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_nearest/f32_nearest_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.nearest) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; frintn s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_neg/f32_neg_const.wat b/tests/disas/winch/aarch64/f32_neg/f32_neg_const.wat new file mode 100644 index 0000000000..7998653eaf --- /dev/null +++ b/tests/disas/winch/aarch64/f32_neg/f32_neg_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.neg) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; fneg s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_neg/f32_neg_param.wat b/tests/disas/winch/aarch64/f32_neg/f32_neg_param.wat new file mode 100644 index 0000000000..24d6548bb2 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_neg/f32_neg_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.neg) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; fneg s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_const.wat b/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_const.wat new file mode 100644 index 0000000000..4c10b9ed69 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const 1.32) + (f32.sqrt) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0x3fa8, lsl #16 +;; fmov s0, w16 +;; fsqrt s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_param.wat b/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_param.wat new file mode 100644 index 0000000000..9c1e4c4f8e --- /dev/null +++ b/tests/disas/winch/aarch64/f32_sqrt/f32_sqrt_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.sqrt) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; fsqrt s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_trunc/f32_trunc_const.wat b/tests/disas/winch/aarch64/f32_trunc/f32_trunc_const.wat new file mode 100644 index 0000000000..263b3e6711 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_trunc/f32_trunc_const.wat @@ -0,0 +1,26 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f32) + (f32.const -1.32) + (f32.trunc) + ) +) +;; 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 w16, #0xf5c3 +;; movk w16, #0xbfa8, lsl #16 +;; fmov s0, w16 +;; frintz s0, s0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f32_trunc/f32_trunc_param.wat b/tests/disas/winch/aarch64/f32_trunc/f32_trunc_param.wat new file mode 100644 index 0000000000..3df3e3b036 --- /dev/null +++ b/tests/disas/winch/aarch64/f32_trunc/f32_trunc_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f32) (result f32) + (local.get 0) + (f32.trunc) + ) +) +;; 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 w0, [x28, #4] +;; ldur w0, [x28, #4] +;; frintz s0, s0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_abs/f64_abs_const.wat b/tests/disas/winch/aarch64/f64_abs/f64_abs_const.wat new file mode 100644 index 0000000000..066de19546 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_abs/f64_abs_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.abs) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; fabs d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_abs/f64_abs_param.wat b/tests/disas/winch/aarch64/f64_abs/f64_abs_param.wat new file mode 100644 index 0000000000..bbc7d51ea2 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_abs/f64_abs_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.abs) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; fabs d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_ceil/f64_ceil_const.wat b/tests/disas/winch/aarch64/f64_ceil/f64_ceil_const.wat new file mode 100644 index 0000000000..9da2b062e7 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_ceil/f64_ceil_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.ceil) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; frintp d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_ceil/f64_ceil_param.wat b/tests/disas/winch/aarch64/f64_ceil/f64_ceil_param.wat new file mode 100644 index 0000000000..8a4b391cea --- /dev/null +++ b/tests/disas/winch/aarch64/f64_ceil/f64_ceil_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.ceil) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; frintp d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_floor/f64_floor_const.wat b/tests/disas/winch/aarch64/f64_floor/f64_floor_const.wat new file mode 100644 index 0000000000..b99ed31387 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_floor/f64_floor_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.floor) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; frintm d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_floor/f64_floor_param.wat b/tests/disas/winch/aarch64/f64_floor/f64_floor_param.wat new file mode 100644 index 0000000000..819933f788 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_floor/f64_floor_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.floor) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; frintm d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_nearest/f64_nearest_const.wat b/tests/disas/winch/aarch64/f64_nearest/f64_nearest_const.wat new file mode 100644 index 0000000000..c30cb810ba --- /dev/null +++ b/tests/disas/winch/aarch64/f64_nearest/f64_nearest_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.nearest) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; frintn d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_nearest/f64_nearest_param.wat b/tests/disas/winch/aarch64/f64_nearest/f64_nearest_param.wat new file mode 100644 index 0000000000..d83cd32ee9 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_nearest/f64_nearest_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.nearest) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; frintn d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_neg/f64_neg_const.wat b/tests/disas/winch/aarch64/f64_neg/f64_neg_const.wat new file mode 100644 index 0000000000..11307202df --- /dev/null +++ b/tests/disas/winch/aarch64/f64_neg/f64_neg_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.neg) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; fneg d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_neg/f64_neg_param.wat b/tests/disas/winch/aarch64/f64_neg/f64_neg_param.wat new file mode 100644 index 0000000000..07bcc1a0ca --- /dev/null +++ b/tests/disas/winch/aarch64/f64_neg/f64_neg_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.neg) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; fneg d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_const.wat b/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_const.wat new file mode 100644 index 0000000000..dc69fbad23 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const 1.32) + (f64.sqrt) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0x3ff5, lsl #48 +;; fmov d0, x16 +;; fsqrt d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_param.wat b/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_param.wat new file mode 100644 index 0000000000..a1e9002e91 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_sqrt/f64_sqrt_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.sqrt) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; fsqrt d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_trunc/f64_trunc_const.wat b/tests/disas/winch/aarch64/f64_trunc/f64_trunc_const.wat new file mode 100644 index 0000000000..134eea48d7 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_trunc/f64_trunc_const.wat @@ -0,0 +1,28 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (result f64) + (f64.const -1.32) + (f64.trunc) + ) +) +;; 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, #0x851f +;; movk x16, #0x51eb, lsl #16 +;; movk x16, #0x1eb8, lsl #32 +;; movk x16, #0xbff5, lsl #48 +;; fmov d0, x16 +;; frintz d0, d0 +;; add sp, sp, #0x10 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/aarch64/f64_trunc/f64_trunc_param.wat b/tests/disas/winch/aarch64/f64_trunc/f64_trunc_param.wat new file mode 100644 index 0000000000..6089eefc19 --- /dev/null +++ b/tests/disas/winch/aarch64/f64_trunc/f64_trunc_param.wat @@ -0,0 +1,25 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (param f64) (result f64) + (local.get 0) + (f64.trunc) + ) +) +;; 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 x0, [x28] +;; ldur x0, [x28] +;; frintz d0, d0 +;; add sp, sp, #0x18 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/winch/codegen/src/isa/aarch64/asm.rs b/winch/codegen/src/isa/aarch64/asm.rs index bd0e519d92..fb2aedc129 100644 --- a/winch/codegen/src/isa/aarch64/asm.rs +++ b/winch/codegen/src/isa/aarch64/asm.rs @@ -1,8 +1,9 @@ //! Assembler library implementation for Aarch64. use super::{address::Address, regs}; +use crate::masm::RoundingMode; use crate::{masm::OperandSize, reg::Reg}; -use cranelift_codegen::isa::aarch64::inst::{FPUOp2, ScalarSize}; +use cranelift_codegen::isa::aarch64::inst::{FPUOp1, FPUOp2, FpuRoundMode, ScalarSize}; use cranelift_codegen::{ ir::{MemFlags, SourceLoc}, isa::aarch64::inst::{ @@ -264,6 +265,37 @@ impl Assembler { self.emit_fpu_rrr(FPUOp2::Min, rm, rn, rd, size); } + /// Float neg with two registers. + pub fn fneg_rr(&mut self, rn: Reg, rd: Reg, size: OperandSize) { + self.emit_fpu_rr(FPUOp1::Neg, rn, rd, size); + } + + /// Float abs with two registers. + pub fn fabs_rr(&mut self, rn: Reg, rd: Reg, size: OperandSize) { + self.emit_fpu_rr(FPUOp1::Abs, rn, rd, size); + } + + /// Float sqrt with two registers. + pub fn fsqrt_rr(&mut self, rn: Reg, rd: Reg, size: OperandSize) { + self.emit_fpu_rr(FPUOp1::Sqrt, rn, rd, size); + } + + /// Float round (ceil, trunc, floor) with two registers. + pub fn fround_rr(&mut self, rn: Reg, rd: Reg, mode: RoundingMode, size: OperandSize) { + let fpu_mode = match (mode, size) { + (RoundingMode::Nearest, OperandSize::S32) => FpuRoundMode::Nearest32, + (RoundingMode::Up, OperandSize::S32) => FpuRoundMode::Plus32, + (RoundingMode::Down, OperandSize::S32) => FpuRoundMode::Minus32, + (RoundingMode::Zero, OperandSize::S32) => FpuRoundMode::Zero32, + (RoundingMode::Nearest, OperandSize::S64) => FpuRoundMode::Nearest64, + (RoundingMode::Up, OperandSize::S64) => FpuRoundMode::Plus64, + (RoundingMode::Down, OperandSize::S64) => FpuRoundMode::Minus64, + (RoundingMode::Zero, OperandSize::S64) => FpuRoundMode::Zero64, + (m, o) => panic!("Invalid rounding mode or operand size {:?}, {:?}", m, o), + }; + self.emit_fpu_round(fpu_mode, rn, rd) + } + /// Return instruction. pub fn ret(&mut self) { self.emit(Inst::Ret {}); @@ -313,6 +345,23 @@ impl Assembler { }); } + fn emit_fpu_rr(&mut self, op: FPUOp1, rn: Reg, rd: Reg, size: OperandSize) { + self.emit(Inst::FpuRR { + fpu_op: op, + size: size.into(), + rd: Writable::from_reg(rd.into()), + rn: rn.into(), + }); + } + + fn emit_fpu_round(&mut self, op: FpuRoundMode, rn: Reg, rd: Reg) { + self.emit(Inst::FpuRound { + op: op, + rd: Writable::from_reg(rd.into()), + rn: rn.into(), + }); + } + /// Get a label from the underlying machine code buffer. pub fn get_label(&mut self) -> MachLabel { self.buffer.get_label() diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index 3b86dbf7f2..39cc2083ff 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -316,27 +316,29 @@ impl Masm for MacroAssembler { todo!() } - fn float_neg(&mut self, _dst: Reg, _size: OperandSize) { - todo!() + fn float_neg(&mut self, dst: Reg, size: OperandSize) { + self.asm.fneg_rr(dst, dst, size); } - fn float_abs(&mut self, _dst: Reg, _size: OperandSize) { - todo!() + fn float_abs(&mut self, dst: Reg, size: OperandSize) { + self.asm.fabs_rr(dst, dst, size); } fn float_round, &mut CodeGenContext, &mut Self)>( &mut self, - _mode: RoundingMode, + mode: RoundingMode, _env: &mut FuncEnv, - _context: &mut CodeGenContext, - _size: OperandSize, + context: &mut CodeGenContext, + size: OperandSize, _fallback: F, ) { - todo!(); + let src = context.pop_to_reg(self, None); + self.asm.fround_rr(src.into(), src.into(), mode, size); + context.stack.push(src.into()); } - fn float_sqrt(&mut self, _dst: Reg, _src: Reg, _size: OperandSize) { - todo!() + fn float_sqrt(&mut self, dst: Reg, src: Reg, size: OperandSize) { + self.asm.fsqrt_rr(src, dst, size); } fn and(&mut self, _dst: Reg, _lhs: Reg, _rhs: RegImm, _size: OperandSize) { diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index 4f18842a1f..38dbf02976 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -425,6 +425,7 @@ impl From for RegImm { } } +#[derive(Debug)] pub enum RoundingMode { Nearest, Up,