Remove !begin-instruction-definitions.
[sbcl.git] / src / compiler / arm / insts.lisp
blob937d6a4a51505c0c19326fe01ddc21ddbb9643fa
1 ;;;; that part of the description of the ARM instruction set (for
2 ;;;; ARMv5) which can live on the cross-compilation host
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB!ARM-ASM")
15 (eval-when (:compile-toplevel :load-toplevel :execute)
16 ;; Imports from this package into SB-VM
17 (import '(*condition-name-vec* conditional-opcode emit-word
18 composite-immediate-instruction encodable-immediate
19 lsl lsr asr ror cpsr @) 'sb!vm)
20 ;; Imports from SB-VM into this package
21 (import '(sb!vm::nil-value sb!vm::registers sb!vm::null-tn sb!vm::null-offset
22 sb!vm::pc-tn sb!vm::pc-offset sb!vm::code-offset)))
24 (setf *disassem-inst-alignment-bytes* 4)
27 (defparameter *conditions*
28 '((:eq . 0)
29 (:ne . 1)
30 (:cs . 2) (:hs . 2)
31 (:cc . 3) (:lo . 3)
32 (:mi . 4)
33 (:pl . 5)
34 (:vs . 6)
35 (:vc . 7)
36 (:hi . 8)
37 (:ls . 9)
38 (:ge . 10)
39 (:lt . 11)
40 (:gt . 12)
41 (:le . 13)
42 (:al . 14)))
43 (defparameter *condition-name-vec*
44 (let ((vec (make-array 16 :initial-element nil)))
45 (dolist (cond *conditions*)
46 (when (null (aref vec (cdr cond)))
47 (setf (aref vec (cdr cond)) (car cond))))
48 vec))
50 ;;; Set assembler parameters. (In CMU CL, this was done with
51 ;;; a call to a macro DEF-ASSEMBLER-PARAMS.)
52 (eval-when (:compile-toplevel :load-toplevel :execute)
53 (setf sb!assem:*assem-scheduler-p* nil))
55 (defun conditional-opcode (condition)
56 (cdr (assoc condition *conditions* :test #'eq)))
58 ;;;; disassembler field definitions
60 (defun maybe-add-notes (dstate)
61 (let* ((inst (sap-ref-int (dstate-segment-sap dstate)
62 (dstate-cur-offs dstate) n-word-bytes
63 (dstate-byte-order dstate)))
64 (op (ldb (byte 8 20) inst))
65 (offset (ldb (byte 12 0) inst))
66 (rn (ldb (byte 4 16) inst)))
67 (cond ((and (= rn null-offset))
68 (let ((offset (+ nil-value offset)))
69 (case op
70 ((88 89) ;; LDR/STR
71 (maybe-note-assembler-routine offset nil dstate)
72 (maybe-note-static-symbol
73 (logior offset other-pointer-lowtag) dstate))
74 (40 ;; ADD
75 (maybe-note-static-symbol offset dstate)))))
77 (case op
78 (89 ;; LDR
79 (case rn
80 (#.code-offset
81 (note-code-constant offset dstate))
82 (#.pc-offset
83 (let ((value (sap-ref-int (dstate-segment-sap dstate)
84 (+ (dstate-cur-offs dstate) offset 8)
85 n-word-bytes
86 (dstate-byte-order dstate))))
87 (maybe-note-assembler-routine value nil dstate))))))))))
89 (eval-when (:compile-toplevel :load-toplevel :execute)
90 ;; DEFINE-ARG-TYPE requires that any :PRINTER be defined at
91 ;; compile-time... Why?
93 (defun print-condition (value stream dstate)
94 (declare (type stream stream)
95 (fixnum value)
96 (ignore dstate))
97 (unless (= value 14) ;; Don't print :al
98 (princ (aref *condition-name-vec* value) stream)))
100 (defun print-reg (value stream dstate)
101 (declare (type stream stream)
102 (fixnum value)
103 (ignore dstate))
104 (princ (aref sb!vm::*register-names* value) stream))
106 (defun print-float-reg (value stream dstate)
107 (declare (type stream stream)
108 (list value)
109 (ignore dstate))
110 (destructuring-bind (double high low) value
111 (format stream "~[S~;D~]~a"
112 double
113 (if (= double 1)
114 high
115 (logior (ash high 1) low)))))
117 (defun print-float-sys-reg (value stream dstate)
118 (declare (type stream stream)
119 (fixnum value)
120 (ignore dstate))
121 (princ (ecase value
122 (#b0000 "FPSID")
123 (#b0001 "FPSCR")
124 (#b1000 "FPEXC")) stream))
126 (defun print-shift-type (value stream dstate)
127 (declare (type stream stream)
128 (fixnum value)
129 (ignore dstate))
130 (princ (aref #(lsl lsr asr ror) value) stream))
132 (defun print-immediate-shift (value stream dstate)
133 (declare (type stream stream)
134 (type (cons fixnum (cons fixnum null)) value)
135 (ignore dstate))
136 (destructuring-bind (amount shift) value
137 (cond
138 ((and (zerop amount)
139 (zerop shift))) ;; No shift
140 ((and (zerop amount)
141 (= shift 3))
142 (princ ", RRX" stream))
144 (princ ", " stream)
145 (princ (aref #(lsl lsr asr ror) shift) stream)
146 (princ " #" stream)
147 (princ amount stream)))))
149 (defun print-shifter-immediate (value stream dstate)
150 (declare (type stream stream)
151 (fixnum value))
152 (maybe-add-notes dstate)
153 (let* ((rotate (ldb (byte 4 8) value))
154 (immediate (mask-field (byte 8 0) value))
155 (left (mask-field (byte 32 0)
156 (ash immediate (- 32 rotate rotate))))
157 (right (ash immediate (- 0 rotate rotate))))
158 (princ (logior left right) stream)))
160 (defun use-label-relative-label (value dstate)
161 (declare (type (signed-byte 24) value)
162 (type disassem-state dstate))
163 (+ 8 (ash value 2) (dstate-cur-addr dstate)))
165 (defun print-load/store-immediate (value stream dstate)
166 (declare (type stream stream)
167 (type (cons bit (cons bit (cons bit (cons fixnum null)))) value))
168 (maybe-add-notes dstate)
169 (destructuring-bind (p u w offset) value
170 (if (zerop offset)
171 (princ "]" stream)
172 (progn
173 (princ (if (zerop p) "], #" ", #") stream)
174 (when (zerop u)
175 (princ "-" stream))
176 (princ offset stream)
177 (unless (zerop p)
178 (princ (if (zerop w) "]" "]!") stream))))))
180 (defun print-load/store-register (value stream dstate)
181 (destructuring-bind (p u w shift-imm shift rm) value
182 (when (zerop p)
183 (princ "]" stream))
184 (princ (if (zerop u) ", -" ", ") stream)
185 (print-reg rm stream dstate)
186 (print-immediate-shift (list shift-imm shift) stream dstate)
187 (unless (zerop p)
188 (princ (if (zerop w) "]" "]!") stream))))
190 (defun print-msr-field-mask (value stream dstate)
191 (declare (type stream stream)
192 (type (cons bit (cons (unsigned-byte 4) null)) value)
193 (ignore dstate))
194 (destructuring-bind (spsr-p field-mask) value
195 (if (zerop spsr-p)
196 (princ "CPSR_" stream)
197 (princ "SPSR_" stream))
198 (when (logbitp 0 field-mask) (princ "c" stream))
199 (when (logbitp 1 field-mask) (princ "x" stream))
200 (when (logbitp 2 field-mask) (princ "s" stream))
201 (when (logbitp 3 field-mask) (princ "f" stream))))
202 ) ; EVAL-WHEN
204 (define-arg-type condition-code :printer #'print-condition)
206 (define-arg-type reg :printer #'print-reg)
208 (define-arg-type float-reg :printer #'print-float-reg)
210 (define-arg-type float-sys-reg :printer #'print-float-sys-reg)
212 (define-arg-type shift-type :printer #'print-shift-type)
214 (define-arg-type immediate-shift :printer #'print-immediate-shift)
216 (define-arg-type shifter-immediate :printer #'print-shifter-immediate)
218 (define-arg-type relative-label
219 :sign-extend t
220 :use-label #'use-label-relative-label)
222 (define-arg-type load/store-immediate :printer #'print-load/store-immediate)
224 (define-arg-type load/store-register :printer #'print-load/store-register)
226 (define-arg-type msr-field-mask :printer #'print-msr-field-mask)
228 ;;;; disassembler instruction format definitions
230 (define-instruction-format (dp-shift-immediate 32
231 :default-printer
232 '(:name cond :tab rd ", " rn ", " rm shift))
233 (cond :field (byte 4 28) :type 'condition-code)
234 (opcode-8 :field (byte 8 20))
235 (rn :field (byte 4 16) :type 'reg)
236 (rd :field (byte 4 12) :type 'reg)
237 (shift :fields (list (byte 5 7) (byte 2 5)) :type 'immediate-shift)
238 (register-shift-p :field (byte 1 4) :value 0)
239 (rm :field (byte 4 0) :type 'reg))
241 (define-instruction-format
242 (dp-shift-register 32
243 :default-printer
244 '(:name cond :tab rd ", " rn ", " rm ", " shift-type " " rs))
245 (cond :field (byte 4 28) :type 'condition-code)
246 (opcode-8 :field (byte 8 20))
247 (rn :field (byte 4 16) :type 'reg)
248 (rd :field (byte 4 12) :type 'reg)
249 (rs :field (byte 4 8) :type 'reg)
250 (multiply-p :field (byte 1 7) :value 0)
251 (shift-type :field (byte 2 5) :type 'shift-type)
252 (register-shift-p :field (byte 1 4) :value 1)
253 (rm :field (byte 4 0) :type 'reg))
255 (define-instruction-format (dp-immediate 32
256 :default-printer
257 '(:name cond :tab rd ", " rn ", #" immediate))
258 (cond :field (byte 4 28) :type 'condition-code)
259 (opcode-8 :field (byte 8 20))
260 (rn :field (byte 4 16) :type 'reg)
261 (rd :field (byte 4 12) :type 'reg)
262 (immediate :field (byte 12 0) :type 'shifter-immediate))
264 (define-instruction-format (branch 32 :default-printer '(:name cond :tab target))
265 (cond :field (byte 4 28) :type 'condition-code)
266 (opcode-4 :field (byte 4 24))
267 (target :field (byte 24 0) :type 'relative-label))
269 (define-instruction-format
270 (load/store-immediate 32
271 ;; FIXME: cond should come between LDR/STR and B.
272 :default-printer '(:name cond :tab rd ", [" rn load/store-offset))
273 (cond :field (byte 4 28) :type 'condition-code)
274 (opcode-3 :field (byte 3 25))
275 (load/store-offset :fields (list (byte 1 24)
276 (byte 1 23)
277 (byte 1 21)
278 (byte 12 0))
279 :type 'load/store-immediate)
280 (opcode-b :field (byte 1 22))
281 (opcode-l :field (byte 1 20))
282 (rn :field (byte 4 16) :type 'reg)
283 (rd :field (byte 4 12) :type 'reg))
285 (define-instruction-format
286 (load/store-register 32
287 ;; FIXME: cond should come between LDR/STR and B.
288 :default-printer '(:name cond :tab rd ", [" rn load/store-offset))
289 (cond :field (byte 4 28) :type 'condition-code)
290 (opcode-3 :field (byte 3 25))
291 (load/store-offset :fields (list (byte 1 24)
292 (byte 1 23)
293 (byte 1 21)
294 (byte 5 7) ;; shift_imm
295 (byte 2 5) ;; shift
296 (byte 4 0)) ;; Rm
297 :type 'load/store-register)
298 (opcode-b :field (byte 1 22))
299 (opcode-l :field (byte 1 20))
300 (opcode-0 :field (byte 1 4))
301 (rn :field (byte 4 16) :type 'reg)
302 (rd :field (byte 4 12) :type 'reg))
304 (define-instruction-format (swi 32
305 :default-printer '(:name cond :tab "#" swi-number))
306 (cond :field (byte 4 28) :type 'condition-code)
307 (opcode-4 :field (byte 4 24))
308 (swi-number :field (byte 24 0)))
310 (define-instruction-format (debug-trap 32 :default-printer '(:name :tab code))
311 (opcode-32 :field (byte 32 0))
312 ;; We use a prefilter in order to read trap codes in order to avoid
313 ;; encoding the code within the instruction body (requiring the use of
314 ;; a different trap instruction and a SIGILL handler) and in order to
315 ;; avoid attempting to include the code in the decoded instruction
316 ;; proper (requiring moving to a 40-bit instruction for disassembling
317 ;; trap codes, and being affected by endianness issues).
318 (code :prefilter (lambda (dstate) (read-suffix 8 dstate))
319 :reader debug-trap-code))
321 (define-instruction-format (msr-immediate 32
322 :default-printer
323 '(:name cond :tab field-mask ", #" immediate))
324 (cond :field (byte 4 28) :type 'condition-code)
325 (opcode-5 :field (byte 5 23) :value #b00110)
326 (field-mask :fields (list (byte 1 22) (byte 4 16)) :type 'msr-field-mask)
327 (opcode-2 :field (byte 2 20) :value #b10)
328 (sbo :field (byte 4 12) :value #b1111)
329 (immediate :field (byte 12 0) :type 'shifter-immediate))
331 (define-instruction-format (msr-register 32
332 :default-printer '(:name cond :tab field-mask ", " rm))
333 (cond :field (byte 4 28) :type 'condition-code)
334 (opcode-5 :field (byte 5 23) :value #b00010)
335 (field-mask :fields (list (byte 1 22) (byte 4 16)) :type 'msr-field-mask)
336 (opcode-2 :field (byte 2 20) :value #b10)
337 (sbo :field (byte 4 12) :value #b1111)
338 (sbz :field (byte 8 4) :value #b00000000)
339 (rm :field (byte 4 0) :type 'reg))
341 (define-instruction-format (multiply-dzsm 32
342 :default-printer '(:name cond :tab rd ", " rs ", " rm))
343 (cond :field (byte 4 28) :type 'condition-code)
344 (opcode-8 :field (byte 8 20))
345 (rd :field (byte 4 16) :type 'reg)
346 (sbz :field (byte 4 12) :value 0)
347 (rs :field (byte 4 8) :type 'reg)
348 (opcode-4 :field (byte 4 4))
349 (rm :field (byte 4 0) :type 'reg))
351 (define-instruction-format
352 (multiply-dnsm 32
353 :default-printer '(:name cond :tab rd ", " rs ", " rm ", " num))
354 (cond :field (byte 4 28) :type 'condition-code)
355 (opcode-8 :field (byte 8 20))
356 (rd :field (byte 4 16) :type 'reg)
357 (num :field (byte 4 12) :type 'reg)
358 (rs :field (byte 4 8) :type 'reg)
359 (opcode-4 :field (byte 4 4))
360 (rm :field (byte 4 0) :type 'reg))
362 (define-instruction-format
363 (multiply-ddsm 32
364 :default-printer '(:name cond :tab rdlo ", " rdhi ", " rs ", " rm))
365 (cond :field (byte 4 28) :type 'condition-code)
366 (opcode-8 :field (byte 8 20))
367 (rdhi :field (byte 4 16) :type 'reg)
368 (rdlo :field (byte 4 12) :type 'reg)
369 (rs :field (byte 4 8) :type 'reg)
370 (opcode-4 :field (byte 4 4))
371 (rm :field (byte 4 0) :type 'reg))
373 (define-instruction-format (branch-exchange 32
374 :default-printer '(:name cond :tab rm))
375 (cond :field (byte 4 28) :type 'condition-code)
376 (opcode-8 :field (byte 8 20))
377 (sbo :field (byte 12 8) :value #xFFF)
378 (opcode-4 :field (byte 4 4))
379 (rm :field (byte 4 0) :type 'reg))
381 (define-instruction-format (fp-binary 32
382 :default-printer '(:name cond :tab fd ", " fn ", " fm))
383 (cond :field (byte 4 28) :type 'condition-code)
384 (opc-1 :field (byte 4 24) :value #b1110)
385 (p :field (byte 1 23))
386 (q :field (byte 1 21))
387 (r :field (byte 1 20))
388 (s :field (byte 1 6))
389 (fn :fields (list (byte 1 8) (byte 4 16) (byte 1 7)) :type 'float-reg)
390 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
391 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
392 (opc-2 :field (byte 3 9) :value #b101)
393 (size :field (byte 1 8))
394 (opc-3 :field (byte 1 4) :value 0))
396 (define-instruction-format (fp-unary 32
397 :default-printer '(:name cond :tab fd ", " fm))
398 (cond :field (byte 4 28) :type 'condition-code)
399 (opc-1 :field (byte 5 23) :value #b11101)
400 (opc-2 :field (byte 2 20) :value #b11)
401 (opc :field (byte 4 16))
402 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
403 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
404 (opc-3 :field (byte 3 9) :value #b101)
405 (size :field (byte 1 8))
406 (n :field (byte 1 7))
407 (s :field (byte 1 6) :value 1)
408 (opc-4 :field (byte 1 4) :value 0))
410 (define-instruction-format (fp-unary-one-op 32
411 :default-printer '(:name cond :tab fd))
412 (cond :field (byte 4 28) :type 'condition-code)
413 (opc-1 :field (byte 5 23) :value #b11101)
414 (opc-2 :field (byte 2 20) :value #b11)
415 (opc :field (byte 4 16))
416 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
417 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
418 (opc-3 :field (byte 3 9) :value #b101)
419 (size :field (byte 1 8))
420 (n :field (byte 1 7))
421 (s :field (byte 1 6) :value 1)
422 (sbz :field (byte 6 0) :value 0))
424 (define-instruction-format (fp-srt 32)
425 (cond :field (byte 4 28) :type 'condition-code)
426 (opc-1 :field (byte 4 24) :value #b1110)
427 (opc :field (byte 3 21))
428 (l :field (byte 1 20))
429 (fn :fields (list (byte 1 8) (byte 1 7) (byte 4 16)) :type 'float-reg)
430 (rd :field (byte 4 12) :type 'reg)
431 (opc-3 :field (byte 3 9) :value #b101)
432 (size :field (byte 1 8))
433 (opc-4 :field (byte 7 0) :value #b0010000))
435 (define-instruction-format (fp-srt-sys 32)
436 (cond :field (byte 4 28) :type 'condition-code)
437 (opc-1 :field (byte 4 24) :value #b1110)
438 (opc :field (byte 3 21))
439 (l :field (byte 1 20))
440 (fn :field (byte 4 16) :type 'float-sys-reg)
441 (rd :field (byte 4 12) :type 'reg)
442 (opc-3 :field (byte 3 9) :value #b101)
443 (opc-4 :field (byte 8 0) :value #b00010000))
445 (define-instruction-format (fp-trt 32)
446 (cond :field (byte 4 28) :type 'condition-code)
447 (opc-1 :field (byte 7 21) :value #b1100010)
448 (l :field (byte 1 20))
449 (rn :field (byte 4 16) :type 'reg)
450 (rd :field (byte 4 12) :type 'reg)
451 (opc-2 :field (byte 3 9) :value #b101)
452 (size :field (byte 1 8))
453 (opc-3 :field (byte 2 6) :value 0)
454 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
455 (opc-4 :field (byte 1 4) :value 1))
457 (define-instruction-format (conditional 32 :default-printer '(:name cond))
458 (cond :field (byte 4 28) :type 'condition-code)
459 (op :field (byte 28 0)))
461 ;;;; special magic to support decoding internal-error and related traps
463 ;; snarf-error-junk is basically identical on all platforms that
464 ;; define it (meaning, not Alpha). Shouldn't it be common somewhere?
465 (defun snarf-error-junk (sap offset &optional length-only)
466 (let* ((length (sap-ref-8 sap offset))
467 (vector (make-array length :element-type '(unsigned-byte 8))))
468 (declare (type system-area-pointer sap)
469 (type (unsigned-byte 8) length)
470 (type (simple-array (unsigned-byte 8) (*)) vector))
471 (cond (length-only
472 (values 0 (1+ length) nil nil))
474 (copy-ub8-from-system-area sap (1+ offset) vector 0 length)
475 (collect ((sc-offsets)
476 (lengths))
477 (lengths 1) ; the length byte
478 (let* ((index 0)
479 (error-number (sb!c:read-var-integer vector index)))
480 (lengths index)
481 (loop
482 (when (>= index length)
483 (return))
484 (let ((old-index index))
485 (sc-offsets (sb!c:read-var-integer vector index))
486 (lengths (- index old-index))))
487 (values error-number
488 (1+ length)
489 (sc-offsets)
490 (lengths))))))))
492 (defun debug-trap-control (chunk inst stream dstate)
493 (declare (ignore inst))
494 (flet ((nt (x) (if stream (note x dstate))))
495 (case (debug-trap-code chunk dstate)
496 (#.halt-trap
497 (nt "Halt trap"))
498 (#.pending-interrupt-trap
499 (nt "Pending interrupt trap"))
500 (#.error-trap
501 (nt "Error trap")
502 (handle-break-args #'snarf-error-junk stream dstate))
503 (#.cerror-trap
504 (nt "Cerror trap")
505 (handle-break-args #'snarf-error-junk stream dstate))
506 (#.breakpoint-trap
507 (nt "Breakpoint trap"))
508 (#.fun-end-breakpoint-trap
509 (nt "Function end breakpoint trap"))
510 (#.single-step-around-trap
511 (nt "Single step around trap"))
512 (#.single-step-before-trap
513 (nt "Single step before trap")))))
515 ;;;; primitive emitters
517 ;(define-bitfield-emitter emit-word 16
518 ; (byte 16 0))
520 (define-bitfield-emitter emit-word 32
521 (byte 32 0))
523 ;;;; fixup emitters
525 (defun emit-absolute-fixup (segment fixup)
526 (note-fixup segment :absolute fixup)
527 (let ((offset (fixup-offset fixup)))
528 (if (label-p offset)
529 (emit-back-patch segment
530 4 ; FIXME: n-word-bytes
531 (lambda (segment posn)
532 (declare (ignore posn))
533 (emit-dword segment
534 (- (+ (component-header-length)
535 (or (label-position offset)
537 other-pointer-lowtag))))
538 (emit-dword segment (or offset 0)))))
540 (defun emit-relative-fixup (segment fixup)
541 (note-fixup segment :relative fixup)
542 (emit-dword segment (or (fixup-offset fixup) 0)))
545 ;;;; miscellaneous hackery
547 (defun register-p (thing)
548 (and (tn-p thing)
549 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)))
551 (defmacro with-condition-defaulted ((argvar arglist) &body body)
552 (let ((internal-emitter (gensym)))
553 `(flet ((,internal-emitter ,arglist
554 ,@body))
555 (if (assoc (car ,argvar) *conditions*)
556 (apply #',internal-emitter ,argvar)
557 (apply #',internal-emitter :al ,argvar)))))
559 (define-instruction byte (segment byte)
560 (:emitter
561 (emit-byte segment byte)))
563 ;(define-instruction word (segment word)
564 ; (:emitter
565 ; (emit-word segment word)))
567 (define-instruction word (segment word)
568 (:emitter
569 (etypecase word
570 (fixup
571 (note-fixup segment :absolute word)
572 (emit-word segment 0))
573 (integer
574 (emit-word segment word)))))
576 (defun emit-header-data (segment type)
577 (emit-back-patch segment
579 (lambda (segment posn)
580 (emit-word segment
581 (logior type
582 (ash (+ posn
583 (component-header-length))
584 (- n-widetag-bits
585 word-shift)))))))
587 (define-instruction simple-fun-header-word (segment)
588 (:emitter
589 (emit-header-data segment simple-fun-header-widetag)))
591 (define-instruction lra-header-word (segment)
592 (:emitter
593 (emit-header-data segment return-pc-header-widetag)))
595 ;;;; Addressing mode 1 support
597 ;;; Addressing mode 1 has some 11 formats. These are immediate,
598 ;;; register, and nine shift/rotate functions based on one or more
599 ;;; registers. As the mnemonics used for these functions are not
600 ;;; currently used, we simply define them as constructors for a
601 ;;; shifter-operand structure, similar to the make-ea function in the
602 ;;; x86 backend.
604 (defstruct shifter-operand
605 register
606 function-code
607 operand)
609 (defun lsl (register operand)
610 (aver (register-p register))
611 (aver (or (register-p operand)
612 (typep operand '(integer 0 31))))
614 (make-shifter-operand :register register :function-code 0 :operand operand))
616 (defun lsr (register operand)
617 (aver (register-p register))
618 (aver (or (register-p operand)
619 (typep operand '(integer 1 32))))
621 (make-shifter-operand :register register :function-code 1 :operand operand))
623 (defun asr (register operand)
624 (aver (register-p register))
625 (aver (or (register-p operand)
626 (typep operand '(integer 1 32))))
628 (make-shifter-operand :register register :function-code 2 :operand operand))
630 (defun ror (register operand)
631 ;; ROR is a special case: the encoding for ROR with an immediate
632 ;; shift of 32 (0) is actually RRX.
633 (aver (register-p register))
634 (aver (or (register-p operand)
635 (typep operand '(integer 1 31))))
637 (make-shifter-operand :register register :function-code 3 :operand operand))
639 (defun rrx (register)
640 ;; RRX is a special case: it is encoded as ROR with an immediate
641 ;; shift of 32 (0), and has no operand.
642 (aver (register-p register))
643 (make-shifter-operand :register register :function-code 3 :operand 0))
645 (define-condition cannot-encode-immediate-operand (error)
646 ((value :initarg :value)))
648 (defun encodable-immediate (operand)
649 ;; 32-bit immediate data is encoded as an 8-bit immediate data value
650 ;; and a 4-bit immediate shift count. The actual value is the
651 ;; immediate data rotated right by a number of bits equal to twice
652 ;; the shift count. Note that this means that there are a limited
653 ;; number of valid immediate integers and that some integers have
654 ;; multiple possible encodings. In the case of multiple encodings,
655 ;; the correct one to use is the one with the lowest shift count.
657 ;; XXX: Is it possible to determine the correct encoding in constant
658 ;; time, rather than time proportional to the final shift count? Is
659 ;; it possible to determine if a given integer is valid without
660 ;; attempting to encode it? Are such solutions cheaper (either time
661 ;; or spacewise) than simply attempting to encode it?
662 (labels ((try-immediate-encoding (value shift)
663 (unless (<= 0 shift 15)
664 (return-from encodable-immediate))
665 (if (typep value '(unsigned-byte 8))
666 (dpb shift (byte 4 8) value)
667 (try-immediate-encoding (dpb value (byte 30 2)
668 (ldb (byte 2 30) value))
669 (1+ shift)))))
670 (try-immediate-encoding operand 0)))
672 (defun encode-shifter-immediate (operand)
674 (encodable-immediate operand)
675 (error 'cannot-encode-immediate-operand :value operand)))
677 (defun encode-shifter-operand (operand)
678 (etypecase operand
679 (integer
680 (dpb 1 (byte 1 25) (encode-shifter-immediate operand)))
683 (cond
684 ((eq 'registers (sb-name (sc-sb (tn-sc operand))))
685 ;; For those wondering, this is LSL immediate for 0 bits.
686 (tn-offset operand))
688 ((eq 'null (sc-name (tn-sc operand)))
689 null-offset)
691 (t (error "Don't know how to encode TN ~A as a SHIFTER-OPERAND" operand))))
693 (shifter-operand
694 (let ((Rm (tn-offset (shifter-operand-register operand)))
695 (shift-code (shifter-operand-function-code operand))
696 (shift-amount (shifter-operand-operand operand)))
697 (etypecase shift-amount
698 (integer
699 (dpb shift-amount (byte 5 7)
700 (dpb shift-code (byte 2 5)
701 Rm)))
703 (dpb (tn-offset shift-amount) (byte 4 8)
704 (dpb shift-code (byte 2 5)
705 (dpb 1 (byte 1 4)
706 Rm)))))))))
708 (defun lowest-set-bit-index (integer-value)
709 (max 0 (1- (integer-length (logand integer-value (- integer-value))))))
711 ;; FIXME: it would be idiomatic to use (DEFINE-INSTRUCTION-MACRO COMPOSITE ...)
712 ;; instead of exporting another instruction-generating macro into SB!VM.
713 ;; An invocation would resemble (INST COMPOSITE {ADD|SUB|whatever| ARGS ...)
714 (defmacro composite-immediate-instruction (op r x y &key fixnumize neg-op invert-y invert-r single-op-op first-op first-no-source)
715 ;; Successively applies 8-bit wide chunks of Y to X using OP storing the result in R.
717 ;; If FIXNUMIZE is true, Y is fixnumized before being used.
718 ;; If NEG-OP is given and Y is negative, NEG-OP is used instead of OP.
719 ;; If INVERT-Y is given LOGNOT is applied to Y before it being used (but after possibly
720 ;; being fixnumized.
721 ;; If INVERT-R is given R is bit wise inverted at the end.
722 ;; If SINGLE-OP-OP is given and (possibly fixnumized) Y fits into a single ARM immediate
723 ;; it is used for a single operation instead of OP.
724 ;; If FIRST-OP is given, it is used in the first iteration instead of OP.
725 ;; If FIRST-NO-SOURCE is given, there will be ne source register (X) in the first iteration.
726 (let ((bytespec (gensym "bytespec"))
727 (value (gensym "value"))
728 (transformed (gensym "transformed")))
729 (labels ((instruction (source-reg op neg-op &optional no-source)
730 `(,@(if neg-op
731 `((if (< ,y 0)
732 (inst ,neg-op ,r ,@(when (not no-source)`(,source-reg))
733 (mask-field ,bytespec ,value))
734 (inst ,op ,r ,@(when (not no-source) `(,source-reg))
735 (mask-field ,bytespec ,value))))
736 `((inst ,op ,r ,@(when (not no-source) `(,source-reg))
737 (mask-field ,bytespec ,value))))
738 (setf (ldb ,bytespec ,value) 0)))
739 (composite ()
740 `((let ((,bytespec (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))))
741 ,@(instruction x (or first-op op) neg-op first-no-source))
742 (do ((,bytespec (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))
743 (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))))
744 ((zerop ,value))
745 ,@(instruction r op neg-op)
746 ,@(when invert-r
747 `((inst mvn ,r ,r)))))))
748 `(let* ((,transformed ,(if fixnumize
749 `(fixnumize ,y)
750 `,y))
751 (,value (ldb (byte 32 0)
752 ,@(if neg-op
753 `((if (< ,transformed 0) (- ,transformed) ,transformed))
754 (if invert-y
755 `((lognot ,transformed))
756 `(,transformed))))))
757 ,@(if single-op-op
758 `((handler-case
759 (progn
760 (inst ,single-op-op ,r ,x ,transformed))
761 (cannot-encode-immediate-operand ()
762 ,@(composite))))
763 (composite))))))
766 ;;;; Addressing mode 2 support
768 ;;; Addressing mode 2 ostensibly has 9 formats. These are formed from
769 ;;; a cross product of three address calculations and three base
770 ;;; register writeback modes. As one of the address calculations is a
771 ;;; scaled register calculation identical to the mode 1 register shift
772 ;;; by constant, we reuse the shifter-operand structure and its public
773 ;;; constructors.
775 (defstruct memory-operand
776 base
777 offset
778 direction
779 mode)
781 ;;; The @ macro is used to encode a memory addressing mode. The
782 ;;; parameters for the base form are a base register, an optional
783 ;;; offset (either an integer, a register tn or a shifter-operand
784 ;;; structure with a constant shift amount, optionally within a unary
785 ;;; - form), and a base register writeback mode (either :offset,
786 ;;; :pre-index, or :post-index). The alternative form uses a label as
787 ;;; the base register, and accepts only (optionally negated) integers
788 ;;; as offsets, and requires a mode of :offset.
789 (defun %@ (base offset direction mode)
790 (when (label-p base)
791 (aver (eq mode :offset))
792 (aver (integerp offset)))
794 (when (shifter-operand-p offset)
795 (aver (integerp (shifter-operand-operand offset))))
797 ;; Fix up direction with negative offsets.
798 (when (and (not (label-p base))
799 (integerp offset)
800 (< offset 0))
801 (setf offset (- offset))
802 (setf direction (if (eq direction :up) :down :up)))
804 (make-memory-operand :base base :offset offset
805 :direction direction :mode mode))
807 (defmacro @ (base &optional (offset 0) (mode :offset))
808 (let* ((direction (if (and (consp offset)
809 (eq (car offset) '-)
810 (null (cddr offset)))
811 :down
812 :up))
813 (offset (if (eq direction :down) (cadr offset) offset)))
814 `(%@ ,base ,offset ,direction ,mode)))
816 ;;;; Data-processing instructions
818 ;;; Data processing instructions have a 4-bit opcode field and a 1-bit
819 ;;; "S" field for updating condition bits. They are adjacent, so we
820 ;;; roll them into one 5-bit field for convenience.
822 (define-bitfield-emitter emit-dp-instruction 32
823 (byte 4 28) (byte 2 26) (byte 1 25) (byte 5 20)
824 (byte 4 16) (byte 4 12) (byte 12 0))
826 ;;; There are 16 data processing instructions, with a breakdown as
827 ;;; follows:
829 ;;; 1.) Two "move" instructions, with no "source" operand (they have
830 ;;; destination and shifter operands only).
832 ;;; 2.) Four "test" instructions, with no "destination" operand.
833 ;;; These instructions always have their "S" bit set, though it
834 ;;; is not specified in their mnemonics.
836 ;;; 3.) Ten "normal" instructions, with all three operands.
838 ;;; Aside from this, the instructions all have a regular encoding, so
839 ;;; we can use a single macro to define them.
841 (defmacro define-data-processing-instruction (instruction opcode dest-p src-p)
842 `(define-instruction ,instruction (segment &rest args)
843 (:printer dp-shift-immediate ((opcode-8 ,opcode)
844 ,@(unless dest-p '((rd 0)))
845 ,@(unless src-p '((rn 0))))
846 ,@(cond
847 ((not dest-p)
848 '('(:name cond :tab rn ", " rm shift)))
849 ((not src-p)
850 '('(:name cond :tab rd ", " rm shift)))))
851 (:printer dp-shift-register ((opcode-8 ,opcode)
852 ,@(unless dest-p '((rd 0)))
853 ,@(unless src-p '((rn 0))))
854 ,@(cond
855 ((not dest-p)
856 '('(:name cond :tab rn ", " rm ", " shift-type " " rs)))
857 ((not src-p)
858 '('(:name cond :tab rd ", " rm ", " shift-type " " rs)))))
859 (:printer dp-immediate ((opcode-8 ,(logior opcode #x20))
860 ,@(unless dest-p '((rd 0)))
861 ,@(unless src-p '((rn 0))))
862 ,@(cond
863 ((not dest-p)
864 '('(:name cond :tab rn ", " immediate)))
865 ((not src-p)
866 '('(:name cond :tab rd ", " immediate)))))
867 (:emitter
868 (with-condition-defaulted (args (condition ,@(if dest-p '(dest))
869 ,@(if src-p '(src))
870 shifter-operand))
871 ,(if dest-p '(aver (register-p dest)))
872 ,(if src-p '(aver (register-p src)))
873 (let ((shifter-operand (encode-shifter-operand shifter-operand)))
874 (emit-dp-instruction segment
875 (conditional-opcode condition)
877 (ldb (byte 1 25) shifter-operand)
878 ,opcode
879 ,(if src-p '(tn-offset src) 0)
880 ,(if dest-p '(tn-offset dest) 0)
881 (ldb (byte 12 0) shifter-operand)))))))
883 (define-data-processing-instruction and #x00 t t)
884 (define-data-processing-instruction ands #x01 t t)
885 (define-data-processing-instruction eor #x02 t t)
886 (define-data-processing-instruction eors #x03 t t)
887 (define-data-processing-instruction sub #x04 t t)
888 (define-data-processing-instruction subs #x05 t t)
889 (define-data-processing-instruction rsb #x06 t t)
890 (define-data-processing-instruction rsbs #x07 t t)
891 (define-data-processing-instruction add #x08 t t)
892 (define-data-processing-instruction adds #x09 t t)
893 (define-data-processing-instruction adc #x0a t t)
894 (define-data-processing-instruction adcs #x0b t t)
895 (define-data-processing-instruction sbc #x0c t t)
896 (define-data-processing-instruction sbcs #x0d t t)
897 (define-data-processing-instruction rsc #x0e t t)
898 (define-data-processing-instruction rscs #x0f t t)
899 (define-data-processing-instruction orr #x18 t t)
900 (define-data-processing-instruction orrs #x19 t t)
901 (define-data-processing-instruction bic #x1c t t)
902 (define-data-processing-instruction bics #x1d t t)
904 (define-data-processing-instruction tst #x11 nil t)
905 (define-data-processing-instruction teq #x13 nil t)
906 (define-data-processing-instruction cmp #x15 nil t)
907 (define-data-processing-instruction cmn #x17 nil t)
909 (define-data-processing-instruction mov #x1a t nil)
910 (define-data-processing-instruction movs #x1b t nil)
911 (define-data-processing-instruction mvn #x1e t nil)
912 (define-data-processing-instruction mvns #x1f t nil)
914 ;;;; Exception-generating instructions
916 ;;; There are two exception-generating instructions. One, BKPT, is
917 ;;; ostensibly used as a breakpoint instruction, and to communicate
918 ;;; with debugging hardware. The other, SWI, is intended for use as a
919 ;;; system call interface. We need both because, at least on some
920 ;;; platforms, the only breakpoint trap that works properly is a
921 ;;; syscall.
923 (define-bitfield-emitter emit-swi-instruction 32
924 (byte 4 28) (byte 4 24) (byte 24 0))
926 (define-instruction swi (segment &rest args)
927 (:printer swi ((opcode-4 #b1111)))
928 (:emitter
929 (with-condition-defaulted (args (condition code))
930 (emit-swi-instruction segment
931 (conditional-opcode condition)
932 #b1111 code))))
934 (define-bitfield-emitter emit-bkpt-instruction 32
935 (byte 4 28) (byte 8 20) (byte 12 8) (byte 4 4) (byte 4 0))
937 (define-instruction bkpt (segment code)
938 (:emitter
939 (emit-bkpt-instruction segment #b1110 #b00010010
940 (ldb (byte 12 4) code)
941 #b0111
942 (ldb (byte 4 0) code))))
944 ;;; It turns out that the Linux kernel decodes this particular
945 ;;; officially undefined instruction as a single-instruction SIGTRAP
946 ;;; generation instruction, or breakpoint.
947 (define-instruction debug-trap (segment)
948 (:printer debug-trap ((opcode-32 #!+linux #xe7f001f0
949 #!+netbsd #xe7ffdefe))
950 :default :control #'debug-trap-control)
951 (:emitter
952 (emit-word segment #!+linux #xe7f001f0 #!+netbsd #xe7ffdefe)))
954 ;;;; Miscellaneous arithmetic instructions
956 (define-bitfield-emitter emit-clz-instruction 32
957 (byte 4 28) (byte 12 16) (byte 4 12) (byte 8 4) (byte 4 0))
959 (define-instruction clz (segment &rest args)
960 (:printer dp-shift-register ((opcode-8 #b00010110)
961 (rn #b1111)
962 (rs #b1111)
963 (shift-type #b00))
964 '(:name cond :tab rd ", " rm))
965 (:emitter
966 (with-condition-defaulted (args (condition dest src))
967 (aver (register-p dest))
968 (aver (register-p src))
969 (emit-clz-instruction segment (conditional-opcode condition)
970 #b000101101111
971 (tn-offset dest)
972 #b11110001
973 (tn-offset src)))))
975 ;;;; Branch instructions
977 (define-bitfield-emitter emit-branch-instruction 32
978 (byte 4 28) (byte 4 24) (byte 24 0))
980 (defun emit-branch-back-patch (segment condition opcode dest)
981 (emit-back-patch segment 4
982 (lambda (segment posn)
983 (emit-branch-instruction segment
984 (conditional-opcode condition)
985 opcode
986 (ldb (byte 24 2)
987 (- (label-position dest)
988 (+ posn 8)))))))
990 (define-instruction b (segment &rest args)
991 (:printer branch ((opcode-4 #b1010)))
992 (:emitter
993 (with-condition-defaulted (args (condition dest))
994 (aver (label-p dest))
995 (emit-branch-back-patch segment condition #b1010 dest))))
997 (define-instruction bl (segment &rest args)
998 (:printer branch ((opcode-4 #b1011)))
999 (:emitter
1000 (with-condition-defaulted (args (condition dest))
1001 (aver (label-p dest))
1002 (emit-branch-back-patch segment condition #b1011 dest))))
1004 (define-bitfield-emitter emit-branch-exchange-instruction 32
1005 (byte 4 28) (byte 8 20) (byte 4 16) (byte 4 12)
1006 (byte 4 8) (byte 4 4) (byte 4 0))
1008 (define-instruction bx (segment &rest args)
1009 (:printer branch-exchange ((opcode-8 #b00010010)
1010 (opcode-4 #b0001)))
1011 (:emitter
1012 (with-condition-defaulted (args (condition dest))
1013 (aver (register-p dest))
1014 (emit-branch-exchange-instruction segment
1015 (conditional-opcode condition)
1016 #b00010010 #b1111 #b1111
1017 #b1111 #b0001 (tn-offset dest)))))
1019 (define-instruction blx (segment &rest args)
1020 (:printer branch-exchange ((opcode-8 #b00010010)
1021 (opcode-4 #b0011)))
1022 (:emitter
1023 (with-condition-defaulted (args (condition dest))
1024 (aver (register-p dest))
1025 (emit-branch-exchange-instruction segment
1026 (conditional-opcode condition)
1027 #b00010010 #b1111 #b1111
1028 #b1111 #b0011 (tn-offset dest)))))
1030 ;;;; Semaphore instructions
1032 (defun emit-semaphore-instruction (segment opcode condition dest value address)
1033 (aver (register-p dest))
1034 (aver (register-p value))
1035 (aver (memory-operand-p address))
1036 (aver (zerop (memory-operand-offset address)))
1037 (aver (eq :offset (memory-operand-mode address)))
1038 (emit-dp-instruction segment (conditional-opcode condition)
1039 #b00 0 opcode (tn-offset (memory-operand-base address))
1040 (tn-offset dest)
1041 (dpb #b1001 (byte 4 4) (tn-offset value))))
1043 (define-instruction swp (segment &rest args)
1044 (:emitter
1045 (with-condition-defaulted (args (condition dest value address))
1046 (emit-semaphore-instruction segment #b10000
1047 condition dest value address))))
1049 (define-instruction swpb (segment &rest args)
1050 (:emitter
1051 (with-condition-defaulted (args (condition dest value address))
1052 (emit-semaphore-instruction segment #b10100
1053 condition dest value address))))
1055 ;;;; Status-register instructions
1057 (define-instruction mrs (segment &rest args)
1058 (:printer dp-shift-immediate ((opcode-8 #b0010000)
1059 (rn #b1111)
1060 (shift '(0 0))
1061 (rm 0))
1062 '(:name cond :tab rd ", CPSR"))
1063 (:printer dp-shift-immediate ((opcode-8 #b0010100)
1064 (rn #b1111)
1065 (shift '(0 0))
1066 (rm 0))
1067 '(:name cond :tab rd ", SPSR"))
1068 (:emitter
1069 (with-condition-defaulted (args (condition dest reg))
1070 (aver (register-p dest))
1071 (aver (member reg '(:cpsr :spsr)))
1072 (emit-dp-instruction segment (conditional-opcode condition)
1073 #b00 0 (if (eq reg :cpsr) #b10000 #b10100)
1074 #b1111 (tn-offset dest) 0))))
1076 (defun encode-status-register-fields (fields)
1077 (let ((fields (string fields)))
1078 (labels ((frob (mask index)
1079 (let* ((field (aref fields index))
1080 (field-mask (cdr (assoc field
1081 '((#\C . #b0001) (#\X . #b0010)
1082 (#\S . #b0100) (#\F . #b1000))
1083 :test #'char=))))
1084 (unless field-mask
1085 (error "bad status register field desginator ~S" fields))
1086 (if (< (1+ index) (length fields))
1087 (frob (logior mask field-mask) (1+ index))
1088 (logior mask field-mask)))))
1089 (frob 0 0))))
1091 (defmacro cpsr (fields)
1092 (encode-status-register-fields fields))
1094 (defmacro spsr (fields)
1095 (logior #b10000 (encode-status-register-fields fields)))
1097 (define-instruction msr (segment &rest args)
1098 (:printer msr-immediate ())
1099 (:printer msr-register ())
1100 (:emitter
1101 (with-condition-defaulted (args (condition field-mask src))
1102 (aver (or (register-p src)
1103 (integerp src)))
1104 (let ((encoded-src (encode-shifter-operand src)))
1105 (emit-dp-instruction segment (conditional-opcode condition)
1106 #b00 (ldb (byte 1 25) encoded-src)
1107 (if (logbitp 4 field-mask) #b10110 #b10010)
1108 field-mask #b1111
1109 (ldb (byte 12 0) encoded-src))))))
1111 ;;;; Multiply instructions
1113 (define-bitfield-emitter emit-multiply-instruction 32
1114 (byte 4 28) (byte 8 20) (byte 4 16) (byte 4 12)
1115 (byte 4 8) (byte 4 4) (byte 4 0))
1117 (macrolet
1118 ((define-multiply-instruction (name field-mapping opcode1 opcode2)
1119 (let ((arglist (ecase field-mapping
1120 (:dzsm '(dest src multiplicand))
1121 (:dnsm '(dest src multiplicand num))
1122 (:ddsm '(dest-lo dest src multiplicand)))))
1123 `(define-instruction ,name (segment &rest args)
1124 (:printer ,(symbolicate 'multiply- field-mapping)
1125 ((opcode-8 ,opcode1)
1126 (opcode-4 ,opcode2)))
1127 (:emitter
1128 (with-condition-defaulted (args (condition ,@arglist))
1129 ,@(loop
1130 for arg in arglist
1131 collect `(aver (register-p ,arg)))
1132 (emit-multiply-instruction segment (conditional-opcode condition)
1133 ,opcode1
1134 (tn-offset dest)
1135 ,(ecase field-mapping
1136 (:dzsm 0)
1137 (:dnsm '(tn-offset num))
1138 (:ddsm '(tn-offset dest-lo)))
1139 (tn-offset src)
1140 ,opcode2
1141 (tn-offset multiplicand))))))))
1143 (define-multiply-instruction mul :dzsm #b00000000 #b1001)
1144 (define-multiply-instruction muls :dzsm #b00000001 #b1001)
1145 (define-multiply-instruction mla :dnsm #b00000010 #b1001)
1146 (define-multiply-instruction mlas :dnsm #b00000011 #b1001)
1148 (define-multiply-instruction umull :ddsm #b00001000 #b1001)
1149 (define-multiply-instruction umulls :ddsm #b00001001 #b1001)
1150 (define-multiply-instruction umlal :ddsm #b00001010 #b1001)
1151 (define-multiply-instruction umlals :ddsm #b00001011 #b1001)
1153 (define-multiply-instruction smull :ddsm #b00001100 #b1001)
1154 (define-multiply-instruction smulls :ddsm #b00001101 #b1001)
1155 (define-multiply-instruction smlal :ddsm #b00001110 #b1001)
1156 (define-multiply-instruction smlals :ddsm #b00001111 #b1001)
1158 (define-multiply-instruction smlabb :dnsm #b00010000 #b1000)
1159 (define-multiply-instruction smlatb :dnsm #b00010000 #b1010)
1160 (define-multiply-instruction smlabt :dnsm #b00010000 #b1100)
1161 (define-multiply-instruction smlatt :dnsm #b00010000 #b1110)
1163 (define-multiply-instruction smlalbb :ddsm #b00010100 #b1000)
1164 (define-multiply-instruction smlaltb :ddsm #b00010100 #b1010)
1165 (define-multiply-instruction smlalbt :ddsm #b00010100 #b1100)
1166 (define-multiply-instruction smlaltt :ddsm #b00010100 #b1110)
1168 (define-multiply-instruction smulbb :dzsm #b00010110 #b1000)
1169 (define-multiply-instruction smultb :dzsm #b00010110 #b1010)
1170 (define-multiply-instruction smulbt :dzsm #b00010110 #b1100)
1171 (define-multiply-instruction smultt :dzsm #b00010110 #b1110)
1173 (define-multiply-instruction smlawb :dnsm #b00010010 #b1000)
1174 (define-multiply-instruction smlawt :dnsm #b00010010 #b1100)
1176 (define-multiply-instruction smulwb :dzsm #b00010010 #b1010)
1177 (define-multiply-instruction smulwt :dzsm #b00010010 #b1110))
1179 ;;;; Load/store instructions
1181 ;;; Emit a load/store instruction. CONDITION is a condition code
1182 ;;; name, KIND is :load or :store, WIDTH is :word or :byte, DATA is a
1183 ;;; register TN and ADDRESS is either a memory-operand structure or a
1184 ;;; stack TN.
1185 (defun emit-load/store-instruction (segment condition kind width data address)
1186 (flet ((compute-opcode (direction mode)
1187 (let ((opcode-bits '(:load #b00001 :store #b00000
1188 :word #b00000 :byte #b00100
1189 :up #b01000 :down #b00000
1190 :offset #b10000
1191 :pre-index #b10010
1192 :post-index #b00000)))
1193 (reduce #'logior (list kind width direction mode)
1194 :key (lambda (value) (getf opcode-bits value))))))
1195 (etypecase address
1196 (memory-operand
1197 (let* ((base (memory-operand-base address))
1198 (offset (memory-operand-offset address))
1199 (direction (memory-operand-direction address))
1200 (mode (memory-operand-mode address))
1201 (cond-bits (conditional-opcode condition)))
1202 (cond
1203 ((label-p base)
1204 (emit-back-patch
1205 segment 4
1206 (lambda (segment posn)
1207 (let* ((label-delta (- (label-position base)
1208 (+ posn 8)))
1209 (offset-delta (if (eq direction :up)
1210 offset
1211 (- offset)))
1212 (overall-delta (+ label-delta
1213 offset-delta))
1214 (absolute-delta (abs overall-delta)))
1215 (aver (typep absolute-delta '(unsigned-byte 12)))
1216 (emit-dp-instruction segment cond-bits #b01 0
1217 (compute-opcode (if (< overall-delta 0)
1218 :down
1219 :up)
1220 mode)
1221 pc-offset (tn-offset data)
1222 absolute-delta)))))
1223 ((integerp offset)
1224 (aver (typep offset '(unsigned-byte 12)))
1225 (emit-dp-instruction segment cond-bits #b01 0
1226 (compute-opcode direction mode)
1227 (tn-offset base) (tn-offset data)
1228 offset))
1230 (emit-dp-instruction segment cond-bits #b01 1
1231 (compute-opcode direction mode)
1232 (tn-offset base) (tn-offset data)
1233 (encode-shifter-operand offset))))))
1235 #+(or)
1237 ;; FIXME: This is for stack TN references, and needs must be
1238 ;; implemented.
1239 ))))
1241 (macrolet
1242 ((define-load/store-instruction (name kind width)
1243 `(define-instruction ,name (segment &rest args)
1244 (:printer load/store-immediate ((opcode-3 #b010)
1245 (opcode-b ,(ecase width
1246 (:word 0)
1247 (:byte 1)))
1248 (opcode-l ,(ecase kind
1249 (:load 1)
1250 (:store 0)))))
1251 (:printer load/store-register ((opcode-3 #b011)
1252 (opcode-0 0)
1253 (opcode-b ,(ecase width
1254 (:word 0)
1255 (:byte 1)))
1256 (opcode-l ,(ecase kind
1257 (:load 1)
1258 (:store 0)))))
1259 (:emitter
1260 (with-condition-defaulted (args (condition reg address))
1261 (aver (or (register-p reg)
1262 ,@(when (eq :store kind)
1263 '((and (tn-p reg)
1264 (eq 'null (sc-name (tn-sc reg))))))))
1265 (emit-load/store-instruction segment condition
1266 ,kind ,width
1267 (if (register-p reg) reg null-tn)
1268 address))))))
1269 (define-load/store-instruction ldr :load :word)
1270 (define-load/store-instruction ldrb :load :byte)
1271 (define-load/store-instruction str :store :word)
1272 (define-load/store-instruction strb :store :byte))
1274 ;;; Emit a miscellaneous load/store instruction. CONDITION is a
1275 ;;; condition code name, OPCODE1 is the low bit of the first opcode
1276 ;;; field, OPCODE2 is the second opcode field, DATA is a register TN
1277 ;;; and ADDRESS is either a memory-operand structure or a stack TN.
1278 (defun emit-misc-load/store-instruction (segment condition opcode1
1279 opcode2 data address)
1280 (flet ((compute-opcode (kind direction mode)
1281 (let ((opcode-bits '(:register #b00000 :immediate #b00100
1282 :up #b01000 :down #b00000
1283 :offset #b10000
1284 :pre-index #b10010
1285 :post-index #b00000)))
1286 (reduce #'logior (list kind direction mode)
1287 :key (lambda (value) (getf opcode-bits value))))))
1288 (etypecase address
1289 (memory-operand
1290 (let* ((base (memory-operand-base address))
1291 (offset (memory-operand-offset address))
1292 (direction (memory-operand-direction address))
1293 (mode (memory-operand-mode address))
1294 (cond-bits (conditional-opcode condition)))
1295 (cond
1296 ((label-p base)
1297 (emit-back-patch
1298 segment 4
1299 (lambda (segment posn)
1300 (let* ((label-delta (- (label-position base)
1301 (+ posn 8)))
1302 (offset-delta (if (eq direction :up)
1303 offset
1304 (- offset)))
1305 (overall-delta (+ label-delta
1306 offset-delta))
1307 (absolute-delta (abs overall-delta)))
1308 (aver (typep absolute-delta '(unsigned-byte 8)))
1309 (emit-multiply-instruction segment cond-bits
1310 (logior opcode1
1311 (compute-opcode :immedaite
1312 (if (< overall-delta 0)
1313 :down
1314 :up)
1315 mode))
1316 (tn-offset base) (tn-offset data)
1317 (ldb (byte 4 4) absolute-delta)
1318 opcode2 absolute-delta)))))
1319 ((integerp offset)
1320 (aver (typep offset '(unsigned-byte 8)))
1321 (emit-multiply-instruction segment cond-bits
1322 (logior opcode1
1323 (compute-opcode :immediate direction mode))
1324 (tn-offset base) (tn-offset data)
1325 (ldb (byte 4 4) offset)
1326 opcode2 offset))
1327 ((register-p offset)
1328 (emit-multiply-instruction segment cond-bits
1329 (logior opcode1
1330 (compute-opcode :register direction mode))
1331 (tn-offset base) (tn-offset data)
1332 0 opcode2 (tn-offset offset)))
1334 (error "bad thing for a miscellaneous load/store address ~S"
1335 address)))))
1337 #+(or)
1339 ;; FIXME: This is for stack TN references, and needs must be
1340 ;; implemented.
1341 ))))
1343 (macrolet
1344 ((define-misc-load/store-instruction (name opcode1 opcode2 double-width)
1345 `(define-instruction ,name (segment &rest args)
1346 (:emitter
1347 (with-condition-defaulted (args (condition reg address))
1348 (aver (register-p reg))
1349 ,(when double-width '(aver (evenp (tn-offset reg))))
1350 (emit-misc-load/store-instruction segment condition
1351 ,opcode1 ,opcode2
1352 reg address))))))
1353 (define-misc-load/store-instruction strh 0 #b1011 nil)
1354 (define-misc-load/store-instruction ldrd 0 #b1101 t)
1355 (define-misc-load/store-instruction strd 0 #b1111 t)
1357 (define-misc-load/store-instruction ldrh 1 #b1011 nil)
1358 (define-misc-load/store-instruction ldrsb 1 #b1101 nil)
1359 (define-misc-load/store-instruction ldrsh 1 #b1111 nil))
1361 ;;;; Boxed-object computation instructions (for LRA and CODE)
1363 ;;; Compute the address of a CODE object by parsing the header of a
1364 ;;; nearby LRA or SIMPLE-FUN.
1365 (define-instruction compute-code (segment code lip object-label temp)
1366 (:vop-var vop)
1367 (:emitter
1368 (emit-back-patch
1369 segment 12
1370 (lambda (segment position)
1371 (assemble (segment vop)
1372 ;; Calculate the address of the code component. This is an
1373 ;; exercise in excess cleverness. First, we calculate (from
1374 ;; our program counter only) the address of OBJECT-LABEL plus
1375 ;; OTHER-POINTER-LOWTAG. The extra two words are to
1376 ;; compensate for the offset applied by ARM CPUs when reading
1377 ;; the program counter.
1378 (inst sub lip pc-tn (- ;; The 8 below is the displacement
1379 ;; from reading the program counter.
1380 (+ position 8)
1381 (+ (label-position object-label)
1382 other-pointer-lowtag)))
1383 ;; Next, we read the function header.
1384 (inst ldr temp (@ lip (- other-pointer-lowtag)))
1385 ;; And finally we use the header value (a count in words),
1386 ;; plus the fact that the top two bits of the widetag are
1387 ;; clear (SIMPLE-FUN-HEADER-WIDETAG is #x2A and
1388 ;; RETURN-PC-HEADER-WIDETAG is #x36) to compute the boxed
1389 ;; address of the code component.
1390 (inst sub code lip (lsr temp (- 8 word-shift))))))))
1392 ;;; Compute the address of a nearby LRA object by dead reckoning from
1393 ;;; the location of the current instruction.
1394 (define-instruction compute-lra (segment dest lip lra-label)
1395 (:vop-var vop)
1396 (:emitter
1397 ;; We can compute the LRA in a single instruction if the overall
1398 ;; offset puts it to within an 8-bit displacement. Otherwise, we
1399 ;; need to load it by parts into LIP until we're down to an 8-bit
1400 ;; displacement, and load the final 8 bits into DEST. We may
1401 ;; safely presume that an overall displacement may be up to 24 bits
1402 ;; wide (the PPC backend has special provision for branches over 15
1403 ;; bits, which implies that segments can become large, but a 16
1404 ;; megabyte segment (24 bits of displacement) is ridiculous), so we
1405 ;; need to cover a range of up to three octets of displacement.
1406 (labels ((compute-delta (position &optional magic-value)
1407 (- (+ (label-position lra-label
1408 (when magic-value position)
1409 magic-value)
1410 other-pointer-lowtag)
1411 ;; The 8 below is the displacement
1412 ;; from reading the program counter.
1413 (+ position 8)))
1415 (load-chunk (segment delta dst src chunk)
1416 (assemble (segment vop)
1417 (if (< delta 0)
1418 (inst sub dst src chunk)
1419 (inst add dst src chunk))))
1421 (three-instruction-emitter (segment position)
1422 (let* ((delta (compute-delta position))
1423 (absolute-delta (abs delta)))
1424 (load-chunk segment delta
1425 lip pc-tn (mask-field (byte 8 16) absolute-delta))
1426 (load-chunk segment delta
1427 lip lip (mask-field (byte 8 8) absolute-delta))
1428 (load-chunk segment delta
1429 dest lip (mask-field (byte 8 0) absolute-delta))))
1431 (two-instruction-emitter (segment position)
1432 (let* ((delta (compute-delta position))
1433 (absolute-delta (abs delta)))
1434 (assemble (segment vop)
1435 (load-chunk segment delta
1436 lip pc-tn (mask-field (byte 8 8) absolute-delta))
1437 (load-chunk segment delta
1438 dest lip (mask-field (byte 8 0) absolute-delta)))))
1440 (one-instruction-emitter (segment position)
1441 (let* ((delta (compute-delta position))
1442 (absolute-delta (abs delta)))
1443 (assemble (segment vop)
1444 (load-chunk segment delta
1445 dest pc-tn absolute-delta))))
1447 (two-instruction-maybe-shrink (segment posn magic-value)
1448 (let ((delta (compute-delta posn magic-value)))
1449 (when (<= (integer-length delta) 8)
1450 (emit-back-patch segment 4
1451 #'one-instruction-emitter)
1452 t)))
1454 (three-instruction-maybe-shrink (segment posn magic-value)
1455 (let ((delta (compute-delta posn magic-value)))
1456 (when (<= (integer-length delta) 16)
1457 (emit-chooser segment 8 2
1458 #'two-instruction-maybe-shrink
1459 #'two-instruction-emitter)
1460 t))))
1461 (emit-chooser
1462 ;; We need to emit up to three instructions, which is 12 octets.
1463 ;; This preserves a mere two bits of alignment.
1464 segment 12 2
1465 #'three-instruction-maybe-shrink
1466 #'three-instruction-emitter))))
1468 ;;; Load a register from a "nearby" LABEL by dead reckoning from the
1469 ;;; location of the current instruction.
1470 (define-instruction load-from-label (segment &rest args)
1471 (:vop-var vop)
1472 (:emitter
1473 (with-condition-defaulted (args (condition dest lip label))
1474 ;; We can load the word addressed by a label in a single
1475 ;; instruction if the overall offset puts it to within a 12-bit
1476 ;; displacement. Otherwise, we need to build an address by parts
1477 ;; into LIP until we're down to a 12-bit displacement, and then
1478 ;; apply the final 12 bits with LDR. For now, we'll allow up to 20
1479 ;; bits of displacement, as that should be easy to implement, and a
1480 ;; megabyte large code object is already a bit unwieldly. If
1481 ;; neccessary, we can expand to a 28 bit displacement.
1482 (labels ((compute-delta (position &optional magic-value)
1483 (- (label-position label
1484 (when magic-value position)
1485 magic-value)
1486 ;; The 8 below is the displacement
1487 ;; from reading the program counter.
1488 (+ position 8)))
1490 (load-chunk (segment delta dst src chunk)
1491 (assemble (segment vop)
1492 (if (< delta 0)
1493 (inst sub condition dst src chunk)
1494 (inst add condition dst src chunk))))
1496 (two-instruction-emitter (segment position)
1497 (let* ((delta (compute-delta position))
1498 (absolute-delta (abs delta)))
1499 (assemble (segment vop)
1500 (load-chunk segment delta
1501 lip pc-tn (mask-field (byte 8 12) absolute-delta))
1502 (inst ldr condition dest (@ lip (mask-field (byte 12 0) delta))))))
1504 (one-instruction-emitter (segment position)
1505 (let* ((delta (compute-delta position)))
1506 (assemble (segment vop)
1507 (inst ldr condition dest (@ pc-tn delta)))))
1509 (two-instruction-maybe-shrink (segment posn magic-value)
1510 (let ((delta (compute-delta posn magic-value)))
1511 (when (<= (integer-length delta) 12)
1512 (emit-back-patch segment 4
1513 #'one-instruction-emitter)
1514 t))))
1515 (emit-chooser
1516 ;; We need to emit up to two instructions, which is 8 octets,
1517 ;; but might wish to emit only one. This preserves a mere two
1518 ;; bits of alignment.
1519 segment 8 2
1520 #'two-instruction-maybe-shrink
1521 #'two-instruction-emitter)))))
1523 ;; data processing floating point instructions
1524 (define-bitfield-emitter emit-fp-dp-instruction 32
1525 (byte 4 28) ; cond
1526 (byte 4 24) ; #b1110
1527 (byte 1 23) ; p
1528 (byte 1 22) ; D
1529 (byte 1 21) ; q
1530 (byte 1 20) ; r
1531 (byte 4 16) ; Fn || extension op
1532 (byte 4 12) ; Fd
1533 (byte 3 9) ; #b101
1534 (byte 1 8) ; double/single precission
1535 (byte 1 7) ; N || extension op
1536 (byte 1 6) ; s
1537 (byte 1 5) ; M
1538 (byte 1 4) ; #b0
1539 (byte 4 0)) ; Fm
1541 (defun low-bit-float-reg (reg-tn)
1542 (logand 1 (tn-offset reg-tn)))
1544 (defun high-bits-float-reg (reg-tn)
1545 (ash (tn-offset reg-tn) -1))
1547 (defmacro define-binary-fp-data-processing-instruction (name precision p q r s)
1548 (let ((precision-flag (ecase precision
1549 (:single 0)
1550 (:double 1))))
1551 `(define-instruction ,name (segment &rest args)
1552 (:printer fp-binary ((p ,p)
1553 (q ,q)
1554 (r ,r)
1555 (s ,s)
1556 (size ,precision-flag)))
1557 (:emitter
1558 (with-condition-defaulted (args (condition dest op-n op-m))
1559 (emit-fp-dp-instruction segment
1560 (conditional-opcode condition)
1561 #b1110
1563 (low-bit-float-reg dest)
1566 (high-bits-float-reg op-n)
1567 (high-bits-float-reg dest)
1568 #b101
1569 ,precision-flag
1570 (low-bit-float-reg op-n)
1572 (low-bit-float-reg op-m)
1574 (high-bits-float-reg op-m)))))))
1576 (defmacro define-binary-fp-data-processing-instructions (root p q r s)
1577 `(progn
1578 (define-binary-fp-data-processing-instruction ,(symbolicate root 's) :single ,p ,q ,r ,s)
1579 (define-binary-fp-data-processing-instruction ,(symbolicate root 'd) :double ,p ,q ,r ,s)))
1581 (define-binary-fp-data-processing-instructions fmac 0 0 0 0)
1582 (define-binary-fp-data-processing-instructions fnmac 0 0 0 1)
1583 (define-binary-fp-data-processing-instructions fmsc 0 0 1 0)
1584 (define-binary-fp-data-processing-instructions fnmsc 0 0 1 1)
1585 (define-binary-fp-data-processing-instructions fmul 0 1 0 0)
1586 (define-binary-fp-data-processing-instructions fnmul 0 1 0 1)
1587 (define-binary-fp-data-processing-instructions fadd 0 1 1 0)
1588 (define-binary-fp-data-processing-instructions fsub 0 1 1 1)
1589 (define-binary-fp-data-processing-instructions fdiv 1 0 0 0)
1591 ;;; op-m-sbz means that it should-be-zero, and only one register is supplied.
1592 (defmacro define-unary-fp-data-processing-instruction (name precision fn n
1593 &key op-m-sbz)
1594 (let ((precision-flag (ecase precision
1595 (:single 0)
1596 (:double 1))))
1597 `(define-instruction ,name (segment &rest args)
1598 (:printer ,(if op-m-sbz
1599 'fp-unary-one-op
1600 'fp-unary)
1601 ((size ,precision-flag)
1602 (n ,n)
1603 (opc ,fn)))
1604 (:emitter
1605 (with-condition-defaulted (args (condition dest
1606 ,@(unless op-m-sbz
1607 '(op-m))))
1608 (emit-fp-dp-instruction segment
1609 (conditional-opcode condition)
1610 #b1110
1612 (low-bit-float-reg dest)
1616 (high-bits-float-reg dest)
1617 #b101
1618 ,precision-flag
1621 ,(if op-m-sbz
1623 '(low-bit-float-reg op-m))
1625 ,(if op-m-sbz
1627 '(high-bits-float-reg op-m))))))))
1629 (defmacro define-unary-fp-data-processing-instructions (root fn n &key op-m-sbz)
1630 `(progn
1631 (define-unary-fp-data-processing-instruction ,(symbolicate root 's) :single ,fn ,n
1632 :op-m-sbz ,op-m-sbz)
1633 (define-unary-fp-data-processing-instruction ,(symbolicate root 'd) :double ,fn ,n
1634 :op-m-sbz ,op-m-sbz)))
1636 (define-unary-fp-data-processing-instructions fcpy #b0000 0)
1637 (define-unary-fp-data-processing-instructions fabs #b0000 1)
1638 (define-unary-fp-data-processing-instructions fneg #b0001 0)
1639 (define-unary-fp-data-processing-instructions fsqrt #b0001 1)
1640 (define-unary-fp-data-processing-instructions fcmp #b0100 0)
1641 (define-unary-fp-data-processing-instructions fcmpe #b0100 1)
1642 (define-unary-fp-data-processing-instructions fcmpz #b0101 0 :op-m-sbz t)
1643 (define-unary-fp-data-processing-instructions fcmpez #b0101 1 :op-m-sbz t)
1644 (define-unary-fp-data-processing-instructions fuito #b1000 0)
1645 (define-unary-fp-data-processing-instructions fsito #b1000 1)
1646 (define-unary-fp-data-processing-instructions ftoui #b1100 0)
1647 (define-unary-fp-data-processing-instructions ftouiz #b1100 1)
1648 (define-unary-fp-data-processing-instructions ftosi #b1101 0)
1649 (define-unary-fp-data-processing-instructions ftosiz #b1101 1)
1651 (define-unary-fp-data-processing-instruction fcvtds :single #b0111 1)
1652 (define-unary-fp-data-processing-instruction fcvtsd :double #b0111 1)
1654 ;;; Load/Store Float Instructions
1656 (define-bitfield-emitter emit-fp-ls-instruction 32
1657 (byte 4 28) ; cond
1658 (byte 3 25) ; #b110
1659 (byte 1 24) ; P
1660 (byte 1 23) ; U
1661 (byte 1 22) ; D
1662 (byte 1 21) ; W
1663 (byte 1 20) ; L
1664 (byte 4 16) ; Rn
1665 (byte 4 12) ; Fd
1666 (byte 3 9) ; #b101
1667 (byte 1 8) ; double/single precission
1668 (byte 8 0)) ; offset
1670 ;; Define a load/store multiple floating point instruction. PRECISION is
1671 ;; :SINGLE for single precision values and :DOUBLE for double precision values.
1672 ;; DIRECTION has to be either :LOAD or :STORE.
1673 ;; If INC-OFFSET is true, the offset part of the instruction will be incremented by 1
1674 ;; indicating in the double case a load/store unknown instruction.
1675 (defmacro define-load-store-multiple-fp-instruction (name precision direction &optional inc-offset)
1676 (let ((precision-flag (ecase precision
1677 (:single 0)
1678 (:double 1)))
1679 (direction-flag (ecase direction
1680 (:load 1)
1681 (:store 0))))
1682 `(define-instruction ,name (segment &rest args)
1683 (:emitter
1684 (with-condition-defaulted (args (condition address base-reg reg-count))
1685 (let* ((mode (cond
1686 ((consp address)
1687 (cdr address))
1688 (t :unindexed)))
1689 (p (ecase mode
1690 ((:unindexed :increment) 0)
1691 ((:decrement) 1)))
1692 (u (ecase mode
1693 ((:unindexed :increment) 1)
1694 ((:decrement) 0)))
1695 (w (ecase mode
1696 ((:unindexed) 0)
1697 ((:increment :decrement) 1))))
1698 (emit-fp-ls-instruction segment
1699 (conditional-opcode condition)
1700 #b110
1703 (low-bit-float-reg base-reg)
1705 ,direction-flag
1706 (tn-offset address)
1707 (high-bits-float-reg base-reg)
1708 #b101
1709 ,precision-flag
1710 ,(ecase precision
1711 (:single 'reg-count)
1712 (:double `(+ (* 2 reg-count)
1713 ,(if inc-offset 1 0)))))))))))
1715 ;; multiple single precision
1716 (define-load-store-multiple-fp-instruction fstms :single :store)
1717 (define-load-store-multiple-fp-instruction fldms :single :load)
1718 ;; multiple double precision
1719 (define-load-store-multiple-fp-instruction fstmd :double :store)
1720 (define-load-store-multiple-fp-instruction fldmd :double :load)
1721 ;; multiple double precision registers of unknown content (needs up to 2 * reg-count + 1 words of space)
1722 (define-load-store-multiple-fp-instruction fstmx :double :store t)
1723 (define-load-store-multiple-fp-instruction fldmx :double :load t)
1725 ;; KLUDGE: this group of pseudo-instructions are fragile (no error
1726 ;; handling for the various ways to mis-use them), have no support for
1727 ;; predication, and use the somewhat-broken interface for the
1728 ;; load-store-multiple-fp instructions above.
1729 (define-instruction-macro load-complex-single (dest memory-operand)
1730 `(inst fldms (memory-operand-base ,memory-operand) ,dest 2))
1731 (define-instruction-macro load-complex-double (dest memory-operand)
1732 `(inst fldmd (memory-operand-base ,memory-operand) ,dest 2))
1733 (define-instruction-macro store-complex-single (src memory-operand)
1734 `(inst fstms (memory-operand-base ,memory-operand) ,src 2))
1735 (define-instruction-macro store-complex-double (src memory-operand)
1736 `(inst fstmd (memory-operand-base ,memory-operand) ,src 2))
1738 ;; Define a load/store one floating point instruction. PRECISION is
1739 ;; :SINGLE for single precision values and :DOUBLE for double precision values.
1740 ;; DIRECTION has to be either :LOAD or :STORE.
1741 (defmacro define-load-store-one-fp-instruction (name precision direction)
1742 (let ((precision-flag (ecase precision
1743 (:single 0)
1744 (:double 1)))
1745 (direction-flag (ecase direction
1746 (:load 1)
1747 (:store 0))))
1748 `(define-instruction ,name (segment &rest args)
1749 (:emitter
1750 (with-condition-defaulted (args (condition float-reg memory-operand))
1751 (let ((base (memory-operand-base memory-operand))
1752 (offset (memory-operand-offset memory-operand))
1753 (direction (memory-operand-direction memory-operand)))
1754 (aver (eq (memory-operand-mode memory-operand) :offset))
1755 (aver (and (integerp offset)
1756 (zerop (logand offset 3))))
1757 ;; FIXME: Should support LABEL bases.
1758 (aver (tn-p base))
1759 (emit-fp-ls-instruction segment
1760 (conditional-opcode condition)
1761 #b110
1763 (if (eq direction :up) 1 0)
1764 (low-bit-float-reg float-reg)
1766 ,direction-flag
1767 (tn-offset base)
1768 (high-bits-float-reg float-reg)
1769 #b101
1770 ,precision-flag
1771 (ash offset -2))))))))
1773 (define-load-store-one-fp-instruction fsts :single :store)
1774 (define-load-store-one-fp-instruction flds :single :load)
1775 (define-load-store-one-fp-instruction fstd :double :store)
1776 (define-load-store-one-fp-instruction fldd :double :load)
1779 ;; single register transfer instructions
1781 (define-bitfield-emitter emit-fp-srt-instruction 32
1782 (byte 4 28) ; cond
1783 (byte 4 24) ; #b1110
1784 (byte 3 21) ; opc
1785 (byte 1 20) ; L
1787 (byte 4 16) ; Fn
1788 (byte 4 12) ; Rd
1789 (byte 3 9) ; #b101
1790 (byte 1 8) ; precision
1792 (byte 1 7) ; N
1793 (byte 7 0)) ; #b0010000
1795 (define-bitfield-emitter emit-conditional-instruction 32
1796 (byte 4 28) ; cond
1797 (byte 28 0)) ; op
1799 ;;; This has the same encoding as FMRX R15, FPSCR
1800 (define-instruction fmstat (segment &rest args)
1801 (:printer conditional
1802 ((op #xEF1FA10)))
1803 (:emitter
1804 (with-condition-defaulted (args (condition))
1805 (emit-conditional-instruction segment
1806 (conditional-opcode condition)
1807 #xEF1FA10))))
1809 (defun system-reg-encoding (float-reg)
1810 (ecase float-reg
1811 (:fpsid #b0000)
1812 (:fpscr #b0001)
1813 (:fpexc #b1000)))
1815 (defmacro define-single-reg-transfer-fp-instruction (name precision direction opcode &optional system-reg)
1816 (let ((precision-flag (ecase precision
1817 (:single 0)
1818 (:double 1)))
1819 (direction-flag (ecase direction
1820 (:to-arm 1)
1821 (:from-arm 0))))
1822 `(define-instruction ,name (segment &rest args)
1823 (:printer ,(if system-reg
1824 'fp-srt-sys
1825 'fp-srt)
1826 ((opc ,opcode)
1827 (l ,direction-flag)
1828 (size ,precision-flag))
1829 ',(if (eq direction :to-arm)
1830 '(:name cond :tab rd ", " fn)
1831 '(:name cond :tab fn ", " rd)))
1832 (:emitter
1833 (with-condition-defaulted (args (condition ,@(if (eq direction :to-arm)
1834 '(arm-reg float-reg)
1835 '(float-reg arm-reg))))
1836 (emit-fp-srt-instruction segment
1837 (conditional-opcode condition)
1838 #b1110
1839 ,opcode
1840 ,direction-flag
1841 ,(if system-reg
1842 '(system-reg-encoding float-reg)
1843 '(high-bits-float-reg float-reg))
1844 (tn-offset arm-reg)
1845 #b101
1846 ,precision-flag
1847 ,(if system-reg
1849 '(low-bit-float-reg float-reg))
1850 #b0010000))))))
1852 (define-single-reg-transfer-fp-instruction fmsr :single :from-arm #b000)
1853 (define-single-reg-transfer-fp-instruction fmrs :single :to-arm #b000)
1854 (define-single-reg-transfer-fp-instruction fmdlr :double :from-arm #b000)
1855 (define-single-reg-transfer-fp-instruction fmrdl :double :to-arm #b000)
1856 (define-single-reg-transfer-fp-instruction fmdhr :double :from-arm #b001)
1857 (define-single-reg-transfer-fp-instruction fmrdh :double :to-arm #b001)
1858 (define-single-reg-transfer-fp-instruction fmxr :single :from-arm #b111 t)
1859 (define-single-reg-transfer-fp-instruction fmrx :single :to-arm #b111 t)
1861 (define-bitfield-emitter emit-fp-trt-instruction 32
1862 (byte 4 28) ; cond
1863 (byte 7 21) ; #b1100010
1864 (byte 1 20) ; L
1865 (byte 4 16) ; Rn
1866 (byte 4 12) ; Rd
1867 (byte 3 9) ; #b101
1868 (byte 1 8) ; precision
1869 (byte 2 6) ; #b00
1870 (byte 1 5) ; M
1871 (byte 1 4) ; #b1
1872 (byte 4 0)) ; Fm
1874 (defmacro define-two-reg-transfer-fp-instruction (name precision direction)
1875 (let ((precision-flag (ecase precision
1876 (:single 0)
1877 (:double 1)))
1878 (direction-flag (ecase direction
1879 (:to-arm 1)
1880 (:from-arm 0))))
1881 `(define-instruction ,name (segment &rest args)
1882 (:printer fp-trt
1883 ((l ,direction-flag)
1884 (size ,precision-flag))
1885 ',(if (eq direction :to-arm)
1886 '(:name cond :tab rd ", " rn ", " fm)
1887 '(:name cond :tab fm ", " rd ", " rn )))
1888 (:emitter
1889 (with-condition-defaulted (args (condition ,@(if (eq direction :to-arm)
1890 '(arm-reg-1 arm-reg-2 float-reg)
1891 '(float-reg arm-reg-1 arm-reg-2))))
1892 (emit-fp-trt-instruction segment
1893 (conditional-opcode condition)
1894 #b1100010
1895 ,direction-flag
1896 (tn-offset arm-reg-2)
1897 (tn-offset arm-reg-1)
1898 #b101
1899 ,precision-flag
1900 #b00
1901 (low-bit-float-reg float-reg)
1903 (high-bits-float-reg float-reg)))))))
1905 (define-two-reg-transfer-fp-instruction fmsrr :single :from-arm)
1906 (define-two-reg-transfer-fp-instruction fmrrs :single :to-arm)
1907 (define-two-reg-transfer-fp-instruction fmdrr :double :from-arm)
1908 (define-two-reg-transfer-fp-instruction fmrrd :double :to-arm)