0.8.4.11:
[sbcl.git] / src / compiler / alpha / arith.lisp
index 35d0b52..c680c61 100644 (file)
@@ -24,7 +24,7 @@
 (define-vop (signed-unop)
   (:args (x :scs (signed-reg)))
   (:results (res :scs (signed-reg)))
 (define-vop (signed-unop)
   (:args (x :scs (signed-reg)))
   (:results (res :scs (signed-reg)))
-  (:note "inline (signed-byte 32) arithmetic")
+  (:note "inline (signed-byte 64) arithmetic")
   (:arg-types signed-num)
   (:result-types signed-num)
   (:policy :fast-safe))
   (:arg-types signed-num)
   (:result-types signed-num)
   (:policy :fast-safe))
@@ -70,7 +70,7 @@
   (:arg-types unsigned-num unsigned-num)
   (:results (r :scs (unsigned-reg)))
   (:result-types unsigned-num)
   (:arg-types unsigned-num unsigned-num)
   (:results (r :scs (unsigned-reg)))
   (:result-types unsigned-num)
-  (:note "inline (unsigned-byte 32) arithmetic")
+  (:note "inline (unsigned-byte 64) arithmetic")
   (:effects)
   (:affected)
   (:policy :fast-safe))
   (:effects)
   (:affected)
   (:policy :fast-safe))
@@ -81,7 +81,7 @@
   (:arg-types signed-num signed-num)
   (:results (r :scs (signed-reg)))
   (:result-types signed-num)
   (:arg-types signed-num signed-num)
   (:results (r :scs (signed-reg)))
   (:result-types signed-num)
-  (:note "inline (signed-byte 32) arithmetic")
+  (:note "inline (signed-byte 64) arithmetic")
   (:effects)
   (:affected)
   (:policy :fast-safe))
   (:effects)
   (:affected)
   (:policy :fast-safe))
 (define-binop logorc2 1 3 ornot (unsigned-byte 6) (unsigned-byte 8) nil t)
 (define-binop logxor 1 3 xor (unsigned-byte 6) (unsigned-byte 8))
 (define-binop logeqv 1 3 eqv (unsigned-byte 6) (unsigned-byte 8) nil t)
 (define-binop logorc2 1 3 ornot (unsigned-byte 6) (unsigned-byte 8) nil t)
 (define-binop logxor 1 3 xor (unsigned-byte 6) (unsigned-byte 8))
 (define-binop logeqv 1 3 eqv (unsigned-byte 6) (unsigned-byte 8) nil t)
