master: arm64: add BIC <Vd>.<T>, #imm8

stassats via Sbcl-commits <[email protected]> Sat, 04 Jul 2026 15:02:45 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  43b5018966d66a33ef9f579204127e0167964d68 (commit)
      from  d0d9c0df6fc8f022b68149a41deef4509d09948e (commit)

- Log -----------------------------------------------------------------
commit 43b5018966d66a33ef9f579204127e0167964d68
Author: Stas Boukarev <[email protected]>
Date:   Sat Jul 4 17:51:24 2026 +0300

    arm64: add BIC <Vd>.<T>, #imm8
---
 src/code/arm64-simd.lisp             |  12 +--
 src/compiler/arm64/insts.lisp        | 148 +++++++++++++++++++++++++++++------
 src/compiler/arm64/target-insts.lisp |  36 ++++++---
 3 files changed, 152 insertions(+), 44 deletions(-)

diff --git a/src/code/arm64-simd.lisp b/src/code/arm64-simd.lisp
index 4bf9f9178..e422c1728 100644
--- a/src/code/arm64-simd.lisp
+++ b/src/code/arm64-simd.lisp
@@ -1693,8 +1693,6 @@
                    ((packed complex-double-reg))
                    ((p32-1 complex-double-reg))
                    ((p32-2 complex-double-reg))
-                   ((mask-3f complex-double-reg))
-                   ((mask-1f complex-double-reg))
                    ((mask-2 complex-double-reg))
                    ((mask-bf complex-double-reg))
                    ((ones complex-double-reg))
@@ -1708,8 +1706,6 @@
                 (inst movi mask-2 2 :8b)
                 (inst movi ones 1 :8b)
                 (inst movi mask-bf #xBF :8h)
-                (inst movi mask-3f #x3f :8h)
-                (inst movi mask-1f #x1f :8h)
                 (inst b start)
 
                 LOOP
@@ -1738,10 +1734,10 @@
                 ;; next16 is shifted by one,
                 ;; construct a codepoint from two overlapping bytes,
                 ;; i.e. (dpb b0 (byte 5 6) b1)
-                (inst and lead current16 mask-1f :8h)
-                (inst shl lead lead 6 :8h)
-                (inst and continuations next16 mask-3f :8h)
-                (inst orr combined lead continuations :8h)
+                (inst shl lead current16 6 :8h)
+                (inst bic lead #xf800 :8h)
+                (inst bic next16 #xc0 :8h)
+                (inst orr combined lead next16 :8h)
 
                 ;; Select either the combined two bytes or one ascii byte
                 (inst cmhi is-lead16 current16 mask-bf :8h)
diff --git a/src/compiler/arm64/insts.lisp b/src/compiler/arm64/insts.lisp
index 368047771..abde88b29 100644
--- a/src/compiler/arm64/insts.lisp
+++ b/src/compiler/arm64/insts.lisp
@@ -959,10 +959,6 @@
                                 (fpr-offset rd))
           (emit-logical-reg-inst segment ,opc 1 rd rn rm)))))
 
