📄 vm.lisp
字号:
;;;; miscellaneous VM definition noise 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");;; the size of an INTEGER representation of a SYSTEM-AREA-POINTER, i.e.;;; size of a native memory address(deftype sap-int () '(unsigned-byte 64));;;; register specs(eval-when (:compile-toplevel :load-toplevel :execute) (defvar *byte-register-names* (make-array 32 :initial-element nil)) (defvar *word-register-names* (make-array 16 :initial-element nil)) (defvar *dword-register-names* (make-array 16 :initial-element nil)) (defvar *qword-register-names* (make-array 32 :initial-element nil)) (defvar *float-register-names* (make-array 16 :initial-element nil)))(macrolet ((defreg (name offset size) (let ((offset-sym (symbolicate name "-OFFSET")) (names-vector (symbolicate "*" size "-REGISTER-NAMES*"))) `(progn (eval-when (:compile-toplevel :load-toplevel :execute) ;; EVAL-WHEN is necessary because stuff like #.EAX-OFFSET ;; (in the same file) depends on compile-time evaluation ;; of the DEFCONSTANT. -- AL 20010224 (def!constant ,offset-sym ,offset)) (setf (svref ,names-vector ,offset-sym) ,(symbol-name name))))) ;; FIXME: It looks to me as though DEFREGSET should also ;; define the related *FOO-REGISTER-NAMES* variable. (defregset (name &rest regs) `(eval-when (:compile-toplevel :load-toplevel :execute) (defparameter ,name (list ,@(mapcar (lambda (name) (symbolicate name "-OFFSET")) regs)))))) ;; byte registers ;; ;; Note: the encoding here is different than that used by the chip. ;; We use this encoding so that the compiler thinks that AX (and ;; EAX) overlap AL and AH instead of AL and CL. ;; ;; High-byte are registers disabled on AMD64, since they can't be ;; encoded for an op that has a REX-prefix and we don't want to ;; add special cases into the code generation. The overlap doesn't ;; therefore exist anymore, but the numbering hasn't been changed ;; to reflect this. (defreg al 0 :byte) (defreg cl 2 :byte) (defreg dl 4 :byte) (defreg bl 6 :byte) (defreg sil 12 :byte) (defreg dil 14 :byte) (defreg r8b 16 :byte) (defreg r9b 18 :byte) (defreg r10b 20 :byte) (defreg r11b 22 :byte) (defreg r12b 24 :byte) (defreg r13b 26 :byte) (defreg r14b 28 :byte) (defreg r15b 30 :byte) (defregset *byte-regs* al cl dl bl sil dil r8b r9b r10b #+nil r11b #+nil r12b r13b r14b r15b) ;; word registers (defreg ax 0 :word) (defreg cx 2 :word) (defreg dx 4 :word) (defreg bx 6 :word) (defreg sp 8 :word) (defreg bp 10 :word) (defreg si 12 :word) (defreg di 14 :word) (defregset *word-regs* ax cx dx bx si di) ;; double word registers (defreg eax 0 :dword) (defreg ecx 2 :dword) (defreg edx 4 :dword) (defreg ebx 6 :dword) (defreg esp 8 :dword) (defreg ebp 10 :dword) (defreg esi 12 :dword) (defreg edi 14 :dword) (defregset *dword-regs* eax ecx edx ebx esi edi) ;; quadword registers (defreg rax 0 :qword) (defreg rcx 2 :qword) (defreg rdx 4 :qword) (defreg rbx 6 :qword) (defreg rsp 8 :qword) (defreg rbp 10 :qword) (defreg rsi 12 :qword) (defreg rdi 14 :qword) (defreg r8 16 :qword) (defreg r9 18 :qword) (defreg r10 20 :qword) (defreg r11 22 :qword) (defreg r12 24 :qword) (defreg r13 26 :qword) (defreg r14 28 :qword) (defreg r15 30 :qword) ;; for no good reason at the time, r12 and r13 were missed from the ;; list of qword registers. However ;; <jsnell> r13 is already used as temporary [#lisp irc 2005/01/30] ;; and we're now going to use r12 for the struct thread* ;; ;; Except that now we use r11 instead of r13 as the temporary, ;; since it's got a more compact encoding than r13, and experimentally ;; the temporary gets used more than the other registers that are never ;; wired. -- JES, 2005-11-02 (defregset *qword-regs* rax rcx rdx rbx rsi rdi r8 r9 r10 #+nil r11 #+nil r12 r13 r14 r15) ;; floating point registers (defreg float0 0 :float) (defreg float1 1 :float) (defreg float2 2 :float) (defreg float3 3 :float) (defreg float4 4 :float) (defreg float5 5 :float) (defreg float6 6 :float) (defreg float7 7 :float) (defreg float8 8 :float) (defreg float9 9 :float) (defreg float10 10 :float) (defreg float11 11 :float) (defreg float12 12 :float) (defreg float13 13 :float) (defreg float14 14 :float) (defreg float15 15 :float) (defregset *float-regs* float0 float1 float2 float3 float4 float5 float6 float7 float8 float9 float10 float11 float12 float13 float14 float15) ;; registers used to pass arguments ;; ;; the number of arguments/return values passed in registers (def!constant register-arg-count 3) ;; names and offsets for registers used to pass arguments (eval-when (:compile-toplevel :load-toplevel :execute) (defparameter *register-arg-names* '(rdx rdi rsi))) (defregset *register-arg-offsets* rdx rdi rsi) (defregset *c-call-register-arg-offsets* rdi rsi rdx rcx r8 r9));;;; SB definitions;;; There are 16 registers really, but we consider them 32 in order to;;; describe the overlap of byte registers. The only thing we need to;;; represent is what registers overlap. Therefore, we consider bytes;;; to take one unit, and [dq]?words to take two. We don't need to;;; tell the difference between [dq]?words, because you can't put two;;; words in a dword register.(define-storage-base registers :finite :size 32)(define-storage-base float-registers :finite :size 16)(define-storage-base stack :unbounded :size 8)(define-storage-base constant :non-packed)(define-storage-base immediate-constant :non-packed)(define-storage-base noise :unbounded :size 2);;;; SC definitions;;; a handy macro so we don't have to keep changing all the numbers whenever;;; we insert a new storage class;;;(defmacro !define-storage-classes (&rest classes) (collect ((forms)) (let ((index 0)) (dolist (class classes) (let* ((sc-name (car class)) (constant-name (symbolicate sc-name "-SC-NUMBER"))) (forms `(define-storage-class ,sc-name ,index ,@(cdr class))) (forms `(def!constant ,constant-name ,index)) (incf index)))) `(progn ,@(forms))));;; The DEFINE-STORAGE-CLASS call for CATCH-BLOCK refers to the size;;; of CATCH-BLOCK. The size of CATCH-BLOCK isn't calculated until;;; later in the build process, and the calculation is entangled with;;; code which has lots of predependencies, including dependencies on;;; the prior call of DEFINE-STORAGE-CLASS. The proper way to;;; unscramble this would be to untangle the code, so that the code;;; which calculates the size of CATCH-BLOCK can be separated from the;;; other lots-of-dependencies code, so that the code which calculates;;; the size of CATCH-BLOCK can be executed early, so that this value;;; is known properly at this point in compilation. However, that;;; would be a lot of editing of code that I (WHN 19990131) can't test;;; until the project is complete. So instead, I set the correct value;;; by hand here (a sort of nondeterministic guess of the right;;; answer:-) and add an assertion later, after the value is;;; calculated, that the original guess was correct.;;;;;; (What a KLUDGE! Anyone who wants to come in and clean up this mess;;; has my gratitude.) (FIXME: Maybe this should be me..)(eval-when (:compile-toplevel :load-toplevel :execute) (def!constant kludge-nondeterministic-catch-block-size 6))(!define-storage-classes ;; non-immediate constants in the constant pool (constant constant) (fp-single-zero immediate-constant) (fp-double-zero immediate-constant) (immediate immediate-constant) ;; ;; the stacks ;; ;; the control stack (control-stack stack) ; may be pointers, scanned by GC ;; the non-descriptor stacks ;; XXX alpha backend has :element-size 2 :alignment 2 in these entries (signed-stack stack) ; (signed-byte 64) (unsigned-stack stack) ; (unsigned-byte 64) (character-stack stack) ; non-descriptor characters. (sap-stack stack) ; System area pointers. (single-stack stack) ; single-floats (double-stack stack) (complex-single-stack stack :element-size 2) ; complex-single-floats (complex-double-stack stack :element-size 2) ; complex-double-floats ;; ;; magic SCs ;; (ignore-me noise) ;; ;; things that can go in the integer registers ;; ;; On the X86, we don't have to distinguish between descriptor and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -