📄 arith.lisp
字号:
;;;; binary conditional VOPs(define-vop (fast-conditional) (:conditional) (:info target not-p) (:effects) (:affected) (:temporary (:scs (non-descriptor-reg)) temp) (:policy :fast-safe))(define-vop (fast-conditional/fixnum fast-conditional) (:args (x :scs (any-reg)) (y :scs (any-reg))) (:arg-types tagged-num tagged-num) (:note "inline fixnum comparison"))(define-vop (fast-conditional-c/fixnum fast-conditional/fixnum) (:args (x :scs (any-reg))) (:arg-types tagged-num (:constant (unsigned-byte-with-a-bite-out 6 4))) (:info target not-p y))(define-vop (fast-conditional/signed fast-conditional) (:args (x :scs (signed-reg)) (y :scs (signed-reg))) (:arg-types signed-num signed-num) (:note "inline (signed-byte 64) comparison"))(define-vop (fast-conditional-c/signed fast-conditional/signed) (:args (x :scs (signed-reg))) (:arg-types signed-num (:constant (unsigned-byte-with-a-bite-out 8 1))) (:info target not-p y))(define-vop (fast-conditional/unsigned fast-conditional) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg))) (:arg-types unsigned-num unsigned-num) (:note "inline (unsigned-byte 64) comparison"))(define-vop (fast-conditional-c/unsigned fast-conditional/unsigned) (:args (x :scs (unsigned-reg))) (:arg-types unsigned-num (:constant (unsigned-byte-with-a-bite-out 8 1))) (:info target not-p y))(defmacro define-conditional-vop (translate &rest generator) `(progn ,@(mapcar (lambda (suffix cost signed) (unless (and (member suffix '(/fixnum -c/fixnum)) (eq translate 'eql)) `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)" translate suffix)) ,(intern (format nil "~:@(FAST-CONDITIONAL~A~)" suffix))) (:translate ,translate) (:generator ,cost (let* ((signed ,signed) (-c/fixnum ,(eq suffix '-c/fixnum)) (y (if -c/fixnum (fixnumize y) y))) ,@generator))))) '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned) '(3 2 5 4 5 4) '(t t t t nil nil))))(define-conditional-vop < (cond ((and signed (eql y 0)) (if not-p (inst bge x target) (inst blt x target))) (t (if signed (inst cmplt x y temp) (inst cmpult x y temp)) (if not-p (inst beq temp target) (inst bne temp target)))))(define-conditional-vop > (cond ((and signed (eql y 0)) (if not-p (inst ble x target) (inst bgt x target))) ((integerp y) (let ((y (+ y (if -c/fixnum (fixnumize 1) 1)))) (if signed (inst cmplt x y temp) (inst cmpult x y temp)) (if not-p (inst bne temp target) (inst beq temp target)))) (t (if signed (inst cmplt y x temp) (inst cmpult y x temp)) (if not-p (inst beq temp target) (inst bne temp target)))));;; EQL/FIXNUM is funny because the first arg can be of any type, not;;; just a known fixnum.(define-conditional-vop eql (declare (ignore signed)) (when (integerp y) (inst li y temp) (setf y temp)) (inst cmpeq x y temp) (if not-p (inst beq temp target) (inst bne temp target)));;; These versions specify a fixnum restriction on their first arg. We;;; have also generic-eql/fixnum VOPs which are the same, but have no;;; restriction on the first arg and a higher cost. The reason for;;; doing this is to prevent fixnum specific operations from being;;; used on word integers, spuriously consing the argument.(define-vop (fast-eql/fixnum fast-conditional) (:args (x :scs (any-reg)) (y :scs (any-reg))) (:arg-types tagged-num tagged-num) (:note "inline fixnum comparison") (:translate eql) (:generator 3 (cond ((equal y zero-tn) (if not-p (inst bne x target) (inst beq x target))) (t (inst cmpeq x y temp) (if not-p (inst beq temp target) (inst bne temp target))))));;;(define-vop (generic-eql/fixnum fast-eql/fixnum) (:args (x :scs (any-reg descriptor-reg)) (y :scs (any-reg))) (:arg-types * tagged-num) (:variant-cost 7))(define-vop (fast-eql-c/fixnum fast-conditional/fixnum) (:args (x :scs (any-reg))) (:arg-types tagged-num (:constant (signed-byte 6))) (:temporary (:scs (non-descriptor-reg)) temp) (:info target not-p y) (:translate eql) (:generator 2 (let ((y (cond ((eql y 0) zero-tn) (t (inst li (fixnumize y) temp) temp)))) (inst cmpeq x y temp) (if not-p (inst beq temp target) (inst bne temp target)))));;;(define-vop (generic-eql-c/fixnum fast-eql-c/fixnum) (:args (x :scs (any-reg descriptor-reg))) (:arg-types * (:constant (signed-byte 6))) (:variant-cost 6));;;; 32-bit logical operations(define-vop (merge-bits) (:translate merge-bits) (:args (shift :scs (signed-reg unsigned-reg)) (prev :scs (unsigned-reg)) (next :scs (unsigned-reg))) (:arg-types tagged-num unsigned-num unsigned-num) (:temporary (:scs (unsigned-reg) :to (:result 0)) temp) (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res) (:results (result :scs (unsigned-reg))) (:result-types unsigned-num) (:policy :fast-safe) (:generator 4 (let ((done (gen-label))) (inst srl next shift res) (inst beq shift done) (inst subq zero-tn shift temp) (inst sll prev temp temp) (inst bis res temp res) (emit-label done) (move res result))))(define-vop (shift-towards-someplace) (:policy :fast-safe) (:args (num :scs (unsigned-reg)) (amount :scs (signed-reg))) (:arg-types unsigned-num tagged-num) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num))(define-vop (shift-towards-start shift-towards-someplace) (:translate shift-towards-start) (:note "SHIFT-TOWARDS-START") (:temporary (:sc non-descriptor-reg) temp) (:generator 1 (inst and amount #x1f temp) (inst srl num temp r)))(define-vop (shift-towards-end shift-towards-someplace) (:translate shift-towards-end) (:note "SHIFT-TOWARDS-END") (:temporary (:sc non-descriptor-reg) temp) (:generator 1 (inst and amount #x1f temp) (inst sll num temp r)));;;; bignum stuff(define-vop (bignum-length get-header-data) (:translate sb!bignum:%bignum-length) (:policy :fast-safe))(define-vop (bignum-set-length set-header-data) (:translate sb!bignum:%bignum-set-length) (:policy :fast-safe))(define-full-reffer bignum-ref * bignum-digits-offset other-pointer-lowtag (unsigned-reg) unsigned-num sb!bignum:%bignum-ref)(define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag (unsigned-reg) unsigned-num sb!bignum:%bignum-set #!+gengc nil)(define-vop (digit-0-or-plus) (:translate sb!bignum:%digit-0-or-plusp) (:policy :fast-safe) (:args (digit :scs (unsigned-reg))) (:arg-types unsigned-num) (:temporary (:sc non-descriptor-reg) temp) (:conditional) (:info target not-p) (:generator 2 (inst sll digit 32 temp) (if not-p (inst blt temp target) (inst bge temp target))))(define-vop (add-w/carry) (:translate sb!bignum:%add-with-carry) (:policy :fast-safe) (:args (a :scs (unsigned-reg)) (b :scs (unsigned-reg)) (c :scs (unsigned-reg))) (:arg-types unsigned-num unsigned-num positive-fixnum) (:results (result :scs (unsigned-reg) :from :load) (carry :scs (unsigned-reg) :from :eval)) (:result-types unsigned-num positive-fixnum) (:generator 5 (inst addq a b result) (inst addq result c result) (inst sra result 32 carry) (inst mskll result 4 result)))(define-vop (sub-w/borrow) (:translate sb!bignum:%subtract-with-borrow) (:policy :fast-safe) (:args (a :scs (unsigned-reg)) (b :scs (unsigned-reg)) (c :scs (unsigned-reg))) (:arg-types unsigned-num unsigned-num positive-fixnum) (:results (result :scs (unsigned-reg) :from :load) (borrow :scs (unsigned-reg) :from :eval)) (:result-types unsigned-num positive-fixnum) (:generator 4 (inst xor c 1 result) (inst subq a result result) (inst subq result b result) (inst srl result 63 borrow) (inst xor borrow 1 borrow) (inst mskll result 4 result)))(define-vop (bignum-mult-and-add-3-arg) (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg)) (carry-in :scs (unsigned-reg) :to :save)) (:arg-types unsigned-num unsigned-num unsigned-num) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 6 (inst mulq x y lo) (inst addq lo carry-in lo) (inst srl lo 32 hi) (inst mskll lo 4 lo)))(define-vop (bignum-mult-and-add-4-arg) (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg)) (prev :scs (unsigned-reg)) (carry-in :scs (unsigned-reg) :to :save)) (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 9 (inst mulq x y lo) (inst addq lo prev lo) (inst addq lo carry-in lo) (inst srl lo 32 hi) (inst mskll lo 4 lo)))(define-vop (bignum-mult) (:translate sb!bignum:%multiply) (:policy :fast-safe) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg))) (:arg-types unsigned-num unsigned-num) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 3 (inst mulq x y lo) (inst srl lo 32 hi) (inst mskll lo 4 lo)))(define-vop (bignum-lognot) (:translate sb!bignum:%lognot) (:policy :fast-safe) (:args (x :scs (unsigned-reg))) (:arg-types unsigned-num) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num) (:generator 1 (inst not x r) (inst mskll r 4 r)))(define-vop (fixnum-to-digit) (:translate sb!bignum:%fixnum-to-digit) (:policy :fast-safe) (:args (fixnum :scs (any-reg))) (:arg-types tagged-num) (:results (digit :scs (unsigned-reg))) (:result-types unsigned-num) (:generator 1 (inst sra fixnum n-fixnum-tag-bits digit)))(define-vop (bignum-floor) (:translate sb!bignum:%floor) (:policy :fast-safe) (:args (num-high :scs (unsigned-reg)) (num-low :scs (unsigned-reg)) (denom-arg :scs (unsigned-reg) :target denom)) (:arg-types unsigned-num unsigned-num unsigned-num) (:temporary (:scs (unsigned-reg) :from (:argument 2)) denom) (:temporary (:scs (unsigned-reg) :from (:eval 0)) temp) (:results (quo :scs (unsigned-reg) :from (:eval 0)) (rem :scs (unsigned-reg) :from (:argument 0))) (:result-types unsigned-num unsigned-num) (:generator 325 ; number of inst assuming targeting works. (inst sll num-high 32 rem) (inst bis rem num-low rem) (inst sll denom-arg 32 denom) (inst cmpule denom rem quo) (inst beq quo shift1) (inst subq rem denom rem) SHIFT1 (dotimes (i 32) (let ((shift2 (gen-label))) (inst srl denom 1 denom) (inst cmpule denom rem temp) (inst sll quo 1 quo) (inst beq temp shift2) (inst subq rem denom rem) (inst bis quo 1 quo) (emit-label shift2)))))(define-vop (signify-digit) (:translate sb!bignum:%fixnum-digit-with-correct-sign) (:policy :fast-safe) (:args (digit :scs (unsigned-reg) :target res)) (:arg-types unsigned-num) (:results (res :scs (any-reg signed-reg))) (:result-types signed-num) (:generator 2 (sc-case res (any-reg (inst sll digit 34 res) (inst sra res 32 res)) (signed-reg (inst sll digit 32 res) (inst sra res 32 res)))))(define-vop (digit-ashr) (:translate sb!bignum:%ashr) (:policy :fast-safe) (:args (digit :scs (unsigned-reg)) (count :scs (unsigned-reg))) (:arg-types unsigned-num positive-fixnum) (:results (result :scs (unsigned-reg) :from (:argument 0))) (:result-types unsigned-num) (:generator 1 (inst sll digit 32 result) (inst sra result count result) (inst srl result 32 result)))(define-vop (digit-lshr digit-ashr) (:translate sb!bignum:%digit-logical-shift-right) (:generator 1 (inst srl digit count result)))(define-vop (digit-ashl digit-ashr) (:translate sb!bignum:%ashl) (:generator 1 (inst sll digit count result)));;;; static functions(define-static-fun two-arg-gcd (x y) :translate gcd)(define-static-fun two-arg-lcm (x y) :translate lcm)(define-static-fun two-arg-+ (x y) :translate +)(define-static-fun two-arg-- (x y) :translate -)(define-static-fun two-arg-* (x y) :translate *)(define-static-fun two-arg-/ (x y) :translate /)(define-static-fun two-arg-< (x y) :translate <)(define-static-fun two-arg-<= (x y) :translate <=)(define-static-fun two-arg-> (x y) :translate >)(define-static-fun two-arg->= (x y) :translate >=)(define-static-fun two-arg-= (x y) :translate =)(define-static-fun two-arg-/= (x y) :translate /=)(define-static-fun %negate (x) :translate %negate)(define-static-fun two-arg-and (x y) :translate logand)(define-static-fun two-arg-ior (x y) :translate logior)(define-static-fun two-arg-xor (x y) :translate logxor)(define-static-fun two-arg-eqv (x y) :translate logeqv)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -