1 ;;;; the instruction set definition for the Sparc
3 ;;;; This software is part of the SBCL system. See the README file for
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.
14 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
15 (setf sb
!assem
:*assem-scheduler-p
* t
)
16 (setf sb
!assem
:*assem-max-locations
* 100))
18 ;;; Constants, types, conversion functions, some disassembler stuff.
19 (defun reg-tn-encoding (tn)
20 (declare (type tn tn
))
25 (if (eq (sb-name (sc-sb (tn-sc tn
))) 'registers
)
27 (error "~S isn't a register." tn
)))))
29 (defun fp-reg-tn-encoding (tn)
30 (declare (type tn tn
))
31 (unless (eq (sb-name (sc-sb (tn-sc tn
))) 'float-registers
)
32 (error "~S isn't a floating-point register." tn
))
33 (let ((offset (tn-offset tn
)))
35 (assert (member :sparc-v9
*backend-subfeatures
*))
36 ;; No single register encoding greater than reg 31.
37 (assert (zerop (mod offset
2)))
38 ;; Upper bit of the register number is encoded in the low bit.
43 ;;;(sb!disassem:set-disassem-params :instruction-alignment 32
44 ;;; :opcode-column-width 11)
46 (defvar *disassem-use-lisp-reg-names
* t
48 "If non-NIL, print registers using the Lisp register names.
49 Otherwise, use the Sparc register names")
51 (!def-vm-support-routine location-number
(loc)
57 (ecase (sb-name (sc-sb (tn-sc loc
)))
59 (unless (zerop (tn-offset loc
))
64 (+ (tn-offset loc
) 32))
66 (let ((offset (tn-offset loc
)))
67 (assert (zerop (mod offset
2)))
68 (values (+ offset
32) 2)))
71 (let ((offset (tn-offset loc
)))
72 (assert (zerop (mod offset
4)))
73 (values (+ offset
32) 4)))))
85 ;;; symbols used for disassembly printing
86 (defparameter reg-symbols
89 (cond ((null name
) nil
)
90 (t (make-symbol (concatenate 'string
"%" name
)))))
92 #!+sb-doc
"The Lisp names for the Sparc integer registers")
94 (defparameter sparc-reg-symbols
95 #("%G0" "%G1" "%G2" "%G3" "%G4" "%G5" NIL NIL
96 "%O0" "%O1" "%O2" "%O3" "%O4" "%O5" "%O6" "%O7"
97 "%L0" "%L1" "%L2" "%L3" "%L4" "%L5" "%L6" "%L7"
98 "%I0" "%I1" "%I2" "%I3" "%I4" "%I5" NIL
"%I7")
99 #!+sb-doc
"The standard names for the Sparc integer registers")
101 (defun get-reg-name (index)
102 (if *disassem-use-lisp-reg-names
*
103 (aref reg-symbols index
)
104 (aref sparc-reg-symbols index
)))
106 (defvar *note-sethi-inst
* nil
107 "An alist for the disassembler indicating the target register and
108 value used in a SETHI instruction. This is used to make annotations
109 about function addresses and register values.")
111 (defvar *pseudo-atomic-set
* nil
)
113 (defun sign-extend-immed-value (val)
114 ;; val is a 13-bit signed number. Extend the sign appropriately.
119 ;; Look at the current instruction and see if we can't add some notes
120 ;; about what's happening.
122 (defun maybe-add-notes (reg dstate
)
123 (let* ((word (sb!disassem
::sap-ref-int
(sb!disassem
::dstate-segment-sap dstate
)
124 (sb!disassem
::dstate-cur-offs dstate
)
126 (sb!disassem
::dstate-byte-order dstate
)))
127 (format (ldb (byte 2 30) word
))
128 (op3 (ldb (byte 6 19) word
))
129 (rs1 (ldb (byte 5 14) word
))
130 (rd (ldb (byte 5 25) word
))
131 (immed-p (not (zerop (ldb (byte 1 13) word
))))
132 (immed-val (sign-extend-immed-value (ldb (byte 13 0) word
))))
133 (declare (ignore immed-p
))
134 ;; Only the value of format and rd are guaranteed to be correct
135 ;; because the disassembler is trying to print out the value of a
136 ;; register. The other values may not be right.
142 (handle-add-inst rs1 immed-val rd dstate
)))
145 (handle-jmpl-inst rs1 immed-val rd dstate
)))
148 (handle-andcc-inst rs1 immed-val rd dstate
)))))
153 (handle-ld/st-inst rs1 immed-val rd dstate
))))))
154 ;; If this is not a SETHI instruction, and RD is the same as some
155 ;; register used by SETHI, we delete the entry. (In case we have
156 ;; a SETHI without any additional instruction because the low bits
158 (unless (and (zerop format
) (= #b100
(ldb (byte 3 22) word
)))
159 (let ((sethi (assoc rd
*note-sethi-inst
*)))
161 (setf *note-sethi-inst
* (delete sethi
*note-sethi-inst
*)))))))
163 (defun handle-add-inst (rs1 immed-val rd dstate
)
164 (let* ((sethi (assoc rs1
*note-sethi-inst
*)))
167 ;; RS1 was used in a SETHI instruction. Assume that
168 ;; this is the offset part of the SETHI instruction for
169 ;; a full 32-bit address of something. Make a note
170 ;; about this usage as a Lisp assembly routine or
171 ;; foreign routine, if possible. If not, just note the
173 (let ((addr (+ immed-val
(ash (cdr sethi
) 10))))
174 (or (sb!disassem
::note-code-constant-absolute addr dstate
)
175 (sb!disassem
:maybe-note-assembler-routine addr t dstate
)
176 (sb!disassem
:note
(format nil
"~A = #x~8,'0X"
177 (get-reg-name rd
) addr
)
179 (setf *note-sethi-inst
* (delete sethi
*note-sethi-inst
*)))
181 ;; We have an ADD %NULL, <n>, RD instruction. This is a
182 ;; reference to a static symbol.
183 (sb!disassem
:maybe-note-nil-indexed-object immed-val
185 ((= rs1 alloc-offset
)
186 ;; ADD %ALLOC, n. This must be some allocation or
187 ;; pseudo-atomic stuff
188 (cond ((and (= immed-val
4) (= rd alloc-offset
)
189 (not *pseudo-atomic-set
*))
190 ;; "ADD 4, %ALLOC" sets the flag
191 (sb!disassem
::note
"Set pseudo-atomic flag" dstate
)
192 (setf *pseudo-atomic-set
* t
))
194 ;; "ADD n, %ALLOC" is reseting the flag, with extra
197 (format nil
"Reset pseudo-atomic, allocated ~D bytes"
198 (+ immed-val
4)) dstate
)
199 (setf *pseudo-atomic-set
* nil
))))
200 #+nil
((and (= rs1 zero-offset
) *pseudo-atomic-set
*)
201 ;; "ADD %ZERO, num, RD" inside a pseudo-atomic is very
202 ;; likely loading up a header word. Make a note to that
204 (let ((type (second (assoc (logand immed-val
#xff
) header-word-type-alist
)))
205 (size (ldb (byte 24 8) immed-val
)))
207 (sb!disassem
:note
(format nil
"Header word ~A, size ~D?" type size
)
210 (defun handle-jmpl-inst (rs1 immed-val rd dstate
)
211 (declare (ignore rd
))
212 (let* ((sethi (assoc rs1
*note-sethi-inst
*)))
214 ;; RS1 was used in a SETHI instruction. Assume that
215 ;; this is the offset part of the SETHI instruction for
216 ;; a full 32-bit address of something. Make a note
217 ;; about this usage as a Lisp assembly routine or
218 ;; foreign routine, if possible. If not, just note the
220 (let ((addr (+ immed-val
(ash (cdr sethi
) 10))))
221 (sb!disassem
:maybe-note-assembler-routine addr t dstate
)
222 (setf *note-sethi-inst
* (delete sethi
*note-sethi-inst
*))))))
224 (defun handle-ld/st-inst
(rs1 immed-val rd dstate
)
225 (declare (ignore rd
))
226 ;; Got an LDUW/LD or STW instruction, with immediate offset.
229 ;; A reference to a code constant (reg = %CODE)
230 (sb!disassem
:note-code-constant immed-val dstate
))
232 ;; A reference to a static symbol or static function (reg =
234 (or (sb!disassem
:maybe-note-nil-indexed-symbol-slot-ref immed-val
236 #+nil
(sb!disassem
::maybe-note-static-function immed-val dstate
)))
238 (let ((sethi (assoc rs1
*note-sethi-inst
*)))
240 (let ((addr (+ immed-val
(ash (cdr sethi
) 10))))
241 (sb!disassem
:maybe-note-assembler-routine addr nil dstate
)
242 (setf *note-sethi-inst
* (delete sethi
*note-sethi-inst
*))))))))
244 (defun handle-andcc-inst (rs1 immed-val rd dstate
)
245 ;; ANDCC %ALLOC, 3, %ZERO instruction
246 (when (and (= rs1 alloc-offset
) (= rd zero-offset
) (= immed-val
3))
247 (sb!disassem
:note
"pseudo-atomic interrupted?" dstate
)))
249 (sb!disassem
:define-arg-type reg
250 :printer
(lambda (value stream dstate
)
251 (declare (stream stream
) (fixnum value
))
252 (let ((regname (get-reg-name value
)))
253 (princ regname stream
)
254 (sb!disassem
:maybe-note-associated-storage-ref value
258 (maybe-add-notes value dstate
))))
260 (defparameter float-reg-symbols
262 (loop for n from
0 to
63 collect
(make-symbol (format nil
"%F~d" n
)))
265 (sb!disassem
:define-arg-type fp-reg
266 :printer
(lambda (value stream dstate
)
267 (declare (stream stream
) (fixnum value
))
268 (let ((regname (aref float-reg-symbols value
)))
269 (princ regname stream
)
270 (sb!disassem
:maybe-note-associated-storage-ref
276 ;;; The extended 6 bit floating point register encoding for the double
277 ;;; and long instructions of the sparc v9.
278 (sb!disassem
:define-arg-type fp-ext-reg
279 :printer
(lambda (value stream dstate
)
280 (declare (stream stream
) (fixnum value
))
281 (let* (;; Decode the register number.
282 (value (if (oddp value
) (+ value
31) value
))
283 (regname (aref float-reg-symbols value
)))
284 (princ regname stream
)
285 (sb!disassem
:maybe-note-associated-storage-ref
291 (sb!disassem
:define-arg-type relative-label
293 :use-label
(lambda (value dstate
)
294 (declare (type (signed-byte 22) value
)
295 (type sb
!disassem
:disassem-state dstate
))
296 (+ (ash value
2) (sb!disassem
:dstate-cur-addr dstate
))))
298 (defconstant-eqx branch-conditions
299 '(:f
:eq
:le
:lt
:leu
:ltu
:n
:vs
:t
:ne
:gt
:ge
:gtu
:geu
:p
:vc
)
302 ;;; Note that these aren't the standard names for branch-conditions, I
303 ;;; think they're a bit more readable (e.g., "eq" instead of "e").
304 ;;; You could just put a vector of the normal ones here too.
306 (sb!disassem
:define-arg-type branch-condition
307 :printer
(coerce branch-conditions
'vector
))
309 (deftype branch-condition
()
310 `(member ,@branch-conditions
))
312 (defun branch-condition (condition)
313 (or (position condition branch-conditions
)
314 (error "Unknown branch condition: ~S~%Must be one of: ~S"
315 condition branch-conditions
)))
317 (def!constant branch-cond-true
320 (defconstant-eqx branch-fp-conditions
321 '(:f
:ne
:lg
:ul
:l
:ug
:g
:u
:t
:eq
:ue
:ge
:uge
:le
:ule
:o
)
324 (sb!disassem
:define-arg-type branch-fp-condition
325 :printer
(coerce branch-fp-conditions
'vector
))
327 (sb!disassem
:define-arg-type call-fixup
:use-label t
)
329 (deftype fp-branch-condition
()
330 `(member ,@branch-fp-conditions
))
332 (defun fp-branch-condition (condition)
333 (or (position condition branch-fp-conditions
)
334 (error "Unknown fp-branch condition: ~S~%Must be one of: ~S"
335 condition branch-fp-conditions
)))
338 ;;;; dissassem:define-instruction-formats
340 (sb!disassem
:define-instruction-format
341 (format-1 32 :default-printer
'(:name
:tab disp
))
342 (op :field
(byte 2 30) :value
1)
343 (disp :field
(byte 30 0)))
345 (sb!disassem
:define-instruction-format
346 (format-2-immed 32 :default-printer
'(:name
:tab immed
", " rd
))
347 (op :field
(byte 2 30) :value
0)
348 (rd :field
(byte 5 25) :type
'reg
)
349 (op2 :field
(byte 3 22))
350 (immed :field
(byte 22 0)))
354 (sb!disassem
:define-instruction-format
355 (format-2-branch 32 :default-printer
`(:name
(:unless
(:constant
,branch-cond-true
) cond
)
356 (:unless
(a :constant
0) "," 'A
)
359 (op :field
(byte 2 30) :value
0)
360 (a :field
(byte 1 29) :value
0)
361 (cond :field
(byte 4 25) :type
'branch-condition
)
362 (op2 :field
(byte 3 22))
363 (disp :field
(byte 22 0) :type
'relative-label
))
365 ;; Branch with prediction instruction for V9
367 ;; Currently only %icc and %xcc are used of the four possible values
369 (defconstant-eqx integer-condition-registers
370 '(:icc
:reserved
:xcc
:reserved
)
373 (defconstant-eqx integer-cond-reg-name-vec
374 (coerce integer-condition-registers
'vector
)
377 (deftype integer-condition-register
()
378 `(member ,@(remove :reserved integer-condition-registers
)))
380 (defparameter integer-condition-reg-symbols
383 (make-symbol (concatenate 'string
"%" (string name
))))
384 integer-condition-registers
))
386 (sb!disassem
:define-arg-type integer-condition-register
387 :printer
(lambda (value stream dstate
)
388 (declare (stream stream
) (fixnum value
) (ignore dstate
))
389 (let ((regname (aref integer-condition-reg-symbols value
)))
390 (princ regname stream
))))
392 (defconstant-eqx branch-predictions
396 (sb!disassem
:define-arg-type branch-prediction
397 :printer
(coerce branch-predictions
'vector
))
399 (defun integer-condition (condition-reg)
400 (declare (type (member :icc
:xcc
) condition-reg
))
401 (or (position condition-reg integer-condition-registers
)
402 (error "Unknown integer condition register: ~S~%"
405 (defun branch-prediction (pred)
406 (or (position pred branch-predictions
)
407 (error "Unknown branch prediction: ~S~%Must be one of: ~S~%"
408 pred branch-predictions
)))
410 (defconstant-eqx branch-pred-printer
411 `(:name
(:unless
(:constant
,branch-cond-true
) cond
)
412 (:unless
(a :constant
0) "," 'A
)
413 (:unless
(p :constant
1) "," 'pn
)
420 (sb!disassem
:define-instruction-format
421 (format-2-branch-pred 32 :default-printer branch-pred-printer
)
422 (op :field
(byte 2 30) :value
0)
423 (a :field
(byte 1 29) :value
0)
424 (cond :field
(byte 4 25) :type
'branch-condition
)
425 (op2 :field
(byte 3 22))
426 (cc :field
(byte 2 20) :type
'integer-condition-register
)
427 (p :field
(byte 1 19))
428 (disp :field
(byte 19 0) :type
'relative-label
))
430 (defconstant-eqx fp-condition-registers
431 '(:fcc0
:fcc1
:fcc2
:fcc3
)
434 (defconstant-eqx fp-cond-reg-name-vec
435 (coerce fp-condition-registers
'vector
)
438 (defparameter fp-condition-reg-symbols
441 (make-symbol (concatenate 'string
"%" (string name
))))
442 fp-condition-registers
))
444 (sb!disassem
:define-arg-type fp-condition-register
445 :printer
(lambda (value stream dstate
)
446 (declare (stream stream
) (fixnum value
) (ignore dstate
))
447 (let ((regname (aref fp-condition-reg-symbols value
)))
448 (princ regname stream
))))
450 (sb!disassem
:define-arg-type fp-condition-register-shifted
451 :printer
(lambda (value stream dstate
)
452 (declare (stream stream
) (fixnum value
) (ignore dstate
))
453 (let ((regname (aref fp-condition-reg-symbols
(ash value -
1))))
454 (princ regname stream
))))
456 (defun fp-condition (condition-reg)
457 (or (position condition-reg fp-condition-registers
)
458 (error "Unknown integer condition register: ~S~%"
461 (defconstant-eqx fp-branch-pred-printer
462 `(:name
(:unless
(:constant
,branch-cond-true
) cond
)
463 (:unless
(a :constant
0) "," 'A
)
464 (:unless
(p :constant
1) "," 'pn
)
471 (sb!disassem
:define-instruction-format
472 (format-2-fp-branch-pred 32 :default-printer fp-branch-pred-printer
)
473 (op :field
(byte 2 30) :value
0)
474 (a :field
(byte 1 29) :value
0)
475 (cond :field
(byte 4 25) :type
'branch-fp-condition
)
476 (op2 :field
(byte 3 22))
477 (fcc :field
(byte 2 20) :type
'fp-condition-register
)
478 (p :field
(byte 1 19))
479 (disp :field
(byte 19 0) :type
'relative-label
))
483 (sb!disassem
:define-instruction-format
484 (format-2-unimp 32 :default-printer
'(:name
:tab data
))
485 (op :field
(byte 2 30) :value
0)
486 (ignore :field
(byte 5 25) :value
0)
487 (op2 :field
(byte 3 22) :value
0)
488 (data :field
(byte 22 0)))
490 (defconstant-eqx f3-printer
492 (:unless
(:same-as rd
) rs1
", ")
493 (:choose rs2 immed
) ", "
497 (sb!disassem
:define-instruction-format
498 (format-3-reg 32 :default-printer f3-printer
)
499 (op :field
(byte 2 30))
500 (rd :field
(byte 5 25) :type
'reg
)
501 (op3 :field
(byte 6 19))
502 (rs1 :field
(byte 5 14) :type
'reg
)
503 (i :field
(byte 1 13) :value
0)
504 (asi :field
(byte 8 5) :value
0)
505 (rs2 :field
(byte 5 0) :type
'reg
))
507 (sb!disassem
:define-instruction-format
508 (format-3-immed 32 :default-printer f3-printer
)
509 (op :field
(byte 2 30))
510 (rd :field
(byte 5 25) :type
'reg
)
511 (op3 :field
(byte 6 19))
512 (rs1 :field
(byte 5 14) :type
'reg
)
513 (i :field
(byte 1 13) :value
1)
514 (immed :field
(byte 13 0) :sign-extend t
)) ; usually sign extended
516 (sb!disassem
:define-instruction-format
517 (format-binary-fpop 32
518 :default-printer
'(:name
:tab rs1
", " rs2
", " rd
))
519 (op :field
(byte 2 30))
520 (rd :field
(byte 5 25) :type
'fp-reg
)
521 (op3 :field
(byte 6 19))
522 (rs1 :field
(byte 5 14) :type
'fp-reg
)
523 (opf :field
(byte 9 5))
524 (rs2 :field
(byte 5 0) :type
'fp-reg
))
526 ;;; Floating point load/save instructions encoding.
527 (sb!disassem
:define-instruction-format
528 (format-unary-fpop 32 :default-printer
'(:name
:tab rs2
", " rd
))
529 (op :field
(byte 2 30))
530 (rd :field
(byte 5 25) :type
'fp-reg
)
531 (op3 :field
(byte 6 19))
532 (rs1 :field
(byte 5 14) :value
0)
533 (opf :field
(byte 9 5))
534 (rs2 :field
(byte 5 0) :type
'fp-reg
))
536 ;;; Floating point comparison instructions encoding.
538 ;; This is a merge of the instructions for FP comparison and FP
539 ;; conditional moves available in the Sparc V9. The main problem is
540 ;; that the new instructions use part of the opcode space used by the
541 ;; comparison instructions. In particular, the OPF field is arranged
546 ;; FMOVcc 0nn0000xx %fccn
552 ;; So we see that if we break up the OPF field into 4 pieces, opf0,
553 ;; opf1, opf2, and opf3, we can distinguish between these
554 ;; instructions. So bit 9 (opf2) can be used to distinguish between
555 ;; FCMP and the rest. Also note that the nn field overlaps with the
556 ;; ccc. We need to take this into account as well.
558 (sb!disassem
:define-instruction-format
560 :default-printer
#!-sparc-v9
'(:name
:tab rs1
", " rs2
)
561 #!+sparc-v9
'(:name
:tab rd
", " rs1
", " rs2
))
562 (op :field
(byte 2 30))
563 (rd :field
(byte 5 25) :value
0)
564 (op3 :field
(byte 6 19))
565 (rs1 :field
(byte 5 14))
566 (opf0 :field
(byte 1 13))
567 (opf1 :field
(byte 3 10))
568 (opf2 :field
(byte 1 9))
569 (opf3 :field
(byte 4 5))
570 (rs2 :field
(byte 5 0) :type
'fp-reg
))
572 ;;; Shift instructions
573 (sb!disassem
:define-instruction-format
574 (format-3-shift-reg 32 :default-printer f3-printer
)
575 (op :field
(byte 2 30))
576 (rd :field
(byte 5 25) :type
'reg
)
577 (op3 :field
(byte 6 19))
578 (rs1 :field
(byte 5 14) :type
'reg
)
579 (i :field
(byte 1 13) :value
0)
580 (x :field
(byte 1 12))
581 (asi :field
(byte 7 5) :value
0)
582 (rs2 :field
(byte 5 0) :type
'reg
))
584 (sb!disassem
:define-instruction-format
585 (format-3-shift-immed 32 :default-printer f3-printer
)
586 (op :field
(byte 2 30))
587 (rd :field
(byte 5 25) :type
'reg
)
588 (op3 :field
(byte 6 19))
589 (rs1 :field
(byte 5 14) :type
'reg
)
590 (i :field
(byte 1 13) :value
1)
591 (x :field
(byte 1 12))
592 (immed :field
(byte 12 0) :sign-extend nil
))
595 ;;; Conditional moves (only available for Sparc V9 architectures)
597 ;; The names of all of the condition registers on the V9: 4 FP
598 ;; conditions, the original integer condition register and the new
599 ;; extended register. The :reserved register is reserved on the V9.
601 (defconstant-eqx cond-move-condition-registers
602 '(:fcc0
:fcc1
:fcc2
:fcc3
:icc
:reserved
:xcc
:reserved
)
605 (defconstant-eqx cond-move-cond-reg-name-vec
606 (coerce cond-move-condition-registers
'vector
)
609 (deftype cond-move-condition-register
()
610 `(member ,@(remove :reserved cond-move-condition-registers
)))
612 (defparameter cond-move-condition-reg-symbols
615 (make-symbol (concatenate 'string
"%" (string name
))))
616 cond-move-condition-registers
))
618 (sb!disassem
:define-arg-type cond-move-condition-register
619 :printer
(lambda (value stream dstate
)
620 (declare (stream stream
) (fixnum value
) (ignore dstate
))
621 (let ((regname (aref cond-move-condition-reg-symbols value
)))
622 (princ regname stream
))))
624 ;; From the given condition register, figure out what the cc2, cc1,
625 ;; and cc0 bits should be. Return cc2 and cc1/cc0 concatenated.
626 (defun cond-move-condition-parts (condition-reg)
627 (let ((posn (position condition-reg cond-move-condition-registers
)))
630 (error "Unknown conditional move condition register: ~S~%"
633 (defun cond-move-condition (condition-reg)
634 (or (position condition-reg cond-move-condition-registers
)
635 (error "Unknown conditional move condition register: ~S~%"
638 (defconstant-eqx cond-move-printer
640 cc
", " (:choose immed rs2
) ", " rd
)
643 ;; Conditional move integer register on integer or FP condition code
644 (sb!disassem
:define-instruction-format
645 (format-4-cond-move 32 :default-printer cond-move-printer
)
646 (op :field
(byte 2 30))
647 (rd :field
(byte 5 25) :type
'reg
)
648 (op3 :field
(byte 6 19))
649 (cc2 :field
(byte 1 18) :value
1)
650 (cond :field
(byte 4 14) :type
'branch-condition
)
651 (i :field
(byte 1 13) :value
0)
652 (cc :field
(byte 2 11) :type
'integer-condition-register
)
653 (empty :field
(byte 6 5) :value
0)
654 (rs2 :field
(byte 5 0) :type
'reg
))
656 (sb!disassem
:define-instruction-format
657 (format-4-cond-move-immed 32 :default-printer cond-move-printer
)
658 (op :field
(byte 2 30))
659 (rd :field
(byte 5 25) :type
'reg
)
660 (op3 :field
(byte 6 19))
661 (cc2 :field
(byte 1 18) :value
1)
662 (cond :field
(byte 4 14) :type
'branch-condition
)
663 (i :field
(byte 1 13) :value
1)
664 (cc :field
(byte 2 11) :type
'integer-condition-register
)
665 (immed :field
(byte 11 0) :sign-extend t
))
667 ;; Floating-point versions of the above integer conditional moves
668 (defconstant-eqx cond-fp-move-printer
669 `(:name rs1
:tab opf1
", " rs2
", " rd
)
672 ;;; Conditional move on integer register condition (only on Sparc
673 ;;; V9). That is, move an integer register if some other integer
674 ;;; register satisfies some condition.
676 (defconstant-eqx cond-move-integer-conditions
677 '(:reserved
:z
:lez
:lz
:reserved
:nz
:gz
:gez
)
680 (defconstant-eqx cond-move-integer-condition-vec
681 (coerce cond-move-integer-conditions
'vector
)
684 (deftype cond-move-integer-condition
()
685 `(member ,@(remove :reserved cond-move-integer-conditions
)))
687 (sb!disassem
:define-arg-type register-condition
688 :printer
(lambda (value stream dstate
)
689 (declare (stream stream
) (fixnum value
) (ignore dstate
))
690 (let ((regname (aref cond-move-integer-condition-vec value
)))
691 (princ regname stream
))))
693 (defconstant-eqx cond-move-integer-printer
694 `(:name rcond
:tab rs1
", " (:choose immed rs2
) ", " rd
)
697 (defun register-condition (rcond)
698 (or (position rcond cond-move-integer-conditions
)
699 (error "Unknown register condition: ~S~%" rcond
)))
701 (sb!disassem
:define-instruction-format
702 (format-4-cond-move-integer 32 :default-printer cond-move-integer-printer
)
703 (op :field
(byte 2 30))
704 (rd :field
(byte 5 25) :type
'reg
)
705 (op3 :field
(byte 6 19))
706 (rs1 :field
(byte 5 14) :type
'reg
)
707 (i :field
(byte 1 13) :value
0)
708 (rcond :field
(byte 3 10) :type
'register-condition
)
709 (opf :field
(byte 5 5))
710 (rs2 :field
(byte 5 0) :type
'reg
))
712 (sb!disassem
:define-instruction-format
713 (format-4-cond-move-integer-immed 32 :default-printer cond-move-integer-printer
)
714 (op :field
(byte 2 30))
715 (rd :field
(byte 5 25) :type
'reg
)
716 (op3 :field
(byte 6 19))
717 (rs1 :field
(byte 5 14) :type
'reg
)
718 (i :field
(byte 1 13) :value
1)
719 (rcond :field
(byte 3 10) :type
'register-condition
)
720 (immed :field
(byte 10 0) :sign-extend t
))
722 (defconstant-eqx trap-printer
723 `(:name rd
:tab cc
", " immed
)
726 (sb!disassem
:define-instruction-format
727 (format-4-trap 32 :default-printer trap-printer
)
728 (op :field
(byte 2 30))
729 (rd :field
(byte 5 25) :type
'reg
)
730 (op3 :field
(byte 6 19))
731 (rs1 :field
(byte 5 14) :type
'reg
)
732 (i :field
(byte 1 13) :value
1)
733 (cc :field
(byte 2 11) :type
'integer-condition-register
)
734 (immed :field
(byte 11 0) :sign-extend t
)) ; usually sign extended
737 (defconstant-eqx cond-fp-move-integer-printer
738 `(:name opf1
:tab rs1
", " rs2
", " rd
)
742 ;;;; Primitive emitters.
744 (define-bitfield-emitter emit-word
32
747 (define-bitfield-emitter emit-short
16
750 (define-bitfield-emitter emit-format-1
32
751 (byte 2 30) (byte 30 0))
753 (define-bitfield-emitter emit-format-2-immed
32
754 (byte 2 30) (byte 5 25) (byte 3 22) (byte 22 0))
756 (define-bitfield-emitter emit-format-2-branch
32
757 (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 22 0))
759 ;; Integer and FP branches with prediction for V9
760 (define-bitfield-emitter emit-format-2-branch-pred
32
761 (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 2 20) (byte 1 19) (byte 19 0))
762 (define-bitfield-emitter emit-format-2-fp-branch-pred
32
763 (byte 2 30) (byte 1 29) (byte 4 25) (byte 3 22) (byte 2 20) (byte 1 19) (byte 19 0))
765 (define-bitfield-emitter emit-format-2-unimp
32
766 (byte 2 30) (byte 5 25) (byte 3 22) (byte 22 0))
768 (define-bitfield-emitter emit-format-3-reg
32
769 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 8 5)
772 (define-bitfield-emitter emit-format-3-immed
32
773 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 13 0))
775 (define-bitfield-emitter emit-format-3-fpop
32
776 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 9 5) (byte 5 0))
778 (define-bitfield-emitter emit-format-3-fpop2
32
779 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14)
780 (byte 1 13) (byte 3 10) (byte 1 9) (byte 4 5)
783 ;;; Shift instructions
785 (define-bitfield-emitter emit-format-3-shift-reg
32
786 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 1 12) (byte 7 5)
789 (define-bitfield-emitter emit-format-3-shift-immed
32
790 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 1 12) (byte 12 0))
792 ;;; Conditional moves
794 ;; Conditional move in condition code
795 (define-bitfield-emitter emit-format-4-cond-move
32
796 (byte 2 30) (byte 5 25) (byte 6 19) (byte 1 18) (byte 4 14) (byte 1 13) (byte 2 11)
799 ;; Conditional move on integer condition
800 (define-bitfield-emitter emit-format-4-cond-move-integer
32
801 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 3 10) (byte 5 5)
804 (define-bitfield-emitter emit-format-4-cond-move-integer-immed
32
805 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 3 10)
808 (define-bitfield-emitter emit-format-4-trap
32
809 (byte 2 30) (byte 5 25) (byte 6 19) (byte 5 14) (byte 1 13) (byte 2 11)
813 ;;;; Most of the format-3-instructions.
815 (defun emit-format-3-inst (segment op op3 dst src1 src2
816 &key load-store fixup dest-kind
)
818 (cond ((and (typep src1
'tn
) load-store
)
825 (emit-format-3-reg segment op
827 (fp-reg-tn-encoding dst
)
828 (reg-tn-encoding dst
))
829 op3
(reg-tn-encoding src1
) 0 0 (reg-tn-encoding src2
)))
831 (emit-format-3-immed segment op
833 (fp-reg-tn-encoding dst
)
834 (reg-tn-encoding dst
))
835 op3
(reg-tn-encoding src1
) 1 src2
))
837 (unless (or load-store fixup
)
838 (error "Fixups aren't allowed."))
839 (note-fixup segment
:add src2
)
840 (emit-format-3-immed segment op
842 (fp-reg-tn-encoding dst
)
843 (reg-tn-encoding dst
))
844 op3
(reg-tn-encoding src1
) 1 0))))
846 ;;; Shift instructions because an extra bit is used in Sparc V9's to
847 ;;; indicate whether the shift is a 32-bit or 64-bit shift.
849 (defun emit-format-3-shift-inst (segment op op3 dst src1 src2
&key extended
)
855 (emit-format-3-shift-reg segment op
(reg-tn-encoding dst
)
856 op3
(reg-tn-encoding src1
) 0 (if extended
1 0)
857 0 (reg-tn-encoding src2
)))
859 (emit-format-3-shift-immed segment op
(reg-tn-encoding dst
)
860 op3
(reg-tn-encoding src1
) 1
861 (if extended
1 0) src2
))))
864 (eval-when (:compile-toplevel
:execute
)
866 ;;; have to do this because def!constant is evalutated in the null lex env.
867 (defmacro with-ref-format
(printer)
869 '(:choose
(:plus-integer immed
) ("+" rs2
)))
871 `("[" rs1
(:unless
(:constant
0) ,addend
) "]"
872 (:choose
(:unless
(:constant
0) asi
) nil
))))
875 (defconstant-eqx load-printer
876 (with-ref-format `(:NAME
:TAB
,ref-format
", " rd
))
879 (defconstant-eqx store-printer
880 (with-ref-format `(:NAME
:TAB rd
", " ,ref-format
))
885 (macrolet ((define-f3-inst (name op op3
&key fixup load-store
(dest-kind 'reg
)
886 (printer :default
) reads writes flushable print-name
)
888 (if (eq printer
:default
)
891 ((:load t
) 'load-printer
)
892 (:store
'store-printer
))
894 (when (and (atom reads
) (not (null reads
)))
895 (setf reads
(list reads
)))
896 (when (and (atom writes
) (not (null writes
)))
897 (setf writes
(list writes
)))
898 `(define-instruction ,name
(segment dst src1
&optional src2
)
899 (:declare
(type tn dst
)
900 ,(if (or fixup load-store
)
901 '(type (or tn
(signed-byte 13) null fixup
) src1 src2
)
902 '(type (or tn
(signed-byte 13) null
) src1 src2
)))
903 (:printer format-3-reg
904 ((op ,op
) (op3 ,op3
) (rd nil
:type
',dest-kind
))
906 ,@(when print-name
`(:print-name
,print-name
)))
907 (:printer format-3-immed
908 ((op ,op
) (op3 ,op3
) (rd nil
:type
',dest-kind
))
910 ,@(when print-name
`(:print-name
,print-name
)))
912 '((:attributes flushable
)))
915 ,@(let ((reads-list nil
))
917 (push (list 'reads read
) reads-list
))
919 ,@(cond ((eq load-store
:store
)
921 (if src2
(reads src2
))))
925 (if src2
(reads src2
))))
926 ((eq load-store
:load
)
928 (if src2
(reads src2
) (reads dst
))))
930 '((if src2
(reads src2
) (reads dst
)))))
931 ,@(let ((writes-list nil
))
932 (dolist (write writes
)
933 (push (list 'writes write
) writes-list
))
935 ,@(cond ((eq load-store
:store
)
936 '((writes :memory
:partially t
)))
938 '((writes :memory
:partially t
)
940 ((eq load-store
:load
)
945 (:emitter
(emit-format-3-inst segment
,op
,op3 dst src1 src2
946 :load-store
,load-store
948 :dest-kind
(not (eq ',dest-kind
'reg
)))))))
950 (define-f3-shift-inst (name op op3
&key extended
)
951 `(define-instruction ,name
(segment dst src1
&optional src2
)
952 (:declare
(type tn dst
)
953 (type (or tn
(unsigned-byte 6) null
) src1 src2
))
954 (:printer format-3-shift-reg
955 ((op ,op
) (op3 ,op3
) (x ,(if extended
1 0)) (i 0)))
956 (:printer format-3-shift-immed
957 ((op ,op
) (op3 ,op3
) (x ,(if extended
1 0)) (i 1)))
960 (if src2
(reads src2
) (reads dst
))
963 (:emitter
(emit-format-3-shift-inst segment
,op
,op3 dst src1 src2
964 :extended
,extended
)))))
966 (define-f3-inst ldsb
#b11
#b001001
:load-store
:load
)
967 (define-f3-inst ldsh
#b11
#b001010
:load-store
:load
)
968 (define-f3-inst ldub
#b11
#b000001
:load-store
:load
)
969 (define-f3-inst lduh
#b11
#b000010
:load-store
:load
)
971 ;; This instruction is called lduw for V9 , but looks exactly like ld
972 ;; on previous architectures.
973 (define-f3-inst ld
#b11
#b000000
:load-store
:load
974 #!+sparc-v9
:print-name
#!+sparc-v9
'lduw
)
976 (define-f3-inst ldsw
#b11
#b001000
:load-store
:load
) ; v9
978 ;; ldd is deprecated on the Sparc V9.
979 (define-f3-inst ldd
#b11
#b000011
:load-store
:load
)
981 (define-f3-inst ldx
#b11
#b001011
:load-store
:load
) ; v9
983 (define-f3-inst ldf
#b11
#b100000
:dest-kind fp-reg
:load-store
:load
)
984 (define-f3-inst lddf
#b11
#b100011
:dest-kind fp-reg
:load-store
:load
)
985 (define-f3-inst ldqf
#b11
#b100010
:dest-kind fp-reg
:load-store
:load
) ; v9
986 (define-f3-inst stb
#b11
#b000101
:load-store
:store
)
987 (define-f3-inst sth
#b11
#b000110
:load-store
:store
)
988 (define-f3-inst st
#b11
#b000100
:load-store
:store
)
990 ;; std is deprecated on the Sparc V9.
991 (define-f3-inst std
#b11
#b000111
:load-store
:store
)
993 (define-f3-inst stx
#b11
#b001110
:load-store
:store
) ; v9
995 (define-f3-inst stf
#b11
#b100100
:dest-kind fp-reg
:load-store
:store
)
996 (define-f3-inst stdf
#b11
#b100111
:dest-kind fp-reg
:load-store
:store
)
997 (define-f3-inst stqf
#b11
#b100110
:dest-kind fp-reg
:load-store
:store
) ; v9
998 (define-f3-inst ldstub
#b11
#b001101
:load-store t
)
1000 ;; swap is deprecated on the Sparc V9
1001 (define-f3-inst swap
#b11
#b001111
:load-store t
)
1003 (define-f3-inst add
#b10
#b000000
:fixup t
)
1004 (define-f3-inst addcc
#b10
#b010000
:writes
:psr
)
1005 (define-f3-inst addx
#b10
#b001000
:reads
:psr
)
1006 (define-f3-inst addxcc
#b10
#b011000
:reads
:psr
:writes
:psr
)
1007 (define-f3-inst taddcc
#b10
#b100000
:writes
:psr
)
1009 ;; taddcctv is deprecated on the Sparc V9. Use taddcc and bpvs or
1010 ;; taddcc and trap to get a similar effect. (Requires changing the C
1012 ;;(define-f3-inst taddcctv #b10 #b100010 :writes :psr)
1014 (define-f3-inst sub
#b10
#b000100
)
1015 (define-f3-inst subcc
#b10
#b010100
:writes
:psr
)
1016 (define-f3-inst subx
#b10
#b001100
:reads
:psr
)
1017 (define-f3-inst subxcc
#b10
#b011100
:reads
:psr
:writes
:psr
)
1018 (define-f3-inst tsubcc
#b10
#b100001
:writes
:psr
)
1020 ;; tsubcctv is deprecated on the Sparc V9. Use tsubcc and bpvs or
1021 ;; tsubcc and trap to get a similar effect. (Requires changing the C
1023 ;;(define-f3-inst tsubcctv #b10 #b100011 :writes :psr)
1025 (define-f3-inst mulscc
#b10
#b100100
:reads
:y
:writes
(:psr
:y
))
1026 (define-f3-inst and
#b10
#b000001
)
1027 (define-f3-inst andcc
#b10
#b010001
:writes
:psr
)
1028 (define-f3-inst andn
#b10
#b000101
)
1029 (define-f3-inst andncc
#b10
#b010101
:writes
:psr
)
1030 (define-f3-inst or
#b10
#b000010
)
1031 (define-f3-inst orcc
#b10
#b010010
:writes
:psr
)
1032 (define-f3-inst orn
#b10
#b000110
)
1033 (define-f3-inst orncc
#b10
#b010110
:writes
:psr
)
1034 (define-f3-inst xor
#b10
#b000011
)
1035 (define-f3-inst xorcc
#b10
#b010011
:writes
:psr
)
1036 (define-f3-inst xnor
#b10
#b000111
)
1037 (define-f3-inst xnorcc
#b10
#b010111
:writes
:psr
)
1039 (define-f3-shift-inst sll
#b10
#b100101
)
1040 (define-f3-shift-inst srl
#b10
#b100110
)
1041 (define-f3-shift-inst sra
#b10
#b100111
)
1042 (define-f3-shift-inst sllx
#b10
#b100101
:extended t
) ; v9
1043 (define-f3-shift-inst srlx
#b10
#b100110
:extended t
) ; v9
1044 (define-f3-shift-inst srax
#b10
#b100111
:extended t
) ; v9
1046 (define-f3-inst save
#b10
#b111100
:reads
:psr
:writes
:psr
)
1047 (define-f3-inst restore
#b10
#b111101
:reads
:psr
:writes
:psr
)
1049 ;; smul, smulcc, umul, umulcc, sdiv, sdivcc, udiv, and udivcc are
1050 ;; deprecated on the Sparc V9. Use mulx, sdivx, and udivx instead.
1051 (define-f3-inst smul
#b10
#b001011
:writes
:y
) ; v8
1052 (define-f3-inst smulcc
#b10
#b011011
:writes
(:psr
:y
)) ; v8
1053 (define-f3-inst umul
#b10
#b001010
:writes
:y
) ; v8
1054 (define-f3-inst umulcc
#b10
#b011010
:writes
(:psr
:y
)) ; v8
1055 (define-f3-inst sdiv
#b10
#b001111
:reads
:y
) ; v8
1056 (define-f3-inst sdivcc
#b10
#b011111
:reads
:y
:writes
:psr
) ; v8
1057 (define-f3-inst udiv
#b10
#b001110
:reads
:y
) ; v8
1058 (define-f3-inst udivcc
#b10
#b011110
:reads
:y
:writes
:psr
) ; v8
1060 (define-f3-inst mulx
#b10
#b001001
) ; v9 for both signed and unsigned
1061 (define-f3-inst sdivx
#b10
#b101101
) ; v9
1062 (define-f3-inst udivx
#b10
#b001101
) ; v9
1064 (define-f3-inst popc
#b10
#b101110
) ; v9: count one bits
1069 ;;;; Random instructions.
1071 ;; ldfsr is deprecated on the Sparc V9. Use ldxfsr instead
1072 (define-instruction ldfsr
(segment src1 src2
)
1073 (:declare
(type tn src1
) (type (signed-byte 13) src2
))
1074 (:printer format-3-immed
((op #b11
) (op3 #b100001
) (rd 0)))
1077 (:emitter
(emit-format-3-immed segment
#b11
0 #b100001
1078 (reg-tn-encoding src1
) 1 src2
)))
1081 (define-instruction ldxfsr
(segment src1 src2
)
1082 (:declare
(type tn src1
) (type (signed-byte 13) src2
))
1083 (:printer format-3-immed
((op #b11
) (op3 #b100001
) (rd 1))
1084 '(:name
:tab
"[" rs1
(:unless
(:constant
0) "+" immed
) "], %FSR")
1088 (:emitter
(emit-format-3-immed segment
#b11
1 #b100001
1089 (reg-tn-encoding src1
) 1 src2
)))
1091 ;; stfsr is deprecated on the Sparc V9. Use stxfsr instead.
1092 (define-instruction stfsr
(segment src1 src2
)
1093 (:declare
(type tn src1
) (type (signed-byte 13) src2
))
1094 (:printer format-3-immed
((op #b11
) (op3 #b100101
) (rd 0)))
1097 (:emitter
(emit-format-3-immed segment
#b11
0 #b100101
1098 (reg-tn-encoding src1
) 1 src2
)))
1101 (define-instruction stxfsr
(segment src1 src2
)
1102 (:declare
(type tn src1
) (type (signed-byte 13) src2
))
1103 (:printer format-3-immed
((op #b11
) (op3 #b100101
) (rd 1))
1104 '(:name
:tab
"%FSR, [" rs1
"+" (:unless
(:constant
0) "+" immed
) "]")
1108 (:emitter
(emit-format-3-immed segment
#b11
1 #b100101
1109 (reg-tn-encoding src1
) 1 src2
)))
1111 (eval-when (#-sb-xc
:compile-toplevel
:load-toplevel
:execute
)
1112 (defun sethi-arg-printer (value stream dstate
)
1113 (format stream
"%hi(#x~8,'0x)" (ash value
10))
1114 ;; Save the immediate value and the destination register from this
1115 ;; sethi instruction. This is used later to print some possible
1116 ;; notes about the value loaded by sethi.
1117 (let* ((word (sb!disassem
::sap-ref-int
(sb!disassem
::dstate-segment-sap dstate
)
1118 (sb!disassem
::dstate-cur-offs dstate
)
1120 (sb!disassem
::dstate-byte-order dstate
)))
1121 (imm22 (ldb (byte 22 0) word
))
1122 (rd (ldb (byte 5 25) word
)))
1123 (push (cons rd imm22
) *note-sethi-inst
*)))
1127 (define-instruction sethi
(segment dst src1
)
1128 (:declare
(type tn dst
)
1129 (type (or (signed-byte 22) (unsigned-byte 22) fixup
) src1
))
1130 (:printer format-2-immed
1131 ((op2 #b100
) (immed nil
:printer
#'sethi-arg-printer
)))
1132 (:dependencies
(writes dst
))
1137 (emit-format-2-immed segment
#b00
(reg-tn-encoding dst
) #b100
1140 (note-fixup segment
:sethi src1
)
1141 (emit-format-2-immed segment
#b00
(reg-tn-encoding dst
) #b100
0)))))
1143 ;; rdy is deprecated on the Sparc V9. It's not needed with 64-bit
1145 (define-instruction rdy
(segment dst
)
1146 (:declare
(type tn dst
))
1147 (:printer format-3-reg
((op #b10
) (op3 #b101000
) (rs1 0) (immed 0))
1148 '('RD
:tab
'%Y
", " rd
))
1149 (:dependencies
(reads :y
) (writes dst
))
1151 (:emitter
(emit-format-3-reg segment
#b10
(reg-tn-encoding dst
) #b101000
1154 (defconstant-eqx wry-printer
1155 '('WR
:tab rs1
(:unless
(:constant
0) ", " (:choose immed rs2
)) ", " '%Y
)
1158 ;; wry is deprecated on the Sparc V9. It's not needed with 64-bit
1160 (define-instruction wry
(segment src1
&optional src2
)
1161 (:declare
(type tn src1
) (type (or (signed-byte 13) tn null
) src2
))
1162 (:printer format-3-reg
((op #b10
) (op3 #b110000
) (rd 0)) wry-printer
)
1163 (:printer format-3-immed
((op #b10
) (op3 #b110000
) (rd 0)) wry-printer
)
1164 (:dependencies
(reads src1
) (if src2
(reads src2
)) (writes :y
))
1169 (emit-format-3-reg segment
#b10
0 #b110000
(reg-tn-encoding src1
) 0 0 0))
1171 (emit-format-3-reg segment
#b10
0 #b110000
(reg-tn-encoding src1
) 0 0
1172 (reg-tn-encoding src2
)))
1174 (emit-format-3-immed segment
#b10
0 #b110000
(reg-tn-encoding src1
) 1
1177 (defun snarf-error-junk (sap offset
&optional length-only
)
1178 (let* ((length (sb!sys
:sap-ref-8 sap offset
))
1179 (vector (make-array length
:element-type
'(unsigned-byte 8))))
1180 (declare (type sb
!sys
:system-area-pointer sap
)
1181 (type (unsigned-byte 8) length
)
1182 (type (simple-array (unsigned-byte 8) (*)) vector
))
1184 (values 0 (1+ length
) nil nil
))
1186 (sb!kernel
:copy-from-system-area sap
(* n-byte-bits
(1+ offset
))
1187 vector
(* n-word-bits
1189 (* length n-byte-bits
))
1190 (collect ((sc-offsets)
1192 (lengths 1) ; the length byte
1194 (error-number (sb!c
:read-var-integer vector index
)))
1197 (when (>= index length
)
1199 (let ((old-index index
))
1200 (sc-offsets (sb!c
:read-var-integer vector index
))
1201 (lengths (- index old-index
))))
1202 (values error-number
1207 (defun unimp-control (chunk inst stream dstate
)
1208 (declare (ignore inst
))
1209 (flet ((nt (x) (if stream
(sb!disassem
:note x dstate
))))
1210 (case (format-2-unimp-data chunk dstate
)
1213 (sb!disassem
:handle-break-args
#'snarf-error-junk stream dstate
))
1216 (sb!disassem
:handle-break-args
#'snarf-error-junk stream dstate
))
1217 (#.object-not-list-trap
1218 (nt "Object not list trap"))
1220 (nt "Breakpoint trap"))
1221 (#.pending-interrupt-trap
1222 (nt "Pending interrupt trap"))
1225 (#.fun-end-breakpoint-trap
1226 (nt "Function end breakpoint trap"))
1227 (#.object-not-instance-trap
1228 (nt "Object not instance trap"))
1231 (define-instruction unimp
(segment data
)
1232 (:declare
(type (unsigned-byte 22) data
))
1233 (:printer format-2-unimp
() :default
:control
#'unimp-control
1234 :print-name
#!-sparc-v9
'unimp
#!+sparc-v9
'illtrap
)
1236 (:emitter
(emit-format-2-unimp segment
0 0 0 data
)))
1240 ;;;; Branch instructions.
1242 ;; The branch instruction is deprecated on the Sparc V9. Use the
1243 ;; branch with prediction instructions instead.
1244 (defun emit-relative-branch (segment a op2 cond-or-target target
&optional fp
)
1245 (emit-back-patch segment
4
1246 (lambda (segment posn
)
1248 (setf target cond-or-target
)
1249 (setf cond-or-target
:t
))
1250 (emit-format-2-branch
1253 (fp-branch-condition cond-or-target
)
1254 (branch-condition cond-or-target
))
1256 (let ((offset (ash (- (label-position target
) posn
) -
2)))
1257 (when (and (= a
1) (> 0 offset
))
1258 (error "Offset of BA must be positive"))
1261 (defun emit-relative-branch-integer (segment a op2 cond-or-target target
&optional
(cc :icc
) (pred :pt
))
1262 (declare (type integer-condition-register cc
))
1263 (assert (member :sparc-v9
*backend-subfeatures
*))
1264 (emit-back-patch segment
4
1265 (lambda (segment posn
)
1267 (setf target cond-or-target
)
1268 (setf cond-or-target
:t
))
1269 (emit-format-2-branch-pred
1271 (branch-condition cond-or-target
)
1273 (integer-condition cc
)
1274 (branch-prediction pred
)
1275 (let ((offset (ash (- (label-position target
) posn
) -
2)))
1276 (when (and (= a
1) (> 0 offset
))
1277 (error "Offset of BA must be positive"))
1280 (defun emit-relative-branch-fp (segment a op2 cond-or-target target
&optional
(cc :fcc0
) (pred :pt
))
1281 (assert (member :sparc-v9
*backend-subfeatures
*))
1282 (emit-back-patch segment
4
1283 (lambda (segment posn
)
1285 (setf target cond-or-target
)
1286 (setf cond-or-target
:t
))
1287 (emit-format-2-branch-pred
1289 (fp-branch-condition cond-or-target
)
1292 (branch-prediction pred
)
1293 (let ((offset (ash (- (label-position target
) posn
) -
2)))
1294 (when (and (= a
1) (> 0 offset
))
1295 (error "Offset of BA must be positive"))
1298 ;; So that I don't have to go change the syntax of every single use of
1299 ;; branches, I'm keeping the Lisp instruction names the same. They
1300 ;; just get translated to the branch with prediction
1301 ;; instructions. However, the disassembler uses the correct V9
1303 (define-instruction b
(segment cond-or-target
&rest args
)
1304 (:declare
(type (or label branch-condition
) cond-or-target
))
1305 (:printer format-2-branch
((op #b00
) (op2 #b010
)))
1306 (:attributes branch
)
1307 (:dependencies
(reads :psr
))
1311 ((member :sparc-v9
*backend-subfeatures
*)
1312 (destructuring-bind (&optional target pred cc
) args
1313 (declare (type (or label null
) target
))
1314 (emit-relative-branch-integer segment
0 #b001 cond-or-target target
(or cc
:icc
) (or pred
:pt
))))
1316 (destructuring-bind (&optional target
) args
1317 (declare (type (or label null
) target
))
1318 (emit-relative-branch segment
0 #b010 cond-or-target target
))))))
1320 (define-instruction bp
(segment cond-or-target
&optional target pred cc
)
1321 (:declare
(type (or label branch-condition
) cond-or-target
)
1322 (type (or label null
) target
))
1323 (:printer format-2-branch-pred
((op #b00
) (op2 #b001
))
1326 (:attributes branch
)
1327 (:dependencies
(reads :psr
))
1330 (emit-relative-branch-integer segment
0 #b001 cond-or-target target
(or cc
:icc
) (or pred
:pt
))))
1332 (define-instruction ba
(segment cond-or-target
&rest args
)
1333 (:declare
(type (or label branch-condition
) cond-or-target
))
1334 (:printer format-2-branch
((op #b00
) (op2 #b010
) (a 1))
1337 (:attributes branch
)
1338 (:dependencies
(reads :psr
))
1342 ((member :sparc-v9
*backend-subfeatures
*)
1343 (destructuring-bind (&optional target pred cc
) args
1344 (declare (type (or label null
) target
))
1345 (emit-relative-branch-integer segment
1 #b001 cond-or-target target
(or cc
:icc
) (or pred
:pt
))))
1347 (destructuring-bind (&optional target
) args
1348 (declare (type (or label null
) target
))
1349 (emit-relative-branch segment
1 #b010 cond-or-target target
))))))
1351 (define-instruction bpa
(segment cond-or-target
&optional target pred cc
)
1352 (:declare
(type (or label branch-condition
) cond-or-target
)
1353 (type (or label null
) target
))
1354 (:printer format-2-branch
((op #b00
) (op2 #b001
) (a 1))
1357 (:attributes branch
)
1358 (:dependencies
(reads :psr
))
1361 (emit-relative-branch-integer segment
1 #b001 cond-or-target target
(or cc
:icc
) (or pred
:pt
))))
1363 ;; This doesn't cover all of the possible formats for the trap
1364 ;; instruction. We really only want a trap with a immediate trap
1365 ;; value and with RS1 = register 0. Also, the Sparc Compliance
1366 ;; Definition 2.4.1 says only trap numbers 16-31 are allowed for user
1367 ;; code. All other trap numbers have other uses. The restriction on
1368 ;; target will prevent us from using bad trap numbers by mistake.
1370 (define-instruction t
(segment condition target
&optional cc
)
1371 (:declare
(type branch-condition condition
)
1372 ;; KLUDGE: see comments in vm.lisp regarding
1373 ;; pseudo-atomic-trap.
1375 (type (integer 16 31) target
))
1376 (:printer format-3-immed
((op #b10
)
1377 (rd nil
:type
'branch-condition
)
1380 '(:name rd
:tab immed
))
1381 (:attributes branch
)
1382 (:dependencies
(reads :psr
))
1386 ((member :sparc-v9
*backend-subfeatures
*)
1389 (emit-format-4-trap segment
1391 (branch-condition condition
)
1393 (integer-condition cc
)
1397 (emit-format-3-immed segment
#b10
(branch-condition condition
)
1398 #b111010
0 1 target
)))))
1400 ;;; KLUDGE: we leave this commented out, as these two (T and TCC)
1401 ;;; operations are actually indistinguishable from their bitfields,
1402 ;;; breaking the disassembler if these are left in. The printer isn't
1403 ;;; terribly smart, but the emitted code is right. - CSR, 2002-08-04
1405 (define-instruction tcc
(segment condition target
&optional
(cc #!-sparc-64
:icc
#!+sparc-64
:xcc
))
1406 (:declare
(type branch-condition condition
)
1407 ;; KLUDGE: see above.
1409 (type (integer 16 31) target
)
1410 (type integer-condition-register cc
))
1411 (:printer format-4-trap
((op #b10
)
1412 (rd nil
:type
'branch-condition
)
1416 (:attributes branch
)
1417 (:dependencies
(reads :psr
))
1419 (:emitter
(emit-format-4-trap segment
1421 (branch-condition condition
)
1423 (integer-condition cc
)
1426 ;; Same as for the branch instructions. On the Sparc V9, we will use
1427 ;; the FP branch with prediction instructions instead.
1429 (define-instruction fb
(segment condition target
&rest args
)
1430 (:declare
(type fp-branch-condition condition
) (type label target
))
1431 (:printer format-2-branch
((op #B00
)
1432 (cond nil
:type
'branch-fp-condition
)
1434 (:attributes branch
)
1435 (:dependencies
(reads :fsr
))
1439 ((member :sparc-v9
*backend-subfeatures
*)
1440 (destructuring-bind (&optional fcc pred
) args
1441 (emit-relative-branch-fp segment
0 #b101 condition target
(or fcc
:fcc0
) (or pred
:pt
))))
1443 (assert (null args
))
1444 (emit-relative-branch segment
0 #b110 condition target t
)))))
1446 (define-instruction fbp
(segment condition target
&optional fcc pred
)
1447 (:declare
(type fp-branch-condition condition
) (type label target
))
1448 (:printer format-2-fp-branch-pred
((op #b00
) (op2 #b101
))
1449 fp-branch-pred-printer
1451 (:attributes branch
)
1452 (:dependencies
(reads :fsr
))
1455 (emit-relative-branch-fp segment
0 #b101 condition target
(or fcc
:fcc0
) (or pred
:pt
))))
1457 (defconstant-eqx jal-printer
1459 (:choose
(rs1 (:unless
(:constant
0) (:plus-integer immed
)))
1460 (:cond
((rs2 :constant
0) rs1
)
1461 ((rs1 :constant
0) rs2
)
1463 (:unless
(:constant
0) ", " rd
))
1466 (define-instruction jal
(segment dst src1
&optional src2
)
1467 (:declare
(type tn dst
)
1468 (type (or tn integer
) src1
)
1469 (type (or null fixup tn
(signed-byte 13)) src2
))
1470 (:printer format-3-reg
((op #b10
) (op3 #b111000
)) jal-printer
)
1471 (:printer format-3-immed
((op #b10
) (op3 #b111000
)) jal-printer
)
1472 (:attributes branch
)
1473 (:dependencies
(reads src1
) (if src2
(reads src2
) (reads dst
)) (writes dst
))
1481 (emit-format-3-reg segment
#b10
(reg-tn-encoding dst
) #b111000
1484 (reg-tn-encoding src1
))
1485 0 0 (reg-tn-encoding src2
)))
1487 (emit-format-3-immed segment
#b10
(reg-tn-encoding dst
) #b111000
1488 (reg-tn-encoding src1
) 1 src2
))
1490 (note-fixup segment
:add src2
)
1491 (emit-format-3-immed segment
#b10
(reg-tn-encoding dst
)
1492 #b111000
(reg-tn-encoding src1
) 1 0)))))
1494 (define-instruction j
(segment src1
&optional src2
)
1495 (:declare
(type tn src1
) (type (or tn
(signed-byte 13) fixup null
) src2
))
1496 (:printer format-3-reg
((op #b10
) (op3 #b111000
) (rd 0)) jal-printer
)
1497 (:printer format-3-immed
((op #b10
) (op3 #b111000
) (rd 0)) jal-printer
)
1498 (:attributes branch
)
1499 (:dependencies
(reads src1
) (if src2
(reads src2
)))
1504 (emit-format-3-reg segment
#b10
0 #b111000
(reg-tn-encoding src1
) 0 0 0))
1506 (emit-format-3-reg segment
#b10
0 #b111000
(reg-tn-encoding src1
) 0 0
1507 (reg-tn-encoding src2
)))
1509 (emit-format-3-immed segment
#b10
0 #b111000
(reg-tn-encoding src1
) 1
1512 (note-fixup segment
:add src2
)
1513 (emit-format-3-immed segment
#b10
0 #b111000
(reg-tn-encoding src1
) 1
1518 ;;;; Unary and binary fp insts.
1520 (macrolet ((define-unary-fp-inst (name opf
&key reads extended
)
1521 `(define-instruction ,name
(segment dst src
)
1522 (:declare
(type tn dst src
))
1523 (:printer format-unary-fpop
1524 ((op #b10
) (op3 #b110100
) (opf ,opf
)
1526 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1527 (rd nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))))
1535 (:emitter
(emit-format-3-fpop segment
#b10
(fp-reg-tn-encoding dst
)
1536 #b110100
0 ,opf
(fp-reg-tn-encoding src
)))))
1538 (define-binary-fp-inst (name opf
&key
(op3 #b110100
)
1539 reads writes delay extended
)
1540 `(define-instruction ,name
(segment dst src1 src2
)
1541 (:declare
(type tn dst src1 src2
))
1542 (:printer format-binary-fpop
1543 ((op #b10
) (op3 ,op3
) (opf ,opf
)
1544 (rs1 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1545 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1546 (rd nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1554 `((writes ,writes
)))
1559 (:emitter
(emit-format-3-fpop segment
#b10
(fp-reg-tn-encoding dst
)
1560 ,op3
(fp-reg-tn-encoding src1
) ,opf
1561 (fp-reg-tn-encoding src2
)))))
1563 (define-cmp-fp-inst (name opf
&key extended
)
1567 `(define-instruction ,name
(segment src1 src2
&optional
(fcc :fcc0
))
1568 (:declare
(type tn src1 src2
)
1569 (type (member :fcc0
:fcc1
:fcc2
:fcc3
) fcc
))
1570 (:printer format-fpop2
1577 (rs1 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1578 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
1582 (rd nil
:type
'fp-condition-register
))
1588 ;; The Sparc V9 doesn't need a delay after a FP compare.
1590 ;; KLUDGE FIXME YAARGH -- how to express that? I guess for now we
1591 ;; do the worst case, and hope to fix it.
1592 ;; (:delay #-sparc-v9 1 #+sparc-v9 0)
1595 (emit-format-3-fpop2 segment
#b10
1596 (or (position fcc
'(:fcc0
:fcc1
:fcc2
:fcc3
))
1599 (fp-reg-tn-encoding src1
)
1600 ,opf0
,opf1
,opf2
,opf
1601 (fp-reg-tn-encoding src2
)))))))
1603 (define-unary-fp-inst fitos
#b011000100
:reads
:fsr
)
1604 (define-unary-fp-inst fitod
#b011001000
:reads
:fsr
:extended t
)
1605 (define-unary-fp-inst fitoq
#b011001100
:reads
:fsr
:extended t
) ; v8
1607 (define-unary-fp-inst fxtos
#b010000100
:reads
:fsr
) ; v9
1608 (define-unary-fp-inst fxtod
#b010001000
:reads
:fsr
:extended t
) ; v9
1609 (define-unary-fp-inst fxtoq
#b010001100
:reads
:fsr
:extended t
) ; v9
1612 ;; I (Raymond Toy) don't think these f{sd}toir instructions exist on
1613 ;; any Ultrasparc, but I only have a V9 manual. The code in
1614 ;; float.lisp seems to indicate that they only existed on non-sun4
1615 ;; machines (sun3 68K machines?).
1616 (define-unary-fp-inst fstoir
#b011000001
:reads
:fsr
)
1617 (define-unary-fp-inst fdtoir
#b011000010
:reads
:fsr
)
1619 (define-unary-fp-inst fstoi
#b011010001
)
1620 (define-unary-fp-inst fdtoi
#b011010010
:extended t
)
1621 (define-unary-fp-inst fqtoi
#b011010011
:extended t
) ; v8
1623 (define-unary-fp-inst fstox
#b010000001
) ; v9
1624 (define-unary-fp-inst fdtox
#b010000010
:extended t
) ; v9
1625 (define-unary-fp-inst fqtox
#b010000011
:extended t
) ; v9
1627 (define-unary-fp-inst fstod
#b011001001
:reads
:fsr
)
1628 (define-unary-fp-inst fstoq
#b011001101
:reads
:fsr
) ; v8
1629 (define-unary-fp-inst fdtos
#b011000110
:reads
:fsr
)
1630 (define-unary-fp-inst fdtoq
#b011001110
:reads
:fsr
) ; v8
1631 (define-unary-fp-inst fqtos
#b011000111
:reads
:fsr
) ; v8
1632 (define-unary-fp-inst fqtod
#b011001011
:reads
:fsr
) ; v8
1634 (define-unary-fp-inst fmovs
#b000000001
)
1635 (define-unary-fp-inst fmovd
#b000000010
:extended t
) ; v9
1636 (define-unary-fp-inst fmovq
#b000000011
:extended t
) ; v9
1638 (define-unary-fp-inst fnegs
#b000000101
)
1639 (define-unary-fp-inst fnegd
#b000000110
:extended t
) ; v9
1640 (define-unary-fp-inst fnegq
#b000000111
:extended t
) ; v9
1642 (define-unary-fp-inst fabss
#b000001001
)
1643 (define-unary-fp-inst fabsd
#b000001010
:extended t
) ; v9
1644 (define-unary-fp-inst fabsq
#b000001011
:extended t
) ; v9
1646 (define-unary-fp-inst fsqrts
#b000101001
:reads
:fsr
) ; V7
1647 (define-unary-fp-inst fsqrtd
#b000101010
:reads
:fsr
:extended t
) ; V7
1648 (define-unary-fp-inst fsqrtq
#b000101011
:reads
:fsr
:extended t
) ; v8
1650 (define-binary-fp-inst fadds
#b001000001
)
1651 (define-binary-fp-inst faddd
#b001000010
:extended t
)
1652 (define-binary-fp-inst faddq
#b001000011
:extended t
) ; v8
1653 (define-binary-fp-inst fsubs
#b001000101
)
1654 (define-binary-fp-inst fsubd
#b001000110
:extended t
)
1655 (define-binary-fp-inst fsubq
#b001000111
:extended t
) ; v8
1657 (define-binary-fp-inst fmuls
#b001001001
)
1658 (define-binary-fp-inst fmuld
#b001001010
:extended t
)
1659 (define-binary-fp-inst fmulq
#b001001011
:extended t
) ; v8
1660 (define-binary-fp-inst fdivs
#b001001101
)
1661 (define-binary-fp-inst fdivd
#b001001110
:extended t
)
1662 (define-binary-fp-inst fdivq
#b001001111
:extended t
) ; v8
1664 ;;; Float comparison instructions.
1666 (define-cmp-fp-inst fcmps
#b0001
)
1667 (define-cmp-fp-inst fcmpd
#b0010
:extended t
)
1668 (define-cmp-fp-inst fcmpq
#b0011
:extended t
) ;v8
1669 (define-cmp-fp-inst fcmpes
#b0101
)
1670 (define-cmp-fp-inst fcmped
#b0110
:extended t
)
1671 (define-cmp-fp-inst fcmpeq
#b0111
:extended t
) ; v8
1675 ;;;; li, jali, ji, nop, cmp, not, neg, move, and more
1677 (defun %li
(reg value
)
1680 (inst add reg zero-tn value
))
1681 ((or (signed-byte 32) (unsigned-byte 32))
1682 (let ((hi (ldb (byte 22 10) value
))
1683 (lo (ldb (byte 10 0) value
)))
1686 (inst add reg lo
))))
1688 (inst sethi reg value
)
1689 (inst add reg value
))))
1691 (define-instruction-macro li
(reg value
)
1694 ;;; Jal to a full 32-bit address. Tmpreg is trashed.
1695 (define-instruction jali
(segment link tmpreg value
)
1696 (:declare
(type tn link tmpreg
)
1697 (type (or (signed-byte 13) (signed-byte 32) (unsigned-byte 32)
1699 (:attributes variable-length
)
1701 (:attributes branch
)
1702 (:dependencies
(writes link
) (writes tmpreg
))
1705 (assemble (segment vop
)
1708 (inst jal link zero-tn value
))
1709 ((or (signed-byte 32) (unsigned-byte 32))
1710 (let ((hi (ldb (byte 22 10) value
))
1711 (lo (ldb (byte 10 0) value
)))
1712 (inst sethi tmpreg hi
)
1713 (inst jal link tmpreg lo
)))
1715 (inst sethi tmpreg value
)
1716 (inst jal link tmpreg value
))))))
1718 ;;; Jump to a full 32-bit address. Tmpreg is trashed.
1719 (define-instruction ji
(segment tmpreg value
)
1720 (:declare
(type tn tmpreg
)
1721 (type (or (signed-byte 13) (signed-byte 32) (unsigned-byte 32)
1723 (:attributes variable-length
)
1725 (:attributes branch
)
1726 (:dependencies
(writes tmpreg
))
1729 (assemble (segment vop
)
1730 (inst jali zero-tn tmpreg value
))))
1732 (define-instruction nop
(segment)
1733 (:printer format-2-immed
((rd 0) (op2 #b100
) (immed 0)) '(:name
))
1734 (:attributes flushable
)
1736 (:emitter
(emit-format-2-immed segment
0 0 #b100
0)))
1738 (!def-vm-support-routine emit-nop
(segment)
1739 (emit-format-2-immed segment
0 0 #b100
0))
1741 (define-instruction cmp
(segment src1
&optional src2
)
1742 (:declare
(type tn src1
) (type (or null tn
(signed-byte 13)) src2
))
1743 (:printer format-3-reg
((op #b10
) (op3 #b010100
) (rd 0))
1744 '(:name
:tab rs1
", " rs2
))
1745 (:printer format-3-immed
((op #b10
) (op3 #b010100
) (rd 0))
1746 '(:name
:tab rs1
", " immed
))
1747 (:dependencies
(reads src1
) (if src2
(reads src2
)) (writes :psr
))
1752 (emit-format-3-reg segment
#b10
0 #b010100
(reg-tn-encoding src1
) 0 0 0))
1754 (emit-format-3-reg segment
#b10
0 #b010100
(reg-tn-encoding src1
) 0 0
1755 (reg-tn-encoding src2
)))
1757 (emit-format-3-immed segment
#b10
0 #b010100
(reg-tn-encoding src1
) 1
1760 (define-instruction not
(segment dst
&optional src1
)
1761 (:declare
(type tn dst
) (type (or tn null
) src1
))
1762 (:printer format-3-reg
((op #b10
) (op3 #b000111
) (rs2 0))
1763 '(:name
:tab
(:unless
(:same-as rd
) rs1
", " ) rd
))
1764 (:dependencies
(if src1
(reads src1
) (reads dst
)) (writes dst
))
1769 (emit-format-3-reg segment
#b10
(reg-tn-encoding dst
) #b000111
1770 (reg-tn-encoding src1
) 0 0 0)))
1772 (define-instruction neg
(segment dst
&optional src1
)
1773 (:declare
(type tn dst
) (type (or tn null
) src1
))
1774 (:printer format-3-reg
((op #b10
) (op3 #b000100
) (rs1 0))
1775 '(:name
:tab
(:unless
(:same-as rd
) rs2
", " ) rd
))
1776 (:dependencies
(if src1
(reads src1
) (reads dst
)) (writes dst
))
1781 (emit-format-3-reg segment
#b10
(reg-tn-encoding dst
) #b000100
1782 0 0 0 (reg-tn-encoding src1
))))
1784 (define-instruction move
(segment dst src1
)
1785 (:declare
(type tn dst src1
))
1786 (:printer format-3-reg
((op #b10
) (op3 #b000010
) (rs1 0))
1787 '(:name
:tab rs2
", " rd
)
1789 (:attributes flushable
)
1790 (:dependencies
(reads src1
) (writes dst
))
1792 (:emitter
(emit-format-3-reg segment
#b10
(reg-tn-encoding dst
) #b000010
1793 0 0 0 (reg-tn-encoding src1
))))
1797 ;;;; Instructions for dumping data and header objects.
1799 (define-instruction word
(segment word
)
1800 (:declare
(type (or (unsigned-byte 32) (signed-byte 32)) word
))
1804 (emit-word segment word
)))
1806 (define-instruction short
(segment short
)
1807 (:declare
(type (or (unsigned-byte 16) (signed-byte 16)) short
))
1811 (emit-short segment short
)))
1813 (define-instruction byte
(segment byte
)
1814 (:declare
(type (or (unsigned-byte 8) (signed-byte 8)) byte
))
1818 (emit-byte segment byte
)))
1820 (define-bitfield-emitter emit-header-object
32
1821 (byte 24 8) (byte 8 0))
1823 (defun emit-header-data (segment type
)
1826 (lambda (segment posn
)
1829 (ash (+ posn
(component-header-length))
1830 (- n-widetag-bits word-shift
)))))))
1832 (define-instruction simple-fun-header-word
(segment)
1836 (emit-header-data segment simple-fun-header-widetag
)))
1838 (define-instruction lra-header-word
(segment)
1842 (emit-header-data segment return-pc-header-widetag
)))
1845 ;;;; Instructions for converting between code objects, functions, and lras.
1847 (defun emit-compute-inst (segment vop dst src label temp calc
)
1849 ;; We emit either 12 or 4 bytes, so we maintain 8 byte alignments.
1851 (lambda (segment posn delta-if-after
)
1852 (let ((delta (funcall calc label posn delta-if-after
)))
1853 (when (<= (- (ash 1 12)) delta
(1- (ash 1 12)))
1854 (emit-back-patch segment
4
1855 (lambda (segment posn
)
1856 (assemble (segment vop
)
1858 (funcall calc label posn
0)))))
1860 (lambda (segment posn
)
1861 (let ((delta (funcall calc label posn
0)))
1862 (assemble (segment vop
)
1863 (inst sethi temp
(ldb (byte 22 10) delta
))
1864 (inst or temp
(ldb (byte 10 0) delta
))
1865 (inst add dst src temp
))))))
1867 ;; code = fn - fn-ptr-type - header - label-offset + other-pointer-tag
1868 (define-instruction compute-code-from-fn
(segment dst src label temp
)
1869 (:declare
(type tn dst src temp
) (type label label
))
1870 (:attributes variable-length
)
1871 (:dependencies
(reads src
) (writes dst
) (writes temp
))
1875 (emit-compute-inst segment vop dst src label temp
1876 (lambda (label posn delta-if-after
)
1877 (- other-pointer-lowtag
1879 (label-position label posn delta-if-after
)
1880 (component-header-length))))))
1882 ;; code = lra - other-pointer-tag - header - label-offset + other-pointer-tag
1883 (define-instruction compute-code-from-lra
(segment dst src label temp
)
1884 (:declare
(type tn dst src temp
) (type label label
))
1885 (:attributes variable-length
)
1886 (:dependencies
(reads src
) (writes dst
) (writes temp
))
1890 (emit-compute-inst segment vop dst src label temp
1891 (lambda (label posn delta-if-after
)
1892 (- (+ (label-position label posn delta-if-after
)
1893 (component-header-length)))))))
1895 ;; lra = code + other-pointer-tag + header + label-offset - other-pointer-tag
1896 (define-instruction compute-lra-from-code
(segment dst src label temp
)
1897 (:declare
(type tn dst src temp
) (type label label
))
1898 (:attributes variable-length
)
1899 (:dependencies
(reads src
) (writes dst
) (writes temp
))
1903 (emit-compute-inst segment vop dst src label temp
1904 (lambda (label posn delta-if-after
)
1905 (+ (label-position label posn delta-if-after
)
1906 (component-header-length))))))
1908 ;;; Sparc V9 additions
1912 ;; Conditional move integer on condition code
1913 (define-instruction cmove
(segment condition dst src
&optional
(ccreg :icc
))
1914 (:declare
(type (or branch-condition fp-branch-condition
) condition
)
1915 (type cond-move-condition-register ccreg
)
1917 (type (or (signed-byte 13) tn
) src
))
1918 (:printer format-4-cond-move
1923 (cc nil
:type
'integer-condition-register
))
1926 (:printer format-4-cond-move-immed
1931 (cc nil
:type
'integer-condition-register
))
1934 (:printer format-4-cond-move
1938 (cond nil
:type
'branch-fp-condition
)
1940 (cc nil
:type
'fp-condition-register
))
1943 (:printer format-4-cond-move-immed
1947 (cond nil
:type
'branch-fp-condition
)
1949 (cc nil
:type
'fp-condition-register
))
1954 (if (member ccreg
'(:icc
:xcc
))
1963 (multiple-value-bind (cc2 cc01
)
1964 (cond-move-condition-parts ccreg
)
1967 (emit-format-4-cond-move segment
1969 (reg-tn-encoding dst
)
1972 (if (member ccreg
'(:icc
:xcc
))
1973 (branch-condition condition
)
1974 (fp-branch-condition condition
))
1977 (reg-tn-encoding src
)))
1979 (emit-format-4-cond-move segment
1981 (reg-tn-encoding dst
)
1984 (if (member ccreg
'(:icc
:xcc
))
1985 (branch-condition condition
)
1986 (fp-branch-condition condition
))
1991 ;; Conditional move floating-point on condition codes
1992 (macrolet ((define-cond-fp-move (name print-name op op3 opf_low
&key extended
)
1993 `(define-instruction ,name
(segment condition dst src
&optional
(ccreg :fcc0
))
1994 (:declare
(type (or branch-condition fp-branch-condition
) condition
)
1995 (type cond-move-condition-register ccreg
)
1997 (:printer format-fpop2
2001 (opf1 nil
:type
'fp-condition-register-shifted
)
2004 (rs1 nil
:type
'branch-fp-condition
)
2005 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
2006 (rd nil
:type
',(if extended
'fp-ext-reg
'fp-reg
)))
2007 cond-fp-move-printer
2008 :print-name
',print-name
)
2009 (:printer format-fpop2
2013 (opf1 nil
:type
'integer-condition-register
)
2015 (rs1 nil
:type
'branch-condition
)
2017 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
2018 (rd nil
:type
',(if extended
'fp-ext-reg
'fp-reg
)))
2019 cond-fp-move-printer
2020 :print-name
',print-name
)
2023 (if (member ccreg
'(:icc
:xcc
))
2030 (multiple-value-bind (opf_cc2 opf_cc01
)
2031 (cond-move-condition-parts ccreg
)
2032 (emit-format-3-fpop2 segment
2034 (fp-reg-tn-encoding dst
)
2036 (if (member ccreg
'(:icc
:xcc
))
2037 (branch-condition condition
)
2038 (fp-branch-condition condition
))
2043 (fp-reg-tn-encoding src
)))))))
2044 (define-cond-fp-move cfmovs fmovs
#b10
#b110101
#b0001
)
2045 (define-cond-fp-move cfmovd fmovd
#b10
#b110101
#b0010
:extended t
)
2046 (define-cond-fp-move cfmovq fmovq
#b10
#b110101
#b0011
:extended t
))
2049 ;; Move on integer register condition
2051 ;; movr dst src reg reg-cond
2053 ;; This means if reg satisfies reg-cond, src is copied to dst. If the
2054 ;; condition is not satisfied, nothing is done.
2056 (define-instruction movr
(segment dst src2 src1 reg-condition
)
2057 (:declare
(type cond-move-integer-condition reg-condition
)
2059 (type (or (signed-byte 10) tn
) src2
))
2060 (:printer format-4-cond-move-integer
2064 (:printer format-4-cond-move-integer-immed
2078 (emit-format-4-cond-move-integer
2079 segment
#b10
(reg-tn-encoding dst
) #b101111
(reg-tn-encoding src1
)
2080 0 (register-condition reg-condition
)
2081 0 (reg-tn-encoding src2
)))
2083 (emit-format-4-cond-move-integer-immed
2084 segment
#b10
(reg-tn-encoding dst
) #b101111
(reg-tn-encoding src1
)
2085 1 (register-condition reg-condition
) src2
)))))
2088 ;; Same as MOVR, except we move FP registers depending on the value of
2089 ;; an integer register.
2091 ;; fmovr dst src reg cond
2093 ;; This means if REG satifies COND, SRC is COPIED to DST. Nothing
2094 ;; happens if the condition is not satisfied.
2095 (macrolet ((define-cond-fp-move-integer (name opf_low
&key extended
)
2096 `(define-instruction ,name
(segment dst src2 src1 reg-condition
)
2097 (:declare
(type cond-move-integer-condition reg-condition
)
2098 (type tn dst src1 src2
))
2099 (:printer format-fpop2
2101 (rd nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
2103 (rs1 nil
:type
'reg
)
2105 (opf1 nil
:type
'register-condition
)
2108 (rs2 nil
:type
',(if extended
'fp-ext-reg
'fp-reg
))
2110 cond-fp-move-integer-printer
)
2118 (emit-format-3-fpop2
2121 (fp-reg-tn-encoding dst
)
2123 (reg-tn-encoding src1
)
2125 (register-condition reg-condition
)
2128 (fp-reg-tn-encoding src2
))))))
2129 (define-cond-fp-move-integer fmovrs
#b0101
)
2130 (define-cond-fp-move-integer fmovrd
#b0110
:extended t
)
2131 (define-cond-fp-move-integer fmovrq
#b0111
:extended t
))