759a8fb68d85558de05273c11704b04db2ddca72
[sbcl.git] / src / compiler / x86 / insts.lisp
1 ;;;; that part of the description of the x86 instruction set (for
2 ;;;; 80386 and above) which can live on the cross-compilation host
3
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
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.
12
13 (in-package "SB!VM")
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.
17
18 ;;; Note: In CMU CL, this used to be a call to SET-DISASSEM-PARAMS.
19 (setf sb!disassem:*disassem-inst-alignment-bytes* 1)
20
21 (deftype reg () '(unsigned-byte 3))
22
23 (def!constant +default-operand-size+ :dword)
24 \f
25 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
26
27 (defun offset-next (value dstate)
28   (declare (type integer value)
29            (type sb!disassem:disassem-state dstate))
30   (+ (sb!disassem:dstate-next-addr dstate) value))
31
32 (defparameter *default-address-size*
33   ;; Actually, :DWORD is the only one really supported.
34   :dword)
35
36 (defparameter *byte-reg-names*
37   #(al cl dl bl ah ch dh bh))
38 (defparameter *word-reg-names*
39   #(ax cx dx bx sp bp si di))
40 (defparameter *dword-reg-names*
41   #(eax ecx edx ebx esp ebp esi edi))
42
43 (defun print-reg-with-width (value width stream dstate)
44   (declare (ignore dstate))
45   (princ (aref (ecase width
46                  (:byte *byte-reg-names*)
47                  (:word *word-reg-names*)
48                  (:dword *dword-reg-names*))
49                value)
50          stream)
51   ;; XXX plus should do some source-var notes
52   )
53
54 (defun print-reg (value stream dstate)
55   (declare (type reg value)
56            (type stream stream)
57            (type sb!disassem:disassem-state dstate))
58   (print-reg-with-width value
59                         (sb!disassem:dstate-get-prop dstate 'width)
60                         stream
61                         dstate))
62
63 (defun print-word-reg (value stream dstate)
64   (declare (type reg value)
65            (type stream stream)
66            (type sb!disassem:disassem-state dstate))
67   (print-reg-with-width value
68                         (or (sb!disassem:dstate-get-prop dstate 'word-width)
69                             +default-operand-size+)
70                         stream
71                         dstate))
72
73 (defun print-byte-reg (value stream dstate)
74   (declare (type reg value)
75            (type stream stream)
76            (type sb!disassem:disassem-state dstate))
77   (print-reg-with-width value :byte stream dstate))
78
79 (defun print-addr-reg (value stream dstate)
80   (declare (type reg value)
81            (type stream stream)
82            (type sb!disassem:disassem-state dstate))
83   (print-reg-with-width value *default-address-size* stream dstate))
84
85 (defun print-reg/mem (value stream dstate)
86   (declare (type (or list reg) value)
87            (type stream stream)
88            (type sb!disassem:disassem-state dstate))
89   (if (typep value 'reg)
90       (print-reg value stream dstate)
91       (print-mem-access value stream nil dstate)))
92
93 ;; Same as print-reg/mem, but prints an explicit size indicator for
94 ;; memory references.
95 (defun print-sized-reg/mem (value stream dstate)
96   (declare (type (or list reg) value)
97            (type stream stream)
98            (type sb!disassem:disassem-state dstate))
99   (if (typep value 'reg)
100       (print-reg value stream dstate)
101       (print-mem-access value stream t dstate)))
102
103 (defun print-byte-reg/mem (value stream dstate)
104   (declare (type (or list reg) value)
105            (type stream stream)
106            (type sb!disassem:disassem-state dstate))
107   (if (typep value 'reg)
108       (print-byte-reg value stream dstate)
109       (print-mem-access value stream t dstate)))
110
111 (defun print-label (value stream dstate)
112   (declare (ignore dstate))
113   (sb!disassem:princ16 value stream))
114
115 ;;; Returns either an integer, meaning a register, or a list of
116 ;;; (BASE-REG OFFSET INDEX-REG INDEX-SCALE), where any component
117 ;;; may be missing or nil to indicate that it's not used or has the
118 ;;; obvious default value (e.g., 1 for the index-scale).
119 (defun prefilter-reg/mem (value dstate)
120   (declare (type list value)
121            (type sb!disassem:disassem-state dstate))
122   (let ((mod (car value))
123         (r/m (cadr value)))
124     (declare (type (unsigned-byte 2) mod)
125              (type (unsigned-byte 3) r/m))
126     (cond ((= mod #b11)
127            ;; registers
128            r/m)
129           ((= r/m #b100)
130            ;; sib byte
131            (let ((sib (sb!disassem:read-suffix 8 dstate)))
132              (declare (type (unsigned-byte 8) sib))
133              (let ((base-reg (ldb (byte 3 0) sib))
134                    (index-reg (ldb (byte 3 3) sib))
135                    (index-scale (ldb (byte 2 6) sib)))
136                (declare (type (unsigned-byte 3) base-reg index-reg)
137                         (type (unsigned-byte 2) index-scale))
138                (let* ((offset
139                        (case mod
140                          (#b00
141                           (if (= base-reg #b101)
142                               (sb!disassem:read-signed-suffix 32 dstate)
143                               nil))
144                          (#b01
145                           (sb!disassem:read-signed-suffix 8 dstate))
146                          (#b10
147                           (sb!disassem:read-signed-suffix 32 dstate)))))
148                  (list (if (and (= mod #b00) (= base-reg #b101)) nil base-reg)
149                        offset
150                        (if (= index-reg #b100) nil index-reg)
151                        (ash 1 index-scale))))))
152           ((and (= mod #b00) (= r/m #b101))
153            (list nil (sb!disassem:read-signed-suffix 32 dstate)) )
154           ((= mod #b00)
155            (list r/m))
156           ((= mod #b01)
157            (list r/m (sb!disassem:read-signed-suffix 8 dstate)))
158           (t                            ; (= mod #b10)
159            (list r/m (sb!disassem:read-signed-suffix 32 dstate))))))
160
161
162 ;;; This is a sort of bogus prefilter that just stores the info globally for
163 ;;; other people to use; it probably never gets printed.
164 (defun prefilter-width (value dstate)
165   (setf (sb!disassem:dstate-get-prop dstate 'width)
166         (if (zerop value)
167             :byte
168             (let ((word-width
169                    ;; set by a prefix instruction
170                    (or (sb!disassem:dstate-get-prop dstate 'word-width)
171                        +default-operand-size+)))
172               (when (not (eql word-width +default-operand-size+))
173                 ;; Reset it.
174                 (setf (sb!disassem:dstate-get-prop dstate 'word-width)
175                       +default-operand-size+))
176               word-width))))
177
178 (defun read-address (value dstate)
179   (declare (ignore value))              ; always nil anyway
180   (sb!disassem:read-suffix (width-bits *default-address-size*) dstate))
181
182 (defun width-bits (width)
183   (ecase width
184     (:byte 8)
185     (:word 16)
186     (:dword 32)
187     (:float 32)
188     (:double 64)))
189
190 ) ; EVAL-WHEN
191 \f
192 ;;;; disassembler argument types
193
194 (sb!disassem:define-arg-type displacement
195   :sign-extend t
196   :use-label #'offset-next
197   :printer (lambda (value stream dstate)
198              (sb!disassem:maybe-note-assembler-routine value nil dstate)
199              (print-label value stream dstate)))
200
201 (sb!disassem:define-arg-type accum
202   :printer (lambda (value stream dstate)
203              (declare (ignore value)
204                       (type stream stream)
205                       (type sb!disassem:disassem-state dstate))
206              (print-reg 0 stream dstate)))
207
208 (sb!disassem:define-arg-type word-accum
209   :printer (lambda (value stream dstate)
210              (declare (ignore value)
211                       (type stream stream)
212                       (type sb!disassem:disassem-state dstate))
213              (print-word-reg 0 stream dstate)))
214
215 (sb!disassem:define-arg-type reg
216   :printer #'print-reg)
217
218 (sb!disassem:define-arg-type addr-reg
219   :printer #'print-addr-reg)
220
221 (sb!disassem:define-arg-type word-reg
222   :printer #'print-word-reg)
223
224 (sb!disassem:define-arg-type imm-addr
225   :prefilter #'read-address
226   :printer #'print-label)
227
228 (sb!disassem:define-arg-type imm-data
229   :prefilter (lambda (value dstate)
230                (declare (ignore value)) ; always nil anyway
231                (sb!disassem:read-suffix
232                 (width-bits (sb!disassem:dstate-get-prop dstate 'width))
233                 dstate)))
234
235 (sb!disassem:define-arg-type signed-imm-data
236   :prefilter (lambda (value dstate)
237                (declare (ignore value)) ; always nil anyway
238                (let ((width (sb!disassem:dstate-get-prop dstate 'width)))
239                  (sb!disassem:read-signed-suffix (width-bits width) dstate))))
240
241 (sb!disassem:define-arg-type signed-imm-byte
242   :prefilter (lambda (value dstate)
243                (declare (ignore value)) ; always nil anyway
244                (sb!disassem:read-signed-suffix 8 dstate)))
245
246 (sb!disassem:define-arg-type signed-imm-dword
247   :prefilter (lambda (value dstate)
248                (declare (ignore value)) ; always nil anyway
249                (sb!disassem:read-signed-suffix 32 dstate)))
250
251 (sb!disassem:define-arg-type imm-word
252   :prefilter (lambda (value dstate)
253                (declare (ignore value)) ; always nil anyway
254                (let ((width
255                       (or (sb!disassem:dstate-get-prop dstate 'word-width)
256                           +default-operand-size+)))
257                  (sb!disassem:read-suffix (width-bits width) dstate))))
258
259 ;;; needed for the ret imm16 instruction
260 (sb!disassem:define-arg-type imm-word-16
261   :prefilter (lambda (value dstate)
262                (declare (ignore value)) ; always nil anyway
263                (sb!disassem:read-suffix 16 dstate)))
264
265 (sb!disassem:define-arg-type reg/mem
266   :prefilter #'prefilter-reg/mem
267   :printer #'print-reg/mem)
268 (sb!disassem:define-arg-type sized-reg/mem
269   ;; Same as reg/mem, but prints an explicit size indicator for
270   ;; memory references.
271   :prefilter #'prefilter-reg/mem
272   :printer #'print-sized-reg/mem)
273 (sb!disassem:define-arg-type byte-reg/mem
274   :prefilter #'prefilter-reg/mem
275   :printer #'print-byte-reg/mem)
276
277 ;;; added by jrd
278 (eval-when (:compile-toplevel :load-toplevel :execute)
279 (defun print-fp-reg (value stream dstate)
280   (declare (ignore dstate))
281   (format stream "FR~D" value))
282 (defun prefilter-fp-reg (value dstate)
283   ;; just return it
284   (declare (ignore dstate))
285   value)
286 ) ; EVAL-WHEN
287 (sb!disassem:define-arg-type fp-reg
288                              :prefilter #'prefilter-fp-reg
289                              :printer #'print-fp-reg)
290
291 (sb!disassem:define-arg-type width
292   :prefilter #'prefilter-width
293   :printer (lambda (value stream dstate)
294              (if;; (zerop value)
295                  (or (null value)
296                      (and (numberp value) (zerop value))) ; zzz jrd
297                  (princ 'b stream)
298                  (let ((word-width
299                         ;; set by a prefix instruction
300                         (or (sb!disassem:dstate-get-prop dstate 'word-width)
301                             +default-operand-size+)))
302                    (princ (schar (symbol-name word-width) 0) stream)))))
303
304 (eval-when (:compile-toplevel :load-toplevel :execute)
305 (defparameter *conditions*
306   '((:o . 0)
307     (:no . 1)
308     (:b . 2) (:nae . 2) (:c . 2)
309     (:nb . 3) (:ae . 3) (:nc . 3)
310     (:eq . 4) (:e . 4) (:z . 4)
311     (:ne . 5) (:nz . 5)
312     (:be . 6) (:na . 6)
313     (:nbe . 7) (:a . 7)
314     (:s . 8)
315     (:ns . 9)
316     (:p . 10) (:pe . 10)
317     (:np . 11) (:po . 11)
318     (:l . 12) (:nge . 12)
319     (:nl . 13) (:ge . 13)
320     (:le . 14) (:ng . 14)
321     (:nle . 15) (:g . 15)))
322 (defparameter *condition-name-vec*
323   (let ((vec (make-array 16 :initial-element nil)))
324     (dolist (cond *conditions*)
325       (when (null (aref vec (cdr cond)))
326         (setf (aref vec (cdr cond)) (car cond))))
327     vec))
328 ) ; EVAL-WHEN
329
330 ;;; Set assembler parameters. (In CMU CL, this was done with
331 ;;; a call to a macro DEF-ASSEMBLER-PARAMS.)
332 (eval-when (:compile-toplevel :load-toplevel :execute)
333   (setf sb!assem:*assem-scheduler-p* nil))
334
335 (sb!disassem:define-arg-type condition-code
336   :printer *condition-name-vec*)
337
338 (defun conditional-opcode (condition)
339   (cdr (assoc condition *conditions* :test #'eq)))
340 \f
341 ;;;; disassembler instruction formats
342
343 (eval-when (:compile-toplevel :execute)
344   (defun swap-if (direction field1 separator field2)
345     `(:if (,direction :constant 0)
346           (,field1 ,separator ,field2)
347           (,field2 ,separator ,field1))))
348
349 (sb!disassem:define-instruction-format (byte 8 :default-printer '(:name))
350   (op    :field (byte 8 0))
351   ;; optional fields
352   (accum :type 'accum)
353   (imm))
354
355 (sb!disassem:define-instruction-format (simple 8)
356   (op    :field (byte 7 1))
357   (width :field (byte 1 0) :type 'width)
358   ;; optional fields
359   (accum :type 'accum)
360   (imm))
361
362 ;;; Same as simple, but with direction bit
363 (sb!disassem:define-instruction-format (simple-dir 8 :include 'simple)
364   (op :field (byte 6 2))
365   (dir :field (byte 1 1)))
366
367 ;;; Same as simple, but with the immediate value occurring by default,
368 ;;; and with an appropiate printer.
369 (sb!disassem:define-instruction-format (accum-imm 8
370                                      :include 'simple
371                                      :default-printer '(:name
372                                                         :tab accum ", " imm))
373   (imm :type 'imm-data))
374
375 (sb!disassem:define-instruction-format (reg-no-width 8
376                                      :default-printer '(:name :tab reg))
377   (op    :field (byte 5 3))
378   (reg   :field (byte 3 0) :type 'word-reg)
379   ;; optional fields
380   (accum :type 'word-accum)
381   (imm))
382
383 ;;; adds a width field to reg-no-width
384 (sb!disassem:define-instruction-format (reg 8
385                                         :default-printer '(:name :tab reg))
386   (op    :field (byte 4 4))
387   (width :field (byte 1 3) :type 'width)
388   (reg   :field (byte 3 0) :type 'reg)
389   ;; optional fields
390   (accum :type 'accum)
391   (imm)
392   )
393
394 ;;; Same as reg, but with direction bit
395 (sb!disassem:define-instruction-format (reg-dir 8 :include 'reg)
396   (op  :field (byte 3 5))
397   (dir :field (byte 1 4)))
398
399 (sb!disassem:define-instruction-format (two-bytes 16
400                                         :default-printer '(:name))
401   (op :fields (list (byte 8 0) (byte 8 8))))
402
403 (sb!disassem:define-instruction-format (reg-reg/mem 16
404                                         :default-printer
405                                         `(:name :tab reg ", " reg/mem))
406   (op      :field (byte 7 1))
407   (width   :field (byte 1 0)    :type 'width)
408   (reg/mem :fields (list (byte 2 14) (byte 3 8))
409                                 :type 'reg/mem)
410   (reg     :field (byte 3 11)   :type 'reg)
411   ;; optional fields
412   (imm))
413
414 ;;; same as reg-reg/mem, but with direction bit
415 (sb!disassem:define-instruction-format (reg-reg/mem-dir 16
416                                         :include 'reg-reg/mem
417                                         :default-printer
418                                         `(:name
419                                           :tab
420                                           ,(swap-if 'dir 'reg/mem ", " 'reg)))
421   (op  :field (byte 6 2))
422   (dir :field (byte 1 1)))
423
424 ;;; Same as reg-rem/mem, but uses the reg field as a second op code.
425 (sb!disassem:define-instruction-format (reg/mem 16
426                                         :default-printer '(:name :tab reg/mem))
427   (op      :fields (list (byte 7 1) (byte 3 11)))
428   (width   :field (byte 1 0)    :type 'width)
429   (reg/mem :fields (list (byte 2 14) (byte 3 8))
430                                 :type 'sized-reg/mem)
431   ;; optional fields
432   (imm))
433
434 ;;; Same as reg/mem, but with the immediate value occurring by default,
435 ;;; and with an appropiate printer.
436 (sb!disassem:define-instruction-format (reg/mem-imm 16
437                                         :include 'reg/mem
438                                         :default-printer
439                                         '(:name :tab reg/mem ", " imm))
440   (reg/mem :type 'sized-reg/mem)
441   (imm     :type 'imm-data))
442
443 ;;; Same as reg/mem, but with using the accumulator in the default printer
444 (sb!disassem:define-instruction-format
445     (accum-reg/mem 16
446      :include 'reg/mem :default-printer '(:name :tab accum ", " reg/mem))
447   (reg/mem :type 'reg/mem)              ; don't need a size
448   (accum :type 'accum))
449
450 ;;; Same as reg-reg/mem, but with a prefix of #b00001111
451 (sb!disassem:define-instruction-format (ext-reg-reg/mem 24
452                                         :default-printer
453                                         `(:name :tab reg ", " reg/mem))
454   (prefix  :field (byte 8 0)    :value #b00001111)
455   (op      :field (byte 7 9))
456   (width   :field (byte 1 8)    :type 'width)
457   (reg/mem :fields (list (byte 2 22) (byte 3 16))
458                                 :type 'reg/mem)
459   (reg     :field (byte 3 19)   :type 'reg)
460   ;; optional fields
461   (imm))
462
463 ;;; Same as reg/mem, but with a prefix of #b00001111
464 (sb!disassem:define-instruction-format (ext-reg/mem 24
465                                         :default-printer '(:name :tab reg/mem))
466   (prefix  :field (byte 8 0)    :value #b00001111)
467   (op      :fields (list (byte 7 9) (byte 3 19)))
468   (width   :field (byte 1 8)    :type 'width)
469   (reg/mem :fields (list (byte 2 22) (byte 3 16))
470                                 :type 'sized-reg/mem)
471   ;; optional fields
472   (imm))
473 \f
474 ;;;; This section was added by jrd, for fp instructions.
475
476 ;;; regular fp inst to/from registers/memory
477 (sb!disassem:define-instruction-format (floating-point 16
478                                         :default-printer
479                                         `(:name :tab reg/mem))
480   (prefix :field (byte 5 3) :value #b11011)
481   (op     :fields (list (byte 3 0) (byte 3 11)))
482   (reg/mem :fields (list (byte 2 14) (byte 3 8)) :type 'reg/mem))
483
484 ;;; fp insn to/from fp reg
485 (sb!disassem:define-instruction-format (floating-point-fp 16
486                                         :default-printer `(:name :tab fp-reg))
487   (prefix :field (byte 5 3) :value #b11011)
488   (suffix :field (byte 2 14) :value #b11)
489   (op     :fields (list (byte 3 0) (byte 3 11)))
490   (fp-reg :field (byte 3 8) :type 'fp-reg))
491
492 ;;; fp insn to/from fp reg, with the reversed source/destination flag.
493 (sb!disassem:define-instruction-format
494  (floating-point-fp-d 16
495    :default-printer `(:name :tab ,(swap-if 'd "ST0" ", " 'fp-reg)))
496   (prefix :field (byte 5 3) :value #b11011)
497   (suffix :field (byte 2 14) :value #b11)
498   (op     :fields (list (byte 2 0) (byte 3 11)))
499   (d      :field (byte 1 2))
500   (fp-reg :field (byte 3 8) :type 'fp-reg))
501
502
503 ;;; (added by (?) pfw)
504 ;;; fp no operand isns
505 (sb!disassem:define-instruction-format (floating-point-no 16
506                                       :default-printer '(:name))
507   (prefix :field (byte 8  0) :value #b11011001)
508   (suffix :field (byte 3 13) :value #b111)
509   (op     :field (byte 5  8)))
510
511 (sb!disassem:define-instruction-format (floating-point-3 16
512                                       :default-printer '(:name))
513   (prefix :field (byte 5 3) :value #b11011)
514   (suffix :field (byte 2 14) :value #b11)
515   (op     :fields (list (byte 3 0) (byte 6 8))))
516
517 (sb!disassem:define-instruction-format (floating-point-5 16
518                                       :default-printer '(:name))
519   (prefix :field (byte 8  0) :value #b11011011)
520   (suffix :field (byte 3 13) :value #b111)
521   (op     :field (byte 5  8)))
522
523 (sb!disassem:define-instruction-format (floating-point-st 16
524                                       :default-printer '(:name))
525   (prefix :field (byte 8  0) :value #b11011111)
526   (suffix :field (byte 3 13) :value #b111)
527   (op     :field (byte 5  8)))
528
529 (sb!disassem:define-instruction-format (string-op 8
530                                      :include 'simple
531                                      :default-printer '(:name width)))
532
533 (sb!disassem:define-instruction-format (short-cond-jump 16)
534   (op    :field (byte 4 4))
535   (cc    :field (byte 4 0) :type 'condition-code)
536   (label :field (byte 8 8) :type 'displacement))
537
538 (sb!disassem:define-instruction-format (short-jump 16
539                                      :default-printer '(:name :tab label))
540   (const :field (byte 4 4) :value #b1110)
541   (op    :field (byte 4 0))
542   (label :field (byte 8 8) :type 'displacement))
543
544 (sb!disassem:define-instruction-format (near-cond-jump 16)
545   (op    :fields (list (byte 8 0) (byte 4 12)) :value '(#b00001111 #b1000))
546   (cc    :field (byte 4 8) :type 'condition-code)
547   ;; The disassembler currently doesn't let you have an instruction > 32 bits
548   ;; long, so we fake it by using a prefilter to read the offset.
549   (label :type 'displacement
550          :prefilter (lambda (value dstate)
551                       (declare (ignore value)) ; always nil anyway
552                       (sb!disassem:read-signed-suffix 32 dstate))))
553
554 (sb!disassem:define-instruction-format (near-jump 8
555                                      :default-printer '(:name :tab label))
556   (op    :field (byte 8 0))
557   ;; The disassembler currently doesn't let you have an instruction > 32 bits
558   ;; long, so we fake it by using a prefilter to read the address.
559   (label :type 'displacement
560          :prefilter (lambda (value dstate)
561                       (declare (ignore value)) ; always nil anyway
562                       (sb!disassem:read-signed-suffix 32 dstate))))
563
564
565 (sb!disassem:define-instruction-format (cond-set 24
566                                      :default-printer '('set cc :tab reg/mem))
567   (prefix :field (byte 8 0) :value #b00001111)
568   (op    :field (byte 4 12) :value #b1001)
569   (cc    :field (byte 4 8) :type 'condition-code)
570   (reg/mem :fields (list (byte 2 22) (byte 3 16))
571            :type 'byte-reg/mem)
572   (reg     :field (byte 3 19)   :value #b000))
573
574 (sb!disassem:define-instruction-format (enter-format 32
575                                      :default-printer '(:name
576                                                         :tab disp
577                                                         (:unless (:constant 0)
578                                                           ", " level)))
579   (op :field (byte 8 0))
580   (disp :field (byte 16 8))
581   (level :field (byte 8 24)))
582
583 ;;; Single byte instruction with an immediate byte argument.
584 (sb!disassem:define-instruction-format (byte-imm 16
585                                      :default-printer '(:name :tab code))
586  (op :field (byte 8 0))
587  (code :field (byte 8 8)))
588 \f
589 ;;;; primitive emitters
590
591 (define-bitfield-emitter emit-word 16
592   (byte 16 0))
593
594 (define-bitfield-emitter emit-dword 32
595   (byte 32 0))
596
597 (define-bitfield-emitter emit-byte-with-reg 8
598   (byte 5 3) (byte 3 0))
599
600 (define-bitfield-emitter emit-mod-reg-r/m-byte 8
601   (byte 2 6) (byte 3 3) (byte 3 0))
602
603 (define-bitfield-emitter emit-sib-byte 8
604   (byte 2 6) (byte 3 3) (byte 3 0))
605 \f
606 ;;;; fixup emitters
607
608 (defun emit-absolute-fixup (segment fixup)
609   (note-fixup segment :absolute fixup)
610   (let ((offset (fixup-offset fixup)))
611     (if (label-p offset)
612         (emit-back-patch segment
613                          4 ; FIXME: sb!vm:n-word-bytes
614                          (lambda (segment posn)
615                            (declare (ignore posn))
616                            (emit-dword segment
617                                        (- (+ (component-header-length)
618                                              (or (label-position offset)
619                                                  0))
620                                           other-pointer-lowtag))))
621         (emit-dword segment (or offset 0)))))
622
623 (defun emit-relative-fixup (segment fixup)
624   (note-fixup segment :relative fixup)
625   (emit-dword segment (or (fixup-offset fixup) 0)))
626 \f
627 ;;;; the effective-address (ea) structure
628
629 (defun reg-tn-encoding (tn)
630   (declare (type tn tn))
631   (aver (eq (sb-name (sc-sb (tn-sc tn))) 'registers))
632   (let ((offset (tn-offset tn)))
633     (logior (ash (logand offset 1) 2)
634             (ash offset -1))))
635
636 (defstruct (ea (:constructor make-ea (size &key base index scale disp))
637                (:copier nil))
638   (size nil :type (member :byte :word :dword))
639   (base nil :type (or tn null))
640   (index nil :type (or tn null))
641   (scale 1 :type (member 1 2 4 8))
642   (disp 0 :type (or (signed-byte 32) fixup)))
643 (def!method print-object ((ea ea) stream)
644   (cond ((or *print-escape* *print-readably*)
645          (print-unreadable-object (ea stream :type t)
646            (format stream
647                    "~S~@[ base=~S~]~@[ index=~S~]~@[ scale=~S~]~@[ disp=~S~]"
648                    (ea-size ea)
649                    (ea-base ea)
650                    (ea-index ea)
651                    (let ((scale (ea-scale ea)))
652                      (if (= scale 1) nil scale))
653                    (ea-disp ea))))
654         (t
655          (format stream "~A PTR [" (symbol-name (ea-size ea)))
656          (when (ea-base ea)
657            (write-string (sb!c::location-print-name (ea-base ea)) stream)
658            (when (ea-index ea)
659              (write-string "+" stream)))
660          (when (ea-index ea)
661            (write-string (sb!c::location-print-name (ea-index ea)) stream))
662          (unless (= (ea-scale ea) 1)
663            (format stream "*~A" (ea-scale ea)))
664          (typecase (ea-disp ea)
665            (null)
666            (integer
667             (format stream "~@D" (ea-disp ea)))
668            (t
669             (format stream "+~A" (ea-disp ea))))
670          (write-char #\] stream))))
671
672 (defun emit-ea (segment thing reg &optional allow-constants)
673   (etypecase thing
674     (tn
675      (ecase (sb-name (sc-sb (tn-sc thing)))
676        (registers
677         (emit-mod-reg-r/m-byte segment #b11 reg (reg-tn-encoding thing)))
678        (stack
679         ;; Convert stack tns into an index off of EBP.
680         (let ((disp (- (* (1+ (tn-offset thing)) n-word-bytes))))
681           (cond ((< -128 disp 127)
682                  (emit-mod-reg-r/m-byte segment #b01 reg #b101)
683                  (emit-byte segment disp))
684                 (t
685                  (emit-mod-reg-r/m-byte segment #b10 reg #b101)
686                  (emit-dword segment disp)))))
687        (constant
688         (unless allow-constants
689           (error
690            "Constant TNs can only be directly used in MOV, PUSH, and CMP."))
691         (emit-mod-reg-r/m-byte segment #b00 reg #b101)
692         (emit-absolute-fixup segment
693                              (make-fixup nil
694                                          :code-object
695                                          (- (* (tn-offset thing) n-word-bytes)
696                                             other-pointer-lowtag))))))
697     (ea
698      (let* ((base (ea-base thing))
699             (index (ea-index thing))
700             (scale (ea-scale thing))
701             (disp (ea-disp thing))
702             (mod (cond ((or (null base)
703                             (and (eql disp 0)
704                                  (not (= (reg-tn-encoding base) #b101))))
705                         #b00)
706                        ((and (fixnump disp) (<= -128 disp 127))
707                         #b01)
708                        (t
709                         #b10)))
710             (r/m (cond (index #b100)
711                        ((null base) #b101)
712                        (t (reg-tn-encoding base)))))
713        (emit-mod-reg-r/m-byte segment mod reg r/m)
714        (when (= r/m #b100)
715          (let ((ss (1- (integer-length scale)))
716                (index (if (null index)
717                           #b100
718                           (let ((index (reg-tn-encoding index)))
719                             (if (= index #b100)
720                                 (error "can't index off of ESP")
721                                 index))))
722                (base (if (null base)
723                          #b101
724                          (reg-tn-encoding base))))
725            (emit-sib-byte segment ss index base)))
726        (cond ((= mod #b01)
727               (emit-byte segment disp))
728              ((or (= mod #b10) (null base))
729               (if (fixup-p disp)
730                   (emit-absolute-fixup segment disp)
731                   (emit-dword segment disp))))))
732     (fixup
733      (emit-mod-reg-r/m-byte segment #b00 reg #b101)
734      (emit-absolute-fixup segment thing))))
735
736 (defun fp-reg-tn-p (thing)
737   (and (tn-p thing)
738        (eq (sb-name (sc-sb (tn-sc thing))) 'float-registers)))
739
740 ;;; like the above, but for fp-instructions--jrd
741 (defun emit-fp-op (segment thing op)
742   (if (fp-reg-tn-p thing)
743       (emit-byte segment (dpb op (byte 3 3) (dpb (tn-offset thing)
744                                                  (byte 3 0)
745                                                  #b11000000)))
746     (emit-ea segment thing op)))
747
748 (defun byte-reg-p (thing)
749   (and (tn-p thing)
750        (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
751        (member (sc-name (tn-sc thing)) *byte-sc-names*)
752        t))
753
754 (defun byte-ea-p (thing)
755   (typecase thing
756     (ea (eq (ea-size thing) :byte))
757     (tn
758      (and (member (sc-name (tn-sc thing)) *byte-sc-names*) t))
759     (t nil)))
760
761 (defun word-reg-p (thing)
762   (and (tn-p thing)
763        (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
764        (member (sc-name (tn-sc thing)) *word-sc-names*)
765        t))
766
767 (defun word-ea-p (thing)
768   (typecase thing
769     (ea (eq (ea-size thing) :word))
770     (tn (and (member (sc-name (tn-sc thing)) *word-sc-names*) t))
771     (t nil)))
772
773 (defun dword-reg-p (thing)
774   (and (tn-p thing)
775        (eq (sb-name (sc-sb (tn-sc thing))) 'registers)
776        (member (sc-name (tn-sc thing)) *dword-sc-names*)
777        t))
778
779 (defun dword-ea-p (thing)
780   (typecase thing
781     (ea (eq (ea-size thing) :dword))
782     (tn
783      (and (member (sc-name (tn-sc thing)) *dword-sc-names*) t))
784     (t nil)))
785
786 (defun register-p (thing)
787   (and (tn-p thing)
788        (eq (sb-name (sc-sb (tn-sc thing))) 'registers)))
789
790 (defun accumulator-p (thing)
791   (and (register-p thing)
792        (= (tn-offset thing) 0)))
793 \f
794 ;;;; utilities
795
796 (def!constant +operand-size-prefix-byte+ #b01100110)
797
798 (defun maybe-emit-operand-size-prefix (segment size)
799   (unless (or (eq size :byte) (eq size +default-operand-size+))
800     (emit-byte segment +operand-size-prefix-byte+)))
801
802 (defun operand-size (thing)
803   (typecase thing
804     (tn
805      ;; FIXME: might as well be COND instead of having to use #. readmacro
806      ;; to hack up the code
807      (case (sc-name (tn-sc thing))
808        (#.*dword-sc-names*
809         :dword)
810        (#.*word-sc-names*
811         :word)
812        (#.*byte-sc-names*
813         :byte)
814        ;; added by jrd: float-registers is a separate size (?)
815        (#.*float-sc-names*
816         :float)
817        (#.*double-sc-names*
818         :double)
819        (t
820         (error "can't tell the size of ~S ~S" thing (sc-name (tn-sc thing))))))
821     (ea
822      (ea-size thing))
823     (t
824      nil)))
825
826 (defun matching-operand-size (dst src)
827   (let ((dst-size (operand-size dst))
828         (src-size (operand-size src)))
829     (if dst-size
830         (if src-size
831             (if (eq dst-size src-size)
832                 dst-size
833                 (error "size mismatch: ~S is a ~S and ~S is a ~S."
834                        dst dst-size src src-size))
835             dst-size)
836         (if src-size
837             src-size
838             (error "can't tell the size of either ~S or ~S" dst src)))))
839
840 (defun emit-sized-immediate (segment size value)
841   (ecase size
842     (:byte
843      (emit-byte segment value))
844     (:word
845      (emit-word segment value))
846     (:dword
847      (emit-dword segment value))))
848 \f
849 ;;;; general data transfer
850
851 (define-instruction mov (segment dst src)
852   ;; immediate to register
853   (:printer reg ((op #b1011) (imm nil :type 'imm-data))
854             '(:name :tab reg ", " imm))
855   ;; absolute mem to/from accumulator
856   (:printer simple-dir ((op #b101000) (imm nil :type 'imm-addr))
857             `(:name :tab ,(swap-if 'dir 'accum ", " '("[" imm "]"))))
858   ;; register to/from register/memory
859   (:printer reg-reg/mem-dir ((op #b100010)))
860   ;; immediate to register/memory
861   (:printer reg/mem-imm ((op '(#b1100011 #b000))))
862
863   (:emitter
864    (let ((size (matching-operand-size dst src)))
865      (maybe-emit-operand-size-prefix segment size)
866      (cond ((register-p dst)
867             (cond ((integerp src)
868                    (emit-byte-with-reg segment
869                                        (if (eq size :byte)
870                                            #b10110
871                                            #b10111)
872                                        (reg-tn-encoding dst))
873                    (emit-sized-immediate segment size src))
874                   ((and (fixup-p src) (accumulator-p dst))
875                    (emit-byte segment
876                               (if (eq size :byte)
877                                   #b10100000
878                                   #b10100001))
879                    (emit-absolute-fixup segment src))
880                   (t
881                    (emit-byte segment
882                               (if (eq size :byte)
883                                   #b10001010
884                                   #b10001011))
885                    (emit-ea segment src (reg-tn-encoding dst) t))))
886            ((and (fixup-p dst) (accumulator-p src))
887             (emit-byte segment (if (eq size :byte) #b10100010 #b10100011))
888             (emit-absolute-fixup segment dst))
889            ((integerp src)
890             (emit-byte segment (if (eq size :byte) #b11000110 #b11000111))
891             (emit-ea segment dst #b000)
892             (emit-sized-immediate segment size src))
893            ((register-p src)
894             (emit-byte segment (if (eq size :byte) #b10001000 #b10001001))
895             (emit-ea segment dst (reg-tn-encoding src)))
896            ((fixup-p src)
897             (aver (eq size :dword))
898             (emit-byte segment #b11000111)
899             (emit-ea segment dst #b000)
900             (emit-absolute-fixup segment src))
901            (t
902             (error "bogus arguments to MOV: ~S ~S" dst src))))))
903
904 (defun emit-move-with-extension (segment dst src opcode)
905   (aver (register-p dst))
906   (let ((dst-size (operand-size dst))
907         (src-size (operand-size src)))
908     (ecase dst-size
909       (:word
910        (aver (eq src-size :byte))
911        (maybe-emit-operand-size-prefix segment :word)
912        (emit-byte segment #b00001111)
913        (emit-byte segment opcode)
914        (emit-ea segment src (reg-tn-encoding dst)))
915       (:dword
916        (ecase src-size
917          (:byte
918           (maybe-emit-operand-size-prefix segment :dword)
919           (emit-byte segment #b00001111)
920           (emit-byte segment opcode)
921           (emit-ea segment src (reg-tn-encoding dst)))
922          (:word
923           (emit-byte segment #b00001111)
924           (emit-byte segment (logior opcode 1))
925           (emit-ea segment src (reg-tn-encoding dst))))))))
926
927 (define-instruction movsx (segment dst src)
928   (:printer ext-reg-reg/mem ((op #b1011111) (reg nil :type 'word-reg)))
929   (:emitter (emit-move-with-extension segment dst src #b10111110)))
930
931 (define-instruction movzx (segment dst src)
932   (:printer ext-reg-reg/mem ((op #b1011011) (reg nil :type 'word-reg)))
933   (:emitter (emit-move-with-extension segment dst src #b10110110)))
934
935 (define-instruction push (segment src)
936   ;; register
937   (:printer reg-no-width ((op #b01010)))
938   ;; register/memory
939   (:printer reg/mem ((op '(#b1111111 #b110)) (width 1)))
940   ;; immediate
941   (:printer byte ((op #b01101010) (imm nil :type 'signed-imm-byte))
942             '(:name :tab imm))
943   (:printer byte ((op #b01101000) (imm nil :type 'imm-word))
944             '(:name :tab imm))
945   ;; ### segment registers?
946
947   (:emitter
948    (cond ((integerp src)
949           (cond ((<= -128 src 127)
950                  (emit-byte segment #b01101010)
951                  (emit-byte segment src))
952                 (t
953                  (emit-byte segment #b01101000)
954                  (emit-dword segment src))))
955          ((fixup-p src)
956           ;; Interpret the fixup as an immediate dword to push.
957           (emit-byte segment #b01101000)
958           (emit-absolute-fixup segment src))
959          (t
960           (let ((size (operand-size src)))
961             (aver (not (eq size :byte)))
962             (maybe-emit-operand-size-prefix segment size)
963             (cond ((register-p src)
964                    (emit-byte-with-reg segment #b01010 (reg-tn-encoding src)))
965                   (t
966                    (emit-byte segment #b11111111)
967                    (emit-ea segment src #b110 t))))))))
968
969 (define-instruction pusha (segment)
970   (:printer byte ((op #b01100000)))
971   (:emitter
972    (emit-byte segment #b01100000)))
973
974 (define-instruction pop (segment dst)
975   (:printer reg-no-width ((op #b01011)))
976   (:printer reg/mem ((op '(#b1000111 #b000)) (width 1)))
977   (:emitter
978    (let ((size (operand-size dst)))
979      (aver (not (eq size :byte)))
980      (maybe-emit-operand-size-prefix segment size)
981      (cond ((register-p dst)
982             (emit-byte-with-reg segment #b01011 (reg-tn-encoding dst)))
983            (t
984             (emit-byte segment #b10001111)
985             (emit-ea segment dst #b000))))))
986
987 (define-instruction popa (segment)
988   (:printer byte ((op #b01100001)))
989   (:emitter
990    (emit-byte segment #b01100001)))
991
992 (define-instruction xchg (segment operand1 operand2)
993   ;; Register with accumulator.
994   (:printer reg-no-width ((op #b10010)) '(:name :tab accum ", " reg))
995   ;; Register/Memory with Register.
996   (:printer reg-reg/mem ((op #b1000011)))
997   (:emitter
998    (let ((size (matching-operand-size operand1 operand2)))
999      (maybe-emit-operand-size-prefix segment size)
1000      (labels ((xchg-acc-with-something (acc something)
1001                 (if (and (not (eq size :byte)) (register-p something))
1002                     (emit-byte-with-reg segment
1003                                         #b10010
1004                                         (reg-tn-encoding something))
1005                     (xchg-reg-with-something acc something)))
1006               (xchg-reg-with-something (reg something)
1007                 (emit-byte segment (if (eq size :byte) #b10000110 #b10000111))
1008                 (emit-ea segment something (reg-tn-encoding reg))))
1009        (cond ((accumulator-p operand1)
1010               (xchg-acc-with-something operand1 operand2))
1011              ((accumulator-p operand2)
1012               (xchg-acc-with-something operand2 operand1))
1013              ((register-p operand1)
1014               (xchg-reg-with-something operand1 operand2))
1015              ((register-p operand2)
1016               (xchg-reg-with-something operand2 operand1))
1017              (t
1018               (error "bogus args to XCHG: ~S ~S" operand1 operand2)))))))
1019
1020 (define-instruction lea (segment dst src)
1021   (:printer reg-reg/mem ((op #b1000110) (width 1)))
1022   (:emitter
1023    (aver (dword-reg-p dst))
1024    (emit-byte segment #b10001101)
1025    (emit-ea segment src (reg-tn-encoding dst))))
1026
1027 (define-instruction cmpxchg (segment dst src)
1028   ;; Register/Memory with Register.
1029   (:printer ext-reg-reg/mem ((op #b1011000)) '(:name :tab reg/mem ", " reg))
1030   (:emitter
1031    (aver (register-p src))
1032    (let ((size (matching-operand-size src dst)))
1033      (maybe-emit-operand-size-prefix segment size)
1034      (emit-byte segment #b00001111)
1035      (emit-byte segment (if (eq size :byte) #b10110000 #b10110001))
1036      (emit-ea segment dst (reg-tn-encoding src)))))
1037
1038 \f
1039 ;;;; flag control instructions
1040
1041 ;;; CLC -- Clear Carry Flag.
1042 (define-instruction clc (segment)
1043   (:printer byte ((op #b11111000)))
1044   (:emitter
1045    (emit-byte segment #b11111000)))
1046
1047 ;;; CLD -- Clear Direction Flag.
1048 (define-instruction cld (segment)
1049   (:printer byte ((op #b11111100)))
1050   (:emitter
1051    (emit-byte segment #b11111100)))
1052
1053 ;;; CLI -- Clear Iterrupt Enable Flag.
1054 (define-instruction cli (segment)
1055   (:printer byte ((op #b11111010)))
1056   (:emitter
1057    (emit-byte segment #b11111010)))
1058
1059 ;;; CMC -- Complement Carry Flag.
1060 (define-instruction cmc (segment)
1061   (:printer byte ((op #b11110101)))
1062   (:emitter
1063    (emit-byte segment #b11110101)))
1064
1065 ;;; LAHF -- Load AH into flags.
1066 (define-instruction lahf (segment)
1067   (:printer byte ((op #b10011111)))
1068   (:emitter
1069    (emit-byte segment #b10011111)))
1070
1071 ;;; POPF -- Pop flags.
1072 (define-instruction popf (segment)
1073   (:printer byte ((op #b10011101)))
1074   (:emitter
1075    (emit-byte segment #b10011101)))
1076
1077 ;;; PUSHF -- push flags.
1078 (define-instruction pushf (segment)
1079   (:printer byte ((op #b10011100)))
1080   (:emitter
1081    (emit-byte segment #b10011100)))
1082
1083 ;;; SAHF -- Store AH into flags.
1084 (define-instruction sahf (segment)
1085   (:printer byte ((op #b10011110)))
1086   (:emitter
1087    (emit-byte segment #b10011110)))
1088
1089 ;;; STC -- Set Carry Flag.
1090 (define-instruction stc (segment)
1091   (:printer byte ((op #b11111001)))
1092   (:emitter
1093    (emit-byte segment #b11111001)))
1094
1095 ;;; STD -- Set Direction Flag.
1096 (define-instruction std (segment)
1097   (:printer byte ((op #b11111101)))
1098   (:emitter
1099    (emit-byte segment #b11111101)))
1100
1101 ;;; STI -- Set Interrupt Enable Flag.
1102 (define-instruction sti (segment)
1103   (:printer byte ((op #b11111011)))
1104   (:emitter
1105    (emit-byte segment #b11111011)))
1106 \f
1107 ;;;; arithmetic
1108
1109 (defun emit-random-arith-inst (name segment dst src opcode
1110                                     &optional allow-constants)
1111   (let ((size (matching-operand-size dst src)))
1112     (maybe-emit-operand-size-prefix segment size)
1113     (cond
1114      ((integerp src)
1115       (cond ((and (not (eq size :byte)) (<= -128 src 127))
1116              (emit-byte segment #b10000011)
1117              (emit-ea segment dst opcode)
1118              (emit-byte segment src))
1119             ((accumulator-p dst)
1120              (emit-byte segment
1121                         (dpb opcode
1122                              (byte 3 3)
1123                              (if (eq size :byte)
1124                                  #b00000100
1125                                  #b00000101)))
1126              (emit-sized-immediate segment size src))
1127             (t
1128              (emit-byte segment (if (eq size :byte) #b10000000 #b10000001))
1129              (emit-ea segment dst opcode)
1130              (emit-sized-immediate segment size src))))
1131      ((register-p src)
1132       (emit-byte segment
1133                  (dpb opcode
1134                       (byte 3 3)
1135                       (if (eq size :byte) #b00000000 #b00000001)))
1136       (emit-ea segment dst (reg-tn-encoding src) allow-constants))
1137      ((register-p dst)
1138       (emit-byte segment
1139                  (dpb opcode
1140                       (byte 3 3)
1141                       (if (eq size :byte) #b00000010 #b00000011)))
1142       (emit-ea segment src (reg-tn-encoding dst) allow-constants))
1143      (t
1144       (error "bogus operands to ~A" name)))))
1145
1146 (eval-when (:compile-toplevel :execute)
1147   (defun arith-inst-printer-list (subop)
1148     `((accum-imm ((op ,(dpb subop (byte 3 2) #b0000010))))
1149       (reg/mem-imm ((op (#b1000000 ,subop))))
1150       (reg/mem-imm ((op (#b1000001 ,subop))
1151                     (imm nil :type signed-imm-byte)))
1152       (reg-reg/mem-dir ((op ,(dpb subop (byte 3 1) #b000000))))))
1153   )
1154
1155 (define-instruction add (segment dst src)
1156   (:printer-list (arith-inst-printer-list #b000))
1157   (:emitter (emit-random-arith-inst "ADD" segment dst src #b000)))
1158
1159 (define-instruction adc (segment dst src)
1160   (:printer-list (arith-inst-printer-list #b010))
1161   (:emitter (emit-random-arith-inst "ADC" segment dst src #b010)))
1162
1163 (define-instruction sub (segment dst src)
1164   (:printer-list (arith-inst-printer-list #b101))
1165   (:emitter (emit-random-arith-inst "SUB" segment dst src #b101)))
1166
1167 (define-instruction sbb (segment dst src)
1168   (:printer-list (arith-inst-printer-list #b011))
1169   (:emitter (emit-random-arith-inst "SBB" segment dst src #b011)))
1170
1171 (define-instruction cmp (segment dst src)
1172   (:printer-list (arith-inst-printer-list #b111))
1173   (:emitter (emit-random-arith-inst "CMP" segment dst src #b111 t)))
1174
1175 (define-instruction inc (segment dst)
1176   ;; Register.
1177   (:printer reg-no-width ((op #b01000)))
1178   ;; Register/Memory
1179   (:printer reg/mem ((op '(#b1111111 #b000))))
1180   (:emitter
1181    (let ((size (operand-size dst)))
1182      (maybe-emit-operand-size-prefix segment size)
1183      (cond ((and (not (eq size :byte)) (register-p dst))
1184             (emit-byte-with-reg segment #b01000 (reg-tn-encoding dst)))
1185            (t
1186             (emit-byte segment (if (eq size :byte) #b11111110 #b11111111))
1187             (emit-ea segment dst #b000))))))
1188
1189 (define-instruction dec (segment dst)
1190   ;; Register.
1191   (:printer reg-no-width ((op #b01001)))
1192   ;; Register/Memory
1193   (:printer reg/mem ((op '(#b1111111 #b001))))
1194   (:emitter
1195    (let ((size (operand-size dst)))
1196      (maybe-emit-operand-size-prefix segment size)
1197      (cond ((and (not (eq size :byte)) (register-p dst))
1198             (emit-byte-with-reg segment #b01001 (reg-tn-encoding dst)))
1199            (t
1200             (emit-byte segment (if (eq size :byte) #b11111110 #b11111111))
1201             (emit-ea segment dst #b001))))))
1202
1203 (define-instruction neg (segment dst)
1204   (:printer reg/mem ((op '(#b1111011 #b011))))
1205   (:emitter
1206    (let ((size (operand-size dst)))
1207      (maybe-emit-operand-size-prefix segment size)
1208      (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1209      (emit-ea segment dst #b011))))
1210
1211 (define-instruction aaa (segment)
1212   (:printer byte ((op #b00110111)))
1213   (:emitter
1214    (emit-byte segment #b00110111)))
1215
1216 (define-instruction aas (segment)
1217   (:printer byte ((op #b00111111)))
1218   (:emitter
1219    (emit-byte segment #b00111111)))
1220
1221 (define-instruction daa (segment)
1222   (:printer byte ((op #b00100111)))
1223   (:emitter
1224    (emit-byte segment #b00100111)))
1225
1226 (define-instruction das (segment)
1227   (:printer byte ((op #b00101111)))
1228   (:emitter
1229    (emit-byte segment #b00101111)))
1230
1231 (define-instruction mul (segment dst src)
1232   (:printer accum-reg/mem ((op '(#b1111011 #b100))))
1233   (:emitter
1234    (let ((size (matching-operand-size dst src)))
1235      (aver (accumulator-p dst))
1236      (maybe-emit-operand-size-prefix segment size)
1237      (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1238      (emit-ea segment src #b100))))
1239
1240 (define-instruction imul (segment dst &optional src1 src2)
1241   (:printer accum-reg/mem ((op '(#b1111011 #b101))))
1242   (:printer ext-reg-reg/mem ((op #b1010111)))
1243   (:printer reg-reg/mem ((op #b0110100) (width 1) (imm nil :type 'imm-word))
1244             '(:name :tab reg ", " reg/mem ", " imm))
1245   (:printer reg-reg/mem ((op #b0110101) (width 1)
1246                          (imm nil :type 'signed-imm-byte))
1247             '(:name :tab reg ", " reg/mem ", " imm))
1248   (:emitter
1249    (flet ((r/m-with-immed-to-reg (reg r/m immed)
1250             (let* ((size (matching-operand-size reg r/m))
1251                    (sx (and (not (eq size :byte)) (<= -128 immed 127))))
1252               (maybe-emit-operand-size-prefix segment size)
1253               (emit-byte segment (if sx #b01101011 #b01101001))
1254               (emit-ea segment r/m (reg-tn-encoding reg))
1255               (if sx
1256                   (emit-byte segment immed)
1257                   (emit-sized-immediate segment size immed)))))
1258      (cond (src2
1259             (r/m-with-immed-to-reg dst src1 src2))
1260            (src1
1261             (if (integerp src1)
1262                 (r/m-with-immed-to-reg dst dst src1)
1263                 (let ((size (matching-operand-size dst src1)))
1264                   (maybe-emit-operand-size-prefix segment size)
1265                   (emit-byte segment #b00001111)
1266                   (emit-byte segment #b10101111)
1267                   (emit-ea segment src1 (reg-tn-encoding dst)))))
1268            (t
1269             (let ((size (operand-size dst)))
1270               (maybe-emit-operand-size-prefix segment size)
1271               (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1272               (emit-ea segment dst #b101)))))))
1273
1274 (define-instruction div (segment dst src)
1275   (:printer accum-reg/mem ((op '(#b1111011 #b110))))
1276   (:emitter
1277    (let ((size (matching-operand-size dst src)))
1278      (aver (accumulator-p dst))
1279      (maybe-emit-operand-size-prefix segment size)
1280      (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1281      (emit-ea segment src #b110))))
1282
1283 (define-instruction idiv (segment dst src)
1284   (:printer accum-reg/mem ((op '(#b1111011 #b111))))
1285   (:emitter
1286    (let ((size (matching-operand-size dst src)))
1287      (aver (accumulator-p dst))
1288      (maybe-emit-operand-size-prefix segment size)
1289      (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1290      (emit-ea segment src #b111))))
1291
1292 (define-instruction aad (segment)
1293   (:printer two-bytes ((op '(#b11010101 #b00001010))))
1294   (:emitter
1295    (emit-byte segment #b11010101)
1296    (emit-byte segment #b00001010)))
1297
1298 (define-instruction aam (segment)
1299   (:printer two-bytes ((op '(#b11010100 #b00001010))))
1300   (:emitter
1301    (emit-byte segment #b11010100)
1302    (emit-byte segment #b00001010)))
1303
1304 ;;; CBW -- Convert Byte to Word. AX <- sign_xtnd(AL)
1305 (define-instruction cbw (segment)
1306   (:emitter
1307    (maybe-emit-operand-size-prefix segment :word)
1308    (emit-byte segment #b10011000)))
1309
1310 ;;; CWDE -- Convert Word To Double Word Extened. EAX <- sign_xtnd(AX)
1311 (define-instruction cwde (segment)
1312   (:emitter
1313    (maybe-emit-operand-size-prefix segment :dword)
1314    (emit-byte segment #b10011000)))
1315
1316 ;;; CWD -- Convert Word to Double Word. DX:AX <- sign_xtnd(AX)
1317 (define-instruction cwd (segment)
1318   (:emitter
1319    (maybe-emit-operand-size-prefix segment :word)
1320    (emit-byte segment #b10011001)))
1321
1322 ;;; CDQ -- Convert Double Word to Quad Word. EDX:EAX <- sign_xtnd(EAX)
1323 (define-instruction cdq (segment)
1324   (:printer byte ((op #b10011001)))
1325   (:emitter
1326    (maybe-emit-operand-size-prefix segment :dword)
1327    (emit-byte segment #b10011001)))
1328
1329 (define-instruction xadd (segment dst src)
1330   ;; Register/Memory with Register.
1331   (:printer ext-reg-reg/mem ((op #b1100000)) '(:name :tab reg/mem ", " reg))
1332   (:emitter
1333    (aver (register-p src))
1334    (let ((size (matching-operand-size src dst)))
1335      (maybe-emit-operand-size-prefix segment size)
1336      (emit-byte segment #b00001111)
1337      (emit-byte segment (if (eq size :byte) #b11000000 #b11000001))
1338      (emit-ea segment dst (reg-tn-encoding src)))))
1339
1340 \f
1341 ;;;; logic
1342
1343 (defun emit-shift-inst (segment dst amount opcode)
1344   (let ((size (operand-size dst)))
1345     (maybe-emit-operand-size-prefix segment size)
1346     (multiple-value-bind (major-opcode immed)
1347         (case amount
1348           (:cl (values #b11010010 nil))
1349           (1 (values #b11010000 nil))
1350           (t (values #b11000000 t)))
1351       (emit-byte segment
1352                  (if (eq size :byte) major-opcode (logior major-opcode 1)))
1353       (emit-ea segment dst opcode)
1354       (when immed
1355         (emit-byte segment amount)))))
1356
1357 (eval-when (:compile-toplevel :execute)
1358   (defun shift-inst-printer-list (subop)
1359     `((reg/mem ((op (#b1101000 ,subop)))
1360                (:name :tab reg/mem ", 1"))
1361       (reg/mem ((op (#b1101001 ,subop)))
1362                (:name :tab reg/mem ", " 'cl))
1363       (reg/mem-imm ((op (#b1100000 ,subop))
1364                     (imm nil :type signed-imm-byte))))))
1365
1366 (define-instruction rol (segment dst amount)
1367   (:printer-list
1368    (shift-inst-printer-list #b000))
1369   (:emitter
1370    (emit-shift-inst segment dst amount #b000)))
1371
1372 (define-instruction ror (segment dst amount)
1373   (:printer-list
1374    (shift-inst-printer-list #b001))
1375   (:emitter
1376    (emit-shift-inst segment dst amount #b001)))
1377
1378 (define-instruction rcl (segment dst amount)
1379   (:printer-list
1380    (shift-inst-printer-list #b010))
1381   (:emitter
1382    (emit-shift-inst segment dst amount #b010)))
1383
1384 (define-instruction rcr (segment dst amount)
1385   (:printer-list
1386    (shift-inst-printer-list #b011))
1387   (:emitter
1388    (emit-shift-inst segment dst amount #b011)))
1389
1390 (define-instruction shl (segment dst amount)
1391   (:printer-list
1392    (shift-inst-printer-list #b100))
1393   (:emitter
1394    (emit-shift-inst segment dst amount #b100)))
1395
1396 (define-instruction shr (segment dst amount)
1397   (:printer-list
1398    (shift-inst-printer-list #b101))
1399   (:emitter
1400    (emit-shift-inst segment dst amount #b101)))
1401
1402 (define-instruction sar (segment dst amount)
1403   (:printer-list
1404    (shift-inst-printer-list #b111))
1405   (:emitter
1406    (emit-shift-inst segment dst amount #b111)))
1407
1408 (defun emit-double-shift (segment opcode dst src amt)
1409   (let ((size (matching-operand-size dst src)))
1410     (when (eq size :byte)
1411       (error "Double shifts can only be used with words."))
1412     (maybe-emit-operand-size-prefix segment size)
1413     (emit-byte segment #b00001111)
1414     (emit-byte segment (dpb opcode (byte 1 3)
1415                             (if (eq amt :cl) #b10100101 #b10100100)))
1416     #+nil
1417     (emit-ea segment dst src)
1418     (emit-ea segment dst (reg-tn-encoding src)) ; pw tries this
1419     (unless (eq amt :cl)
1420       (emit-byte segment amt))))
1421
1422 (eval-when (:compile-toplevel :execute)
1423   (defun double-shift-inst-printer-list (op)
1424     `(#+nil
1425       (ext-reg-reg/mem-imm ((op ,(logior op #b100))
1426                             (imm nil :type signed-imm-byte)))
1427       (ext-reg-reg/mem ((op ,(logior op #b101)))
1428          (:name :tab reg/mem ", " 'cl)))))
1429
1430 (define-instruction shld (segment dst src amt)
1431   (:declare (type (or (member :cl) (mod 32)) amt))
1432   (:printer-list (double-shift-inst-printer-list #b10100000))
1433   (:emitter
1434    (emit-double-shift segment #b0 dst src amt)))
1435
1436 (define-instruction shrd (segment dst src amt)
1437   (:declare (type (or (member :cl) (mod 32)) amt))
1438   (:printer-list (double-shift-inst-printer-list #b10101000))
1439   (:emitter
1440    (emit-double-shift segment #b1 dst src amt)))
1441
1442 (define-instruction and (segment dst src)
1443   (:printer-list
1444    (arith-inst-printer-list #b100))
1445   (:emitter
1446    (emit-random-arith-inst "AND" segment dst src #b100)))
1447
1448 (define-instruction test (segment this that)
1449   (:printer accum-imm ((op #b1010100)))
1450   (:printer reg/mem-imm ((op '(#b1111011 #b000))))
1451   (:printer reg-reg/mem ((op #b1000010)))
1452   (:emitter
1453    (let ((size (matching-operand-size this that)))
1454      (maybe-emit-operand-size-prefix segment size)
1455      (flet ((test-immed-and-something (immed something)
1456               (cond ((accumulator-p something)
1457                      (emit-byte segment
1458                                 (if (eq size :byte) #b10101000 #b10101001))
1459                      (emit-sized-immediate segment size immed))
1460                     (t
1461                      (emit-byte segment
1462                                 (if (eq size :byte) #b11110110 #b11110111))
1463                      (emit-ea segment something #b000)
1464                      (emit-sized-immediate segment size immed))))
1465             (test-reg-and-something (reg something)
1466               (emit-byte segment (if (eq size :byte) #b10000100 #b10000101))
1467               (emit-ea segment something (reg-tn-encoding reg))))
1468        (cond ((integerp that)
1469               (test-immed-and-something that this))
1470              ((integerp this)
1471               (test-immed-and-something this that))
1472              ((register-p this)
1473               (test-reg-and-something this that))
1474              ((register-p that)
1475               (test-reg-and-something that this))
1476              (t
1477               (error "bogus operands for TEST: ~S and ~S" this that)))))))
1478
1479 (define-instruction or (segment dst src)
1480   (:printer-list
1481    (arith-inst-printer-list #b001))
1482   (:emitter
1483    (emit-random-arith-inst "OR" segment dst src #b001)))
1484
1485 (define-instruction xor (segment dst src)
1486   (:printer-list
1487    (arith-inst-printer-list #b110))
1488   (:emitter
1489    (emit-random-arith-inst "XOR" segment dst src #b110)))
1490
1491 (define-instruction not (segment dst)
1492   (:printer reg/mem ((op '(#b1111011 #b010))))
1493   (:emitter
1494    (let ((size (operand-size dst)))
1495      (maybe-emit-operand-size-prefix segment size)
1496      (emit-byte segment (if (eq size :byte) #b11110110 #b11110111))
1497      (emit-ea segment dst #b010))))
1498 \f
1499 ;;;; string manipulation
1500
1501 (define-instruction cmps (segment size)
1502   (:printer string-op ((op #b1010011)))
1503   (:emitter
1504    (maybe-emit-operand-size-prefix segment size)
1505    (emit-byte segment (if (eq size :byte) #b10100110 #b10100111))))
1506
1507 (define-instruction ins (segment acc)
1508   (:printer string-op ((op #b0110110)))
1509   (:emitter
1510    (let ((size (operand-size acc)))
1511      (aver (accumulator-p acc))
1512      (maybe-emit-operand-size-prefix segment size)
1513      (emit-byte segment (if (eq size :byte) #b01101100 #b01101101)))))
1514
1515 (define-instruction lods (segment acc)
1516   (:printer string-op ((op #b1010110)))
1517   (:emitter
1518    (let ((size (operand-size acc)))
1519      (aver (accumulator-p acc))
1520      (maybe-emit-operand-size-prefix segment size)
1521      (emit-byte segment (if (eq size :byte) #b10101100 #b10101101)))))
1522
1523 (define-instruction movs (segment size)
1524   (:printer string-op ((op #b1010010)))
1525   (:emitter
1526    (maybe-emit-operand-size-prefix segment size)
1527    (emit-byte segment (if (eq size :byte) #b10100100 #b10100101))))
1528
1529 (define-instruction outs (segment acc)
1530   (:printer string-op ((op #b0110111)))
1531   (:emitter
1532    (let ((size (operand-size acc)))
1533      (aver (accumulator-p acc))
1534      (maybe-emit-operand-size-prefix segment size)
1535      (emit-byte segment (if (eq size :byte) #b01101110 #b01101111)))))
1536
1537 (define-instruction scas (segment acc)
1538   (:printer string-op ((op #b1010111)))
1539   (:emitter
1540    (let ((size (operand-size acc)))
1541      (aver (accumulator-p acc))
1542      (maybe-emit-operand-size-prefix segment size)
1543      (emit-byte segment (if (eq size :byte) #b10101110 #b10101111)))))
1544
1545 (define-instruction stos (segment acc)
1546   (:printer string-op ((op #b1010101)))
1547   (:emitter
1548    (let ((size (operand-size acc)))
1549      (aver (accumulator-p acc))
1550      (maybe-emit-operand-size-prefix segment size)
1551      (emit-byte segment (if (eq size :byte) #b10101010 #b10101011)))))
1552
1553 (define-instruction xlat (segment)
1554   (:printer byte ((op #b11010111)))
1555   (:emitter
1556    (emit-byte segment #b11010111)))
1557
1558 (define-instruction rep (segment)
1559   (:emitter
1560    (emit-byte segment #b11110010)))
1561
1562 (define-instruction repe (segment)
1563   (:printer byte ((op #b11110011)))
1564   (:emitter
1565    (emit-byte segment #b11110011)))
1566
1567 (define-instruction repne (segment)
1568   (:printer byte ((op #b11110010)))
1569   (:emitter
1570    (emit-byte segment #b11110010)))
1571
1572 \f
1573 ;;;; bit manipulation
1574
1575 (define-instruction bsf (segment dst src)
1576   (:emitter
1577    (let ((size (matching-operand-size dst src)))
1578      (when (eq size :byte)
1579        (error "can't scan bytes: ~S" src))
1580      (maybe-emit-operand-size-prefix segment size)
1581      (emit-byte segment #b00001111)
1582      (emit-byte segment #b10111100)
1583      (emit-ea segment src (reg-tn-encoding dst)))))
1584
1585 (define-instruction bsr (segment dst src)
1586   (:emitter
1587    (let ((size (matching-operand-size dst src)))
1588      (when (eq size :byte)
1589        (error "can't scan bytes: ~S" src))
1590      (maybe-emit-operand-size-prefix segment size)
1591      (emit-byte segment #b00001111)
1592      (emit-byte segment #b10111101)
1593      (emit-ea segment src (reg-tn-encoding dst)))))
1594
1595 (defun emit-bit-test-and-mumble (segment src index opcode)
1596   (let ((size (operand-size src)))
1597     (when (eq size :byte)
1598       (error "can't scan bytes: ~S" src))
1599     (maybe-emit-operand-size-prefix segment size)
1600     (emit-byte segment #b00001111)
1601     (cond ((integerp index)
1602            (emit-byte segment #b10111010)
1603            (emit-ea segment src opcode)
1604            (emit-byte segment index))
1605           (t
1606            (emit-byte segment (dpb opcode (byte 3 3) #b10000011))
1607            (emit-ea segment src (reg-tn-encoding index))))))
1608
1609 (define-instruction bt (segment src index)
1610   (:emitter
1611    (emit-bit-test-and-mumble segment src index #b100)))
1612
1613 (define-instruction btc (segment src index)
1614   (:emitter
1615    (emit-bit-test-and-mumble segment src index #b111)))
1616
1617 (define-instruction btr (segment src index)
1618   (:emitter
1619    (emit-bit-test-and-mumble segment src index #b110)))
1620
1621 (define-instruction bts (segment src index)
1622   (:emitter
1623    (emit-bit-test-and-mumble segment src index #b101)))
1624
1625 \f
1626 ;;;; control transfer
1627
1628 (define-instruction call (segment where)
1629   (:printer near-jump ((op #b11101000)))
1630   (:printer reg/mem ((op '(#b1111111 #b010)) (width 1)))
1631   (:emitter
1632    (typecase where
1633      (label
1634       (emit-byte segment #b11101000)
1635       (emit-back-patch segment
1636                        4
1637                        (lambda (segment posn)
1638                          (emit-dword segment
1639                                      (- (label-position where)
1640                                         (+ posn 4))))))
1641      (fixup
1642       (emit-byte segment #b11101000)
1643       (emit-relative-fixup segment where))
1644      (t
1645       (emit-byte segment #b11111111)
1646       (emit-ea segment where #b010)))))
1647
1648 (defun emit-byte-displacement-backpatch (segment target)
1649   (emit-back-patch segment
1650                    1
1651                    (lambda (segment posn)
1652                      (let ((disp (- (label-position target) (1+ posn))))
1653                        (aver (<= -128 disp 127))
1654                        (emit-byte segment disp)))))
1655
1656 (define-instruction jmp (segment cond &optional where)
1657   ;; conditional jumps
1658   (:printer short-cond-jump ((op #b0111)) '('j cc :tab label))
1659   (:printer near-cond-jump () '('j cc :tab label))
1660   ;; unconditional jumps
1661   (:printer short-jump ((op #b1011)))
1662   (:printer near-jump ((op #b11101001)) )
1663   (:printer reg/mem ((op '(#b1111111 #b100)) (width 1)))
1664   (:emitter
1665    (cond (where
1666           (emit-chooser
1667            segment 6 2
1668            (lambda (segment posn delta-if-after)
1669              (let ((disp (- (label-position where posn delta-if-after)
1670                             (+ posn 2))))
1671                (when (<= -128 disp 127)
1672                  (emit-byte segment
1673                             (dpb (conditional-opcode cond)
1674                                  (byte 4 0)
1675                                  #b01110000))
1676                  (emit-byte-displacement-backpatch segment where)
1677                  t)))
1678            (lambda (segment posn)
1679              (let ((disp (- (label-position where) (+ posn 6))))
1680                (emit-byte segment #b00001111)
1681                (emit-byte segment
1682                           (dpb (conditional-opcode cond)
1683                                (byte 4 0)
1684                                #b10000000))
1685                (emit-dword segment disp)))))
1686          ((label-p (setq where cond))
1687           (emit-chooser
1688            segment 5 0
1689            (lambda (segment posn delta-if-after)
1690              (let ((disp (- (label-position where posn delta-if-after)
1691                             (+ posn 2))))
1692                (when (<= -128 disp 127)
1693                  (emit-byte segment #b11101011)
1694                  (emit-byte-displacement-backpatch segment where)
1695                  t)))
1696            (lambda (segment posn)
1697              (let ((disp (- (label-position where) (+ posn 5))))
1698                (emit-byte segment #b11101001)
1699                (emit-dword segment disp)))))
1700          ((fixup-p where)
1701           (emit-byte segment #b11101001)
1702           (emit-relative-fixup segment where))
1703          (t
1704           (unless (or (ea-p where) (tn-p where))
1705                   (error "don't know what to do with ~A" where))
1706           (emit-byte segment #b11111111)
1707           (emit-ea segment where #b100)))))
1708
1709 (define-instruction jmp-short (segment label)
1710   (:emitter
1711    (emit-byte segment #b11101011)
1712    (emit-byte-displacement-backpatch segment label)))
1713
1714 (define-instruction ret (segment &optional stack-delta)
1715   (:printer byte ((op #b11000011)))
1716   (:printer byte ((op #b11000010) (imm nil :type 'imm-word-16))
1717             '(:name :tab imm))
1718   (:emitter
1719    (cond (stack-delta
1720           (emit-byte segment #b11000010)
1721           (emit-word segment stack-delta))
1722          (t
1723           (emit-byte segment #b11000011)))))
1724
1725 (define-instruction jecxz (segment target)
1726   (:printer short-jump ((op #b0011)))
1727   (:emitter
1728    (emit-byte segment #b11100011)
1729    (emit-byte-displacement-backpatch segment target)))
1730
1731 (define-instruction loop (segment target)
1732   (:printer short-jump ((op #b0010)))
1733   (:emitter
1734    (emit-byte segment #b11100010)       ; pfw this was 11100011, or jecxz!!!!
1735    (emit-byte-displacement-backpatch segment target)))
1736
1737 (define-instruction loopz (segment target)
1738   (:printer short-jump ((op #b0001)))
1739   (:emitter
1740    (emit-byte segment #b11100001)
1741    (emit-byte-displacement-backpatch segment target)))
1742
1743 (define-instruction loopnz (segment target)
1744   (:printer short-jump ((op #b0000)))
1745   (:emitter
1746    (emit-byte segment #b11100000)
1747    (emit-byte-displacement-backpatch segment target)))
1748 \f
1749 ;;;; conditional byte set
1750
1751 (define-instruction set (segment dst cond)
1752   (:printer cond-set ())
1753   (:emitter
1754    (emit-byte segment #b00001111)
1755    (emit-byte segment (dpb (conditional-opcode cond) (byte 4 0) #b10010000))
1756    (emit-ea segment dst #b000)))
1757 \f
1758 ;;;; enter/leave
1759
1760 (define-instruction enter (segment disp &optional (level 0))
1761   (:declare (type (unsigned-byte 16) disp)
1762             (type (unsigned-byte 8) level))
1763   (:printer enter-format ((op #b11001000)))
1764   (:emitter
1765    (emit-byte segment #b11001000)
1766    (emit-word segment disp)
1767    (emit-byte segment level)))
1768
1769 (define-instruction leave (segment)
1770   (:printer byte ((op #b11001001)))
1771   (:emitter
1772    (emit-byte segment #b11001001)))
1773 \f
1774 ;;;; interrupt instructions
1775
1776 (defun snarf-error-junk (sap offset &optional length-only)
1777   (let* ((length (sb!sys:sap-ref-8 sap offset))
1778          (vector (make-array length :element-type '(unsigned-byte 8))))
1779     (declare (type sb!sys:system-area-pointer sap)
1780              (type (unsigned-byte 8) length)
1781              (type (simple-array (unsigned-byte 8) (*)) vector))
1782     (cond (length-only
1783            (values 0 (1+ length) nil nil))
1784           (t
1785            (sb!kernel:copy-from-system-area sap (* n-byte-bits (1+ offset))
1786                                             vector (* n-word-bits
1787                                                       vector-data-offset)
1788                                             (* length n-byte-bits))
1789            (collect ((sc-offsets)
1790                      (lengths))
1791              (lengths 1)                ; the length byte
1792              (let* ((index 0)
1793                     (error-number (sb!c::read-var-integer vector index)))
1794                (lengths index)
1795                (loop
1796                  (when (>= index length)
1797                    (return))
1798                  (let ((old-index index))
1799                    (sc-offsets (sb!c::read-var-integer vector index))
1800                    (lengths (- index old-index))))
1801                (values error-number
1802                        (1+ length)
1803                        (sc-offsets)
1804                        (lengths))))))))
1805
1806 #|
1807 (defmacro break-cases (breaknum &body cases)
1808   (let ((bn-temp (gensym)))
1809     (collect ((clauses))
1810       (dolist (case cases)
1811         (clauses `((= ,bn-temp ,(car case)) ,@(cdr case))))
1812       `(let ((,bn-temp ,breaknum))
1813          (cond ,@(clauses))))))
1814 |#
1815
1816 (defun break-control (chunk inst stream dstate)
1817   (declare (ignore inst))
1818   (flet ((nt (x) (if stream (sb!disassem:note x dstate))))
1819     ;; FIXME: Make sure that BYTE-IMM-CODE is defined. The genesis
1820     ;; map has it undefined; and it should be easier to look in the target
1821     ;; Lisp (with (DESCRIBE 'BYTE-IMM-CODE)) than to definitively deduce
1822     ;; from first principles whether it's defined in some way that genesis
1823     ;; can't grok.
1824     (case (byte-imm-code chunk dstate)
1825       (#.error-trap
1826        (nt "error trap")
1827        (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
1828       (#.cerror-trap
1829        (nt "cerror trap")
1830        (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
1831       (#.breakpoint-trap
1832        (nt "breakpoint trap"))
1833       (#.pending-interrupt-trap
1834        (nt "pending interrupt trap"))
1835       (#.halt-trap
1836        (nt "halt trap"))
1837       (#.fun-end-breakpoint-trap
1838        (nt "function end breakpoint trap")))))
1839
1840 (define-instruction break (segment code)
1841   (:declare (type (unsigned-byte 8) code))
1842   (:printer byte-imm ((op #b11001100)) '(:name :tab code)
1843             :control #'break-control)
1844   (:emitter
1845    (emit-byte segment #b11001100)
1846    (emit-byte segment code)))
1847
1848 (define-instruction int (segment number)
1849   (:declare (type (unsigned-byte 8) number))
1850   (:printer byte-imm ((op #b11001101)))
1851   (:emitter
1852    (etypecase number
1853      ((member 3)
1854       (emit-byte segment #b11001100))
1855      ((unsigned-byte 8)
1856       (emit-byte segment #b11001101)
1857       (emit-byte segment number)))))
1858
1859 (define-instruction into (segment)
1860   (:printer byte ((op #b11001110)))
1861   (:emitter
1862    (emit-byte segment #b11001110)))
1863
1864 (define-instruction bound (segment reg bounds)
1865   (:emitter
1866    (let ((size (matching-operand-size reg bounds)))
1867      (when (eq size :byte)
1868        (error "can't bounds-test bytes: ~S" reg))
1869      (maybe-emit-operand-size-prefix segment size)
1870      (emit-byte segment #b01100010)
1871      (emit-ea segment bounds (reg-tn-encoding reg)))))
1872
1873 (define-instruction iret (segment)
1874   (:printer byte ((op #b11001111)))
1875   (:emitter
1876    (emit-byte segment #b11001111)))
1877 \f
1878 ;;;; processor control
1879
1880 (define-instruction hlt (segment)
1881   (:printer byte ((op #b11110100)))
1882   (:emitter
1883    (emit-byte segment #b11110100)))
1884
1885 (define-instruction nop (segment)
1886   (:printer byte ((op #b10010000)))
1887   (:emitter
1888    (emit-byte segment #b10010000)))
1889
1890 (define-instruction wait (segment)
1891   (:printer byte ((op #b10011011)))
1892   (:emitter
1893    (emit-byte segment #b10011011)))
1894
1895 (define-instruction lock (segment)
1896   (:printer byte ((op #b11110000)))
1897   (:emitter
1898    (emit-byte segment #b11110000)))
1899 \f
1900 ;;;; miscellaneous hackery
1901
1902 (define-instruction byte (segment byte)
1903   (:emitter
1904    (emit-byte segment byte)))
1905
1906 (define-instruction word (segment word)
1907   (:emitter
1908    (emit-word segment word)))
1909
1910 (define-instruction dword (segment dword)
1911   (:emitter
1912    (emit-dword segment dword)))
1913
1914 (defun emit-header-data (segment type)
1915   (emit-back-patch segment
1916                    4
1917                    (lambda (segment posn)
1918                      (emit-dword segment
1919                                  (logior type
1920                                          (ash (+ posn
1921                                                  (component-header-length))
1922                                               (- n-widetag-bits
1923                                                  word-shift)))))))
1924
1925 (define-instruction simple-fun-header-word (segment)
1926   (:emitter
1927    (emit-header-data segment simple-fun-header-widetag)))
1928
1929 (define-instruction lra-header-word (segment)
1930   (:emitter
1931    (emit-header-data segment return-pc-header-widetag)))
1932 \f
1933 ;;;; fp instructions
1934 ;;;;
1935 ;;;; FIXME: This section said "added by jrd", which should end up in CREDITS.
1936 ;;;;
1937 ;;;; Note: We treat the single-precision and double-precision variants
1938 ;;;; as separate instructions.
1939
1940 ;;; Load single to st(0).
1941 (define-instruction fld (segment source)
1942   (:printer floating-point ((op '(#b001 #b000))))
1943   (:emitter
1944     (emit-byte segment #b11011001)
1945     (emit-fp-op segment source #b000)))
1946
1947 ;;; Load double to st(0).
1948 (define-instruction fldd (segment source)
1949   (:printer floating-point ((op '(#b101 #b000))))
1950   (:printer floating-point-fp ((op '(#b001 #b000))))
1951   (:emitter
1952    (if (fp-reg-tn-p source)
1953        (emit-byte segment #b11011001)
1954      (emit-byte segment #b11011101))
1955     (emit-fp-op segment source #b000)))
1956
1957 ;;; Load long to st(0).
1958 (define-instruction fldl (segment source)
1959   (:printer floating-point ((op '(#b011 #b101))))
1960   (:emitter
1961     (emit-byte segment #b11011011)
1962     (emit-fp-op segment source #b101)))
1963
1964 ;;; Store single from st(0).
1965 (define-instruction fst (segment dest)
1966   (:printer floating-point ((op '(#b001 #b010))))
1967   (:emitter
1968     (cond ((fp-reg-tn-p dest)
1969            (emit-byte segment #b11011101)
1970            (emit-fp-op segment dest #b010))
1971           (t
1972            (emit-byte segment #b11011001)
1973            (emit-fp-op segment dest #b010)))))
1974
1975 ;;; Store double from st(0).
1976 (define-instruction fstd (segment dest)
1977   (:printer floating-point ((op '(#b101 #b010))))
1978   (:printer floating-point-fp ((op '(#b101 #b010))))
1979   (:emitter
1980    (cond ((fp-reg-tn-p dest)
1981           (emit-byte segment #b11011101)
1982           (emit-fp-op segment dest #b010))
1983          (t
1984           (emit-byte segment #b11011101)
1985           (emit-fp-op segment dest #b010)))))
1986
1987 ;;; Arithmetic ops are all done with at least one operand at top of
1988 ;;; stack. The other operand is is another register or a 32/64 bit
1989 ;;; memory loc.
1990
1991 ;;; dtc: I've tried to follow the Intel ASM386 conventions, but note
1992 ;;; that these conflict with the Gdb conventions for binops. To reduce
1993 ;;; the confusion I've added comments showing the mathamatical
1994 ;;; operation and the two syntaxes. By the ASM386 convention the
1995 ;;; instruction syntax is:
1996 ;;;
1997 ;;;      Fop Source
1998 ;;; or   Fop Destination, Source
1999 ;;;
2000 ;;; If only one operand is given then it is the source and the
2001 ;;; destination is ST(0). There are reversed forms of the fsub and
2002 ;;; fdiv instructions inducated by an 'R' suffix.
2003 ;;;
2004 ;;; The mathematical operation for the non-reverse form is always:
2005 ;;;     destination = destination op source
2006 ;;;
2007 ;;; For the reversed form it is:
2008 ;;;     destination = source op destination
2009 ;;;
2010 ;;; The instructions below only accept one operand at present which is
2011 ;;; usually the source. I've hack in extra instructions to implement
2012 ;;; the fops with a ST(i) destination, these have a -sti suffix and
2013 ;;; the operand is the destination with the source being ST(0).
2014
2015 ;;; Add single:
2016 ;;;   st(0) = st(0) + memory or st(i).
2017 (define-instruction fadd (segment source)
2018   (:printer floating-point ((op '(#b000 #b000))))
2019   (:emitter
2020     (emit-byte segment #b11011000)
2021     (emit-fp-op segment source #b000)))
2022
2023 ;;; Add double:
2024 ;;;   st(0) = st(0) + memory or st(i).
2025 (define-instruction faddd (segment source)
2026   (:printer floating-point ((op '(#b100 #b000))))
2027   (:printer floating-point-fp ((op '(#b000 #b000))))
2028   (:emitter
2029    (if (fp-reg-tn-p source)
2030        (emit-byte segment #b11011000)
2031      (emit-byte segment #b11011100))
2032    (emit-fp-op segment source #b000)))
2033
2034 ;;; Add double destination st(i):
2035 ;;;   st(i) = st(0) + st(i).
2036 (define-instruction fadd-sti (segment destination)
2037   (:printer floating-point-fp ((op '(#b100 #b000))))
2038   (:emitter
2039    (aver (fp-reg-tn-p destination))
2040    (emit-byte segment #b11011100)
2041    (emit-fp-op segment destination #b000)))
2042 ;;; with pop
2043 (define-instruction faddp-sti (segment destination)
2044   (:printer floating-point-fp ((op '(#b110 #b000))))
2045   (:emitter
2046    (aver (fp-reg-tn-p destination))
2047    (emit-byte segment #b11011110)
2048    (emit-fp-op segment destination #b000)))
2049
2050 ;;; Subtract single:
2051 ;;;   st(0) = st(0) - memory or st(i).
2052 (define-instruction fsub (segment source)
2053   (:printer floating-point ((op '(#b000 #b100))))
2054   (:emitter
2055     (emit-byte segment #b11011000)
2056     (emit-fp-op segment source #b100)))
2057
2058 ;;; Subtract single, reverse:
2059 ;;;   st(0) = memory or st(i) - st(0).
2060 (define-instruction fsubr (segment source)
2061   (:printer floating-point ((op '(#b000 #b101))))
2062   (:emitter
2063     (emit-byte segment #b11011000)
2064     (emit-fp-op segment source #b101)))
2065
2066 ;;; Subtract double:
2067 ;;;   st(0) = st(0) - memory or st(i).
2068 (define-instruction fsubd (segment source)
2069   (:printer floating-point ((op '(#b100 #b100))))
2070   (:printer floating-point-fp ((op '(#b000 #b100))))
2071   (:emitter
2072    (if (fp-reg-tn-p source)
2073        (emit-byte segment #b11011000)
2074      (emit-byte segment #b11011100))
2075    (emit-fp-op segment source #b100)))
2076
2077 ;;; Subtract double, reverse:
2078 ;;;   st(0) = memory or st(i) - st(0).
2079 (define-instruction fsubrd (segment source)
2080   (:printer floating-point ((op '(#b100 #b101))))
2081   (:printer floating-point-fp ((op '(#b000 #b101))))
2082   (:emitter
2083    (if (fp-reg-tn-p source)
2084        (emit-byte segment #b11011000)
2085      (emit-byte segment #b11011100))
2086    (emit-fp-op segment source #b101)))
2087
2088 ;;; Subtract double, destination st(i):
2089 ;;;   st(i) = st(i) - st(0).
2090 ;;;
2091 ;;; ASM386 syntax: FSUB ST(i), ST
2092 ;;; Gdb    syntax: fsubr %st,%st(i)
2093 (define-instruction fsub-sti (segment destination)
2094   (:printer floating-point-fp ((op '(#b100 #b101))))
2095   (:emitter
2096    (aver (fp-reg-tn-p destination))
2097    (emit-byte segment #b11011100)
2098    (emit-fp-op segment destination #b101)))
2099 ;;; with a pop
2100 (define-instruction fsubp-sti (segment destination)
2101   (:printer floating-point-fp ((op '(#b110 #b101))))
2102   (:emitter
2103    (aver (fp-reg-tn-p destination))
2104    (emit-byte segment #b11011110)
2105    (emit-fp-op segment destination #b101)))
2106
2107 ;;; Subtract double, reverse, destination st(i):
2108 ;;;   st(i) = st(0) - st(i).
2109 ;;;
2110 ;;; ASM386 syntax: FSUBR ST(i), ST
2111 ;;; Gdb    syntax: fsub %st,%st(i)
2112 (define-instruction fsubr-sti (segment destination)
2113   (:printer floating-point-fp ((op '(#b100 #b100))))
2114   (:emitter
2115    (aver (fp-reg-tn-p destination))
2116    (emit-byte segment #b11011100)
2117    (emit-fp-op segment destination #b100)))
2118 ;;; with a pop
2119 (define-instruction fsubrp-sti (segment destination)
2120   (:printer floating-point-fp ((op '(#b110 #b100))))
2121   (:emitter
2122    (aver (fp-reg-tn-p destination))
2123    (emit-byte segment #b11011110)
2124    (emit-fp-op segment destination #b100)))
2125
2126 ;;; Multiply single:
2127 ;;;   st(0) = st(0) * memory or st(i).
2128 (define-instruction fmul (segment source)
2129   (:printer floating-point ((op '(#b000 #b001))))
2130   (:emitter
2131     (emit-byte segment #b11011000)
2132     (emit-fp-op segment source #b001)))
2133
2134 ;;; Multiply double:
2135 ;;;   st(0) = st(0) * memory or st(i).
2136 (define-instruction fmuld (segment source)
2137   (:printer floating-point ((op '(#b100 #b001))))
2138   (:printer floating-point-fp ((op '(#b000 #b001))))
2139   (:emitter
2140    (if (fp-reg-tn-p source)
2141        (emit-byte segment #b11011000)
2142      (emit-byte segment #b11011100))
2143    (emit-fp-op segment source #b001)))
2144
2145 ;;; Multiply double, destination st(i):
2146 ;;;   st(i) = st(i) * st(0).
2147 (define-instruction fmul-sti (segment destination)
2148   (:printer floating-point-fp ((op '(#b100 #b001))))
2149   (:emitter
2150    (aver (fp-reg-tn-p destination))
2151    (emit-byte segment #b11011100)
2152    (emit-fp-op segment destination #b001)))
2153
2154 ;;; Divide single:
2155 ;;;   st(0) = st(0) / memory or st(i).
2156 (define-instruction fdiv (segment source)
2157   (:printer floating-point ((op '(#b000 #b110))))
2158   (:emitter
2159     (emit-byte segment #b11011000)
2160     (emit-fp-op segment source #b110)))
2161
2162 ;;; Divide single, reverse:
2163 ;;;   st(0) = memory or st(i) / st(0).
2164 (define-instruction fdivr (segment source)
2165   (:printer floating-point ((op '(#b000 #b111))))
2166   (:emitter
2167     (emit-byte segment #b11011000)
2168     (emit-fp-op segment source #b111)))
2169
2170 ;;; Divide double:
2171 ;;;   st(0) = st(0) / memory or st(i).
2172 (define-instruction fdivd (segment source)
2173   (:printer floating-point ((op '(#b100 #b110))))
2174   (:printer floating-point-fp ((op '(#b000 #b110))))
2175   (:emitter
2176    (if (fp-reg-tn-p source)
2177        (emit-byte segment #b11011000)
2178      (emit-byte segment #b11011100))
2179    (emit-fp-op segment source #b110)))
2180
2181 ;;; Divide double, reverse:
2182 ;;;   st(0) = memory or st(i) / st(0).
2183 (define-instruction fdivrd (segment source)
2184   (:printer floating-point ((op '(#b100 #b111))))
2185   (:printer floating-point-fp ((op '(#b000 #b111))))
2186   (:emitter
2187    (if (fp-reg-tn-p source)
2188        (emit-byte segment #b11011000)
2189      (emit-byte segment #b11011100))
2190    (emit-fp-op segment source #b111)))
2191
2192 ;;; Divide double, destination st(i):
2193 ;;;   st(i) = st(i) / st(0).
2194 ;;;
2195 ;;; ASM386 syntax: FDIV ST(i), ST
2196 ;;; Gdb    syntax: fdivr %st,%st(i)
2197 (define-instruction fdiv-sti (segment destination)
2198   (:printer floating-point-fp ((op '(#b100 #b111))))
2199   (:emitter
2200    (aver (fp-reg-tn-p destination))
2201    (emit-byte segment #b11011100)
2202    (emit-fp-op segment destination #b111)))
2203
2204 ;;; Divide double, reverse, destination st(i):
2205 ;;;   st(i) = st(0) / st(i).
2206 ;;;
2207 ;;; ASM386 syntax: FDIVR ST(i), ST
2208 ;;; Gdb    syntax: fdiv %st,%st(i)
2209 (define-instruction fdivr-sti (segment destination)
2210   (:printer floating-point-fp ((op '(#b100 #b110))))
2211   (:emitter
2212    (aver (fp-reg-tn-p destination))
2213    (emit-byte segment #b11011100)
2214    (emit-fp-op segment destination #b110)))
2215
2216 ;;; Exchange fr0 with fr(n). (There is no double precision variant.)
2217 (define-instruction fxch (segment source)
2218   (:printer floating-point-fp ((op '(#b001 #b001))))
2219   (:emitter
2220     (unless (and (tn-p source)
2221                  (eq (sb-name (sc-sb (tn-sc source))) 'float-registers))
2222       (cl:break))
2223     (emit-byte segment #b11011001)
2224     (emit-fp-op segment source #b001)))
2225
2226 ;;; Push 32-bit integer to st0.
2227 (define-instruction fild (segment source)
2228   (:printer floating-point ((op '(#b011 #b000))))
2229   (:emitter
2230    (emit-byte segment #b11011011)
2231    (emit-fp-op segment source #b000)))
2232
2233 ;;; Push 64-bit integer to st0.
2234 (define-instruction fildl (segment source)
2235   (:printer floating-point ((op '(#b111 #b101))))
2236   (:emitter
2237    (emit-byte segment #b11011111)
2238    (emit-fp-op segment source #b101)))
2239
2240 ;;; Store 32-bit integer.
2241 (define-instruction fist (segment dest)
2242   (:printer floating-point ((op '(#b011 #b010))))
2243   (:emitter
2244    (emit-byte segment #b11011011)
2245    (emit-fp-op segment dest #b010)))
2246
2247 ;;; Store and pop 32-bit integer.
2248 (define-instruction fistp (segment dest)
2249   (:printer floating-point ((op '(#b011 #b011))))
2250   (:emitter
2251    (emit-byte segment #b11011011)
2252    (emit-fp-op segment dest #b011)))
2253
2254 ;;; Store and pop 64-bit integer.
2255 (define-instruction fistpl (segment dest)
2256   (:printer floating-point ((op '(#b111 #b111))))
2257   (:emitter
2258    (emit-byte segment #b11011111)
2259    (emit-fp-op segment dest #b111)))
2260
2261 ;;; Store single from st(0) and pop.
2262 (define-instruction fstp (segment dest)
2263   (:printer floating-point ((op '(#b001 #b011))))
2264   (:emitter
2265    (cond ((fp-reg-tn-p dest)
2266           (emit-byte segment #b11011101)
2267           (emit-fp-op segment dest #b011))
2268          (t
2269           (emit-byte segment #b11011001)
2270           (emit-fp-op segment dest #b011)))))
2271
2272 ;;; Store double from st(0) and pop.
2273 (define-instruction fstpd (segment dest)
2274   (:printer floating-point ((op '(#b101 #b011))))
2275   (:printer floating-point-fp ((op '(#b101 #b011))))
2276   (:emitter
2277    (cond ((fp-reg-tn-p dest)
2278           (emit-byte segment #b11011101)
2279           (emit-fp-op segment dest #b011))
2280          (t
2281           (emit-byte segment #b11011101)
2282           (emit-fp-op segment dest #b011)))))
2283
2284 ;;; Store long from st(0) and pop.
2285 (define-instruction fstpl (segment dest)
2286   (:printer floating-point ((op '(#b011 #b111))))
2287   (:emitter
2288     (emit-byte segment #b11011011)
2289     (emit-fp-op segment dest #b111)))
2290
2291 ;;; Decrement stack-top pointer.
2292 (define-instruction fdecstp (segment)
2293   (:printer floating-point-no ((op #b10110)))
2294   (:emitter
2295    (emit-byte segment #b11011001)
2296    (emit-byte segment #b11110110)))
2297
2298 ;;; Increment stack-top pointer.
2299 (define-instruction fincstp (segment)
2300   (:printer floating-point-no ((op #b10111)))
2301   (:emitter
2302    (emit-byte segment #b11011001)
2303    (emit-byte segment #b11110111)))
2304
2305 ;;; Free fp register.
2306 (define-instruction ffree (segment dest)
2307   (:printer floating-point-fp ((op '(#b101 #b000))))
2308   (:emitter
2309    (emit-byte segment #b11011101)
2310    (emit-fp-op segment dest #b000)))
2311
2312 (define-instruction fabs (segment)
2313   (:printer floating-point-no ((op #b00001)))
2314   (:emitter
2315    (emit-byte segment #b11011001)
2316    (emit-byte segment #b11100001)))
2317
2318 (define-instruction fchs (segment)
2319   (:printer floating-point-no ((op #b00000)))
2320   (:emitter
2321    (emit-byte segment #b11011001)
2322    (emit-byte segment #b11100000)))
2323
2324 (define-instruction frndint(segment)
2325   (:printer floating-point-no ((op #b11100)))
2326   (:emitter
2327    (emit-byte segment #b11011001)
2328    (emit-byte segment #b11111100)))
2329
2330 ;;; Initialize NPX.
2331 (define-instruction fninit(segment)
2332   (:printer floating-point-5 ((op #b00011)))
2333   (:emitter
2334    (emit-byte segment #b11011011)
2335    (emit-byte segment #b11100011)))
2336
2337 ;;; Store Status Word to AX.
2338 (define-instruction fnstsw(segment)
2339   (:printer floating-point-st ((op #b00000)))
2340   (:emitter
2341    (emit-byte segment #b11011111)
2342    (emit-byte segment #b11100000)))
2343
2344 ;;; Load Control Word.
2345 ;;;
2346 ;;; src must be a memory location
2347 (define-instruction fldcw(segment src)
2348   (:printer floating-point ((op '(#b001 #b101))))
2349   (:emitter
2350    (emit-byte segment #b11011001)
2351    (emit-fp-op segment src #b101)))
2352
2353 ;;; Store Control Word.
2354 (define-instruction fnstcw(segment dst)
2355   (:printer floating-point ((op '(#b001 #b111))))
2356   (:emitter
2357    (emit-byte segment #b11011001)
2358    (emit-fp-op segment dst #b111)))
2359
2360 ;;; Store FP Environment.
2361 (define-instruction fstenv(segment dst)
2362   (:printer floating-point ((op '(#b001 #b110))))
2363   (:emitter
2364    (emit-byte segment #b11011001)
2365    (emit-fp-op segment dst #b110)))
2366
2367 ;;; Restore FP Environment.
2368 (define-instruction fldenv(segment src)
2369   (:printer floating-point ((op '(#b001 #b100))))
2370   (:emitter
2371    (emit-byte segment #b11011001)
2372    (emit-fp-op segment src #b100)))
2373
2374 ;;; Save FP State.
2375 (define-instruction fsave(segment dst)
2376   (:printer floating-point ((op '(#b101 #b110))))
2377   (:emitter
2378    (emit-byte segment #b11011101)
2379    (emit-fp-op segment dst #b110)))
2380
2381 ;;; Restore FP State.
2382 (define-instruction frstor(segment src)
2383   (:printer floating-point ((op '(#b101 #b100))))
2384   (:emitter
2385    (emit-byte segment #b11011101)
2386    (emit-fp-op segment src #b100)))
2387
2388 ;;; Clear exceptions.
2389 (define-instruction fnclex(segment)
2390   (:printer floating-point-5 ((op #b00010)))
2391   (:emitter
2392    (emit-byte segment #b11011011)
2393    (emit-byte segment #b11100010)))
2394
2395 ;;; comparison
2396 (define-instruction fcom (segment src)
2397   (:printer floating-point ((op '(#b000 #b010))))
2398   (:emitter
2399    (emit-byte segment #b11011000)
2400    (emit-fp-op segment src #b010)))
2401
2402 (define-instruction fcomd (segment src)
2403   (:printer floating-point ((op '(#b100 #b010))))
2404   (:printer floating-point-fp ((op '(#b000 #b010))))
2405   (:emitter
2406    (if (fp-reg-tn-p src)
2407        (emit-byte segment #b11011000)
2408      (emit-byte segment #b11011100))
2409    (emit-fp-op segment src #b010)))
2410
2411 ;;; Compare ST1 to ST0, popping the stack twice.
2412 (define-instruction fcompp (segment)
2413   (:printer floating-point-3 ((op '(#b110 #b011001))))
2414   (:emitter
2415    (emit-byte segment #b11011110)
2416    (emit-byte segment #b11011001)))
2417
2418 ;;; unordered comparison
2419 (define-instruction fucom (segment src)
2420   ;; XX Printer conflicts with frstor
2421   ;; (:printer floating-point ((op '(#b101 #b100))))
2422   (:emitter
2423    (aver (fp-reg-tn-p src))
2424    (emit-byte segment #b11011101)
2425    (emit-fp-op segment src #b100)))
2426
2427 (define-instruction ftst (segment)
2428   (:printer floating-point-no ((op #b00100)))
2429   (:emitter
2430    (emit-byte segment #b11011001)
2431    (emit-byte segment #b11100100)))
2432
2433 ;;;; 80387 specials
2434
2435 (define-instruction fsqrt(segment)
2436   (:printer floating-point-no ((op #b11010)))
2437   (:emitter
2438    (emit-byte segment #b11011001)
2439    (emit-byte segment #b11111010)))
2440
2441 (define-instruction fscale(segment)
2442   (:printer floating-point-no ((op #b11101)))
2443   (:emitter
2444    (emit-byte segment #b11011001)
2445    (emit-byte segment #b11111101)))
2446
2447 (define-instruction fxtract(segment)
2448   (:printer floating-point-no ((op #b10100)))
2449   (:emitter
2450    (emit-byte segment #b11011001)
2451    (emit-byte segment #b11110100)))
2452
2453 (define-instruction fsin(segment)
2454   (:printer floating-point-no ((op #b11110)))
2455   (:emitter
2456    (emit-byte segment #b11011001)
2457    (emit-byte segment #b11111110)))
2458
2459 (define-instruction fcos(segment)
2460   (:printer floating-point-no ((op #b11111)))
2461   (:emitter
2462    (emit-byte segment #b11011001)
2463    (emit-byte segment #b11111111)))
2464
2465 (define-instruction fprem1(segment)
2466   (:printer floating-point-no ((op #b10101)))
2467   (:emitter
2468    (emit-byte segment #b11011001)
2469    (emit-byte segment #b11110101)))
2470
2471 (define-instruction fprem(segment)
2472   (:printer floating-point-no ((op #b11000)))
2473   (:emitter
2474    (emit-byte segment #b11011001)
2475    (emit-byte segment #b11111000)))
2476
2477 (define-instruction fxam (segment)
2478   (:printer floating-point-no ((op #b00101)))
2479   (:emitter
2480    (emit-byte segment #b11011001)
2481    (emit-byte segment #b11100101)))
2482
2483 ;;; These do push/pop to stack and need special handling
2484 ;;; in any VOPs that use them. See the book.
2485
2486 ;;; st0 <- st1*log2(st0)
2487 (define-instruction fyl2x(segment)      ; pops stack
2488   (:printer floating-point-no ((op #b10001)))
2489   (:emitter
2490    (emit-byte segment #b11011001)
2491    (emit-byte segment #b11110001)))
2492
2493 (define-instruction fyl2xp1(segment)
2494   (:printer floating-point-no ((op #b11001)))
2495   (:emitter
2496    (emit-byte segment #b11011001)
2497    (emit-byte segment #b11111001)))
2498
2499 (define-instruction f2xm1(segment)
2500   (:printer floating-point-no ((op #b10000)))
2501   (:emitter
2502    (emit-byte segment #b11011001)
2503    (emit-byte segment #b11110000)))
2504
2505 (define-instruction fptan(segment)      ; st(0) <- 1; st(1) <- tan
2506   (:printer floating-point-no ((op #b10010)))
2507   (:emitter
2508    (emit-byte segment #b11011001)
2509    (emit-byte segment #b11110010)))
2510
2511 (define-instruction fpatan(segment)     ; POPS STACK
2512   (:printer floating-point-no ((op #b10011)))
2513   (:emitter
2514    (emit-byte segment #b11011001)
2515    (emit-byte segment #b11110011)))
2516
2517 ;;;; loading constants
2518
2519 (define-instruction fldz(segment)
2520   (:printer floating-point-no ((op #b01110)))
2521   (:emitter
2522    (emit-byte segment #b11011001)
2523    (emit-byte segment #b11101110)))
2524
2525 (define-instruction fld1(segment)
2526   (:printer floating-point-no ((op #b01000)))
2527   (:emitter
2528    (emit-byte segment #b11011001)
2529    (emit-byte segment #b11101000)))
2530
2531 (define-instruction fldpi(segment)
2532   (:printer floating-point-no ((op #b01011)))
2533   (:emitter
2534    (emit-byte segment #b11011001)
2535    (emit-byte segment #b11101011)))
2536
2537 (define-instruction fldl2t(segment)
2538   (:printer floating-point-no ((op #b01001)))
2539   (:emitter
2540    (emit-byte segment #b11011001)
2541    (emit-byte segment #b11101001)))
2542
2543 (define-instruction fldl2e(segment)
2544   (:printer floating-point-no ((op #b01010)))
2545   (:emitter
2546    (emit-byte segment #b11011001)
2547    (emit-byte segment #b11101010)))
2548
2549 (define-instruction fldlg2(segment)
2550   (:printer floating-point-no ((op #b01100)))
2551   (:emitter
2552    (emit-byte segment #b11011001)
2553    (emit-byte segment #b11101100)))
2554
2555 (define-instruction fldln2(segment)
2556   (:printer floating-point-no ((op #b01101)))
2557   (:emitter
2558    (emit-byte segment #b11011001)
2559    (emit-byte segment #b11101101)))