📄 arith.lisp
字号:
;;;; the VM definition of arithmetic VOPs for the x86-64;;;; 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");;;; unary operations(define-vop (fast-safe-arith-op) (:policy :fast-safe) (:effects) (:affected))(define-vop (fixnum-unop fast-safe-arith-op) (:args (x :scs (any-reg) :target res)) (:results (res :scs (any-reg))) (:note "inline fixnum arithmetic") (:arg-types tagged-num) (:result-types tagged-num))(define-vop (signed-unop fast-safe-arith-op) (:args (x :scs (signed-reg) :target res)) (:results (res :scs (signed-reg))) (:note "inline (signed-byte 64) arithmetic") (:arg-types signed-num) (:result-types signed-num))(define-vop (fast-negate/fixnum fixnum-unop) (:translate %negate) (:generator 1 (move res x) (inst neg res)))(define-vop (fast-negate/signed signed-unop) (:translate %negate) (:generator 2 (move res x) (inst neg res)))(define-vop (fast-lognot/fixnum fixnum-unop) (:translate lognot) (:generator 1 (move res x) (inst xor res (fixnumize -1))))(define-vop (fast-lognot/signed signed-unop) (:translate lognot) (:generator 2 (move res x) (inst not res)));;;; binary fixnum operations;;; Assume that any constant operand is the second arg...(define-vop (fast-fixnum-binop fast-safe-arith-op) (:args (x :target r :scs (any-reg) :load-if (not (and (sc-is x control-stack) (sc-is y any-reg) (sc-is r control-stack) (location= x r)))) (y :scs (any-reg control-stack))) (:arg-types tagged-num tagged-num) (:results (r :scs (any-reg) :from (:argument 0) :load-if (not (and (sc-is x control-stack) (sc-is y any-reg) (sc-is r control-stack) (location= x r))))) (:result-types tagged-num) (:note "inline fixnum arithmetic"))(define-vop (fast-unsigned-binop fast-safe-arith-op) (:args (x :target r :scs (unsigned-reg) :load-if (not (and (sc-is x unsigned-stack) (sc-is y unsigned-reg) (sc-is r unsigned-stack) (location= x r)))) (y :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num) (:results (r :scs (unsigned-reg) :from (:argument 0) :load-if (not (and (sc-is x unsigned-stack) (sc-is y unsigned-reg) (sc-is r unsigned-stack) (location= x r))))) (:result-types unsigned-num) (:note "inline (unsigned-byte 64) arithmetic"))(define-vop (fast-signed-binop fast-safe-arith-op) (:args (x :target r :scs (signed-reg) :load-if (not (and (sc-is x signed-stack) (sc-is y signed-reg) (sc-is r signed-stack) (location= x r)))) (y :scs (signed-reg signed-stack))) (:arg-types signed-num signed-num) (:results (r :scs (signed-reg) :from (:argument 0) :load-if (not (and (sc-is x signed-stack) (sc-is y signed-reg) (sc-is r signed-stack) (location= x r))))) (:result-types signed-num) (:note "inline (signed-byte 64) arithmetic"))(define-vop (fast-fixnum-binop-c fast-safe-arith-op) (:args (x :target r :scs (any-reg control-stack))) (:info y) (:arg-types tagged-num (:constant (signed-byte 29))) (:results (r :scs (any-reg) :load-if (not (location= x r)))) (:result-types tagged-num) (:note "inline fixnum arithmetic"));; 31 not 64 because it's hard work loading 64 bit constants, and since;; sign-extension of immediates causes problems with 32.(define-vop (fast-unsigned-binop-c fast-safe-arith-op) (:args (x :target r :scs (unsigned-reg unsigned-stack))) (:info y) (:arg-types unsigned-num (:constant (unsigned-byte 31))) (:results (r :scs (unsigned-reg) :load-if (not (location= x r)))) (:result-types unsigned-num) (:note "inline (unsigned-byte 64) arithmetic"))(define-vop (fast-signed-binop-c fast-safe-arith-op) (:args (x :target r :scs (signed-reg signed-stack))) (:info y) (:arg-types signed-num (:constant (signed-byte 32))) (:results (r :scs (signed-reg) :load-if (not (location= x r)))) (:result-types signed-num) (:note "inline (signed-byte 64) arithmetic"))(macrolet ((define-binop (translate untagged-penalty op) `(progn (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM") fast-fixnum-binop) (:translate ,translate) (:generator 2 (move r x) (inst ,op r y))) (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum) fast-fixnum-binop-c) (:translate ,translate) (:generator 1 (move r x) (inst ,op r (fixnumize y)))) (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED") fast-signed-binop) (:translate ,translate) (:generator ,(1+ untagged-penalty) (move r x) (inst ,op r y))) (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed) fast-signed-binop-c) (:translate ,translate) (:generator ,untagged-penalty (move r x) (inst ,op r y))) (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED") fast-unsigned-binop) (:translate ,translate) (:generator ,(1+ untagged-penalty) (move r x) (inst ,op r y))) (define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned) fast-unsigned-binop-c) (:translate ,translate) (:generator ,untagged-penalty (move r x) (inst ,op r y)))))) ;;(define-binop + 4 add) (define-binop - 4 sub) (define-binop logand 2 and) (define-binop logior 2 or) (define-binop logxor 2 xor));;; Special handling of add on the x86; can use lea to avoid a;;; register load, otherwise it uses add.(define-vop (fast-+/fixnum=>fixnum fast-safe-arith-op) (:translate +) (:args (x :scs (any-reg) :target r :load-if (not (and (sc-is x control-stack) (sc-is y any-reg) (sc-is r control-stack) (location= x r)))) (y :scs (any-reg control-stack))) (:arg-types tagged-num tagged-num) (:results (r :scs (any-reg) :from (:argument 0) :load-if (not (and (sc-is x control-stack) (sc-is y any-reg) (sc-is r control-stack) (location= x r))))) (:result-types tagged-num) (:note "inline fixnum arithmetic") (:generator 2 (cond ((and (sc-is x any-reg) (sc-is y any-reg) (sc-is r any-reg) (not (location= x r))) (inst lea r (make-ea :qword :base x :index y :scale 1))) (t (move r x) (inst add r y)))))(define-vop (fast-+-c/fixnum=>fixnum fast-safe-arith-op) (:translate +) (:args (x :target r :scs (any-reg control-stack))) (:info y) (:arg-types tagged-num (:constant (signed-byte 29))) (:results (r :scs (any-reg) :load-if (not (location= x r)))) (:result-types tagged-num) (:note "inline fixnum arithmetic") (:generator 1 (cond ((and (sc-is x any-reg) (sc-is r any-reg) (not (location= x r))) (inst lea r (make-ea :qword :base x :disp (fixnumize y)))) (t (move r x) (inst add r (fixnumize y))))))(define-vop (fast-+/signed=>signed fast-safe-arith-op) (:translate +) (:args (x :scs (signed-reg) :target r :load-if (not (and (sc-is x signed-stack) (sc-is y signed-reg) (sc-is r signed-stack) (location= x r)))) (y :scs (signed-reg signed-stack))) (:arg-types signed-num signed-num) (:results (r :scs (signed-reg) :from (:argument 0) :load-if (not (and (sc-is x signed-stack) (sc-is y signed-reg) (location= x r))))) (:result-types signed-num) (:note "inline (signed-byte 64) arithmetic") (:generator 5 (cond ((and (sc-is x signed-reg) (sc-is y signed-reg) (sc-is r signed-reg) (not (location= x r))) (inst lea r (make-ea :qword :base x :index y :scale 1))) (t (move r x) (inst add r y)))));;;; Special logand cases: (logand signed unsigned) => unsigned(define-vop (fast-logand/signed-unsigned=>unsigned fast-logand/unsigned=>unsigned) (:args (x :target r :scs (signed-reg) :load-if (not (and (sc-is x signed-stack) (sc-is y unsigned-reg) (sc-is r unsigned-stack) (location= x r)))) (y :scs (unsigned-reg unsigned-stack))) (:arg-types signed-num unsigned-num))(define-vop (fast-logand-c/signed-unsigned=>unsigned fast-logand-c/unsigned=>unsigned) (:args (x :target r :scs (signed-reg signed-stack))) (:arg-types signed-num (:constant (unsigned-byte 31))))(define-vop (fast-logand/unsigned-signed=>unsigned fast-logand/unsigned=>unsigned) (:args (x :target r :scs (unsigned-reg) :load-if (not (and (sc-is x unsigned-stack) (sc-is y signed-reg) (sc-is r unsigned-stack) (location= x r)))) (y :scs (signed-reg signed-stack))) (:arg-types unsigned-num signed-num))(define-vop (fast-+-c/signed=>signed fast-safe-arith-op) (:translate +) (:args (x :target r :scs (signed-reg signed-stack))) (:info y) (:arg-types signed-num (:constant (signed-byte 32))) (:results (r :scs (signed-reg) :load-if (not (location= x r)))) (:result-types signed-num) (:note "inline (signed-byte 64) arithmetic") (:generator 4 (cond ((and (sc-is x signed-reg) (sc-is r signed-reg) (not (location= x r))) (inst lea r (make-ea :qword :base x :disp y))) (t (move r x) (if (= y 1) (inst inc r) (inst add r y))))))(define-vop (fast-+/unsigned=>unsigned fast-safe-arith-op) (:translate +) (:args (x :scs (unsigned-reg) :target r :load-if (not (and (sc-is x unsigned-stack) (sc-is y unsigned-reg) (sc-is r unsigned-stack) (location= x r)))) (y :scs (unsigned-reg unsigned-stack))) (:arg-types unsigned-num unsigned-num) (:results (r :scs (unsigned-reg) :from (:argument 0) :load-if (not (and (sc-is x unsigned-stack) (sc-is y unsigned-reg) (sc-is r unsigned-stack) (location= x r))))) (:result-types unsigned-num) (:note "inline (unsigned-byte 64) arithmetic") (:generator 5 (cond ((and (sc-is x unsigned-reg) (sc-is y unsigned-reg) (sc-is r unsigned-reg) (not (location= x r))) (inst lea r (make-ea :qword :base x :index y :scale 1))) (t (move r x) (inst add r y)))))(define-vop (fast-+-c/unsigned=>unsigned fast-safe-arith-op) (:translate +) (:args (x :target r :scs (unsigned-reg unsigned-stack))) (:info y) (:arg-types unsigned-num (:constant (unsigned-byte 31))) (:results (r :scs (unsigned-reg) :load-if (not (location= x r)))) (:result-types unsigned-num) (:note "inline (unsigned-byte 64) arithmetic") (:generator 4 (cond ((and (sc-is x unsigned-reg) (sc-is r unsigned-reg) (not (location= x r)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -