📄 move.lisp
字号:
;;;; the x86-64 VM definition of operand loading/saving and the MOVE vop;;;; 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")(defun make-byte-tn (tn) (aver (sc-is tn any-reg descriptor-reg unsigned-reg signed-reg)) (make-random-tn :kind :normal :sc (sc-or-lose 'byte-reg) :offset (tn-offset tn)))(defun make-dword-tn (tn) (aver (sc-is tn any-reg descriptor-reg character-reg unsigned-reg signed-reg)) (make-random-tn :kind :normal :sc (sc-or-lose 'dword-reg) :offset (tn-offset tn)))(defun zeroize (tn) (let ((offset (tn-offset tn))) ;; Using the 32-bit instruction accomplishes the same thing and is ;; one byte shorter. (if (<= offset edi-offset) (let ((tn (make-random-tn :kind :normal :sc (sc-or-lose 'dword-reg) :offset offset))) (inst xor tn tn)) (inst xor tn tn))))(define-move-fun (load-immediate 1) (vop x y) ((immediate) (any-reg descriptor-reg)) (let ((val (tn-value x))) (etypecase val (integer (if (zerop val) (zeroize y) (inst mov y (fixnumize val)))) (symbol (load-symbol y val)) (character (inst mov y (logior (ash (char-code val) n-widetag-bits) character-widetag))))))(define-move-fun (load-number 1) (vop x y) ((immediate) (signed-reg unsigned-reg)) (let ((val (tn-value x))) (if (zerop val) (zeroize y) (inst mov y val))))(define-move-fun (load-character 1) (vop x y) ((immediate) (character-reg)) (inst mov y (char-code (tn-value x))))(define-move-fun (load-system-area-pointer 1) (vop x y) ((immediate) (sap-reg)) (inst mov y (sap-int (tn-value x))))(define-move-fun (load-constant 5) (vop x y) ((constant) (descriptor-reg any-reg)) (inst mov y x))(define-move-fun (load-stack 5) (vop x y) ((control-stack) (any-reg descriptor-reg) (character-stack) (character-reg) (sap-stack) (sap-reg) (signed-stack) (signed-reg) (unsigned-stack) (unsigned-reg)) (inst mov y x))(define-move-fun (store-stack 5) (vop x y) ((any-reg descriptor-reg) (control-stack) (character-reg) (character-stack) (sap-reg) (sap-stack) (signed-reg) (signed-stack) (unsigned-reg) (unsigned-stack)) (inst mov y x));;;; the MOVE VOP(define-vop (move) (:args (x :scs (any-reg descriptor-reg immediate) :target y :load-if (not (location= x y)))) (:results (y :scs (any-reg descriptor-reg) :load-if (not (or (location= x y) (and (sc-is x any-reg descriptor-reg immediate) (sc-is y control-stack)))))) (:temporary (:sc unsigned-reg) temp) (:effects) (:affected) (:generator 0 (if (and (sc-is x immediate) (sc-is y any-reg descriptor-reg control-stack)) (let ((val (tn-value x))) (etypecase val (integer (if (and (zerop val) (sc-is y any-reg descriptor-reg)) (zeroize y) (move-immediate y (fixnumize val) temp))) (symbol (inst mov y (+ nil-value (static-symbol-offset val)))) (character (inst mov y (logior (ash (char-code val) n-widetag-bits) character-widetag))))) (move y x))))(define-move-vop move :move (any-reg descriptor-reg immediate) (any-reg descriptor-reg));;; Make MOVE the check VOP for T so that type check generation;;; doesn't think it is a hairy type. This also allows checking of a;;; few of the values in a continuation to fall out.(primitive-type-vop move (:check) t)(defun move-immediate (target val &optional tmp-tn) (cond ;; If target is a register, we can just mov it there directly ((and (tn-p target) (sc-is target signed-reg unsigned-reg descriptor-reg any-reg)) (inst mov target val)) ;; Likewise if the value is small enough. ((typep val '(signed-byte 31)) (inst mov target val)) ;; Otherwise go through the temporary register (tmp-tn (inst mov tmp-tn val) (inst mov target tmp-tn)) (t (error "~A is not a register, no temporary given, and immediate ~A too large" target val))));;; The MOVE-ARG VOP is used for moving descriptor values into;;; another frame for argument or known value passing.;;;;;; Note: It is not going to be possible to move a constant directly;;; to another frame, except if the destination is a register and in;;; this case the loading works out.(define-vop (move-arg) (:args (x :scs (any-reg descriptor-reg immediate) :target y :load-if (not (and (sc-is y any-reg descriptor-reg) (sc-is x control-stack)))) (fp :scs (any-reg) :load-if (not (sc-is y any-reg descriptor-reg)))) (:results (y)) (:generator 0 (sc-case y ((any-reg descriptor-reg) (if (sc-is x immediate) (let ((val (tn-value x))) (etypecase val ((integer 0 0) (zeroize y)) ((or (signed-byte 29) (unsigned-byte 29)) (inst mov y (fixnumize val))) (integer (move-immediate y (fixnumize val))) (symbol (load-symbol y val)) (character (inst mov y (logior (ash (char-code val) n-widetag-bits) character-widetag))))) (move y x))) ((control-stack) (if (sc-is x immediate) (let ((val (tn-value x))) (if (= (tn-offset fp) esp-offset) ;; C-call (etypecase val (integer (storew (fixnumize val) fp (tn-offset y))) (symbol (storew (+ nil-value (static-symbol-offset val)) fp (tn-offset y))) (character (storew (logior (ash (char-code val) n-widetag-bits) character-widetag) fp (tn-offset y)))) ;; Lisp stack (etypecase val (integer (storew (fixnumize val) fp (- (1+ (tn-offset y))))) (symbol (storew (+ nil-value (static-symbol-offset val)) fp (- (1+ (tn-offset y))))) (character (storew (logior (ash (char-code val) n-widetag-bits) character-widetag) fp (- (1+ (tn-offset y)))))))) (if (= (tn-offset fp) esp-offset) ;; C-call (storew x fp (tn-offset y)) ;; Lisp stack (storew x fp (- (1+ (tn-offset y))))))))))(define-move-vop move-arg :move-arg (any-reg descriptor-reg) (any-reg descriptor-reg));;;; ILLEGAL-MOVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -