New VOP for LOGAND of bignum and word-sized constant on x86-64
[sbcl.git] / src / compiler / x86-64 / arith.lisp
index 516f2d0..9229626 100644 (file)
@@ -902,6 +902,52 @@ constant shift greater than word length")))
 
     DONE))
 
+#!+ash-right-vops
+(define-vop (fast-%ash/right/unsigned)
+  (:translate %ash/right)
+  (:policy :fast-safe)
+  (:args (number :scs (unsigned-reg) :target result)
+         (amount :scs (unsigned-reg) :target rcx))
+  (:arg-types unsigned-num unsigned-num)
+  (:results (result :scs (unsigned-reg) :from (:argument 0)))
+  (:result-types unsigned-num)
+  (:temporary (:sc signed-reg :offset rcx-offset :from (:argument 1)) rcx)
+  (:generator 4
+    (move result number)
+    (move rcx amount)
+    (inst shr result :cl)))
+
+#!+ash-right-vops
+(define-vop (fast-%ash/right/signed)
+  (:translate %ash/right)
+  (:policy :fast-safe)
+  (:args (number :scs (signed-reg) :target result)
+         (amount :scs (unsigned-reg) :target rcx))
+  (:arg-types signed-num unsigned-num)
+  (:results (result :scs (signed-reg) :from (:argument 0)))
+  (:result-types signed-num)
+  (:temporary (:sc signed-reg :offset rcx-offset :from (:argument 1)) rcx)
+  (:generator 4
+    (move result number)
+    (move rcx amount)
+    (inst sar result :cl)))
+
+#!+ash-right-vops
+(define-vop (fast-%ash/right/fixnum)
+  (:translate %ash/right)
+  (:policy :fast-safe)
+  (:args (number :scs (any-reg) :target result)
+         (amount :scs (unsigned-reg) :target rcx))
+  (:arg-types tagged-num unsigned-num)
+  (:results (result :scs (any-reg) :from (:argument 0)))
+  (:result-types tagged-num)
+  (:temporary (:sc signed-reg :offset rcx-offset :from (:argument 1)) rcx)
+  (:generator 3
+    (move result number)
+    (move rcx amount)
+    (inst sar result :cl)
+    (inst and result (lognot fixnum-tag-mask))))
+
 (in-package "SB!C")
 
 (defknown %lea (integer integer (member 1 2 4 8 16) (signed-byte 64))
@@ -1844,6 +1890,77 @@ constant shift greater than word length")))
     (move result digit)
     (move ecx count)
     (inst shl result :cl)))
+
+(define-vop (logand-bignum/c)
+  (:translate logand)
+  (:policy :fast-safe)
+  (:args (x :scs (descriptor-reg)))
+  (:arg-types bignum (:constant word))
+  (:results (r :scs (unsigned-reg)))
+  (:info mask)
+  (:result-types unsigned-num)
+  (:generator 4
+    (let ((mask (constantize mask)))
+      (cond ((or (integerp mask)
+                 (location= x r))
+             (loadw r x bignum-digits-offset other-pointer-lowtag)
+             (unless (eql mask -1)
+               (inst and r mask)))
+            (t
+             (inst mov r mask)
+             (inst and r (make-ea-for-object-slot x
+                                                  bignum-digits-offset
+                                                  other-pointer-lowtag)))))))
+
+;; Specialised mask-signed-field VOPs.
+(define-vop (mask-signed-field-word/c)
+  (:translate sb!c::mask-signed-field)
+  (:policy :fast-safe)
+  (:args (x :scs (signed-reg unsigned-reg) :target r))
+  (:arg-types (:constant (integer 0 64)) untagged-num)
+  (:results (r :scs (signed-reg)))
+  (:result-types signed-num)
+  (:info width)
+  (:generator 3
+    (cond ((zerop width)
+           (zeroize r))
+          ((= width 64)
+           (move r x))
+          ((member width '(32 16 8))
+           (inst movsx r (reg-in-size x (ecase width
+                                             (32 :dword)
+                                             (16 :word)
+                                             (8  :byte)))))
+          (t
+           (move r x)
+           (let ((delta (- n-word-bits width)))
+             (inst shl r delta)
+             (inst sar r delta))))))
+
+(define-vop (mask-signed-field-bignum/c)
+  (:translate sb!c::mask-signed-field)
+  (:policy :fast-safe)
+  (:args (x :scs (descriptor-reg) :target r))
+  (:arg-types (:constant (integer 0 64)) bignum)
+  (:results (r :scs (signed-reg)))
+  (:result-types signed-num)
+  (:info width)
+  (:generator 4
+    (cond ((zerop width)
+           (zeroize r))
+          ((member width '(8 16 32 64))
+           (ecase width
+             (64 (loadw r x bignum-digits-offset other-pointer-lowtag))
+             ((32 16 8)
+              (inst movsx r (make-ea (ecase width (32 :dword) (16 :word) (8 :byte))
+                                     :base x
+                                     :disp (- (* bignum-digits-offset n-word-bytes)
+                                              other-pointer-lowtag))))))
+          (t
+           (loadw r x bignum-digits-offset other-pointer-lowtag)
+           (let ((delta (- n-word-bits width)))
+             (inst shl r delta)
+             (inst sar r delta))))))
 \f
 ;;;; static functions