From 31a6aa52b69d20c6950ba08b7367beec0f690794 Mon Sep 17 00:00:00 2001 From: macovedj Date: Tue, 21 Jul 2026 17:32:05 -0500 Subject: [PATCH] winch(aarch64): v128 shift ops --- .../winch/aarch64/v128_ops/i16x8_shl.wat | 47 +++++++++++++++++ .../winch/aarch64/v128_ops/i16x8_shr_s.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i16x8_shr_u.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i32x4_shl.wat | 47 +++++++++++++++++ .../winch/aarch64/v128_ops/i32x4_shr_s.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i32x4_shr_u.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i64x2_shl.wat | 47 +++++++++++++++++ .../winch/aarch64/v128_ops/i64x2_shr_s.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i64x2_shr_u.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i8x16_shl.wat | 47 +++++++++++++++++ .../winch/aarch64/v128_ops/i8x16_shr_s.wat | 51 +++++++++++++++++++ .../winch/aarch64/v128_ops/i8x16_shr_u.wat | 51 +++++++++++++++++++ winch/codegen/src/isa/aarch64/asm.rs | 5 ++ winch/codegen/src/isa/aarch64/masm.rs | 48 +++++++++++++++-- 14 files changed, 645 insertions(+), 4 deletions(-) create mode 100644 tests/disas/winch/aarch64/v128_ops/i16x8_shl.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i16x8_shr_s.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i16x8_shr_u.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i32x4_shl.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i32x4_shr_s.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i32x4_shr_u.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i64x2_shl.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i64x2_shr_s.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i64x2_shr_u.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i8x16_shl.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i8x16_shr_s.wat create mode 100644 tests/disas/winch/aarch64/v128_ops/i8x16_shr_u.wat diff --git a/tests/disas/winch/aarch64/v128_ops/i16x8_shl.wat b/tests/disas/winch/aarch64/v128_ops/i16x8_shl.wat new file mode 100644 index 000000000000..41358badf47d --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i16x8_shl.wat @@ -0,0 +1,47 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i16x8.shl + (v128.const i16x8 32768 1 65535 16384 2 3 4 5) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x7c +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x80 +;; and w0, w0, #0xf +;; dup v31.8h, w0 +;; sshl v0.8h, v0.8h, v31.8h +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 7c: udf #0xc11f +;; 80: .byte 0x00, 0x80, 0x01, 0x00 +;; 84: .byte 0xff, 0xff, 0x00, 0x40 +;; 88: .byte 0x02, 0x00, 0x03, 0x00 +;; 8c: .byte 0x04, 0x00, 0x05, 0x00 diff --git a/tests/disas/winch/aarch64/v128_ops/i16x8_shr_s.wat b/tests/disas/winch/aarch64/v128_ops/i16x8_shr_s.wat new file mode 100644 index 000000000000..0dfbbe1d828d --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i16x8_shr_s.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i16x8.shr_s + (v128.const i16x8 32768 1 65535 16384 2 3 4 5) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x90 +;; and w0, w0, #0xf +;; neg x0, x0 +;; dup v31.8h, w0 +;; sshl v0.8h, v0.8h, v31.8h +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x00, 0x80, 0x01, 0x00 +;; 94: .byte 0xff, 0xff, 0x00, 0x40 +;; 98: .byte 0x02, 0x00, 0x03, 0x00 +;; 9c: .byte 0x04, 0x00, 0x05, 0x00 diff --git a/tests/disas/winch/aarch64/v128_ops/i16x8_shr_u.wat b/tests/disas/winch/aarch64/v128_ops/i16x8_shr_u.wat new file mode 100644 index 000000000000..e98bffd3661b --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i16x8_shr_u.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i16x8.shr_u + (v128.const i16x8 32768 1 65535 16384 2 3 4 5) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x90 +;; and w0, w0, #0xf +;; neg x0, x0 +;; dup v31.8h, w0 +;; ushl v0.8h, v0.8h, v31.8h +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x00, 0x80, 0x01, 0x00 +;; 94: .byte 0xff, 0xff, 0x00, 0x40 +;; 98: .byte 0x02, 0x00, 0x03, 0x00 +;; 9c: .byte 0x04, 0x00, 0x05, 0x00 diff --git a/tests/disas/winch/aarch64/v128_ops/i32x4_shl.wat b/tests/disas/winch/aarch64/v128_ops/i32x4_shl.wat new file mode 100644 index 000000000000..813e321e48d3 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i32x4_shl.wat @@ -0,0 +1,47 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i32x4.shl + (v128.const i32x4 0x80000000 1 0xFFFFFFFF 7) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x7c +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x80 +;; and w0, w0, #0x1f +;; dup v31.4s, w0 +;; sshl v0.4s, v0.4s, v31.4s +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 7c: udf #0xc11f +;; 80: .byte 0x00, 0x00, 0x00, 0x80 +;; 84: udf #1 +;; 88: .byte 0xff, 0xff, 0xff, 0xff +;; 8c: udf #7 diff --git a/tests/disas/winch/aarch64/v128_ops/i32x4_shr_s.wat b/tests/disas/winch/aarch64/v128_ops/i32x4_shr_s.wat new file mode 100644 index 000000000000..4fbf27559505 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i32x4_shr_s.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i32x4.shr_s + (v128.const i32x4 0x80000000 1 0xFFFFFFFF 7) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x90 +;; and w0, w0, #0x1f +;; neg x0, x0 +;; dup v31.4s, w0 +;; sshl v0.4s, v0.4s, v31.4s +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x00, 0x00, 0x00, 0x80 +;; 94: udf #1 +;; 98: .byte 0xff, 0xff, 0xff, 0xff +;; 9c: udf #7 diff --git a/tests/disas/winch/aarch64/v128_ops/i32x4_shr_u.wat b/tests/disas/winch/aarch64/v128_ops/i32x4_shr_u.wat new file mode 100644 index 000000000000..d2216b16add5 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i32x4_shr_u.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i32x4.shr_u + (v128.const i32x4 0x80000000 1 0xFFFFFFFF 7) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x90 +;; and w0, w0, #0x1f +;; neg x0, x0 +;; dup v31.4s, w0 +;; ushl v0.4s, v0.4s, v31.4s +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x00, 0x00, 0x00, 0x80 +;; 94: udf #1 +;; 98: .byte 0xff, 0xff, 0xff, 0xff +;; 9c: udf #7 diff --git a/tests/disas/winch/aarch64/v128_ops/i64x2_shl.wat b/tests/disas/winch/aarch64/v128_ops/i64x2_shl.wat new file mode 100644 index 000000000000..cdd0f7a1ea09 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i64x2_shl.wat @@ -0,0 +1,47 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i64x2.shl + (v128.const i64x2 0x8000000000000000 0xFFFFFFFFFFFFFFFF) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x7c +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x80 +;; and w0, w0, #0x3f +;; dup v31.2d, x0 +;; sshl v0.2d, v0.2d, v31.2d +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 7c: udf #0xc11f +;; 80: udf #0 +;; 84: .byte 0x00, 0x00, 0x00, 0x80 +;; 88: .byte 0xff, 0xff, 0xff, 0xff +;; 8c: .byte 0xff, 0xff, 0xff, 0xff diff --git a/tests/disas/winch/aarch64/v128_ops/i64x2_shr_s.wat b/tests/disas/winch/aarch64/v128_ops/i64x2_shr_s.wat new file mode 100644 index 000000000000..eaebafd7978b --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i64x2_shr_s.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i64x2.shr_s + (v128.const i64x2 0x8000000000000000 0xFFFFFFFFFFFFFFFF) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x90 +;; and w0, w0, #0x3f +;; neg x0, x0 +;; dup v31.2d, x0 +;; sshl v0.2d, v0.2d, v31.2d +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: udf #0 +;; 94: .byte 0x00, 0x00, 0x00, 0x80 +;; 98: .byte 0xff, 0xff, 0xff, 0xff +;; 9c: .byte 0xff, 0xff, 0xff, 0xff diff --git a/tests/disas/winch/aarch64/v128_ops/i64x2_shr_u.wat b/tests/disas/winch/aarch64/v128_ops/i64x2_shr_u.wat new file mode 100644 index 000000000000..4eacd622354d --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i64x2_shr_u.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i64x2.shr_u + (v128.const i64x2 0x8000000000000000 0xFFFFFFFFFFFFFFFF) + (i32.const 2))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #2 +;; ldr q0, #0x90 +;; and w0, w0, #0x3f +;; neg x0, x0 +;; dup v31.2d, x0 +;; ushl v0.2d, v0.2d, v31.2d +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: udf #0 +;; 94: .byte 0x00, 0x00, 0x00, 0x80 +;; 98: .byte 0xff, 0xff, 0xff, 0xff +;; 9c: .byte 0xff, 0xff, 0xff, 0xff diff --git a/tests/disas/winch/aarch64/v128_ops/i8x16_shl.wat b/tests/disas/winch/aarch64/v128_ops/i8x16_shl.wat new file mode 100644 index 000000000000..696532a9c1b0 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i8x16_shl.wat @@ -0,0 +1,47 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i8x16.shl + (v128.const i8x16 128 1 255 64 2 250 7 8 9 10 11 12 13 14 15 16) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x7c +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x80 +;; and w0, w0, #7 +;; dup v31.16b, w0 +;; sshl v0.16b, v0.16b, v31.16b +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 7c: udf #0xc11f +;; 80: .byte 0x80, 0x01, 0xff, 0x40 +;; 84: stlxrb w7, w2, [x16] +;; 88: .byte 0x09, 0x0a, 0x0b, 0x0c +;; 8c: adr x13, #0x1e24c diff --git a/tests/disas/winch/aarch64/v128_ops/i8x16_shr_s.wat b/tests/disas/winch/aarch64/v128_ops/i8x16_shr_s.wat new file mode 100644 index 000000000000..81227e98b69a --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i8x16_shr_s.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i8x16.shr_s + (v128.const i8x16 128 1 255 64 2 250 7 8 9 10 11 12 13 14 15 16) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x90 +;; and w0, w0, #7 +;; neg x0, x0 +;; dup v31.16b, w0 +;; sshl v0.16b, v0.16b, v31.16b +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x80, 0x01, 0xff, 0x40 +;; 94: stlxrb w7, w2, [x16] +;; 98: .byte 0x09, 0x0a, 0x0b, 0x0c +;; 9c: adr x13, #0x1e25c diff --git a/tests/disas/winch/aarch64/v128_ops/i8x16_shr_u.wat b/tests/disas/winch/aarch64/v128_ops/i8x16_shr_u.wat new file mode 100644 index 000000000000..cf2e76a5aa64 --- /dev/null +++ b/tests/disas/winch/aarch64/v128_ops/i8x16_shr_u.wat @@ -0,0 +1,51 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (memory 1) + (func (export "run") + (v128.store (i32.const 0) + (i8x16.shr_u + (v128.const i8x16 128 1 255 64 2 250 7 8 9 10 11 12 13 14 15 16) + (i32.const 3))))) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; str x28, [sp, #-0x10]! +;; mov x28, sp +;; ldur x16, [x0, #8] +;; ldur x16, [x16, #0x18] +;; mov x17, #0 +;; movk x17, #0x10 +;; add x16, x16, x17 +;; cmp sp, x16 +;; b.lo #0x80 +;; 2c: mov x9, x0 +;; sub x28, x28, #0x10 +;; mov sp, x28 +;; stur x0, [x28, #8] +;; stur x1, [x28] +;; mov x0, #3 +;; ldr q0, #0x90 +;; and w0, w0, #7 +;; neg x0, x0 +;; dup v31.16b, w0 +;; ushl v0.16b, v0.16b, v31.16b +;; mov x0, #0 +;; ldur x1, [x9, #0x38] +;; add x1, x1, w0, uxtw +;; stur q0, [x1] +;; add x28, x28, #0x10 +;; mov sp, x28 +;; mov sp, x28 +;; ldr x28, [sp], #0x10 +;; ldp x29, x30, [sp], #0x10 +;; ret +;; 80: udf #0xc11f +;; 84: udf #0 +;; 88: udf #0 +;; 8c: udf #0 +;; 90: .byte 0x80, 0x01, 0xff, 0x40 +;; 94: stlxrb w7, w2, [x16] +;; 98: .byte 0x09, 0x0a, 0x0b, 0x0c +;; 9c: adr x13, #0x1e25c diff --git a/winch/codegen/src/isa/aarch64/asm.rs b/winch/codegen/src/isa/aarch64/asm.rs index 2a8d485f52c4..ec9cb3976686 100644 --- a/winch/codegen/src/isa/aarch64/asm.rs +++ b/winch/codegen/src/isa/aarch64/asm.rs @@ -660,6 +660,11 @@ impl Assembler { self.alu_rrr_extend(ALUOp::Sub, rm, rn, rd, size, ExtendOp::UXTX); } + /// Negate a general-purpose register. + pub fn neg_rr(&mut self, rn: Reg, rd: WritableReg, size: OperandSize) { + self.alu_rrr(ALUOp::Sub, rn, zero(), rd, size); + } + /// Subtract with three registers, setting flags. pub fn subs_rrr(&mut self, rm: Reg, rn: Reg, rd: WritableReg, size: OperandSize) { self.alu_rrr_extend(ALUOp::SubS, rm, rn, rd, size, ExtendOp::UXTX); diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index f66873b92ab4..d747f8ae7285 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -1868,11 +1868,51 @@ impl Masm for MacroAssembler { fn v128_shift( &mut self, - _context: &mut CodeGenContext, - _lane_width: OperandSize, - _shift_kind: ShiftKind, + context: &mut CodeGenContext, + lane_width: OperandSize, + shift_kind: ShiftKind, ) -> Result<()> { - Err(format_err!(CodeGenError::unimplemented_masm_instruction())) + let shift_amount = context.pop_to_reg(self, None)?.reg; + let operand = context.pop_to_reg(self, None)?.reg; + let amount_mask = lane_width.num_bits() - 1; + self.and( + writable!(shift_amount), + shift_amount, + RegImm::i32(amount_mask as i32), + OperandSize::S32, + )?; + + let size = match lane_width { + OperandSize::S8 => VectorSize::Size8x16, + OperandSize::S16 => VectorSize::Size16x8, + OperandSize::S32 => VectorSize::Size32x4, + OperandSize::S64 => VectorSize::Size64x2, + _ => bail!(CodeGenError::unexpected_operand_size()), + }; + + let (op, negate) = match shift_kind { + ShiftKind::Shl => (VecALUOp::Sshl, false), + ShiftKind::ShrS => (VecALUOp::Sshl, true), + ShiftKind::ShrU => (VecALUOp::Ushl, true), + ShiftKind::Rotl | ShiftKind::Rotr => { + bail!(CodeGenError::unimplemented_masm_instruction()) + } + }; + + if negate { + self.asm + .neg_rr(shift_amount, writable!(shift_amount), OperandSize::S64); + } + + self.with_scratch::(|masm, tmp| { + masm.asm.vec_dup(shift_amount, tmp.writable(), size); + masm.asm + .vec_rrr(op, operand, tmp.inner(), writable!(operand), size); + }); + + context.free_reg(shift_amount); + context.stack.push(TypedReg::v128(operand).into()); + Ok(()) } fn v128_q15mulr_sat_s(