📄 vm.lisp
字号:
;;;; miscellaneous VM definition noise for the x86;;;; 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 32));;;; register specs(eval-when (:compile-toplevel :load-toplevel :execute) (defvar *byte-register-names* (make-array 8 :initial-element nil)) (defvar *word-register-names* (make-array 16 :initial-element nil)) (defvar *dword-register-names* (make-array 16 :initial-element nil)) (defvar *float-register-names* (make-array 8 :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. (defreg al 0 :byte) (defreg ah 1 :byte) (defreg cl 2 :byte) (defreg ch 3 :byte) (defreg dl 4 :byte) (defreg dh 5 :byte) (defreg bl 6 :byte) (defreg bh 7 :byte) (defregset *byte-regs* al ah cl ch dl dh bl bh) ;; 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) ;; floating point registers (defreg fr0 0 :float) (defreg fr1 1 :float) (defreg fr2 2 :float) (defreg fr3 3 :float) (defreg fr4 4 :float) (defreg fr5 5 :float) (defreg fr6 6 :float) (defreg fr7 7 :float) (defregset *float-regs* fr0 fr1 fr2 fr3 fr4 fr5 fr6 fr7) ;; 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* '(edx edi esi))) (defregset *register-arg-offsets* edx edi esi));;;; SB definitions;;; Despite the fact that there are only 8 different registers, we consider;;; them 16 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 words or dwords to take two. We;;; don't need to tell the difference between words and dwords, because;;; you can't put two words in a dword register.(define-storage-base registers :finite :size 16);;; jrd changed this from size 1 to size 8. It doesn't seem to make much;;; sense to use the 387's idea of a stack; 8 separate registers is easier;;; to deal with.;;; the old way:;;; (define-storage-base float-registers :finite :size 1);;; the new way:(define-storage-base float-registers :finite :size 8)(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 #!-win32 6 #!+win32 8))(!define-storage-classes ;; non-immediate constants in the constant pool (constant constant) ;; some FP constants can be generated in the i387 silicon (fp-constant immediate-constant) (immediate immediate-constant) ;; ;; the stacks ;; ;; the control stack (control-stack stack) ; may be pointers, scanned by GC ;; the non-descriptor stacks (signed-stack stack) ; (signed-byte 32) (unsigned-stack stack) ; (unsigned-byte 32) (character-stack stack) ; non-descriptor characters. (sap-stack stack) ; System area pointers. (single-stack stack) ; single-floats (double-stack stack :element-size 2) ; double-floats. #!+long-float (long-stack stack :element-size 3) ; long-floats. (complex-single-stack stack :element-size 2) ; complex-single-floats (complex-double-stack stack :element-size 4) ; complex-double-floats #!+long-float (complex-long-stack stack :element-size 6) ; complex-long-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 ;; non-descriptor registers, because of the conservative GC. ;; Therefore, we use different scs only to distinguish between ;; descriptor and non-descriptor values and to specify size. ;; immediate descriptor objects. Don't have to be seen by GC, but nothing ;; bad will happen if they are. (fixnums, characters, header values, etc). (any-reg registers :locations #.*dword-regs* :element-size 2; :reserve-locations (#.eax-offset) :constant-scs (immediate) :save-p t :alternate-scs (control-stack)) ;; pointer descriptor objects -- must be seen by GC (descriptor-reg registers :locations #.*dword-regs* :element-size 2; :reserve-locations (#.eax-offset) :constant-scs (constant immediate) :save-p t :alternate-scs (control-stack)) ;; non-descriptor characters (character-reg registers :locations #!-sb-unicode #.*byte-regs* #!+sb-unicode #.*dword-regs* #!+sb-unicode #!+sb-unicode :element-size 2 #!-sb-unicode #!-sb-unicode :reserve-locations (#.ah-offset #.al-offset) :constant-scs (immediate) :save-p t :alternate-scs (character-stack)) ;; non-descriptor SAPs (arbitrary pointers into address space) (sap-reg registers :locations #.*dword-regs* :element-size 2; :reserve-locations (#.eax-offset) :constant-scs (immediate) :save-p t :alternate-scs (sap-stack)) ;; non-descriptor (signed or unsigned) numbers (signed-reg registers :locations #.*dword-regs*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -