Restore buildability of #+ultrafutex
[sbcl.git] / src / compiler / arm / insts.lisp
blob3afb611888ffd1793b9e577fa7ef98228aabbba6
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 '(conditional-opcode negate-condition 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)))
26 (defconstant-eqx +conditions+
27 '((:eq . 0)
28 (:ne . 1)
29 (:cs . 2) (:hs . 2)
30 (:cc . 3) (:lo . 3)
31 (:mi . 4)
32 (:pl . 5)
33 (:vs . 6)
34 (:vc . 7)
35 (:hi . 8)
36 (:ls . 9)
37 (:ge . 10)
38 (:lt . 11)
39 (:gt . 12)
40 (:le . 13)
41 (:al . 14))
42 #'equal)
43 (defconstant-eqx +condition-name-vec+
44 (let ((vec (make-array 16 :initial-element nil)))
45 (dolist (cond +conditions+ vec)
46 (when (null (aref vec (cdr cond)))
47 (setf (aref vec (cdr cond)) (car cond)))))
48 #'equalp)
50 (defun conditional-opcode (condition)
51 (cdr (assoc condition +conditions+ :test #'eq)))
52 (defun negate-condition (name)
53 (let ((code (logxor 1 (conditional-opcode name))))
54 (aref +condition-name-vec+ code)))
56 ;;;; disassembler field definitions
58 (define-arg-type condition-code :printer #'print-condition)
60 (define-arg-type reg :printer #'print-reg)
62 (define-arg-type float-reg :printer #'print-float-reg)
64 (define-arg-type float-sys-reg :printer #'print-float-sys-reg)
66 (define-arg-type shift-type :printer #'print-shift-type)
68 (define-arg-type immediate-shift :printer #'print-immediate-shift)
70 (define-arg-type shifter-immediate :printer #'print-shifter-immediate)
72 (define-arg-type relative-label
73 :sign-extend t
74 :use-label #'use-label-relative-label)
76 (define-arg-type load/store-immediate :printer #'print-load/store-immediate)
78 (define-arg-type load/store-register :printer #'print-load/store-register)
80 (define-arg-type msr-field-mask :printer #'print-msr-field-mask)
82 ;;;; disassembler instruction format definitions
84 (define-instruction-format (dp-shift-immediate 32
85 :default-printer
86 '(:name cond :tab rd ", " rn ", " rm shift))
87 (cond :field (byte 4 28) :type 'condition-code)
88 (opcode-8 :field (byte 8 20))
89 (rn :field (byte 4 16) :type 'reg)
90 (rd :field (byte 4 12) :type 'reg)
91 (shift :fields (list (byte 5 7) (byte 2 5)) :type 'immediate-shift)
92 (register-shift-p :field (byte 1 4) :value 0)
93 (rm :field (byte 4 0) :type 'reg))
95 (define-instruction-format
96 (dp-shift-register 32
97 :default-printer
98 '(:name cond :tab rd ", " rn ", " rm ", " shift-type " " rs))
99 (cond :field (byte 4 28) :type 'condition-code)
100 (opcode-8 :field (byte 8 20))
101 (rn :field (byte 4 16) :type 'reg)
102 (rd :field (byte 4 12) :type 'reg)
103 (rs :field (byte 4 8) :type 'reg)
104 (multiply-p :field (byte 1 7) :value 0)
105 (shift-type :field (byte 2 5) :type 'shift-type)
106 (register-shift-p :field (byte 1 4) :value 1)
107 (rm :field (byte 4 0) :type 'reg))
109 (define-instruction-format (dp-immediate 32
110 :default-printer
111 '(:name cond :tab rd ", " rn ", #" immediate))
112 (cond :field (byte 4 28) :type 'condition-code)
113 (opcode-8 :field (byte 8 20))
114 (rn :field (byte 4 16) :type 'reg)
115 (rd :field (byte 4 12) :type 'reg)
116 (immediate :field (byte 12 0) :type 'shifter-immediate))
118 (define-instruction-format (branch 32 :default-printer '(:name cond :tab target))
119 (cond :field (byte 4 28) :type 'condition-code)
120 (opcode-4 :field (byte 4 24))
121 (target :field (byte 24 0) :type 'relative-label))
123 (define-instruction-format
124 (load/store-immediate 32
125 ;; FIXME: cond should come between LDR/STR and B.
126 :default-printer '(:name cond :tab rd ", [" rn load/store-offset))
127 (cond :field (byte 4 28) :type 'condition-code)
128 (opcode-3 :field (byte 3 25))
129 (load/store-offset :fields (list (byte 1 24)
130 (byte 1 23)
131 (byte 1 21)
132 (byte 12 0))
133 :type 'load/store-immediate)
134 (opcode-b :field (byte 1 22))
135 (opcode-l :field (byte 1 20))
136 (rn :field (byte 4 16) :type 'reg)
137 (rd :field (byte 4 12) :type 'reg))
139 (define-instruction-format
140 (load/store-register 32
141 ;; FIXME: cond should come between LDR/STR and B.
142 :default-printer '(:name cond :tab rd ", [" rn load/store-offset))
143 (cond :field (byte 4 28) :type 'condition-code)
144 (opcode-3 :field (byte 3 25))
145 (load/store-offset :fields (list (byte 1 24)
146 (byte 1 23)
147 (byte 1 21)
148 (byte 5 7) ;; shift_imm
149 (byte 2 5) ;; shift
150 (byte 4 0)) ;; Rm
151 :type 'load/store-register)
152 (opcode-b :field (byte 1 22))
153 (opcode-l :field (byte 1 20))
154 (opcode-0 :field (byte 1 4))
155 (rn :field (byte 4 16) :type 'reg)
156 (rd :field (byte 4 12) :type 'reg))
158 ;;; Not sure if we can coerce our disassembler to print anything resembling this:
159 ;;; <LDM|STM>{cond}<FD|ED|FA|EA|IA|IB|DA|DB> Rn{!},<Rlist>{^} where:
160 ;;; {cond} two-character condition mnemonic. See Table 4-2: Condition code
161 ;;; summary on page 4-5.
162 ;;; Rn is an expression evaluating to a valid register number
163 ;;; <Rlist> is a list of registers and register ranges enclosed in {} (For example,
164 ;;; {R0,R2-R7,R10}).
165 ;;; {!} if present requests write-back (W=1), otherwise W=0
166 ;;; {^} if present set S bit to load the CPSR along with the PC, or force transfer
167 ;;; of user bank when in privileged mode
168 ;;; not to mention the alternative mnemonics PUSH and POP
169 ;;; when using the native stack pointer as base register.
170 (define-instruction-format
171 ;; This is just to show something in the disassembly other than BYTE ...
172 (ldm/stm 32 :default-printer '(:name cond :tab bits ", " rn ", " reglist))
173 (cond :field (byte 4 28) :type 'condition-code)
174 (opcode-3 :field (byte 3 25))
175 (bits :field (byte 4 21)) ; complicated
176 (opcode-l :field (byte 1 20))
177 (rn :field (byte 4 16) :type 'reg)
178 (reglist :field (byte 16 0)
179 :printer (lambda (value stream dstate)
180 (declare (ignore dstate))
181 (format stream "{~{R~d~^,~}}"
182 (loop for i below 16
183 when (logbitp i value) collect i)))))
185 (define-instruction-format (swi 32
186 :default-printer '(:name cond :tab "#" swi-number))
187 (cond :field (byte 4 28) :type 'condition-code)
188 (opcode-4 :field (byte 4 24))
189 (swi-number :field (byte 24 0)))
191 (define-instruction-format (debug-trap 32 :default-printer '(:name :tab code))
192 (opcode-32 :field (byte 32 0))
193 ;; We use a prefilter in order to read trap codes in order to avoid
194 ;; encoding the code within the instruction body (requiring the use of
195 ;; a different trap instruction and a SIGILL handler) and in order to
196 ;; avoid attempting to include the code in the decoded instruction
197 ;; proper (requiring moving to a 40-bit instruction for disassembling
198 ;; trap codes, and being affected by endianness issues).
199 (code :prefilter (lambda (dstate) (read-suffix 8 dstate))
200 :reader debug-trap-code))
202 (define-instruction-format (msr-immediate 32
203 :default-printer
204 '(:name cond :tab field-mask ", #" immediate))
205 (cond :field (byte 4 28) :type 'condition-code)
206 (opcode-5 :field (byte 5 23) :value #b00110)
207 (field-mask :fields (list (byte 1 22) (byte 4 16)) :type 'msr-field-mask)
208 (opcode-2 :field (byte 2 20) :value #b10)
209 (sbo :field (byte 4 12) :value #b1111)
210 (immediate :field (byte 12 0) :type 'shifter-immediate))
212 (define-instruction-format (msr-register 32
213 :default-printer '(:name cond :tab field-mask ", " rm))
214 (cond :field (byte 4 28) :type 'condition-code)
215 (opcode-5 :field (byte 5 23) :value #b00010)
216 (field-mask :fields (list (byte 1 22) (byte 4 16)) :type 'msr-field-mask)
217 (opcode-2 :field (byte 2 20) :value #b10)
218 (sbo :field (byte 4 12) :value #b1111)
219 (sbz :field (byte 8 4) :value #b00000000)
220 (rm :field (byte 4 0) :type 'reg))
222 (define-instruction-format (multiply-dzsm 32
223 :default-printer '(:name cond :tab rd ", " rs ", " rm))
224 (cond :field (byte 4 28) :type 'condition-code)
225 (opcode-8 :field (byte 8 20))
226 (rd :field (byte 4 16) :type 'reg)
227 (sbz :field (byte 4 12) :value 0)
228 (rs :field (byte 4 8) :type 'reg)
229 (opcode-4 :field (byte 4 4))
230 (rm :field (byte 4 0) :type 'reg))
232 (define-instruction-format
233 (multiply-dnsm 32
234 :default-printer '(:name cond :tab rd ", " rs ", " rm ", " num))
235 (cond :field (byte 4 28) :type 'condition-code)
236 (opcode-8 :field (byte 8 20))
237 (rd :field (byte 4 16) :type 'reg)
238 (num :field (byte 4 12) :type 'reg)
239 (rs :field (byte 4 8) :type 'reg)
240 (opcode-4 :field (byte 4 4))
241 (rm :field (byte 4 0) :type 'reg))
243 (define-instruction-format
244 (multiply-ddsm 32
245 :default-printer '(:name cond :tab rdlo ", " rdhi ", " rs ", " rm))
246 (cond :field (byte 4 28) :type 'condition-code)
247 (opcode-8 :field (byte 8 20))
248 (rdhi :field (byte 4 16) :type 'reg)
249 (rdlo :field (byte 4 12) :type 'reg)
250 (rs :field (byte 4 8) :type 'reg)
251 (opcode-4 :field (byte 4 4))
252 (rm :field (byte 4 0) :type 'reg))
254 (define-instruction-format (branch-exchange 32
255 :default-printer '(:name cond :tab rm))
256 (cond :field (byte 4 28) :type 'condition-code)
257 (opcode-8 :field (byte 8 20))
258 (sbo :field (byte 12 8) :value #xFFF)
259 (opcode-4 :field (byte 4 4))
260 (rm :field (byte 4 0) :type 'reg))
262 (define-instruction-format (fp-binary 32
263 :default-printer '(:name cond :tab fd ", " fn ", " fm))
264 (cond :field (byte 4 28) :type 'condition-code)
265 (opc-1 :field (byte 4 24) :value #b1110)
266 (p :field (byte 1 23))
267 (q :field (byte 1 21))
268 (r :field (byte 1 20))
269 (s :field (byte 1 6))
270 (fn :fields (list (byte 1 8) (byte 4 16) (byte 1 7)) :type 'float-reg)
271 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
272 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
273 (opc-2 :field (byte 3 9) :value #b101)
274 (size :field (byte 1 8))
275 (opc-3 :field (byte 1 4) :value 0))
277 (define-instruction-format (fp-unary 32
278 :default-printer '(:name cond :tab fd ", " fm))
279 (cond :field (byte 4 28) :type 'condition-code)
280 (opc-1 :field (byte 5 23) :value #b11101)
281 (opc-2 :field (byte 2 20) :value #b11)
282 (opc :field (byte 4 16))
283 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
284 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
285 (opc-3 :field (byte 3 9) :value #b101)
286 (size :field (byte 1 8))
287 (n :field (byte 1 7))
288 (s :field (byte 1 6) :value 1)
289 (opc-4 :field (byte 1 4) :value 0))
291 (define-instruction-format (fp-unary-one-op 32
292 :default-printer '(:name cond :tab fd))
293 (cond :field (byte 4 28) :type 'condition-code)
294 (opc-1 :field (byte 5 23) :value #b11101)
295 (opc-2 :field (byte 2 20) :value #b11)
296 (opc :field (byte 4 16))
297 (fd :fields (list (byte 1 8) (byte 4 12) (byte 1 22)) :type 'float-reg)
298 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
299 (opc-3 :field (byte 3 9) :value #b101)
300 (size :field (byte 1 8))
301 (n :field (byte 1 7))
302 (s :field (byte 1 6) :value 1)
303 (sbz :field (byte 6 0) :value 0))
305 (define-instruction-format (fp-srt 32)
306 (cond :field (byte 4 28) :type 'condition-code)
307 (opc-1 :field (byte 4 24) :value #b1110)
308 (opc :field (byte 3 21))
309 (l :field (byte 1 20))
310 (fn :fields (list (byte 1 8) (byte 1 7) (byte 4 16)) :type 'float-reg)
311 (rd :field (byte 4 12) :type 'reg)
312 (opc-3 :field (byte 3 9) :value #b101)
313 (size :field (byte 1 8))
314 (opc-4 :field (byte 7 0) :value #b0010000))
316 (define-instruction-format (fp-srt-sys 32)
317 (cond :field (byte 4 28) :type 'condition-code)
318 (opc-1 :field (byte 4 24) :value #b1110)
319 (opc :field (byte 3 21))
320 (l :field (byte 1 20))
321 (fn :field (byte 4 16) :type 'float-sys-reg)
322 (rd :field (byte 4 12) :type 'reg)
323 (opc-3 :field (byte 3 9) :value #b101)
324 (opc-4 :field (byte 8 0) :value #b00010000))
326 (define-instruction-format (fp-trt 32)
327 (cond :field (byte 4 28) :type 'condition-code)
328 (opc-1 :field (byte 7 21) :value #b1100010)
329 (l :field (byte 1 20))
330 (rn :field (byte 4 16) :type 'reg)
331 (rd :field (byte 4 12) :type 'reg)
332 (opc-2 :field (byte 3 9) :value #b101)
333 (size :field (byte 1 8))
334 (opc-3 :field (byte 2 6) :value 0)
335 (fm :fields (list (byte 1 8) (byte 4 0) (byte 1 5)) :type 'float-reg)
336 (opc-4 :field (byte 1 4) :value 1))
338 (define-instruction-format (conditional 32 :default-printer '(:name cond))
339 (cond :field (byte 4 28) :type 'condition-code)
340 (op :field (byte 28 0)))
342 ;;;; primitive emitters
344 ;(define-bitfield-emitter emit-word 16
345 ; (byte 16 0))
347 (define-bitfield-emitter emit-word 32
348 (byte 32 0))
350 ;;;; miscellaneous hackery
352 (defun register-p (thing)
353 (and (tn-p thing)
354 (eq (sb-name (sc-sb (tn-sc thing))) 'registers)))
356 (defmacro with-condition-defaulted ((argvar arglist) &body body)
357 (let ((internal-emitter (gensym)))
358 `(flet ((,internal-emitter ,arglist
359 ,@body))
360 (if (assoc (car ,argvar) +conditions+)
361 (apply #',internal-emitter ,argvar)
362 (apply #',internal-emitter :al ,argvar)))))
364 (define-instruction byte (segment byte)
365 (:emitter
366 (emit-byte segment byte)))
368 ;(define-instruction word (segment word)
369 ; (:emitter
370 ; (emit-word segment word)))
372 (define-instruction word (segment word)
373 (:emitter
374 (etypecase word
375 (fixup
376 (note-fixup segment :absolute word)
377 (emit-word segment 0))
378 (integer
379 (emit-word segment word)))))
381 (defun emit-header-data (segment type)
382 (emit-back-patch segment
384 (lambda (segment posn)
385 (emit-word segment
386 (logior type
387 (ash (+ posn
388 (component-header-length))
389 (- n-widetag-bits
390 word-shift)))))))
392 (define-instruction simple-fun-header-word (segment)
393 (:emitter
394 (emit-header-data segment simple-fun-widetag)))
396 (define-instruction lra-header-word (segment)
397 (:emitter
398 (emit-header-data segment return-pc-widetag)))
400 ;;;; Addressing mode 1 support
402 ;;; Addressing mode 1 has some 11 formats. These are immediate,
403 ;;; register, and nine shift/rotate functions based on one or more
404 ;;; registers. As the mnemonics used for these functions are not
405 ;;; currently used, we simply define them as constructors for a
406 ;;; shifter-operand structure, similar to the make-ea function in the
407 ;;; x86 backend.
409 (defstruct shifter-operand
410 register
411 function-code
412 operand)
414 (defun lsl (register operand)
415 (aver (register-p register))
416 (aver (or (register-p operand)
417 (typep operand '(integer 0 31))))
419 (make-shifter-operand :register register :function-code 0 :operand operand))
421 (defun lsr (register operand)
422 (aver (register-p register))
423 (aver (or (register-p operand)
424 (typep operand '(integer 1 32))))
426 (make-shifter-operand :register register :function-code 1 :operand operand))
428 (defun asr (register operand)
429 (aver (register-p register))
430 (aver (or (register-p operand)
431 (typep operand '(integer 1 32))))
433 (make-shifter-operand :register register :function-code 2 :operand operand))
435 (defun ror (register operand)
436 ;; ROR is a special case: the encoding for ROR with an immediate
437 ;; shift of 32 (0) is actually RRX.
438 (aver (register-p register))
439 (aver (or (register-p operand)
440 (typep operand '(integer 1 31))))
442 (make-shifter-operand :register register :function-code 3 :operand operand))
444 (defun rrx (register)
445 ;; RRX is a special case: it is encoded as ROR with an immediate
446 ;; shift of 32 (0), and has no operand.
447 (aver (register-p register))
448 (make-shifter-operand :register register :function-code 3 :operand 0))
450 (define-condition cannot-encode-immediate-operand (error)
451 ((value :initarg :value)))
453 (defun encodable-immediate (operand)
454 ;; 32-bit immediate data is encoded as an 8-bit immediate data value
455 ;; and a 4-bit immediate shift count. The actual value is the
456 ;; immediate data rotated right by a number of bits equal to twice
457 ;; the shift count. Note that this means that there are a limited
458 ;; number of valid immediate integers and that some integers have
459 ;; multiple possible encodings. In the case of multiple encodings,
460 ;; the correct one to use is the one with the lowest shift count.
462 ;; XXX: Is it possible to determine the correct encoding in constant
463 ;; time, rather than time proportional to the final shift count? Is
464 ;; it possible to determine if a given integer is valid without
465 ;; attempting to encode it? Are such solutions cheaper (either time
466 ;; or spacewise) than simply attempting to encode it?
467 (labels ((try-immediate-encoding (value shift)
468 (unless (<= 0 shift 15)
469 (return-from encodable-immediate))
470 (if (typep value '(unsigned-byte 8))
471 (dpb shift (byte 4 8) value)
472 (try-immediate-encoding (dpb value (byte 30 2)
473 (ldb (byte 2 30) value))
474 (1+ shift)))))
475 (try-immediate-encoding operand 0)))
477 (defun encode-shifter-immediate (operand)
479 (encodable-immediate operand)
480 (error 'cannot-encode-immediate-operand :value operand)))
482 (defun encode-shifter-operand (operand)
483 (etypecase operand
484 (integer
485 (dpb 1 (byte 1 25) (encode-shifter-immediate operand)))
488 (cond
489 ((eq 'registers (sb-name (sc-sb (tn-sc operand))))
490 ;; For those wondering, this is LSL immediate for 0 bits.
491 (tn-offset operand))
493 ((eq 'null (sc-name (tn-sc operand)))
494 null-offset)
496 (t (error "Don't know how to encode TN ~A as a SHIFTER-OPERAND" operand))))
498 (shifter-operand
499 (let ((Rm (tn-offset (shifter-operand-register operand)))
500 (shift-code (shifter-operand-function-code operand))
501 (shift-amount (shifter-operand-operand operand)))
502 (etypecase shift-amount
503 (integer
504 (dpb shift-amount (byte 5 7)
505 (dpb shift-code (byte 2 5)
506 Rm)))
508 (dpb (tn-offset shift-amount) (byte 4 8)
509 (dpb shift-code (byte 2 5)
510 (dpb 1 (byte 1 4)
511 Rm)))))))))
513 (defun lowest-set-bit-index (integer-value)
514 (max 0 (1- (integer-length (logand integer-value (- integer-value))))))
516 ;; FIXME: it would be idiomatic to use (DEFINE-INSTRUCTION-MACRO COMPOSITE ...)
517 ;; instead of exporting another instruction-generating macro into SB-VM.
518 ;; An invocation would resemble (INST COMPOSITE {ADD|SUB|whatever| ARGS ...)
519 (defmacro composite-immediate-instruction (op r x y &key fixnumize neg-op invert-y invert-r single-op-op first-op first-no-source temporary)
520 ;; Successively applies 8-bit wide chunks of Y to X using OP storing the result in R.
522 ;; If FIXNUMIZE is true, Y is fixnumized before being used.
523 ;; If NEG-OP is given and Y is negative, NEG-OP is used instead of OP.
524 ;; If INVERT-Y is given LOGNOT is applied to Y before it being used (but after possibly
525 ;; being fixnumized.
526 ;; If INVERT-R is given R is bit wise inverted at the end.
527 ;; If SINGLE-OP-OP is given and (possibly fixnumized) Y fits into a single ARM immediate
528 ;; it is used for a single operation instead of OP.
529 ;; If FIRST-OP is given, it is used in the first iteration instead of OP.
530 ;; If FIRST-NO-SOURCE is given, there will be ne source register (X) in the first iteration.
531 ;; If TEMPORARY is given, it should be a non-descriptor register
532 ;; used for the accumulation of a temporary non-descriptor. Only makes sense with INVERT-R
533 (when temporary
534 (aver invert-r))
535 (let ((bytespec (gensym "bytespec"))
536 (value (gensym "value"))
537 (transformed (gensym "transformed"))
538 (acc (gensym "acc")))
539 (labels ((instruction (source-reg op neg-op &optional no-source)
540 `(,@(if neg-op
541 `((if (< ,y 0)
542 (inst ,neg-op ,acc ,@(when (not no-source)`(,source-reg))
543 (mask-field ,bytespec ,value))
544 (inst ,op ,acc ,@(when (not no-source) `(,source-reg))
545 (mask-field ,bytespec ,value))))
546 `((inst ,op ,acc ,@(when (not no-source) `(,source-reg))
547 (mask-field ,bytespec ,value))))
548 (setf (ldb ,bytespec ,value) 0)))
549 (composite ()
550 `((let ((,bytespec (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))))
551 ,@(instruction x (or first-op op) neg-op first-no-source))
552 (do ((,bytespec (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))
553 (byte 8 (logandc1 1 (lowest-set-bit-index ,value)))))
554 ((zerop ,value))
555 ,@(instruction acc op neg-op))
556 ,@(when invert-r
557 `((inst mvn ,r ,acc))))))
558 `(let* ((,transformed ,(if fixnumize
559 `(fixnumize ,y)
560 `,y))
561 (,value (ldb (byte 32 0)
562 ,@(if neg-op
563 `((if (< ,transformed 0) (- ,transformed) ,transformed))
564 (if invert-y
565 `((lognot ,transformed))
566 `(,transformed)))))
567 (,acc (or ,temporary ,r)))
568 ,@(if single-op-op
569 `((if (encodable-immediate ,transformed)
570 (inst ,single-op-op ,r ,x ,transformed)
571 (progn ,@(composite))))
572 (composite))))))
575 ;;;; Addressing mode 2 support
577 ;;; Addressing mode 2 ostensibly has 9 formats. These are formed from
578 ;;; a cross product of three address calculations and three base
579 ;;; register writeback modes. As one of the address calculations is a
580 ;;; scaled register calculation identical to the mode 1 register shift
581 ;;; by constant, we reuse the shifter-operand structure and its public
582 ;;; constructors.
584 (defstruct memory-operand
585 base
586 offset
587 direction
588 mode)
590 ;;; The @ macro is used to encode a memory addressing mode. The
591 ;;; parameters for the base form are a base register, an optional
592 ;;; offset (either an integer, a register tn or a shifter-operand
593 ;;; structure with a constant shift amount, optionally within a unary
594 ;;; - form), and a base register writeback mode (either :offset,
595 ;;; :pre-index, or :post-index). The alternative form uses a label as
596 ;;; the base register, and accepts only (optionally negated) integers
597 ;;; as offsets, and requires a mode of :offset.
598 (defun %@ (base offset direction mode)
599 (when (label-p base)
600 (aver (eq mode :offset))
601 (aver (integerp offset)))
603 (when (shifter-operand-p offset)
604 (aver (integerp (shifter-operand-operand offset))))
606 ;; Fix up direction with negative offsets.
607 (when (and (not (label-p base))
608 (integerp offset)
609 (< offset 0))
610 (setf offset (- offset))
611 (setf direction (if (eq direction :up) :down :up)))
613 (make-memory-operand :base base :offset offset
614 :direction direction :mode mode))
616 (defmacro @ (base &optional (offset 0) (mode :offset))
617 (let* ((direction (if (and (consp offset)
618 (eq (car offset) '-)
619 (null (cddr offset)))
620 :down
621 :up))
622 (offset (if (eq direction :down) (cadr offset) offset)))
623 `(%@ ,base ,offset ,direction ,mode)))
625 ;;;; Data-processing instructions
627 ;;; Data processing instructions have a 4-bit opcode field and a 1-bit
628 ;;; "S" field for updating condition bits. They are adjacent, so we
629 ;;; roll them into one 5-bit field for convenience.
631 (define-bitfield-emitter emit-dp-instruction 32
632 (byte 4 28) (byte 2 26) (byte 1 25) (byte 5 20)
633 (byte 4 16) (byte 4 12) (byte 12 0))
635 ;;; There are 16 data processing instructions, with a breakdown as
636 ;;; follows:
638 ;;; 1.) Two "move" instructions, with no "source" operand (they have
639 ;;; destination and shifter operands only).
641 ;;; 2.) Four "test" instructions, with no "destination" operand.
642 ;;; These instructions always have their "S" bit set, though it
643 ;;; is not specified in their mnemonics.
645 ;;; 3.) Ten "normal" instructions, with all three operands.
647 ;;; Aside from this, the instructions all have a regular encoding, so
648 ;;; we can use a single macro to define them.
650 (defmacro define-data-processing-instruction (instruction opcode dest-p src-p)
651 `(define-instruction ,instruction (segment &rest args)
652 (:printer dp-shift-immediate ((opcode-8 ,opcode)
653 ,@(unless dest-p '((rd 0)))
654 ,@(unless src-p '((rn 0))))
655 ,@(cond
656 ((not dest-p)
657 '('(:name cond :tab rn ", " rm shift)))
658 ((not src-p)
659 '('(:name cond :tab rd ", " rm shift)))))
660 (:printer dp-shift-register ((opcode-8 ,opcode)
661 ,@(unless dest-p '((rd 0)))
662 ,@(unless src-p '((rn 0))))
663 ,@(cond
664 ((not dest-p)
665 '('(:name cond :tab rn ", " rm ", " shift-type " " rs)))
666 ((not src-p)
667 '('(:name cond :tab rd ", " rm ", " shift-type " " rs)))))
668 (:printer dp-immediate ((opcode-8 ,(logior opcode #x20))
669 ,@(unless dest-p '((rd 0)))
670 ,@(unless src-p '((rn 0))))
671 ,@(cond
672 ((not dest-p)
673 '('(:name cond :tab rn ", " immediate)))
674 ((not src-p)
675 '('(:name cond :tab rd ", " immediate)))))
676 (:emitter
677 (with-condition-defaulted (args (condition ,@(if dest-p '(dest))
678 ,@(if src-p '(src))
679 shifter-operand))
680 ,(if dest-p '(aver (register-p dest)))
681 ,(if src-p '(aver (register-p src)))
682 (let ((shifter-operand (encode-shifter-operand shifter-operand)))
683 (emit-dp-instruction segment
684 (conditional-opcode condition)
686 (ldb (byte 1 25) shifter-operand)
687 ,opcode
688 ,(if src-p '(tn-offset src) 0)
689 ,(if dest-p '(tn-offset dest) 0)
690 (ldb (byte 12 0) shifter-operand)))))))
692 (define-data-processing-instruction and #x00 t t)
693 (define-data-processing-instruction ands #x01 t t)
694 (define-data-processing-instruction eor #x02 t t)
695 (define-data-processing-instruction eors #x03 t t)
696 (define-data-processing-instruction sub #x04 t t)
697 (define-data-processing-instruction subs #x05 t t)
698 (define-data-processing-instruction rsb #x06 t t)
699 (define-data-processing-instruction rsbs #x07 t t)
700 (define-data-processing-instruction add #x08 t t)
701 (define-data-processing-instruction adds #x09 t t)
702 (define-data-processing-instruction adc #x0a t t)
703 (define-data-processing-instruction adcs #x0b t t)
704 (define-data-processing-instruction sbc #x0c t t)
705 (define-data-processing-instruction sbcs #x0d t t)
706 (define-data-processing-instruction rsc #x0e t t)
707 (define-data-processing-instruction rscs #x0f t t)
708 (define-data-processing-instruction orr #x18 t t)
709 (define-data-processing-instruction orrs #x19 t t)
710 (define-data-processing-instruction bic #x1c t t)
711 (define-data-processing-instruction bics #x1d t t)
713 (define-data-processing-instruction tst #x11 nil t)
714 (define-data-processing-instruction teq #x13 nil t)
715 (define-data-processing-instruction cmp #x15 nil t)
716 (define-data-processing-instruction cmn #x17 nil t)
718 (define-data-processing-instruction mov #x1a t nil)
719 (define-data-processing-instruction movs #x1b t nil)
720 (define-data-processing-instruction mvn #x1e t nil)
721 (define-data-processing-instruction mvns #x1f t nil)
723 (define-instruction-format (movw-format 32
724 :default-printer '(:name :tab rd ", #" immediate))
725 (cond :field (byte 4 28) :type 'condition-code)
726 (opcode-8 :field (byte 8 20))
727 (immediate :fields (list (byte 4 16) (byte 12 0))
728 :prefilter (lambda (dstate high low)
729 (declare (ignore dstate))
730 (logior (ash high 12) low)))
731 (rd :field (byte 4 12) :type 'reg))
733 (macrolet ((mov-imm-16 (segment rd imm half)
734 `(emit-dp-instruction ,segment 14 #b00 #b1
735 ,(ecase half
736 (:low #b10000)
737 (:high #b10100))
738 (ldb (byte 4 12) ,imm)
739 (tn-offset ,rd)
740 (ldb (byte 12 0) ,imm))))
741 (define-instruction movw (segment rd imm) ; move wide (zero-extend)
742 (:printer movw-format ((opcode-8 #b00110000)))
743 (:emitter (mov-imm-16 segment rd imm :low)))
744 (define-instruction movt (segment rd imm) ; move top bits (and keep bottom)
745 (:printer movw-format ((opcode-8 #b00110100)))
746 (:emitter (mov-imm-16 segment rd imm :high))))
748 ;;;; Exception-generating instructions
750 ;;; There are two exception-generating instructions. One, BKPT, is
751 ;;; ostensibly used as a breakpoint instruction, and to communicate
752 ;;; with debugging hardware. The other, SWI, is intended for use as a
753 ;;; system call interface. We need both because, at least on some
754 ;;; platforms, the only breakpoint trap that works properly is a
755 ;;; syscall.
757 (define-bitfield-emitter emit-swi-instruction 32
758 (byte 4 28) (byte 4 24) (byte 24 0))
760 (define-instruction swi (segment &rest args)
761 (:printer swi ((opcode-4 #b1111)))
762 (:emitter
763 (with-condition-defaulted (args (condition code))
764 (emit-swi-instruction segment
765 (conditional-opcode condition)
766 #b1111 code))))
768 (define-bitfield-emitter emit-bkpt-instruction 32
769 (byte 4 28) (byte 8 20) (byte 12 8) (byte 4 4) (byte 4 0))
771 (define-instruction bkpt (segment code)
772 (:emitter
773 (emit-bkpt-instruction segment #b1110 #b00010010
774 (ldb (byte 12 4) code)
775 #b0111
776 (ldb (byte 4 0) code))))
778 ;;; It turns out that the Linux kernel decodes this particular
779 ;;; officially undefined instruction as a single-instruction SIGTRAP
780 ;;; generation instruction, or breakpoint.
781 (define-instruction debug-trap (segment)
782 (:printer debug-trap ((opcode-32 #+linux #xe7f001f0
783 #+(or netbsd openbsd) #xe7ffdefe))
784 :default :control #'debug-trap-control)
785 (:emitter
786 (emit-word segment #+linux #xe7f001f0 #+(or netbsd openbsd) #xe7ffdefe)))
788 ;;;; Miscellaneous arithmetic instructions
790 (define-bitfield-emitter emit-clz-instruction 32
791 (byte 4 28) (byte 12 16) (byte 4 12) (byte 8 4) (byte 4 0))
793 (define-instruction clz (segment &rest args)
794 (:printer dp-shift-register ((opcode-8 #b00010110)
795 (rn #b1111)
796 (rs #b1111)
797 (shift-type #b00))
798 '(:name cond :tab rd ", " rm))
799 (:emitter
800 (with-condition-defaulted (args (condition dest src))
801 (aver (register-p dest))
802 (aver (register-p src))
803 (emit-clz-instruction segment (conditional-opcode condition)
804 #b000101101111
805 (tn-offset dest)
806 #b11110001
807 (tn-offset src)))))
809 ;;;; Branch instructions
811 (define-bitfield-emitter emit-branch-instruction 32
812 (byte 4 28) (byte 4 24) (byte 24 0))
814 (defun emit-branch-back-patch (segment condition opcode dest)
815 (emit-back-patch segment 4
816 (lambda (segment posn)
817 (emit-branch-instruction segment
818 (conditional-opcode condition)
819 opcode
820 (ldb (byte 24 2)
821 (- (label-position dest)
822 (+ posn 8)))))))
824 (define-instruction b (segment &rest args)
825 (:printer branch ((opcode-4 #b1010)))
826 (:emitter
827 (with-condition-defaulted (args (condition dest))
828 (aver (label-p dest))
829 (emit-branch-back-patch segment condition #b1010 dest))))
831 (define-instruction bl (segment &rest args)
832 (:printer branch ((opcode-4 #b1011)))
833 (:emitter
834 (with-condition-defaulted (args (condition dest))
835 (aver (label-p dest))
836 (emit-branch-back-patch segment condition #b1011 dest))))
838 (define-bitfield-emitter emit-branch-exchange-instruction 32
839 (byte 4 28) (byte 8 20) (byte 4 16) (byte 4 12)
840 (byte 4 8) (byte 4 4) (byte 4 0))
842 (define-instruction bx (segment &rest args)
843 (:printer branch-exchange ((opcode-8 #b00010010)
844 (opcode-4 #b0001)))
845 (:emitter
846 (with-condition-defaulted (args (condition dest))
847 (aver (register-p dest))
848 (emit-branch-exchange-instruction segment
849 (conditional-opcode condition)
850 #b00010010 #b1111 #b1111
851 #b1111 #b0001 (tn-offset dest)))))
853 (define-instruction blx (segment &rest args)
854 (:printer branch-exchange ((opcode-8 #b00010010)
855 (opcode-4 #b0011)))
856 (:emitter
857 (with-condition-defaulted (args (condition dest))
858 (aver (register-p dest))
859 (emit-branch-exchange-instruction segment
860 (conditional-opcode condition)
861 #b00010010 #b1111 #b1111
862 #b1111 #b0011 (tn-offset dest)))))
864 ;;;; Semaphore instructions
866 (defun emit-semaphore-instruction (segment opcode condition dest value address)
867 (aver (register-p dest))
868 (aver (register-p value))
869 (aver (memory-operand-p address))
870 (aver (zerop (memory-operand-offset address)))
871 (aver (eq :offset (memory-operand-mode address)))
872 (emit-dp-instruction segment (conditional-opcode condition)
873 #b00 0 opcode (tn-offset (memory-operand-base address))
874 (tn-offset dest)
875 (dpb #b1001 (byte 4 4) (tn-offset value))))
877 (define-instruction swp (segment &rest args)
878 (:emitter
879 (with-condition-defaulted (args (condition dest value address))
880 (emit-semaphore-instruction segment #b10000
881 condition dest value address))))
883 (define-instruction swpb (segment &rest args)
884 (:emitter
885 (with-condition-defaulted (args (condition dest value address))
886 (emit-semaphore-instruction segment #b10100
887 condition dest value address))))
889 ;;;; Status-register instructions
891 (define-instruction mrs (segment &rest args)
892 (:printer dp-shift-immediate ((opcode-8 #b0010000)
893 (rn #b1111)
894 (shift '(0 0))
895 (rm 0))
896 '(:name cond :tab rd ", CPSR"))
897 (:printer dp-shift-immediate ((opcode-8 #b0010100)
898 (rn #b1111)
899 (shift '(0 0))
900 (rm 0))
901 '(:name cond :tab rd ", SPSR"))
902 (:emitter
903 (with-condition-defaulted (args (condition dest reg))
904 (aver (register-p dest))
905 (aver (member reg '(:cpsr :spsr)))
906 (emit-dp-instruction segment (conditional-opcode condition)
907 #b00 0 (if (eq reg :cpsr) #b10000 #b10100)
908 #b1111 (tn-offset dest) 0))))
910 (defun encode-status-register-fields (fields)
911 (let ((fields (string fields)))
912 (labels ((frob (mask index)
913 (let* ((field (aref fields index))
914 (field-mask (cdr (assoc field
915 '((#\C . #b0001) (#\X . #b0010)
916 (#\S . #b0100) (#\F . #b1000))
917 :test #'char=))))
918 (unless field-mask
919 (error "bad status register field desginator ~S" fields))
920 (if (< (1+ index) (length fields))
921 (frob (logior mask field-mask) (1+ index))
922 (logior mask field-mask)))))
923 (frob 0 0))))
925 (defmacro cpsr (fields)
926 (encode-status-register-fields fields))
928 (defmacro spsr (fields)
929 (logior #b10000 (encode-status-register-fields fields)))
931 (define-instruction msr (segment &rest args)
932 (:printer msr-immediate ())
933 (:printer msr-register ())
934 (:emitter
935 (with-condition-defaulted (args (condition field-mask src))
936 (aver (or (register-p src)
937 (integerp src)))
938 (let ((encoded-src (encode-shifter-operand src)))
939 (emit-dp-instruction segment (conditional-opcode condition)
940 #b00 (ldb (byte 1 25) encoded-src)
941 (if (logbitp 4 field-mask) #b10110 #b10010)
942 field-mask #b1111
943 (ldb (byte 12 0) encoded-src))))))
945 ;;;; Multiply instructions
947 (define-bitfield-emitter emit-multiply-instruction 32
948 (byte 4 28) (byte 8 20) (byte 4 16) (byte 4 12)
949 (byte 4 8) (byte 4 4) (byte 4 0))
951 (macrolet
952 ((define-multiply-instruction (name field-mapping opcode1 opcode2)
953 (let ((arglist (ecase field-mapping
954 (:dzsm '(dest src multiplicand))
955 (:dnsm '(dest src multiplicand num))
956 (:ddsm '(dest-lo dest src multiplicand)))))
957 `(define-instruction ,name (segment &rest args)
958 (:printer ,(symbolicate 'multiply- field-mapping)
959 ((opcode-8 ,opcode1)
960 (opcode-4 ,opcode2)))
961 (:emitter
962 (with-condition-defaulted (args (condition ,@arglist))
963 ,@(loop
964 for arg in arglist
965 collect `(aver (register-p ,arg)))
966 (emit-multiply-instruction segment (conditional-opcode condition)
967 ,opcode1
968 (tn-offset dest)
969 ,(ecase field-mapping
970 (:dzsm 0)
971 (:dnsm '(tn-offset num))
972 (:ddsm '(tn-offset dest-lo)))
973 (tn-offset src)
974 ,opcode2
975 (tn-offset multiplicand))))))))
977 (define-multiply-instruction mul :dzsm #b00000000 #b1001)
978 (define-multiply-instruction muls :dzsm #b00000001 #b1001)
979 (define-multiply-instruction mla :dnsm #b00000010 #b1001)
980 (define-multiply-instruction mlas :dnsm #b00000011 #b1001)
982 (define-multiply-instruction umull :ddsm #b00001000 #b1001)
983 (define-multiply-instruction umulls :ddsm #b00001001 #b1001)
984 (define-multiply-instruction umlal :ddsm #b00001010 #b1001)
985 (define-multiply-instruction umlals :ddsm #b00001011 #b1001)
987 (define-multiply-instruction smull :ddsm #b00001100 #b1001)
988 (define-multiply-instruction smulls :ddsm #b00001101 #b1001)
989 (define-multiply-instruction smlal :ddsm #b00001110 #b1001)
990 (define-multiply-instruction smlals :ddsm #b00001111 #b1001)
992 (define-multiply-instruction smlabb :dnsm #b00010000 #b1000)
993 (define-multiply-instruction smlatb :dnsm #b00010000 #b1010)
994 (define-multiply-instruction smlabt :dnsm #b00010000 #b1100)
995 (define-multiply-instruction smlatt :dnsm #b00010000 #b1110)
997 (define-multiply-instruction smlalbb :ddsm #b00010100 #b1000)
998 (define-multiply-instruction smlaltb :ddsm #b00010100 #b1010)
999 (define-multiply-instruction smlalbt :ddsm #b00010100 #b1100)
1000 (define-multiply-instruction smlaltt :ddsm #b00010100 #b1110)
1002 (define-multiply-instruction smulbb :dzsm #b00010110 #b1000)
1003 (define-multiply-instruction smultb :dzsm #b00010110 #b1010)
1004 (define-multiply-instruction smulbt :dzsm #b00010110 #b1100)
1005 (define-multiply-instruction smultt :dzsm #b00010110 #b1110)
1007 (define-multiply-instruction smlawb :dnsm #b00010010 #b1000)
1008 (define-multiply-instruction smlawt :dnsm #b00010010 #b1100)
1010 (define-multiply-instruction smulwb :dzsm #b00010010 #b1010)
1011 (define-multiply-instruction smulwt :dzsm #b00010010 #b1110))
1013 ;;;; Load/store instructions
1015 ;;; Emit a load/store instruction. CONDITION is a condition code
1016 ;;; name, KIND is :load or :store, WIDTH is :word or :byte, DATA is a
1017 ;;; register TN and ADDRESS is either a memory-operand structure or a
1018 ;;; stack TN.
1019 (defun emit-load/store-instruction (segment condition kind width data address)
1020 (flet ((compute-opcode (direction mode)
1021 (let ((opcode-bits '(:load #b00001 :store #b00000
1022 :word #b00000 :byte #b00100
1023 :up #b01000 :down #b00000
1024 :offset #b10000
1025 :pre-index #b10010
1026 :post-index #b00000)))
1027 (reduce #'logior (list kind width direction mode)
1028 :key (lambda (value) (getf opcode-bits value))))))
1029 (etypecase address
1030 (memory-operand
1031 (let* ((base (memory-operand-base address))
1032 (offset (memory-operand-offset address))
1033 (direction (memory-operand-direction address))
1034 (mode (memory-operand-mode address))
1035 (cond-bits (conditional-opcode condition)))
1036 (cond
1037 ((label-p base)
1038 (emit-back-patch
1039 segment 4
1040 (lambda (segment posn)
1041 (let* ((label-delta (- (label-position base)
1042 (+ posn 8)))
1043 (offset-delta (if (eq direction :up)
1044 offset
1045 (- offset)))
1046 (overall-delta (+ label-delta
1047 offset-delta))
1048 (absolute-delta (abs overall-delta)))
1049 (aver (typep absolute-delta '(unsigned-byte 12)))
1050 (emit-dp-instruction segment cond-bits #b01 0
1051 (compute-opcode (if (< overall-delta 0)
1052 :down
1053 :up)
1054 mode)
1055 pc-offset (tn-offset data)
1056 absolute-delta)))))
1057 ((integerp offset)
1058 (aver (typep offset '(unsigned-byte 12)))
1059 (emit-dp-instruction segment cond-bits #b01 0
1060 (compute-opcode direction mode)
1061 (tn-offset base) (tn-offset data)
1062 offset))
1064 (emit-dp-instruction segment cond-bits #b01 1
1065 (compute-opcode direction mode)
1066 (tn-offset base) (tn-offset data)
1067 (encode-shifter-operand offset))))))
1069 #+(or)
1071 ;; FIXME: This is for stack TN references, and needs must be
1072 ;; implemented.
1073 ))))
1075 (macrolet
1076 ((define-load/store-instruction (name kind width)
1077 `(define-instruction ,name (segment &rest args)
1078 (:printer load/store-immediate ((opcode-3 #b010)
1079 (opcode-b ,(ecase width
1080 (:word 0)
1081 (:byte 1)))
1082 (opcode-l ,(ecase kind
1083 (:load 1)
1084 (:store 0)))))
1085 (:printer load/store-register ((opcode-3 #b011)
1086 (opcode-0 0)
1087 (opcode-b ,(ecase width
1088 (:word 0)
1089 (:byte 1)))
1090 (opcode-l ,(ecase kind
1091 (:load 1)
1092 (:store 0)))))
1093 (:emitter
1094 (with-condition-defaulted (args (condition reg address))
1095 (aver (or (register-p reg)
1096 ,@(when (eq :store kind)
1097 '((and (tn-p reg)
1098 (eq 'null (sc-name (tn-sc reg))))))))
1099 (emit-load/store-instruction segment condition
1100 ,kind ,width
1101 (if (register-p reg) reg null-tn)
1102 address))))))
1103 (define-load/store-instruction ldr :load :word)
1104 (define-load/store-instruction ldrb :load :byte)
1105 (define-load/store-instruction str :store :word)
1106 (define-load/store-instruction strb :store :byte))
1108 (define-instruction ldm (segment &rest args) ; load multiple
1109 (:printer ldm/stm ((opcode-3 #b100) (opcode-l 1))))
1110 (define-instruction stm (segment &rest args) ; store multiple
1111 (:printer ldm/stm ((opcode-3 #b100) (opcode-l 0))))
1113 ;;; Emit a miscellaneous load/store instruction. CONDITION is a
1114 ;;; condition code name, OPCODE1 is the low bit of the first opcode
1115 ;;; field, OPCODE2 is the second opcode field, DATA is a register TN
1116 ;;; and ADDRESS is either a memory-operand structure or a stack TN.
1117 (defun emit-misc-load/store-instruction (segment condition opcode1
1118 opcode2 data address)
1119 (flet ((compute-opcode (kind direction mode)
1120 (let ((opcode-bits '(:register #b00000 :immediate #b00100
1121 :up #b01000 :down #b00000
1122 :offset #b10000
1123 :pre-index #b10010
1124 :post-index #b00000)))
1125 (reduce #'logior (list kind direction mode)
1126 :key (lambda (value) (getf opcode-bits value))))))
1127 (etypecase address
1128 (memory-operand
1129 (let* ((base (memory-operand-base address))
1130 (offset (memory-operand-offset address))
1131 (direction (memory-operand-direction address))
1132 (mode (memory-operand-mode address))
1133 (cond-bits (conditional-opcode condition)))
1134 (cond
1135 ((label-p base)
1136 (emit-back-patch
1137 segment 4
1138 (lambda (segment posn)
1139 (let* ((label-delta (- (label-position base)
1140 (+ posn 8)))
1141 (offset-delta (if (eq direction :up)
1142 offset
1143 (- offset)))
1144 (overall-delta (+ label-delta
1145 offset-delta))
1146 (absolute-delta (abs overall-delta)))
1147 (aver (typep absolute-delta '(unsigned-byte 8)))
1148 (emit-multiply-instruction segment cond-bits
1149 (logior opcode1
1150 (compute-opcode :immedaite
1151 (if (< overall-delta 0)
1152 :down
1153 :up)
1154 mode))
1155 pc-offset (tn-offset data)
1156 (ldb (byte 4 4) absolute-delta)
1157 opcode2 absolute-delta)))))
1158 ((integerp offset)
1159 (aver (typep offset '(unsigned-byte 8)))
1160 (emit-multiply-instruction segment cond-bits
1161 (logior opcode1
1162 (compute-opcode :immediate direction mode))
1163 (tn-offset base) (tn-offset data)
1164 (ldb (byte 4 4) offset)
1165 opcode2 offset))
1166 ((register-p offset)
1167 (emit-multiply-instruction segment cond-bits
1168 (logior opcode1
1169 (compute-opcode :register direction mode))
1170 (tn-offset base) (tn-offset data)
1171 0 opcode2 (tn-offset offset)))
1173 (error "bad thing for a miscellaneous load/store address ~S"
1174 address)))))
1176 #+(or)
1178 ;; FIXME: This is for stack TN references, and needs must be
1179 ;; implemented.
1180 ))))
1182 (macrolet
1183 ((define-misc-load/store-instruction (name opcode1 opcode2 double-width)
1184 `(define-instruction ,name (segment &rest args)
1185 (:emitter
1186 (with-condition-defaulted (args (condition reg address))
1187 (aver (register-p reg))
1188 ,(when double-width '(aver (evenp (tn-offset reg))))
1189 (emit-misc-load/store-instruction segment condition
1190 ,opcode1 ,opcode2
1191 reg address))))))
1192 (define-misc-load/store-instruction strh 0 #b1011 nil)
1193 (define-misc-load/store-instruction ldrd 0 #b1101 t)
1194 (define-misc-load/store-instruction strd 0 #b1111 t)
1196 (define-misc-load/store-instruction ldrh 1 #b1011 nil)
1197 (define-misc-load/store-instruction ldrsb 1 #b1101 nil)
1198 (define-misc-load/store-instruction ldrsh 1 #b1111 nil))
1200 ;;;; Boxed-object computation instructions (for LRA and CODE)
1202 ;;; Compute the address of a CODE object by parsing the header of a
1203 ;;; nearby LRA or SIMPLE-FUN.
1204 (define-instruction compute-code (segment code lip object-label temp)
1205 (:vop-var vop)
1206 (:emitter
1207 (emit-back-patch
1208 segment 16
1209 (lambda (segment position)
1210 (assemble (segment vop)
1211 ;; Calculate the address of the code component. This is an
1212 ;; exercise in excess cleverness. First, we calculate (from
1213 ;; our program counter only) the address of OBJECT-LABEL plus
1214 ;; OTHER-POINTER-LOWTAG. The extra two words are to
1215 ;; compensate for the offset applied by ARM CPUs when reading
1216 ;; the program counter.
1217 (inst sub lip pc-tn (- ;; The 8 below is the displacement
1218 ;; from reading the program counter.
1219 (+ position 8)
1220 (+ (label-position object-label)
1221 other-pointer-lowtag)))
1222 ;; Next, we read the function header.
1223 (inst ldr temp (@ lip (- other-pointer-lowtag)))
1224 (inst bic temp temp widetag-mask)
1225 ;; And finally we use the header value (a count in words),
1226 ;; to compute the boxed address of the code component.
1227 (inst sub code lip (lsr temp (- 8 word-shift))))))))
1229 ;;; Compute the address of a nearby LRA object by dead reckoning from
1230 ;;; the location of the current instruction.
1231 (define-instruction compute-lra (segment dest lip lra-label)
1232 (:vop-var vop)
1233 (:emitter
1234 ;; We can compute the LRA in a single instruction if the overall
1235 ;; offset puts it to within an 8-bit displacement. Otherwise, we
1236 ;; need to load it by parts into LIP until we're down to an 8-bit
1237 ;; displacement, and load the final 8 bits into DEST. We may
1238 ;; safely presume that an overall displacement may be up to 24 bits
1239 ;; wide (the PPC backend has special provision for branches over 15
1240 ;; bits, which implies that segments can become large, but a 16
1241 ;; megabyte segment (24 bits of displacement) is ridiculous), so we
1242 ;; need to cover a range of up to three octets of displacement.
1243 (labels ((compute-delta (position &optional magic-value)
1244 (- (+ (label-position lra-label
1245 (when magic-value position)
1246 magic-value)
1247 other-pointer-lowtag)
1248 ;; The 8 below is the displacement
1249 ;; from reading the program counter.
1250 (+ position 8)))
1252 (load-chunk (segment delta dst src chunk)
1253 (assemble (segment vop)
1254 (if (< delta 0)
1255 (inst sub dst src chunk)
1256 (inst add dst src chunk))))
1258 (three-instruction-emitter (segment position)
1259 (let* ((delta (compute-delta position))
1260 (absolute-delta (abs delta)))
1261 (load-chunk segment delta
1262 lip pc-tn (mask-field (byte 8 16) absolute-delta))
1263 (load-chunk segment delta
1264 lip lip (mask-field (byte 8 8) absolute-delta))
1265 (load-chunk segment delta
1266 dest lip (mask-field (byte 8 0) absolute-delta))))
1268 (two-instruction-emitter (segment position)
1269 (let* ((delta (compute-delta position))
1270 (absolute-delta (abs delta)))
1271 (assemble (segment vop)
1272 (load-chunk segment delta
1273 lip pc-tn (mask-field (byte 8 8) absolute-delta))
1274 (load-chunk segment delta
1275 dest lip (mask-field (byte 8 0) absolute-delta)))))
1277 (one-instruction-emitter (segment position)
1278 (let* ((delta (compute-delta position))
1279 (absolute-delta (abs delta)))
1280 (assemble (segment vop)
1281 (load-chunk segment delta
1282 dest pc-tn absolute-delta))))
1284 (two-instruction-maybe-shrink (segment chooser posn magic-value)
1285 (declare (ignore chooser))
1286 (let ((delta (compute-delta posn magic-value)))
1287 (when (<= (integer-length delta) 8)
1288 (emit-back-patch segment 4
1289 #'one-instruction-emitter)
1290 t)))
1292 (three-instruction-maybe-shrink (segment chooser posn magic-value)
1293 (declare (ignore chooser))
1294 (let ((delta (compute-delta posn magic-value)))
1295 (when (<= (integer-length delta) 16)
1296 (emit-chooser segment 8 2
1297 #'two-instruction-maybe-shrink
1298 #'two-instruction-emitter)
1299 t))))
1300 (emit-chooser
1301 ;; We need to emit up to three instructions, which is 12 octets.
1302 ;; This preserves a mere two bits of alignment.
1303 segment 12 2
1304 #'three-instruction-maybe-shrink
1305 #'three-instruction-emitter))))
1307 ;;; Load a register from a "nearby" LABEL by dead reckoning from the
1308 ;;; location of the current instruction.
1309 (define-instruction load-from-label (segment &rest args)
1310 (:vop-var vop)
1311 (:emitter
1312 ;; ISTM this use of an interior-pointer is unnecessary. Since we know the
1313 ;; displacement of the label from the base of the CODE, we could load
1314 ;; either from [code+X] or [PC+X] where X is in an unsigned-reg.
1315 (with-condition-defaulted (args (condition dest lip label))
1316 ;; We can load the word addressed by a label in a single
1317 ;; instruction if the overall offset puts it to within a 12-bit
1318 ;; displacement. Otherwise, we need to build an address by parts
1319 ;; into LIP until we're down to a 12-bit displacement, and then
1320 ;; apply the final 12 bits with LDR. For now, we'll allow up to 20
1321 ;; bits of displacement, as that should be easy to implement, and a
1322 ;; megabyte large code object is already a bit unwieldly. If
1323 ;; necessary, we can expand to a 28 bit displacement.
1324 (labels ((compute-delta (position &optional magic-value)
1325 (- (label-position label
1326 (when magic-value position)
1327 magic-value)
1328 ;; The 8 below is the displacement
1329 ;; from reading the program counter.
1330 (+ position 8)))
1332 (load-chunk (segment delta dst src chunk)
1333 (assemble (segment vop)
1334 (if (< delta 0)
1335 (inst sub condition dst src chunk)
1336 (inst add condition dst src chunk))))
1338 (two-instruction-emitter (segment position)
1339 (let* ((delta (compute-delta position))
1340 (absolute-delta (abs delta)))
1341 (assemble (segment vop)
1342 (load-chunk segment delta
1343 lip pc-tn (mask-field (byte 8 12) absolute-delta))
1344 (inst ldr condition dest (@ lip (mask-field (byte 12 0) delta))))))
1346 (one-instruction-emitter (segment position)
1347 (let* ((delta (compute-delta position)))
1348 (assemble (segment vop)
1349 (inst ldr condition dest (@ pc-tn delta)))))
1351 (two-instruction-maybe-shrink (segment chooser posn magic-value)
1352 (declare (ignore chooser))
1353 (let ((delta (compute-delta posn magic-value)))
1354 (when (<= (integer-length delta) 12)
1355 (emit-back-patch segment 4
1356 #'one-instruction-emitter)
1357 t))))
1358 (emit-chooser
1359 ;; We need to emit up to two instructions, which is 8 octets,
1360 ;; but might wish to emit only one. This preserves a mere two
1361 ;; bits of alignment.
1362 segment 8 2
1363 #'two-instruction-maybe-shrink
1364 #'two-instruction-emitter)))))
1366 (define-instruction adr (segment code label &optional (offset 0))
1367 (:vop-var vop)
1368 (:emitter
1369 (emit-back-patch
1370 segment 4
1371 (lambda (segment position)
1372 (assemble (segment vop)
1373 (let ((offset (+ (- (label-position label)
1374 (+ position 8))
1375 offset)))
1376 (if (plusp offset)
1377 (inst add code pc-tn offset)
1378 (inst sub code pc-tn (- offset)))))))))
1380 ;; data processing floating point instructions
1381 (define-bitfield-emitter emit-fp-dp-instruction 32
1382 (byte 4 28) ; cond
1383 (byte 4 24) ; #b1110
1384 (byte 1 23) ; p
1385 (byte 1 22) ; D
1386 (byte 1 21) ; q
1387 (byte 1 20) ; r
1388 (byte 4 16) ; Fn || extension op
1389 (byte 4 12) ; Fd
1390 (byte 3 9) ; #b101
1391 (byte 1 8) ; double/single precission
1392 (byte 1 7) ; N || extension op
1393 (byte 1 6) ; s
1394 (byte 1 5) ; M
1395 (byte 1 4) ; #b0
1396 (byte 4 0)) ; Fm
1398 (defun low-bit-float-reg (reg-tn)
1399 (logand 1 (tn-offset reg-tn)))
1401 (defun high-bits-float-reg (reg-tn)
1402 (ash (tn-offset reg-tn) -1))
1404 (defmacro define-binary-fp-data-processing-instruction (name precision p q r s)
1405 (let ((precision-flag (ecase precision
1406 (:single 0)
1407 (:double 1))))
1408 `(define-instruction ,name (segment &rest args)
1409 (:printer fp-binary ((p ,p)
1410 (q ,q)
1411 (r ,r)
1412 (s ,s)
1413 (size ,precision-flag)))
1414 (:emitter
1415 (with-condition-defaulted (args (condition dest op-n op-m))
1416 (emit-fp-dp-instruction segment
1417 (conditional-opcode condition)
1418 #b1110
1420 (low-bit-float-reg dest)
1423 (high-bits-float-reg op-n)
1424 (high-bits-float-reg dest)
1425 #b101
1426 ,precision-flag
1427 (low-bit-float-reg op-n)
1429 (low-bit-float-reg op-m)
1431 (high-bits-float-reg op-m)))))))
1433 (defmacro define-binary-fp-data-processing-instructions (root p q r s)
1434 `(progn
1435 (define-binary-fp-data-processing-instruction ,(symbolicate root 's) :single ,p ,q ,r ,s)
1436 (define-binary-fp-data-processing-instruction ,(symbolicate root 'd) :double ,p ,q ,r ,s)))
1438 (define-binary-fp-data-processing-instructions fmac 0 0 0 0)
1439 (define-binary-fp-data-processing-instructions fnmac 0 0 0 1)
1440 (define-binary-fp-data-processing-instructions fmsc 0 0 1 0)
1441 (define-binary-fp-data-processing-instructions fnmsc 0 0 1 1)
1442 (define-binary-fp-data-processing-instructions fmul 0 1 0 0)
1443 (define-binary-fp-data-processing-instructions fnmul 0 1 0 1)
1444 (define-binary-fp-data-processing-instructions fadd 0 1 1 0)
1445 (define-binary-fp-data-processing-instructions fsub 0 1 1 1)
1446 (define-binary-fp-data-processing-instructions fdiv 1 0 0 0)
1448 ;;; op-m-sbz means that it should-be-zero, and only one register is supplied.
1449 (defmacro define-unary-fp-data-processing-instruction (name precision fn n
1450 &key op-m-sbz)
1451 (let ((precision-flag (ecase precision
1452 (:single 0)
1453 (:double 1))))
1454 `(define-instruction ,name (segment &rest args)
1455 (:printer ,(if op-m-sbz
1456 'fp-unary-one-op
1457 'fp-unary)
1458 ((size ,precision-flag)
1459 (n ,n)
1460 (opc ,fn)))
1461 (:emitter
1462 (with-condition-defaulted (args (condition dest
1463 ,@(unless op-m-sbz
1464 '(op-m))))
1465 (emit-fp-dp-instruction segment
1466 (conditional-opcode condition)
1467 #b1110
1469 (low-bit-float-reg dest)
1473 (high-bits-float-reg dest)
1474 #b101
1475 ,precision-flag
1478 ,(if op-m-sbz
1480 '(low-bit-float-reg op-m))
1482 ,(if op-m-sbz
1484 '(high-bits-float-reg op-m))))))))
1486 (defmacro define-unary-fp-data-processing-instructions (root fn n &key op-m-sbz)
1487 `(progn
1488 (define-unary-fp-data-processing-instruction ,(symbolicate root 's) :single ,fn ,n
1489 :op-m-sbz ,op-m-sbz)
1490 (define-unary-fp-data-processing-instruction ,(symbolicate root 'd) :double ,fn ,n
1491 :op-m-sbz ,op-m-sbz)))
1493 (define-unary-fp-data-processing-instructions fcpy #b0000 0)
1494 (define-unary-fp-data-processing-instructions fabs #b0000 1)
1495 (define-unary-fp-data-processing-instructions fneg #b0001 0)
1496 (define-unary-fp-data-processing-instructions fsqrt #b0001 1)
1497 (define-unary-fp-data-processing-instructions fcmp #b0100 0)
1498 (define-unary-fp-data-processing-instructions fcmpe #b0100 1)
1499 (define-unary-fp-data-processing-instructions fcmpz #b0101 0 :op-m-sbz t)
1500 (define-unary-fp-data-processing-instructions fcmpez #b0101 1 :op-m-sbz t)
1501 (define-unary-fp-data-processing-instructions fuito #b1000 0)
1502 (define-unary-fp-data-processing-instructions fsito #b1000 1)
1503 (define-unary-fp-data-processing-instructions ftoui #b1100 0)
1504 (define-unary-fp-data-processing-instructions ftouiz #b1100 1)
1505 (define-unary-fp-data-processing-instructions ftosi #b1101 0)
1506 (define-unary-fp-data-processing-instructions ftosiz #b1101 1)
1508 (define-unary-fp-data-processing-instruction fcvtds :single #b0111 1)
1509 (define-unary-fp-data-processing-instruction fcvtsd :double #b0111 1)
1511 ;;; Load/Store Float Instructions
1513 (define-bitfield-emitter emit-fp-ls-instruction 32
1514 (byte 4 28) ; cond
1515 (byte 3 25) ; #b110
1516 (byte 1 24) ; P
1517 (byte 1 23) ; U
1518 (byte 1 22) ; D
1519 (byte 1 21) ; W
1520 (byte 1 20) ; L
1521 (byte 4 16) ; Rn
1522 (byte 4 12) ; Fd
1523 (byte 3 9) ; #b101
1524 (byte 1 8) ; double/single precission
1525 (byte 8 0)) ; offset
1527 ;; Define a load/store multiple floating point instruction. PRECISION is
1528 ;; :SINGLE for single precision values and :DOUBLE for double precision values.
1529 ;; DIRECTION has to be either :LOAD or :STORE.
1530 ;; If INC-OFFSET is true, the offset part of the instruction will be incremented by 1
1531 ;; indicating in the double case a load/store unknown instruction.
1532 (defmacro define-load-store-multiple-fp-instruction (name precision direction &optional inc-offset)
1533 (let ((precision-flag (ecase precision
1534 (:single 0)
1535 (:double 1)))
1536 (direction-flag (ecase direction
1537 (:load 1)
1538 (:store 0))))
1539 `(define-instruction ,name (segment &rest args)
1540 (:emitter
1541 (with-condition-defaulted (args (condition address base-reg reg-count))
1542 (let* ((mode (cond
1543 ((consp address)
1544 (cdr address))
1545 (t :unindexed)))
1546 (p (ecase mode
1547 ((:unindexed :increment) 0)
1548 ((:decrement) 1)))
1549 (u (ecase mode
1550 ((:unindexed :increment) 1)
1551 ((:decrement) 0)))
1552 (w (ecase mode
1553 ((:unindexed) 0)
1554 ((:increment :decrement) 1))))
1555 (emit-fp-ls-instruction segment
1556 (conditional-opcode condition)
1557 #b110
1560 (low-bit-float-reg base-reg)
1562 ,direction-flag
1563 (tn-offset address)
1564 (high-bits-float-reg base-reg)
1565 #b101
1566 ,precision-flag
1567 ,(ecase precision
1568 (:single 'reg-count)
1569 (:double `(+ (* 2 reg-count)
1570 ,(if inc-offset 1 0)))))))))))
1572 ;; multiple single precision
1573 (define-load-store-multiple-fp-instruction fstms :single :store)
1574 (define-load-store-multiple-fp-instruction fldms :single :load)
1575 ;; multiple double precision
1576 (define-load-store-multiple-fp-instruction fstmd :double :store)
1577 (define-load-store-multiple-fp-instruction fldmd :double :load)
1578 ;; multiple double precision registers of unknown content (needs up to 2 * reg-count + 1 words of space)
1579 (define-load-store-multiple-fp-instruction fstmx :double :store t)
1580 (define-load-store-multiple-fp-instruction fldmx :double :load t)
1582 ;; KLUDGE: this group of pseudo-instructions are fragile (no error
1583 ;; handling for the various ways to mis-use them), have no support for
1584 ;; predication, and use the somewhat-broken interface for the
1585 ;; load-store-multiple-fp instructions above.
1586 (define-instruction-macro load-complex-single (dest memory-operand)
1587 `(inst fldms (memory-operand-base ,memory-operand) ,dest 2))
1588 (define-instruction-macro load-complex-double (dest memory-operand)
1589 `(inst fldmd (memory-operand-base ,memory-operand) ,dest 2))
1590 (define-instruction-macro store-complex-single (src memory-operand)
1591 `(inst fstms (memory-operand-base ,memory-operand) ,src 2))
1592 (define-instruction-macro store-complex-double (src memory-operand)
1593 `(inst fstmd (memory-operand-base ,memory-operand) ,src 2))
1595 ;; Define a load/store one floating point instruction. PRECISION is
1596 ;; :SINGLE for single precision values and :DOUBLE for double precision values.
1597 ;; DIRECTION has to be either :LOAD or :STORE.
1598 (defmacro define-load-store-one-fp-instruction (name precision direction)
1599 (let ((precision-flag (ecase precision
1600 (:single 0)
1601 (:double 1)))
1602 (direction-flag (ecase direction
1603 (:load 1)
1604 (:store 0))))
1605 `(define-instruction ,name (segment &rest args)
1606 (:emitter
1607 (with-condition-defaulted (args (condition float-reg memory-operand))
1608 (let ((base (memory-operand-base memory-operand))
1609 (offset (memory-operand-offset memory-operand))
1610 (direction (memory-operand-direction memory-operand)))
1611 (aver (eq (memory-operand-mode memory-operand) :offset))
1612 (aver (and (integerp offset)
1613 (zerop (logand offset 3))))
1614 ;; FIXME: Should support LABEL bases.
1615 (aver (tn-p base))
1616 (emit-fp-ls-instruction segment
1617 (conditional-opcode condition)
1618 #b110
1620 (if (eq direction :up) 1 0)
1621 (low-bit-float-reg float-reg)
1623 ,direction-flag
1624 (tn-offset base)
1625 (high-bits-float-reg float-reg)
1626 #b101
1627 ,precision-flag
1628 (ash offset -2))))))))
1630 (define-load-store-one-fp-instruction fsts :single :store)
1631 (define-load-store-one-fp-instruction flds :single :load)
1632 (define-load-store-one-fp-instruction fstd :double :store)
1633 (define-load-store-one-fp-instruction fldd :double :load)
1636 ;; single register transfer instructions
1638 (define-bitfield-emitter emit-fp-srt-instruction 32
1639 (byte 4 28) ; cond
1640 (byte 4 24) ; #b1110
1641 (byte 3 21) ; opc
1642 (byte 1 20) ; L
1644 (byte 4 16) ; Fn
1645 (byte 4 12) ; Rd
1646 (byte 3 9) ; #b101
1647 (byte 1 8) ; precision
1649 (byte 1 7) ; N
1650 (byte 7 0)) ; #b0010000
1652 (define-bitfield-emitter emit-conditional-instruction 32
1653 (byte 4 28) ; cond
1654 (byte 28 0)) ; op
1656 ;;; This has the same encoding as FMRX R15, FPSCR
1657 (define-instruction fmstat (segment &rest args)
1658 (:printer conditional
1659 ((op #xEF1FA10)))
1660 (:emitter
1661 (with-condition-defaulted (args (condition))
1662 (emit-conditional-instruction segment
1663 (conditional-opcode condition)
1664 #xEF1FA10))))
1666 (defun system-reg-encoding (float-reg)
1667 (ecase float-reg
1668 (:fpsid #b0000)
1669 (:fpscr #b0001)
1670 (:fpexc #b1000)))
1672 (defmacro define-single-reg-transfer-fp-instruction (name precision direction opcode &optional system-reg)
1673 (let ((precision-flag (ecase precision
1674 (:single 0)
1675 (:double 1)))
1676 (direction-flag (ecase direction
1677 (:to-arm 1)
1678 (:from-arm 0))))
1679 `(define-instruction ,name (segment &rest args)
1680 (:printer ,(if system-reg
1681 'fp-srt-sys
1682 'fp-srt)
1683 ((opc ,opcode)
1684 (l ,direction-flag)
1685 (size ,precision-flag))
1686 ',(if (eq direction :to-arm)
1687 '(:name cond :tab rd ", " fn)
1688 '(:name cond :tab fn ", " rd)))
1689 (:emitter
1690 (with-condition-defaulted (args (condition ,@(if (eq direction :to-arm)
1691 '(arm-reg float-reg)
1692 '(float-reg arm-reg))))
1693 (emit-fp-srt-instruction segment
1694 (conditional-opcode condition)
1695 #b1110
1696 ,opcode
1697 ,direction-flag
1698 ,(if system-reg
1699 '(system-reg-encoding float-reg)
1700 '(high-bits-float-reg float-reg))
1701 (tn-offset arm-reg)
1702 #b101
1703 ,precision-flag
1704 ,(if system-reg
1706 '(low-bit-float-reg float-reg))
1707 #b0010000))))))
1709 (define-single-reg-transfer-fp-instruction fmsr :single :from-arm #b000)
1710 (define-single-reg-transfer-fp-instruction fmrs :single :to-arm #b000)
1711 (define-single-reg-transfer-fp-instruction fmdlr :double :from-arm #b000)
1712 (define-single-reg-transfer-fp-instruction fmrdl :double :to-arm #b000)
1713 (define-single-reg-transfer-fp-instruction fmdhr :double :from-arm #b001)
1714 (define-single-reg-transfer-fp-instruction fmrdh :double :to-arm #b001)
1715 (define-single-reg-transfer-fp-instruction fmxr :single :from-arm #b111 t)
1716 (define-single-reg-transfer-fp-instruction fmrx :single :to-arm #b111 t)
1718 (define-bitfield-emitter emit-fp-trt-instruction 32
1719 (byte 4 28) ; cond
1720 (byte 7 21) ; #b1100010
1721 (byte 1 20) ; L
1722 (byte 4 16) ; Rn
1723 (byte 4 12) ; Rd
1724 (byte 3 9) ; #b101
1725 (byte 1 8) ; precision
1726 (byte 2 6) ; #b00
1727 (byte 1 5) ; M
1728 (byte 1 4) ; #b1
1729 (byte 4 0)) ; Fm
1731 (defmacro define-two-reg-transfer-fp-instruction (name precision direction)
1732 (let ((precision-flag (ecase precision
1733 (:single 0)
1734 (:double 1)))
1735 (direction-flag (ecase direction
1736 (:to-arm 1)
1737 (:from-arm 0))))
1738 `(define-instruction ,name (segment &rest args)
1739 (:printer fp-trt
1740 ((l ,direction-flag)
1741 (size ,precision-flag))
1742 ',(if (eq direction :to-arm)
1743 '(:name cond :tab rd ", " rn ", " fm)
1744 '(:name cond :tab fm ", " rd ", " rn )))
1745 (:emitter
1746 (with-condition-defaulted (args (condition ,@(if (eq direction :to-arm)
1747 '(arm-reg-1 arm-reg-2 float-reg)
1748 '(float-reg arm-reg-1 arm-reg-2))))
1749 (emit-fp-trt-instruction segment
1750 (conditional-opcode condition)
1751 #b1100010
1752 ,direction-flag
1753 (tn-offset arm-reg-2)
1754 (tn-offset arm-reg-1)
1755 #b101
1756 ,precision-flag
1757 #b00
1758 (low-bit-float-reg float-reg)
1760 (high-bits-float-reg float-reg)))))))
1762 (define-two-reg-transfer-fp-instruction fmsrr :single :from-arm)
1763 (define-two-reg-transfer-fp-instruction fmrrs :single :to-arm)
1764 (define-two-reg-transfer-fp-instruction fmdrr :double :from-arm)
1765 (define-two-reg-transfer-fp-instruction fmrrd :double :to-arm)
1767 (sb-assem::%def-inst-encoder
1768 '.layout-id
1769 (lambda (segment layout)
1770 (sb-c:note-fixup segment :layout-id (sb-c:make-fixup layout :layout-id))))
1772 (defun sb-vm:fixup-code-object (code offset value kind flavor)
1773 (declare (type index offset) (ignore flavor))
1774 (unless (zerop (rem offset sb-assem:+inst-alignment-bytes+))
1775 (error "Unaligned instruction? offset=#x~X." offset))
1776 (let ((sap (code-instructions code)))
1777 (ecase kind
1778 (:layout-id
1779 (aver (typep value '(unsigned-byte 24)))
1780 (setf (sap-ref-word sap offset)
1781 (dpb (ldb (byte 8 16) value) (byte 8 0) (sap-ref-word sap offset))
1782 (sap-ref-word sap (+ offset 4))
1783 (dpb (ldb (byte 8 8) value) (byte 8 0) (sap-ref-word sap (+ offset 4)))
1784 (sap-ref-word sap (+ offset 8))
1785 (dpb (ldb (byte 8 0) value) (byte 8 0) (sap-ref-word sap (+ offset 8)))))
1786 (:absolute
1787 (setf (sap-ref-32 sap offset) value))))
1788 nil)
1790 (define-instruction store-coverage-mark (segment mark-index temp)
1791 (:emitter
1792 ;; No backpatch is needed to compute the offset into the code header
1793 ;; because COMPONENT-HEADER-LENGTH is known at this point.
1794 (let* ((offset (+ (component-header-length)
1795 ;; skip over jump table word and entries
1796 (* (1+ (component-n-jump-table-entries))
1797 n-word-bytes)
1798 mark-index
1799 (- other-pointer-lowtag)))
1800 (addr
1801 (@ sb-vm::code-tn
1802 (etypecase offset
1803 ((integer 0 4095) offset)
1804 ((unsigned-byte 31)
1805 (inst* segment 'movw temp (logand offset #xffff))
1806 (when (ldb-test (byte 16 16) offset)
1807 (inst* segment 'movt temp (ldb (byte 16 16) offset)))
1808 temp)))))
1809 (inst* segment 'strb sb-vm::null-tn addr))))