master: sb-simd: Fix a bunch of bugs

stassats via Sbcl-commits <[email protected]>
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  e4e628ab84b1832297cedeb2d2613509cb6a601d (commit)
      from  62f4bd103264bf1c92fb4fc68305b8307fdd06fb (commit)

- Log -----------------------------------------------------------------
commit e4e628ab84b1832297cedeb2d2613509cb6a601d
Author: Sylvia Harrington <[email protected]>
Date:   Wed Aug 26 19:02:38 2026 +0100

    sb-simd: Fix a bunch of bugs
    
    64-bit integer min/max don't have actual instructions, fake instead
    Fix signed lane extraction not sign-extending
    Add float abs/neg
    Fix fsqrt encoding
    Fix u32.4-from-u64.2/s32.4-from-s64.2 family, wrong size
    Remove 64-bit integer vector mul, instruction doesn't exist
    Add missing exports for integer min/max
    Align spilled neon registers properly
    Validate more vector instruction forms properly
    Fix movi immediates
---
 contrib/sb-simd/code/arm64-fake-vops.lisp          |  12 ++
 contrib/sb-simd/code/define-custom-vops.lisp       |   5 +-
 contrib/sb-simd/code/instruction-sets/neon.lisp    |  34 ++--
 contrib/sb-simd/code/packages.lisp                 |  22 ++-
 .../sb-simd/test-suite/test-arm64-regressions.lisp | 179 +++++++++++++++++++++
 .../test-simple-simd-functions-arm64.lisp          |  20 +++
 src/compiler/arm64/insts.lisp                      | 145 +++++++++--------
 src/compiler/arm64/simd-pack.lisp                  |   8 +-
 src/compiler/arm64/vm.lisp                         |   6 +-
 tests/sb-simd.impure.lisp                          |   1 +
 10 files changed, 340 insertions(+), 92 deletions(-)

diff --git a/contrib/sb-simd/code/arm64-fake-vops.lisp b/contrib/sb-simd/code/arm64-fake-vops.lisp
index c8a6f7605..cacdde336 100644
--- a/contrib/sb-simd/code/arm64-fake-vops.lisp
+++ b/contrib/sb-simd/code/arm64-fake-vops.lisp
@@ -109,6 +109,12 @@
 (define-fake-vop u64.2-horizontal+ (a)
   (sb-simd::%two-arg-u64+ (%u64.2-lane-extract a 0) (%u64.2-lane-extract a 1)))
 
+(define-fake-vop two-arg-u64.2-min (a b)
+  (%u64.2-bit-select (%two-arg-u64.2> b a) a b))
+
+(define-fake-vop two-arg-u64.2-max (a b)
+  (%u64.2-bit-select (%two-arg-u64.2> a b) a b))
+
 (define-fake-vop s64.2-pair-min (a b)
   (%make-s64.2 (sb-simd::%two-arg-s64-min (%s64.2-lane-extract a 0) (%s64.2-lane-extract a 1))
                (sb-simd::%two-arg-s64-min (%s64.2-lane-extract b 0) (%s64.2-lane-extract b 1))))
@@ -129,3 +135,9 @@
 
 (define-fake-vop s64.2-horizontal+ (a)
   (sb-simd::%two-arg-s64+ (%s64.2-lane-extract a 0) (%s64.2-lane-extract a 1)))
