📄 arith.lisp
字号:
(define-vop (%lea-mod64/unsigned=>unsigned %lea/unsigned=>unsigned) (:translate %lea-mod64))(define-vop (%lea-smod61/fixnum=>fixnum %lea/fixnum=>fixnum) (:translate %lea-smod61));;; logical operations(define-modular-fun lognot-mod64 (x) lognot :untagged nil 64)(define-vop (lognot-mod64/unsigned=>unsigned) (:translate lognot-mod64) (:args (x :scs (unsigned-reg unsigned-stack) :target r :load-if (not (and (sc-is x unsigned-stack) (sc-is r unsigned-stack) (location= x r))))) (:arg-types unsigned-num) (:results (r :scs (unsigned-reg) :load-if (not (and (sc-is x unsigned-stack) (sc-is r unsigned-stack) (location= x r))))) (:result-types unsigned-num) (:policy :fast-safe) (:generator 1 (move r x) (inst not r)))(define-source-transform logeqv (&rest args) (if (oddp (length args)) `(logxor ,@args) `(lognot (logxor ,@args))))(define-source-transform logandc1 (x y) `(logand (lognot ,x) ,y))(define-source-transform logandc2 (x y) `(logand ,x (lognot ,y)))(define-source-transform logorc1 (x y) `(logior (lognot ,x) ,y))(define-source-transform logorc2 (x y) `(logior ,x (lognot ,y)))(define-source-transform lognor (x y) `(lognot (logior ,x ,y)))(define-source-transform lognand (x y) `(lognot (logand ,x ,y)));;;; 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-reffer+offset bignum--ref-with-offset * bignum-digits-offset other-pointer-lowtag (unsigned-reg) unsigned-num sb!bignum:%bignum-ref-with-offset)(define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag (unsigned-reg) unsigned-num sb!bignum:%bignum-set)(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) (:conditional) (:info target not-p) (:generator 3 (inst or digit digit) (inst jmp (if not-p :s :ns) target)));;; For add and sub with carry the sc of carry argument is any-reg so;;; that it may be passed as a fixnum or word and thus may be 0, 1, or;;; 8. This is easy to deal with and may save a fixnum-word;;; conversion.(define-vop (add-w/carry) (:translate sb!bignum:%add-with-carry) (:policy :fast-safe) (:args (a :scs (unsigned-reg) :target result) (b :scs (unsigned-reg unsigned-stack) :to :eval) (c :scs (any-reg) :target temp)) (:arg-types unsigned-num unsigned-num positive-fixnum) (:temporary (:sc any-reg :from (:argument 2) :to :eval) temp) (:results (result :scs (unsigned-reg) :from (:argument 0)) (carry :scs (unsigned-reg))) (:result-types unsigned-num positive-fixnum) (:generator 4 (move result a) (move temp c) (inst neg temp) ; Set the carry flag to 0 if c=0 else to 1 (inst adc result b) (inst mov carry 0) (inst adc carry carry)));;; Note: the borrow is 1 for no borrow and 0 for a borrow, the opposite;;; of the x86-64 convention.(define-vop (sub-w/borrow) (:translate sb!bignum:%subtract-with-borrow) (:policy :fast-safe) (:args (a :scs (unsigned-reg) :to :eval :target result) (b :scs (unsigned-reg unsigned-stack) :to :result) (c :scs (any-reg control-stack))) (:arg-types unsigned-num unsigned-num positive-fixnum) (:results (result :scs (unsigned-reg) :from :eval) (borrow :scs (unsigned-reg))) (:result-types unsigned-num positive-fixnum) (:generator 5 (inst cmp c 1) ; Set the carry flag to 1 if c=0 else to 0 (move result a) (inst sbb result b) (inst mov borrow 1) (inst sbb borrow 0)))(define-vop (bignum-mult-and-add-3-arg) (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg) :target eax) (y :scs (unsigned-reg unsigned-stack)) (carry-in :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num unsigned-num) (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 0) :to (:result 1) :target lo) eax) (:temporary (:sc unsigned-reg :offset edx-offset :from (:argument 1) :to (:result 0) :target hi) edx) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 20 (move eax x) (inst mul eax y) (inst add eax carry-in) (inst adc edx 0) (move hi edx) (move lo eax)))(define-vop (bignum-mult-and-add-4-arg) (:translate sb!bignum:%multiply-and-add) (:policy :fast-safe) (:args (x :scs (unsigned-reg) :target eax) (y :scs (unsigned-reg unsigned-stack)) (prev :scs (unsigned-reg unsigned-stack)) (carry-in :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num) (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 0) :to (:result 1) :target lo) eax) (:temporary (:sc unsigned-reg :offset edx-offset :from (:argument 1) :to (:result 0) :target hi) edx) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 20 (move eax x) (inst mul eax y) (inst add eax prev) (inst adc edx 0) (inst add eax carry-in) (inst adc edx 0) (move hi edx) (move lo eax)))(define-vop (bignum-mult) (:translate sb!bignum:%multiply) (:policy :fast-safe) (:args (x :scs (unsigned-reg) :target eax) (y :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num) (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 0) :to (:result 1) :target lo) eax) (:temporary (:sc unsigned-reg :offset edx-offset :from (:argument 1) :to (:result 0) :target hi) edx) (:results (hi :scs (unsigned-reg)) (lo :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 20 (move eax x) (inst mul eax y) (move hi edx) (move lo eax)))(define-vop (bignum-lognot lognot-mod64/unsigned=>unsigned) (:translate sb!bignum:%lognot))(define-vop (fixnum-to-digit) (:translate sb!bignum:%fixnum-to-digit) (:policy :fast-safe) (:args (fixnum :scs (any-reg control-stack) :target digit)) (:arg-types tagged-num) (:results (digit :scs (unsigned-reg) :load-if (not (and (sc-is fixnum control-stack) (sc-is digit unsigned-stack) (location= fixnum digit))))) (:result-types unsigned-num) (:generator 1 (move digit fixnum) (inst sar digit 3)))(define-vop (bignum-floor) (:translate sb!bignum:%floor) (:policy :fast-safe) (:args (div-high :scs (unsigned-reg) :target edx) (div-low :scs (unsigned-reg) :target eax) (divisor :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num unsigned-num) (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 1) :to (:result 0) :target quo) eax) (:temporary (:sc unsigned-reg :offset edx-offset :from (:argument 0) :to (:result 1) :target rem) edx) (:results (quo :scs (unsigned-reg)) (rem :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:generator 300 (move edx div-high) (move eax div-low) (inst div eax divisor) (move quo eax) (move rem edx)))(define-vop (signify-digit) (:translate sb!bignum:%fixnum-digit-with-correct-sign) (:policy :fast-safe) (:args (digit :scs (unsigned-reg unsigned-stack) :target res)) (:arg-types unsigned-num) (:results (res :scs (any-reg signed-reg) :load-if (not (and (sc-is digit unsigned-stack) (sc-is res control-stack signed-stack) (location= digit res))))) (:result-types signed-num) (:generator 1 (move res digit) (when (sc-is res any-reg control-stack) (inst shl res 3))))(define-vop (digit-ashr) (:translate sb!bignum:%ashr) (:policy :fast-safe) (:args (digit :scs (unsigned-reg unsigned-stack) :target result) (count :scs (unsigned-reg) :target ecx)) (:arg-types unsigned-num positive-fixnum) (:temporary (:sc unsigned-reg :offset ecx-offset :from (:argument 1)) ecx) (:results (result :scs (unsigned-reg) :from (:argument 0) :load-if (not (and (sc-is result unsigned-stack) (location= digit result))))) (:result-types unsigned-num) (:generator 2 (move result digit) (move ecx count) (inst sar result :cl)))(define-vop (digit-ashr/c) (:translate sb!bignum:%ashr) (:policy :fast-safe) (:args (digit :scs (unsigned-reg unsigned-stack) :target result)) (:arg-types unsigned-num (:constant (integer 0 63))) (:info count) (:results (result :scs (unsigned-reg) :from (:argument 0) :load-if (not (and (sc-is result unsigned-stack) (location= digit result))))) (:result-types unsigned-num) (:generator 1 (move result digit) (inst sar result count)))(define-vop (digit-lshr digit-ashr) (:translate sb!bignum:%digit-logical-shift-right) (:generator 1 (move result digit) (move ecx count) (inst shr result :cl)))(define-vop (digit-ashl digit-ashr) (:translate sb!bignum:%ashl) (:generator 1 (move result digit) (move ecx count) (inst shl result :cl)));;;; static functions(define-static-fun two-arg-/ (x y) :translate /)(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-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)(in-package "SB!C")(defun *-transformer (y) (cond ((= y (ash 1 (integer-length y))) ;; there's a generic transform for y = 2^k (give-up-ir1-transform)) ((member y '(3 5 9)) ;; we can do these multiplications directly using LEA `(%lea x x ,(1- y) 0)) (t ;; A normal 64-bit multiplication takes 4 cycles on Athlon 64/Opteron. ;; Optimizing multiplications (other than the above cases) to ;; shifts/adds/leas gives a maximum improvement of 1 cycle, but requires ;; quite a lot of hairy code. (give-up-ir1-transform))))(deftransform * ((x y) ((unsigned-byte 64) (constant-arg (unsigned-byte 64))) (unsigned-byte 64)) "recode as leas, shifts and adds" (let ((y (lvar-value y))) (*-transformer y)))(deftransform sb!vm::*-mod64 ((x y) ((unsigned-byte 64) (constant-arg (unsigned-byte 64))) (unsigned-byte 64)) "recode as leas, shifts and adds" (let ((y (lvar-value y))) (*-transformer y)))(deftransform * ((x y) ((signed-byte 61) (constant-arg (unsigned-byte 64))) (signed-byte 61)) "recode as leas, shifts and adds" (let ((y (lvar-value y))) (*-transformer y)))(deftransform sb!vm::*-smod61 ((x y) ((signed-byte 61) (constant-arg (unsigned-byte 64))) (signed-byte 61)) "recode as leas, shifts and adds" (let ((y (lvar-value y))) (*-transformer y)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -