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

📄 insts.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 5 页
字号:
;;;; that part of the description of the x86-64 instruction set;;;; which can live on the cross-compilation host;;;; 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");;; FIXME: SB!DISASSEM: prefixes are used so widely in this file that;;; I wonder whether the separation of the disassembler from the;;; virtual machine is valid or adds value.;;; Note: In CMU CL, this used to be a call to SET-DISASSEM-PARAMS.(setf sb!disassem:*disassem-inst-alignment-bytes* 1);;; This type is used mostly in disassembly and represents legacy;;; registers only. R8-R15 are handled separately.(deftype reg () '(unsigned-byte 3));;; This includes legacy registers and R8-R15.(deftype full-reg () '(unsigned-byte 4));;; The XMM registers XMM0 - XMM15.(deftype xmmreg () '(unsigned-byte 4));;; Default word size for the chip: if the operand size /= :dword;;; we need to output #x66 (or REX) prefix(def!constant +default-operand-size+ :dword);;; The default address size for the chip. It could be overwritten;;; to :dword with a #x67 prefix, but this is never needed by SBCL;;; and thus not supported by this assembler/disassembler.(def!constant +default-address-size+ :qword)(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)(defun offset-next (value dstate)  (declare (type integer value)           (type sb!disassem:disassem-state dstate))  (+ (sb!disassem:dstate-next-addr dstate) value))(defparameter *byte-reg-names*  #(al cl dl bl spl bpl sil dil r8b r9b r10b r11b r12b r13b r14b r15b))(defparameter *high-byte-reg-names*  #(ah ch dh bh))(defparameter *word-reg-names*  #(ax cx dx bx sp bp si di r8w r9w r10w r11w r12w r13w r14w r15w))(defparameter *dword-reg-names*  #(eax ecx edx ebx esp ebp esi edi r8d r9d r10d r11d r12d r13d r14d r15d))(defparameter *qword-reg-names*  #(rax rcx rdx rbx rsp rbp rsi rdi r8 r9 r10 r11 r12 r13 r14 r15));;; The printers for registers, memory references and immediates need to;;; take into account the width bit in the instruction, whether a #x66;;; or a REX prefix was issued, and the contents of the REX prefix.;;; This is implemented using prefilters to put flags into the slot;;; INST-PROPERTIES of the DSTATE.  These flags are the following;;; symbols:;;;;;; OPERAND-SIZE-8   The width bit was zero;;; OPERAND-SIZE-16  The "operand size override" prefix (#x66) was found;;; REX              A REX prefix was found;;; REX-W            A REX prefix with the "operand width" bit set was;;;                  found;;; REX-R            A REX prefix with the "register" bit set was found;;; REX-X            A REX prefix with the "index" bit set was found;;; REX-B            A REX prefix with the "base" bit set was found;;; Return the operand size depending on the prefixes and width bit as;;; stored in DSTATE.(defun inst-operand-size (dstate)  (declare (type sb!disassem:disassem-state dstate))  (cond ((sb!disassem:dstate-get-inst-prop dstate 'operand-size-8)         :byte)        ((sb!disassem:dstate-get-inst-prop dstate 'rex-w)         :qword)        ((sb!disassem:dstate-get-inst-prop dstate 'operand-size-16)         :word)        (t         +default-operand-size+)));;; The same as INST-OPERAND-SIZE, but for those instructions (e.g.;;; PUSH, JMP) that have a default operand size of :qword. It can only;;; be overwritten to :word.(defun inst-operand-size-default-qword (dstate)  (declare (type sb!disassem:disassem-state dstate))  (if (sb!disassem:dstate-get-inst-prop dstate 'operand-size-16)      :word      :qword));;; Print to STREAM the name of the general-purpose register encoded by;;; VALUE and of size WIDTH. For robustness, the high byte registers;;; (AH, BH, CH, DH) are correctly detected, too, although the compiler;;; does not use them.(defun print-reg-with-width (value width stream dstate)  (declare (type full-reg value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (princ (if (and (eq width :byte)                  (<= 4 value 7)                  (not (sb!disassem:dstate-get-inst-prop dstate 'rex)))             (aref *high-byte-reg-names* (- value 4))             (aref (ecase width                     (:byte *byte-reg-names*)                     (:word *word-reg-names*)                     (:dword *dword-reg-names*)                     (:qword *qword-reg-names*))                   value))         stream)  ;; XXX plus should do some source-var notes  )(defun print-reg (value stream dstate)  (declare (type full-reg value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg-with-width value                        (inst-operand-size dstate)                        stream                        dstate))(defun print-reg-default-qword (value stream dstate)  (declare (type full-reg value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg-with-width value                        (inst-operand-size-default-qword dstate)                        stream                        dstate))(defun print-byte-reg (value stream dstate)  (declare (type full-reg value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg-with-width value :byte stream dstate))(defun print-addr-reg (value stream dstate)  (declare (type full-reg value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg-with-width value +default-address-size+ stream dstate));;; Print a register or a memory reference of the given WIDTH.;;; If SIZED-P is true, add an explicit size indicator for memory;;; references.(defun print-reg/mem-with-width (value width sized-p stream dstate)  (declare (type (or list full-reg) value)           (type (member :byte :word :dword :qword) width)           (type boolean sized-p)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (if (typep value 'full-reg)      (print-reg-with-width value width stream dstate)    (print-mem-access value (and sized-p width) stream dstate)));;; Print a register or a memory reference. The width is determined by;;; calling INST-OPERAND-SIZE.(defun print-reg/mem (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width   value (inst-operand-size dstate) nil stream dstate));; Same as print-reg/mem, but prints an explicit size indicator for;; memory references.(defun print-sized-reg/mem (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width   value (inst-operand-size dstate) t stream dstate));;; Same as print-sized-reg/mem, but with a default operand size of;;; :qword.(defun print-sized-reg/mem-default-qword (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width   value (inst-operand-size-default-qword dstate) t stream dstate))(defun print-sized-byte-reg/mem (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width value :byte t stream dstate))(defun print-sized-word-reg/mem (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width value :word t stream dstate))(defun print-sized-dword-reg/mem (value stream dstate)  (declare (type (or list full-reg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (print-reg/mem-with-width value :dword t stream dstate))(defun print-label (value stream dstate)  (declare (ignore dstate))  (sb!disassem:princ16 value stream))(defun print-xmmreg (value stream dstate)  (declare (type xmmreg value)           (type stream stream)           (ignore dstate))  (format stream "XMM~d" value))(defun print-xmmreg/mem (value stream dstate)  (declare (type (or list xmmreg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (if (typep value 'xmmreg)      (print-xmmreg value stream dstate)    (print-mem-access value nil stream dstate)));; Same as print-xmmreg/mem, but prints an explicit size indicator for;; memory references.(defun print-sized-xmmreg/mem (value stream dstate)  (declare (type (or list xmmreg) value)           (type stream stream)           (type sb!disassem:disassem-state dstate))  (if (typep value 'xmmreg)      (print-xmmreg value stream dstate)    (print-mem-access value (inst-operand-size dstate) stream dstate)));;; This prefilter is used solely for its side effects, namely to put;;; the bits found in the REX prefix into the DSTATE for use by other;;; prefilters and by printers.(defun prefilter-wrxb (value dstate)  (declare (type (unsigned-byte 4) value)           (type sb!disassem:disassem-state dstate))  (sb!disassem:dstate-put-inst-prop dstate 'rex)  (when (plusp (logand value #b1000))    (sb!disassem:dstate-put-inst-prop dstate 'rex-w))  (when (plusp (logand value #b0100))    (sb!disassem:dstate-put-inst-prop dstate 'rex-r))  (when (plusp (logand value #b0010))    (sb!disassem:dstate-put-inst-prop dstate 'rex-x))  (when (plusp (logand value #b0001))    (sb!disassem:dstate-put-inst-prop dstate 'rex-b))  value);;; This prefilter is used solely for its side effect, namely to put;;; the property OPERAND-SIZE-8 into the DSTATE if VALUE is 0.(defun prefilter-width (value dstate)  (declare (type bit value)           (type sb!disassem:disassem-state dstate))  (when (zerop value)    (sb!disassem:dstate-put-inst-prop dstate 'operand-size-8))  value);;; This prefilter is used solely for its side effect, namely to put;;; the property OPERAND-SIZE-16 into the DSTATE.(defun prefilter-x66 (value dstate)  (declare (type (eql #x66) value)           (ignore value)           (type sb!disassem:disassem-state dstate))  (sb!disassem:dstate-put-inst-prop dstate 'operand-size-16));;; A register field that can be extended by REX.R.(defun prefilter-reg-r (value dstate)  (declare (type reg value)           (type sb!disassem:disassem-state dstate))  (if (sb!disassem::dstate-get-inst-prop dstate 'rex-r)      (+ value 8)      value));;; A register field that can be extended by REX.B.(defun prefilter-reg-b (value dstate)  (declare (type reg value)           (type sb!disassem:disassem-state dstate))  (if (sb!disassem::dstate-get-inst-prop dstate 'rex-b)      (+ value 8)      value));;; Returns either an integer, meaning a register, or a list of;;; (BASE-REG OFFSET INDEX-REG INDEX-SCALE), where any component;;; may be missing or nil to indicate that it's not used or has the;;; obvious default value (e.g., 1 for the index-scale). VALUE is a list;;; of the mod and r/m field of the ModRM byte of the instruction.;;; Depending on VALUE a SIB byte and/or an offset may be read. The;;; REX.B bit from DSTATE is used to extend the sole register or the;;; BASE-REG to a full register, the REX.X bit does the same for the;;; INDEX-REG.(defun prefilter-reg/mem (value dstate)  (declare (type list value)           (type sb!disassem:disassem-state dstate))  (let ((mod (first value))        (r/m (second value)))    (declare (type (unsigned-byte 2) mod)             (type (unsigned-byte 3) r/m))    (let ((full-reg (if (sb!disassem:dstate-get-inst-prop dstate 'rex-b)                        (+ r/m 8)                        r/m)))      (declare (type full-reg full-reg))      (cond ((= mod #b11)             ;; registers             full-reg)            ((= r/m #b100)             ;; sib byte             (let ((sib (sb!disassem:read-suffix 8 dstate)))               (declare (type (unsigned-byte 8) sib))               (let ((base-reg (ldb (byte 3 0) sib))                     (index-reg (ldb (byte 3 3) sib))                     (index-scale (ldb (byte 2 6) sib)))                 (declare (type (unsigned-byte 3) base-reg index-reg)                          (type (unsigned-byte 2) index-scale))                 (let* ((offset                         (case mod                               (#b00                                (if (= base-reg #b101)                                    (sb!disassem:read-signed-suffix 32 dstate)

⌨️ 快捷键说明

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