+
+;;; special cases for LOGAND where we can use a mask operation
+(define-vop (fast-logand-c-mask/unsigned=>unsigned fast-unsigned-c-binop)
+  (:translate logand)
+  (:arg-types unsigned-num
+             (:constant (or (integer #xffffffff #xffffffff)
+                            (integer #xffffffff00000000 #xffffffff00000000))))
+  (:generator 1
+    (ecase y
+      (#xffffffff (inst mskll x 4 r))
+      (#xffffffff00000000 (inst mskll x 0 r)))))
 \f
 ;;;; shifting
 
 \f
 ;;;; shifting
 
-(define-vop (fast-ash)
+(define-vop (fast-ash/unsigned=>unsigned)
+  (:note "inline ASH")
+  (:args (number :scs (unsigned-reg) :to :save)
+        (amount :scs (signed-reg)))
+  (:arg-types unsigned-num signed-num)
+  (:results (result :scs (unsigned-reg)))
+  (:result-types unsigned-num)
+  (:translate ash)
+  (:policy :fast-safe)
+  (:temporary (:sc non-descriptor-reg) ndesc)
+  (:temporary (:sc non-descriptor-reg) temp)
+  (:generator 3
+    (inst bge amount positive)
+    (inst subq zero-tn amount ndesc)
+    (inst cmplt ndesc 64 temp)
+    (inst srl number ndesc result)
+    ;; FIXME: this looks like a candidate for a conditional move --
+    ;; CSR, 2003-09-10
+    (inst bne temp done)
+    (move zero-tn result)
+    (inst br zero-tn done)
+      
+    POSITIVE
+    (inst sll number amount result)
+      
+    DONE))
+
+(define-vop (fast-ash/signed=>signed)
   (:note "inline ASH")
   (:note "inline ASH")
-  (:args (number :scs (signed-reg unsigned-reg) :to :save)
+  (:args (number :scs (signed-reg) :to :save)
         (amount :scs (signed-reg)))
         (amount :scs (signed-reg)))
-  (:arg-types (:or signed-num unsigned-num) signed-num)
-  (:results (result :scs (signed-reg unsigned-reg)))
-  (:result-types (:or signed-num unsigned-num))
+  (:arg-types signed-num signed-num)
+  (:results (result :scs (signed-reg)))
+  (:result-types signed-num)
   (:translate ash)
   (:policy :fast-safe)
   (:temporary (:sc non-descriptor-reg) ndesc)
   (:translate ash)
   (:policy :fast-safe)
   (:temporary (:sc non-descriptor-reg) ndesc)
-  (:temporary (:sc non-descriptor-reg :to :eval) temp)
+  (:temporary (:sc non-descriptor-reg) temp)
   (:generator 3
     (inst bge amount positive)
     (inst subq zero-tn amount ndesc)
   (:generator 3
     (inst bge amount positive)
     (inst subq zero-tn amount ndesc)
-    (inst cmplt ndesc 31 temp)
-    (sc-case number
-      (signed-reg (inst sra number ndesc result))
-      (unsigned-reg (inst srl number ndesc result)))
+    (inst cmplt ndesc 63 temp)
+    (inst sra number ndesc result)
     (inst bne temp done)
     (inst bne temp done)
-    (sc-case number
-      (signed-reg (inst sra number 31 result))
-      (unsigned-reg (inst srl number 31 result)))
+    (inst sra number 63 result)
     (inst br zero-tn done)
       
     POSITIVE
     (inst br zero-tn done)
       
     POSITIVE
-    ;; The result-type assures us that this shift will not overflow.
     (inst sll number amount result)
       
     DONE))
 
     (inst sll number amount result)
       
     DONE))
 
-(define-vop (fast-ash-c)
+(define-vop (fast-ash-c/signed=>signed)
   (:policy :fast-safe)
   (:translate ash)
   (:note nil)
   (:policy :fast-safe)
   (:translate ash)
   (:note nil)
-  (:args (number :scs (signed-reg unsigned-reg)))
+  (:args (number :scs (signed-reg)))
   (:info count)
   (:info count)
-  (:arg-types (:or signed-num unsigned-num) (:constant integer))
-  (:results (result :scs (signed-reg unsigned-reg)))
-  (:result-types (:or signed-num unsigned-num))
+  (:arg-types signed-num (:constant integer))
+  (:results (result :scs (signed-reg)))
+  (:result-types signed-num)
   (:generator 1
   (:generator 1
-    (cond ((< count 0)
-          ;; It is a right shift.
-          (sc-case number
-            (signed-reg (inst sra number (- count) result))
-            (unsigned-reg (inst srl number (- count) result))))
-         ((> count 0)
-          ;; It is a left shift.
-          (inst sll number count result))
-         (t
-          ;; Count=0?  Shouldn't happen, but it's easy:
-          (move number result)))))
+    (cond
+      ((< count 0) (inst sra number (min 63 (- count)) result))
+      ((> count 0) (inst sll number (min 63 count) result))
+      (t (bug "identity ASH not transformed away")))))
 
 
-(define-vop (signed-byte-32-len)
+(define-vop (fast-ash-c/unsigned=>unsigned)
+  (:policy :fast-safe)
+  (:translate ash)
+  (:note nil)
+  (:args (number :scs (unsigned-reg)))
+  (:info count)
+  (:arg-types unsigned-num (:constant integer))
+  (:results (result :scs (unsigned-reg)))
+  (:result-types unsigned-num)
+  (:generator 1
+    (cond
+      ((< count -63) (move zero-tn result))
+      ((< count 0) (inst sra number (- count) result))
+      ((> count 0) (inst sll number (min 63 count) result))
+      (t (bug "identity ASH not transformed away")))))
+
+(define-vop (signed-byte-64-len)
   (:translate integer-length)
   (:translate integer-length)
-  (:note "inline (signed-byte 32) integer-length")
+  (:note "inline (signed-byte 64) integer-length")
   (:policy :fast-safe)
   (:args (arg :scs (signed-reg) :to (:argument 1)))
   (:arg-types signed-num)
   (:policy :fast-safe)
   (:args (arg :scs (signed-reg) :to (:argument 1)))
   (:arg-types signed-num)
   (:generator 30
     (inst not arg shift)
     (inst cmovge arg arg shift)
   (:generator 30
     (inst not arg shift)
     (inst cmovge arg arg shift)
-    (inst subq zero-tn 4 res)
+    (inst subq zero-tn (fixnumize 1) res)
     (inst sll shift 1 shift)
     LOOP
     (inst addq res (fixnumize 1) res)
     (inst srl shift 1 shift)
     (inst bne shift loop)))
 
     (inst sll shift 1 shift)
     LOOP
     (inst addq res (fixnumize 1) res)
     (inst srl shift 1 shift)
     (inst bne shift loop)))
 
-(define-vop (unsigned-byte-32-count)
+(define-vop (unsigned-byte-64-count)
   (:translate logcount)
   (:translate logcount)
-  (:note "inline (unsigned-byte 32) logcount")
+  (:note "inline (unsigned-byte 64) logcount")
   (:policy :fast-safe)
   (:args (arg :scs (unsigned-reg) :target num))
   (:arg-types unsigned-num)
   (:policy :fast-safe)
   (:args (arg :scs (unsigned-reg) :target num))
   (:arg-types unsigned-num)
   (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
                    :target res) num)
   (:temporary (:scs (non-descriptor-reg)) mask temp)
   (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
                    :target res) num)
   (:temporary (:scs (non-descriptor-reg)) mask temp)
-  (:generator 30
-    (inst li #x55555555 mask)
+  (:generator 60
+    ;; FIXME: now this looks expensive, what with these 64bit loads.
+    ;; Maybe a loop and count would be faster?  -- CSR, 2003-09-10
+    (inst li #x5555555555555555 mask)
     (inst srl arg 1 temp)
     (inst and arg mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
     (inst srl arg 1 temp)
     (inst and arg mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
-    (inst li #x33333333 mask)
+    (inst li #x3333333333333333 mask)
     (inst srl num 2 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
     (inst srl num 2 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
-    (inst li #x0f0f0f0f mask)
+    (inst li #x0f0f0f0f0f0f0f0f mask)
     (inst srl num 4 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
     (inst srl num 4 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
-    (inst li #x00ff00ff mask)
+    (inst li #x00ff00ff00ff00ff mask)
     (inst srl num 8 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
     (inst srl num 8 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst addq num temp num)
-    (inst li #x0000ffff mask)
+    (inst li #x0000ffff0000ffff mask)
     (inst srl num 16 temp)
     (inst and num mask num)
     (inst and temp mask temp)
     (inst srl num 16 temp)
     (inst and num mask num)
     (inst and temp mask temp)
+    (inst addq num temp num)
+    (inst li #x00000000ffffffff mask)
+    (inst srl num 32 temp)
+    (inst and num mask num)
+    (inst and temp mask temp)
     (inst addq num temp res)))
 \f
 ;;;; multiplying
     (inst addq num temp res)))
 \f
 ;;;; multiplying
   (:args (x :scs (signed-reg))
         (y :scs (signed-reg)))
   (:arg-types signed-num signed-num)
   (:args (x :scs (signed-reg))
         (y :scs (signed-reg)))
   (:arg-types signed-num signed-num)
-  (:note "inline (signed-byte 32) comparison"))
+  (:note "inline (signed-byte 64) comparison"))
 
 (define-vop (fast-conditional-c/signed fast-conditional/signed)
   (:args (x :scs (signed-reg)))
 
 (define-vop (fast-conditional-c/signed fast-conditional/signed)
   (:args (x :scs (signed-reg)))
   (:args (x :scs (unsigned-reg))
         (y :scs (unsigned-reg)))
   (:arg-types unsigned-num unsigned-num)
   (:args (x :scs (unsigned-reg))
         (y :scs (unsigned-reg)))
   (:arg-types unsigned-num unsigned-num)
-  (:note "inline (unsigned-byte 32) comparison"))
+  (:note "inline (unsigned-byte 64) comparison"))
 
 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
   (:args (x :scs (unsigned-reg)))
 
 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
   (:args (x :scs (unsigned-reg)))
       (emit-label done)
       (move res result))))
 
       (emit-label done)
       (move res result))))
 
+(define-source-transform 32bit-logical-not (x)
+  `(logand (lognot (the (unsigned-byte 32) ,x)) #.(1- (ash 1 32))))
 
 
-(define-vop (32bit-logical)
-  (:args (x :scs (unsigned-reg))
-        (y :scs (unsigned-reg)))
-  (:arg-types unsigned-num unsigned-num)
-  (:results (r :scs (unsigned-reg)))
-  (:result-types unsigned-num)
-  (:policy :fast-safe))
+(deftransform 32bit-logical-and ((x y))
+  '(logand x y))
 
 
-(define-vop (32bit-logical-not 32bit-logical)
-  (:translate 32bit-logical-not)
-  (:args (x :scs (unsigned-reg)))
-  (:arg-types unsigned-num)
-  (:generator 2
-    (inst not x r)
-    (inst mskll r 4 r)))
-
-(define-vop (32bit-logical-and 32bit-logical)
-  (:translate 32bit-logical-and)
-  (:generator 1
-    (inst and x y r)))
-
-(deftransform 32bit-logical-nand ((x y) (* *))
-  '(32bit-logical-not (32bit-logical-and x y)))
+(define-source-transform 32bit-logical-nand (x y)
+  `(32bit-logical-not (32bit-logical-and ,x ,y)))
 
 
-(define-vop (32bit-logical-or 32bit-logical)
-  (:translate 32bit-logical-or)
-  (:generator 1
-    (inst bis x y r)))
+(deftransform 32bit-logical-or ((x y))
+  '(logior x y))
 
 
-(define-vop (32bit-logical-nor 32bit-logical)
-  (:translate 32bit-logical-nor)
-  (:generator 2
-    (inst ornot x y r)
-    (inst mskll r 4 r)))
+(define-source-transform 32bit-logical-nor (x y)
+  `(logand (lognor (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
+           #.(1- (ash 1 32))))
 
 
-(define-vop (32bit-logical-xor 32bit-logical)
-  (:translate 32bit-logical-xor)
-  (:generator 1
-    (inst xor x y r)))
+(deftransform 32bit-logical-xor ((x y))
+  '(logxor x y))
 
 
-(deftransform 32bit-logical-eqv ((x y) (* *))
-  '(32bit-logical-not (32bit-logical-xor x y)))
+(define-source-transform 32bit-logical-eqv (x y)
+  `(logand (logeqv (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
+          #.(1- (ash 1 32))))
 
 
-(deftransform 32bit-logical-andc1 ((x y) (* *))
-  '(32bit-logical-and (32bit-logical-not x) y))
+(define-source-transform 32bit-logical-orc1 (x y)
+  `(logand (logorc1 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
+          #.(1- (ash 1 32))))
 
 
-(deftransform 32bit-logical-andc2 ((x y) (* *))
-  '(32bit-logical-and x (32bit-logical-not y)))
+(define-source-transform 32bit-logical-orc2 (x y)
+  `(logand (logorc2 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
+          #.(1- (ash 1 32))))
 
 
-(deftransform 32bit-logical-orc1 ((x y) (* *))
-  '(32bit-logical-or (32bit-logical-not x) y))
-
-(deftransform 32bit-logical-orc2 ((x y) (* *))
-  '(32bit-logical-or x (32bit-logical-not y)))
+(define-source-transform 32bit-logical-andc1 (x y)
+  `(logandc1 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y)))
 
 
+(define-source-transform 32bit-logical-andc2 (x y)
+  `(logandc2 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y)))
 
 (define-vop (shift-towards-someplace)
   (:policy :fast-safe)
 
 (define-vop (shift-towards-someplace)
   (:policy :fast-safe)
   (:generator 6
     (inst mulq x y lo)
     (inst addq lo carry-in lo)
   (:generator 6
     (inst mulq x y lo)
     (inst addq lo carry-in lo)
-    (inst sra lo 32 hi)
+    (inst srl lo 32 hi)
     (inst mskll lo 4 lo)))
 
 
     (inst mskll lo 4 lo)))
 
 
     (inst mulq x y lo)
     (inst addq lo prev lo)
     (inst addq lo carry-in lo)
     (inst mulq x y lo)
     (inst addq lo prev lo)
     (inst addq lo carry-in lo)
-    (inst sra lo 32 hi)
+    (inst srl lo 32 hi)
     (inst mskll lo 4 lo)))
 
 (define-vop (bignum-mult)
     (inst mskll lo 4 lo)))
 
 (define-vop (bignum-mult)