⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arith.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 5 页
字号:
  (:arg-types unsigned-num (:constant integer))  (:results (result :scs (unsigned-reg)                    :load-if (not (and (sc-is number unsigned-stack)                                       (sc-is result unsigned-stack)                                       (location= number result)))))  (:result-types unsigned-num)  (:note "inline ASH")  (:generator 3    (cond ((and (= amount 1) (not (location= number result)))           (inst lea result (make-ea :qword :base number :index number)))          ((and (= amount 2) (not (location= number result)))           (inst lea result (make-ea :qword :index number :scale 4)))          ((and (= amount 3) (not (location= number result)))           (inst lea result (make-ea :qword :index number :scale 8)))          (t           (move result number)           (cond ((< -64 amount 64) ;; XXXX                  ;; this code is used both in ASH and ASH-MOD32, so                  ;; be careful                  (if (plusp amount)                      (inst shl result amount)                      (inst shr result (- amount))))                 (t (if (sc-is result unsigned-reg)                        (zeroize result)                        (inst mov result 0))))))))(define-vop (fast-ash-left/signed=>signed)  (:translate ash)  (:args (number :scs (signed-reg) :target result                 :load-if (not (and (sc-is number signed-stack)                                    (sc-is result signed-stack)                                    (location= number result))))         (amount :scs (unsigned-reg) :target ecx))  (:arg-types signed-num positive-fixnum)  (:temporary (:sc unsigned-reg :offset ecx-offset :from (:argument 1)) ecx)  (:results (result :scs (signed-reg) :from (:argument 0)                    :load-if (not (and (sc-is number signed-stack)                                       (sc-is result signed-stack)                                       (location= number result)))))  (:result-types signed-num)  (:policy :fast-safe)  (:note "inline ASH")  (:generator 4    (move result number)    (move ecx amount)    (inst shl result :cl)))(define-vop (fast-ash-left/unsigned=>unsigned)  (:translate ash)  (:args (number :scs (unsigned-reg) :target result                 :load-if (not (and (sc-is number unsigned-stack)                                    (sc-is result unsigned-stack)                                    (location= number result))))         (amount :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 number unsigned-stack)                                       (sc-is result unsigned-stack)                                       (location= number result)))))  (:result-types unsigned-num)  (:policy :fast-safe)  (:note "inline ASH")  (:generator 4    (move result number)    (move ecx amount)    (inst shl result :cl)))(define-vop (fast-ash/signed=>signed)  (:translate ash)  (:policy :fast-safe)  (:args (number :scs (signed-reg) :target result)         (amount :scs (signed-reg) :target ecx))  (:arg-types signed-num signed-num)  (:results (result :scs (signed-reg) :from (:argument 0)))  (:result-types signed-num)  (:temporary (:sc signed-reg :offset ecx-offset :from (:argument 1)) ecx)  (:note "inline ASH")  (:generator 5    (move result number)    (move ecx amount)    (inst or ecx ecx)    (inst jmp :ns POSITIVE)    (inst neg ecx)    (inst cmp ecx 63)    (inst jmp :be OKAY)    (inst mov ecx 63)    OKAY    (inst sar result :cl)    (inst jmp DONE)    POSITIVE    ;; The result-type ensures us that this shift will not overflow.    (inst shl result :cl)    DONE))(define-vop (fast-ash/unsigned=>unsigned)  (:translate ash)  (:policy :fast-safe)  (:args (number :scs (unsigned-reg) :target result)         (amount :scs (signed-reg) :target ecx))  (:arg-types unsigned-num signed-num)  (:results (result :scs (unsigned-reg) :from (:argument 0)))  (:result-types unsigned-num)  (:temporary (:sc signed-reg :offset ecx-offset :from (:argument 1)) ecx)  (:note "inline ASH")  (:generator 5    (move result number)    (move ecx amount)    (inst or ecx ecx)    (inst jmp :ns POSITIVE)    (inst neg ecx)    (inst cmp ecx 63)    (inst jmp :be OKAY)    (zeroize result)    (inst jmp DONE)    OKAY    (inst shr result :cl)    (inst jmp DONE)    POSITIVE    ;; The result-type ensures us that this shift will not overflow.    (inst shl result :cl)    DONE))(in-package "SB!C")(defknown %lea (integer integer (member 1 2 4 8 16) (signed-byte 64))  integer  (foldable flushable movable))(defoptimizer (%lea derive-type) ((base index scale disp))  (when (and (constant-lvar-p scale)             (constant-lvar-p disp))    (let ((scale (lvar-value scale))          (disp (lvar-value disp))          (base-type (lvar-type base))          (index-type (lvar-type index)))      (when (and (numeric-type-p base-type)                 (numeric-type-p index-type))        (let ((base-lo (numeric-type-low base-type))              (base-hi (numeric-type-high base-type))              (index-lo (numeric-type-low index-type))              (index-hi (numeric-type-high index-type)))          (make-numeric-type :class 'integer                             :complexp :real                             :low (when (and base-lo index-lo)                                    (+ base-lo (* index-lo scale) disp))                             :high (when (and base-hi index-hi)                                     (+ base-hi (* index-hi scale) disp))))))))(defun %lea (base index scale disp)  (+ base (* index scale) disp))(in-package "SB!VM")(define-vop (%lea/unsigned=>unsigned)  (:translate %lea)  (:policy :fast-safe)  (:args (base :scs (unsigned-reg))         (index :scs (unsigned-reg)))  (:info scale disp)  (:arg-types unsigned-num unsigned-num              (:constant (member 1 2 4 8))              (:constant (signed-byte 64)))  (:results (r :scs (unsigned-reg)))  (:result-types unsigned-num)  (:generator 5    (inst lea r (make-ea :qword :base base :index index                         :scale scale :disp disp))))(define-vop (%lea/signed=>signed)  (:translate %lea)  (:policy :fast-safe)  (:args (base :scs (signed-reg))         (index :scs (signed-reg)))  (:info scale disp)  (:arg-types signed-num signed-num              (:constant (member 1 2 4 8))              (:constant (signed-byte 64)))  (:results (r :scs (signed-reg)))  (:result-types signed-num)  (:generator 4    (inst lea r (make-ea :qword :base base :index index                         :scale scale :disp disp))))(define-vop (%lea/fixnum=>fixnum)  (:translate %lea)  (:policy :fast-safe)  (:args (base :scs (any-reg))         (index :scs (any-reg)))  (:info scale disp)  (:arg-types tagged-num tagged-num              (:constant (member 1 2 4 8))              (:constant (signed-byte 64)))  (:results (r :scs (any-reg)))  (:result-types tagged-num)  (:generator 3    (inst lea r (make-ea :qword :base base :index index                         :scale scale :disp disp))));;; FIXME: before making knowledge of this too public, it needs to be;;; fixed so that it's actually _faster_ than the non-CMOV version; at;;; least on my Celeron-XXX laptop, this version is marginally slower;;; than the above version with branches.  -- CSR, 2003-09-04(define-vop (fast-cmov-ash/unsigned=>unsigned)  (:translate ash)  (:policy :fast-safe)  (:args (number :scs (unsigned-reg) :target result)         (amount :scs (signed-reg) :target ecx))  (:arg-types unsigned-num signed-num)  (:results (result :scs (unsigned-reg) :from (:argument 0)))  (:result-types unsigned-num)  (:temporary (:sc signed-reg :offset ecx-offset :from (:argument 1)) ecx)  (:temporary (:sc any-reg :from (:eval 0) :to (:eval 1)) zero)  (:note "inline ASH")  (:guard (member :cmov *backend-subfeatures*))  (:generator 4    (move result number)    (move ecx amount)    (inst or ecx ecx)    (inst jmp :ns POSITIVE)    (inst neg ecx)    (zeroize zero)    (inst shr result :cl)    (inst cmp ecx 63)    (inst cmov :nbe result zero)    (inst jmp DONE)    POSITIVE    ;; The result-type ensures us that this shift will not overflow.    (inst shl result :cl)    DONE))(define-vop (signed-byte-64-len)  (:translate integer-length)  (:note "inline (signed-byte 64) integer-length")  (:policy :fast-safe)  (:args (arg :scs (signed-reg) :target res))  (:arg-types signed-num)  (:results (res :scs (unsigned-reg)))  (:result-types unsigned-num)  (:generator 28    (move res arg)    (if (sc-is res unsigned-reg)        (inst test res res)        (inst cmp res 0))    (inst jmp :ge POS)    (inst not res)    POS    (inst bsr res res)    (inst jmp :z ZERO)    (inst inc res)    (inst jmp DONE)    ZERO    (zeroize res)    DONE))(define-vop (unsigned-byte-64-len)  (:translate integer-length)  (:note "inline (unsigned-byte 64) integer-length")  (:policy :fast-safe)  (:args (arg :scs (unsigned-reg)))  (:arg-types unsigned-num)  (:results (res :scs (unsigned-reg)))  (:result-types unsigned-num)  (:generator 26    (inst bsr res arg)    (inst jmp :z ZERO)    (inst inc res)    (inst jmp DONE)    ZERO    (zeroize res)    DONE))(define-vop (unsigned-byte-64-count)  (:translate logcount)  (:note "inline (unsigned-byte 64) logcount")  (:policy :fast-safe)  (:args (arg :scs (unsigned-reg) :target result))  (:arg-types unsigned-num)  (:results (result :scs (unsigned-reg)))  (:result-types positive-fixnum)  (:temporary (:sc unsigned-reg) temp)  (:temporary (:sc unsigned-reg) mask)  (:generator 14    ;; See the comments below for how the algorithm works. The tricks    ;; used can be found for example in AMD's software optimization    ;; guide or at "http://www.hackersdelight.org/HDcode/pop.cc" in the    ;; function "pop1", for 32-bit words. The extension to 64 bits is    ;; straightforward.    ;; Calculate 2-bit sums. Note that the value of a two-digit binary    ;; number is the sum of the right digit and twice the left digit.    ;; Thus we can calculate the sum of the two digits by shifting the    ;; left digit to the right position and doing a two-bit subtraction.    ;; This subtraction will never create a borrow and thus can be made    ;; on all 32 2-digit numbers at once.    (move result arg)    (move temp arg)    (inst shr result 1)    (inst mov mask #x5555555555555555)    (inst and result mask)    (inst sub temp result)    ;; Calculate 4-bit sums by straightforward shift, mask and add.    ;; Note that we shift the source operand of the MOV and not its    ;; destination so that the SHR and the MOV can execute in the same    ;; clock cycle.    (inst mov result temp)    (inst shr temp 2)    (inst mov mask #x3333333333333333)    (inst and result mask)    (inst and temp mask)    (inst add result temp)    ;; Calculate 8-bit sums. Since each sum is at most 8, which fits    ;; into 4 bits, we can apply the mask after the addition, saving one    ;; instruction.    (inst mov temp result)    (inst shr result 4)    (inst add result temp)    (inst mov mask #x0f0f0f0f0f0f0f0f)    (inst and result mask)    ;; Add all 8 bytes at once by multiplying with #256r11111111.    ;; We need to calculate only the lower 8 bytes of the product.    ;; Of these the most significant byte contains the final result.    ;; Note that there can be no overflow from one byte to the next    ;; as the sum is at most 64 which needs only 7 bits.    (inst mov mask #x0101010101010101)    (inst imul result mask)    (inst shr result 56)));;;; binary conditional VOPs(define-vop (fast-conditional)  (:conditional)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -