bd3589cf368568ee75013c31b590193ab90d9a8d
[sbcl.git] / src / compiler / sparc / insts.lisp
1 ;;;; the instruction set definition for the Sparc
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!VM")
13
14 ;;;FIXME: the analogue is commented out in alpha/insts.lisp
15 ;;;(def-assembler-params
16 ;;;    :scheduler-p t
17 ;;;  :max-locations 100)
18 \f
19 ;;; Constants, types, conversion functions, some disassembler stuff.
20 (defun reg-tn-encoding (tn)
21   (declare (type tn tn))
22   (sc-case tn
23     (zero zero-offset)
24     (null null-offset)
25     (t
26      (if (eq (sb-name (sc-sb (tn-sc tn))) 'registers)
27          (tn-offset tn)
28          (error "~S isn't a register." tn)))))
29
30 (defun fp-reg-tn-encoding (tn)
31   (declare (type tn tn))
32   (unless (eq (sb-name (sc-sb (tn-sc tn))) 'float-registers)
33     (error "~S isn't a floating-point register." tn))
34   (let ((offset (tn-offset tn)))
35     (cond ((> offset 31)
36            (assert (member :sparc-v9 *backend-subfeatures*))
37            ;; No single register encoding greater than reg 31.
38            (assert (zerop (mod offset 2)))
39            ;; Upper bit of the register number is encoded in the low bit.
40            (1+ (- offset 32)))
41           (t
42            (tn-offset tn)))))
43
44 ;;;(sb!disassem:set-disassem-params :instruction-alignment 32
45 ;;;                              :opcode-column-width 11)
46
47 (defvar *disassem-use-lisp-reg-names* t
48   #!+sb-doc
49   "If non-NIL, print registers using the Lisp register names.
50 Otherwise, use the Sparc register names")
51
52 (!def-vm-support-routine location-number (loc)
53   (etypecase loc
54     (null)
55     (number)
56     (fixup)
57     (tn
58      (ecase (sb-name (sc-sb (tn-sc loc)))
59        (registers
60         (unless (zerop (tn-offset loc))
61           (tn-offset loc)))
62        (float-registers
63         (sc-case loc
64           (single-reg
65            (+ (tn-offset loc) 32))
66           (double-reg
67            (let ((offset (tn-offset loc)))
68              (assert (zerop (mod offset 2)))
69              (values (+ offset 32) 2)))
70           #!+long-float
71           (long-reg
72            (let ((offset (tn-offset loc)))
73              (assert (zerop (mod offset 4)))
74              (values (+ offset 32) 4)))))
75        (control-registers
76         96)
77        (immediate-constant
78         nil)))
79     (symbol
80      (ecase loc
81        (:memory 0)
82        (:psr 97)
83        (:fsr 98)
84        (:y 99)))))
85
86 ;;; symbols used for disassembly printing
87 (defparameter reg-symbols
88   (map 'vector
89        (lambda (name)
90            (cond ((null name) nil)
91                  (t (make-symbol (concatenate 'string "%" name)))))
92        *register-names*)
93   #!+sb-doc "The Lisp names for the Sparc integer registers")
94
95 (defparameter sparc-reg-symbols
96   #("%G0" "%G1" "%G2" "%G3" "%G4" "%G5" NIL NIL
97     "%O0" "%O1" "%O2" "%O3" "%O4" "%O5" "%O6" "%O7"
98     "%L0" "%L1" "%L2" "%L3" "%L4" "%L5" "%L6" "%L7"
99     "%I0" "%I1" "%I2" "%I3" "%I4" "%I5" NIL "%I7")
100   #!+sb-doc "The standard names for the Sparc integer registers")
101     
102 (defun get-reg-name (index)
103   (if *disassem-use-lisp-reg-names*
104       (aref reg-symbols index)
105       (aref sparc-reg-symbols index)))
106
107 (defvar *note-sethi-inst* nil
108   "An alist for the disassembler indicating the target register and
109 value used in a SETHI instruction.  This is used to make annotations
110 about function addresses and register values.")
111
112 (defvar *pseudo-atomic-set* nil)
113
114 (defun sign-extend-immed-value (val)
115   ;; val is a 13-bit signed number.  Extend the sign appropriately.
116   (if (logbitp 12 val)
117       (- val (ash 1 13))
118       val))
119
120 ;;; Oh, come on, this is ridiculous. I'm not going to solve
121 ;;; bootstrapping issues for a disassembly note. Does this make me
122 ;;; lazy? Christophe, 2001-09-02. FIXME
123 #+nil
124 (macrolet
125     ((frob (&rest names)
126        (let ((results (mapcar (lambda (n)
127                                   (let ((nn (intern (concatenate 'string (string n)
128                                                                  "-TYPE"))))
129                                     `(,(eval nn) ,nn)))
130                               names)))
131          `(eval-when (:compile-toplevel :load-toplevel :execute)
132            (def!constant header-word-type-alist
133              ',results)))))
134   ;; This is the same list as in objdefs.
135   (frob bignum
136         ratio
137         single-float
138         double-float
139         #!+long-float long-float
140         complex
141         complex-single-float
142         complex-double-float
143         #!+long-float complex-long-float
144   
145         simple-array
146         simple-string
147         simple-bit-vector
148         simple-vector
149         simple-array-unsigned-byte-2
150         simple-array-unsigned-byte-4
151         simple-array-unsigned-byte-8
152         simple-array-unsigned-byte-16
153         simple-array-unsigned-byte-32
154         simple-array-signed-byte-8
155         simple-array-signed-byte-16
156         simple-array-signed-byte-30
157         simple-array-signed-byte-32
158         simple-array-single-float
159         simple-array-double-float
160         #!+long-float simple-array-long-float
161         simple-array-complex-single-float
162         simple-array-complex-double-float
163         #!+long-float simple-array-complex-long-float
164         complex-string
165         complex-bit-vector
166         complex-vector
167         complex-array
168   
169         code-header
170         function-header
171         closure-header
172         funcallable-instance-header
173         byte-code-function
174         byte-code-closure
175         closure-function-header
176         #!-gengc return-pc-header
177         #!+gengc forwarding-pointer
178         value-cell-header
179         symbol-header
180         base-char
181         sap
182         unbound-marker
183         weak-pointer
184         instance-header
185         fdefn
186         #!+(or gengc gencgc) scavenger-hook))
187
188 ;; Look at the current instruction and see if we can't add some notes
189 ;; about what's happening.
190
191 (defun maybe-add-notes (reg dstate)
192   (let* ((word (sb!disassem::sap-ref-int (sb!disassem::dstate-segment-sap dstate)
193                                       (sb!disassem::dstate-cur-offs dstate)
194                                       n-word-bytes
195                                       (sb!disassem::dstate-byte-order dstate)))
196          (format (ldb (byte 2 30) word))
197          (op3 (ldb (byte 6 19) word))
198          (rs1 (ldb (byte 5 14) word))
199          (rd (ldb (byte 5 25) word))
200          (immed-p (not (zerop (ldb (byte 1 13) word))))
201          (immed-val (sign-extend-immed-value (ldb (byte 13 0) word))))
202     ;; Only the value of format and rd are guaranteed to be correct
203     ;; because the disassembler is trying to print out the value of a
204     ;; register.  The other values may not be right.
205     (case format
206       (2
207        (case op3
208          (#b000000
209           (when (= reg rs1)
210             (handle-add-inst rs1 immed-val rd dstate)))
211          (#b111000
212           (when (= reg rs1)
213             (handle-jmpl-inst rs1 immed-val rd dstate)))
214          (#b010001
215           (when (= reg rs1)
216             (handle-andcc-inst rs1 immed-val rd dstate)))))
217       (3
218        (case op3
219          ((#b000000 #b000100)
220           (when (= reg rs1)
221             (handle-ld/st-inst rs1 immed-val rd dstate))))))
222     ;; If this is not a SETHI instruction, and RD is the same as some
223     ;; register used by SETHI, we delete the entry.  (In case we have
224     ;; a SETHI without any additional instruction because the low bits
225     ;; were zero.)
226     (unless (and (zerop format) (= #b100 (ldb (byte 3 22) word)))
227       (let ((sethi (assoc rd *note-sethi-inst*)))
228         (when sethi
229           (setf *note-sethi-inst* (delete sethi *note-sethi-inst*)))))))
230
231 (defun handle-add-inst (rs1 immed-val rd dstate)
232   (let* ((sethi (assoc rs1 *note-sethi-inst*)))
233     (cond
234       (sethi
235        ;; RS1 was used in a SETHI instruction.  Assume that
236        ;; this is the offset part of the SETHI instruction for
237        ;; a full 32-bit address of something.  Make a note
238        ;; about this usage as a Lisp assembly routine or
239        ;; foreign routine, if possible.  If not, just note the
240        ;; final value.
241        (let ((addr (+ immed-val (ash (cdr sethi) 10))))
242          (or (sb!disassem::note-code-constant-absolute addr dstate)
243              (sb!disassem:maybe-note-assembler-routine addr t dstate)
244              (sb!disassem:note (format nil "~A = #x~8,'0X"
245                                      (get-reg-name rd) addr)
246                              dstate)))
247        (setf *note-sethi-inst* (delete sethi *note-sethi-inst*)))
248       ((= rs1 null-offset)
249        ;; We have an ADD %NULL, <n>, RD instruction.  This is a
250        ;; reference to a static symbol.
251        (sb!disassem:maybe-note-nil-indexed-object immed-val
252                                                dstate))
253       ((= rs1 alloc-offset)
254        ;; ADD %ALLOC, n.  This must be some allocation or
255        ;; pseudo-atomic stuff
256        (cond ((and (= immed-val 4) (= rd alloc-offset)
257                    (not *pseudo-atomic-set*))
258               ;; "ADD 4, %ALLOC" sets the flag
259               (sb!disassem::note "Set pseudo-atomic flag" dstate)
260               (setf *pseudo-atomic-set* t))
261              ((= rd alloc-offset)
262               ;; "ADD n, %ALLOC" is reseting the flag, with extra
263               ;; allocation.
264               (sb!disassem:note
265                (format nil "Reset pseudo-atomic, allocated ~D bytes"
266                        (+ immed-val 4)) dstate)
267               (setf *pseudo-atomic-set* nil))))
268       #+nil ((and (= rs1 zero-offset) *pseudo-atomic-set*)
269        ;; "ADD %ZERO, num, RD" inside a pseudo-atomic is very
270        ;; likely loading up a header word.  Make a note to that
271        ;; effect.
272        (let ((type (second (assoc (logand immed-val #xff) header-word-type-alist)))
273              (size (ldb (byte 24 8) immed-val)))
274          (when type
275            (sb!disassem:note (format nil "Header word ~A, size ~D?" type size)
276                           dstate)))))))
277
278 (defun handle-jmpl-inst (rs1 immed-val rd dstate)
279   (let* ((sethi (assoc rs1 *note-sethi-inst*)))
280     (when sethi
281       ;; RS1 was used in a SETHI instruction.  Assume that
282       ;; this is the offset part of the SETHI instruction for
283       ;; a full 32-bit address of something.  Make a note
284       ;; about this usage as a Lisp assembly routine or
285       ;; foreign routine, if possible.  If not, just note the
286       ;; final value.
287       (let ((addr (+ immed-val (ash (cdr sethi) 10))))
288         (sb!disassem:maybe-note-assembler-routine addr t dstate)
289         (setf *note-sethi-inst* (delete sethi *note-sethi-inst*))))))
290
291 (defun handle-ld/st-inst (rs1 immed-val rd dstate)
292   (declare (ignore rd))
293   ;; Got an LDUW/LD or STW instruction, with immediate offset.
294   (case rs1
295     (29
296      ;; A reference to a code constant (reg = %CODE)
297      (sb!disassem:note-code-constant immed-val dstate))
298     (2
299      ;; A reference to a static symbol or static function (reg =
300      ;; %NULL)
301      (or (sb!disassem:maybe-note-nil-indexed-symbol-slot-ref immed-val
302                                                       dstate)
303          #+nil (sb!disassem::maybe-note-static-function immed-val dstate)))
304     (t
305      (let ((sethi (assoc rs1 *note-sethi-inst*)))
306        (when sethi
307          (let ((addr (+ immed-val (ash (cdr sethi) 10))))
308            (sb!disassem:maybe-note-assembler-routine addr nil dstate)
309            (setf *note-sethi-inst* (delete sethi *note-sethi-inst*))))))))
310
311 (defun handle-andcc-inst (rs1 immed-val rd dstate)
312   ;; ANDCC %ALLOC, 3, %ZERO instruction
313   (when (and (= rs1 alloc-offset) (= rd zero-offset) (= immed-val 3))
314     (sb!disassem:note "pseudo-atomic interrupted?" dstate)))
315          
316 (sb!disassem:define-arg-type reg
317   :printer (lambda (value stream dstate)
318                (declare (stream stream) (fixnum value))
319                (let ((regname (get-reg-name value)))
320                  (princ regname stream)
321                  (sb!disassem:maybe-note-associated-storage-ref value
322                                                                 'registers
323                                                                 regname
324                                                                 dstate)
325                  (maybe-add-notes value dstate))))
326
327 (defparameter float-reg-symbols
328   (coerce 
329    (loop for n from 0 to 63 collect (make-symbol (format nil "%F~d" n)))
330    'vector))
331
332 (sb!disassem:define-arg-type fp-reg
333   :printer (lambda (value stream dstate)
334                (declare (stream stream) (fixnum value))
335                (let ((regname (aref float-reg-symbols value)))
336                  (princ regname stream)
337                  (sb!disassem:maybe-note-associated-storage-ref
338                   value
339                   'float-registers
340                   regname
341                   dstate))))
342
343 ;;; The extended 6 bit floating point register encoding for the double
344 ;;; and long instructions of the sparc v9.
345 (sb!disassem:define-arg-type fp-ext-reg
346   :printer (lambda (value stream dstate)
347                (declare (stream stream) (fixnum value))
348                (let* (;; Decode the register number.
349                       (value (if (oddp value) (+ value 31) value))
350                       (regname (aref float-reg-symbols value)))
351                  (princ regname stream)
352                  (sb!disassem:maybe-note-associated-storage-ref
353                   value
354                   'float-registers
355                   regname
356                   dstate))))
357
358 (sb!disassem:define-arg-type relative-label
359   :sign-extend t
360   :use-label (lambda (value dstate)
361                (declare (type (signed-byte 22) value)
362                         (type sb!disassem:disassem-state dstate))
363                (+ (ash value 2) (sb!disassem:dstate-cur-addr dstate))))
364
365 (defconstant-eqx branch-conditions
366   '(:f :eq :le :lt :leu :ltu :n :vs :t :ne :gt :ge :gtu :geu :p :vc)
367   #'equalp)
368
369 ;;; Note that these aren't the standard names for branch-conditions, I
370 ;;; think they're a bit more readable (e.g., "eq" instead of "e").
371 ;;; You could just put a vector of the normal ones here too.
372
373 (sb!disassem:define-arg-type branch-condition
374   :printer (coerce branch-conditions 'vector))
375
376 (deftype branch-condition ()
377   `(member ,@branch-conditions))
378
379 (defun branch-condition (condition)
380   (or (position condition branch-conditions)
381       (error "Unknown branch condition: ~S~%Must be one of: ~S"
382              condition branch-conditions)))
383
384 (def!constant branch-cond-true
385   #b1000)
386
387 (defconstant-eqx branch-fp-conditions
388   '(:f :ne :lg :ul :l :ug :g :u :t :eq :ue :ge :uge :le :ule :o)
389   #'equalp)
390
391 (sb!disassem:define-arg-type branch-fp-condition
392   :printer (coerce branch-fp-conditions 'vector))
393
394 (sb!disassem:define-arg-type call-fixup :use-label t)
395
396 (deftype fp-branch-condition ()
397   `(member ,@branch-fp-conditions))
398
399 (defun fp-branch-condition (condition)
400   (or (position condition branch-fp-conditions)
401       (error "Unknown fp-branch condition: ~S~%Must be one of: ~S"
402              condition branch-fp-conditions)))
403
404 \f
405 ;;;; dissassem:define-instruction-formats
406
407 (sb!disassem:define-instruction-format
408     (format-1 32 :default-printer '(:name :tab disp))
409   (op   :field (byte 2 30) :value 1)
410   (disp :field (byte 30 0)))
411
412 (sb!disassem:define-instruction-format
413     (format-2-immed 32 :default-printer '(:name :tab immed ", " rd))
414   (op    :field (byte 2 30) :value 0)
415   (rd    :field (byte 5 25) :type 'reg)
416   (op2   :field (byte 3 22))
417   (immed :field (byte 22 0)))
418
419   
420
421 (sb!disassem:define-instruction-format
422     (format-2-branch 32 :default-printer `(:name (:unless (:constant ,branch-cond-true) cond)
423                                            (:unless (a :constant 0) "," 'A)
424                                            :tab
425                                            disp))
426   (op   :field (byte 2 30) :value 0)
427   (a    :field (byte 1 29) :value 0)
428   (cond :field (byte 4 25) :type 'branch-condition)
429   (op2  :field (byte 3 22))
430   (disp :field (byte 22 0) :type 'relative-label))
431
432 ;; Branch with prediction instruction for V9
433
434 ;; Currently only %icc and %xcc are used of the four possible values
435
436 (defconstant-eqx integer-condition-registers
437   '(:icc :reserved :xcc :reserved)
438   #'equalp)
439
440 (defconstant-eqx integer-cond-reg-name-vec
441   (coerce integer-condition-registers 'vector)
442   #'equalp)
443
444 (deftype integer-condition-register ()
445   `(member ,@(remove :reserved integer-condition-registers)))
446
447 (defparameter integer-condition-reg-symbols
448   (map 'vector
449        (lambda (name)
450            (make-symbol (concatenate 'string "%" (string name))))
451        integer-condition-registers))
452
453 (sb!disassem:define-arg-type integer-condition-register
454     :printer (lambda (value stream dstate)
455                  (declare (stream stream) (fixnum value) (ignore dstate))
456                  (let ((regname (aref integer-condition-reg-symbols value)))
457                    (princ regname stream))))
458
459 (defconstant-eqx branch-predictions
460   '(:pn :pt)
461   #'equalp)
462
463 (sb!disassem:define-arg-type branch-prediction
464     :printer (coerce branch-predictions 'vector))
465
466 (defun integer-condition (condition-reg)
467   (declare (type (member :icc :xcc) condition-reg))
468   (or (position condition-reg integer-condition-registers)
469       (error "Unknown integer condition register:  ~S~%"
470              condition-reg)))
471
472 (defun branch-prediction (pred)
473   (or (position pred branch-predictions)
474       (error "Unknown branch prediction:  ~S~%Must be one of: ~S~%"
475              pred branch-predictions)))
476
477 (defconstant-eqx branch-pred-printer
478   `(:name (:unless (:constant ,branch-cond-true) cond)
479           (:unless (a :constant 0) "," 'A)
480           (:unless (p :constant 1) "," 'pn)
481           :tab
482           cc
483           ", "
484           disp)
485   #'equalp)
486
487 (sb!disassem:define-instruction-format
488     (format-2-branch-pred 32 :default-printer branch-pred-printer)
489   (op   :field (byte 2 30) :value 0)
490   (a    :field (byte 1 29) :value 0)
491   (cond :field (byte 4 25) :type 'branch-condition)
492   (op2  :field (byte 3 22))
493   (cc   :field (byte 2 20) :type 'integer-condition-register)
494   (p    :field (byte 1 19))
495   (disp :field (byte 19 0) :type 'relative-label))
496
497 (defconstant-eqx fp-condition-registers
498   '(:fcc0 :fcc1 :fcc2 :fcc3)
499   #'equalp)
500
501 (defconstant-eqx fp-cond-reg-name-vec
502   (coerce fp-condition-registers 'vector)
503   #'equalp)
504
505 (defparameter fp-condition-reg-symbols
506   (map 'vector
507        (lambda (name)
508            (make-symbol (concatenate 'string "%" (string name))))
509        fp-condition-registers))
510
511 (sb!disassem:define-arg-type fp-condition-register
512     :printer (lambda (value stream dstate)
513                  (declare (stream stream) (fixnum value) (ignore dstate))
514                  (let ((regname (aref fp-condition-reg-symbols value)))
515                    (princ regname stream))))
516
517 (sb!disassem:define-arg-type fp-condition-register-shifted
518     :printer (lambda (value stream dstate)
519                  (declare (stream stream) (fixnum value) (ignore dstate))
520                  (let ((regname (aref fp-condition-reg-symbols (ash value -1))))
521                    (princ regname stream))))
522
523 (defun fp-condition (condition-reg)
524   (or (position condition-reg fp-condition-registers)
525       (error "Unknown integer condition register:  ~S~%"
526              condition-reg)))
527
528 (defconstant-eqx fp-branch-pred-printer
529   `(:name (:unless (:constant ,branch-cond-true) cond)
530           (:unless (a :constant 0) "," 'A)
531           (:unless (p :constant 1) "," 'pn)
532           :tab
533           fcc
534           ", "
535           disp)
536   #'equalp)
537
538 (sb!disassem:define-instruction-format
539     (format-2-fp-branch-pred 32 :default-printer fp-branch-pred-printer)
540   (op   :field (byte 2 30) :value 0)
541   (a    :field (byte 1 29) :value 0)
542   (cond :field (byte 4 25) :type 'branch-fp-condition)
543   (op2  :field (byte 3 22))
544   (fcc  :field (byte 2 20) :type 'fp-condition-register)
545   (p    :field (byte 1 19))
546   (disp :field (byte 19 0) :type 'relative-label))
547   
548
549
550 (sb!disassem:define-instruction-format
551     (format-2-unimp 32 :default-printer '(:name :tab data))
552   (op     :field (byte 2 30) :value 0)
553   (ignore :field (byte 5 25) :value 0)
554   (op2    :field (byte 3 22) :value 0)
555   (data   :field (byte 22 0)))
556
557 (defconstant-eqx f3-printer
558   '(:name :tab
559           (:unless (:same-as rd) rs1 ", ")
560           (:choose rs2 immed) ", "
561           rd)
562   #'equalp)
563
564 (sb!disassem:define-instruction-format
565     (format-3-reg 32 :default-printer f3-printer)
566   (op  :field (byte 2 30))
567   (rd  :field (byte 5 25) :type 'reg)
568   (op3 :field (byte 6 19))
569   (rs1 :field (byte 5 14) :type 'reg)
570   (i   :field (byte 1 13) :value 0)
571   (asi :field (byte 8 5)  :value 0)
572   (rs2 :field (byte 5 0)  :type 'reg))
573
574 (sb!disassem:define-instruction-format
575     (format-3-immed 32 :default-printer f3-printer)
576   (op    :field (byte 2 30))
577   (rd    :field (byte 5 25) :type 'reg)
578   (op3   :field (byte 6 19))
579   (rs1   :field (byte 5 14) :type 'reg)
580   (i     :field (byte 1 13) :value 1)
581   (immed :field (byte 13 0) :sign-extend t))    ; usually sign extended
582
583 (sb!disassem:define-instruction-format
584     (format-binary-fpop 32
585      :default-printer '(:name :tab rs1 ", " rs2 ", " rd))
586   (op   :field (byte 2 30))
587   (rd   :field (byte 5 25) :type 'fp-reg)
588   (op3  :field (byte 6 19))
589   (rs1  :field (byte 5 14) :type 'fp-reg)
590   (opf  :field (byte 9 5))
591   (rs2  :field (byte 5 0) :type 'fp-reg))
592
593 ;;; Floating point load/save instructions encoding.
594 (sb!disassem:define-instruction-format
595     (format-unary-fpop 32 :default-printer '(:name :tab rs2 ", " rd))
596   (op   :field (byte 2 30))
597   (rd   :field (byte 5 25) :type 'fp-reg)
598   (op3  :field (byte 6 19))
599   (rs1  :field (byte 5 14) :value 0)
600   (opf  :field (byte 9 5))
601   (rs2  :field (byte 5 0) :type 'fp-reg))
602
603 ;;; Floating point comparison instructions encoding.
604
605 ;; This is a merge of the instructions for FP comparison and FP
606 ;; conditional moves available in the Sparc V9.  The main problem is
607 ;; that the new instructions use part of the opcode space used by the
608 ;; comparison instructions.  In particular, the OPF field is arranged
609 ;; as so:
610 ;;
611 ;; Bit          1       0
612 ;;              3       5
613 ;; FMOVcc       0nn0000xx       %fccn
614 ;;              1000000xx       %icc
615 ;;              1100000xx       %xcc
616 ;; FMOVR        0ccc001yy
617 ;; FCMP         001010zzz
618 ;;
619 ;; So we see that if we break up the OPF field into 4 pieces, opf0,
620 ;; opf1, opf2, and opf3, we can distinguish between these
621 ;; instructions. So bit 9 (opf2) can be used to distinguish between
622 ;; FCMP and the rest.  Also note that the nn field overlaps with the
623 ;; ccc.  We need to take this into account as well.
624 ;;
625 (sb!disassem:define-instruction-format
626     (format-fpop2 32
627                   :default-printer #!-sparc-v9 '(:name :tab rs1 ", " rs2)
628                                    #!+sparc-v9 '(:name :tab rd ", " rs1 ", " rs2))
629   (op   :field (byte 2 30))
630   (rd   :field (byte 5 25) :value 0)
631   (op3  :field (byte 6 19))
632   (rs1  :field (byte 5 14))
633   (opf0 :field (byte 1 13))
634   (opf1 :field (byte 3 10))
635   (opf2 :field (byte 1 9))
636   (opf3 :field (byte 4 5))
637   (rs2  :field (byte 5 0) :type 'fp-reg))
638
639 ;;; Shift instructions
640 (sb!disassem:define-instruction-format
641     (format-3-shift-reg 32 :default-printer f3-printer)
642   (op   :field (byte 2 30))
643   (rd    :field (byte 5 25) :type 'reg)
644   (op3  :field (byte 6 19))
645   (rs1   :field (byte 5 14) :type 'reg)
646   (i     :field (byte 1 13) :value 0)
647   (x     :field (byte 1 12))
648   (asi   :field (byte 7 5) :value 0)
649   (rs2   :field (byte 5 0) :type 'reg))
650
651 (sb!disassem:define-instruction-format
652     (format-3-shift-immed 32 :default-printer f3-printer)
653   (op   :field (byte 2 30))
654   (rd    :field (byte 5 25) :type 'reg)
655   (op3  :field (byte 6 19))
656   (rs1   :field (byte 5 14) :type 'reg)
657   (i     :field (byte 1 13) :value 1)
658   (x     :field (byte 1 12))
659   (immed :field (byte 12 0) :sign-extend nil))
660
661 \f
662 ;;; Conditional moves (only available for Sparc V9 architectures)
663
664 ;; The names of all of the condition registers on the V9: 4 FP
665 ;; conditions, the original integer condition register and the new
666 ;; extended register.  The :reserved register is reserved on the V9.
667
668 (defconstant-eqx cond-move-condition-registers
669   '(:fcc0 :fcc1 :fcc2 :fcc3 :icc :reserved :xcc :reserved)
670   #'equalp)
671
672 (defconstant-eqx cond-move-cond-reg-name-vec
673   (coerce cond-move-condition-registers 'vector)
674   #'equalp)
675
676 (deftype cond-move-condition-register ()
677     `(member ,@(remove :reserved cond-move-condition-registers)))
678
679 (defparameter cond-move-condition-reg-symbols
680   (map 'vector
681        (lambda (name)
682            (make-symbol (concatenate 'string "%" (string name))))
683        cond-move-condition-registers))
684
685 (sb!disassem:define-arg-type cond-move-condition-register
686     :printer (lambda (value stream dstate)
687                  (declare (stream stream) (fixnum value) (ignore dstate))
688                  (let ((regname (aref cond-move-condition-reg-symbols value)))
689                    (princ regname stream))))
690
691 ;; From the given condition register, figure out what the cc2, cc1,
692 ;; and cc0 bits should be.  Return cc2 and cc1/cc0 concatenated.
693 (defun cond-move-condition-parts (condition-reg)
694   (let ((posn (position condition-reg cond-move-condition-registers)))
695     (if posn
696         (truncate posn 4)
697         (error "Unknown conditional move condition register:  ~S~%"
698                condition-reg))))
699
700 (defun cond-move-condition (condition-reg)
701   (or (position condition-reg cond-move-condition-registers)
702       (error "Unknown conditional move condition register:  ~S~%")))
703
704 (defconstant-eqx cond-move-printer
705   `(:name cond :tab
706           cc ", " (:choose immed rs2) ", " rd)
707   #'equalp)
708
709 ;; Conditional move integer register on integer or FP condition code
710 (sb!disassem:define-instruction-format
711     (format-4-cond-move 32 :default-printer cond-move-printer)
712   (op   :field (byte 2 30))
713   (rd    :field (byte 5 25) :type 'reg)
714   (op3  :field (byte 6 19))
715   (cc2   :field (byte 1 18) :value 1)
716   (cond  :field (byte 4 14) :type 'branch-condition)
717   (i     :field (byte 1 13) :value 0)
718   (cc    :field (byte 2 11) :type 'integer-condition-register)
719   (empty :field (byte 6 5) :value 0)
720   (rs2   :field (byte 5 0) :type 'reg))
721
722 (sb!disassem:define-instruction-format
723     (format-4-cond-move-immed 32 :default-printer cond-move-printer)
724   (op    :field (byte 2 30))
725   (rd    :field (byte 5 25) :type 'reg)
726   (op3   :field (byte 6 19))
727   (cc2   :field (byte 1 18) :value 1)
728   (cond  :field (byte 4 14) :type 'branch-condition)
729   (i     :field (byte 1 13) :value 1)
730   (cc    :field (byte 2 11) :type 'integer-condition-register)
731   (immed :field (byte 11 0) :sign-extend t))
732
733 ;; Floating-point versions of the above integer conditional moves
734 (defconstant-eqx cond-fp-move-printer
735   `(:name rs1 :tab opf1 ", " rs2 ", " rd)
736   #'equalp)
737
738 ;;; Conditional move on integer register condition (only on Sparc
739 ;;; V9). That is, move an integer register if some other integer
740 ;;; register satisfies some condition.
741
742 (defconstant-eqx cond-move-integer-conditions
743   '(:reserved :z :lez :lz :reserved :nz :gz :gez)
744   #'equalp)
745
746 (defconstant-eqx cond-move-integer-condition-vec
747   (coerce cond-move-integer-conditions 'vector)
748   #'equalp)
749
750 (deftype cond-move-integer-condition ()
751   `(member ,@(remove :reserved cond-move-integer-conditions)))
752
753 (sb!disassem:define-arg-type register-condition
754     :printer (lambda (value stream dstate)
755                  (declare (stream stream) (fixnum value) (ignore dstate))
756                  (let ((regname (aref cond-move-integer-condition-vec value)))
757                    (princ regname stream))))
758
759 (defconstant-eqx cond-move-integer-printer
760   `(:name rcond :tab rs1 ", " (:choose immed rs2) ", " rd)
761   #'equalp)
762
763 (defun register-condition (rcond)
764   (or (position rcond cond-move-integer-conditions)
765       (error "Unknown register condition:  ~S~%")))
766
767 (sb!disassem:define-instruction-format
768     (format-4-cond-move-integer 32 :default-printer cond-move-integer-printer)
769   (op    :field (byte 2 30))
770   (rd    :field (byte 5 25) :type 'reg)
771   (op3   :field (byte 6 19))
772   (rs1   :field (byte 5 14) :type 'reg)
773   (i     :field (byte 1 13) :value 0)
774   (rcond :field (byte 3 10) :type 'register-condition)
775   (opf   :field (byte 5 5))
776   (rs2   :field (byte 5 0) :type 'reg))
777
778 (sb!disassem:define-instruction-format
779     (format-4-cond-move-integer-immed 32 :default-printer cond-move-integer-printer)
780   (op    :field (byte 2 30))
781   (rd    :field (byte 5 25) :type 'reg)
782   (op3   :field (byte 6 19))
783   (rs1   :field (byte 5 14) :type 'reg)
784   (i     :field (byte 1 13) :value 1)
785   (rcond :field (byte 3 10) :type 'register-condition)
786   (immed :field (byte 10 0) :sign-extend t))
787
788 (defconstant-eqx trap-printer
789   `(:name rd :tab cc ", " immed)
790   #'equalp)
791
792 (sb!disassem:define-instruction-format
793     (format-4-trap 32 :default-printer trap-printer)
794   (op    :field (byte 2 30))
795   (rd    :field (byte 5 25) :type 'reg)
796   (op3   :field (byte 6 19))
797   (rs1   :field (byte 5 14) :type 'reg)
798   (i     :field (byte 1 13) :value 1)
799   (cc    :field (byte 2 11) :type 'integer-condition-register)
800   (immed :field (byte 11 0) :sign-extend t))    ; usually sign extended
801
802
803 (defconstant-eqx cond-fp-move-integer-printer
804   `(:name opf1 :tab rs1 ", " rs2 ", " rd)
805   #'equalp)
806
807 \f
808 ;;;; Primitive emitters.
809
810 (define-bitfield-emitter emit-word 32
811   (byte 32 0))
812
813 (define-bitfield-emitter emit-short 16
814   (byte 16 0))
815
816 (define-bitfield-emitter emit-format-1 32
817   (byte 2 30) (byte 30 0))
818
819 (define-bitfield-emitter emit-format-2-immed 32
820   (byte 2 30) (byte 5 25) (byte 3 22) (byte 22 0))
821
822 (define-bitfield-emitter emit-format-2-branch 32
823   (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 22 0))
824
825 ;; Integer and FP branches with prediction for V9
826 (define-bitfield-emitter emit-format-2-branch-pred 32
827   (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 2 20) (byte 1 19) (byte 19 0))
828 (define-bitfield-emitter emit-format-2-fp-branch-pred 32
829   (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 2 20) (byte 1 19) (byte 19 0))
830   
831 (define-bitfield-emitter emit-format-2-unimp 32
832   (byte 2 30) (byte 5 25) (byte 3 22) (byte 22 0))
833
834 (define-bitfield-emitter emit-format-3-reg 32
835   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 8 5)
836   (byte 5 0))
837
838 (define-bitfield-emitter emit-format-3-immed 32
839   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 13 0))
840
841 (define-bitfield-emitter emit-format-3-fpop 32
842   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 9 5) (byte 5 0))
843
844 (define-bitfield-emitter emit-format-3-fpop2 32
845   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14)
846   (byte 1 13) (byte 3 10) (byte 1 9) (byte 4 5)
847   (byte 5 0))
848
849 ;;; Shift instructions
850
851 (define-bitfield-emitter emit-format-3-shift-reg 32
852   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 1 12) (byte 7 5)
853   (byte 5 0))
854
855 (define-bitfield-emitter emit-format-3-shift-immed 32
856   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 1 12) (byte 12 0))
857
858 ;;; Conditional moves
859
860 ;; Conditional move in condition code
861 (define-bitfield-emitter emit-format-4-cond-move 32
862   (byte 2 30) (byte 5 25) (byte 6 19) (byte 1 18) (byte 4 14) (byte 1 13) (byte 2 11)
863   (byte 11 0))
864
865 ;; Conditional move on integer condition
866 (define-bitfield-emitter emit-format-4-cond-move-integer 32
867   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 3 10) (byte 5 5)
868   (byte 5 0))
869
870 (define-bitfield-emitter emit-format-4-cond-move-integer-immed 32
871   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 3 10)
872   (byte 10 0))
873
874 (define-bitfield-emitter emit-format-4-trap 32
875   (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 2 11)
876   (byte 11 0))
877   
878 \f
879 ;;;; Most of the format-3-instructions.
880
881 (defun emit-format-3-inst (segment op op3 dst src1 src2
882                                    &key load-store fixup dest-kind)
883   (unless src2
884     (cond ((and (typep src1 'tn) load-store)
885            (setf src2 0))
886           (t
887            (setf src2 src1)
888            (setf src1 dst))))
889   (etypecase src2
890     (tn
891      (emit-format-3-reg segment op
892                         (if dest-kind
893                             (fp-reg-tn-encoding dst)
894                             (reg-tn-encoding dst))
895                         op3 (reg-tn-encoding src1) 0 0 (reg-tn-encoding src2)))
896     (integer
897      (emit-format-3-immed segment op
898                           (if dest-kind
899                               (fp-reg-tn-encoding dst)
900                               (reg-tn-encoding dst))
901                           op3 (reg-tn-encoding src1) 1 src2))
902     (fixup
903      (unless (or load-store fixup)
904        (error "Fixups aren't allowed."))
905      (note-fixup segment :add src2)
906      (emit-format-3-immed segment op
907                           (if dest-kind
908                               (fp-reg-tn-encoding dst)
909                               (reg-tn-encoding dst))
910                           op3 (reg-tn-encoding src1) 1 0))))
911
912 ;;; Shift instructions because an extra bit is used in Sparc V9's to
913 ;;; indicate whether the shift is a 32-bit or 64-bit shift.
914 ;;;
915 (defun emit-format-3-shift-inst (segment op op3 dst src1 src2 &key extended)
916   (unless src2
917     (setf src2 src1)
918     (setf src1 dst))
919   (etypecase src2
920     (tn
921      (emit-format-3-shift-reg segment op (reg-tn-encoding dst)
922                               op3 (reg-tn-encoding src1) 0 (if extended 1 0)
923                               0 (reg-tn-encoding src2)))
924     (integer
925      (emit-format-3-shift-immed segment op (reg-tn-encoding dst)
926                                 op3 (reg-tn-encoding src1) 1
927                                 (if extended 1 0) src2))))
928
929
930 (eval-when (:compile-toplevel :execute)
931
932 ;;; have to do this because def!constant is evalutated in the null lex env.
933 (defmacro with-ref-format (printer)
934   `(let* ((addend
935            '(:choose (:plus-integer immed) ("+" rs2)))
936           (ref-format
937            `("[" rs1 (:unless (:constant 0) ,addend) "]"
938              (:choose (:unless (:constant 0) asi) nil))))
939      ,printer))
940
941 (defconstant-eqx load-printer
942   (with-ref-format `(:NAME :TAB ,ref-format ", " rd))
943   #'equalp)
944
945 (defconstant-eqx store-printer
946   (with-ref-format `(:NAME :TAB rd ", " ,ref-format))
947   #'equalp)
948
949 ) ; eval-when (compile eval)
950
951 (macrolet ((define-f3-inst (name op op3 &key fixup load-store (dest-kind 'reg)
952                                  (printer :default) reads writes flushable print-name)
953   (let ((printer
954          (if (eq printer :default)
955              (case load-store
956                ((nil) :default)
957                ((:load t) 'load-printer)
958                (:store 'store-printer))
959              printer)))
960     (when (and (atom reads) (not (null reads)))
961       (setf reads (list reads)))
962     (when (and (atom writes) (not (null writes)))
963        (setf writes (list writes)))
964     `(define-instruction ,name (segment dst src1 &optional src2)
965        (:declare (type tn dst)
966                  ,(if (or fixup load-store)
967                       '(type (or tn (signed-byte 13) null fixup) src1 src2)
968                       '(type (or tn (signed-byte 13) null) src1 src2)))
969        (:printer format-3-reg
970                  ((op ,op) (op3 ,op3) (rd nil :type ',dest-kind))
971                  ,printer
972                  ,@(when print-name `(:print-name ,print-name)))
973        (:printer format-3-immed
974                  ((op ,op) (op3 ,op3) (rd nil :type ',dest-kind))
975                  ,printer
976                  ,@(when print-name `(:print-name ,print-name)))
977        ,@(when flushable
978            '((:attributes flushable)))
979        (:dependencies
980         (reads src1)
981         ,@(let ((reads-list nil))
982             (dolist (read reads)
983               (push (list 'reads read) reads-list))
984             reads-list)
985         ,@(cond ((eq load-store :store)
986                  '((reads dst)
987                    (if src2 (reads src2))))
988                  ((eq load-store t)
989                   '((reads :memory)
990                     (reads dst)
991                     (if src2 (reads src2))))
992                 ((eq load-store :load)
993                  '((reads :memory)
994                    (if src2 (reads src2) (reads dst))))
995                 (t
996                  '((if src2 (reads src2) (reads dst)))))
997         ,@(let ((writes-list nil))
998             (dolist (write writes)
999               (push (list 'writes write) writes-list))
1000             writes-list)
1001         ,@(cond ((eq load-store :store)
1002                  '((writes :memory :partially t)))
1003                 ((eq load-store t)
1004                  '((writes :memory :partially t)
1005                    (writes dst)))
1006                 ((eq load-store :load)
1007                  '((writes dst)))
1008                 (t
1009                  '((writes dst)))))
1010        (:delay 0)
1011        (:emitter (emit-format-3-inst segment ,op ,op3 dst src1 src2
1012                                      :load-store ,load-store
1013                                      :fixup ,fixup
1014                                      :dest-kind (not (eq ',dest-kind 'reg)))))))
1015
1016            (define-f3-shift-inst (name op op3 &key extended)
1017                `(define-instruction ,name (segment dst src1 &optional src2)
1018                  (:declare (type tn dst)
1019                   (type (or tn (unsigned-byte 6) null) src1 src2))
1020                  (:printer format-3-shift-reg
1021                   ((op ,op) (op3 ,op3) (x ,(if extended 1 0)) (i 0)))
1022                  (:printer format-3-shift-immed
1023                   ((op ,op) (op3 ,op3) (x ,(if extended 1 0)) (i 1)))
1024                  (:dependencies
1025                   (reads src1)
1026                   (if src2 (reads src2) (reads dst))
1027                   (writes dst))
1028                  (:delay 0)
1029                  (:emitter (emit-format-3-shift-inst segment ,op ,op3 dst src1 src2
1030                             :extended ,extended)))))
1031
1032   (define-f3-inst ldsb #b11 #b001001 :load-store :load)
1033   (define-f3-inst ldsh #b11 #b001010 :load-store :load)
1034   (define-f3-inst ldub #b11 #b000001 :load-store :load)
1035   (define-f3-inst lduh #b11 #b000010 :load-store :load)
1036
1037   ;; This instruction is called lduw for V9 , but looks exactly like ld
1038   ;; on previous architectures.
1039   (define-f3-inst ld #b11 #b000000 :load-store :load
1040                   #!+sparc-v9 :print-name #!+sparc-v9 'lduw)
1041
1042   (define-f3-inst ldsw #b11 #b001000 :load-store :load) ; v9
1043   
1044   ;; ldd is deprecated on the Sparc V9.
1045   (define-f3-inst ldd #b11 #b000011 :load-store :load)
1046   
1047   (define-f3-inst ldx #b11 #b001011 :load-store :load) ; v9
1048   
1049   (define-f3-inst ldf #b11 #b100000 :dest-kind fp-reg :load-store :load)
1050   (define-f3-inst lddf #b11 #b100011 :dest-kind fp-reg :load-store :load)
1051   (define-f3-inst ldqf #b11 #b100010 :dest-kind fp-reg :load-store :load)       ; v9
1052   (define-f3-inst stb #b11 #b000101 :load-store :store)
1053   (define-f3-inst sth #b11 #b000110 :load-store :store)
1054   (define-f3-inst st #b11 #b000100 :load-store :store)
1055   
1056   ;; std is deprecated on the Sparc V9.
1057   (define-f3-inst std #b11 #b000111 :load-store :store)
1058   
1059   (define-f3-inst stx #b11 #b001110 :load-store :store) ; v9
1060   
1061   (define-f3-inst stf #b11 #b100100 :dest-kind fp-reg :load-store :store)
1062   (define-f3-inst stdf #b11 #b100111 :dest-kind fp-reg :load-store :store)
1063   (define-f3-inst stqf #b11 #b100110 :dest-kind fp-reg :load-store :store) ; v9
1064   (define-f3-inst ldstub #b11 #b001101 :load-store t)
1065   
1066   ;; swap is deprecated on the Sparc V9
1067   (define-f3-inst swap #b11 #b001111 :load-store t)
1068   
1069   (define-f3-inst add #b10 #b000000 :fixup t)
1070   (define-f3-inst addcc #b10 #b010000 :writes :psr)
1071   (define-f3-inst addx #b10 #b001000 :reads :psr)
1072   (define-f3-inst addxcc #b10 #b011000 :reads :psr :writes :psr)
1073   (define-f3-inst taddcc #b10 #b100000 :writes :psr)
1074   
1075   ;; taddcctv is deprecated on the Sparc V9.  Use taddcc and bpvs or
1076   ;; taddcc and trap to get a similar effect.  (Requires changing the C
1077   ;; code though!)
1078   ;;(define-f3-inst taddcctv #b10 #b100010 :writes :psr)
1079
1080   (define-f3-inst sub #b10 #b000100)
1081   (define-f3-inst subcc #b10 #b010100 :writes :psr)
1082   (define-f3-inst subx #b10 #b001100 :reads :psr)
1083   (define-f3-inst subxcc #b10 #b011100 :reads :psr :writes :psr)
1084   (define-f3-inst tsubcc #b10 #b100001 :writes :psr)
1085
1086   ;; tsubcctv is deprecated on the Sparc V9.  Use tsubcc and bpvs or
1087   ;; tsubcc and trap to get a similar effect.  (Requires changing the C
1088   ;; code though!)
1089   ;;(define-f3-inst tsubcctv #b10 #b100011 :writes :psr)
1090
1091   (define-f3-inst mulscc #b10 #b100100 :reads :y :writes (:psr :y))
1092   (define-f3-inst and #b10 #b000001)
1093   (define-f3-inst andcc #b10 #b010001 :writes :psr)
1094   (define-f3-inst andn #b10 #b000101)
1095   (define-f3-inst andncc #b10 #b010101 :writes :psr)
1096   (define-f3-inst or #b10 #b000010)
1097   (define-f3-inst orcc #b10 #b010010 :writes :psr)
1098   (define-f3-inst orn #b10 #b000110)
1099   (define-f3-inst orncc #b10 #b010110 :writes :psr)
1100   (define-f3-inst xor #b10 #b000011)
1101   (define-f3-inst xorcc #b10 #b010011 :writes :psr)
1102   (define-f3-inst xnor #b10 #b000111)
1103   (define-f3-inst xnorcc #b10 #b010111 :writes :psr)
1104   
1105   (define-f3-shift-inst sll #b10 #b100101)
1106   (define-f3-shift-inst srl #b10 #b100110)
1107   (define-f3-shift-inst sra #b10 #b100111)
1108   (define-f3-shift-inst sllx #b10 #b100101 :extended t) ; v9
1109   (define-f3-shift-inst srlx #b10 #b100110 :extended t) ; v9
1110   (define-f3-shift-inst srax #b10 #b100111 :extended t) ; v9
1111
1112   (define-f3-inst save #b10 #b111100 :reads :psr :writes :psr)
1113   (define-f3-inst restore #b10 #b111101 :reads :psr :writes :psr)
1114   
1115   ;; smul, smulcc, umul, umulcc, sdiv, sdivcc, udiv, and udivcc are
1116   ;; deprecated on the Sparc V9.  Use mulx, sdivx, and udivx instead.
1117   (define-f3-inst smul #b10 #b001011 :writes :y)                        ; v8
1118   (define-f3-inst smulcc #b10 #b011011 :writes (:psr :y))               ; v8
1119   (define-f3-inst umul #b10 #b001010 :writes :y)                        ; v8
1120   (define-f3-inst umulcc #b10 #b011010 :writes (:psr :y))               ; v8
1121   (define-f3-inst sdiv #b10 #b001111 :reads :y)                 ; v8
1122   (define-f3-inst sdivcc #b10 #b011111 :reads :y :writes :psr)  ; v8
1123   (define-f3-inst udiv #b10 #b001110 :reads :y)                 ; v8
1124   (define-f3-inst udivcc #b10 #b011110 :reads :y :writes :psr)  ; v8
1125   
1126   (define-f3-inst mulx #b10 #b001001)   ; v9 for both signed and unsigned
1127   (define-f3-inst sdivx #b10 #b101101)  ; v9
1128   (define-f3-inst udivx #b10 #b001101)  ; v9
1129
1130   (define-f3-inst popc #b10 #b101110)   ; v9: count one bits
1131
1132 ) ; MACROLET
1133
1134 \f
1135 ;;;; Random instructions.
1136
1137 ;; ldfsr is deprecated on the Sparc V9.  Use ldxfsr instead
1138 (define-instruction ldfsr (segment src1 src2)
1139   (:declare (type tn src1) (type (signed-byte 13) src2))
1140   (:printer format-3-immed ((op #b11) (op3 #b100001) (rd 0)))
1141   :pinned
1142   (:delay 0)
1143   (:emitter (emit-format-3-immed segment #b11 0 #b100001
1144                                  (reg-tn-encoding src1) 1 src2)))
1145
1146 #!+sparc-64
1147 (define-instruction ldxfsr (segment src1 src2)
1148   (:declare (type tn src1) (type (signed-byte 13) src2))
1149   (:printer format-3-immed ((op #b11) (op3 #b100001) (rd 1))
1150             '(:name :tab "[" rs1 (:unless (:constant 0) "+" immed) "], %FSR")
1151             :print-name 'ldx)
1152   :pinned
1153   (:delay 0)
1154   (:emitter (emit-format-3-immed segment #b11 1 #b100001
1155                                  (reg-tn-encoding src1) 1 src2)))
1156   
1157 ;; stfsr is deprecated on the Sparc V9.  Use stxfsr instead.
1158 (define-instruction stfsr (segment src1 src2)
1159   (:declare (type tn src1) (type (signed-byte 13) src2))
1160   (:printer format-3-immed ((op #b11) (op3 #b100101) (rd 0)))
1161   :pinned
1162   (:delay 0)
1163   (:emitter (emit-format-3-immed segment #b11 0 #b100101 
1164                                  (reg-tn-encoding src1) 1 src2)))
1165
1166 #!+sparc-64
1167 (define-instruction stxfsr (segment src1 src2)
1168   (:declare (type tn src1) (type (signed-byte 13) src2))
1169   (:printer format-3-immed ((op #b11) (op3 #b100101) (rd 1))
1170             '(:name :tab "%FSR, [" rs1 "+" (:unless (:constant 0) "+" immed) "]")
1171             :print-name 'stx)
1172   :pinned
1173   (:delay 0)
1174   (:emitter (emit-format-3-immed segment #b11 1 #b100101 
1175                                  (reg-tn-encoding src1) 1 src2)))
1176
1177 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
1178   (defun sethi-arg-printer (value stream dstate)
1179     (format stream "%hi(#x~8,'0x)" (ash value 10))
1180     ;; Save the immediate value and the destination register from this
1181     ;; sethi instruction.  This is used later to print some possible
1182     ;; notes about the value loaded by sethi.
1183     (let* ((word (sb!disassem::sap-ref-int (sb!disassem::dstate-segment-sap dstate)
1184                                            (sb!disassem::dstate-cur-offs dstate)
1185                                            n-word-bytes
1186                                            (sb!disassem::dstate-byte-order dstate)))
1187            (imm22 (ldb (byte 22 0) word))
1188            (rd (ldb (byte 5 25) word)))
1189       (push (cons rd imm22) *note-sethi-inst*)))
1190 ) ; EVAL-WHEN
1191
1192
1193 (define-instruction sethi (segment dst src1)
1194   (:declare (type tn dst)
1195             (type (or (signed-byte 22) (unsigned-byte 22) fixup) src1))
1196   (:printer format-2-immed
1197             ((op2 #b100) (immed nil :printer #'sethi-arg-printer)))
1198   (:dependencies (writes dst))
1199   (:delay 0)
1200   (:emitter
1201    (etypecase src1
1202      (integer
1203       (emit-format-2-immed segment #b00 (reg-tn-encoding dst) #b100
1204                                  src1))
1205      (fixup
1206       (note-fixup segment :sethi src1)
1207       (emit-format-2-immed segment #b00 (reg-tn-encoding dst) #b100 0)))))
1208                            
1209 ;; rdy is deprecated on the Sparc V9.  It's not needed with 64-bit
1210 ;; registers.
1211 (define-instruction rdy (segment dst)
1212   (:declare (type tn dst))
1213   (:printer format-3-immed ((op #b10) (op3 #b101000) (rs1 0) (immed 0))
1214             '('RD :tab '%Y ", " rd))
1215   (:dependencies (reads :y) (writes dst))
1216   (:delay 0)
1217   (:emitter (emit-format-3-immed segment #b10 (reg-tn-encoding dst) #b101000
1218                                  0 0 0)))
1219
1220 (defconstant-eqx wry-printer
1221   '('WR :tab rs1 (:unless (:constant 0) ", " (:choose immed rs2)) ", " '%Y)
1222   #'equalp)
1223
1224 ;; wry is deprecated on the Sparc V9.  It's not needed with 64-bit
1225 ;; registers.
1226 (define-instruction wry (segment src1 &optional src2)
1227   (:declare (type tn src1) (type (or (signed-byte 13) tn null) src2))
1228   (:printer format-3-reg ((op #b10) (op3 #b110000) (rd 0)) wry-printer)
1229   (:printer format-3-immed ((op #b10) (op3 #b110000) (rd 0)) wry-printer)
1230   (:dependencies (reads src1) (if src2 (reads src2)) (writes :y))
1231   (:delay 3)
1232   (:emitter
1233    (etypecase src2
1234      (null 
1235       (emit-format-3-reg segment #b10 0 #b110000 (reg-tn-encoding src1) 0 0 0))
1236      (tn
1237       (emit-format-3-reg segment #b10 0 #b110000 (reg-tn-encoding src1) 0 0
1238                          (reg-tn-encoding src2)))
1239      (integer
1240       (emit-format-3-immed segment #b10 0 #b110000 (reg-tn-encoding src1) 1
1241                            src2)))))
1242
1243 (defun snarf-error-junk (sap offset &optional length-only)
1244   (let* ((length (sb!sys:sap-ref-8 sap offset))
1245          (vector (make-array length :element-type '(unsigned-byte 8))))
1246     (declare (type sb!sys:system-area-pointer sap)
1247              (type (unsigned-byte 8) length)
1248              (type (simple-array (unsigned-byte 8) (*)) vector))
1249     (cond (length-only
1250            (values 0 (1+ length) nil nil))
1251           (t
1252            (sb!kernel:copy-from-system-area sap (* n-byte-bits (1+ offset))
1253                                          vector (* n-word-bits
1254                                                    vector-data-offset)
1255                                          (* length n-byte-bits))
1256            (collect ((sc-offsets)
1257                      (lengths))
1258              (lengths 1)                ; the length byte
1259              (let* ((index 0)
1260                     (error-number (sb!c:read-var-integer vector index)))
1261                (lengths index)
1262                (loop
1263                  (when (>= index length)
1264                    (return))
1265                  (let ((old-index index))
1266                    (sc-offsets (sb!c:read-var-integer vector index))
1267                    (lengths (- index old-index))))
1268                (values error-number
1269                        (1+ length)
1270                        (sc-offsets)
1271                        (lengths))))))))
1272
1273 (defun unimp-control (chunk inst stream dstate)
1274   (declare (ignore inst))
1275   (flet ((nt (x) (if stream (sb!disassem:note x dstate))))
1276     (case (format-2-unimp-data chunk dstate)
1277       (#.error-trap
1278        (nt "Error trap")
1279        (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
1280       (#.cerror-trap
1281        (nt "Cerror trap")
1282        (sb!disassem:handle-break-args #'snarf-error-junk stream dstate))
1283       (#.object-not-list-trap
1284        (nt "Object not list trap"))
1285       (#.breakpoint-trap
1286        (nt "Breakpoint trap"))
1287       (#.pending-interrupt-trap
1288        (nt "Pending interrupt trap"))
1289       (#.halt-trap
1290        (nt "Halt trap"))
1291       (#.fun-end-breakpoint-trap
1292        (nt "Function end breakpoint trap"))
1293       (#.object-not-instance-trap
1294        (nt "Object not instance trap"))
1295     )))
1296
1297 (define-instruction unimp (segment data)
1298   (:declare (type (unsigned-byte 22) data))
1299   (:printer format-2-unimp () :default :control #'unimp-control
1300             :print-name #!-sparc-v9 'unimp #!+sparc-v9 'illtrap)
1301   (:delay 0)
1302   (:emitter (emit-format-2-unimp segment 0 0 0 data)))
1303
1304
1305 \f
1306 ;;;; Branch instructions.
1307
1308 ;; The branch instruction is deprecated on the Sparc V9.  Use the
1309 ;; branch with prediction instructions instead.
1310 (defun emit-relative-branch (segment a op2 cond-or-target target &optional fp)
1311   (emit-back-patch segment 4
1312     (lambda (segment posn)
1313         (unless target
1314           (setf target cond-or-target)
1315           (setf cond-or-target :t))
1316         (emit-format-2-branch
1317           segment #b00 a
1318           (if fp
1319               (fp-branch-condition cond-or-target)
1320               (branch-condition cond-or-target))
1321           op2
1322           (let ((offset (ash (- (label-position target) posn) -2)))
1323             (when (and (= a 1) (> 0 offset))
1324               (error "Offset of BA must be positive"))
1325             offset)))))
1326
1327 (defun emit-relative-branch-integer (segment a op2 cond-or-target target &optional (cc :icc) (pred :pt))
1328   (declare (type integer-condition-register cc))
1329   (assert (member :sparc-v9 *backend-subfeatures*))
1330   (emit-back-patch segment 4
1331     (lambda (segment posn)
1332         (unless target
1333           (setf target cond-or-target)
1334           (setf cond-or-target :t))
1335         (emit-format-2-branch-pred
1336           segment #b00 a
1337           (branch-condition cond-or-target)
1338           op2
1339           (integer-condition cc)
1340           (branch-prediction pred)
1341           (let ((offset (ash (- (label-position target) posn) -2)))
1342             (when (and (= a 1) (> 0 offset))
1343               (error "Offset of BA must be positive"))
1344             offset)))))
1345
1346 (defun emit-relative-branch-fp (segment a op2 cond-or-target target &optional (cc :fcc0) (pred :pt))
1347   (assert (member :sparc-v9 *backend-subfeatures*))
1348   (emit-back-patch segment 4
1349     (lambda (segment posn)
1350         (unless target
1351           (setf target cond-or-target)
1352           (setf cond-or-target :t))
1353         (emit-format-2-branch-pred
1354           segment #b00 a
1355           (fp-branch-condition cond-or-target)
1356           op2
1357           (fp-condition cc)
1358           (branch-prediction pred)
1359           (let ((offset (ash (- (label-position target) posn) -2)))
1360             (when (and (= a 1) (> 0 offset))
1361               (error "Offset of BA must be positive"))
1362             offset)))))
1363
1364 ;; So that I don't have to go change the syntax of every single use of
1365 ;; branches, I'm keeping the Lisp instruction names the same.  They
1366 ;; just get translated to the branch with prediction
1367 ;; instructions. However, the disassembler uses the correct V9
1368 ;; mnemonic.
1369 (define-instruction b (segment cond-or-target &rest args)
1370   (:declare (type (or label branch-condition) cond-or-target))
1371   (:printer format-2-branch ((op #b00) (op2 #b010)))
1372   (:attributes branch)
1373   (:dependencies (reads :psr))
1374   (:delay 1)
1375   (:emitter
1376    (cond
1377      ((member :sparc-v9 *backend-subfeatures*)
1378       (destructuring-bind (&optional target pred cc) args
1379         (declare (type (or label null) target))
1380         (emit-relative-branch-integer segment 0 #b001 cond-or-target target (or cc :icc) (or pred :pt))))
1381      (t
1382       (destructuring-bind (&optional target) args
1383         (declare (type (or label null) target))
1384         (emit-relative-branch segment 0 #b010 cond-or-target target))))))
1385
1386 (define-instruction bp (segment cond-or-target &optional target pred cc)
1387   (:declare (type (or label branch-condition) cond-or-target)
1388             (type (or label null) target))
1389   (:printer format-2-branch-pred ((op #b00) (op2 #b001))
1390             branch-pred-printer
1391             :print-name 'bp)
1392   (:attributes branch)
1393   (:dependencies (reads :psr))
1394   (:delay 1)
1395   (:emitter
1396    (emit-relative-branch-integer segment 0 #b001 cond-or-target target (or cc :icc) (or pred :pt))))
1397
1398 (define-instruction ba (segment cond-or-target &rest args)
1399   (:declare (type (or label branch-condition) cond-or-target))
1400   (:printer format-2-branch ((op #b00) (op2 #b010) (a 1))
1401             nil
1402             :print-name 'b)
1403   (:attributes branch)
1404   (:dependencies (reads :psr))
1405   (:delay 0)
1406   (:emitter
1407    (cond
1408      ((member :sparc-v9 *backend-subfeatures*)
1409       (destructuring-bind (&optional target pred cc) args
1410         (declare (type (or label null) target))
1411         (emit-relative-branch-integer segment 1 #b001 cond-or-target target (or cc :icc) (or pred :pt))))
1412      (t
1413       (destructuring-bind (&optional target) args
1414         (declare (type (or label null) target))
1415         (emit-relative-branch segment 1 #b010 cond-or-target target))))))
1416
1417 (define-instruction bpa (segment cond-or-target &optional target pred cc)
1418   (:declare (type (or label branch-condition) cond-or-target)
1419             (type (or label null) target))
1420   (:printer format-2-branch ((op #b00) (op2 #b001) (a 1))
1421             nil
1422             :print-name 'bp)
1423   (:attributes branch)
1424   (:dependencies (reads :psr))
1425   (:delay 0)
1426   (:emitter
1427    (emit-relative-branch-integer segment 1 #b001 cond-or-target target (or cc :icc) (or pred :pt))))
1428
1429 ;; This doesn't cover all of the possible formats for the trap
1430 ;; instruction.  We really only want a trap with a immediate trap
1431 ;; value and with RS1 = register 0.  Also, the Sparc Compliance
1432 ;; Definition 2.4.1 says only trap numbers 16-31 are allowed for user
1433 ;; code.  All other trap numbers have other uses.  The restriction on
1434 ;; target will prevent us from using bad trap numbers by mistake.
1435
1436 (define-instruction t (segment condition target &optional cc)
1437   (:declare (type branch-condition condition)
1438             ;; KLUDGE: see comments in vm.lisp regarding
1439             ;; pseudo-atomic-trap.
1440             #!-linux
1441             (type (integer 16 31) target))
1442   (:printer format-3-immed ((op #b10)
1443                             (rd nil :type 'branch-condition)
1444                             (op3 #b111010)
1445                             (rs1 0))
1446             '(:name rd :tab immed))
1447   (:attributes branch)
1448   (:dependencies (reads :psr))
1449   (:delay 0)
1450   (:emitter 
1451    (cond
1452      ((member :sparc-v9 *backend-subfeatures*)
1453       (unless cc
1454         (setf cc :icc))
1455       (emit-format-4-trap segment
1456                           #b10
1457                           (branch-condition condition)
1458                           #b111010 0 1
1459                           (integer-condition cc)
1460                           target))
1461      (t
1462       (assert (null cc))
1463       (emit-format-3-immed segment #b10 (branch-condition condition)
1464                            #b111010 0 1 target)))))
1465
1466 ;;; KLUDGE: we leave this commented out, as these two (T and TCC)
1467 ;;; operations are actually indistinguishable from their bitfields,
1468 ;;; breaking the disassembler if these are left in. The printer isn't
1469 ;;; terribly smart, but the emitted code is right. - CSR, 2002-08-04
1470 #+nil
1471 (define-instruction tcc (segment condition target &optional (cc #!-sparc-64 :icc #!+sparc-64 :xcc))
1472   (:declare (type branch-condition condition)
1473             ;; KLUDGE: see above.
1474             #!-linux
1475             (type (integer 16 31) target)
1476             (type integer-condition-register cc))
1477   (:printer format-4-trap ((op #b10)
1478                             (rd nil :type 'branch-condition)
1479                             (op3 #b111010)
1480                             (rs1 0))
1481             trap-printer)
1482   (:attributes branch)
1483   (:dependencies (reads :psr))
1484   (:delay 0)
1485   (:emitter (emit-format-4-trap segment
1486                                 #b10
1487                                 (branch-condition condition)
1488                                 #b111010 0 1
1489                                 (integer-condition cc)
1490                                 target)))
1491
1492 ;; Same as for the branch instructions.  On the Sparc V9, we will use
1493 ;; the FP branch with prediction instructions instead.
1494
1495 (define-instruction fb (segment condition target &rest args)
1496   (:declare (type fp-branch-condition condition) (type label target))
1497   (:printer format-2-branch ((op #B00)
1498                              (cond nil :type 'branch-fp-condition)
1499                              (op2 #b110)))
1500   (:attributes branch)
1501   (:dependencies (reads :fsr))
1502   (:delay 1)
1503   (:emitter
1504    (cond
1505      ((member :sparc-v9 *backend-subfeatures*)
1506       (destructuring-bind (&optional fcc pred) args
1507         (emit-relative-branch-fp segment 0 #b101 condition target (or fcc :fcc0) (or pred :pt))))
1508      (t 
1509       (assert (null args))
1510       (emit-relative-branch segment 0 #b110 condition target t)))))
1511
1512 (define-instruction fbp (segment condition target &optional fcc pred)
1513   (:declare (type fp-branch-condition condition) (type label target))
1514   (:printer format-2-fp-branch-pred ((op #b00) (op2 #b101))
1515             fp-branch-pred-printer
1516             :print-name 'fbp)
1517   (:attributes branch)
1518   (:dependencies (reads :fsr))
1519   (:delay 1)
1520   (:emitter
1521    (emit-relative-branch-fp segment 0 #b101 condition target (or fcc :fcc0) (or pred :pt))))
1522
1523 (defconstant-eqx jal-printer
1524   '(:name :tab
1525           (:choose (rs1 (:unless (:constant 0) (:plus-integer immed)))
1526                    (:cond ((rs2 :constant 0) rs1)
1527                           ((rs1 :constant 0) rs2)
1528                           (t rs1 "+" rs2)))
1529           (:unless (:constant 0) ", " rd))
1530   #'equalp)
1531
1532 (define-instruction jal (segment dst src1 &optional src2)
1533   (:declare (type tn dst)
1534             (type (or tn integer) src1)
1535             (type (or null fixup tn (signed-byte 13)) src2))
1536   (:printer format-3-reg ((op #b10) (op3 #b111000)) jal-printer)
1537   (:printer format-3-immed ((op #b10) (op3 #b111000)) jal-printer)
1538   (:attributes branch)
1539   (:dependencies (reads src1) (if src2 (reads src2) (reads dst)) (writes dst))
1540   (:delay 1)
1541   (:emitter
1542    (unless src2
1543      (setf src2 src1)
1544      (setf src1 0))
1545    (etypecase src2
1546      (tn
1547       (emit-format-3-reg segment #b10 (reg-tn-encoding dst) #b111000
1548                          (if (integerp src1)
1549                              src1
1550                              (reg-tn-encoding src1))
1551                          0 0 (reg-tn-encoding src2)))
1552      (integer
1553       (emit-format-3-immed segment #b10 (reg-tn-encoding dst) #b111000
1554                            (reg-tn-encoding src1) 1 src2))
1555      (fixup
1556       (note-fixup segment :add src2)
1557       (emit-format-3-immed segment #b10 (reg-tn-encoding dst)
1558                            #b111000 (reg-tn-encoding src1) 1 0)))))
1559
1560 (define-instruction j (segment src1 &optional src2)
1561   (:declare (type tn src1) (type (or tn (signed-byte 13) fixup null) src2))
1562   (:printer format-3-reg ((op #b10) (op3 #b111000) (rd 0)) jal-printer)
1563   (:printer format-3-immed ((op #b10) (op3 #b111000) (rd 0)) jal-printer)
1564   (:attributes branch)
1565   (:dependencies (reads src1) (if src2 (reads src2)))
1566   (:delay 1)
1567   (:emitter
1568    (etypecase src2
1569      (null
1570       (emit-format-3-reg segment #b10 0 #b111000 (reg-tn-encoding src1) 0 0 0))
1571      (tn
1572       (emit-format-3-reg segment #b10 0 #b111000 (reg-tn-encoding src1) 0 0
1573                          (reg-tn-encoding src2)))
1574      (integer
1575       (emit-format-3-immed segment #b10 0 #b111000 (reg-tn-encoding src1) 1
1576                            src2))
1577      (fixup
1578       (note-fixup segment :add src2)
1579       (emit-format-3-immed segment #b10 0 #b111000 (reg-tn-encoding src1) 1
1580                            0)))))
1581
1582
1583 \f
1584 ;;;; Unary and binary fp insts.
1585
1586 (macrolet ((define-unary-fp-inst (name opf &key reads extended)
1587   `(define-instruction ,name (segment dst src)
1588      (:declare (type tn dst src))
1589      (:printer format-unary-fpop
1590        ((op #b10) (op3 #b110100) (opf ,opf)
1591         (rs1 0)
1592         (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1593         (rd nil :type ',(if extended 'fp-ext-reg 'fp-reg))))
1594      (:dependencies
1595       ,@(when reads
1596           `((reads ,reads)))
1597       (reads dst)
1598       (reads src)
1599       (writes dst))
1600      (:delay 0)
1601      (:emitter (emit-format-3-fpop segment #b10 (fp-reg-tn-encoding dst)
1602                 #b110100 0 ,opf (fp-reg-tn-encoding src)))))
1603
1604            (define-binary-fp-inst (name opf &key (op3 #b110100)
1605                                       reads writes delay extended)
1606   `(define-instruction ,name (segment dst src1 src2)
1607      (:declare (type tn dst src1 src2))
1608      (:printer format-binary-fpop
1609       ((op #b10) (op3 ,op3) (opf ,opf)
1610        (rs1 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1611        (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1612        (rd nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1613        ))
1614      (:dependencies
1615       ,@(when reads
1616           `((reads ,reads)))
1617       (reads src1)
1618       (reads src2)
1619       ,@(when writes
1620           `((writes ,writes)))
1621       (writes dst))
1622      ,@(if delay
1623            `((:delay ,delay))
1624            '((:delay 0)))
1625      (:emitter (emit-format-3-fpop segment #b10 (fp-reg-tn-encoding dst)
1626                 ,op3 (fp-reg-tn-encoding src1) ,opf
1627                 (fp-reg-tn-encoding src2)))))
1628
1629            (define-cmp-fp-inst (name opf &key extended)
1630                (let ((opf0 #b0)
1631                      (opf1 #b010)
1632                      (opf2 #b1))
1633                  `(define-instruction ,name (segment src1 src2 &optional (fcc :fcc0))
1634                    (:declare (type tn src1 src2)
1635                     (type (member :fcc0 :fcc1 :fcc2 :fcc3) fcc))
1636        (:printer format-fpop2
1637                  ((op #b10)
1638                   (op3 #b110101)
1639                   (opf0 ,opf0)
1640                   (opf1 ,opf1)
1641                   (opf2 ,opf2)
1642                   (opf3 ,opf)
1643                   (rs1 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1644                   (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
1645                   #!-sparc-v9
1646                   (rd 0)
1647                   #!+sparc-v9
1648                   (rd nil :type 'fp-condition-register))
1649         )
1650      (:dependencies
1651       (reads src1)
1652       (reads src2)
1653       (writes :fsr))
1654      ;; The Sparc V9 doesn't need a delay after a FP compare.
1655      ;;
1656      ;; KLUDGE FIXME YAARGH -- how to express that? I guess for now we
1657      ;; do the worst case, and hope to fix it.
1658      ;; (:delay #-sparc-v9 1 #+sparc-v9 0)
1659      (:delay 1)
1660        (:emitter
1661         (emit-format-3-fpop2 segment #b10
1662                              (or (position fcc '(:fcc0 :fcc1 :fcc2 :fcc3))
1663                                  0)
1664                              #b110101
1665                              (fp-reg-tn-encoding src1)
1666                              ,opf0 ,opf1 ,opf2 ,opf
1667                              (fp-reg-tn-encoding src2)))))))
1668
1669   (define-unary-fp-inst fitos #b011000100 :reads :fsr)
1670   (define-unary-fp-inst fitod #b011001000 :reads :fsr :extended t)
1671   (define-unary-fp-inst fitoq #b011001100 :reads :fsr :extended t)      ; v8
1672   
1673   (define-unary-fp-inst fxtos #b010000100 :reads :fsr)                    ; v9
1674   (define-unary-fp-inst fxtod #b010001000 :reads :fsr :extended t)        ; v9
1675   (define-unary-fp-inst fxtoq #b010001100 :reads :fsr :extended t)      ; v9
1676
1677
1678   ;; I (Raymond Toy) don't think these f{sd}toir instructions exist on
1679   ;; any Ultrasparc, but I only have a V9 manual. The code in
1680   ;; float.lisp seems to indicate that they only existed on non-sun4
1681   ;; machines (sun3 68K machines?).
1682   (define-unary-fp-inst fstoir #b011000001 :reads :fsr)
1683   (define-unary-fp-inst fdtoir #b011000010 :reads :fsr)
1684   
1685   (define-unary-fp-inst fstoi #b011010001)
1686   (define-unary-fp-inst fdtoi #b011010010 :extended t)
1687   (define-unary-fp-inst fqtoi #b011010011 :extended t)  ; v8
1688
1689   (define-unary-fp-inst fstox #b010000001)                ; v9
1690   (define-unary-fp-inst fdtox #b010000010 :extended t)    ; v9
1691   (define-unary-fp-inst fqtox #b010000011 :extended t)  ; v9
1692
1693   (define-unary-fp-inst fstod #b011001001 :reads :fsr)
1694   (define-unary-fp-inst fstoq #b011001101 :reads :fsr)  ; v8
1695   (define-unary-fp-inst fdtos #b011000110 :reads :fsr)
1696   (define-unary-fp-inst fdtoq #b011001110 :reads :fsr)  ; v8
1697   (define-unary-fp-inst fqtos #b011000111 :reads :fsr)  ; v8
1698   (define-unary-fp-inst fqtod #b011001011 :reads :fsr)  ; v8
1699   
1700   (define-unary-fp-inst fmovs #b000000001)
1701   (define-unary-fp-inst fmovd #b000000010 :extended t)  ; v9
1702   (define-unary-fp-inst fmovq #b000000011 :extended t)  ; v9
1703   
1704   (define-unary-fp-inst fnegs #b000000101)
1705   (define-unary-fp-inst fnegd #b000000110 :extended t)  ; v9
1706   (define-unary-fp-inst fnegq #b000000111 :extended t)  ; v9
1707
1708   (define-unary-fp-inst fabss #b000001001)
1709   (define-unary-fp-inst fabsd #b000001010 :extended t)  ; v9
1710   (define-unary-fp-inst fabsq #b000001011 :extended t)  ; v9
1711   
1712   (define-unary-fp-inst fsqrts #b000101001 :reads :fsr)         ; V7
1713   (define-unary-fp-inst fsqrtd #b000101010 :reads :fsr :extended t)     ; V7
1714   (define-unary-fp-inst fsqrtq #b000101011 :reads :fsr :extended t)     ; v8
1715   
1716   (define-binary-fp-inst fadds #b001000001)
1717   (define-binary-fp-inst faddd #b001000010 :extended t)
1718   (define-binary-fp-inst faddq #b001000011 :extended t) ; v8
1719   (define-binary-fp-inst fsubs #b001000101)
1720   (define-binary-fp-inst fsubd #b001000110 :extended t)
1721   (define-binary-fp-inst fsubq #b001000111 :extended t) ; v8
1722   
1723   (define-binary-fp-inst fmuls #b001001001)
1724   (define-binary-fp-inst fmuld #b001001010 :extended t)
1725   (define-binary-fp-inst fmulq #b001001011 :extended t) ; v8
1726   (define-binary-fp-inst fdivs #b001001101)
1727   (define-binary-fp-inst fdivd #b001001110 :extended t)
1728   (define-binary-fp-inst fdivq #b001001111 :extended t) ; v8
1729
1730 ;;; Float comparison instructions.
1731 ;;;
1732   (define-cmp-fp-inst fcmps #b0001)
1733   (define-cmp-fp-inst fcmpd #b0010 :extended t)
1734   (define-cmp-fp-inst fcmpq #b0011 :extended t) ;v8
1735   (define-cmp-fp-inst fcmpes #b0101)
1736   (define-cmp-fp-inst fcmped #b0110 :extended t)
1737   (define-cmp-fp-inst fcmpeq #b0111 :extended t)        ; v8
1738
1739 ) ; MACROLET
1740 \f
1741 ;;;; li, jali, ji, nop, cmp, not, neg, move, and more
1742
1743 (defun %li (reg value)
1744   (etypecase value
1745     ((signed-byte 13)
1746      (inst add reg zero-tn value))
1747     ((or (signed-byte 32) (unsigned-byte 32))
1748      (let ((hi (ldb (byte 22 10) value))
1749            (lo (ldb (byte 10 0) value)))
1750        (inst sethi reg hi)
1751        (unless (zerop lo)
1752          (inst add reg lo))))
1753     (fixup
1754      (inst sethi reg value)
1755      (inst add reg value))))
1756
1757 (define-instruction-macro li (reg value)
1758   `(%li ,reg ,value))
1759
1760 ;;; Jal to a full 32-bit address.  Tmpreg is trashed.
1761 (define-instruction jali (segment link tmpreg value)
1762   (:declare (type tn link tmpreg)
1763             (type (or (signed-byte 13) (signed-byte 32) (unsigned-byte 32)
1764                       fixup) value))
1765   (:attributes variable-length)
1766   (:vop-var vop)
1767   (:attributes branch)
1768   (:dependencies (writes link) (writes tmpreg))
1769   (:delay 1)
1770   (:emitter
1771    (assemble (segment vop)
1772      (etypecase value
1773        ((signed-byte 13)
1774         (inst jal link zero-tn value))
1775        ((or (signed-byte 32) (unsigned-byte 32))
1776         (let ((hi (ldb (byte 22 10) value))
1777               (lo (ldb (byte 10 0) value)))
1778           (inst sethi tmpreg hi)
1779           (inst jal link tmpreg lo)))
1780        (fixup
1781         (inst sethi tmpreg value)
1782         (inst jal link tmpreg value))))))
1783
1784 ;;; Jump to a full 32-bit address.  Tmpreg is trashed.
1785 (define-instruction ji (segment tmpreg value)
1786   (:declare (type tn tmpreg)
1787             (type (or (signed-byte 13) (signed-byte 32) (unsigned-byte 32)
1788                       fixup) value))
1789   (:attributes variable-length)
1790   (:vop-var vop)
1791   (:attributes branch)
1792   (:dependencies (writes tmpreg))
1793   (:delay 1)
1794   (:emitter
1795    (assemble (segment vop)
1796              (inst jali zero-tn tmpreg value))))
1797
1798 (define-instruction nop (segment)
1799   (:printer format-2-immed ((rd 0) (op2 #b100) (immed 0)) '(:name))
1800   (:attributes flushable)
1801   (:delay 0)
1802   (:emitter (emit-format-2-immed segment 0 0 #b100 0)))
1803
1804 (!def-vm-support-routine emit-nop (segment)
1805   (emit-format-2-immed segment 0 0 #b100 0))
1806
1807 (define-instruction cmp (segment src1 &optional src2)
1808   (:declare (type tn src1) (type (or null tn (signed-byte 13)) src2))
1809   (:printer format-3-reg ((op #b10) (op3 #b010100) (rd 0))
1810             '(:name :tab rs1 ", " rs2))
1811   (:printer format-3-immed ((op #b10) (op3 #b010100) (rd 0))
1812             '(:name :tab rs1 ", " immed))
1813   (:dependencies (reads src1) (if src2 (reads src2)) (writes :psr))
1814   (:delay 0)
1815   (:emitter
1816    (etypecase src2
1817      (null
1818       (emit-format-3-reg segment #b10 0 #b010100 (reg-tn-encoding src1) 0 0 0))
1819      (tn
1820       (emit-format-3-reg segment #b10 0 #b010100 (reg-tn-encoding src1) 0 0
1821                          (reg-tn-encoding src2)))
1822      (integer
1823       (emit-format-3-immed segment #b10 0 #b010100 (reg-tn-encoding src1) 1
1824                            src2)))))
1825
1826 (define-instruction not (segment dst &optional src1)
1827   (:declare (type tn dst) (type (or tn null) src1))
1828   (:printer format-3-reg ((op #b10) (op3 #b000111) (rs2 0))
1829             '(:name :tab (:unless (:same-as rd) rs1 ", " ) rd))
1830   (:dependencies (if src1 (reads src1) (reads dst)) (writes dst))
1831   (:delay 0)
1832   (:emitter
1833    (unless src1
1834      (setf src1 dst))
1835    (emit-format-3-reg segment #b10 (reg-tn-encoding dst) #b000111
1836                       (reg-tn-encoding src1) 0 0 0)))
1837
1838 (define-instruction neg (segment dst &optional src1)
1839   (:declare (type tn dst) (type (or tn null) src1))
1840   (:printer format-3-reg ((op #b10) (op3 #b000100) (rs1 0))
1841             '(:name :tab (:unless (:same-as rd) rs2 ", " ) rd))
1842   (:dependencies (if src1 (reads src1) (reads dst)) (writes dst))
1843   (:delay 0)
1844   (:emitter
1845    (unless src1
1846      (setf src1 dst))
1847    (emit-format-3-reg segment #b10 (reg-tn-encoding dst) #b000100
1848                       0 0 0 (reg-tn-encoding src1))))
1849
1850 (define-instruction move (segment dst src1)
1851   (:declare (type tn dst src1))
1852   (:printer format-3-reg ((op #b10) (op3 #b000010) (rs1 0))
1853             '(:name :tab rs2 ", " rd)
1854             :print-name 'mov)
1855   (:attributes flushable)
1856   (:dependencies (reads src1) (writes dst))
1857   (:delay 0)
1858   (:emitter (emit-format-3-reg segment #b10 (reg-tn-encoding dst) #b000010
1859                                0 0 0 (reg-tn-encoding src1))))
1860
1861
1862 \f
1863 ;;;; Instructions for dumping data and header objects.
1864
1865 (define-instruction word (segment word)
1866   (:declare (type (or (unsigned-byte 32) (signed-byte 32)) word))
1867   :pinned
1868   (:delay 0)
1869   (:emitter
1870    (emit-word segment word)))
1871
1872 (define-instruction short (segment short)
1873   (:declare (type (or (unsigned-byte 16) (signed-byte 16)) short))
1874   :pinned
1875   (:delay 0)
1876   (:emitter
1877    (emit-short segment short)))
1878
1879 (define-instruction byte (segment byte)
1880   (:declare (type (or (unsigned-byte 8) (signed-byte 8)) byte))
1881   :pinned
1882   (:delay 0)
1883   (:emitter
1884    (emit-byte segment byte)))
1885
1886 (define-bitfield-emitter emit-header-object 32
1887   (byte 24 8) (byte 8 0))
1888   
1889 (defun emit-header-data (segment type)
1890   (emit-back-patch
1891    segment 4
1892    (lambda (segment posn)
1893        (emit-word segment
1894                   (logior type
1895                           (ash (+ posn (component-header-length))
1896                                (- n-widetag-bits word-shift)))))))
1897
1898 (define-instruction simple-fun-header-word (segment)
1899   :pinned
1900   (:delay 0)
1901   (:emitter
1902    (emit-header-data segment simple-fun-header-widetag)))
1903
1904 (define-instruction lra-header-word (segment)
1905   :pinned
1906   (:delay 0)
1907   (:emitter
1908    (emit-header-data segment return-pc-header-widetag)))
1909
1910 \f
1911 ;;;; Instructions for converting between code objects, functions, and lras.
1912
1913 (defun emit-compute-inst (segment vop dst src label temp calc)
1914   (emit-chooser
1915    ;; We emit either 12 or 4 bytes, so we maintain 8 byte alignments.
1916    segment 12 3
1917    (lambda (segment posn delta-if-after)
1918        (let ((delta (funcall calc label posn delta-if-after)))
1919          (when (<= (- (ash 1 12)) delta (1- (ash 1 12)))
1920            (emit-back-patch segment 4
1921                             (lambda (segment posn)
1922                                 (assemble (segment vop)
1923                                           (inst add dst src
1924                                                 (funcall calc label posn 0)))))
1925            t)))
1926    (lambda (segment posn)
1927        (let ((delta (funcall calc label posn 0)))
1928          (assemble (segment vop)
1929                    (inst sethi temp (ldb (byte 22 10) delta))
1930                    (inst or temp (ldb (byte 10 0) delta))
1931                    (inst add dst src temp))))))
1932
1933 ;; code = fn - fn-ptr-type - header - label-offset + other-pointer-tag
1934 (define-instruction compute-code-from-fn (segment dst src label temp)
1935   (:declare (type tn dst src temp) (type label label))
1936   (:attributes variable-length)
1937   (:dependencies (reads src) (writes dst) (writes temp))
1938   (:delay 0)
1939   (:vop-var vop)
1940   (:emitter
1941    (emit-compute-inst segment vop dst src label temp
1942                       (lambda (label posn delta-if-after)
1943                           (- other-pointer-lowtag
1944                              fun-pointer-lowtag
1945                              (label-position label posn delta-if-after)
1946                              (component-header-length))))))
1947
1948 ;; code = lra - other-pointer-tag - header - label-offset + other-pointer-tag
1949 (define-instruction compute-code-from-lra (segment dst src label temp)
1950   (:declare (type tn dst src temp) (type label label))
1951   (:attributes variable-length)
1952   (:dependencies (reads src) (writes dst) (writes temp))
1953   (:delay 0)
1954   (:vop-var vop)
1955   (:emitter
1956    (emit-compute-inst segment vop dst src label temp
1957                       (lambda (label posn delta-if-after)
1958                           (- (+ (label-position label posn delta-if-after)
1959                                 (component-header-length)))))))
1960
1961 ;; lra = code + other-pointer-tag + header + label-offset - other-pointer-tag
1962 (define-instruction compute-lra-from-code (segment dst src label temp)
1963   (:declare (type tn dst src temp) (type label label))
1964   (:attributes variable-length)
1965   (:dependencies (reads src) (writes dst) (writes temp))
1966   (:delay 0)
1967   (:vop-var vop)
1968   (:emitter
1969    (emit-compute-inst segment vop dst src label temp
1970                       (lambda (label posn delta-if-after)
1971                           (+ (label-position label posn delta-if-after)
1972                              (component-header-length))))))
1973 \f
1974 ;;; Sparc V9 additions
1975
1976
1977
1978 ;; Conditional move integer on condition code
1979 (define-instruction cmove (segment condition dst src &optional (ccreg :icc))
1980   (:declare (type (or branch-condition fp-branch-condition) condition)
1981             (type cond-move-condition-register ccreg)
1982             (type tn dst)
1983             (type (or (signed-byte 13) tn) src))
1984   (:printer format-4-cond-move
1985             ((op #b10)
1986              (op3 #b101100)
1987              (cc2 #b1)
1988              (i 0)
1989              (cc nil :type 'integer-condition-register))
1990              cond-move-printer
1991              :print-name 'mov)
1992   (:printer format-4-cond-move-immed
1993             ((op #b10)
1994              (op3 #b101100)
1995              (cc2 #b1)
1996              (i 1)
1997              (cc nil :type 'integer-condition-register))
1998              cond-move-printer
1999              :print-name 'mov)
2000   (:printer format-4-cond-move
2001             ((op #b10)
2002              (op3 #b101100)
2003              (cc2 #b0)
2004              (cond nil :type 'branch-fp-condition)
2005              (i 0)
2006              (cc nil :type 'fp-condition-register))
2007              cond-move-printer
2008              :print-name 'mov)
2009   (:printer format-4-cond-move-immed
2010             ((op #b10)
2011              (op3 #b101100)
2012              (cc2 #b0)
2013              (cond nil :type 'branch-fp-condition)
2014              (i 1)
2015              (cc nil :type 'fp-condition-register))
2016              cond-move-printer
2017              :print-name 'mov)
2018   (:delay 0)
2019   (:dependencies
2020    (if (member ccreg '(:icc :xcc))
2021        (reads :psr)
2022        (reads :fsr))
2023    (reads src)
2024    (reads dst)
2025    (writes dst))
2026   (:emitter
2027    (let ((op #b10)
2028          (op3 #b101100))
2029      (multiple-value-bind (cc2 cc01)
2030          (cond-move-condition-parts ccreg)
2031        (etypecase src
2032          (tn
2033           (emit-format-4-cond-move segment
2034                                    op
2035                                    (reg-tn-encoding dst)
2036                                    op3
2037                                    cc2
2038                                    (if (member ccreg '(:icc :xcc))
2039                                        (branch-condition condition)
2040                                        (fp-branch-condition condition))
2041                                    0
2042                                    cc01
2043                                    (reg-tn-encoding src)))
2044          (integer
2045           (emit-format-4-cond-move segment
2046                                    op
2047                                    (reg-tn-encoding dst)
2048                                    op3
2049                                    cc2
2050                                    (if (member ccreg '(:icc :xcc))
2051                                        (branch-condition condition)
2052                                        (fp-branch-condition condition))
2053                                    1
2054                                    cc01
2055                                    src)))))))
2056
2057 ;; Conditional move floating-point on condition codes
2058 (macrolet ((define-cond-fp-move (name print-name op op3 opf_low &key extended)
2059   `(define-instruction ,name (segment condition dst src &optional (ccreg :fcc0))
2060      (:declare (type (or branch-condition fp-branch-condition) condition)
2061                (type cond-move-condition-register ccreg)
2062                (type tn dst src))
2063      (:printer format-fpop2
2064                ((op ,op)
2065                 (op3 ,op3)
2066                 (opf0 0)
2067                 (opf1 nil :type 'fp-condition-register-shifted)
2068                 (opf2 0)
2069                 (opf3 ,opf_low)
2070                 (rs1 nil :type 'branch-fp-condition)
2071                 (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
2072                 (rd nil :type ',(if extended 'fp-ext-reg 'fp-reg)))
2073                 cond-fp-move-printer
2074                 :print-name ',print-name)
2075      (:printer format-fpop2
2076                ((op ,op)
2077                 (op3 ,op3)
2078                 (opf0 1)
2079                 (opf1 nil :type 'integer-condition-register)
2080                 (opf2 0)
2081                 (rs1 nil :type 'branch-condition)
2082                 (opf3 ,opf_low)
2083                 (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
2084                 (rd nil :type ',(if extended 'fp-ext-reg 'fp-reg)))
2085                cond-fp-move-printer
2086                :print-name ',print-name)
2087      (:delay 0)
2088      (:dependencies
2089       (if (member ccreg '(:icc :xcc))
2090           (reads :psr)
2091           (reads :fsr))
2092       (reads src)
2093       (reads dst)
2094       (writes dst))
2095      (:emitter
2096       (multiple-value-bind (opf_cc2 opf_cc01)
2097           (cond-move-condition-parts ccreg)
2098         (emit-format-3-fpop2 segment
2099                              ,op
2100                              (fp-reg-tn-encoding dst)
2101                              ,op3
2102                              (if (member ccreg '(:icc :xcc))
2103                                  (branch-condition condition)
2104                                  (fp-branch-condition condition))
2105                              opf_cc2
2106                              (ash opf_cc01 1)
2107                              0
2108                              ,opf_low
2109                              (fp-reg-tn-encoding src)))))))
2110   (define-cond-fp-move cfmovs fmovs #b10 #b110101 #b0001)
2111   (define-cond-fp-move cfmovd fmovd #b10 #b110101 #b0010 :extended t)
2112   (define-cond-fp-move cfmovq fmovq #b10 #b110101 #b0011 :extended t))
2113
2114
2115 ;; Move on integer register condition
2116 ;;
2117 ;; movr dst src reg reg-cond
2118 ;;
2119 ;; This means if reg satisfies reg-cond, src is copied to dst.  If the
2120 ;; condition is not satisfied, nothing is done.
2121 ;;
2122 (define-instruction movr (segment dst src2 src1 reg-condition)
2123   (:declare (type cond-move-integer-condition reg-condition)
2124             (type tn dst src1)
2125             (type (or (signed-byte 10) tn) src2))
2126   (:printer format-4-cond-move-integer
2127             ((op #b10)
2128              (op3 #b101111)
2129              (i 0)))
2130   (:printer format-4-cond-move-integer-immed
2131             ((op #b10)
2132              (op3 #b101111)
2133              (i 1)))
2134   (:delay 0)
2135   (:dependencies
2136    (reads :psr)
2137    (reads src2)
2138    (reads src1)
2139    (reads dst)
2140    (writes dst))
2141   (:emitter
2142    (etypecase src2
2143      (tn
2144       (emit-format-4-cond-move-integer
2145        segment #b10 (reg-tn-encoding dst) #b101111 (reg-tn-encoding src1)
2146        0 (register-condition reg-condition)
2147        0 (reg-tn-encoding src2)))
2148      (integer
2149       (emit-format-4-cond-move-integer-immed
2150        segment #b10 (reg-tn-encoding dst) #b101111 (reg-tn-encoding src1)
2151        1 (register-condition reg-condition) src2)))))
2152
2153
2154 ;; Same as MOVR, except we move FP registers depending on the value of
2155 ;; an integer register.
2156 ;;
2157 ;; fmovr dst src reg cond
2158 ;;
2159 ;; This means if REG satifies COND, SRC is COPIED to DST.  Nothing
2160 ;; happens if the condition is not satisfied.
2161 (macrolet ((define-cond-fp-move-integer (name opf_low &key extended)
2162   `(define-instruction ,name (segment dst src2 src1 reg-condition)
2163      (:declare (type cond-move-integer-condition reg-condition)
2164                (type tn dst src1 src2))
2165      (:printer format-fpop2
2166                ((op #b10)
2167                 (rd nil :type ',(if extended 'fp-ext-reg 'fp-reg))
2168                 (op3 #b110101)
2169                 (rs1 nil :type 'reg)
2170                 (opf0 0)
2171                 (opf1 nil :type 'register-condition)
2172                 (opf2 0)
2173                 (opf3 ,opf_low)
2174                 (rs2 nil :type ',(if extended 'fp-ext-reg 'fp-reg))
2175                 )
2176                cond-fp-move-integer-printer)
2177      (:delay 0)
2178      (:dependencies
2179       (reads src2)
2180       (reads src1)
2181       (reads dst)
2182       (writes dst))
2183      (:emitter
2184       (emit-format-3-fpop2
2185        segment
2186        #b10
2187        (fp-reg-tn-encoding dst)
2188        #b110101
2189        (reg-tn-encoding src1)
2190        0
2191        (register-condition reg-condition)
2192        0
2193        ,opf_low
2194        (fp-reg-tn-encoding src2))))))
2195   (define-cond-fp-move-integer fmovrs #b0101)
2196   (define-cond-fp-move-integer fmovrd #b0110 :extended t)
2197   (define-cond-fp-move-integer fmovrq #b0111 :extended t))