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

📄 arith.lisp

📁 开源跨平台Lisp编译器
💻 LISP
字号:
;;;; simple cases for generic arithmetic;;;; This software is part of the SBCL system. See the README file for;;;; more information.;;;;;;;; This software is derived from the CMU CL system, which was;;;; written at Carnegie Mellon University and released into the;;;; public domain. The software is in the public domain and is;;;; provided with absolutely no warranty. See the COPYING and CREDITS;;;; files for more information.(in-package "SB!VM");;;; addition, subtraction, and multiplication(macrolet ((define-generic-arith-routine ((fun cost) &body body)             `(define-assembly-routine (,(symbolicate "GENERIC-" fun)                                        (:cost ,cost)                                        (:return-style :full-call)                                        (:translate ,fun)                                        (:policy :safe)                                        (:save-p t))                ((:arg x (descriptor-reg any-reg) edx-offset)                 (:arg y (descriptor-reg any-reg)                       ;; this seems wrong esi-offset -- FIXME: What's it mean?                       edi-offset)                 (:res res (descriptor-reg any-reg) edx-offset)                 (:temp eax unsigned-reg eax-offset)                 (:temp ecx unsigned-reg ecx-offset))                (inst mov ecx x)                (inst or ecx y)                (inst test ecx fixnum-tag-mask)  ; both fixnums?                (inst jmp :nz DO-STATIC-FUN)     ; no - do generic                ,@body                (inst clc) ; single-value return                (inst ret)                DO-STATIC-FUN                (inst pop eax)                (inst push ebp-tn)                (inst lea                      ebp-tn                      (make-ea :dword :base esp-tn :disp n-word-bytes))                (inst sub esp-tn (fixnumize 2))                (inst push eax)  ; callers return addr                (inst mov ecx (fixnumize 2)) ; arg count                (inst jmp                      (make-ea :dword                               :disp (+ nil-value                                        (static-fun-offset                                         ',(symbolicate "TWO-ARG-" fun))))))))  (define-generic-arith-routine (+ 10)    (move res x)    (inst add res y)    (inst jmp :no OKAY)    (inst rcr res 1)                  ; carry has correct sign    (inst sar res 1)                  ; remove type bits    (move ecx res)    (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))      (storew ecx res bignum-digits-offset other-pointer-lowtag))    OKAY)  (define-generic-arith-routine (- 10)    (move res x)    (inst sub res y)    (inst jmp :no OKAY)    (inst cmc)                        ; carry has correct sign now    (inst rcr res 1)    (inst sar res 1)                  ; remove type bits    (move ecx res)    (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))      (storew ecx res bignum-digits-offset other-pointer-lowtag))    OKAY)  (define-generic-arith-routine (* 30)    (move eax x)                          ; must use eax for 64-bit result    (inst sar eax n-fixnum-tag-bits)      ; remove *4 fixnum bias    (inst imul y)                         ; result in edx:eax    (inst jmp :no okay)                   ; still fixnum    ;; zzz jrd changed edx to ebx in here, as edx isn't listed as a temp, above    ;;     pfw says that loses big -- edx is target for arg x and result res    ;;     note that 'edx' is not defined -- using x    (inst shrd eax x n-fixnum-tag-bits)    ; high bits from edx    (inst sar x n-fixnum-tag-bits)         ; now shift edx too    (move ecx x)                           ; save high bits from cdq    (inst cdq)                             ; edx:eax <- sign-extend of eax    (inst cmp x ecx)    (inst jmp :e SINGLE-WORD-BIGNUM)    (with-fixed-allocation (res bignum-widetag (+ bignum-digits-offset 2))      (storew eax res bignum-digits-offset other-pointer-lowtag)      (storew ecx res (1+ bignum-digits-offset) other-pointer-lowtag))    (inst jmp DONE)    SINGLE-WORD-BIGNUM    (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))      (storew eax res bignum-digits-offset other-pointer-lowtag))    (inst jmp DONE)    OKAY    (move res eax)    DONE));;;; negation(define-assembly-routine (generic-negate                          (:cost 10)                          (:return-style :full-call)                          (:policy :safe)                          (:translate %negate)                          (:save-p t))                         ((:arg x (descriptor-reg any-reg) edx-offset)                          (:res res (descriptor-reg any-reg) edx-offset)                          (:temp eax unsigned-reg eax-offset)                          (:temp ecx unsigned-reg ecx-offset))  (inst test x fixnum-tag-mask)  (inst jmp :z FIXNUM)  (inst pop eax)  (inst push ebp-tn)  (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))  (inst sub esp-tn (fixnumize 2))  (inst push eax)  (inst mov ecx (fixnumize 1))    ; arg count  (inst jmp (make-ea :dword                     :disp (+ nil-value (static-fun-offset '%negate))))  FIXNUM  (move res x)  (inst neg res)                        ; (- most-negative-fixnum) is BIGNUM  (inst jmp :no OKAY)  (inst shr res n-fixnum-tag-bits)      ; sign bit is data - remove type bits  (move ecx res)  (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))    (storew ecx res bignum-digits-offset other-pointer-lowtag))  OKAY);;;; comparison(macrolet ((define-cond-assem-rtn (name translate static-fn test)             `(define-assembly-routine (,name                                        (:cost 10)                                        (:return-style :full-call)                                        (:policy :safe)                                        (:translate ,translate)                                        (:save-p t))                ((:arg x (descriptor-reg any-reg) edx-offset)                 (:arg y (descriptor-reg any-reg) edi-offset)                 (:res res descriptor-reg edx-offset)                 (:temp eax unsigned-reg eax-offset)                 (:temp ecx unsigned-reg ecx-offset))                (inst mov ecx x)                (inst or ecx y)                (inst test ecx fixnum-tag-mask)                (inst jmp :nz DO-STATIC-FUN)  ; are both fixnums?                (inst cmp x y)                (cond ((member :cmov *backend-subfeatures*)                       (load-symbol res t)                       (inst mov eax nil-value)                       (inst cmov ,test res eax))                      (t                       (inst mov res nil-value)                       (inst jmp ,test RETURN)                       (load-symbol res t)))                RETURN                (inst clc)     ; single-value return                (inst ret)                DO-STATIC-FUN                (inst pop eax)                (inst push ebp-tn)                (inst lea ebp-tn (make-ea :dword                                          :base esp-tn                                          :disp n-word-bytes))                (inst sub esp-tn (fixnumize 2)) ; FIXME: Push 2 words on stack,                                                ; weirdly?                (inst push eax)                (inst mov ecx (fixnumize 2)) ; FIXME: FIXNUMIZE and                                        ; SINGLE-FLOAT-BITS are parallel,                                        ; should be named parallelly.                (inst jmp (make-ea :dword                                   :disp (+ nil-value                                            (static-fun-offset ',static-fn)))))))  (define-cond-assem-rtn generic-< < two-arg-< :ge)  (define-cond-assem-rtn generic-> > two-arg-> :le))(define-assembly-routine (generic-eql                          (:cost 10)                          (:return-style :full-call)                          (:policy :safe)                          (:translate eql)                          (:save-p t))                         ((:arg x (descriptor-reg any-reg) edx-offset)                          (:arg y (descriptor-reg any-reg) edi-offset)                          (:res res descriptor-reg edx-offset)                          (:temp eax unsigned-reg eax-offset)                          (:temp ecx unsigned-reg ecx-offset))  (inst mov ecx x)  (inst and ecx y)  (inst test ecx fixnum-tag-mask)  (inst jmp :nz DO-STATIC-FUN)  ;; At least one fixnum  (inst cmp x y)  (load-symbol res t)  (cond ((member :cmov *backend-subfeatures*)         (inst mov eax nil-value)         (inst cmov :ne res eax))        (t         (inst jmp :e RETURN)         (inst mov res nil-value)))  RETURN  (inst clc)  (inst ret)  ;; FIXME: We could handle all non-numbers here easily enough: go to  ;; TWO-ARG-EQL only if lowtags and widetags match, lowtag is  ;; other-pointer-lowtag and widetag is < code-header-widetag.  DO-STATIC-FUN  (inst pop eax)  (inst push ebp-tn)  (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))  (inst sub esp-tn (fixnumize 2))  (inst push eax)  (inst mov ecx (fixnumize 2))  (inst jmp (make-ea :dword                     :disp (+ nil-value (static-fun-offset 'eql)))))(define-assembly-routine (generic-=                          (:cost 10)                          (:return-style :full-call)                          (:policy :safe)                          (:translate =)                          (:save-p t))                         ((:arg x (descriptor-reg any-reg) edx-offset)                          (:arg y (descriptor-reg any-reg) edi-offset)                          (:res res descriptor-reg edx-offset)                          (:temp eax unsigned-reg eax-offset)                          (:temp ecx unsigned-reg ecx-offset))  (inst mov ecx x)  (inst or ecx y)  (inst test ecx fixnum-tag-mask)        ; both fixnums?  (inst jmp :nz DO-STATIC-FUN)  (inst cmp x y)  (load-symbol res t)  (cond ((member :cmov *backend-subfeatures*)         (inst mov eax nil-value)         (inst cmov :ne res eax))        (t         (inst jmp :e RETURN)         (inst mov res nil-value)))  RETURN  (inst clc)  (inst ret)  DO-STATIC-FUN  (inst pop eax)  (inst push ebp-tn)  (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))  (inst sub esp-tn (fixnumize 2))  (inst push eax)  (inst mov ecx (fixnumize 2))  (inst jmp (make-ea :dword                     :disp (+ nil-value (static-fun-offset 'two-arg-=)))));;; Support for the Mersenne Twister, MT19937, random number generator;;; due to Matsumoto and Nishimura.;;;;;; Makoto Matsumoto and T. Nishimura, "Mersenne twister: A;;; 623-dimensionally equidistributed uniform pseudorandom number;;; generator.", ACM Transactions on Modeling and Computer Simulation,;;; 1997, to appear.;;;;;; State:;;;  0-1:   Constant matrix A. [0, #x9908b0df] (not used here);;;  2:     Index; init. to 1.;;;  3-626: State.;;; This assembly routine is called from the inline VOP and updates;;; the state vector with new random numbers. The state vector is;;; passed in the EAX register.#+sb-assembling ; We don't want a vop for this one.(define-assembly-routine    (random-mt19937-update)    ((:temp state unsigned-reg eax-offset)     (:temp k unsigned-reg ebx-offset)     (:temp y unsigned-reg ecx-offset)     (:temp tmp unsigned-reg edx-offset))  ;; Save the temporary registers.  (inst push k)  (inst push y)  (inst push tmp)  ;; Generate a new set of results.  (inst xor k k)  LOOP1  (inst mov y (make-ea-for-vector-data state :index k :offset 3))  (inst mov tmp (make-ea-for-vector-data state :index k :offset (+ 1 3)))  (inst and y #x80000000)  (inst and tmp #x7fffffff)  (inst or y tmp)  (inst shr y 1)  (inst jmp :nc skip1)  (inst xor y #x9908b0df)  SKIP1  (inst xor y (make-ea-for-vector-data state :index k :offset (+ 397 3)))  (inst mov (make-ea-for-vector-data state :index k :offset 3) y)  (inst inc k)  (inst cmp k (- 624 397))  (inst jmp :b loop1)  LOOP2  (inst mov y (make-ea-for-vector-data state :index k :offset 3))  (inst mov tmp (make-ea-for-vector-data state :index k :offset (+ 1 3)))  (inst and y #x80000000)  (inst and tmp #x7fffffff)  (inst or y tmp)  (inst shr y 1)  (inst jmp :nc skip2)  (inst xor y #x9908b0df)  SKIP2  (inst xor y (make-ea-for-vector-data state :index k :offset (+ (- 397 624) 3)))  (inst mov (make-ea-for-vector-data state :index k :offset 3) y)  (inst inc k)  (inst cmp k (- 624 1))  (inst jmp :b loop2)  (inst mov y (make-ea-for-vector-data state :offset (+ (- 624 1) 3)))  (inst mov tmp (make-ea-for-vector-data state :offset (+ 0 3)))  (inst and y #x80000000)  (inst and tmp #x7fffffff)  (inst or y tmp)  (inst shr y 1)  (inst jmp :nc skip3)  (inst xor y #x9908b0df)  SKIP3  (inst xor y (make-ea-for-vector-data state :offset (+ (- 397 1) 3)))  (inst mov (make-ea-for-vector-data state :offset (+ (- 624 1) 3)) y)  ;; Restore the temporary registers and return.  (inst pop tmp)  (inst pop y)  (inst pop k)  (inst ret))

⌨️ 快捷键说明

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