(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)
;; 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)
;; 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)