+
+(define-fake-vop two-arg-s64.2-min (a b)
+  (%s64.2-bit-select (%two-arg-s64.2> b a) a b))
+
+(define-fake-vop two-arg-s64.2-max (a b)
+  (%s64.2-bit-select (%two-arg-s64.2> a b) a b))
diff --git a/contrib/sb-simd/code/define-custom-vops.lisp b/contrib/sb-simd/code/define-custom-vops.lisp
index af0456cc4..873f55176 100644
--- a/contrib/sb-simd/code/define-custom-vops.lisp
+++ b/contrib/sb-simd/code/define-custom-vops.lisp
@@ -313,7 +313,10 @@
                    (:info lane)
                    (:results (dst :scs (,scalar-reg)))
                    (:generator
-                    (inst umov dst src lane ,element)))
+                    (inst ,(if (and (eql sign :s) (not (eql width 64)))
+                               'smov
+                               'umov)
+                          dst src lane ,element)))
                  (define-custom-vop ,(name "~a~d.~d-LANE-INSERT" sign width count)
                      (:args (src1 :scs (int-neon-reg) :target dst)
                             (src2 :scs (,scalar-reg) :to :save))
diff --git a/contrib/sb-simd/code/instruction-sets/neon.lisp b/contrib/sb-simd/code/instruction-sets/neon.lisp
index 52d2f9c3d..096d583a5 100644
--- a/contrib/sb-simd/code/instruction-sets/neon.lisp
+++ b/contrib/sb-simd/code/instruction-sets/neon.lisp
@@ -85,6 +85,8 @@
    (f32.4-andc2       #:bic      (f32.4) (f32.4 f32.4) :cost 1 :suffix '(:16b))
    (f32.4-not         #:not      (f32.4) (f32.4)       :cost 1 :suffix '(:16b))
    (f32.4-sqrt        #:fsqrt    (f32.4) (f32.4)       :cost 15 :suffix '(:4s))
+   (f32.4-abs         #:fabs     (f32.4) (f32.4)       :cost 1 :suffix '(:4s))
+   (f32.4-neg         #:fneg     (f32.4) (f32.4)       :cost 1 :suffix '(:4s))
    (f32.4-bit-select  #:bsl      (f32.4) (u32.4 f32.4 f32.4) :cost 1 :encoding :neon-rmw :suffix '(:16b))
    (f32.4-lane-extract nil       (f32) (f32.4 imm2) :cost 1 :encoding :custom)
    (f32.4-lane-insert nil        (f32.4) (f32.4 f32 imm2) :cost 1 :encoding :custom)
@@ -133,6 +135,8 @@
    (f64.2-andc2       #:bic      (f64.2) (f64.2 f64.2) :cost 1 :suffix '(:16b))
    (f64.2-not         #:not      (f64.2) (f64.2)       :cost 1 :suffix '(:16b))
    (f64.2-sqrt        #:fsqrt    (f64.2) (f64.2)       :cost 15 :suffix '(:2d))
+   (f64.2-abs         #:fabs     (f64.2) (f64.2)       :cost 1 :suffix '(:2d))
+   (f64.2-neg         #:fneg     (f64.2) (f64.2)       :cost 1 :suffix '(:2d))
    (f64.2-bit-select  #:bsl      (f64.2) (u64.2 f64.2 f64.2) :cost 1 :encoding :neon-rmw :suffix '(:16b))
    (f64.2-lane-extract nil       (f64) (f64.2 imm1)    :cost 1 :encoding :custom)
    (f64.2-lane-insert nil        (f64.2) (f64.2 f64 imm1) :cost 1 :encoding :custom)
@@ -266,10 +270,10 @@
    (u32.4-from-f32.4  #:fcvtnu   (u32.4) (f32.4)       :cost 5 :suffix '(:4s))
    (u32.4-from-u16.8  nil        (u32.4) (u16.8)       :cost 1 :encoding :custom)
    (u32.4-from-u16.8-hi nil      (u32.4) (u16.8)       :cost 1 :encoding :custom)
-   (u32.4-from-u64.2  #:xtn      (u32.4) (u64.2)       :cost 1 :suffix '(:4h))
-   (u32.4-from-u64.2-hi #:xtn2   (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
-   (u32.4-from-u64.2-saturating #:uqxtn (u32.4) (u64.2)  :cost 1 :suffix '(:4h))
-   (u32.4-from-u64.2-saturating-hi #:uqxtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
+   (u32.4-from-u64.2  #:xtn      (u32.4) (u64.2)       :cost 1 :suffix '(:2s))
+   (u32.4-from-u64.2-hi #:xtn2   (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
+   (u32.4-from-u64.2-saturating #:uqxtn (u32.4) (u64.2)  :cost 1 :suffix '(:2s))
+   (u32.4-from-u64.2-saturating-hi #:uqxtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
    (make-u32.4        nil        (u32.4) (u32 u32 u32 u32) :cost 1 :encoding :fake-vop)
    (u32.4-values      nil        (u32 u32 u32 u32) (u32.4) :cost 1 :encoding :fake-vop)
    (u32.4-broadcast   #:dup      (u32.4) (u32)         :cost 1 :suffix '(:4s))
@@ -329,8 +333,8 @@
    (two-arg-u64.2-and #:and      (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
    (two-arg-u64.2-or  #:orr      (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
    (two-arg-u64.2-xor #:eor      (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
-   (two-arg-u64.2-max #:umax     (u64.2) (u64.2 u64.2) :cost 3 :associative t :suffix '(:2d))
-   (two-arg-u64.2-min #:umin     (u64.2) (u64.2 u64.2) :cost 3 :associative t :suffix '(:2d))
+   (two-arg-u64.2-max nil        (u64.2) (u64.2 u64.2) :cost 3 :associative t :encoding :fake-vop)
+   (two-arg-u64.2-min nil        (u64.2) (u64.2 u64.2) :cost 3 :associative t :encoding :fake-vop)
    (u64.2-andc1       nil        (u64.2) (u64.2 u64.2) :cost 1 :encoding :fake-vop)
    (u64.2-andc2       #:bic      (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:16b))
    (u64.2-not         #:not      (u64.2) (u64.2)       :cost 1 :suffix '(:16b))
@@ -338,7 +342,6 @@
    (two-arg-u64.2+-saturating #:uqadd (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d) :associative t)
    (two-arg-u64.2-    #:sub      (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d))
    (two-arg-u64.2--saturating #:uqsub (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d))
-   (two-arg-u64.2*    #:mul      (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d) :associative t)
    (two-arg-u64.2=    #:cmeq     (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:2d))
    (two-arg-u64.2/=   nil        (u64.2) (u64.2 u64.2) :cost 2 :associative t :encoding :fake-vop)
    (two-arg-u64.2>    #:cmhi     (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:2d))
@@ -478,10 +481,10 @@
    (s32.4-from-f32.4  #:fcvtns   (s32.4) (f32.4)       :cost 5 :suffix '(:4s))
    (s32.4-from-s16.8  nil        (s32.4) (s16.8)       :cost 1 :encoding :custom)
    (s32.4-from-s16.8-hi nil      (s32.4) (s16.8)       :cost 1 :encoding :custom)
-   (s32.4-from-s64.2  #:xtn      (s32.4) (s64.2)       :cost 1 :suffix '(:4h))
-   (s32.4-from-s64.2-hi #:xtn2   (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
-   (s32.4-from-s64.2-saturating #:sqxtn (s32.4) (s64.2) :cost 1 :suffix '(:4h))
-   (s32.4-from-s64.2-saturating-hi #:sqxtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
+   (s32.4-from-s64.2  #:xtn      (s32.4) (s64.2)       :cost 1 :suffix '(:2s))
+   (s32.4-from-s64.2-hi #:xtn2   (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
+   (s32.4-from-s64.2-saturating #:sqxtn (s32.4) (s64.2) :cost 1 :suffix '(:2s))
+   (s32.4-from-s64.2-saturating-hi #:sqxtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
    (make-s32.4        nil        (s32.4) (s32 s32 s32 s32) :cost 1 :encoding :fake-vop)
    (s32.4-values      nil        (s32 s32 s32 s32) (s32.4) :cost 1 :encoding :fake-vop)
    (s32.4-broadcast   #:dup      (s32.4) (s32)         :cost 1 :suffix '(:4s))
@@ -539,8 +542,8 @@
    (two-arg-s64.2-and #:and      (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
    (two-arg-s64.2-or  #:orr      (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
    (two-arg-s64.2-xor #:eor      (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
-   (two-arg-s64.2-max #:smax     (s64.2) (s64.2 s64.2) :cost 3 :associative t :suffix '(:2d))
-   (two-arg-s64.2-min #:smin     (s64.2) (s64.2 s64.2) :cost 3 :associative t :suffix '(:2d))
+   (two-arg-s64.2-max nil        (s64.2) (s64.2 s64.2) :cost 3 :associative t :encoding :fake-vop)
+   (two-arg-s64.2-min nil        (s64.2) (s64.2 s64.2) :cost 3 :associative t :encoding :fake-vop)
    (s64.2-andc1       nil        (s64.2) (s64.2 s64.2) :cost 1 :encoding :fake-vop)
    (s64.2-andc2       #:bic      (s64.2) (s64.2 s64.2) :cost 1 :suffix '(:16b))
    (s64.2-not         #:not      (s64.2) (s64.2)       :cost 1 :suffix '(:16b))
@@ -548,7 +551,6 @@
    (two-arg-s64.2+-saturating #:sqadd (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d) :associative t)
    (two-arg-s64.2-    #:sub      (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d))
    (two-arg-s64.2--saturating #:sqsub (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d))
-   (two-arg-s64.2*    #:mul      (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d) :associative t)
    (two-arg-s64.2=    #:cmeq     (u64.2) (s64.2 s64.2) :cost 1 :suffix '(:2d))
    (two-arg-s64.2/=   nil        (u64.2) (s64.2 s64.2) :cost 2 :associative t :encoding :fake-vop)
    (two-arg-s64.2>    #:cmgt     (u64.2) (s64.2 s64.2) :cost 1 :suffix '(:2d))
@@ -646,7 +648,6 @@
    (u64.2-min two-arg-u64.2-min nil)
    (u64.2+    two-arg-u64.2+ 0)
    (u64.2+-saturating two-arg-u64.2+-saturating 0)
-   (u64.2*    two-arg-u64.2* 1)
    (s8.16-and two-arg-s8.16-and +s8-true+)
    (s8.16-or  two-arg-s8.16-or  +s8-false+)
    (s8.16-xor two-arg-s8.16-xor +s8-false+)
@@ -677,8 +678,7 @@
    (s64.2-max two-arg-s64.2-max nil)
    (s64.2-min two-arg-s64.2-min nil)
    (s64.2+    two-arg-s64.2+ 0)
-   (s64.2+-saturating two-arg-s64.2+-saturating 0)
-   (s64.2*    two-arg-s64.2* 1))
+   (s64.2+-saturating two-arg-s64.2+-saturating 0))
   (:comparisons
    (f32.4=  two-arg-f32.4=  u32.4-and +u32-true+)
    (f32.4<  two-arg-f32.4<  u32.4-and +u32-true+)
diff --git a/contrib/sb-simd/code/packages.lisp b/contrib/sb-simd/code/packages.lisp
index d28bdcc86..aca8836b3 100644
--- a/contrib/sb-simd/code/packages.lisp
+++ b/contrib/sb-simd/code/packages.lisp
@@ -2170,6 +2170,8 @@
      #:f32.4-max
      #:f32.4-min
      #:f32.4-sqrt
+     #:f32.4-abs
+     #:f32.4-neg
      #:f32.4+
      #:f32.4-
      #:f32.4*
@@ -2220,6 +2222,8 @@
      #:f64.2-max
      #:f64.2-min
      #:f64.2-sqrt
+     #:f64.2-abs
+     #:f64.2-neg
      #:f64.2+
      #:f64.2-
      #:f64.2*
@@ -2268,6 +2272,8 @@
      #:u8.16-andc1
      #:u8.16-andc2
      #:u8.16-not
+     #:u8.16-min
+     #:u8.16-max
      #:u8.16+
      #:u8.16+-saturating
      #:u8.16*
@@ -2326,6 +2332,8 @@
      #:u16.8-andc1
      #:u16.8-andc2
      #:u16.8-not
+     #:u16.8-min
+     #:u16.8-max
      #:u16.8+
      #:u16.8+-saturating
      #:u16.8*
@@ -2382,6 +2390,8 @@
      #:u32.4-andc1
      #:u32.4-andc2
      #:u32.4-not
+     #:u32.4-min
+     #:u32.4-max
      #:u32.4+
      #:u32.4+-saturating
      #:u32.4*
@@ -2438,9 +2448,10 @@
      #:u64.2-andc1
      #:u64.2-andc2
      #:u64.2-not
+     #:u64.2-min
+     #:u64.2-max
      #:u64.2+
      #:u64.2+-saturating
-     #:u64.2*
      #:u64.2-
      #:u64.2--saturating
      #:u64.2=
@@ -2487,6 +2498,8 @@
      #:s8.16-andc1
      #:s8.16-andc2
      #:s8.16-not
+     #:s8.16-min
+     #:s8.16-max
      #:s8.16+
      #:s8.16+-saturating
      #:s8.16*
@@ -2540,6 +2553,8 @@
      #:s16.8-andc1
      #:s16.8-andc2
      #:s16.8-not
+     #:s16.8-min
+     #:s16.8-max
      #:s16.8+
      #:s16.8+-saturating
      #:s16.8*
@@ -2594,6 +2609,8 @@
      #:s32.4-andc1
      #:s32.4-andc2
      #:s32.4-not
+     #:s32.4-min
+     #:s32.4-max
      #:s32.4+
      #:s32.4+-saturating
      #:s32.4*
@@ -2644,9 +2661,10 @@
      #:s64.2-andc1
      #:s64.2-andc2
      #:s64.2-not
+     #:s64.2-min
+     #:s64.2-max
      #:s64.2+
      #:s64.2+-saturating
-     #:s64.2*
      #:s64.2-
      #:s64.2--saturating
      #:s64.2=
diff --git a/contrib/sb-simd/test-suite/test-arm64-regressions.lisp b/contrib/sb-simd/test-suite/test-arm64-regressions.lisp
new file mode 100644
index 000000000..f125a7730
--- /dev/null
+++ b/contrib/sb-simd/test-suite/test-arm64-regressions.lisp
@@ -0,0 +1,179 @@
+;;; Regression tests for AdvSIMD bugs found by auditing sb-simd against
+;;; the A64 instruction set.  Each test targets a bug that once produced
+;;; wrong results or illegal instructions rather than a clean error.
+
+(in-package #:sb-simd-neon)
+
+;;; Values that sit on both sides of the signed/unsigned wrap-around
+;;; point.  Random sampling almost never generates pairs like
+;;; (0, #xFFFFFFFFFFFFFFFF), so test them exhaustively.
+(defparameter *u64-boundary-values*
+  (list 0 1 2 3 5
+        #x7FFFFFFFFFFFFFFE #x7FFFFFFFFFFFFFFF
+        #x8000000000000000 #x8000000000000001
+        #xFFFFFFFFFFFFFFFD #xFFFFFFFFFFFFFFFE #xFFFFFFFFFFFFFFFF))
+
+(defparameter *s64-boundary-values*
+  (list -9223372036854775808 -9223372036854775807 -1 0 1 42
+        9223372036854775806 9223372036854775807))
+
+;;; Issue: UMAX/UMIN/SMAX/SMIN have no .2d form; max/min are fake vops
+;;; built from CMHI/CMGT plus BSL.
+(sb-simd-test-suite:define-test u64.2-max-min-boundaries
+  (dolist (a *u64-boundary-values*)
+    (dolist (b *u64-boundary-values*)
+      (let ((pa (make-u64.2 a a))
+            (pb (make-u64.2 b b)))
+        (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-max pa pb) 0) (max a b)))
+        (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-min pa pb) 0) (min a b)))))))
+
+(sb-simd-test-suite:define-test s64.2-max-min-boundaries
+  (dolist (a *s64-boundary-values*)
+    (dolist (b *s64-boundary-values*)
+      (let ((pa (make-s64.2 a a))
+            (pb (make-s64.2 b b)))
+        (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-max pa pb) 0) (max a b)))
+        (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-min pa pb) 0) (min a b)))))))
+
+;;; Random cross-check of the same fake vops against the scalar
+;;; reference implementation.
+(sb-simd-test-suite:define-test u64.2-max-min-random
+  (flet ((to-signed (x) (if (logbitp 63 x) (- x (ash 1 64)) x)))
+    (dotimes (i 2000)
+      (let* ((bits (lambda () (logior (ash (random (ash 1 32)) 32)
+                                      (random (ash 1 32)))))
+             (a0 (funcall bits)) (a1 (funcall bits))
+             (b0 (funcall bits)) (b1 (funcall bits))
+             (ua (make-u64.2 a0 a1))
+             (ub (make-u64.2 b0 b1))
+             (sa (make-s64.2 (to-signed a0) (to-signed a1)))
+             (sb (make-s64.2 (to-signed b0) (to-signed b1))))
+        (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-max ua ub) 0) (max a0 b0)))
+        (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-min ua ub) 1) (min a1 b1)))
+        (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-max sa sb) 0)
+               (max (to-signed a0) (to-signed b0))))
+        (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-min sa sb) 1)
+               (min (to-signed a1) (to-signed b1))))))))
+
+;;; Issue: the XTN-family narrowing records used .4h/.8h suffixes,
+;;; silently computing a 32-to-16-bit narrowing on 64-bit lanes.
+(sb-simd-test-suite:define-test u32.4-from-u64.2-narrowing
+  ;; Plain narrowing takes the low half of each lane and zeroes the rest.
+  (let ((r (u32.4-from-u64.2 (make-u64.2 #x1111111122222222
+                                         #x3333333344444444))))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) #x22222222))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) #x44444444))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) 0))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) 0)))
+  ;; Saturating narrowing clamps into the target range.
+  (let ((r (u32.4-from-u64.2-saturating (make-u64.2 #xFFFFFFFFFFFFFFFF 3))))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) #xFFFFFFFF))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 3)))
+  ;; The -hi variants append to the high half and preserve the low half.
+  (let ((r (u32.4-from-u64.2-hi (make-u32.4 10 20 30 40)
+                                (make-u64.2 #x1111111122222222
+                                            #x3333333344444444))))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) 10))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 20))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) #x22222222))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) #x44444444)))
+  (let ((r (u32.4-from-u64.2-saturating-hi
+            (make-u32.4 10 20 30 40)
+            (make-u64.2 #xFFFFFFFFFFFFFFFF #xFFFFFFFFFFFFFFFF))))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) 10))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 20))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) #xFFFFFFFF))
+    (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) #xFFFFFFFF))))
+
+(sb-simd-test-suite:define-test s32.4-from-s64.2-narrowing
+  (let ((r (s32.4-from-s64.2 (make-s64.2 -5 #x7000000011112222))))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) -5))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) #x11112222))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 2) 0))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 3) 0)))
+  ;; Saturation clamps in both directions.
+  (let ((r (s32.4-from-s64.2-saturating
+            (make-s64.2 #x7FFFFFFFFFFFFFFF -99999999999999))))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) most-positive-s32))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) most-negative-s32)))
+  (let ((r (s32.4-from-s64.2-hi (make-s32.4 10 20 30 40)
+                                (make-s64.2 -5 #x7000000011112222))))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) 10))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) 20))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 2) -5))
+    (sb-simd-test-suite:is (= (s32.4-lane-extract r 3) #x11112222))))
+
+;;; Issue: signed lane extraction returned zero-extended values because
+;;; the custom vops emitted UMOV instead of SMOV.
+(sb-simd-test-suite:define-test signed-lane-extraction-sign-extends
+  (let ((v (make-s8.16 -128 -1 127 42 0 -42 1 -127 2 -2 3 -3 4 -4 5 -5)))
+    (loop for expected in '(-128 -1 127 42 0 -42 1 -127 2 -2 3 -3 4 -4 5 -5)
+          for i from 0
+          do (sb-simd-test-suite:is (= (s8.16-lane-extract v i) expected))))
+  (let ((v (make-s16.8 -32768 -1 32767 12345 -5432 0 1 -1)))
+    (loop for expected in '(-32768 -1 32767 12345 -5432 0 1 -1)
+          for i from 0
+          do (sb-simd-test-suite:is (= (s16.8-lane-extract v i) expected))))
+  (let ((v (make-s32.4 -2147483648 -1 2147483647 42)))
+    (loop for expected in '(-2147483648 -1 2147483647 42)
+          for i from 0
+          do (sb-simd-test-suite:is (= (s32.4-lane-extract v i) expected))))
+  ;; Unsigned shapes must remain unaffected.
+  (let ((v (make-u8.16 255 254 253 252 0 1 2 3 4 5 6 7 8 9 10 11)))
+    (sb-simd-test-suite:is (= (u8.16-lane-extract v 0) 255))
+    (sb-simd-test-suite:is (= (u8.16-lane-extract v 3) 252))))
+
+;;; Issue: emit-movi-vector-imm passed replicated broadcast patterns to
+;;; MOVI instead of lane immediates, aborting compilation with "bad
+;;; immediate".  Every constant below is materialized through that code
+;;; path; several exercise the shifted-cmode forms.  The tests are split
+;;; into several functions because packing too many distinct vector
+;;; constants into one function currently overflows the LDR spill
+;;; offset range - see issue about large SIMD constant pools.
+(sb-simd-test-suite:define-test integer-broadcast-constants-simple
+  ;; The original reproducer: 1 does not fit MOVI's simple .8h form.
+  (let ((r (u16.8-and (u16.8-broadcast 5) 1)))
+    (sb-simd-test-suite:is (= (u16.8-lane-extract r 0) 1))
+    (sb-simd-test-suite:is (= (u16.8-lane-extract r 7) 1)))
+  ;; Shifted immediates (low byte zero).
+  (let ((r (u16.8-and (u16.8-broadcast #x0100) #x0100)))
+    (sb-simd-test-suite:is (= (u16.8-lane-extract r 3) #x0100)))
+  ;; Byte-replicated patterns.
+  (dolist (c (list 0 1 #x7F #x80 #xFF))
+    (let ((r (u8.16-or (u8.16-broadcast c) (u8.16-broadcast c))))
+      (sb-simd-test-suite:is (= (u8.16-lane-extract r 15) c)))))
+
+(sb-simd-test-suite:define-test integer-broadcast-constants-word
+  ;; 32-bit constants with shifted bytes.
+  (dolist (c (list 0 1 255 256 #xFFFF #x10000 #xFF0000 #xFF000000))
+    (let ((r (u32.4-and (u32.4-broadcast c) (u32.4-broadcast c))))
+      (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) c)))))
+
+;;; Bit-replication patterns (.2d MOVI form): every byte is 0 or #xFF.
+(sb-simd-test-suite:define-test integer-broadcast-constants-bit-replicated
+  (dolist (c (list #xFF00FF00FF00FF00
+                   #x8000000000000000
+                   #xFFFFFFFFFFFFFFFF
+                   #x7F7F7F7F7F7F7F7F
+                   #x00FF00FF00FF00FF))
+    (let ((r (u64.2-and (u64.2-broadcast c) (u64.2-broadcast c))))
+      (sb-simd-test-suite:is (= (u64.2-lane-extract r 0) c))
+      (sb-simd-test-suite:is (= (u64.2-lane-extract r 1) c)))))
+
+;;; Patterns that fit no MOVI form fall back to register synthesis
+;;; (MOVZ/DUP or logical-immediate ORR).
+(sb-simd-test-suite:define-test integer-broadcast-constants-synthesized
+  (dolist (c (list #x0102030405060708 #xDEADBEEFCAFEBABE))
+    (let ((r (u64.2-and (u64.2-broadcast c) (u64.2-broadcast c))))
+      (sb-simd-test-suite:is (= (u64.2-lane-extract r 1) c)))))
+
+;;; Float constants take a different path (movi-immediate-p guarded);
+;;; keep them covered too.
+(sb-simd-test-suite:define-test float-broadcast-constants
+  (let ((r (f32.4-max (make-f32.4 0.5 -1.0 2.0 3.0) 1.0f0)))
+    (sb-simd-test-suite:is (= (f32.4-lane-extract r 0) 1.0f0))
+    (sb-simd-test-suite:is (= (f32.4-lane-extract r 1) 1.0f0))
+    (sb-simd-test-suite:is (= (f32.4-lane-extract r 2) 2.0f0)))
+  (let ((r (f64.2-min (make-f64.2 0.5d0 -5d0) -1d0)))
+    (sb-simd-test-suite:is (= (f64.2-lane-extract r 0) -1d0))
+    (sb-simd-test-suite:is (= (f64.2-lane-extract r 1) -5d0))))
diff --git a/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp b/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
index 280d4184b..8ad454e4c 100644
--- a/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
+++ b/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
@@ -8,6 +8,8 @@
 (sb-simd-test-suite:define-simple-simd-test f32.4-not (f32.4) (f32.4) f32-not)
 (sb-simd-test-suite:define-simple-simd-test f32.4-max (f32.4) (f32.4 &rest f32.4) f32-max)
 (sb-simd-test-suite:define-simple-simd-test f32.4-min (f32.4) (f32.4 &rest f32.4) f32-min)
+(sb-simd-test-suite:define-simple-simd-test f32.4-abs (f32.4) (f32.4) abs)
+(sb-simd-test-suite:define-simple-simd-test f32.4-neg (f32.4) (f32.4) -)
 (sb-simd-test-suite:define-simple-simd-test f32.4+ (f32.4) (&rest f32.4) f32+)
 (sb-simd-test-suite:define-simple-simd-test f32.4- (f32.4) (f32.4 &rest f32.4) f32-)
 (sb-simd-test-suite:define-simple-simd-test f32.4* (f32.4) (&rest f32.4) f32*)
@@ -26,6 +28,8 @@
 (sb-simd-test-suite:define-simple-simd-test f64.2-not (f64.2) (f64.2) f64-not)
 (sb-simd-test-suite:define-simple-simd-test f64.2-max (f64.2) (f64.2 &rest f64.2) f64-max)
 (sb-simd-test-suite:define-simple-simd-test f64.2-min (f64.2) (f64.2 &rest f64.2) f64-min)
+(sb-simd-test-suite:define-simple-simd-test f64.2-abs (f64.2) (f64.2) abs)
+(sb-simd-test-suite:define-simple-simd-test f64.2-neg (f64.2) (f64.2) -)
 (sb-simd-test-suite:define-simple-simd-test f64.2+ (f64.2) (&rest f64.2) f64+)
 (sb-simd-test-suite:define-simple-simd-test f64.2- (f64.2) (f64.2 &rest f64.2) f64-)
 (sb-simd-test-suite:define-simple-simd-test f64.2* (f64.2) (&rest f64.2) f64*)
@@ -42,6 +46,8 @@
 (sb-simd-test-suite:define-simple-simd-test u8.16-xor (u8.16) (&rest u8.16) u8-xor)
 (sb-simd-test-suite:define-simple-simd-test u8.16-andc1 (u8.16) (u8.16 u8.16) u8-andc1)
 (sb-simd-test-suite:define-simple-simd-test u8.16-not (u8.16) (u8.16) u8-not)
+(sb-simd-test-suite:define-simple-simd-test u8.16-max (u8.16) (u8.16 &rest u8.16) u8-max)
+(sb-simd-test-suite:define-simple-simd-test u8.16-min (u8.16) (u8.16 &rest u8.16) u8-min)
 (sb-simd-test-suite:define-simple-simd-test u8.16+ (u8.16) (&rest u8.16) u8+)
 (sb-simd-test-suite:define-simple-simd-test u8.16- (u8.16) (u8.16 &rest u8.16) u8-)
 (sb-simd-test-suite:define-simple-simd-test u8.16= (u8.16) (u8.16 &rest u8.16) u8=)
@@ -56,6 +62,8 @@
 (sb-simd-test-suite:define-simple-simd-test u16.8-xor (u16.8) (&rest u16.8) u16-xor)
 (sb-simd-test-suite:define-simple-simd-test u16.8-andc1 (u16.8) (u16.8 u16.8) u16-andc1)
 (sb-simd-test-suite:define-simple-simd-test u16.8-not (u16.8) (u16.8) u16-not)
+(sb-simd-test-suite:define-simple-simd-test u16.8-max (u16.8) (u16.8 &rest u16.8) u16-max)
+(sb-simd-test-suite:define-simple-simd-test u16.8-min (u16.8) (u16.8 &rest u16.8) u16-min)
 (sb-simd-test-suite:define-simple-simd-test u16.8+ (u16.8) (&rest u16.8) u16+)
 (sb-simd-test-suite:define-simple-simd-test u16.8- (u16.8) (u16.8 &rest u16.8) u16-)
 (sb-simd-test-suite:define-simple-simd-test u16.8= (u16.8) (u16.8 &rest u16.8) u16=)
@@ -70,6 +78,8 @@
 (sb-simd-test-suite:define-simple-simd-test u32.4-xor (u32.4) (&rest u32.4) u32-xor)
 (sb-simd-test-suite:define-simple-simd-test u32.4-andc1 (u32.4) (u32.4 u32.4) u32-andc1)
 (sb-simd-test-suite:define-simple-simd-test u32.4-not (u32.4) (u32.4) u32-not)
+(sb-simd-test-suite:define-simple-simd-test u32.4-max (u32.4) (u32.4 &rest u32.4) u32-max)
+(sb-simd-test-suite:define-simple-simd-test u32.4-min (u32.4) (u32.4 &rest u32.4) u32-min)
 (sb-simd-test-suite:define-simple-simd-test u32.4+ (u32.4) (&rest u32.4) u32+)
 (sb-simd-test-suite:define-simple-simd-test u32.4- (u32.4) (u32.4 &rest u32.4) u32-)
 (sb-simd-test-suite:define-simple-simd-test u32.4= (u32.4) (u32.4 &rest u32.4) u32=)
@@ -84,6 +94,8 @@
 (sb-simd-test-suite:define-simple-simd-test u64.2-xor (u64.2) (&rest u64.2) u64-xor)
 (sb-simd-test-suite:define-simple-simd-test u64.2-andc1 (u64.2) (u64.2 u64.2) u64-andc1)
 (sb-simd-test-suite:define-simple-simd-test u64.2-not (u64.2) (u64.2) u64-not)
+(sb-simd-test-suite:define-simple-simd-test u64.2-max (u64.2) (u64.2 &rest u64.2) u64-max)
+(sb-simd-test-suite:define-simple-simd-test u64.2-min (u64.2) (u64.2 &rest u64.2) u64-min)
 (sb-simd-test-suite:define-simple-simd-test u64.2+ (u64.2) (&rest u64.2) u64+)
 (sb-simd-test-suite:define-simple-simd-test u64.2- (u64.2) (u64.2 &rest u64.2) u64-)
 (sb-simd-test-suite:define-simple-simd-test u64.2= (u64.2) (u64.2 &rest u64.2) u64=)
@@ -98,6 +110,8 @@
 (sb-simd-test-suite:define-simple-simd-test s8.16-xor (s8.16) (&rest s8.16) s8-xor)
 (sb-simd-test-suite:define-simple-simd-test s8.16-andc1 (s8.16) (s8.16 s8.16) s8-andc1)
 (sb-simd-test-suite:define-simple-simd-test s8.16-not (s8.16) (s8.16) s8-not)
+(sb-simd-test-suite:define-simple-simd-test s8.16-max (s8.16) (s8.16 &rest s8.16) s8-max)
+(sb-simd-test-suite:define-simple-simd-test s8.16-min (s8.16) (s8.16 &rest s8.16) s8-min)
 (sb-simd-test-suite:define-simple-simd-test s8.16+ (s8.16) (&rest s8.16) s8+)
 (sb-simd-test-suite:define-simple-simd-test s8.16- (s8.16) (s8.16 &rest s8.16) s8-)
 (sb-simd-test-suite:define-simple-simd-test s8.16= (u8.16) (s8.16 &rest s8.16) s8=)
@@ -112,6 +126,8 @@
 (sb-simd-test-suite:define-simple-simd-test s16.8-xor (s16.8) (&rest s16.8) s16-xor)
 (sb-simd-test-suite:define-simple-simd-test s16.8-andc1 (s16.8) (s16.8 s16.8) s16-andc1)
 (sb-simd-test-suite:define-simple-simd-test s16.8-not (s16.8) (s16.8) s16-not)
+(sb-simd-test-suite:define-simple-simd-test s16.8-max (s16.8) (s16.8 &rest s16.8) s16-max)
+(sb-simd-test-suite:define-simple-simd-test s16.8-min (s16.8) (s16.8 &rest s16.8) s16-min)
 (sb-simd-test-suite:define-simple-simd-test s16.8+ (s16.8) (&rest s16.8) s16+)
 (sb-simd-test-suite:define-simple-simd-test s16.8- (s16.8) (s16.8 &rest s16.8) s16-)
 (sb-simd-test-suite:define-simple-simd-test s16.8= (u16.8) (s16.8 &rest s16.8) s16=)
@@ -126,6 +142,8 @@
 (sb-simd-test-suite:define-simple-simd-test s32.4-xor (s32.4) (&rest s32.4) s32-xor)
 (sb-simd-test-suite:define-simple-simd-test s32.4-andc1 (s32.4) (s32.4 s32.4) s32-andc1)
 (sb-simd-test-suite:define-simple-simd-test s32.4-not (s32.4) (s32.4) s32-not)
+(sb-simd-test-suite:define-simple-simd-test s32.4-max (s32.4) (s32.4 &rest s32.4) s32-max)
+(sb-simd-test-suite:define-simple-simd-test s32.4-min (s32.4) (s32.4 &rest s32.4) s32-min)
 (sb-simd-test-suite:define-simple-simd-test s32.4+ (s32.4) (&rest s32.4) s32+)
 (sb-simd-test-suite:define-simple-simd-test s32.4- (s32.4) (s32.4 &rest s32.4) s32-)
 (sb-simd-test-suite:define-simple-simd-test s32.4= (u32.4) (s32.4 &rest s32.4) s32=)
@@ -140,6 +158,8 @@
 (sb-simd-test-suite:define-simple-simd-test s64.2-xor (s64.2) (&rest s64.2) s64-xor)
 (sb-simd-test-suite:define-simple-simd-test s64.2-andc1 (s64.2) (s64.2 s64.2) s64-andc1)
 (sb-simd-test-suite:define-simple-simd-test s64.2-not (s64.2) (s64.2) s64-not)
+(sb-simd-test-suite:define-simple-simd-test s64.2-max (s64.2) (s64.2 &rest s64.2) s64-max)
+(sb-simd-test-suite:define-simple-simd-test s64.2-min (s64.2) (s64.2 &rest s64.2) s64-min)
 (sb-simd-test-suite:define-simple-simd-test s64.2+ (s64.2) (&rest s64.2) s64+)
 (sb-simd-test-suite:define-simple-simd-test s64.2- (s64.2) (s64.2 &rest s64.2) s64-)
 (sb-simd-test-suite:define-simple-simd-test s64.2= (u64.2) (s64.2 &rest s64.2) s64=)
diff --git a/src/compiler/arm64/insts.lisp b/src/compiler/arm64/insts.lisp
index 234b9b5c3..70023117c 100644
--- a/src/compiler/arm64/insts.lisp
+++ b/src/compiler/arm64/insts.lisp
@@ -2810,38 +2810,42 @@
                                  (fpr-offset rd)))))
 
 (defmacro def-fp-data-processing-1+simd (name op
-                                         simd-u simd-neg simd-op)
+                                         simd-u simd-neg simd-op6 simd-op)
   `(define-instruction ,name (segment rd rn &optional vector-size)
      (:printer fp-data-processing-1 ((op ,op)))
-     (:printer simd-two-same-float ((u ,simd-u) (neg ,simd-neg) (op ,simd-op)))
+     (:printer simd-two-same-float ((u ,simd-u) (neg ,simd-neg) (op6 ,simd-op6)
+                                    (op ,simd-op)))
      (:emitter
       (assert (and (eq (tn-sc rd)
                        (tn-sc rn)))
               (rd rn)
               "Arguments should have the same FP storage class: ~s ~s." rd rn)
-      (if vector-size
-          (multiple-value-bind (q size) (encode-vector-size vector-size)
-            (emit-simd-two-same-float
-             segment
-             q
-             ,simd-u
-             ,simd-neg
-             (logand 1 size)
-             ,simd-op
-             (fpr-offset rn)
-             (fpr-offset rd)))
-          (emit-fp-data-processing-1 segment
-                                     (fp-reg-type rn)
-                                     ,op
-                                     (fpr-offset rn)
-                                     (fpr-offset rd))))))
+      (cond (vector-size
+             (aver (member vector-size '(:2s :4s :2d)))
+             (multiple-value-bind (q size) (encode-vector-size vector-size)
+               (emit-simd-two-same-float
+                segment
+                q
+                ,simd-u
+                ,simd-neg
+                (logand 1 size)
+                ,simd-op6
+                ,simd-op
+                (fpr-offset rn)
+                (fpr-offset rd))))
+            (t
+             (emit-fp-data-processing-1 segment
+                                        (fp-reg-type rn)
+                                        ,op
+                                        (fpr-offset rn)
+                                        (fpr-offset rd)))))))
 
 (def-fp-data-processing-1+simd fabs #b0001
-  #b0 #b1 #b11111)
+  #b0 #b1 #b00000 #b11111)
 (def-fp-data-processing-1+simd fneg #b0010
-  #b1 #b1 #b11111)
+  #b1 #b1 #b00000 #b11111)
 (def-fp-data-processing-1+simd fsqrt #b0011
-  #b1 #b0 #b11111)
+  #b1 #b1 #b00001 #b11111)
 (def-fp-data-processing-1 frintn #b1000)
 (def-fp-data-processing-1 frintp #b1001)
 (def-fp-data-processing-1 frintm #b1010)
@@ -2888,24 +2892,26 @@
      (:printer fp-data-processing-2 ((op ,op)))
      (:printer simd-three-same-float ((u ,simd-u) (neg ,simd-neg) (op ,simd-op)))
      (:emitter
-      (if vector-size
-          (multiple-value-bind (q size) (encode-vector-size vector-size)
-            (emit-simd-three-same-float
-             segment
-             q
-             ,simd-u
-             ,simd-neg
-             (logand 1 size)
-             (fpr-offset rm)
-             ,simd-op
-             (fpr-offset rn)
-             (fpr-offset rd)))
-          (emit-fp-data-processing-2 segment
-                                     (fp-reg-type rn)
-                                     (fpr-offset rm)
-                                     ,op
-                                     (fpr-offset rn)
-                                     (fpr-offset rd))))))
+      (cond (vector-size
+             (aver (member vector-size '(:2s :4s :2d)))
+             (multiple-value-bind (q size) (encode-vector-size vector-size)
+               (emit-simd-three-same-float
+                segment
+                q
+                ,simd-u
+                ,simd-neg
+                (logand 1 size)
+                (fpr-offset rm)
+                ,simd-op
+                (fpr-offset rn)
+                (fpr-offset rd))))
+            (t
+             (emit-fp-data-processing-2 segment
+                                        (fp-reg-type rn)
+                                        (fpr-offset rm)
+                                        ,op
+                                        (fpr-offset rn)
+                                        (fpr-offset rd)))))))
 
 (def-fp-data-processing-2+simd fmul #b0000
   #b1 #b0 #b11011)
@@ -3479,8 +3485,8 @@
   (neg 1 23)
   (size 1 22)
   (#b1 1 21)
-  (#b00000 5 16)
-  (opc 5 11)
+  (op6 5 16)
+  (op 5 11)
   (#b0 1 10)
   (rn 5 5)
   (rd 5 0))
@@ -3533,10 +3539,10 @@
   (op3 :field (byte 1 31) :value #b0)
   (u :field (byte 1 29))
   (op4 :field (byte 5 24) :value #b01110)
-  (neg :field (byte 1 23))
+  (neg :field (byte 1 23) :value #b1)
   (size :field (byte 1 22))
   (op5 :field (byte 1 21) :value #b1)
-  (op6 :field (byte 5 16) :value #b00000)
+  (op6 :field (byte 5 16))
   (op :field (byte 5 11))
   (op7 :field (byte 1 10) :value #b0)
   (rn :fields (list (byte 1 30) (byte 1 22) (byte 5 5)) :type 'simd-float-reg)
@@ -3612,7 +3618,9 @@
   (def bit #b1 #b10 #b00011)
   (def bif #b1 #b11 #b00011))
 
-(macrolet ((def (name u op &optional zero-u zero)
+(macrolet ((def (name u op &optional
+                              (2d t)
+                              zero-u zero)
              `(define-instruction ,name (segment rd rn rm size)
                 ,@(when op
                     `((:printer simd-three-same-sized ((u ,u) (op ,op)))))
@@ -3620,6 +3628,9 @@
                     `((:printer simd-two-misc ((u ,zero-u) (op ,zero))
                                 '(:name :tab rd ", " rn ", " "#0"))))
                 (:emitter
+                 (aver (member size ',(if 2d
+                                          '(:8b :16b :4h :8h :2s :4s :2d)
+                                          '(:8b :16b :4h :8h :2s :4s))))
                  (multiple-value-bind (q size) (encode-vector-size size)
                    (cond ,@(when zero
                              `(((eql rm 0)
@@ -3644,32 +3655,32 @@
                                                       (fpr-offset rd))
                                `(error "Can be compared only with zero, not ~s" rm)))))))))
   (def cmtst #b0 #b10001)
-  (def cmeq #b1 #b10001 0 #b01001)
-  (def cmgt #b0 #b00110 0 #b01000)
-  (def cmge #b0 #b00111 1 #b01000)
-  (def cmlt nil nil 0 #b01010)
-  (def cmle nil nil 1 #b01001)
+  (def cmeq #b1 #b10001 t 0 #b01001)
+  (def cmgt #b0 #b00110 t 0 #b01000)
+  (def cmge #b0 #b00111 t 1 #b01000)
+  (def cmlt nil nil t 0 #b01010)
+  (def cmle nil nil t 1 #b01001)
   (def cmhi #b1 #b00110)
   (def cmhs #b1 #b00111)
-  (def umin #b1 #b01101)
-  (def umax #b1 #b01100)
-  (def smin #b0 #b01101)
-  (def smax #b0 #b01100)
-  (def uhadd #b1 #b00000)
+  (def umin #b1 #b01101 nil)
+  (def umax #b1 #b01100 nil)
+  (def smin #b0 #b01101 nil)
+  (def smax #b0 #b01100 nil)
+  (def uhadd #b1 #b00000 nil)
   (def uqadd #b1 #b00001)
-  (def urhadd #b1 #b00010)
-  (def uhsub #b1 #b00100)
+  (def urhadd #b1 #b00010 nil)
+  (def uhsub #b1 #b00100 nil)
   (def uqsub #b1 #b00101)
   (def addp #b0 #b10111)
-  (def shadd #b0 #b00000)
+  (def shadd #b0 #b00000 nil)
   (def sqadd #b0 #b00001)
-  (def srhadd #b0 #b00010)
-  (def shsub #b0 #b00100)
+  (def srhadd #b0 #b00010 nil)
+  (def shsub #b0 #b00100 nil)
   (def sqsub #b0 #b00101)
-  (def uminp #b1 #b10101)
-  (def umaxp #b1 #b10100)
-  (def sminp #b0 #b10101)
-  (def smaxp #b0 #b10100)
+  (def uminp #b1 #b10101 nil)
+  (def umaxp #b1 #b10100 nil)
+  (def sminp #b0 #b10101 nil)
+  (def smaxp #b0 #b10100 nil)
   (def sshl #b0 #b01001)
   (def ushl #b1 #b01001))
 
@@ -3677,6 +3688,7 @@
              `(define-instruction ,name (segment rd rn rm size)
                 (:printer simd-three-same-float ((u ,u) (neg ,neg) (op ,op)))
                 (:emitter
+                 (aver (member size '(:2s :4s :2d)))
                  (multiple-value-bind (q size) (encode-vector-size size)
                    (emit-simd-three-same-float
                     segment
@@ -3759,6 +3771,7 @@
                                                          (fpr-offset rn)
                                                          (fpr-offset rd)))
                        (t
+                        (aver (member vector-size '(:2s :4s :2d)))
                         (multiple-value-bind (q size) (encode-vector-size vector-size)
                           (emit-simd-three-same-float
                            segment
@@ -4082,6 +4095,7 @@
                 (:printer simd-across-lanes  ((u ,u) (op ,op)
                                               (rd nil :type 'vbhs)))
                 (:emitter
+                 (aver (member size '(:8b :16b :4h :8h :2s :4s)))
                  (multiple-value-bind (q size) (encode-vector-size size)
                    (emit-simd-across-lanes
                     segment
@@ -4171,6 +4185,7 @@
        `(define-instruction ,name (segment rd rn size)
           (:printer simd-two-misc ((u ,u) (op ,op) (rd nil :type 'simd-reg-2x)))
           (:emitter
+           (aver (member size '(:8b :16b :4h :8h :2s :4s)))
            (multiple-value-bind (q size) (encode-vector-size size)
              (emit-simd-two-misc segment
                                  q
@@ -4366,8 +4381,8 @@
                                      (fpr-offset rn)
                                      (fpr-offset rd)))))))
   (def shl #b0 #b01010 nil t)
-  (def sli #b1 #b01010)
-  (def sri #b1 #b01000 t)
+  (def sli #b1 #b01010 nil t)
+  (def sri #b1 #b01000 t t)
   (def sshr #b0 #b00000 t t)
   (def shrn #b0 #b10000 t)
   (def ssra #b0 #b00010 t t)
diff --git a/src/compiler/arm64/simd-pack.lisp b/src/compiler/arm64/simd-pack.lisp
index 2f4811365..6cedbe04f 100644
--- a/src/compiler/arm64/simd-pack.lisp
+++ b/src/compiler/arm64/simd-pack.lisp
@@ -35,13 +35,13 @@
                 (zerop (dpb 0 (byte 8 8) (ldb (byte 32 0) value)))
                 (zerop (dpb 0 (byte 8 16) (ldb (byte 32 0) value)))
                 (zerop (dpb 0 (byte 8 24) (ldb (byte 32 0) value)))))
-       (inst movi dst value :4s))
+       (inst movi dst (ldb (byte 32 0) value) :4s))
       ((and wordp
             (or (zerop (dpb 0 (byte 8 0) (ldb (byte 16 0) value)))
                 (zerop (dpb 0 (byte 8 8) (ldb (byte 16 0) value)))))
-       (inst movi dst value :8h))
+       (inst movi dst (ldb (byte 16 0) value) :8h))
       (bytep
-       (inst movi dst value :16b))
+       (inst movi dst (ldb (byte 8 0) value) :16b))
       ((and (member (ldb (byte 8 0) value) '(0 #xFF))
             (member (ldb (byte 8 8) value) '(0 #xFF))
             (member (ldb (byte 8 16) value) '(0 #xFF))
@@ -50,7 +50,7 @@
             (member (ldb (byte 8 40) value) '(0 #xFF))
             (member (ldb (byte 8 48) value) '(0 #xFF))
             (member (ldb (byte 8 56) value) '(0 #xFF)))
-       (inst movi value :2d))
+       (inst movi dst value :2d))
       ;; Can't do movi, try via the scalar regs.
       (wordp
        (inst movz tmp-tn (ldb (byte 16 0) value))
diff --git a/src/compiler/arm64/vm.lisp b/src/compiler/arm64/vm.lisp
index 7067eff56..e38541185 100644
--- a/src/compiler/arm64/vm.lisp
+++ b/src/compiler/arm64/vm.lisp
@@ -148,11 +148,11 @@
   (complex-single-stack non-descriptor-stack)
   (complex-double-stack non-descriptor-stack :element-size 2 :alignment 2)
   #+sb-simd-pack
-  (int-neon-stack non-descriptor-stack :element-size 2)
+  (int-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
   #+sb-simd-pack
-  (double-neon-stack non-descriptor-stack :element-size 2)
+  (double-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
   #+sb-simd-pack
-  (single-neon-stack non-descriptor-stack :element-size 2)
+  (single-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
 
   ;; **** Things that can go in the integer registers.
 
diff --git a/tests/sb-simd.impure.lisp b/tests/sb-simd.impure.lisp
index 0e647a95c..a71bd9b8d 100644
--- a/tests/sb-simd.impure.lisp
+++ b/tests/sb-simd.impure.lisp
@@ -28,6 +28,7 @@
                   "test-horizontal-functions.lisp"
                   #+x86-64 "test-horizontal-functions-x86-64.lisp"
                   #+arm64 "test-horizontal-functions-arm64.lisp"
+                  #+arm64 "test-arm64-regressions.lisp"
                   "test-hairy-simd-functions.lisp"
                   "test-packages.lisp"))
     (load (merge-pathnames file #P"../contrib/sb-simd/test-suite/"))))

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.