master: arm64: More simd instructions

stassats via Sbcl-commits <[email protected]> Tue, 30 Jun 2026 22:46:53 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  bb63ab41bff760762ec43564844f0a928116f6bb (commit)
      from  ba8d93710c549d87e66597a9ce69803f2857a07c (commit)

- Log -----------------------------------------------------------------
commit bb63ab41bff760762ec43564844f0a928116f6bb
Author: Sylvia Harrington <[email protected]>
Date:   Sun Jun 28 10:22:44 2026 +0100

    arm64: More simd instructions
---
 src/compiler/arm64/insts.lisp        | 365 +++++++++++++++++++++++++++++------
 src/compiler/arm64/target-insts.lisp |   5 +
 2 files changed, 312 insertions(+), 58 deletions(-)

diff --git a/src/compiler/arm64/insts.lisp b/src/compiler/arm64/insts.lisp
index 7eb8d0688..8f757b4af 100644
--- a/src/compiler/arm64/insts.lisp
+++ b/src/compiler/arm64/insts.lisp
@@ -119,6 +119,7 @@
   (define-arg-type simd-copy-reg :printer #'print-simd-copy-reg)
   (define-arg-type simd-dup-reg :printer #'print-simd-dup-reg)
   (define-arg-type simd-float-reg :printer #'print-simd-float-reg)
+  (define-arg-type simd-float-pair-reg :printer #'print-simd-float-pair-reg)
   (define-arg-type simd-dup-float-reg :printer #'print-simd-dup-float-reg)
 
   (define-arg-type simd-immh-reg :printer #'print-simd-immh-reg)
@@ -1287,7 +1288,6 @@
                               (gpr-offset rd)))))
 
 (def-data-processing-1 rbit #b000)
-(def-data-processing-1 rev16 #b001)
 (def-data-processing-1 clz #b100)
 (def-data-processing-1 cls #b101)
 
@@ -1417,8 +1417,29 @@
 (def-data-processing-3 smsubl #b001 1)
 (def-data-processing-3 umsubl #b101 1)
 
-(define-instruction-macro mul (rd rn rm)
-  `(inst madd ,rd ,rn ,rm zr-tn))
+(define-instruction mul (segment rd rn rm &optional vector-size)
+  (:printer simd-three-same-sized ((u #b0) (op #b10011)))
+  (:emitter
+   (if vector-size
+       (multiple-value-bind (q size)
+           (encode-vector-size vector-size)
+         (emit-simd-three-same segment
+                               q
+                               #b0
+                               size
+                               (fpr-offset rm)
+                               #b10011
+                               (fpr-offset rn)
+                               (fpr-offset rd)))
+       ;; madd
+       (emit-data-processing-3 segment
+                               (reg-size rd)
+                               #b000
+                               (gpr-offset rm)
+                               0
+                               (gpr-offset zr-tn)
+                               (gpr-offset rn)
+                               (gpr-offset rd)))))
 
 (define-instruction smulh (segment rd rn rm)
   (:printer data-processing-3 ((op31 #b010) (o0 0) (ra 31))
@@ -2731,7 +2752,8 @@
   #b0 #b1 #b11111)
 (def-fp-data-processing-1+simd fneg #b0010
   #b1 #b1 #b11111)
-(def-fp-data-processing-1 fsqrt #b0011)
+(def-fp-data-processing-1+simd fsqrt #b0011
+  #b1 #b0 #b11111)
 (def-fp-data-processing-1 frintn #b1000)
 (def-fp-data-processing-1 frintp #b1001)
 (def-fp-data-processing-1 frintm #b1010)
@@ -2805,10 +2827,14 @@
   #b0 #b0 #b11010)
 (def-fp-data-processing-2+simd fsub #b0011
   #b0 #b1 #b11010)
-(def-fp-data-processing-2 fmax #b0100)
-(def-fp-data-processing-2 fmin #b0101)
-(def-fp-data-processing-2 fmaxnm #b0110)
-(def-fp-data-processing-2 fminnm #b0111)
+(def-fp-data-processing-2+simd fmax #b0100
+  #b0 #b0 #b11110)
+(def-fp-data-processing-2+simd fmin #b0101
+  #b0 #b1 #b11110)
+(def-fp-data-processing-2+simd fmaxnm #b0110
+  #b0 #b0 #b11000)
+(def-fp-data-processing-2+simd fminnm #b0111
+  #b0 #b1 #b11000)
 (def-fp-data-processing-2 fnmul #b1000)
 
 (defmacro def-fp-data-processing-3 (name o1 o2)
@@ -2868,10 +2894,51 @@
                          (reg-offset rn)
                          (reg-offset rd)))))
 
-(def-fp-conversion fcvtns #b00000)
-(def-fp-conversion fcvtnu #b00001)
-(def-fp-conversion scvtf #b00010 t)
-(def-fp-conversion ucvtf #b00011 t)
+(defmacro def-fp-conversion+simd (name op &optional from-int simd-u simd-op)
+  `(define-instruction ,name (segment rd rn &optional vector-size)
+     (:printer fp-conversion ((op ,op) (,(if from-int
+                                               'rn
+                                               'rd)
+                                          nil :type 'reg)))
+     (:printer simd-two-misc ((u ,simd-u) (op ,simd-op)))
+     (:emitter
+      (if vector-size
+          (multiple-value-bind (q size)
+              (encode-vector-float-size vector-size)
+            (emit-simd-two-misc segment
+                                q
+                                ,simd-u
+                                size
+                                ,simd-op
+                                (fpr-offset rn)
+                                (fpr-offset rd)))
+          (progn
+            ,@(if from-int
+                  `((assert (fp-register-p rd)
+                            (rd)
+                            "Destination ~d should be an FP register." rd)
+                    (assert (register-p rn)
+                            (rn)
+                            "Source ~d should be an integer register." rn))
+                  `((assert (register-p rd)
+                            (rd)
+                            "Destination ~d should be an integer register." rn)
+                    (assert (fp-register-p rn)
+                            (rn)
+                            "Source ~d should be an FP register." rn)))
+            (emit-fp-conversion segment
+                                +64-bit-size+
+                                (fp-reg-type ,(if from-int
+                                                  'rd
+                                                  'rn))
+                                ,op
+                                (reg-offset rn)
+                                (reg-offset rd)))))))
+
+(def-fp-conversion+simd fcvtns #b00000 nil #b0 #b11100)
+(def-fp-conversion+simd fcvtnu #b00001 nil #b1 #b11100)
+(def-fp-conversion+simd scvtf #b00010 t #b0 #b11101)
+(def-fp-conversion+simd ucvtf #b00011 t #b1 #b11101)
 (def-fp-conversion fcvtas #b00100)
 (def-fp-conversion fcvtau #b00101)
 (def-fp-conversion fcvtps #b01000)
@@ -3162,6 +3229,20 @@
   (rn 5 5)
   (rd 5 0))
 
+(define-instruction-format (simd-three-diff 32
+                            :default-printer '(:name :tab rd ", " rn ", " rm))
+  (op3 :field (byte 1 31) :value #b0)
+  (q :field (byte 1 30))
+  (u :field (byte 1 29))
+  (op4 :field (byte 5 24) :value #b01110)
+  (size :field (byte 2 22))
+  (op5 :field (byte 1 21) :value #b1)
+  (rm :fields (list (byte 1 30) (byte 2 22) (byte 5 16)) :type 'simd-reg)
+  (op :field (byte 4 12))
+  (op6 :field (byte 2 10) :value #b00)
+  (rn :fields (list (byte 1 30) (byte 2 22) (byte 5 5)) :type 'simd-reg)
+  (rd :fields (list (byte 1 30) (byte 2 22) (byte 5 0)) :type 'simd-reg))
+
 (def-emitter simd-three-same
   (#b0 1 31)
   (q 1 30)
@@ -3262,6 +3343,35 @@
     (:1d (values 0 #b11))
     (:2d (values 1 #b11))))
 
+(defun encode-vector-float-size (size)
+  (ecase size
+    (:2s (values 0 0))
+    (:4s (values 1 0))
+    (:2d (values 1 1))))
+
+(macrolet ((def (name q u opc)
+             `(define-instruction ,name (segment rd rn rm &optional (size :16b))
+                (:printer simd-three-diff ((q ,q) (u ,u) (op ,opc)))
+                (:emitter
+                 (emit-simd-three-diff segment
+                                       ,q
+                                       ,u
+                                       (if (zerop ,q)
+                                           (ecase size
+                                             (:8b #b00)
+                                             (:4h #b01)
+                                             (:2s #b10))
+                                           (ecase size
+                                             (:16b #b00)
+                                             (:8h #b01)
+                                             (:4s #b10)))
+                                       (fpr-offset rm)
+                                       ,opc
+                                       (fpr-offset rn)
+                                       (fpr-offset rd))))))
+  (def umull 0 1 #b1100)
+  (def umull2 1 1 #b1100))
+
 (macrolet ((def (name u size op &rest printer)
              `(define-instruction ,name (segment rd rn rm size)
                 (:printer simd-three-same ((u ,u) (size ,size) (op ,op))
@@ -3307,7 +3417,18 @@
   (def urhadd #b1 #b00010)
   (def uhsub #b1 #b00100)
   (def uqsub #b1 #b00101)
-  (def addp #b0 #b10111))
+  (def addp #b0 #b10111)
+  (def shadd #b0 #b00000)
+  (def sqadd #b0 #b00001)
+  (def srhadd #b0 #b00010)
+  (def shsub #b0 #b00100)
+  (def sqsub #b0 #b00101)
+  (def uminp #b1 #b10101)
+  (def umaxp #b1 #b10100)
+  (def sminp #b0 #b10101)
+  (def smaxp #b0 #b10100)
+  (def sshl #b0 #b01001)
+  (def ushl #b1 #b01001))
 
 (macrolet ((def (name u neg op)
              `(define-instruction ,name (segment rd rn rm size)
@@ -3324,7 +3445,9 @@
                     ,op
                     (fpr-offset rn)
                     (fpr-offset rd)))))))
-  (def fcmeq #b0 #b0 #b11100))
+  (def fcmeq #b0 #b0 #b11100)
+  (def fcmge #b1 #b0 #b11100)
+  (def fcmgt #b1 #b1 #b11100))
 
 (def-emitter simd-scalar-three-same
     (#b01 2 30)
@@ -3351,6 +3474,63 @@
   (rn :fields (list (byte 1 30) (byte 5 5)) :type 'simd-reg)
   (rd :fields (list (byte 1 30) (byte 5 0)) :type 'simd-reg))
 
+(def-emitter simd-scalar-and-vector-two
+    (#b01 2 30)
+  (u 1 29)
+  (#b11110 5 24)
+  (sz2 1 23)
+  (size 1 22)
+  (#b11000 5 17)
+  (opc 5 12)
+  (#b10 2 10)
+  (rn 5 5)
+  (rd 5 0))
+
+(define-instruction-format (simd-scalar-and-vector-two 32
+                            :default-printer '(:name :tab rd ", " rn))
+  (op3 :field (byte 2 30) :value #b01)
+  (u :field (byte 1 29))
+  (op4 :field (byte 5 24) :value #b11110)
+  (op2 :field (byte 1 23) :value #b0)
+  (size :field (byte 1 22))
+  (op5 :field (byte 5 17) :value #b11000)
+  (op :field (byte 5 12))
+  (op6 :field (byte 2 10) :value #b10)
+  (rn :fields (list (byte 1 22) (byte 5 5)) :type 'float-reg)
+  (rd :fields (list (byte 1 30) (byte 5 0)) :type 'simd-float-pair-reg))
+
+(macrolet ((def (name u sz2 opc simd-o1 simd-opc)
+             `(define-instruction ,name (segment rd rn rm-or-scalar-size &optional vector-size)
+                (:printer simd-scalar-and-vector-two ((u ,u) (op2 ,sz2) (op ,opc)))
+                (:printer simd-three-same-float ((u ,u) (neg ,simd-o1) (op ,simd-opc)))
+                (:emitter
+                 (cond ((member rm-or-scalar-size '(:2s :2d))
+                        (aver (null vector-size))
+                        (emit-simd-scalar-and-vector-two segment
+                                                         ,u
+                                                         ,sz2
+                                                         (ecase rm-or-scalar-size
+                                                           (:2s 0)
+                                                           (:2d 1))
+                                                         ,opc
+                                                         (fpr-offset rn)
+                                                         (fpr-offset rd)))
+                       (t
+                        (multiple-value-bind (q size) (encode-vector-size vector-size)
+                          (emit-simd-three-same-float
+                           segment
+                           q
+                           ,u
+                           ,simd-o1
+                           (logand 1 size)
+                           (fpr-offset rm-or-scalar-size)
+                           ,simd-opc
+                           (fpr-offset rn)
+                           (fpr-offset rd)))))))))
+  (def faddp 1 0 #b01101 0 #b11010)
+  (def fminp 1 1 #b01111 1 #b11110)
+  (def fmaxp 1 0 #b01111 0 #b11110))
+
 ;;;
 
 (def-emitter simd-extract
@@ -3446,23 +3626,37 @@
   (rn :fields (list (byte 5 5) (byte 5 16)) :type 'simd-copy-reg)
   (rd :fields (list (byte 1 30) (byte 5 0)) :type 'sized-reg))
 
-(macrolet ((def (name op imm4 q)
-             `(define-instruction ,name (segment rd rn index size)
-                (:printer simd-copy-to-general ((op ,op) (imm4 ,imm4)))
-                (:emitter
-                 (let ((isize (position size '(:B :H :S :D))))
-                   (emit-simd-copy segment
-                                   (case size
-                                     (,q 1)
-                                     (t 0))
-                                   ,op
-                                   (logior (ash index (1+ isize))
-                                           (ash 1 isize))
-                                   ,imm4
-                                   (fpr-offset rn)
-                                   (gpr-offset rd)))))))
-  (def umov 0 #b0111 (:d))
-  (def smov 0 #b0101 (:d :s)))
+(define-instruction umov (segment rd rn index size)
+  (:printer simd-copy-to-general ((op 0) (imm4 #b0111)))
+  (:emitter
+   (if (sc-is rd 32-bit-reg)
+       (aver (member size '(:b :h :s)))
+       (aver (member size '(:b :h :s :d))))
+   (let ((isize (position size '(:b :h :s :d))))
+     (emit-simd-copy segment
+                     (if (eq size :d) 1 0)
+                     0
+                     (logior (ash index (1+ isize))
+                             (ash 1 isize))
+                     #b0111
+                     (fpr-offset rn)
+                     (gpr-offset rd)))))
+
+(define-instruction smov (segment rd rn index size)
+  (:printer simd-copy-to-general ((op 0) (imm4 #b0101)))
+  (:emitter
+   (if (sc-is rd 32-bit-reg)
+       (aver (member size '(:b :h)))
+       (aver (member size '(:b :h :s))))
+   (let ((isize (position size '(:b :h :s))))
+     (emit-simd-copy segment
+                     (reg-size rd)
+                     0
+                     (logior (ash index (1+ isize))
+                             (ash 1 isize))
+                     #b0101
+                     (fpr-offset rn)
+                     (gpr-offset rd)))))
 
 (define-instruction-format (simd-dup-from-general 32
                             :include simd-copy
@@ -3573,18 +3767,6 @@
   (rd :fields (list (byte 2 22) (byte 5 0)) :type 'vbhs))
 
 
-(def-emitter simd-two-misc
-    (#b0 1 31)
-  (q 1 30)
-  (u 1 29)
-  (#b01110 5 24)
-  (size 2 22)
-  (#b10000 5 17)
-  (op 5 12)
-  (#b10 2 10)
-  (rn 5 5)
-  (rd 5 0))
-
 (define-instruction addv (segment rd rn size)
   (:printer simd-across-lanes  ((u 0) (op #b11011)))
   (:emitter
@@ -3625,6 +3807,30 @@
     (fpr-offset rn)
     (fpr-offset rd))))
 
+(define-instruction fminv (segment rd rn)
+  (:printer simd-across-lanes  ((u 0) (size #b10) (op #b01111)))
+  (:emitter
+   (emit-simd-across-lanes
+    segment
+    1
+    1
+    #b10
+    #b01111
+    (fpr-offset rn)
+    (fpr-offset rd))))
+
+(define-instruction fmaxv (segment rd rn)
+  (:printer simd-across-lanes  ((u 0) (size #b00) (op #b01111)))
+  (:emitter
+   (emit-simd-across-lanes
+    segment
+    1
+    1
+    #b00
+    #b01111
+    (fpr-offset rn)
+    (fpr-offset rd))))
+
 (macrolet ((def (name u op)
              `(define-instruction ,name (segment rd rn size)
                 (:printer simd-across-lanes  ((u ,u) (op ,op)
@@ -3644,6 +3850,18 @@
   (def sminv 0 #b11010)
   (def smaxv 0 #b01010))
 
+(def-emitter simd-two-misc
+    (#b0 1 31)
+  (q 1 30)
+  (u 1 29)
+  (#b01110 5 24)
+  (size 2 22)
+  (#b10000 5 17)
+  (op 5 12)
+  (#b10 2 10)
+  (rn 5 5)
+  (rd 5 0))
+
 (define-instruction-format (simd-two-misc 32
                             :default-printer '(:name :tab rd ", " rn))
   (o1 :field (byte 1 31) :value #b0)
@@ -3675,6 +3893,23 @@
   (def rev64 #b0 #b00000 (:8b :16b :4h :8h :2s :4s))
   (def not #b1 #b00101))
 
+(macrolet
+    ((def (name q op)
+       `(define-instruction ,name (segment rd rn)
+          (:printer simd-two-misc ((q ,q) (u #b0) (op ,op)))
+          (:emitter
+           (emit-simd-two-misc segment
+                               ,q
+                               #b0
+                               #b01
+                               ,op
+                               (fpr-offset rn)
+                               (fpr-offset rd))))))
+  (def fcvtl 0 #b10111)
+  (def fcvtl2 1 #b10111)
+  (def fcvtn 0 #b10110)
+  (def fcvtn2 1 #b10110))
+
 (macrolet
     ((def (name u op)
        `(define-instruction ,name (segment rd rn size)
@@ -3708,6 +3943,10 @@
                                  ,op
                                  (fpr-offset rn)
                                  (fpr-offset rd)))))))
+  (def sqxtn #b0 #b10100 0 (:8b :4h :2s))
+  (def sqxtn2 #b0 #b10100 1 (:16b :8h :4s))
+  (def uqxtn #b1 #b10100 0 (:8b :4h :2s))
+  (def uqxtn2 #b1 #b10100 1 (:16b :8h :4s))
   (def xtn #b0 #b10010 0 (:8b :4h :2s))
   (def xtn2 #b0 #b10010 1 (:16b :8h :4s)))
 
@@ -3780,6 +4019,8 @@
                                      ,op
                                      (fpr-offset rn)
                                      (fpr-offset rd)))))))
+  (def sshll #b0 #b0 #b10100)
+  (def sshll2 #b1 #b0 #b10100)
   (def ushll #b0 #b1 #b10100)
   (def ushll2 #b1 #b1 #b10100))
 
@@ -3838,10 +4079,11 @@
                                      ,op
                                      (fpr-offset rn)
                                      (fpr-offset rd)))))))
+  (def shl #b0 #b01010 nil t)
   (def sli #b1 #b01010)
   (def sri #b1 #b01000 t)
   (def ushr #b1 #b00000 t t)
-  (def shl #b0 #b01010 nil t)
+  (def sshr #b0 #b00000 t t)
   (def shrn #b0 #b10000 t))
 
 (def-emitter simd-modified-imm
@@ -4577,8 +4819,9 @@
 
 (defpattern "lsl + arith -> arith" ((ubfm) (add and orr eor)) (stmt next)
   (destructuring-bind (dst1 src1 immr imms) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn srcm) (stmt-operands next)
-      (when (and (/= imms 63)
+    (destructuring-bind (dst2 srcn srcm &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (/= imms 63)
                  (= (1+ imms) immr)
                  (tn-p srcm)
                  (or
@@ -4598,8 +4841,9 @@
 
 (defpattern "asr + arith -> arith" ((sbfm) (add and orr eor)) (stmt next)
   (destructuring-bind (dst1 src1 immr imms) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn srcm) (stmt-operands next)
-      (when (and (= imms 63)
+    (destructuring-bind (dst2 srcn srcm &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (= imms 63)
                  (tn-p srcm)
                  (or
                   (location= dst1 srcm)
@@ -4618,8 +4862,9 @@
 
 (defpattern "lsl + sub -> sub" ((ubfm) (sub)) (stmt next)
   (destructuring-bind (dst1 src1 immr imms) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn srcm) (stmt-operands next)
-      (when (and (/= imms 63)
+    (destructuring-bind (dst2 srcn srcm &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (/= imms 63)
                  (= (1+ imms) immr)
                  (tn-p srcm)
                  (location= dst1 srcm)
@@ -4634,8 +4879,9 @@
 
 (defpattern "asr + sub -> sub" ((sbfm) (sub)) (stmt next)
   (destructuring-bind (dst1 src1 immr imms) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn srcm) (stmt-operands next)
-      (when (and (= imms 63)
+    (destructuring-bind (dst2 srcn srcm &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (= imms 63)
                  (tn-p srcm)
                  (location= dst1 srcm)
                  (not (location= srcn srcm))
@@ -4716,9 +4962,10 @@
 ;;; An even number can be shifted right and then negated,
 ;;; and fixnums are even.
 (defpattern "neg + asr -> neg" ((sub) (sbfm)) (stmt next)
-  (destructuring-bind (dst1 srcn srcm) (stmt-operands stmt)
+  (destructuring-bind (dst1 srcn srcm &optional vector-size) (stmt-operands stmt)
     (destructuring-bind (dst2 src2 immr imms) (stmt-operands next)
-      (when (and (= imms 63)
+      (when (and (not vector-size)
+                 (= imms 63)
                  (= immr 1)
                  (tn-p srcm)
                  (sc-is srcm sb-vm::any-reg)
@@ -4733,8 +4980,9 @@
 
 (defpattern "mul + sub -> msub" ((madd) (sub)) (stmt next)
   (destructuring-bind (dst1 srcn1 srcm1 srca) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn2 srcm2) (stmt-operands next)
-      (when (and (tn-p srcm2)
+    (destructuring-bind (dst2 srcn2 srcm2 &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (tn-p srcm2)
                  (location= dst1 srcm2)
                  (location= srca zr-tn)
                  (not (location= srcn2 srcm2))
@@ -4749,8 +4997,9 @@
 
 (defpattern "mul + add -> madd" ((madd) (add)) (stmt next)
   (destructuring-bind (dst1 srcn1 srcm1 srca) (stmt-operands stmt)
-    (destructuring-bind (dst2 srcn2 srcm2) (stmt-operands next)
-      (when (and (tn-p srcm2)
+    (destructuring-bind (dst2 srcn2 srcm2 &optional vector-size) (stmt-operands next)
+      (when (and (not vector-size)
+                 (tn-p srcm2)
                  (location= srca zr-tn)
                  (not (location= srcn2 srcm2))
                  (or (location= dst1 srcm2)
diff --git a/src/compiler/arm64/target-insts.lisp b/src/compiler/arm64/target-insts.lisp
index 10e090dc3..d3eef6d26 100644
--- a/src/compiler/arm64/target-insts.lisp
+++ b/src/compiler/arm64/target-insts.lisp
@@ -304,6 +304,11 @@
     (format stream "V~d.~a" offset
             (decode-vector-size-2x q size))))
 
+(defun print-simd-float-pair-reg (value stream dstate)
+  (declare (ignore dstate))
+  (destructuring-bind (size offset) value
+    (format stream "V~d.~a" offset (if (= size 1) "2S" "2D"))))
+
 (defun print-simd-immh-reg (value stream dstate)
   (declare (ignore dstate))
   (if (= (length value) 2)

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


hooks/post-receive
-- 
SBCL