1 ;;;; that part of the description of the x86 instruction set (for
2 ;;;; 80386 and above) which can live on the cross-compilation host
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
14 ;;; FIXME: SB!DISASSEM: prefixes are used so widely in this file that
15 ;;; I wonder whether the separation of the disassembler from the
16 ;;; virtual machine is valid or adds value.
18 ;;; Note: In CMU CL, this used to be a call to SET-DISASSEM-PARAMS.
19 (setf sb!disassem:*disassem-inst-alignment-bytes* 1)
21 ;;; this type is used mostly in disassembly and represents legacy
22 ;;; registers only. r8-15 are handled separately
23 (deftype reg () '(unsigned-byte 3))
25 ;;; default word size for the chip: if the operand size !=:dword
26 ;;; we need to output #x66 (or REX) prefix
27 (def!constant +default-operand-size+ :dword)
29 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
31 (defun offset-next (value dstate)
32 (declare (type integer value)
33 (type sb!disassem:disassem-state dstate))
34 (+ (sb!disassem:dstate-next-addr dstate) value))
36 (defparameter *default-address-size*
37 ;; Again, this is the chip default, not the SBCL backend preference
38 ;; which must be set with prefixes if it's different. It's :dword;
39 ;; this is not negotiable
42 (defparameter *byte-reg-names*
43 #(al cl dl bl ah ch dh bh))
44 (defparameter *word-reg-names*
45 #(ax cx dx bx sp bp si di))
46 (defparameter *dword-reg-names*
47 #(eax ecx edx ebx esp ebp esi edi))
48 (defparameter *qword-reg-names*
49 #(rax rcx rdx rbx rsp rbp rsi rdi r8 r9 r10 r11 r12 r13 r14 r15))
51 (defun print-reg-with-width (value width stream dstate)
52 (declare (ignore dstate))
53 (princ (aref (ecase width
54 (:byte *byte-reg-names*)
55 (:word *word-reg-names*)
56 (:dword *dword-reg-names*)
57 (:qword *qword-reg-names*))
60 ;; XXX plus should do some source-var notes
63 (defun print-reg (value stream dstate)
64 (declare (type reg value)
66 (type sb!disassem:disassem-state dstate))
67 (print-reg-with-width value
68 (sb!disassem:dstate-get-prop dstate 'width)
72 (defun print-word-reg (value stream dstate)
73 (declare (type reg value)
75 (type sb!disassem:disassem-state dstate))
76 (print-reg-with-width value
77 (or (sb!disassem:dstate-get-prop dstate 'word-width)
78 +default-operand-size+)
82 (defun print-byte-reg (value stream dstate)
83 (declare (type reg value)
85 (type sb!disassem:disassem-state dstate))
86 (print-reg-with-width value :byte stream dstate))
88 (defun print-addr-reg (value stream dstate)
89 (declare (type reg value)
91 (type sb!disassem:disassem-state dstate))
92 (print-reg-with-width value *default-address-size* stream dstate))
94 (defun print-reg/mem (value stream dstate)
95 (declare (type (or list reg) value)
97 (type sb!disassem:disassem-state dstate))
98 (if (typep value 'reg)
99 (print-reg value stream dstate)
100 (print-mem-access value stream nil dstate)))
102 ;; Same as print-reg/mem, but prints an explicit size indicator for
103 ;; memory references.
104 (defun print-sized-reg/mem (value stream dstate)
105 (declare (type (or list reg) value)
107 (type sb!disassem:disassem-state dstate))
108 (if (typep value 'reg)
109 (print-reg value stream dstate)
110 (print-mem-access value stream t dstate)))
112 (defun print-byte-reg/mem (value stream dstate)
113 (declare (type (or list reg) value)
115 (type sb!disassem:disassem-state dstate))
116 (if (typep value 'reg)
117 (print-byte-reg value stream dstate)
118 (print-mem-access value stream t dstate)))
120 (defun print-word-reg/mem (value stream dstate)
121 (declare (type (or list reg) value)
123 (type sb!disassem:disassem-state dstate))
124 (if (typep value 'reg)
125 (print-word-reg value stream dstate)
126 (print-mem-access value stream nil dstate)))
128 (defun print-label (value stream dstate)
129 (declare (ignore dstate))
130 (sb!disassem:princ16 value stream))
132 ;;; Returns either an integer, meaning a register, or a list of
133 ;;; (BASE-REG OFFSET INDEX-REG INDEX-SCALE), where any component
134 ;;; may be missing or nil to indicate that it's not used or has the
135 ;;; obvious default value (e.g., 1 for the index-scale).
136 (defun prefilter-reg/mem (value dstate)
137 (declare (type list value)
138 (type sb!disassem:disassem-state dstate))
139 (let ((mod (car value))
141 (declare (type (unsigned-byte 2) mod)
142 (type (unsigned-byte 3) r/m))
148 (let ((sib (sb!disassem:read-suffix 8 dstate)))
149 (declare (type (unsigned-byte 8) sib))
150 (let ((base-reg (ldb (byte 3 0) sib))
151 (index-reg (ldb (byte 3 3) sib))
152 (index-scale (ldb (byte 2 6) sib)))
153 (declare (type (unsigned-byte 3) base-reg index-reg)
154 (type (unsigned-byte 2) index-scale))
158 (if (= base-reg #b101)
159 (sb!disassem:read-signed-suffix 32 dstate)
162 (sb!disassem:read-signed-suffix 8 dstate))
164 (sb!disassem:read-signed-suffix 32 dstate)))))
165 (list (if (and (= mod #b00) (= base-reg #b101)) nil base-reg)
167 (if (= index-reg #b100) nil index-reg)
168 (ash 1 index-scale))))))
169 ((and (= mod #b00) (= r/m #b101))
170 (list nil (sb!disassem:read-signed-suffix 32 dstate)) )
174 (list r/m (sb!disassem:read-signed-suffix 8 dstate)))
176 (list r/m (sb!disassem:read-signed-suffix 32 dstate))))))
179 ;;; This is a sort of bogus prefilter that just stores the info globally for
180 ;;; other people to use; it probably never gets printed.
181 (defun prefilter-width (value dstate)
182 (setf (sb!disassem:dstate-get-prop dstate 'width)
186 ;; set by a prefix instruction
187 (or (sb!disassem:dstate-get-prop dstate 'word-width)
188 +default-operand-size+)))
189 (when (not (eql word-width +default-operand-size+))
191 (setf (sb!disassem:dstate-get-prop dstate 'word-width)
192 +default-operand-size+))
195 (defun read-address (value dstate)
196 (declare (ignore value)) ; always nil anyway
197 (sb!disassem:read-suffix (width-bits *default-address-size*) dstate))
199 (defun width-bits (width)
209 ;;;; disassembler argument types
211 (sb!disassem:define-arg-type displacement
213 :use-label #'offset-next
214 :printer (lambda (value stream dstate)
215 (sb!disassem:maybe-note-assembler-routine value nil dstate)
216 (print-label value stream dstate)))
218 (sb!disassem:define-arg-type accum
219 :printer (lambda (value stream dstate)
220 (declare (ignore value)
222 (type sb!disassem:disassem-state dstate))
223 (print-reg 0 stream dstate)))
225 (sb!disassem:define-arg-type word-accum
226 :printer (lambda (value stream dstate)
227 (declare (ignore value)
229 (type sb!disassem:disassem-state dstate))
230 (print-word-reg 0 stream dstate)))
232 (sb!disassem:define-arg-type reg
233 :printer #'print-reg)
235 (sb!disassem:define-arg-type addr-reg
236 :printer #'print-addr-reg)
238 (sb!disassem:define-arg-type word-reg
239 :printer #'print-word-reg)
241 (sb!disassem:define-arg-type imm-addr
242 :prefilter #'read-address
243 :printer #'print-label)
245 (sb!disassem:define-arg-type imm-data
246 :prefilter (lambda (value dstate)
247 (declare (ignore value)) ; always nil anyway
248 (sb!disassem:read-suffix
249 (width-bits (sb!disassem:dstate-get-prop dstate 'width))
252 (sb!disassem:define-arg-type signed-imm-data
253 :prefilter (lambda (value dstate)
254 (declare (ignore value)) ; always nil anyway
255 (let ((width (sb!disassem:dstate-get-prop dstate 'width)))
256 (sb!disassem:read-signed-suffix (width-bits width) dstate))))
258 (sb!disassem:define-arg-type signed-imm-byte
259 :prefilter (lambda (value dstate)
260 (declare (ignore value)) ; always nil anyway
261 (sb!disassem:read-signed-suffix 8 dstate)))
263 (sb!disassem:define-arg-type signed-imm-dword
264 :prefilter (lambda (value dstate)
265 (declare (ignore value)) ; always nil anyway
266 (sb!disassem:read-signed-suffix 32 dstate)))
268 (sb!disassem:define-arg-type imm-word
269 :prefilter (lambda (value dstate)
270 (declare (ignore value)) ; always nil anyway
272 (or (sb!disassem:dstate-get-prop dstate 'word-width)
273 +default-operand-size+)))
274 (sb!disassem:read-suffix (width-bits width) dstate))))
276 ;;; needed for the ret imm16 instruction
277 (sb!disassem:define-arg-type imm-word-16
278 :prefilter (lambda (value dstate)
279 (declare (ignore value)) ; always nil anyway
280 (sb!disassem:read-suffix 16 dstate)))
282 (sb!disassem:define-arg-type reg/mem
283 :prefilter #'prefilter-reg/mem
284 :printer #'print-reg/mem)
285 (sb!disassem:define-arg-type sized-reg/mem
286 ;; Same as reg/mem, but prints an explicit size indicator for
287 ;; memory references.
288 :prefilter #'prefilter-reg/mem
289 :printer #'print-sized-reg/mem)
290 (sb!disassem:define-arg-type byte-reg/mem
291 :prefilter #'prefilter-reg/mem
292 :printer #'print-byte-reg/mem)
293 (sb!disassem:define-arg-type word-reg/mem
294 :prefilter #'prefilter-reg/mem
295 :printer #'print-word-reg/mem)
298 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
299 (defun print-fp-reg (value stream dstate)
300 (declare (ignore dstate))
301 (format stream "FR~D" value))
302 (defun prefilter-fp-reg (value dstate)
304 (declare (ignore dstate))
307 (sb!disassem:define-arg-type fp-reg
308 :prefilter #'prefilter-fp-reg
309 :printer #'print-fp-reg)
311 (sb!disassem:define-arg-type width
312 :prefilter #'prefilter-width
313 :printer (lambda (value stream dstate)
316 (and (numberp value) (zerop value))) ; zzz jrd
319 ;; set by a prefix instruction
320 (or (sb!disassem:dstate-get-prop dstate 'word-width)
321 +default-operand-size+)))
322 (princ (schar (symbol-name word-width) 0) stream)))))
324 (eval-when (:compile-toplevel :load-toplevel :execute)
325 (defparameter *conditions*
328 (:b . 2) (:nae . 2) (:c . 2)
329 (:nb . 3) (:ae . 3) (:nc . 3)
330 (:eq . 4) (:e . 4) (:z . 4)
337 (:np . 11) (:po . 11)
338 (:l . 12) (:nge . 12)
339 (:nl . 13) (:ge . 13)
340 (:le . 14) (:ng . 14)
341 (:nle . 15) (:g . 15)))
342 (defparameter *condition-name-vec*
343 (let ((vec (make-array 16 :initial-element nil)))
344 (dolist (cond *conditions*)
345 (when (null (aref vec (cdr cond)))
346 (setf (aref vec (cdr cond)) (car cond))))
350 ;;; Set assembler parameters. (In CMU CL, this was done with
351 ;;; a call to a macro DEF-ASSEMBLER-PARAMS.)
352 (eval-when (:compile-toplevel :load-toplevel :execute)
353 (setf sb!assem:*assem-scheduler-p* nil))
355 (sb!disassem:define-arg-type condition-code
356 :printer *condition-name-vec*)
358 (defun conditional-opcode (condition)
359 (cdr (assoc condition *conditions* :test #'eq)))
361 ;;;; disassembler instruction formats
363 (eval-when (:compile-toplevel :execute)
364 (defun swap-if (direction field1 separator field2)
365 `(:if (,direction :constant 0)
366 (,field1 ,separator ,field2)
367 (,field2 ,separator ,field1))))
369 (sb!disassem:define-instruction-format (byte 8 :default-printer '(:name))
370 (op :field (byte 8 0))
375 (sb!disassem:define-instruction-format (simple 8)
376 (op :field (byte 7 1))
377 (width :field (byte 1 0) :type 'width)
382 ;;; Same as simple, but with direction bit
383 (sb!disassem:define-instruction-format (simple-dir 8 :include 'simple)
384 (op :field (byte 6 2))
385 (dir :field (byte 1 1)))
387 ;;; Same as simple, but with the immediate value occurring by default,
388 ;;; and with an appropiate printer.
389 (sb!disassem:define-instruction-format (accum-imm 8
391 :default-printer '(:name
392 :tab accum ", " imm))
393 (imm :type 'imm-data))
395 (sb!disassem:define-instruction-format (reg-no-width 8
396 :default-printer '(:name :tab reg))
397 (op :field (byte 5 3))
398 (reg :field (byte 3 0) :type 'word-reg)
400 (accum :type 'word-accum)
403 ;;; adds a width field to reg-no-width
404 (sb!disassem:define-instruction-format (reg 8
405 :default-printer '(:name :tab reg))
406 (op :field (byte 4 4))
407 (width :field (byte 1 3) :type 'width)
408 (reg :field (byte 3 0) :type 'reg)
414 ;;; Same as reg, but with direction bit
415 (sb!disassem:define-instruction-format (reg-dir 8 :include 'reg)
416 (op :field (byte 3 5))
417 (dir :field (byte 1 4)))
419 (sb!disassem:define-instruction-format (two-bytes 16
420 :default-printer '(:name))
421 (op :fields (list (byte 8 0) (byte 8 8))))
423 (sb!disassem:define-instruction-format (reg-reg/mem 16
425 `(:name :tab reg ", " reg/mem))
426 (op :field (byte 7 1))
427 (width :field (byte 1 0) :type 'width)
428 (reg/mem :fields (list (byte 2 14) (byte 3 8))
430 (reg :field (byte 3 11) :type 'reg)
434 ;;; same as reg-reg/mem, but with direction bit
435 (sb!disassem:define-instruction-format (reg-reg/mem-dir 16
436 :include 'reg-reg/mem
440 ,(swap-if 'dir 'reg/mem ", " 'reg)))
441 (op :field (byte 6 2))
442 (dir :field (byte 1 1)))
444 ;;; Same as reg-rem/mem, but uses the reg field as a second op code.
445 (sb!disassem:define-instruction-format (reg/mem 16
446 :default-printer '(:name :tab reg/mem))
447 (op :fields (list (byte 7 1) (byte 3 11)))
448 (width :field (byte 1 0) :type 'width)
449 (reg/mem :fields (list (byte 2 14) (byte 3 8))
450 :type 'sized-reg/mem)
454 ;;; Same as reg/mem, but with the immediate value occurring by default,
455 ;;; and with an appropiate printer.
456 (sb!disassem:define-instruction-format (reg/mem-imm 16
459 '(:name :tab reg/mem ", " imm))
460 (reg/mem :type 'sized-reg/mem)
461 (imm :type 'imm-data))
463 ;;; Same as reg/mem, but with using the accumulator in the default printer
464 (sb!disassem:define-instruction-format
466 :include 'reg/mem :default-printer '(:name :tab accum ", " reg/mem))
467 (reg/mem :type 'reg/mem) ; don't need a size
468 (accum :type 'accum))
470 ;;; Same as reg-reg/mem, but with a prefix of #b00001111
471 (sb!disassem:define-instruction-format (ext-reg-reg/mem 24
473 `(:name :tab reg ", " reg/mem))
474 (prefix :field (byte 8 0) :value #b00001111)
475 (op :field (byte 7 9))
476 (width :field (byte 1 8) :type 'width)
477 (reg/mem :fields (list (byte 2 22) (byte 3 16))
479 (reg :field (byte 3 19) :type 'reg)
483 ;;; reg-no-width with #x0f prefix
484 (sb!disassem:define-instruction-format (ext-reg-no-width 16
485 :default-printer '(:name :tab reg))
486 (prefix :field (byte 8 0) :value #b00001111)
487 (op :field (byte 5 11))
488 (reg :field (byte 3 8) :type 'word-reg))
490 ;;; Same as reg/mem, but with a prefix of #b00001111
491 (sb!disassem:define-instruction-format (ext-reg/mem 24
492 :default-printer '(:name :tab reg/mem))
493 (prefix :field (byte 8 0) :value #b00001111)
494 (op :fields (list (byte 7 9) (byte 3 19)))
495 (width :field (byte 1 8) :type 'width)
496 (reg/mem :fields (list (byte 2 22) (byte 3 16))
497 :type 'sized-reg/mem)
501 (sb!disassem:define-instruction-format (ext-reg/mem-imm 24
502 :include 'ext-reg/mem
504 '(:name :tab reg/mem ", " imm))
505 (imm :type 'imm-data))
507 ;;;; This section was added by jrd, for fp instructions.
509 ;;; regular fp inst to/from registers/memory
510 (sb!disassem:define-instruction-format (floating-point 16
512 `(:name :tab reg/mem))
513 (prefix :field (byte 5 3) :value #b11011)
514 (op :fields (list (byte 3 0) (byte 3 11)))
515 (reg/mem :fields (list (byte 2 14) (byte 3 8)) :type 'reg/mem))
517 ;;; fp insn to/from fp reg
518 (sb!disassem:define-instruction-format (floating-point-fp 16
519 :default-printer `(:name :tab fp-reg))
520 (prefix :field (byte 5 3) :value #b11011)
521 (suffix :field (byte 2 14) :value #b11)
522 (op :fields (list (byte 3 0) (byte 3 11)))
523 (fp-reg :field (byte 3 8) :type 'fp-reg))
525 ;;; fp insn to/from fp reg, with the reversed source/destination flag.
526 (sb!disassem:define-instruction-format
527 (floating-point-fp-d 16
528 :default-printer `(:name :tab ,(swap-if 'd "ST0" ", " 'fp-reg)))
529 (prefix :field (byte 5 3) :value #b11011)
530 (suffix :field (byte 2 14) :value #b11)
531 (op :fields (list (byte 2 0) (byte 3 11)))
532 (d :field (byte 1 2))
533 (fp-reg :field (byte 3 8) :type 'fp-reg))
536 ;;; (added by (?) pfw)
537 ;;; fp no operand isns
538 (sb!disassem:define-instruction-format (floating-point-no 16
539 :default-printer '(:name))
540 (prefix :field (byte 8 0) :value #b11011001)
541 (suffix :field (byte 3 13) :value #b111)
542 (op :field (byte 5 8)))
544 (sb!disassem:define-instruction-format (floating-point-3 16
545 :default-printer '(:name))
546 (prefix :field (byte 5 3) :value #b11011)
547 (suffix :field (byte 2 14) :value #b11)
548 (op :fields (list (byte 3 0) (byte 6 8))))
550 (sb!disassem:define-instruction-format (floating-point-5 16
551 :default-printer '(:name))
552 (prefix :field (byte 8 0) :value #b11011011)
553 (suffix :field (byte 3 13) :value #b111)
554 (op :field (byte 5 8)))
556 (sb!disassem:define-instruction-format (floating-point-st 16
557 :default-printer '(:name))
558 (prefix :field (byte 8 0) :value #b11011111)
559 (suffix :field (byte 3 13) :value #b111)
560 (op :field (byte 5 8)))
562 (sb!disassem:define-instruction-format (string-op 8
564 :default-printer '(:name width)))
566 (sb!disassem:define-instruction-format (short-cond-jump 16)
567 (op :field (byte 4 4))
568 (cc :field (byte 4 0) :type 'condition-code)
569 (label :field (byte 8 8) :type 'displacement))
571 (sb!disassem:define-instruction-format (short-jump 16
572 :default-printer '(:name :tab label))
573 (const :field (byte 4 4) :value #b1110)
574 (op :field (byte 4 0))
575 (label :field (byte 8 8) :type 'displacement))
577 (sb!disassem:define-instruction-format (near-cond-jump 16)
578 (op :fields (list (byte 8 0) (byte 4 12)) :value '(#b00001111 #b1000))
579 (cc :field (byte 4 8) :type 'condition-code)
580 ;; The disassembler currently doesn't let you have an instruction > 32 bits
581 ;; long, so we fake it by using a prefilter to read the offset.
582 (label :type 'displacement
583 :prefilter (lambda (value dstate)
584 (declare (ignore value)) ; always nil anyway
585 (sb!disassem:read-signed-suffix 32 dstate))))
587 (sb!disassem:define-instruction-format (near-jump 8
588 :default-printer '(:name :tab label))
589 (op :field (byte 8 0))
590 ;; The disassembler currently doesn't let you have an instruction > 32 bits
591 ;; long, so we fake it by using a prefilter to read the address.
592 (label :type 'displacement
593 :prefilter (lambda (value dstate)
594 (declare (ignore value)) ; always nil anyway
595 (sb!disassem:read-signed-suffix 32 dstate))))
598 (sb!disassem:define-instruction-format (cond-set 24
599 :default-printer '('set cc :tab reg/mem))
600 (prefix :field (byte 8 0) :value #b00001111)
601 (op :field (byte 4 12) :value #b1001)
602 (cc :field (byte 4 8) :type 'condition-code)
603 (reg/mem :fields (list (byte 2 22) (byte 3 16))
605 (reg :field (byte 3 19) :value #b000))
607 (sb!disassem:define-instruction-format (cond-move 24
609 '('cmov cc :tab reg ", " reg/mem))
610 (prefix :field (byte 8 0) :value #b00001111)
611 (op :field (byte 4 12) :value #b0100)
612 (cc :field (byte 4 8) :type 'condition-code)
613 (reg/mem :fields (list (byte 2 22) (byte 3 16))
615 (reg :field (byte 3 19) :type 'reg))
617 (sb!disassem:define-instruction-format (enter-format 32
618 :default-printer '(:name
620 (:unless (:constant 0)
622 (op :field (byte 8 0))
623 (disp :field (byte 16 8))
624 (level :field (byte 8 24)))
626 ;;; Single byte instruction with an immediate byte argument.
627 (sb!disassem:define-instruction-format (byte-imm 16
628 :default-printer '(:name :tab code))
629 (op :field (byte 8 0))
630 (code :field (byte 8 8)))
632 ;;;; primitive emitters
634 (define-bitfield-emitter emit-word 16
637 (define-bitfield-emitter emit-dword 32
640 (define-bitfield-emitter emit-qword 64
643 (define-bitfield-emitter emit-byte-with-reg 8
644 (byte 5 3) (byte 3 0))
646 (define-bitfield-emitter emit-mod-reg-r/m-byte 8
647 (byte 2 6) (byte 3 3) (byte 3 0))
649 (define-bitfield-emitter emit-sib-byte 8
650 (byte 2 6) (byte 3 3) (byte 3 0))
652 (define-bitfield-emitter emit-rex-byte 8
653 (byte 4 4) (byte 1 3) (byte 1 2) (byte 1 1) (byte 1 0))
659 (defun emit-absolute-fixup (segment fixup &optional quad-p)
660 (note-fixup segment (if quad-p :absolute64 :absolute) fixup)
661 (let ((offset (fixup-offset fixup)))
663 (emit-back-patch segment
665 (lambda (segment posn)
666 (declare (ignore posn))
667 (let ((val (- (+ (component-header-length)
668 (or (label-position offset)
670 other-pointer-lowtag)))
672 (emit-qword segment val )
673 (emit-dword segment val )))))
675 (emit-qword segment (or offset 0))
676 (emit-dword segment (or offset 0))))))
678 (defun emit-relative-fixup (segment fixup)
679 (note-fixup segment :relative fixup)
680 (emit-dword segment (or (fixup-offset fixup) 0)))
682 ;;;; the effective-address (ea) structure
684 (defun reg-tn-encoding (tn)
685 (declare (type tn tn))
686 (aver (eq (sb-name (sc-sb (tn-sc tn))) 'registers))
687 ;; ea only has space for three bits of register number: regs r8
688 ;; and up are selected by a REX prefix byte which caller is responsible
689 ;; for having emitted where necessary already
690 (let ((offset (mod (tn-offset tn) 16)))
691 (logior (ash (logand offset 1) 2)
694 (defstruct (ea (:constructor make-ea (size &key base index scale disp))
696 ;; note that we can represent an EA qith a QWORD size, but EMIT-EA
697 ;; can't actually emit it on its own: caller also needs to emit REX
699 (size nil :type (member :byte :word :dword :qword))
700 (base nil :type (or tn null))
701 (index nil :type (or tn null))
702 (scale 1 :type (member 1 2 4 8))
703 (disp 0 :type (or (unsigned-byte 32) (signed-byte 32) fixup)))
704 (def!method print-object ((ea ea) stream)
705 (cond ((or *print-escape* *print-readably*)
706 (print-unreadable-object (ea stream :type t)
708 "~S~@[ base=~S~]~@[ index=~S~]~@[ scale=~S~]~@[ disp=~S~]"
712 (let ((scale (ea-scale ea)))
713 (if (= scale 1) nil scale))
716 (format stream "~A PTR [" (symbol-name (ea-size ea)))
718 (write-string (sb!c::location-print-name (ea-base ea)) stream)
720 (write-string "+" stream)))
722 (write-string (sb!c::location-print-name (ea-index ea)) stream))
723 (unless (= (ea-scale ea) 1)
724 (format stream "*~A" (ea-scale ea)))
725 (typecase (ea-disp ea)
728 (format stream "~@D" (ea-disp ea)))
730 (format stream "+~A" (ea-disp ea))))
731 (write-char #\] stream))))
733 (defun emit-ea (segment thing reg &optional allow-constants)
736 ;; this would be eleganter if we had a function that would create
738 (ecase (sb-name (sc-sb (tn-sc thing)))
740 (emit-mod-reg-r/m-byte segment #b11 reg (reg-tn-encoding thing)))
742 ;; Convert stack tns into an index off RBP.
743 (let ((disp (- (* (1+ (tn-offset thing)) n-word-bytes))))
744 (cond ((< -128 disp 127)
745 (emit-mod-reg-r/m-byte segment #b01 reg #b101)
746 (emit-byte segment disp))
748 (emit-mod-reg-r/m-byte segment #b10 reg #b101)
749 (emit-dword segment disp)))))
751 (unless allow-constants
753 "Constant TNs can only be directly used in MOV, PUSH, and CMP."))
754 (emit-mod-reg-r/m-byte segment #b00 reg #b100)
755 (emit-sib-byte segment 1 4 5) ;no base, no index
756 (emit-absolute-fixup segment
759 (- (* (tn-offset thing) n-word-bytes)
760 other-pointer-lowtag))))))
762 (let* ((base (ea-base thing))
763 (index (ea-index thing))
764 (scale (ea-scale thing))
765 (disp (ea-disp thing))
766 (mod (cond ((or (null base)
768 (not (= (reg-tn-encoding base) #b101))))
770 ((and (fixnump disp) (<= -128 disp 127))
774 (r/m (cond (index #b100)
776 (t (reg-tn-encoding base)))))
777 (when (and (= mod 0) (= r/m #b101))
778 ;; this is rip-relative in amd64, so we'll use a sib instead
779 (setf r/m #b100 scale 1))
780 (emit-mod-reg-r/m-byte segment mod reg r/m)
782 (let ((ss (1- (integer-length scale)))
783 (index (if (null index)
785 (let ((index (reg-tn-encoding index)))
787 (error "can't index off of ESP")
789 (base (if (null base)
791 (reg-tn-encoding base))))
792 (emit-sib-byte segment ss index base)))
794 (emit-byte segment disp))
795 ((or (= mod #b10) (null base))
797 (emit-absolute-fixup segment disp)
798 (emit-dword segment disp))))))
800 (emit-mod-reg-r/m-byte segment #b00 reg #b100)
801 (emit-sib-byte segment 0 #b100 #b101)
802 (emit-absolute-fixup segment thing))))
804 (defun fp-reg-tn-p (thing)
806 (eq (sb-name (sc-sb (tn-sc thing))) 'float-registers)))
808 ;;; like the above, but for fp-instructions--jrd
809 (defun emit-fp-op (segment thing op)
810 (if (fp-reg-tn-p thing)
811 (emit-byte segment (dpb op (byte 3 3) (dpb (tn-offset thing)
814 (emit-ea segment thing op)))
816 (defun byte-reg-p (thing)
818 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
819 (member (sc-name (tn-sc thing)) *byte-sc-names*)
822 (defun byte-ea-p (thing)
824 (ea (eq (ea-size thing) :byte))
826 (and (member (sc-name (tn-sc thing)) *byte-sc-names*) t))
829 (defun word-reg-p (thing)
831 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
832 (member (sc-name (tn-sc thing)) *word-sc-names*)
835 (defun word-ea-p (thing)
837 (ea (eq (ea-size thing) :word))
838 (tn (and (member (sc-name (tn-sc thing)) *word-sc-names*) t))
841 (defun dword-reg-p (thing)
843 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
844 (member (sc-name (tn-sc thing)) *dword-sc-names*)
847 (defun dword-ea-p (thing)
849 (ea (eq (ea-size thing) :dword))
851 (and (member (sc-name (tn-sc thing)) *dword-sc-names*) t))
854 (defun qword-reg-p (thing)
856 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
857 (member (sc-name (tn-sc thing)) *qword-sc-names*)
860 (defun qword-ea-p (thing)
862 (ea (eq (ea-size thing) :qword))
864 (and (member (sc-name (tn-sc thing)) *qword-sc-names*) t))
868 (defun register-p (thing)
870 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)))
872 (defun accumulator-p (thing)
873 (and (register-p thing)
874 (= (tn-offset thing) 0)))
878 (def!constant +operand-size-prefix-byte+ #b01100110)
880 (defun maybe-emit-operand-size-prefix (segment size)
881 (unless (or (eq size :byte)
882 (eq size :qword) ; REX prefix handles this
883 (eq size +default-operand-size+))
884 (emit-byte segment +operand-size-prefix-byte+)))
886 (defun maybe-emit-rex-prefix (segment operand-size r x b)
887 (labels ((if-hi (r) ;; offset of r8 is 16
888 (if (and r (> (tn-offset r) 15)) 1 0)))
889 (let ((rex-w (if (eq operand-size :qword) 1 0))
893 (when (not (zerop (logior rex-w rex-r rex-x rex-b)))
894 (emit-rex-byte segment #b0100 rex-w rex-r rex-x rex-b)))))
896 (defun maybe-emit-rex-for-ea (segment ea reg)
897 (let ((ea-p (ea-p ea))) ;emit-ea can also be called with a tn
898 (maybe-emit-rex-prefix segment (operand-size ea) reg
899 (and ea-p (ea-index ea))
900 (cond (ea-p (ea-base ea))
902 (eql (sb-name (sc-sb (tn-sc ea)))
907 (defun operand-size (thing)
910 ;; FIXME: might as well be COND instead of having to use #. readmacro
911 ;; to hack up the code
912 (case (sc-name (tn-sc thing))
921 ;; added by jrd: float-registers is a separate size (?)
927 (error "can't tell the size of ~S ~S" thing (sc-name (tn-sc thing))))))
933 (defun matching-operand-size (dst src)
934 (let ((dst-size (operand-size dst))
935 (src-size (operand-size src)))
938 (if (eq dst-size src-size)
940 (error "size mismatch: ~S is a ~S and ~S is a ~S."
941 dst dst-size src src-size))
945 (error "can't tell the size of either ~S or ~S" dst src)))))
947 (defun emit-sized-immediate (segment size value &optional quad-p)
950 (emit-byte segment value))
952 (emit-word segment value))
954 ;; except in a very few cases (MOV instructions A1,A3,B8) we expect
955 ;; dword data bytes even when 64 bit work is being done. So, mostly
956 ;; we treat quad constants as dwords.
957 (if (and quad-p (eq size :qword))
958 (emit-qword segment value)
959 (emit-dword segment value)))))
961 ;;;; general data transfer
963 (define-instruction mov (segment dst src)
964 ;; immediate to register
965 (:printer reg ((op #b1011) (imm nil :type 'imm-data))
966 '(:name :tab reg ", " imm))
967 ;; absolute mem to/from accumulator
968 (:printer simple-dir ((op #b101000) (imm nil :type 'imm-addr))
969 `(:name :tab ,(swap-if 'dir 'accum ", " '("[" imm "]"))))
970 ;; register to/from register/memory
971 (:printer reg-reg/mem-dir ((op #b100010)))
972 ;; immediate to register/memory
973 (:printer reg/mem-imm ((op '(#b1100011 #b000))))
976 (let ((size (matching-operand-size dst src)))
977 (maybe-emit-operand-size-prefix segment size)
978 (cond ((register-p dst)
979 (cond ((integerp src)
980 (maybe-emit-rex-prefix segment size nil nil dst)
981 (emit-byte-with-reg segment
985 (reg-tn-encoding dst))
986 (emit-sized-immediate segment size src (eq size :qword)))
987 ((and (fixup-p src) (accumulator-p dst))
988 (maybe-emit-rex-prefix segment (operand-size src)
994 (emit-absolute-fixup segment src (eq size :qword)))
996 (maybe-emit-rex-for-ea segment src dst)
1001 (emit-ea segment src (reg-tn-encoding dst) t))))
1002 ((and (fixup-p dst) (accumulator-p src))
1003 (maybe-emit-rex-prefix segment size nil nil nil)
1004 (emit-byte segment (if (eq size :byte) #b10100010 #b10100011))
1005 (emit-absolute-fixup segment dst (eq size :qword)))
1007 ;; C7 only deals with 32 bit immediates even if register is
1008 ;; 64 bit: only b8-bf use 64 bit immediates
1009 (maybe-emit-rex-for-ea segment dst nil)
1010 (cond ((typep src '(or (signed-byte 32) (unsigned-byte 32)))
1012 (if (eq size :byte) #b11000110 #b11000111))
1013 (emit-ea segment dst #b000)
1014 (emit-sized-immediate segment
1015 (case size (:qword :dword) (t size))
1020 (maybe-emit-rex-for-ea segment dst src)
1021 (emit-byte segment (if (eq size :byte) #b10001000 #b10001001))
1022 (emit-ea segment dst (reg-tn-encoding src)))
1024 (maybe-emit-rex-for-ea segment dst nil)
1025 (emit-byte segment #b11000111)
1026 (emit-ea segment dst #b000)
1027 (emit-absolute-fixup segment src))
1029 (error "bogus arguments to MOV: ~S ~S" dst src))))))
1031 (defun emit-move-with-extension (segment dst src signed-p)
1032 (aver (register-p dst))
1033 (let ((dst-size (operand-size dst))
1034 (src-size (operand-size src))
1035 (opcode (if signed-p #b10111110 #b10110110)))
1038 (aver (eq src-size :byte))
1039 (maybe-emit-operand-size-prefix segment :word)
1040 (emit-byte segment #b00001111)
1041 (emit-byte segment opcode)
1042 (emit-ea segment src (reg-tn-encoding dst)))
1046 (maybe-emit-operand-size-prefix segment :dword)
1047 (maybe-emit-rex-for-ea segment src dst)
1048 (emit-byte segment #b00001111)
1049 (emit-byte segment opcode)
1050 (emit-ea segment src (reg-tn-encoding dst)))
1052 (maybe-emit-rex-for-ea segment src dst)
1053 (emit-byte segment #b00001111)
1054 (emit-byte segment (logior opcode 1))
1055 (emit-ea segment src (reg-tn-encoding dst)))
1057 (aver (eq dst-size :qword))
1058 ;; dst is in reg, src is in modrm
1059 (let ((ea-p (ea-p src)))
1060 (maybe-emit-rex-prefix segment (if signed-p :qword :dword) dst
1061 (and ea-p (ea-index src))
1062 (cond (ea-p (ea-base src))
1065 (emit-byte segment #x63) ;movsxd
1066 ;;(emit-byte segment opcode)
1067 (emit-ea segment src (reg-tn-encoding dst)))))))))
1069 (define-instruction movsx (segment dst src)
1070 (:printer ext-reg-reg/mem ((op #b1011111) (reg nil :type 'word-reg)))
1071 (:emitter (emit-move-with-extension segment dst src :signed)))
1073 (define-instruction movzx (segment dst src)
1074 (:printer ext-reg-reg/mem ((op #b1011011) (reg nil :type 'word-reg)))
1075 (:emitter (emit-move-with-extension segment dst src nil)))
1077 (define-instruction movsxd (segment dst src)
1078 (:printer reg-reg/mem ((op #x63) (reg nil :type 'word-reg)))
1079 (:emitter (emit-move-with-extension segment dst src :signed)))
1081 ;;; this is not a real amd64 instruction, of course
1082 (define-instruction movzxd (segment dst src)
1083 (:printer reg-reg/mem ((op #x63) (reg nil :type 'word-reg)))
1084 (:emitter (emit-move-with-extension segment dst src nil)))
1086 (define-instruction push (segment src)
1088 (:printer reg-no-width ((op #b01010)))
1090 (:printer reg/mem ((op '(#b1111111 #b110)) (width 1)))
1092 (:printer byte ((op #b01101010) (imm nil :type 'signed-imm-byte))
1094 (:printer byte ((op #b01101000) (imm nil :type 'imm-word))
1096 ;; ### segment registers?
1099 (cond ((integerp src)
1100 (cond ((<= -128 src 127)
1101 (emit-byte segment #b01101010)
1102 (emit-byte segment src))
1104 ;; AMD64 manual says no REX needed but is unclear
1105 ;; whether it expects 32 or 64 bit immediate here
1106 (emit-byte segment #b01101000)
1107 (emit-dword segment src))))
1109 ;; Interpret the fixup as an immediate dword to push.
1110 (emit-byte segment #b01101000)
1111 (emit-absolute-fixup segment src))
1113 (let ((size (operand-size src)))
1114 (aver (not (eq size :byte)))
1115 (maybe-emit-operand-size-prefix segment size)
1116 (maybe-emit-rex-for-ea segment src nil)
1117 (cond ((register-p src)
1118 (emit-byte-with-reg segment #b01010 (reg-tn-encoding src)))
1120 (emit-byte segment #b11111111)
1121 (emit-ea segment src #b110 t))))))))
1123 (define-instruction pusha (segment)
1124 (:printer byte ((op #b01100000)))
1126 (emit-byte segment #b01100000)))
1128 (define-instruction pop (segment dst)
1129 (:printer reg-no-width ((op #b01011)))
1130 (:printer reg/mem ((op '(#b1000111 #b000)) (width 1)))
1132 (let ((size (operand-size dst)))
1133 (aver (not (eq size :byte)))
1134 (maybe-emit-operand-size-prefix segment size)
1135 (maybe-emit-rex-for-ea segment dst nil)
1136 (cond ((register-p dst)
1137 (emit-byte-with-reg segment #b01011 (reg-tn-encoding dst)))
1139 (emit-byte segment #b10001111)
1140 (emit-ea segment dst #b000))))))
1142 (define-instruction popa (segment)
1143 (:printer byte ((op #b01100001)))
1145 (emit-byte segment #b01100001)))
1147 (define-instruction xchg (segment operand1 operand2)
1148 ;; Register with accumulator.
1149 (:printer reg-no-width ((op #b10010)) '(:name :tab accum ", " reg))
1150 ;; Register/Memory with Register.
1151 (:printer reg-reg/mem ((op #b1000011)))
1153 (let ((size (matching-operand-size operand1 operand2)))
1154 (maybe-emit-operand-size-prefix segment size)
1155 (labels ((xchg-acc-with-something (acc something)
1156 (if (and (not (eq size :byte)) (register-p something))
1157 (emit-byte-with-reg segment
1159 (reg-tn-encoding something))
1160 (xchg-reg-with-something acc something)))
1161 (xchg-reg-with-something (reg something)
1162 (emit-byte segment (if (eq size :byte) #b10000110 #b10000111))
1163 (emit-ea segment something (reg-tn-encoding reg))))
1164 (cond ((accumulator-p operand1)
1165 (xchg-acc-with-something operand1 operand2))
1166 ((accumulator-p operand2)
1167 (xchg-acc-with-something operand2 operand1))
1168 ((register-p operand1)
1169 (xchg-reg-with-something operand1 operand2))
1170 ((register-p operand2)
1171 (xchg-reg-with-something operand2 operand1))
1173 (error "bogus args to XCHG: ~S ~S" operand1 operand2)))))))
1175 (define-instruction lea (segment dst src)
1176 (:printer reg-reg/mem ((op #b1000110) (width 1)))
1178 (aver (or (dword-reg-p dst) (qword-reg-p dst)))
1179 (maybe-emit-rex-for-ea segment src dst)
1180 (emit-byte segment #b10001101)
1181 (emit-ea segment src (reg-tn-encoding dst))))
1183 (define-instruction cmpxchg (segment dst src)
1184 ;; Register/Memory with Register.
1185 (:printer ext-reg-reg/mem ((op #b1011000)) '(:name :tab reg/mem ", " reg))
1187 (aver (register-p src))
1188 (let ((size (matching-operand-size src dst)))
1189 (maybe-emit-operand-size-prefix segment size)
1190 (maybe-emit-rex-for-ea segment dst src)
1191 (emit-byte segment #b00001111)
1192 (emit-byte segment (if (eq size :byte) #b10110000 #b10110001))
1193 (emit-ea segment dst (reg-tn-encoding src)))))
1197 (define-instruction fs-segment-prefix (segment)
1199 (emit-byte segment #x64)))
1201 ;;;; flag control instructions
1203 ;;; CLC -- Clear Carry Flag.
1204 (define-instruction clc (segment)
1205 (:printer byte ((op #b11111000)))
1207 (emit-byte segment #b11111000)))
1209 ;;; CLD -- Clear Direction Flag.
1210 (define-instruction cld (segment)
1211 (:printer byte ((op #b11111100)))
1213 (emit-byte segment #b11111100)))
1215 ;;; CLI -- Clear Iterrupt Enable Flag.
1216 (define-instruction cli (segment)
1217 (:printer byte ((op #b11111010)))
1219 (emit-byte segment #b11111010)))
1221 ;;; CMC -- Complement Carry Flag.
1222 (define-instruction cmc (segment)
1223 (:printer byte ((op #b11110101)))
1225 (emit-byte segment #b11110101)))
1227 ;;; LAHF -- Load AH into flags.
1228 (define-instruction lahf (segment)
1229 (:printer byte ((op #b10011111)))
1231 (emit-byte segment #b10011111)))
1233 ;;; POPF -- Pop flags.
1234 (define-instruction popf (segment)
1235 (:printer byte ((op #b10011101)))
1237 (emit-byte segment #b10011101)))
1239 ;;; PUSHF -- push flags.
1240 (define-instruction pushf (segment)
1241 (:printer byte ((op #b10011100)))
1243 (emit-byte segment #b10011100)))
1245 ;;; SAHF -- Store AH into flags.
1246 (define-instruction sahf (segment)
1247 (:printer byte ((op #b10011110)))
1249 (emit-byte segment #b10011110)))
1251 ;;; STC -- Set Carry Flag.
1252 (define-instruction stc (segment)
1253 (:printer byte ((op #b11111001)))
1255 (emit-byte segment #b11111001)))
1257 ;;; STD -- Set Direction Flag.
1258 (define-instruction std (segment)
1259 (:printer byte ((op #b11111101)))
1261 (emit-byte segment #b11111101)))
1263 ;;; STI -- Set Interrupt Enable Flag.
1264 (define-instruction sti (segment)
1265 (:printer byte ((op #b11111011)))
1267 (emit-byte segment #b11111011)))
1271 (defun emit-random-arith-inst (name segment dst src opcode
1272 &optional allow-constants)
1273 (let ((size (matching-operand-size dst src)))
1274 (maybe-emit-operand-size-prefix segment size)
1277 (cond ((and (not (eq size :byte)) (<= -128 src 127))
1278 (maybe-emit-rex-for-ea segment dst nil)
1279 (emit-byte segment #b10000011)
1280 (emit-ea segment dst opcode allow-constants)
1281 (emit-byte segment src))
1282 ((accumulator-p dst)
1289 (emit-sized-immediate segment size src))
1291 (maybe-emit-rex-for-ea segment dst nil)
1292 (emit-byte segment (if (eq size :byte) #b10000000 #b10000001))
1293 (emit-ea segment dst opcode allow-constants)
1294 (emit-sized-immediate segment size src))))
1296 (maybe-emit-rex-for-ea segment dst src)
1300 (if (eq size :byte) #b00000000 #b00000001)))
1301 (emit-ea segment dst (reg-tn-encoding src) allow-constants))
1303 (maybe-emit-rex-for-ea segment src dst)
1307 (if (eq size :byte) #b00000010 #b00000011)))
1308 (emit-ea segment src (reg-tn-encoding dst) allow-constants))
1310 (error "bogus operands to ~A" name)))))
1312 (eval-when (:compile-toplevel :execute)
1313 (defun arith-inst-printer-list (subop)
1314 `((accum-imm ((op ,(dpb subop (byte 3 2) #b0000010))))
1315 (reg/mem-imm ((op (#b1000000 ,subop))))
1316 (reg/mem-imm ((op (#b1000001 ,subop))
1317 (imm nil :type signed-imm-byte)))
1318 (reg-reg/mem-dir ((op ,(dpb subop (byte 3 1) #b000000))))))
1321 (define-instruction add (segment dst src)
1322 (:printer-list (arith-inst-printer-list #b000))
1323 (:emitter (emit-random-arith-inst "ADD" segment dst src #b000)))
1325 (define-instruction adc (segment dst src)
1326 (:printer-list (arith-inst-printer-list #b010))
1327 (:emitter (emit-random-arith-inst "ADC" segment dst src #b010)))
1329 (define-instruction sub (segment dst src)
1330 (:printer-list (arith-inst-printer-list #b101))
1331 (:emitter (emit-random-arith-inst "SUB" segment dst src #b101)))
1333 (define-instruction sbb (segment dst src)
1334 (:printer-list (arith-inst-printer-list #b011))
1335 (:emitter (emit-random-arith-inst "SBB" segment dst src #b011)))
1337 (define-instruction cmp (segment dst src)
1338 (:printer-list (arith-inst-printer-list #b111))
1339 (:emitter (emit-random-arith-inst "CMP" segment dst src #b111 t)))
1341 (define-instruction inc (segment dst)
1343 (:printer reg/mem ((op '(#b1111111 #b000))))
1345 (let ((size (operand-size dst)))
1346 (maybe-emit-operand-size-prefix segment size)
1347 (cond #+nil ; these opcodes become REX prefixes in x86-64
1348 ((and (not (eq size :byte)) (register-p dst))
1349 (emit-byte-with-reg segment #b01000 (reg-tn-encoding dst)))
1351 (maybe-emit-rex-for-ea segment dst nil)
1352 (emit-byte segment (if (eq size :byte) #b11111110 #b11111111))
1353 (emit-ea segment dst #b000))))))
1355 (define-instruction dec (segment dst)
1357 (:printer reg-no-width ((op #b01001)))
1359 (:printer reg/mem ((op '(#b1111111 #b001))))
1361 (let ((size (operand-size dst)))
1362 (maybe-emit-operand-size-prefix segment size)
1363 (cond ((and (not (eq size :byte)) (register-p dst))
1364 (emit-byte-with-reg segment #b01001 (reg-tn-encoding dst)))
1366 (maybe-emit-rex-for-ea segment dst nil)
1367 (emit-byte segment (if (eq size :byte) #b11111110 #b11111111))
1368 (emit-ea segment dst #b001))))))
1370 (define-instruction neg (segment dst)
1371 (:printer reg/mem ((op '(#b1111011 #b011))))
1373 (let ((size (operand-size dst)))
1374 (maybe-emit-operand-size-prefix segment size)
1375 (maybe-emit-rex-for-ea segment dst nil)
1376 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1377 (emit-ea segment dst #b011))))
1379 (define-instruction aaa (segment)
1380 (:printer byte ((op #b00110111)))
1382 (emit-byte segment #b00110111)))
1384 (define-instruction aas (segment)
1385 (:printer byte ((op #b00111111)))
1387 (emit-byte segment #b00111111)))
1389 (define-instruction daa (segment)
1390 (:printer byte ((op #b00100111)))
1392 (emit-byte segment #b00100111)))
1394 (define-instruction das (segment)
1395 (:printer byte ((op #b00101111)))
1397 (emit-byte segment #b00101111)))
1399 (define-instruction mul (segment dst src)
1400 (:printer accum-reg/mem ((op '(#b1111011 #b100))))
1402 (let ((size (matching-operand-size dst src)))
1403 (aver (accumulator-p dst))
1404 (maybe-emit-operand-size-prefix segment size)
1405 (maybe-emit-rex-for-ea segment src nil)
1406 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1407 (emit-ea segment src #b100))))
1409 (define-instruction imul (segment dst &optional src1 src2)
1410 (:printer accum-reg/mem ((op '(#b1111011 #b101))))
1411 (:printer ext-reg-reg/mem ((op #b1010111)))
1412 (:printer reg-reg/mem ((op #b0110100) (width 1) (imm nil :type 'imm-word))
1413 '(:name :tab reg ", " reg/mem ", " imm))
1414 (:printer reg-reg/mem ((op #b0110101) (width 1)
1415 (imm nil :type 'signed-imm-byte))
1416 '(:name :tab reg ", " reg/mem ", " imm))
1418 (flet ((r/m-with-immed-to-reg (reg r/m immed)
1419 (let* ((size (matching-operand-size reg r/m))
1420 (sx (and (not (eq size :byte)) (<= -128 immed 127))))
1421 (maybe-emit-operand-size-prefix segment size)
1422 (maybe-emit-rex-for-ea segment r/m reg)
1423 (emit-byte segment (if sx #b01101011 #b01101001))
1424 (emit-ea segment r/m (reg-tn-encoding reg))
1426 (emit-byte segment immed)
1427 (emit-sized-immediate segment size immed)))))
1429 (r/m-with-immed-to-reg dst src1 src2))
1432 (r/m-with-immed-to-reg dst dst src1)
1433 (let ((size (matching-operand-size dst src1)))
1434 (maybe-emit-operand-size-prefix segment size)
1435 (maybe-emit-rex-for-ea segment src1 dst)
1436 (emit-byte segment #b00001111)
1437 (emit-byte segment #b10101111)
1438 (emit-ea segment src1 (reg-tn-encoding dst)))))
1440 (let ((size (operand-size dst)))
1441 (maybe-emit-operand-size-prefix segment size)
1442 (maybe-emit-rex-for-ea segment dst nil)
1443 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1444 (emit-ea segment dst #b101)))))))
1446 (define-instruction div (segment dst src)
1447 (:printer accum-reg/mem ((op '(#b1111011 #b110))))
1449 (let ((size (matching-operand-size dst src)))
1450 (aver (accumulator-p dst))
1451 (maybe-emit-operand-size-prefix segment size)
1452 (maybe-emit-rex-for-ea segment src nil)
1453 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1454 (emit-ea segment src #b110))))
1456 (define-instruction idiv (segment dst src)
1457 (:printer accum-reg/mem ((op '(#b1111011 #b111))))
1459 (let ((size (matching-operand-size dst src)))
1460 (aver (accumulator-p dst))
1461 (maybe-emit-operand-size-prefix segment size)
1462 (maybe-emit-rex-for-ea segment src nil)
1463 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1464 (emit-ea segment src #b111))))
1466 (define-instruction bswap (segment dst)
1467 (:printer ext-reg-no-width ((op #b11001)))
1469 (let ((size (operand-size dst)))
1470 (maybe-emit-rex-prefix segment size nil nil dst)
1471 (emit-byte segment #x0f)
1472 (emit-byte-with-reg segment #b11001 (reg-tn-encoding dst)))))
1475 (define-instruction aad (segment)
1476 (:printer two-bytes ((op '(#b11010101 #b00001010))))
1478 (emit-byte segment #b11010101)
1479 (emit-byte segment #b00001010)))
1481 (define-instruction aam (segment)
1482 (:printer two-bytes ((op '(#b11010100 #b00001010))))
1484 (emit-byte segment #b11010100)
1485 (emit-byte segment #b00001010)))
1487 ;;; CBW -- Convert Byte to Word. AX <- sign_xtnd(AL)
1488 (define-instruction cbw (segment)
1490 (maybe-emit-operand-size-prefix segment :word)
1491 (emit-byte segment #b10011000)))
1493 ;;; CWDE -- Convert Word To Double Word Extened. EAX <- sign_xtnd(AX)
1494 (define-instruction cwde (segment)
1496 (maybe-emit-operand-size-prefix segment :dword)
1497 (emit-byte segment #b10011000)))
1499 ;;; CWD -- Convert Word to Double Word. DX:AX <- sign_xtnd(AX)
1500 (define-instruction cwd (segment)
1502 (maybe-emit-operand-size-prefix segment :word)
1503 (emit-byte segment #b10011001)))
1505 ;;; CDQ -- Convert Double Word to Quad Word. EDX:EAX <- sign_xtnd(EAX)
1506 (define-instruction cdq (segment)
1507 (:printer byte ((op #b10011001)))
1509 (maybe-emit-operand-size-prefix segment :dword)
1510 (emit-byte segment #b10011001)))
1512 ;;; CQO -- Convert Quad or Octaword. RDX:RAX <- sign_xtnd(RAX)
1513 (define-instruction cqo (segment)
1514 (:printer byte ((op #b10011001)))
1516 (maybe-emit-rex-prefix segment :qword nil nil nil)
1517 (emit-byte segment #b10011001)))
1519 (define-instruction xadd (segment dst src)
1520 ;; Register/Memory with Register.
1521 (:printer ext-reg-reg/mem ((op #b1100000)) '(:name :tab reg/mem ", " reg))
1523 (aver (register-p src))
1524 (let ((size (matching-operand-size src dst)))
1525 (maybe-emit-operand-size-prefix segment size)
1526 (maybe-emit-rex-for-ea segment dst src)
1527 (emit-byte segment #b00001111)
1528 (emit-byte segment (if (eq size :byte) #b11000000 #b11000001))
1529 (emit-ea segment dst (reg-tn-encoding src)))))
1534 (defun emit-shift-inst (segment dst amount opcode)
1535 (let ((size (operand-size dst)))
1536 (maybe-emit-operand-size-prefix segment size)
1537 (multiple-value-bind (major-opcode immed)
1539 (:cl (values #b11010010 nil))
1540 (1 (values #b11010000 nil))
1541 (t (values #b11000000 t)))
1542 (maybe-emit-rex-for-ea segment dst nil)
1544 (if (eq size :byte) major-opcode (logior major-opcode 1)))
1545 (emit-ea segment dst opcode)
1547 (emit-byte segment amount)))))
1549 (eval-when (:compile-toplevel :execute)
1550 (defun shift-inst-printer-list (subop)
1551 `((reg/mem ((op (#b1101000 ,subop)))
1552 (:name :tab reg/mem ", 1"))
1553 (reg/mem ((op (#b1101001 ,subop)))
1554 (:name :tab reg/mem ", " 'cl))
1555 (reg/mem-imm ((op (#b1100000 ,subop))
1556 (imm nil :type signed-imm-byte))))))
1558 (define-instruction rol (segment dst amount)
1560 (shift-inst-printer-list #b000))
1562 (emit-shift-inst segment dst amount #b000)))
1564 (define-instruction ror (segment dst amount)
1566 (shift-inst-printer-list #b001))
1568 (emit-shift-inst segment dst amount #b001)))
1570 (define-instruction rcl (segment dst amount)
1572 (shift-inst-printer-list #b010))
1574 (emit-shift-inst segment dst amount #b010)))
1576 (define-instruction rcr (segment dst amount)
1578 (shift-inst-printer-list #b011))
1580 (emit-shift-inst segment dst amount #b011)))
1582 (define-instruction shl (segment dst amount)
1584 (shift-inst-printer-list #b100))
1586 (emit-shift-inst segment dst amount #b100)))
1588 (define-instruction shr (segment dst amount)
1590 (shift-inst-printer-list #b101))
1592 (emit-shift-inst segment dst amount #b101)))
1594 (define-instruction sar (segment dst amount)
1596 (shift-inst-printer-list #b111))
1598 (emit-shift-inst segment dst amount #b111)))
1600 (defun emit-double-shift (segment opcode dst src amt)
1601 (let ((size (matching-operand-size dst src)))
1602 (when (eq size :byte)
1603 (error "Double shifts can only be used with words."))
1604 (maybe-emit-operand-size-prefix segment size)
1605 (maybe-emit-rex-for-ea segment dst src)
1606 (emit-byte segment #b00001111)
1607 (emit-byte segment (dpb opcode (byte 1 3)
1608 (if (eq amt :cl) #b10100101 #b10100100)))
1609 (emit-ea segment dst (reg-tn-encoding src))
1610 (unless (eq amt :cl)
1611 (emit-byte segment amt))))
1613 (eval-when (:compile-toplevel :execute)
1614 (defun double-shift-inst-printer-list (op)
1616 (ext-reg-reg/mem-imm ((op ,(logior op #b100))
1617 (imm nil :type signed-imm-byte)))
1618 (ext-reg-reg/mem ((op ,(logior op #b101)))
1619 (:name :tab reg/mem ", " 'cl)))))
1621 (define-instruction shld (segment dst src amt)
1622 (:declare (type (or (member :cl) (mod 32)) amt))
1623 (:printer-list (double-shift-inst-printer-list #b10100000))
1625 (emit-double-shift segment #b0 dst src amt)))
1627 (define-instruction shrd (segment dst src amt)
1628 (:declare (type (or (member :cl) (mod 32)) amt))
1629 (:printer-list (double-shift-inst-printer-list #b10101000))
1631 (emit-double-shift segment #b1 dst src amt)))
1633 (define-instruction and (segment dst src)
1635 (arith-inst-printer-list #b100))
1637 (emit-random-arith-inst "AND" segment dst src #b100)))
1639 (define-instruction test (segment this that)
1640 (:printer accum-imm ((op #b1010100)))
1641 (:printer reg/mem-imm ((op '(#b1111011 #b000))))
1642 (:printer reg-reg/mem ((op #b1000010)))
1644 (let ((size (matching-operand-size this that)))
1645 (maybe-emit-operand-size-prefix segment size)
1646 (flet ((test-immed-and-something (immed something)
1647 (cond ((accumulator-p something)
1649 (if (eq size :byte) #b10101000 #b10101001))
1650 (emit-sized-immediate segment size immed))
1652 (maybe-emit-rex-for-ea segment something nil)
1654 (if (eq size :byte) #b11110110 #b11110111))
1655 (emit-ea segment something #b000)
1656 (emit-sized-immediate segment size immed))))
1657 (test-reg-and-something (reg something)
1658 (maybe-emit-rex-for-ea segment something reg)
1659 (emit-byte segment (if (eq size :byte) #b10000100 #b10000101))
1660 (emit-ea segment something (reg-tn-encoding reg))))
1661 (cond ((integerp that)
1662 (test-immed-and-something that this))
1664 (test-immed-and-something this that))
1666 (test-reg-and-something this that))
1668 (test-reg-and-something that this))
1670 (error "bogus operands for TEST: ~S and ~S" this that)))))))
1672 (define-instruction or (segment dst src)
1674 (arith-inst-printer-list #b001))
1676 (emit-random-arith-inst "OR" segment dst src #b001)))
1678 (define-instruction xor (segment dst src)
1680 (arith-inst-printer-list #b110))
1682 (emit-random-arith-inst "XOR" segment dst src #b110)))
1684 (define-instruction not (segment dst)
1685 (:printer reg/mem ((op '(#b1111011 #b010))))
1687 (let ((size (operand-size dst)))
1688 (maybe-emit-operand-size-prefix segment size)
1689 (maybe-emit-rex-for-ea segment dst nil)
1690 (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1691 (emit-ea segment dst #b010))))
1693 ;;;; string manipulation
1695 (define-instruction cmps (segment size)
1696 (:printer string-op ((op #b1010011)))
1698 (maybe-emit-operand-size-prefix segment size)
1699 (maybe-emit-rex-prefix segment size nil nil nil)
1700 (emit-byte segment (if (eq size :byte) #b10100110 #b10100111))))
1702 (define-instruction ins (segment acc)
1703 (:printer string-op ((op #b0110110)))
1705 (let ((size (operand-size acc)))
1706 (aver (accumulator-p acc))
1707 (maybe-emit-operand-size-prefix segment size)
1708 (maybe-emit-rex-prefix segment size nil nil nil)
1709 (emit-byte segment (if (eq size :byte) #b01101100 #b01101101)))))
1711 (define-instruction lods (segment acc)
1712 (:printer string-op ((op #b1010110)))
1714 (let ((size (operand-size acc)))
1715 (aver (accumulator-p acc))
1716 (maybe-emit-operand-size-prefix segment size)
1717 (maybe-emit-rex-prefix segment size nil nil nil)
1718 (emit-byte segment (if (eq size :byte) #b10101100 #b10101101)))))
1720 (define-instruction movs (segment size)
1721 (:printer string-op ((op #b1010010)))
1723 (maybe-emit-operand-size-prefix segment size)
1724 (maybe-emit-rex-prefix segment size nil nil nil)
1725 (emit-byte segment (if (eq size :byte) #b10100100 #b10100101))))
1727 (define-instruction outs (segment acc)
1728 (:printer string-op ((op #b0110111)))
1730 (let ((size (operand-size acc)))
1731 (aver (accumulator-p acc))
1732 (maybe-emit-operand-size-prefix segment size)
1733 (maybe-emit-rex-prefix segment size nil nil nil)
1734 (emit-byte segment (if (eq size :byte) #b01101110 #b01101111)))))
1736 (define-instruction scas (segment acc)
1737 (:printer string-op ((op #b1010111)))
1739 (let ((size (operand-size acc)))
1740 (aver (accumulator-p acc))
1741 (maybe-emit-operand-size-prefix segment size)
1742 (maybe-emit-rex-prefix segment size nil nil nil)
1743 (emit-byte segment (if (eq size :byte) #b10101110 #b10101111)))))
1745 (define-instruction stos (segment acc)
1746 (:printer string-op ((op #b1010101)))
1748 (let ((size (operand-size acc)))
1749 (aver (accumulator-p acc))
1750 (maybe-emit-operand-size-prefix segment size)
1751 (maybe-emit-rex-prefix segment size nil nil nil)
1752 (emit-byte segment (if (eq size :byte) #b10101010 #b10101011)))))
1754 (define-instruction xlat (segment)
1755 (:printer byte ((op #b11010111)))
1757 (emit-byte segment #b11010111)))
1759 (define-instruction rep (segment)
1761 (emit-byte segment #b11110010)))
1763 (define-instruction repe (segment)
1764 (:printer byte ((op #b11110011)))
1766 (emit-byte segment #b11110011)))
1768 (define-instruction repne (segment)
1769 (:printer byte ((op #b11110010)))
1771 (emit-byte segment #b11110010)))
1774 ;;;; bit manipulation
1776 (define-instruction bsf (segment dst src)
1777 (:printer ext-reg-reg/mem ((op #b1011110) (width 0)))
1779 (let ((size (matching-operand-size dst src)))
1780 (when (eq size :byte)
1781 (error "can't scan bytes: ~S" src))
1782 (maybe-emit-operand-size-prefix segment size)
1783 (maybe-emit-rex-for-ea segment src dst)
1784 (emit-byte segment #b00001111)
1785 (emit-byte segment #b10111100)
1786 (emit-ea segment src (reg-tn-encoding dst)))))
1788 (define-instruction bsr (segment dst src)
1789 (:printer ext-reg-reg/mem ((op #b1011110) (width 1)))
1791 (let ((size (matching-operand-size dst src)))
1792 (when (eq size :byte)
1793 (error "can't scan bytes: ~S" src))
1794 (maybe-emit-operand-size-prefix segment size)
1795 (maybe-emit-rex-for-ea segment src dst)
1796 (emit-byte segment #b00001111)
1797 (emit-byte segment #b10111101)
1798 (emit-ea segment src (reg-tn-encoding dst)))))
1800 (defun emit-bit-test-and-mumble (segment src index opcode)
1801 (let ((size (operand-size src)))
1802 (when (eq size :byte)
1803 (error "can't scan bytes: ~S" src))
1804 (maybe-emit-operand-size-prefix segment size)
1805 (cond ((integerp index)
1806 (maybe-emit-rex-for-ea segment src nil)
1807 (emit-byte segment #b00001111)
1808 (emit-byte segment #b10111010)
1809 (emit-ea segment src opcode)
1810 (emit-byte segment index))
1812 (maybe-emit-rex-for-ea segment src index)
1813 (emit-byte segment #b00001111)
1814 (emit-byte segment (dpb opcode (byte 3 3) #b10000011))
1815 (emit-ea segment src (reg-tn-encoding index))))))
1817 (eval-when (:compile-toplevel :execute)
1818 (defun bit-test-inst-printer-list (subop)
1819 `((ext-reg/mem-imm ((op (#b1011101 ,subop))
1820 (reg/mem nil :type word-reg/mem)
1821 (imm nil :type imm-data)
1823 (ext-reg-reg/mem ((op ,(dpb subop (byte 3 2) #b1000001))
1825 (:name :tab reg/mem ", " reg)))))
1827 (define-instruction bt (segment src index)
1828 (:printer-list (bit-test-inst-printer-list #b100))
1830 (emit-bit-test-and-mumble segment src index #b100)))
1832 (define-instruction btc (segment src index)
1833 (:printer-list (bit-test-inst-printer-list #b111))
1835 (emit-bit-test-and-mumble segment src index #b111)))
1837 (define-instruction btr (segment src index)
1838 (:printer-list (bit-test-inst-printer-list #b110))
1840 (emit-bit-test-and-mumble segment src index #b110)))
1842 (define-instruction bts (segment src index)
1843 (:printer-list (bit-test-inst-printer-list #b101))
1845 (emit-bit-test-and-mumble segment src index #b101)))
1848 ;;;; control transfer
1850 (define-instruction call (segment where)
1851 (:printer near-jump ((op #b11101000)))
1852 (:printer reg/mem ((op '(#b1111111 #b010)) (width 1)))
1856 (emit-byte segment #b11101000) ; 32 bit relative
1857 (emit-back-patch segment
1859 (lambda (segment posn)
1861 (- (label-position where)
1864 (emit-byte segment #b11101000)
1865 (emit-relative-fixup segment where))
1867 (emit-byte segment #b11111111)
1868 (emit-ea segment where #b010)))))
1870 (defun emit-byte-displacement-backpatch (segment target)
1871 (emit-back-patch segment
1873 (lambda (segment posn)
1874 (let ((disp (- (label-position target) (1+ posn))))
1875 (aver (<= -128 disp 127))
1876 (emit-byte segment disp)))))
1878 (define-instruction jmp (segment cond &optional where)
1879 ;; conditional jumps
1880 (:printer short-cond-jump ((op #b0111)) '('j cc :tab label))
1881 (:printer near-cond-jump () '('j cc :tab label))
1882 ;; unconditional jumps
1883 (:printer short-jump ((op #b1011)))
1884 (:printer near-jump ((op #b11101001)) )
1885 (:printer reg/mem ((op '(#b1111111 #b100)) (width 1)))
1890 (lambda (segment posn delta-if-after)
1891 (let ((disp (- (label-position where posn delta-if-after)
1893 (when (<= -128 disp 127)
1895 (dpb (conditional-opcode cond)
1898 (emit-byte-displacement-backpatch segment where)
1900 (lambda (segment posn)
1901 (let ((disp (- (label-position where) (+ posn 6))))
1902 (emit-byte segment #b00001111)
1904 (dpb (conditional-opcode cond)
1907 (emit-dword segment disp)))))
1908 ((label-p (setq where cond))
1911 (lambda (segment posn delta-if-after)
1912 (let ((disp (- (label-position where posn delta-if-after)
1914 (when (<= -128 disp 127)
1915 (emit-byte segment #b11101011)
1916 (emit-byte-displacement-backpatch segment where)
1918 (lambda (segment posn)
1919 (let ((disp (- (label-position where) (+ posn 5))))
1920 (emit-byte segment #b11101001)
1921 (emit-dword segment disp)))))
1923 (emit-byte segment #b11101001)
1924 (emit-relative-fixup segment where))
1926 (unless (or (ea-p where) (tn-p where))
1927 (error "don't know what to do with ~A" where))
1928 (emit-byte segment #b11111111)
1929 (emit-ea segment where #b100)))))
1931 (define-instruction jmp-short (segment label)
1933 (emit-byte segment #b11101011)
1934 (emit-byte-displacement-backpatch segment label)))
1936 (define-instruction ret (segment &optional stack-delta)
1937 (:printer byte ((op #b11000011)))
1938 (:printer byte ((op #b11000010) (imm nil :type 'imm-word-16))
1942 (emit-byte segment #b11000010)
1943 (emit-word segment stack-delta))
1945 (emit-byte segment #b11000011)))))
1947 (define-instruction jecxz (segment target)
1948 (:printer short-jump ((op #b0011)))
1950 (emit-byte segment #b11100011)
1951 (emit-byte-displacement-backpatch segment target)))
1953 (define-instruction loop (segment target)
1954 (:printer short-jump ((op #b0010)))
1956 (emit-byte segment #b11100010) ; pfw this was 11100011, or jecxz!!!!
1957 (emit-byte-displacement-backpatch segment target)))
1959 (define-instruction loopz (segment target)
1960 (:printer short-jump ((op #b0001)))
1962 (emit-byte segment #b11100001)
1963 (emit-byte-displacement-backpatch segment target)))
1965 (define-instruction loopnz (segment target)
1966 (:printer short-jump ((op #b0000)))
1968 (emit-byte segment #b11100000)
1969 (emit-byte-displacement-backpatch segment target)))
1971 ;;;; conditional move
1972 (define-instruction cmov (segment cond dst src)
1973 (:printer cond-move ())
1975 (aver (register-p dst))
1976 (let ((size (matching-operand-size dst src)))
1977 (aver (or (eq size :word) (eq size :dword) (eq size :qword) ))
1978 (maybe-emit-operand-size-prefix segment size))
1979 (maybe-emit-rex-for-ea segment src dst)
1980 (emit-byte segment #b00001111)
1981 (emit-byte segment (dpb (conditional-opcode cond) (byte 4 0) #b01000000))
1982 (emit-ea segment src (reg-tn-encoding dst))))
1984 ;;;; conditional byte set
1986 (define-instruction set (segment dst cond)
1987 (:printer cond-set ())
1989 (maybe-emit-rex-for-ea segment dst nil)
1990 (emit-byte segment #b00001111)
1991 (emit-byte segment (dpb (conditional-opcode cond) (byte 4 0) #b10010000))
1992 (emit-ea segment dst #b000)))
1996 (define-instruction enter (segment disp &optional (level 0))
1997 (:declare (type (unsigned-byte 16) disp)
1998 (type (unsigned-byte 8) level))
1999 (:printer enter-format ((op #b11001000)))
2001 (emit-byte segment #b11001000)
2002 (emit-word segment disp)
2003 (emit-byte segment level)))
2005 (define-instruction leave (segment)
2006 (:printer byte ((op #b11001001)))
2008 (emit-byte segment #b11001001)))
2010 ;;;; interrupt instructions
2012 (defun snarf-error-junk (sap offset &optional length-only)
2013 (let* ((length (sb!sys:sap-ref-8 sap offset))
2014 (vector (make-array length :element-type '(unsigned-byte 8))))
2015 (declare (type sb!sys:system-area-pointer sap)
2016 (type (unsigned-byte 8) length)
2017 (type (simple-array (unsigned-byte 8) (*)) vector))
2019 (values 0 (1+ length) nil nil))
2021 (sb!kernel:copy-from-system-area sap (* n-byte-bits (1+ offset))
2022 vector (* n-word-bits
2024 (* length n-byte-bits))
2025 (collect ((sc-offsets)
2027 (lengths 1) ; the length byte
2029 (error-number (sb!c:read-var-integer vector index)))
2032 (when (>= index length)
2034 (let ((old-index index))
2035 (sc-offsets (sb!c:read-var-integer vector index))
2036 (lengths (- index old-index))))
2037 (values error-number
2043 (defmacro break-cases (breaknum &body cases)
2044 (let ((bn-temp (gensym)))
2045 (collect ((clauses))
2046 (dolist (case cases)
2047 (clauses `((= ,bn-temp ,(car case)) ,@(cdr case))))
2048 `(let ((,bn-temp ,breaknum))
2049 (cond ,@(clauses))))))
2052 (defun break-control (chunk inst stream dstate)
2053 (declare (ignore inst))
2054 (flet ((nt (x) (if stream (sb!disassem:note x dstate))))
2055 ;; FIXME: Make sure that BYTE-IMM-CODE is defined. The genesis
2056 ;; map has it undefined; and it should be easier to look in the target
2057 ;; Lisp (with (DESCRIBE 'BYTE-IMM-CODE)) than to definitively deduce
2058 ;; from first principles whether it's defined in some way that genesis
2060 (case (byte-imm-code chunk dstate)
2063 (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
2066 (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
2068 (nt "breakpoint trap"))
2069 (#.pending-interrupt-trap
2070 (nt "pending interrupt trap"))
2073 (#.fun-end-breakpoint-trap
2074 (nt "function end breakpoint trap")))))
2076 (define-instruction break (segment code)
2077 (:declare (type (unsigned-byte 8) code))
2078 (:printer byte-imm ((op #b11001100)) '(:name :tab code)
2079 :control #'break-control)
2081 (emit-byte segment #b11001100)
2082 (emit-byte segment code)))
2084 (define-instruction int (segment number)
2085 (:declare (type (unsigned-byte 8) number))
2086 (:printer byte-imm ((op #b11001101)))
2090 (emit-byte segment #b11001100))
2092 (emit-byte segment #b11001101)
2093 (emit-byte segment number)))))
2095 (define-instruction into (segment)
2096 (:printer byte ((op #b11001110)))
2098 (emit-byte segment #b11001110)))
2100 (define-instruction bound (segment reg bounds)
2102 (let ((size (matching-operand-size reg bounds)))
2103 (when (eq size :byte)
2104 (error "can't bounds-test bytes: ~S" reg))
2105 (maybe-emit-operand-size-prefix segment size)
2106 (maybe-emit-rex-for-ea segment bounds reg)
2107 (emit-byte segment #b01100010)
2108 (emit-ea segment bounds (reg-tn-encoding reg)))))
2110 (define-instruction iret (segment)
2111 (:printer byte ((op #b11001111)))
2113 (emit-byte segment #b11001111)))
2115 ;;;; processor control
2117 (define-instruction hlt (segment)
2118 (:printer byte ((op #b11110100)))
2120 (emit-byte segment #b11110100)))
2122 (define-instruction nop (segment)
2123 (:printer byte ((op #b10010000)))
2125 (emit-byte segment #b10010000)))
2127 (define-instruction wait (segment)
2128 (:printer byte ((op #b10011011)))
2130 (emit-byte segment #b10011011)))
2132 (define-instruction lock (segment)
2133 (:printer byte ((op #b11110000)))
2135 (emit-byte segment #b11110000)))
2137 ;;;; miscellaneous hackery
2139 (define-instruction byte (segment byte)
2141 (emit-byte segment byte)))
2143 (define-instruction word (segment word)
2145 (emit-word segment word)))
2147 (define-instruction dword (segment dword)
2149 (emit-dword segment dword)))
2151 (defun emit-header-data (segment type)
2152 (emit-back-patch segment
2154 (lambda (segment posn)
2158 (component-header-length))
2162 (define-instruction simple-fun-header-word (segment)
2164 (emit-header-data segment simple-fun-header-widetag)))
2166 (define-instruction lra-header-word (segment)
2168 (emit-header-data segment return-pc-header-widetag)))
2170 ;;;; fp instructions
2172 ;;;; Note: We treat the single-precision and double-precision variants
2173 ;;;; as separate instructions.
2175 ;;; Load single to st(0).
2176 (define-instruction fld (segment source)
2177 (:printer floating-point ((op '(#b001 #b000))))
2179 (and (not (fp-reg-tn-p source))
2180 (maybe-emit-rex-for-ea segment source nil))
2181 (emit-byte segment #b11011001)
2182 (emit-fp-op segment source #b000)))
2184 ;;; Load double to st(0).
2185 (define-instruction fldd (segment source)
2186 (:printer floating-point ((op '(#b101 #b000))))
2187 (:printer floating-point-fp ((op '(#b001 #b000))))
2189 (if (fp-reg-tn-p source)
2190 (emit-byte segment #b11011001)
2192 (maybe-emit-rex-for-ea segment source nil)
2193 (emit-byte segment #b11011101)))
2194 (emit-fp-op segment source #b000)))
2196 ;;; Load long to st(0).
2197 (define-instruction fldl (segment source)
2198 (:printer floating-point ((op '(#b011 #b101))))
2200 (and (not (fp-reg-tn-p source))
2201 (maybe-emit-rex-for-ea segment source nil))
2202 (emit-byte segment #b11011011)
2203 (emit-fp-op segment source #b101)))
2205 ;;; Store single from st(0).
2206 (define-instruction fst (segment dest)
2207 (:printer floating-point ((op '(#b001 #b010))))
2209 (cond ((fp-reg-tn-p dest)
2210 (emit-byte segment #b11011101)
2211 (emit-fp-op segment dest #b010))
2213 (maybe-emit-rex-for-ea segment dest nil)
2214 (emit-byte segment #b11011001)
2215 (emit-fp-op segment dest #b010)))))
2217 ;;; Store double from st(0).
2218 (define-instruction fstd (segment dest)
2219 (:printer floating-point ((op '(#b101 #b010))))
2220 (:printer floating-point-fp ((op '(#b101 #b010))))
2222 (cond ((fp-reg-tn-p dest)
2223 (emit-byte segment #b11011101)
2224 (emit-fp-op segment dest #b010))
2226 (maybe-emit-rex-for-ea segment dest nil)
2227 (emit-byte segment #b11011101)
2228 (emit-fp-op segment dest #b010)))))
2230 ;;; Arithmetic ops are all done with at least one operand at top of
2231 ;;; stack. The other operand is is another register or a 32/64 bit
2234 ;;; dtc: I've tried to follow the Intel ASM386 conventions, but note
2235 ;;; that these conflict with the Gdb conventions for binops. To reduce
2236 ;;; the confusion I've added comments showing the mathamatical
2237 ;;; operation and the two syntaxes. By the ASM386 convention the
2238 ;;; instruction syntax is:
2241 ;;; or Fop Destination, Source
2243 ;;; If only one operand is given then it is the source and the
2244 ;;; destination is ST(0). There are reversed forms of the fsub and
2245 ;;; fdiv instructions inducated by an 'R' suffix.
2247 ;;; The mathematical operation for the non-reverse form is always:
2248 ;;; destination = destination op source
2250 ;;; For the reversed form it is:
2251 ;;; destination = source op destination
2253 ;;; The instructions below only accept one operand at present which is
2254 ;;; usually the source. I've hack in extra instructions to implement
2255 ;;; the fops with a ST(i) destination, these have a -sti suffix and
2256 ;;; the operand is the destination with the source being ST(0).
2259 ;;; st(0) = st(0) + memory or st(i).
2260 (define-instruction fadd (segment source)
2261 (:printer floating-point ((op '(#b000 #b000))))
2263 (and (not (fp-reg-tn-p source))
2264 (maybe-emit-rex-for-ea segment source nil))
2265 (emit-byte segment #b11011000)
2266 (emit-fp-op segment source #b000)))
2269 ;;; st(0) = st(0) + memory or st(i).
2270 (define-instruction faddd (segment source)
2271 (:printer floating-point ((op '(#b100 #b000))))
2272 (:printer floating-point-fp ((op '(#b000 #b000))))
2274 (and (not (fp-reg-tn-p source))
2275 (maybe-emit-rex-for-ea segment source nil))
2276 (if (fp-reg-tn-p source)
2277 (emit-byte segment #b11011000)
2278 (emit-byte segment #b11011100))
2279 (emit-fp-op segment source #b000)))
2281 ;;; Add double destination st(i):
2282 ;;; st(i) = st(0) + st(i).
2283 (define-instruction fadd-sti (segment destination)
2284 (:printer floating-point-fp ((op '(#b100 #b000))))
2286 (aver (fp-reg-tn-p destination))
2287 (emit-byte segment #b11011100)
2288 (emit-fp-op segment destination #b000)))
2290 (define-instruction faddp-sti (segment destination)
2291 (:printer floating-point-fp ((op '(#b110 #b000))))
2293 (aver (fp-reg-tn-p destination))
2294 (emit-byte segment #b11011110)
2295 (emit-fp-op segment destination #b000)))
2297 ;;; Subtract single:
2298 ;;; st(0) = st(0) - memory or st(i).
2299 (define-instruction fsub (segment source)
2300 (:printer floating-point ((op '(#b000 #b100))))
2302 (and (not (fp-reg-tn-p source))
2303 (maybe-emit-rex-for-ea segment source nil))
2304 (emit-byte segment #b11011000)
2305 (emit-fp-op segment source #b100)))
2307 ;;; Subtract single, reverse:
2308 ;;; st(0) = memory or st(i) - st(0).
2309 (define-instruction fsubr (segment source)
2310 (:printer floating-point ((op '(#b000 #b101))))
2312 (and (not (fp-reg-tn-p source))
2313 (maybe-emit-rex-for-ea segment source nil))
2314 (emit-byte segment #b11011000)
2315 (emit-fp-op segment source #b101)))
2317 ;;; Subtract double:
2318 ;;; st(0) = st(0) - memory or st(i).
2319 (define-instruction fsubd (segment source)
2320 (:printer floating-point ((op '(#b100 #b100))))
2321 (:printer floating-point-fp ((op '(#b000 #b100))))
2323 (if (fp-reg-tn-p source)
2324 (emit-byte segment #b11011000)
2326 (and (not (fp-reg-tn-p source))
2327 (maybe-emit-rex-for-ea segment source nil))
2328 (emit-byte segment #b11011100)))
2329 (emit-fp-op segment source #b100)))
2331 ;;; Subtract double, reverse:
2332 ;;; st(0) = memory or st(i) - st(0).
2333 (define-instruction fsubrd (segment source)
2334 (:printer floating-point ((op '(#b100 #b101))))
2335 (:printer floating-point-fp ((op '(#b000 #b101))))
2337 (if (fp-reg-tn-p source)
2338 (emit-byte segment #b11011000)
2340 (and (not (fp-reg-tn-p source))
2341 (maybe-emit-rex-for-ea segment source nil))
2342 (emit-byte segment #b11011100)))
2343 (emit-fp-op segment source #b101)))
2345 ;;; Subtract double, destination st(i):
2346 ;;; st(i) = st(i) - st(0).
2348 ;;; ASM386 syntax: FSUB ST(i), ST
2349 ;;; Gdb syntax: fsubr %st,%st(i)
2350 (define-instruction fsub-sti (segment destination)
2351 (:printer floating-point-fp ((op '(#b100 #b101))))
2353 (aver (fp-reg-tn-p destination))
2354 (emit-byte segment #b11011100)
2355 (emit-fp-op segment destination #b101)))
2357 (define-instruction fsubp-sti (segment destination)
2358 (:printer floating-point-fp ((op '(#b110 #b101))))
2360 (aver (fp-reg-tn-p destination))
2361 (emit-byte segment #b11011110)
2362 (emit-fp-op segment destination #b101)))
2364 ;;; Subtract double, reverse, destination st(i):
2365 ;;; st(i) = st(0) - st(i).
2367 ;;; ASM386 syntax: FSUBR ST(i), ST
2368 ;;; Gdb syntax: fsub %st,%st(i)
2369 (define-instruction fsubr-sti (segment destination)
2370 (:printer floating-point-fp ((op '(#b100 #b100))))
2372 (aver (fp-reg-tn-p destination))
2373 (emit-byte segment #b11011100)
2374 (emit-fp-op segment destination #b100)))
2376 (define-instruction fsubrp-sti (segment destination)
2377 (:printer floating-point-fp ((op '(#b110 #b100))))
2379 (aver (fp-reg-tn-p destination))
2380 (emit-byte segment #b11011110)
2381 (emit-fp-op segment destination #b100)))
2383 ;;; Multiply single:
2384 ;;; st(0) = st(0) * memory or st(i).
2385 (define-instruction fmul (segment source)
2386 (:printer floating-point ((op '(#b000 #b001))))
2388 (and (not (fp-reg-tn-p source))
2389 (maybe-emit-rex-for-ea segment source nil))
2390 (emit-byte segment #b11011000)
2391 (emit-fp-op segment source #b001)))
2393 ;;; Multiply double:
2394 ;;; st(0) = st(0) * memory or st(i).
2395 (define-instruction fmuld (segment source)
2396 (:printer floating-point ((op '(#b100 #b001))))
2397 (:printer floating-point-fp ((op '(#b000 #b001))))
2399 (if (fp-reg-tn-p source)
2400 (emit-byte segment #b11011000)
2402 (and (not (fp-reg-tn-p source))
2403 (maybe-emit-rex-for-ea segment source nil))
2404 (emit-byte segment #b11011100)))
2405 (emit-fp-op segment source #b001)))
2407 ;;; Multiply double, destination st(i):
2408 ;;; st(i) = st(i) * st(0).
2409 (define-instruction fmul-sti (segment destination)
2410 (:printer floating-point-fp ((op '(#b100 #b001))))
2412 (aver (fp-reg-tn-p destination))
2413 (emit-byte segment #b11011100)
2414 (emit-fp-op segment destination #b001)))
2417 ;;; st(0) = st(0) / memory or st(i).
2418 (define-instruction fdiv (segment source)
2419 (:printer floating-point ((op '(#b000 #b110))))
2421 (and (not (fp-reg-tn-p source))
2422 (maybe-emit-rex-for-ea segment source nil))
2423 (emit-byte segment #b11011000)
2424 (emit-fp-op segment source #b110)))
2426 ;;; Divide single, reverse:
2427 ;;; st(0) = memory or st(i) / st(0).
2428 (define-instruction fdivr (segment source)
2429 (:printer floating-point ((op '(#b000 #b111))))
2431 (and (not (fp-reg-tn-p source))
2432 (maybe-emit-rex-for-ea segment source nil))
2433 (emit-byte segment #b11011000)
2434 (emit-fp-op segment source #b111)))
2437 ;;; st(0) = st(0) / memory or st(i).
2438 (define-instruction fdivd (segment source)
2439 (:printer floating-point ((op '(#b100 #b110))))
2440 (:printer floating-point-fp ((op '(#b000 #b110))))
2442 (if (fp-reg-tn-p source)
2443 (emit-byte segment #b11011000)
2445 (and (not (fp-reg-tn-p source))
2446 (maybe-emit-rex-for-ea segment source nil))
2447 (emit-byte segment #b11011100)))
2448 (emit-fp-op segment source #b110)))
2450 ;;; Divide double, reverse:
2451 ;;; st(0) = memory or st(i) / st(0).
2452 (define-instruction fdivrd (segment source)
2453 (:printer floating-point ((op '(#b100 #b111))))
2454 (:printer floating-point-fp ((op '(#b000 #b111))))
2456 (if (fp-reg-tn-p source)
2457 (emit-byte segment #b11011000)
2459 (and (not (fp-reg-tn-p source))
2460 (maybe-emit-rex-for-ea segment source nil))
2461 (emit-byte segment #b11011100)))
2462 (emit-fp-op segment source #b111)))
2464 ;;; Divide double, destination st(i):
2465 ;;; st(i) = st(i) / st(0).
2467 ;;; ASM386 syntax: FDIV ST(i), ST
2468 ;;; Gdb syntax: fdivr %st,%st(i)
2469 (define-instruction fdiv-sti (segment destination)
2470 (:printer floating-point-fp ((op '(#b100 #b111))))
2472 (aver (fp-reg-tn-p destination))
2473 (emit-byte segment #b11011100)
2474 (emit-fp-op segment destination #b111)))
2476 ;;; Divide double, reverse, destination st(i):
2477 ;;; st(i) = st(0) / st(i).
2479 ;;; ASM386 syntax: FDIVR ST(i), ST
2480 ;;; Gdb syntax: fdiv %st,%st(i)
2481 (define-instruction fdivr-sti (segment destination)
2482 (:printer floating-point-fp ((op '(#b100 #b110))))
2484 (aver (fp-reg-tn-p destination))
2485 (emit-byte segment #b11011100)
2486 (emit-fp-op segment destination #b110)))
2488 ;;; Exchange fr0 with fr(n). (There is no double precision variant.)
2489 (define-instruction fxch (segment source)
2490 (:printer floating-point-fp ((op '(#b001 #b001))))
2492 (unless (and (tn-p source)
2493 (eq (sb-name (sc-sb (tn-sc source))) 'float-registers))
2495 (emit-byte segment #b11011001)
2496 (emit-fp-op segment source #b001)))
2498 ;;; Push 32-bit integer to st0.
2499 (define-instruction fild (segment source)
2500 (:printer floating-point ((op '(#b011 #b000))))
2502 (and (not (fp-reg-tn-p source))
2503 (maybe-emit-rex-for-ea segment source nil))
2504 (emit-byte segment #b11011011)
2505 (emit-fp-op segment source #b000)))
2507 ;;; Push 64-bit integer to st0.
2508 (define-instruction fildl (segment source)
2509 (:printer floating-point ((op '(#b111 #b101))))
2511 (and (not (fp-reg-tn-p source))
2512 (maybe-emit-rex-for-ea segment source nil))
2513 (emit-byte segment #b11011111)
2514 (emit-fp-op segment source #b101)))
2516 ;;; Store 32-bit integer.
2517 (define-instruction fist (segment dest)
2518 (:printer floating-point ((op '(#b011 #b010))))
2520 (and (not (fp-reg-tn-p dest))
2521 (maybe-emit-rex-for-ea segment dest nil))
2522 (emit-byte segment #b11011011)
2523 (emit-fp-op segment dest #b010)))
2525 ;;; Store and pop 32-bit integer.
2526 (define-instruction fistp (segment dest)
2527 (:printer floating-point ((op '(#b011 #b011))))
2529 (and (not (fp-reg-tn-p dest))
2530 (maybe-emit-rex-for-ea segment dest nil))
2531 (emit-byte segment #b11011011)
2532 (emit-fp-op segment dest #b011)))
2534 ;;; Store and pop 64-bit integer.
2535 (define-instruction fistpl (segment dest)
2536 (:printer floating-point ((op '(#b111 #b111))))
2538 (and (not (fp-reg-tn-p dest))
2539 (maybe-emit-rex-for-ea segment dest nil))
2540 (emit-byte segment #b11011111)
2541 (emit-fp-op segment dest #b111)))
2543 ;;; Store single from st(0) and pop.
2544 (define-instruction fstp (segment dest)
2545 (:printer floating-point ((op '(#b001 #b011))))
2547 (cond ((fp-reg-tn-p dest)
2548 (emit-byte segment #b11011101)
2549 (emit-fp-op segment dest #b011))
2551 (maybe-emit-rex-for-ea segment dest nil)
2552 (emit-byte segment #b11011001)
2553 (emit-fp-op segment dest #b011)))))
2555 ;;; Store double from st(0) and pop.
2556 (define-instruction fstpd (segment dest)
2557 (:printer floating-point ((op '(#b101 #b011))))
2558 (:printer floating-point-fp ((op '(#b101 #b011))))
2560 (cond ((fp-reg-tn-p dest)
2561 (emit-byte segment #b11011101)
2562 (emit-fp-op segment dest #b011))
2564 (maybe-emit-rex-for-ea segment dest nil)
2565 (emit-byte segment #b11011101)
2566 (emit-fp-op segment dest #b011)))))
2568 ;;; Store long from st(0) and pop.
2569 (define-instruction fstpl (segment dest)
2570 (:printer floating-point ((op '(#b011 #b111))))
2572 (and (not (fp-reg-tn-p dest))
2573 (maybe-emit-rex-for-ea segment dest nil))
2574 (emit-byte segment #b11011011)
2575 (emit-fp-op segment dest #b111)))
2577 ;;; Decrement stack-top pointer.
2578 (define-instruction fdecstp (segment)
2579 (:printer floating-point-no ((op #b10110)))
2581 (emit-byte segment #b11011001)
2582 (emit-byte segment #b11110110)))
2584 ;;; Increment stack-top pointer.
2585 (define-instruction fincstp (segment)
2586 (:printer floating-point-no ((op #b10111)))
2588 (emit-byte segment #b11011001)
2589 (emit-byte segment #b11110111)))
2591 ;;; Free fp register.
2592 (define-instruction ffree (segment dest)
2593 (:printer floating-point-fp ((op '(#b101 #b000))))
2595 (and (not (fp-reg-tn-p dest))
2596 (maybe-emit-rex-for-ea segment dest nil))
2597 (emit-byte segment #b11011101)
2598 (emit-fp-op segment dest #b000)))
2600 (define-instruction fabs (segment)
2601 (:printer floating-point-no ((op #b00001)))
2603 (emit-byte segment #b11011001)
2604 (emit-byte segment #b11100001)))
2606 (define-instruction fchs (segment)
2607 (:printer floating-point-no ((op #b00000)))
2609 (emit-byte segment #b11011001)
2610 (emit-byte segment #b11100000)))
2612 (define-instruction frndint(segment)
2613 (:printer floating-point-no ((op #b11100)))
2615 (emit-byte segment #b11011001)
2616 (emit-byte segment #b11111100)))
2619 (define-instruction fninit(segment)
2620 (:printer floating-point-5 ((op #b00011)))
2622 (emit-byte segment #b11011011)
2623 (emit-byte segment #b11100011)))
2625 ;;; Store Status Word to AX.
2626 (define-instruction fnstsw(segment)
2627 (:printer floating-point-st ((op #b00000)))
2629 (emit-byte segment #b11011111)
2630 (emit-byte segment #b11100000)))
2632 ;;; Load Control Word.
2634 ;;; src must be a memory location
2635 (define-instruction fldcw(segment src)
2636 (:printer floating-point ((op '(#b001 #b101))))
2638 (and (not (fp-reg-tn-p src))
2639 (maybe-emit-rex-for-ea segment src nil))
2640 (emit-byte segment #b11011001)
2641 (emit-fp-op segment src #b101)))
2643 ;;; Store Control Word.
2644 (define-instruction fnstcw(segment dst)
2645 (:printer floating-point ((op '(#b001 #b111))))
2647 (and (not (fp-reg-tn-p dst))
2648 (maybe-emit-rex-for-ea segment dst nil))
2649 (emit-byte segment #b11011001)
2650 (emit-fp-op segment dst #b111)))
2652 ;;; Store FP Environment.
2653 (define-instruction fstenv(segment dst)
2654 (:printer floating-point ((op '(#b001 #b110))))
2656 (and (not (fp-reg-tn-p dst))
2657 (maybe-emit-rex-for-ea segment dst nil))
2658 (emit-byte segment #b11011001)
2659 (emit-fp-op segment dst #b110)))
2661 ;;; Restore FP Environment.
2662 (define-instruction fldenv(segment src)
2663 (:printer floating-point ((op '(#b001 #b100))))
2665 (and (not (fp-reg-tn-p src))
2666 (maybe-emit-rex-for-ea segment src nil))
2667 (emit-byte segment #b11011001)
2668 (emit-fp-op segment src #b100)))
2671 (define-instruction fsave(segment dst)
2672 (:printer floating-point ((op '(#b101 #b110))))
2674 (and (not (fp-reg-tn-p dst))
2675 (maybe-emit-rex-for-ea segment dst nil))
2676 (emit-byte segment #b11011101)
2677 (emit-fp-op segment dst #b110)))
2679 ;;; Restore FP State.
2680 (define-instruction frstor(segment src)
2681 (:printer floating-point ((op '(#b101 #b100))))
2683 (and (not (fp-reg-tn-p src))
2684 (maybe-emit-rex-for-ea segment src nil))
2685 (emit-byte segment #b11011101)
2686 (emit-fp-op segment src #b100)))
2688 ;;; Clear exceptions.
2689 (define-instruction fnclex(segment)
2690 (:printer floating-point-5 ((op #b00010)))
2692 (emit-byte segment #b11011011)
2693 (emit-byte segment #b11100010)))
2696 (define-instruction fcom (segment src)
2697 (:printer floating-point ((op '(#b000 #b010))))
2699 (and (not (fp-reg-tn-p src))
2700 (maybe-emit-rex-for-ea segment src nil))
2701 (emit-byte segment #b11011000)
2702 (emit-fp-op segment src #b010)))
2704 (define-instruction fcomd (segment src)
2705 (:printer floating-point ((op '(#b100 #b010))))
2706 (:printer floating-point-fp ((op '(#b000 #b010))))
2708 (if (fp-reg-tn-p src)
2709 (emit-byte segment #b11011000)
2711 (maybe-emit-rex-for-ea segment src nil)
2712 (emit-byte segment #b11011100)))
2713 (emit-fp-op segment src #b010)))
2715 ;;; Compare ST1 to ST0, popping the stack twice.
2716 (define-instruction fcompp (segment)
2717 (:printer floating-point-3 ((op '(#b110 #b011001))))
2719 (emit-byte segment #b11011110)
2720 (emit-byte segment #b11011001)))
2722 ;;; unordered comparison
2723 (define-instruction fucom (segment src)
2724 (:printer floating-point-fp ((op '(#b101 #b100))))
2726 (aver (fp-reg-tn-p src))
2727 (emit-byte segment #b11011101)
2728 (emit-fp-op segment src #b100)))
2730 (define-instruction ftst (segment)
2731 (:printer floating-point-no ((op #b00100)))
2733 (emit-byte segment #b11011001)
2734 (emit-byte segment #b11100100)))
2738 (define-instruction fsqrt(segment)
2739 (:printer floating-point-no ((op #b11010)))
2741 (emit-byte segment #b11011001)
2742 (emit-byte segment #b11111010)))
2744 (define-instruction fscale(segment)
2745 (:printer floating-point-no ((op #b11101)))
2747 (emit-byte segment #b11011001)
2748 (emit-byte segment #b11111101)))
2750 (define-instruction fxtract(segment)
2751 (:printer floating-point-no ((op #b10100)))
2753 (emit-byte segment #b11011001)
2754 (emit-byte segment #b11110100)))
2756 (define-instruction fsin(segment)
2757 (:printer floating-point-no ((op #b11110)))
2759 (emit-byte segment #b11011001)
2760 (emit-byte segment #b11111110)))
2762 (define-instruction fcos(segment)
2763 (:printer floating-point-no ((op #b11111)))
2765 (emit-byte segment #b11011001)
2766 (emit-byte segment #b11111111)))
2768 (define-instruction fprem1(segment)
2769 (:printer floating-point-no ((op #b10101)))
2771 (emit-byte segment #b11011001)
2772 (emit-byte segment #b11110101)))
2774 (define-instruction fprem(segment)
2775 (:printer floating-point-no ((op #b11000)))
2777 (emit-byte segment #b11011001)
2778 (emit-byte segment #b11111000)))
2780 (define-instruction fxam (segment)
2781 (:printer floating-point-no ((op #b00101)))
2783 (emit-byte segment #b11011001)
2784 (emit-byte segment #b11100101)))
2786 ;;; These do push/pop to stack and need special handling
2787 ;;; in any VOPs that use them. See the book.
2789 ;;; st0 <- st1*log2(st0)
2790 (define-instruction fyl2x(segment) ; pops stack
2791 (:printer floating-point-no ((op #b10001)))
2793 (emit-byte segment #b11011001)
2794 (emit-byte segment #b11110001)))
2796 (define-instruction fyl2xp1(segment)
2797 (:printer floating-point-no ((op #b11001)))
2799 (emit-byte segment #b11011001)
2800 (emit-byte segment #b11111001)))
2802 (define-instruction f2xm1(segment)
2803 (:printer floating-point-no ((op #b10000)))
2805 (emit-byte segment #b11011001)
2806 (emit-byte segment #b11110000)))
2808 (define-instruction fptan(segment) ; st(0) <- 1; st(1) <- tan
2809 (:printer floating-point-no ((op #b10010)))
2811 (emit-byte segment #b11011001)
2812 (emit-byte segment #b11110010)))
2814 (define-instruction fpatan(segment) ; POPS STACK
2815 (:printer floating-point-no ((op #b10011)))
2817 (emit-byte segment #b11011001)
2818 (emit-byte segment #b11110011)))
2820 ;;;; loading constants
2822 (define-instruction fldz(segment)
2823 (:printer floating-point-no ((op #b01110)))
2825 (emit-byte segment #b11011001)
2826 (emit-byte segment #b11101110)))
2828 (define-instruction fld1(segment)
2829 (:printer floating-point-no ((op #b01000)))
2831 (emit-byte segment #b11011001)
2832 (emit-byte segment #b11101000)))
2834 (define-instruction fldpi(segment)
2835 (:printer floating-point-no ((op #b01011)))
2837 (emit-byte segment #b11011001)
2838 (emit-byte segment #b11101011)))
2840 (define-instruction fldl2t(segment)
2841 (:printer floating-point-no ((op #b01001)))
2843 (emit-byte segment #b11011001)
2844 (emit-byte segment #b11101001)))
2846 (define-instruction fldl2e(segment)
2847 (:printer floating-point-no ((op #b01010)))
2849 (emit-byte segment #b11011001)
2850 (emit-byte segment #b11101010)))
2852 (define-instruction fldlg2(segment)
2853 (:printer floating-point-no ((op #b01100)))
2855 (emit-byte segment #b11011001)
2856 (emit-byte segment #b11101100)))
2858 (define-instruction fldln2(segment)
2859 (:printer floating-point-no ((op #b01101)))
2861 (emit-byte segment #b11011001)
2862 (emit-byte segment #b11101101)))