1.0.17.4: support for dynamic-extent structures
[sbcl.git] / src / compiler / x86 / insts.lisp
index ea56bf5..c51745c 100644 (file)
   (accum :type 'accum)
   (imm))
 
+(sb!disassem:define-instruction-format (two-bytes 16
+                                        :default-printer '(:name))
+  (op :fields (list (byte 8 0) (byte 8 8))))
+
 ;;; Same as simple, but with direction bit
 (sb!disassem:define-instruction-format (simple-dir 8 :include 'simple)
   (op :field (byte 6 2))
         (emit-mod-reg-r/m-byte segment #b11 reg (reg-tn-encoding thing)))
        (stack
         ;; Convert stack tns into an index off of EBP.
-        (let ((disp (- (* (1+ (tn-offset thing)) n-word-bytes))))
-          (cond ((< -128 disp 127)
+        (let ((disp (frame-byte-offset (tn-offset thing))))
+          (cond ((<= -128 disp 127)
                  (emit-mod-reg-r/m-byte segment #b01 reg #b101)
                  (emit-byte segment disp))
                 (t
      (emit-word segment value))
     (:dword
      (emit-dword segment value))))
+
+(defun toggle-word-width (chunk inst stream dstate)
+  (declare (ignore chunk inst stream))
+  (let ((word-width (or (sb!disassem:dstate-get-prop dstate 'word-width)
+                        +default-operand-size+)))
+    (setf (sb!disassem:dstate-get-prop dstate 'word-width)
+          (ecase word-width
+            (:word :dword)
+            (:dword :word)))))
+
+;;; This is a "prefix" instruction, which means that it modifies the
+;;; following instruction in some way without having an actual
+;;; mnemonic of its own.
+(define-instruction operand-size-prefix (segment)
+  (:printer byte ((op +operand-size-prefix-byte+))
+            nil                         ; don't actually print it
+            :control #'toggle-word-width))
 \f
 ;;;; general data transfer
 
 \f
 
 (define-instruction fs-segment-prefix (segment)
+  (:printer byte ((op #b01100100)))
   (:emitter
    (emit-byte segment #x64)))
 
+(define-instruction gs-segment-prefix (segment)
+  (:printer byte ((op #b01100101)))
+  (:emitter
+   (emit-byte segment #x65)))
+
 ;;;; flag control instructions
 
 ;;; CLC -- Clear Carry Flag.
              (t
               (error "bogus operands for TEST: ~S and ~S" this that)))))))
 
+;;; Emit the most compact form of the test immediate instruction,
+;;; using an 8 bit test when the immediate is only 8 bits and the
+;;; value is one of the four low registers (eax, ebx, ecx, edx) or the
+;;; control stack.
+(defun emit-optimized-test-inst (x y)
+  (typecase y
+    ((unsigned-byte 7)
+     (let ((offset (tn-offset x)))
+       (cond ((and (sc-is x any-reg descriptor-reg)
+                   (or (= offset eax-offset) (= offset ebx-offset)
+                       (= offset ecx-offset) (= offset edx-offset)))
+              (inst test (make-random-tn :kind :normal
+                                         :sc (sc-or-lose 'byte-reg)
+                                         :offset offset)
+                    y))
+             ((sc-is x control-stack)
+              (inst test (make-ea :byte :base ebp-tn
+                                  :disp (- (* (1+ offset) n-word-bytes)))
+                    y))
+             (t
+              (inst test x y)))))
+    (t
+     (inst test x y))))
+
 (define-instruction or (segment dst src)
   (:printer-list
    (arith-inst-printer-list #b001))
     ;; Lisp (with (DESCRIBE 'BYTE-IMM-CODE)) than to definitively deduce
     ;; from first principles whether it's defined in some way that genesis
     ;; can't grok.
-    (case #-darwin (byte-imm-code chunk dstate)
-          #+darwin (word-imm-code chunk dstate)
+    (case #!-darwin (byte-imm-code chunk dstate)
+          #!+darwin (word-imm-code chunk dstate)
       (#.error-trap
        (nt "error trap")
        (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
 
 (define-instruction break (segment code)
   (:declare (type (unsigned-byte 8) code))
-  #-darwin (:printer byte-imm ((op #b11001100)) '(:name :tab code)
+  #!-darwin (:printer byte-imm ((op #b11001100)) '(:name :tab code)
                      :control #'break-control)
-  #+darwin (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
+  #!+darwin (:printer word-imm ((op #b0000101100001111)) '(:name :tab code)
                      :control #'break-control)
   (:emitter
-   #-darwin (emit-byte segment #b11001100)
+   #!-darwin (emit-byte segment #b11001100)
    ;; On darwin, trap handling via SIGTRAP is unreliable, therefore we
    ;; throw a sigill with 0x0b0f instead and check for this in the
    ;; SIGILL handler and pass it on to the sigtrap handler if
    ;; appropriate
-   #+darwin (emit-word segment #b0000101100001111)
+   #!+darwin (emit-word segment #b0000101100001111)
    (emit-byte segment code)))
 
 (define-instruction int (segment number)
   (:emitter
    (emit-byte segment #b11011001)
    (emit-byte segment #b11101101)))
+
+;;;; Miscellany
+
+(define-instruction cpuid (segment)
+  (:printer two-bytes ((op '(#b00001111 #b10100010))))
+  (:emitter
+   (emit-byte segment #b00001111)
+   (emit-byte segment #b10100010)))
+
+(define-instruction rdtsc (segment)
+  (:printer two-bytes ((op '(#b00001111 #b00110001))))
+  (:emitter
+   (emit-byte segment #b00001111)
+   (emit-byte segment #b00110001)))