0.9.7.28:
[sbcl.git] / src / assembly / mips / arith.lisp
index c36fcdd..94803c9 100644 (file)
@@ -1,24 +1,33 @@
 (in-package "SB!VM")
 
 
+\f
+;;;; Addition and subtraction.
+
+;;; static-fun-offset returns the address of the raw_addr slot of
+;;; a static function's fdefn.
+
+;;; Note that there is only one use of static-fun-offset outside this
+;;; file (in genesis.lisp)
+
 (define-assembly-routine (generic-+
-                         (:cost 10)
-                         (:return-style :full-call)
-                         (:translate +)
-                         (:policy :safe)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-
-                         (:res res (descriptor-reg any-reg) a0-offset)
-
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp temp1 non-descriptor-reg nl1-offset)
-                         (:temp temp2 non-descriptor-reg nl2-offset)
-                         (:temp pa-flag non-descriptor-reg nl4-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 10)
+                          (:return-style :full-call)
+                          (:translate +)
+                          (:policy :safe)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res (descriptor-reg any-reg) a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp temp1 non-descriptor-reg nl1-offset)
+                          (:temp temp2 non-descriptor-reg nl2-offset)
+                          (:temp pa-flag non-descriptor-reg nl4-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   (inst beq temp DO-ADD)
@@ -27,9 +36,9 @@
   ;; DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'two-arg-+))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   DO-ADD
   (inst sra temp2 y n-fixnum-tag-bits)
 
 
 (define-assembly-routine (generic--
-                         (:cost 10)
-                         (:return-style :full-call)
-                         (:translate -)
-                         (:policy :safe)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-
-                         (:res res (descriptor-reg any-reg) a0-offset)
-
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp temp1 non-descriptor-reg nl1-offset)
-                         (:temp temp2 non-descriptor-reg nl2-offset)
-                         (:temp pa-flag non-descriptor-reg nl4-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 10)
+                          (:return-style :full-call)
+                          (:translate -)
+                          (:policy :safe)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res (descriptor-reg any-reg) a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp temp1 non-descriptor-reg nl1-offset)
+                          (:temp temp2 non-descriptor-reg nl2-offset)
+                          (:temp pa-flag non-descriptor-reg nl4-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   (inst beq temp DO-SUB)
@@ -77,9 +86,9 @@
   ;; DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'two-arg--))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   DO-SUB
   (inst sra temp2 y n-fixnum-tag-bits)
   DONE)
 
 
+\f
+;;;; Multiplication
+
+
 (define-assembly-routine (generic-*
-                         (:cost 25)
-                         (:return-style :full-call)
-                         (:translate *)
-                         (:policy :safe)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-
-                         (:res res (descriptor-reg any-reg) a0-offset)
-
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp lo non-descriptor-reg nl1-offset)
-                         (:temp hi non-descriptor-reg nl2-offset)
-                         (:temp pa-flag non-descriptor-reg nl4-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 25)
+                          (:return-style :full-call)
+                          (:translate *)
+                          (:policy :safe)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res (descriptor-reg any-reg) a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp lo non-descriptor-reg nl1-offset)
+                          (:temp hi non-descriptor-reg nl2-offset)
+                          (:temp pa-flag non-descriptor-reg nl4-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   ;; If either arg is not a fixnum, call the static function.
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   (pseudo-atomic (pa-flag :extra (pad-data-block (+ 1 bignum-digits-offset)))
     (inst or res alloc-tn other-pointer-lowtag)
     (storew temp res 0 other-pointer-lowtag))
-
-  (storew lo res bignum-digits-offset other-pointer-lowtag)
-
-  ;; Out of here
   (inst b DONE)
-  (inst nop)
+  (storew lo res bignum-digits-offset other-pointer-lowtag)
 
   TWO-WORDS
   (pseudo-atomic (pa-flag :extra (pad-data-block (+ 2 bignum-digits-offset)))
     (storew temp res 0 other-pointer-lowtag))
 
   (storew lo res bignum-digits-offset other-pointer-lowtag)
-  (storew hi res (1+ bignum-digits-offset) other-pointer-lowtag)
-
-  ;; Out of here
   (inst b DONE)
-  (inst nop)
+  (storew hi res (1+ bignum-digits-offset) other-pointer-lowtag)
 
   DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'two-arg-*))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   DONE)
 
+(macrolet
+    ((frob (name note cost type sc signed-p)
+       `(define-assembly-routine (,name
+                                  (:note ,note)
+                                  (:cost ,cost)
+                                  (:translate *)
+                                  (:policy :fast-safe)
+                                  (:arg-types ,type ,type)
+                                  (:result-types ,type))
+                                 ((:arg x ,sc nl0-offset)
+                                  (:arg y ,sc nl1-offset)
+                                  (:res res ,sc nl0-offset))
+          ,@(when (eq type 'tagged-num)
+              `((inst sra x 2)))
+          (inst ,(if signed-p 'mult 'multu) x y)
+          (inst mflo res))))
+  (frob unsigned-* "unsigned *" 40 unsigned-num unsigned-reg nil)
+  (frob signed-* "signed *" 41 signed-num signed-reg t)
+  (frob fixnum-* "fixnum *" 30 tagged-num any-reg t))
+
+
+\f
+;;;; Division.
+
+
+(define-assembly-routine (positive-fixnum-truncate
+                          (:note "unsigned fixnum truncate")
+                          (:cost 45)
+                          (:translate truncate)
+                          (:policy :fast-safe)
+                          (:arg-types positive-fixnum positive-fixnum)
+                          (:result-types positive-fixnum positive-fixnum))
+                         ((:arg dividend any-reg nl0-offset)
+                          (:arg divisor any-reg nl1-offset)
+
+                          (:res quo any-reg nl2-offset)
+                          (:res rem any-reg nl3-offset))
+  (let ((error (generate-error-code nil division-by-zero-error
+                                    dividend divisor)))
+    (inst beq divisor error)
+    (inst nop))
+
+    (inst divu dividend divisor)
+    (inst mflo quo)
+    (inst mfhi rem)
+    (inst sll quo 2))
+
+
+(define-assembly-routine (fixnum-truncate
+                          (:note "fixnum truncate")
+                          (:cost 50)
+                          (:policy :fast-safe)
+                          (:translate truncate)
+                          (:arg-types tagged-num tagged-num)
+                          (:result-types tagged-num tagged-num))
+                         ((:arg dividend any-reg nl0-offset)
+                          (:arg divisor any-reg nl1-offset)
+
+                          (:res quo any-reg nl2-offset)
+                          (:res rem any-reg nl3-offset))
+  (let ((error (generate-error-code nil division-by-zero-error
+                                    dividend divisor)))
+    (inst beq divisor error)
+    (inst nop))
+
+    (inst div dividend divisor)
+    (inst mflo quo)
+    (inst mfhi rem)
+    (inst sll quo 2))
+
+
+(define-assembly-routine (signed-truncate
+                          (:note "(signed-byte 32) truncate")
+                          (:cost 60)
+                          (:policy :fast-safe)
+                          (:translate truncate)
+                          (:arg-types signed-num signed-num)
+                          (:result-types signed-num signed-num))
+
+                         ((:arg dividend signed-reg nl0-offset)
+                          (:arg divisor signed-reg nl1-offset)
+
+                          (:res quo signed-reg nl2-offset)
+                          (:res rem signed-reg nl3-offset))
+  (let ((error (generate-error-code nil division-by-zero-error
+                                    dividend divisor)))
+    (inst beq divisor error)
+    (inst nop))
+
+    (inst div dividend divisor)
+    (inst mflo quo)
+    (inst mfhi rem))
+
 
 \f
 ;;;; Comparison routines.
 
 (macrolet
-    ((define-cond-assem-rtn (name translate static-fn cmp)
+    ((define-cond-assem-rtn (name translate static-fn cmp not-p)
        `(define-assembly-routine (,name
-                                 (:cost 10)
-                                 (:return-style :full-call)
-                                 (:policy :safe)
-                                 (:translate ,translate)
-                                 (:save-p t))
-                                ((:arg x (descriptor-reg any-reg) a0-offset)
-                                 (:arg y (descriptor-reg any-reg) a1-offset)
-                                 
-                                 (:res res descriptor-reg a0-offset)
-                                 
-                                 (:temp temp non-descriptor-reg nl0-offset)
-                                 (:temp lip interior-reg lip-offset)
-                                 (:temp nargs any-reg nargs-offset)
-                                 (:temp ocfp any-reg ocfp-offset))
-         (inst or temp x y)
-         (inst and temp fixnum-tag-mask)
-         (inst beq temp DO-COMPARE)
-         ,cmp
-
-         ;; DO-STATIC-FUN
-         (inst lw lip null-tn (static-fun-offset ',static-fn))
-         (inst li nargs (fixnumize 2))
-         (inst move ocfp cfp-tn)
-         (inst j lip)
-         (inst move cfp-tn csp-tn)
-         
-         DO-COMPARE
-         (inst beq temp DONE)
-         (inst move res null-tn)
-         (load-symbol res t)
-
-         DONE)))
-
-  (define-cond-assem-rtn generic-< < two-arg-< (inst slt temp x y))
-  (define-cond-assem-rtn generic-> > two-arg-> (inst slt temp y x)))
+                                  (:cost 10)
+                                  (:return-style :full-call)
+                                  (:policy :safe)
+                                  (:translate ,translate)
+                                  (:save-p t))
+                                 ((:arg x (descriptor-reg any-reg) a0-offset)
+                                  (:arg y (descriptor-reg any-reg) a1-offset)
+
+                                  (:res res descriptor-reg a0-offset)
+
+                                  (:temp temp non-descriptor-reg nl0-offset)
+                                  (:temp lip interior-reg lip-offset)
+                                  (:temp nargs any-reg nargs-offset)
+                                  (:temp ocfp any-reg ocfp-offset))
+          (inst or temp x y)
+          (inst and temp fixnum-tag-mask)
+          (inst beq temp DO-COMPARE)
+          ,cmp
+
+          ;; DO-STATIC-FUN
+          (inst lw lip null-tn (static-fun-offset ',static-fn))
+          (inst li nargs (fixnumize 2))
+          (move ocfp cfp-tn)
+          (inst j lip)
+          (move cfp-tn csp-tn t)
+
+          DO-COMPARE
+          (inst ,(if not-p 'beq 'bne) temp DONE)
+          (move res null-tn t)
+          (load-symbol res t)
+
+          DONE)))
+
+  (define-cond-assem-rtn generic-< < two-arg-< (inst slt temp x y) t)
+  (define-cond-assem-rtn generic-<= <= two-arg-<= (inst slt temp x y) nil)
+  (define-cond-assem-rtn generic-> > two-arg-> (inst slt temp y x) t)
+  (define-cond-assem-rtn generic->= >= two-arg->= (inst slt temp y x) nil))
 
 
 (define-assembly-routine (generic-eql
-                         (:cost 10)
-                         (:return-style :full-call)
-                         (:policy :safe)
-                         (:translate eql)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-                         
-                         (:res res descriptor-reg a0-offset)
-                         
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 10)
+                          (:return-style :full-call)
+                          (:policy :safe)
+                          (:translate eql)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res descriptor-reg a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   (inst beq x y RETURN-T)
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   ;; DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'eql))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   RETURN
   (inst bne x y DONE)
-  (inst move res null-tn)
+  (move res null-tn t)
 
   RETURN-T
   (load-symbol res t)
 
 
 (define-assembly-routine (generic-=
-                         (:cost 10)
-                         (:return-style :full-call)
-                         (:policy :safe)
-                         (:translate =)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-                         
-                         (:res res descriptor-reg a0-offset)
-                         
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 10)
+                          (:return-style :full-call)
+                          (:policy :safe)
+                          (:translate =)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res descriptor-reg a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   (inst beq temp RETURN)
   ;; DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'two-arg-=))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   RETURN
   (inst bne x y DONE)
-  (inst move res null-tn)
+  (move res null-tn t)
   (load-symbol res t)
 
   DONE)
 
 
 (define-assembly-routine (generic-/=
-                         (:cost 10)
-                         (:return-style :full-call)
-                         (:policy :safe)
-                         (:translate /=)
-                         (:save-p t))
-                        ((:arg x (descriptor-reg any-reg) a0-offset)
-                         (:arg y (descriptor-reg any-reg) a1-offset)
-                         
-                         (:res res descriptor-reg a0-offset)
-                         
-                         (:temp temp non-descriptor-reg nl0-offset)
-                         (:temp lip interior-reg lip-offset)
-                         (:temp nargs any-reg nargs-offset)
-                         (:temp ocfp any-reg ocfp-offset))
+                          (:cost 10)
+                          (:return-style :full-call)
+                          (:policy :safe)
+                          (:translate /=)
+                          (:save-p t))
+                         ((:arg x (descriptor-reg any-reg) a0-offset)
+                          (:arg y (descriptor-reg any-reg) a1-offset)
+
+                          (:res res descriptor-reg a0-offset)
+
+                          (:temp temp non-descriptor-reg nl0-offset)
+                          (:temp lip interior-reg lip-offset)
+                          (:temp nargs any-reg nargs-offset)
+                          (:temp ocfp any-reg ocfp-offset))
   (inst or temp x y)
   (inst and temp fixnum-tag-mask)
   (inst beq temp RETURN)
   ;; DO-STATIC-FUN
   (inst lw lip null-tn (static-fun-offset 'two-arg-/=))
   (inst li nargs (fixnumize 2))
-  (inst move ocfp cfp-tn)
+  (move ocfp cfp-tn)
   (inst j lip)
-  (inst move cfp-tn csp-tn)
+  (move cfp-tn csp-tn t)
 
   RETURN
   (inst beq x y DONE)
-  (inst move res null-tn)
+  (move res null-tn t)
   (load-symbol res t)
 
   DONE)