-(def-logical-reg+simd bic #b00
-  ((:printer logical-reg ((op #b00) (n 1))))
-   #b0 #b01 #b00011)
-
 (def-logical-reg+simd orn #b01
   ((:printer logical-reg ((op #b01) (n 1)))
    (:printer logical-reg ((op #b01) (n 1) (rn 31))
@@ -3017,7 +3013,7 @@
   (cmode :field (byte 4 12))
   (o2 :field (byte 1 11))
   (op3 :field (byte 1 10) :value #b1)
-  (imm :fields (list (byte 3 16) (byte 4 12) (byte 5 5)) :type 'simd-modified-imm)
+  (imm :fields (list (byte 3 16) (byte 5 5) (byte 4 12)) :type 'simd-modified-imm)
   (rd :fields (list (byte 1 30) (byte 4 12) (byte 5 0) (byte 1 29)) :type 'simd-reg-cmode))
 
 (define-instruction-format (simd-modified-fp-imm 32
@@ -3112,6 +3108,117 @@
                                     #b01111
                                     #b00111)
                                 (gpr-offset rn) (fpr-offset rd)))))))
+
+(defun emit-simd-orr/bic-imm (segment op rd imm vector-size)
+  (let (cmode)
+    (ecase vector-size
+      ((:4h :8h)
+       (cond ((typep imm '(unsigned-byte 8))
+              (setf cmode #b1001))
+             ((and (typep imm '(unsigned-byte 16))
+                   (zerop (ldb (byte 8 0) imm)))
+              (setf imm (ldb (byte 8 8) imm)
+                    cmode #b1011))
+             (t
+              (error "~x bad immediate" imm))))
+      ((:2s :4s)
+       (cond ((typep imm '(unsigned-byte 8))
+              (setf cmode #b0001))
+             ((and (typep imm '(unsigned-byte 16))
+                   (zerop (ldb (byte 8 0) imm)))
+              (setf imm (ldb (byte 8 8) imm)
+                    cmode #b0011))
+             ((and (typep imm '(unsigned-byte 24))
+                   (zerop (ldb (byte 16 0) imm)))
+              (setf imm (ldb (byte 8 16) imm)
+                    cmode #b0101))
+             ((and (typep imm '(unsigned-byte 32))
+                   (zerop (ldb (byte 24 0) imm)))
+              (setf imm (ldb (byte 8 24) imm)
+                    cmode #b0111))
+             (t
+              (error "~x bad immediate" imm)))))
+    (emit-simd-modified-imm segment
+                            (encode-vector-size vector-size)
+                            op
+                            (ldb (byte 3 5) imm)
+                            cmode
+                            0
+                            (ldb (byte 5 0) imm)
+                            (fpr-offset rd))))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun simd-modified-imm-printer (op cmodes)
+    (loop for cmode in cmodes
+          for fields = (loop for bit in cmode
+                             for i downfrom 15
+                             unless (eq bit 'x)
+                             collect `(byte 1 ,i))
+          for bits = (remove 'x cmode)
+          collect `(:printer simd-modified-imm ((o2 0)
+                                                (op ,op)
+                                                (cmodes ',bits
+                                                        :fields (list ,@fields)))))))
+
+(macrolet ((def (name simd-op cmodes)
+             `(define-instruction ,name (segment rd &rest args)
+                (:printer logical-reg ((op 0) (n 1)))
+                (:printer simd-three-same ((u 0) (size 1) (op 3)))
+                ,@(simd-modified-imm-printer simd-op cmodes)
+                (:emitter
+                 (if (and (keywordp (car (last args)))
+                          (= (length args) 2))
+                     (destructuring-bind (imm vector-size) args
+                       (emit-simd-orr/bic-imm segment ,simd-op rd imm vector-size))
+                     (destructuring-bind (rn rm &optional vector-size) args
+                       (if vector-size
+                           (emit-simd-three-same segment
+                                                 (encode-vector-size vector-size)
+                                                 0 1 (fpr-offset rm) 3
+                                                 (fpr-offset rn) (fpr-offset rd))
+                           (emit-logical-reg-inst segment 0 1 rd rn rm))))))))
+  (def bic 1 ((1 0 x 1)
+              (0 x x 1))))
+
+(macrolet ((def (name simd-op cmodes)
+             `(define-instruction ,name (segment rd &rest args)
+                (:printer simd-three-same ((u 0) (size 2) (op 3))
+                          '((:cond ((rn :same-as rm) 'mov) (t 'orr)) :tab rd ", " rn
+                            (:unless (:same-as rn) ", " rm)))
+                (:printer logical-imm ((op 1)))
+                (:printer logical-reg ((op 1)))
+                (:printer logical-imm ((op 1) (rn 31))
+                          '('mov :tab rd ", " imm))
+                (:printer logical-reg ((op 1) (rn 31))
+                          '('mov :tab rd ", " rm shift))
+                ,@(simd-modified-imm-printer simd-op cmodes)
+                (:emitter
+                 (if (and (keywordp (car (last args)))
+                          (= (length args) 2))
+                     (destructuring-bind (imm vector-size) args
+                       (emit-simd-orr/bic-imm segment ,simd-op rd imm vector-size))
+                     (destructuring-bind (rn rm &optional vector-size) args
+                       (if vector-size
+                           (emit-simd-three-same segment
+                                                 (encode-vector-size vector-size)
+                                                 0 2 (fpr-offset rm) 3
+                                                 (fpr-offset rn) (fpr-offset rd))
+                           (if (or (register-p rm) (shifter-operand-p rm))
+                               (emit-logical-reg-inst segment 1 0 rd rn rm)
+                               (let ((size (reg-size rd)))
+                                 (multiple-value-bind (n immr imms)
+                                     (encode-logical-immediate rm
+                                                               (if (= size 1)
+                                                                   64
+                                                                   32))
+                                   (unless n
+                                     (error 'cannot-encode-immediate-operand
+                                            :value rm))
+                                   (emit-logical-imm segment size 1 n immr imms
+                                                     (gpr-offset rn)
+                                                     (gpr-offset rd))))))))))))
+  (def orr 0 ((1 0 x 1)
+              (0 x x 1))))
+
 
 (define-instruction load-from-label (segment dest label &optional lip)
   (:vop-var vop)
@@ -4129,20 +4236,11 @@
       (typep (ldb (byte 8 0) value) '(member 255 0))))))
 
 (macrolet
-    ((def (name o2 op cmodes)
+    ((def (name op cmodes)
        `(define-instruction ,name (segment rd imm &optional size)
-          ,@(loop for cmode in cmodes
-                  for fields = (loop for bit in cmode
-                                     for i downfrom 15
-                                     unless (eq bit 'x)
-                                     collect `(byte 1 ,i))
-                  for bits = (remove 'x cmode)
-                  collect `(:printer simd-modified-imm ((o2 ,o2)
-                                                        (op ,op)
-                                                        (cmodes ',bits
-                                                                :fields (list ,@fields)))))
+          ,@(simd-modified-imm-printer op cmodes)
           ,@(when (eq name 'movi)
-              `((:printer simd-modified-imm ((o2 ,o2)
+              `((:printer simd-modified-imm ((o2 0)
                                              (op 1)
                                              (cmode #b1110)
                                              (imm nil :type '64-bit-modified-imm)))))
@@ -4219,17 +4317,17 @@
                                      op
                                      abc
                                      cmode
-                                     ,o2
+                                     0
                                      defgh
                                      (fpr-offset rd)))))))
 
-  (def movi 0 0 ((0 x x 0)
-                 (1 0 x 0)
-                 (1 1 0 x)
-                 (1 1 1 0)))
-  (def mvni 0 1 ((0 x x 0)
-                 (1 0 x 0)
-                 (1 1 0 x))))
+  (def movi 0 ((0 x x 0)
+               (1 0 x 0)
+               (1 1 0 x)
+               (1 1 1 0)))
+  (def mvni 1 ((0 x x 0)
+               (1 0 x 0)
+               (1 1 0 x))))
 
 (def-emitter fp-cond-select
   (0 1 31)
diff --git a/src/compiler/arm64/target-insts.lisp b/src/compiler/arm64/target-insts.lisp
index 3eadb141a..5a7410d85 100644
--- a/src/compiler/arm64/target-insts.lisp
+++ b/src/compiler/arm64/target-insts.lisp
@@ -368,18 +368,20 @@
         (format stream "D~d" offset)
         (format stream "V~d.~a" offset
                 (cond ((eq cmode #b1110)
-                       (if (eq op 1)
-                           (if (zerop q)
-                               ""
-                               "2D")
-                           (if (zerop q)
-                               "8B"
-                               "16B")))
-                      ((eq (logandc2 cmode #b10) #b1000)
+                          (if (eq op 1)
+                              (if (zerop q)
+                                  ""
+                                  "2D")
+                              (if (zerop q)
+                                  "8B"
+                                  "16B")))
+                      ((or (eq (logand cmode #b1101) #b1001)
+                           (eq (logandc2 cmode #b10) #b1000))
                        (if (zerop q)
                            "4H"
                            "8H"))
-                      ((or (zerop (logand cmode #b1001))
+                      ((or (eq (logand cmode #b1001) #b0001)
+                           (zerop (logand cmode #b1001))
                            (= (ldb (byte 3 13) cmode) #b110))
                        (if (zerop q)
                            "2S"
@@ -425,9 +427,21 @@
 
 (defun print-simd-modified-imm (value stream dstate)
   (declare (ignore dstate))
-  (destructuring-bind (abc cmode defgh) value
+  (destructuring-bind (abc defgh cmode) value
     (let ((shift
-            (cond ((eq cmode #b1110)
+            (cond ((eq cmode #b1001)
+                   0)
+                  ((eq cmode #b1011)
+                   8)
+                  ((eq cmode #b0001)
+                   0)
+                  ((eq cmode #b0011)
+                   8)
+                  ((eq cmode #b0101)
+                   16)
+                  ((eq cmode #b0111)
+                   24)
+                  ((eq cmode #b1110)
                    0)
                   ((zerop (logand cmode #b1001))
                    (ash cmode 2))

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


hooks/post-receive
-- 
SBCL