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
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
+
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
)))))
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
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
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
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
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)
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)
148 (byte 5 7) ;; shift_imm
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,
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~^,~}}"
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
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
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
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
347 (define-bitfield-emitter emit-word
32
350 ;;;; miscellaneous hackery
352 (defun register-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
360 (if (assoc (car ,argvar
) +conditions
+)
361 (apply #',internal-emitter
,argvar
)
362 (apply #',internal-emitter
:al
,argvar
)))))
364 (define-instruction byte
(segment byte
)
366 (emit-byte segment byte
)))
368 ;(define-instruction word (segment word)
370 ; (emit-word segment word)))
372 (define-instruction word
(segment word
)
376 (note-fixup segment
:absolute word
)
377 (emit-word segment
0))
379 (emit-word segment word
)))))
381 (defun emit-header-data (segment type
)
382 (emit-back-patch segment
384 (lambda (segment posn
)
388 (component-header-length))
392 (define-instruction simple-fun-header-word
(segment)
394 (emit-header-data segment simple-fun-widetag
)))
396 (define-instruction lra-header-word
(segment)
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
409 (defstruct shifter-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
))
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)
485 (dpb 1 (byte 1 25) (encode-shifter-immediate operand
)))
489 ((eq 'registers
(sb-name (sc-sb (tn-sc operand
))))
490 ;; For those wondering, this is LSL immediate for 0 bits.
493 ((eq 'null
(sc-name (tn-sc operand
)))
496 (t (error "Don't know how to encode TN ~A as a SHIFTER-OPERAND" 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
504 (dpb shift-amount
(byte 5 7)
505 (dpb shift-code
(byte 2 5)
508 (dpb (tn-offset shift-amount
) (byte 4 8)
509 (dpb shift-code
(byte 2 5)
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
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
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
)
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)))
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
)))))
555 ,@(instruction acc op neg-op
))
557 `((inst mvn
,r
,acc
))))))
558 `(let* ((,transformed
,(if fixnumize
561 (,value
(ldb (byte 32 0)
563 `((if (< ,transformed
0) (- ,transformed
) ,transformed
))
565 `((lognot ,transformed
))
567 (,acc
(or ,temporary
,r
)))
569 `((if (encodable-immediate ,transformed
)
570 (inst ,single-op-op
,r
,x
,transformed
)
571 (progn ,@(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
584 (defstruct memory-operand
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
)
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
))
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
)
619 (null (cddr offset
)))
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
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))))
657 '('(:name cond
:tab rn
", " rm shift
)))
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))))
665 '('(:name cond
:tab rn
", " rm
", " shift-type
" " rs
)))
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))))
673 '('(:name cond
:tab rn
", " immediate
)))
675 '('(:name cond
:tab rd
", " immediate
)))))
677 (with-condition-defaulted (args (condition ,@(if dest-p
'(dest))
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
)
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
738 (ldb (byte 4 12) ,imm
)
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
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
)))
763 (with-condition-defaulted (args (condition code
))
764 (emit-swi-instruction segment
765 (conditional-opcode condition
)
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
)
773 (emit-bkpt-instruction segment
#b1110
#b00010010
774 (ldb (byte 12 4) code
)
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
)
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
)
798 '(:name cond
:tab rd
", " rm
))
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
)
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
)
821 (- (label-position dest
)
824 (define-instruction b
(segment &rest args
)
825 (:printer branch
((opcode-4 #b1010
)))
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
)))
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
)
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
)
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
))
875 (dpb #b1001
(byte 4 4) (tn-offset value
))))
877 (define-instruction swp
(segment &rest args
)
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
)
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
)
896 '(:name cond
:tab rd
", CPSR"))
897 (:printer dp-shift-immediate
((opcode-8 #b0010100
)
901 '(:name cond
:tab rd
", SPSR"))
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
))
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
)))))
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
())
935 (with-condition-defaulted (args (condition field-mask src
))
936 (aver (or (register-p 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
)
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))
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
)
960 (opcode-4 ,opcode2
)))
962 (with-condition-defaulted (args (condition ,@arglist
))
965 collect
`(aver (register-p ,arg
)))
966 (emit-multiply-instruction segment
(conditional-opcode condition
)
969 ,(ecase field-mapping
971 (:dnsm
'(tn-offset num
))
972 (:ddsm
'(tn-offset dest-lo
)))
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
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
1026 :post-index
#b00000
)))
1027 (reduce #'logior
(list kind width direction mode
)
1028 :key
(lambda (value) (getf opcode-bits value
))))))
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
)))
1040 (lambda (segment posn
)
1041 (let* ((label-delta (- (label-position base
)
1043 (offset-delta (if (eq direction
:up
)
1046 (overall-delta (+ label-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)
1055 pc-offset
(tn-offset data
)
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
)
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
))))))
1071 ;; FIXME: This is for stack TN references, and needs must be
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
1082 (opcode-l ,(ecase kind
1085 (:printer load
/store-register
((opcode-3 #b011
)
1087 (opcode-b ,(ecase width
1090 (opcode-l ,(ecase kind
1094 (with-condition-defaulted (args (condition reg address
))
1095 (aver (or (register-p reg
)
1096 ,@(when (eq :store kind
)
1098 (eq 'null
(sc-name (tn-sc reg
))))))))
1099 (emit-load/store-instruction segment condition
1101 (if (register-p reg
) reg null-tn
)
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
1124 :post-index
#b00000
)))
1125 (reduce #'logior
(list kind direction mode
)
1126 :key
(lambda (value) (getf opcode-bits value
))))))
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
)))
1138 (lambda (segment posn
)
1139 (let* ((label-delta (- (label-position base
)
1141 (offset-delta (if (eq direction
:up
)
1144 (overall-delta (+ label-delta
1146 (absolute-delta (abs overall-delta
)))
1147 (aver (typep absolute-delta
'(unsigned-byte 8)))
1148 (emit-multiply-instruction segment cond-bits
1150 (compute-opcode :immedaite
1151 (if (< overall-delta
0)
1155 pc-offset
(tn-offset data
)
1156 (ldb (byte 4 4) absolute-delta
)
1157 opcode2 absolute-delta
)))))
1159 (aver (typep offset
'(unsigned-byte 8)))
1160 (emit-multiply-instruction segment cond-bits
1162 (compute-opcode :immediate direction mode
))
1163 (tn-offset base
) (tn-offset data
)
1164 (ldb (byte 4 4) offset
)
1166 ((register-p offset
)
1167 (emit-multiply-instruction segment cond-bits
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"
1178 ;; FIXME: This is for stack TN references, and needs must be
1183 ((define-misc-load/store-instruction
(name opcode1 opcode2 double-width
)
1184 `(define-instruction ,name
(segment &rest args
)
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
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
)
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.
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
)
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
)
1247 other-pointer-lowtag
)
1248 ;; The 8 below is the displacement
1249 ;; from reading the program counter.
1252 (load-chunk (segment delta dst src chunk
)
1253 (assemble (segment vop
)
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
)
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
)
1301 ;; We need to emit up to three instructions, which is 12 octets.
1302 ;; This preserves a mere two bits of alignment.
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
)
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
)
1328 ;; The 8 below is the displacement
1329 ;; from reading the program counter.
1332 (load-chunk (segment delta dst src chunk
)
1333 (assemble (segment vop
)
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
)
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.
1363 #'two-instruction-maybe-shrink
1364 #'two-instruction-emitter
)))))
1366 (define-instruction adr
(segment code label
&optional
(offset 0))
1371 (lambda (segment position
)
1372 (assemble (segment vop
)
1373 (let ((offset (+ (- (label-position label
)
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
1383 (byte 4 24) ; #b1110
1388 (byte 4 16) ; Fn || extension op
1391 (byte 1 8) ; double/single precission
1392 (byte 1 7) ; N || extension op
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
1408 `(define-instruction ,name
(segment &rest args
)
1409 (:printer fp-binary
((p ,p
)
1413 (size ,precision-flag
)))
1415 (with-condition-defaulted (args (condition dest op-n op-m
))
1416 (emit-fp-dp-instruction segment
1417 (conditional-opcode condition
)
1420 (low-bit-float-reg dest
)
1423 (high-bits-float-reg op-n
)
1424 (high-bits-float-reg dest
)
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
)
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
1451 (let ((precision-flag (ecase precision
1454 `(define-instruction ,name
(segment &rest args
)
1455 (:printer
,(if op-m-sbz
1458 ((size ,precision-flag
)
1462 (with-condition-defaulted (args (condition dest
1465 (emit-fp-dp-instruction segment
1466 (conditional-opcode condition
)
1469 (low-bit-float-reg dest
)
1473 (high-bits-float-reg dest
)
1480 '(low-bit-float-reg op-m
))
1484 '(high-bits-float-reg op-m
))))))))
1486 (defmacro define-unary-fp-data-processing-instructions
(root fn n
&key op-m-sbz
)
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
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
1536 (direction-flag (ecase direction
1539 `(define-instruction ,name
(segment &rest args
)
1541 (with-condition-defaulted (args (condition address base-reg reg-count
))
1547 ((:unindexed
:increment
) 0)
1550 ((:unindexed
:increment
) 1)
1554 ((:increment
:decrement
) 1))))
1555 (emit-fp-ls-instruction segment
1556 (conditional-opcode condition
)
1560 (low-bit-float-reg base-reg
)
1564 (high-bits-float-reg base-reg
)
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
1602 (direction-flag (ecase direction
1605 `(define-instruction ,name
(segment &rest args
)
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.
1616 (emit-fp-ls-instruction segment
1617 (conditional-opcode condition
)
1620 (if (eq direction
:up
) 1 0)
1621 (low-bit-float-reg float-reg
)
1625 (high-bits-float-reg float-reg
)
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
1640 (byte 4 24) ; #b1110
1647 (byte 1 8) ; precision
1650 (byte 7 0)) ; #b0010000
1652 (define-bitfield-emitter emit-conditional-instruction
32
1656 ;;; This has the same encoding as FMRX R15, FPSCR
1657 (define-instruction fmstat
(segment &rest args
)
1658 (:printer conditional
1661 (with-condition-defaulted (args (condition))
1662 (emit-conditional-instruction segment
1663 (conditional-opcode condition
)
1666 (defun system-reg-encoding (float-reg)
1672 (defmacro define-single-reg-transfer-fp-instruction
(name precision direction opcode
&optional system-reg
)
1673 (let ((precision-flag (ecase precision
1676 (direction-flag (ecase direction
1679 `(define-instruction ,name
(segment &rest args
)
1680 (:printer
,(if system-reg
1685 (size ,precision-flag
))
1686 ',(if (eq direction
:to-arm
)
1687 '(:name cond
:tab rd
", " fn
)
1688 '(:name cond
:tab fn
", " rd
)))
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
)
1699 '(system-reg-encoding float-reg
)
1700 '(high-bits-float-reg float-reg
))
1706 '(low-bit-float-reg float-reg
))
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
1720 (byte 7 21) ; #b1100010
1725 (byte 1 8) ; precision
1731 (defmacro define-two-reg-transfer-fp-instruction
(name precision direction
)
1732 (let ((precision-flag (ecase precision
1735 (direction-flag (ecase direction
1738 `(define-instruction ,name
(segment &rest args
)
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
)))
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
)
1753 (tn-offset arm-reg-2
)
1754 (tn-offset arm-reg-1
)
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
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
)))
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)))))
1787 (setf (sap-ref-32 sap offset
) value
))))
1790 (define-instruction store-coverage-mark
(segment mark-index temp
)
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))
1799 (- other-pointer-lowtag
)))
1803 ((integer 0 4095) offset
)
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
)))
1809 (inst* segment
'strb sb-vm
::null-tn addr
))))