]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/arm/disassembler.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / dev / arm / disassembler.c
1 /*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 *
4 * Disassemblers for ARM (arm), Thumb (thumb16), and Thumb2 (thumb32).
5 *
6 * Each disassembly begins with a call to dtrace_decode_arm or dtrace_decode_thumb. The thumb
7 * decoder will then call dtrace_decode_thumb16 or dtrace_decode_thumb32 as appropriate.
8 *
9 * The respective disassembly functions are all of the form {arm,thumb16,thumb32}_type. They
10 * follow the ordering and breakdown in the ARMv7 Architecture Reference Manual.
11 */
12
13 #include <sys/fasttrap_isa.h>
14
15 #define BITS(x, n, mask) (((x) >> (n)) & (mask))
16
17 static uint32_t
18 thumb32_instword_to_arm(uint16_t hw1, uint16_t hw2)
19 {
20 return (hw1 << 16) | hw2;
21 }
22
23 int dtrace_decode_arm(uint32_t instr);
24 int dtrace_decode_thumb(uint32_t instr);
25
26 /*
27 * VFP decoder - shared between ARM and THUMB32 mode
28 */
29
30 static
31 int
32 vfp_struct_loadstore(uint32_t instr)
33 {
34 if (ARM_RM(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
35 return FASTTRAP_T_COMMON;
36 }
37
38 return FASTTRAP_T_INV;
39 }
40
41 static
42 int
43 vfp_64transfer(uint32_t instr)
44 {
45 /* These instructions all use RD and RN */
46 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
47 return FASTTRAP_T_COMMON;
48 }
49
50 return FASTTRAP_T_INV;
51 }
52
53 static
54 int
55 vfp_transfer(uint32_t instr)
56 {
57 /* These instructions all use RD only */
58 if (ARM_RD(instr) != REG_PC) {
59 return FASTTRAP_T_COMMON;
60 }
61
62 return FASTTRAP_T_INV;
63 }
64
65 static
66 int
67 vfp_loadstore(uint32_t instr)
68 {
69 int opcode = BITS(instr, 20, 0x1F);
70
71 /* Instrument VLDR */
72 if ((opcode & 0x13) == 0x11 && ARM_RN(instr) == REG_PC) {
73 return FASTTRAP_T_VLDR_PC_IMMED;
74 }
75
76 /* These instructions all use RN only */
77 if (ARM_RN(instr) != REG_PC) {
78 return FASTTRAP_T_COMMON;
79 }
80
81 return FASTTRAP_T_INV;
82 }
83
84 /*
85 * ARM decoder
86 */
87
88 static
89 int
90 arm_unconditional_misc(uint32_t instr)
91 {
92 int op = BITS(instr, 20, 0x7F);
93
94 if ((op & 0x60) == 0x20) {
95 /* VFP data processing uses its own registers */
96 return FASTTRAP_T_COMMON;
97 }
98
99 if ((op & 0x71) == 0x40) {
100 return vfp_struct_loadstore(instr);
101 }
102
103 return FASTTRAP_T_INV;
104 }
105
106 static
107 int
108 arm_unconditional(uint32_t instr)
109 {
110 if (BITS(instr, 27, 0x1) == 0) {
111 return arm_unconditional_misc(instr);
112 }
113
114 /* The rest are privileged or BL/BLX, do not instrument */
115
116 /* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
117
118 return FASTTRAP_T_INV;
119 }
120
121 static
122 int
123 arm_syscall_coproc(uint32_t instr)
124 {
125 /* Instrument any VFP data processing instructions, ignore the rest */
126
127 int op1 = BITS(instr, 20, 0x3F), coproc = BITS(instr, 8, 0xF), op = BITS(instr, 4, 0x1);
128
129 if ((op1 & 0x3E) == 0 || (op1 & 0x30) == 0x30) {
130 /* Undefined or swi */
131 return FASTTRAP_T_INV;
132 }
133
134 if ((coproc & 0xE) == 0xA) {
135 /* VFP instruction */
136
137 if ((op1 & 0x20) == 0 && (op1 & 0x3A) != 0) {
138 return vfp_loadstore(instr);
139 }
140
141 if ((op1 & 0x3E) == 0x04) {
142 return vfp_64transfer(instr);
143 }
144
145 if ((op1 & 0x30) == 0x20) {
146 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
147 if (op == 0) {
148 /* VFP data processing uses its own registers */
149 return FASTTRAP_T_COMMON;
150 } else {
151 return vfp_transfer(instr);
152 }
153 }
154 }
155
156 return FASTTRAP_T_INV;
157 }
158
159 static
160 int
161 arm_branch_link_blockdata(uint32_t instr)
162 {
163 int branch = BITS(instr, 25, 0x1), link = BITS(instr, 24, 0x1), op = BITS(instr, 20, 0x1F), uses_pc = BITS(instr, 15, 0x1), uses_lr = BITS(instr, 14, 0x1);
164
165 if (branch == 1) {
166 if (link == 0) {
167 return FASTTRAP_T_B_COND;
168 }
169 return FASTTRAP_T_INV;
170 } else {
171 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc } */
172 if (op == 0x0B && ARM_RN(instr) == REG_SP && uses_pc == 1) {
173 return FASTTRAP_T_LDM_PC;
174 }
175
176 /* stmia sp!, { ... lr } doesn't touch the pc, but it is very common, so special case it */
177 if (op == 0x12 && ARM_RN(instr) == REG_SP && uses_lr == 1) {
178 return FASTTRAP_T_STM_LR;
179 }
180
181 if (ARM_RN(instr) != REG_PC && uses_pc == 0) {
182 return FASTTRAP_T_COMMON;
183 }
184 }
185
186 return FASTTRAP_T_INV;
187 }
188
189 static
190 int
191 arm_signed_multiplies(uint32_t instr)
192 {
193 int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
194
195 /* smlald, smlsld, smmls use RD in addition to RM, RS, and RN */
196 if ((op1 == 0x4 && (op2 & 0x4) == 0) || (op1 == 0x5 && (op2 & 0x6) == 0x6)) {
197 if (ARM_RD(instr) == REG_PC) {
198 return FASTTRAP_T_INV;
199 }
200 }
201
202 if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
203 return FASTTRAP_T_COMMON;
204 }
205
206 return FASTTRAP_T_INV;
207 }
208
209 static
210 int
211 arm_pack_unpack_sat_reversal(uint32_t instr)
212 {
213 int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
214
215 /* pkh, sel use RN in addition to RD and RM */
216 if ((op1 == 0 && (op2 & 0x1) == 0) || (op1 == 0 && op2 == 0x5)) {
217 if (ARM_RN(instr) == REG_PC) {
218 return FASTTRAP_T_INV;
219 }
220 }
221
222 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
223 return FASTTRAP_T_COMMON;
224 }
225
226 return FASTTRAP_T_INV;
227 }
228
229 static
230 int
231 arm_parallel_addsub_unsigned(uint32_t instr)
232 {
233 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
234 return FASTTRAP_T_COMMON;
235 }
236
237 return FASTTRAP_T_INV;
238 }
239
240 static
241 int
242 arm_parallel_addsub_signed(uint32_t instr)
243 {
244 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
245 return FASTTRAP_T_COMMON;
246 }
247
248 return FASTTRAP_T_INV;
249 }
250
251 static
252 int
253 arm_media(uint32_t instr)
254 {
255 int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 5, 0x7);
256
257 if ((op1 & 0x1C) == 0) {
258 return arm_parallel_addsub_signed(instr);
259 }
260
261 if ((op1 & 0x1C) == 0x04) {
262 return arm_parallel_addsub_unsigned(instr);
263 }
264
265 if ((op1 & 0x18) == 0x08) {
266 return arm_pack_unpack_sat_reversal(instr);
267 }
268
269 if ((op1 & 0x18) == 0x10) {
270 return arm_signed_multiplies(instr);
271 }
272
273 if (op1 == 0x1F && op2 == 0x7) {
274 /* Undefined instruction */
275 return FASTTRAP_T_INV;
276 }
277
278 if (op1 == 0x18 && op2 == 0) {
279 /* usad8 usada8 */
280 /* The registers are named differently in the reference manual for this instruction
281 * but the following positions are correct */
282
283 if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
284 return FASTTRAP_T_COMMON;
285 }
286
287 return FASTTRAP_T_INV;
288 }
289
290 if ((op1 & 0x1E) == 0x1C && (op2 & 0x3) == 0) {
291 /* bfc bfi */
292 if (ARM_RD(instr) != REG_PC) {
293 return FASTTRAP_T_COMMON;
294 }
295
296 return FASTTRAP_T_INV;
297 }
298
299 if (((op1 & 0x1E) == 0x1A || (op1 & 0x1E) == 0x1E) && ((op2 & 0x3) == 0x2)) {
300 /* sbfx ubfx */
301 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
302 return FASTTRAP_T_COMMON;
303 }
304
305 return FASTTRAP_T_INV;
306 }
307
308 return FASTTRAP_T_INV;
309 }
310
311 static
312 int
313 arm_loadstore_wordbyte(uint32_t instr)
314 {
315 /* Instrument PC relative load with immediate, ignore any other uses of the PC */
316 int R = BITS(instr, 25, 0x1), L = BITS(instr, 20, 0x1);
317
318 if (R == 1) {
319 /* Three register load/store */
320 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
321 return FASTTRAP_T_COMMON;
322 }
323 } else {
324 /* Immediate load/store, but still do not support ldr pc, [pc...] */
325 if (L == 1 && ARM_RN(instr) == REG_PC && ARM_RD(instr) != REG_PC) {
326 return FASTTRAP_T_LDR_PC_IMMED;
327 }
328
329 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
330 return FASTTRAP_T_COMMON;
331 }
332 }
333
334 return FASTTRAP_T_INV;
335 }
336
337 static
338 int
339 arm_saturating(uint32_t instr)
340 {
341 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
342 return FASTTRAP_T_COMMON;
343 }
344
345 return FASTTRAP_T_INV;
346 }
347
348 static
349 int
350 arm_misc(uint32_t instr)
351 {
352 int op = BITS(instr, 21, 0x3), __unused op1 = BITS(instr, 16, 0xF), op2 = BITS(instr, 4, 0x7);
353
354 if (op2 == 1 && op == 1) {
355 return FASTTRAP_T_BX_REG;
356 }
357
358 /* We do not need to emulate BLX for entry/return probes; if we eventually support full offset
359 * tracing, then we will. This is because BLX overwrites the link register, so a function that
360 * can execute this as its first instruction is a special function indeed.
361 */
362
363 if (op2 == 0x5) {
364 return arm_saturating(instr);
365 }
366
367 return FASTTRAP_T_INV;
368 }
369
370 static
371 int
372 arm_msr_hints(__unused uint32_t instr)
373 {
374 /* These deal with the psr, not instrumented */
375
376 return FASTTRAP_T_INV;
377 }
378
379 static
380 int
381 arm_sync_primitive(__unused uint32_t instr)
382 {
383 /* TODO will instrumenting these interfere with any kernel usage of these instructions? */
384 /* Don't instrument for now */
385
386 return FASTTRAP_T_INV;
387 }
388
389 static
390 int
391 arm_extra_loadstore_unpriv(uint32_t instr)
392 {
393 int op = BITS(instr, 20, 0x1), __unused op2 = BITS(instr, 5, 0x3), immed = BITS(instr, 22, 0x1);
394
395 if (op == 0 && (op2 & 0x2) == 0x2) {
396 /* Unpredictable or undefined */
397 return FASTTRAP_T_INV;
398 }
399
400 if (immed == 1) {
401 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
402 return FASTTRAP_T_COMMON;
403 }
404 } else {
405 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
406 return FASTTRAP_T_COMMON;
407 }
408 }
409
410 return FASTTRAP_T_INV;
411 }
412
413 static
414 int
415 arm_extra_loadstore(uint32_t instr)
416 {
417 int op1 = BITS(instr, 20, 0x1F);
418
419 /* There are two variants, and we do not instrument either of them that use the PC */
420
421 if ((op1 & 0x4) == 0) {
422 /* Variant 1, register */
423 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
424 return FASTTRAP_T_COMMON;
425 }
426 } else {
427 /* Variant 2, immediate */
428 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
429 return FASTTRAP_T_COMMON;
430 }
431 }
432
433 return FASTTRAP_T_INV;
434 }
435
436 static
437 int
438 arm_halfword_multiply(uint32_t instr)
439 {
440 /* Not all multiply instructions use all four registers. The ones that don't should have those
441 * register locations set to 0, so we can test them anyway.
442 */
443
444 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
445 return FASTTRAP_T_COMMON;
446 }
447
448 return FASTTRAP_T_INV;
449 }
450
451 static
452 int
453 arm_multiply(uint32_t instr)
454 {
455 /* Not all multiply instructions use all four registers. The ones that don't should have those
456 * register locations set to 0, so we can test them anyway.
457 */
458
459 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
460 return FASTTRAP_T_COMMON;
461 }
462
463 return FASTTRAP_T_INV;
464 }
465
466 static
467 int
468 arm_dataproc_immed(uint32_t instr)
469 {
470 /* All these instructions are either two registers, or one register and have 0 where the other reg would be used */
471 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
472 return FASTTRAP_T_COMMON;
473 }
474
475 return FASTTRAP_T_INV;
476 }
477
478 static
479 int
480 arm_dataproc_regshift(uint32_t instr)
481 {
482 /* All these instructions are either four registers, or three registers and have 0 where there last reg would be used */
483 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
484 return FASTTRAP_T_COMMON;
485 }
486
487 return FASTTRAP_T_INV;
488 }
489
490 static
491 int
492 arm_dataproc_reg(uint32_t instr)
493 {
494 int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 7, 0x1F), op3 = BITS(instr, 5, 0x3);
495
496 if (op1 == 0x11 || op1 == 0x13 || op1 == 0x15 || op1 == 0x17) {
497 /* These are comparison flag setting instructions and do not have RD */
498 if (ARM_RN(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
499 return FASTTRAP_T_COMMON;
500 }
501
502 return FASTTRAP_T_INV;
503 }
504
505 /* The rest can, in theory, write or use the PC. The only one we instrument is mov pc, reg.
506 * movs pc, reg is a privileged instruction so we don't instrument that variant. The s bit
507 * is bit 0 of op1 and should be zero.
508 */
509 if (op1 == 0x1A && op2 == 0 && op3 == 0 && ARM_RD(instr) == REG_PC) {
510 return FASTTRAP_T_MOV_PC_REG;
511 }
512
513 /* Any instruction at this point is a three register instruction or two register instruction with RN = 0 */
514 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
515 return FASTTRAP_T_COMMON;
516 }
517
518 return FASTTRAP_T_INV;
519 }
520
521 static
522 int
523 arm_dataproc_misc(uint32_t instr)
524 {
525 int op = BITS(instr, 25, 0x1), op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 4, 0xF);
526
527 if (op == 0) {
528 if ((op1 & 0x19) != 0x10 && (op2 & 0x1) == 0) {
529 return arm_dataproc_reg(instr);
530 }
531
532 if ((op1 & 0x19) != 0x10 && (op2 & 0x9) == 0x1) {
533 return arm_dataproc_regshift(instr);
534 }
535
536 if ((op1 & 0x19) == 0x10 && (op2 & 0x8) == 0) {
537 return arm_misc(instr);
538 }
539
540 if ((op1 & 0x19) == 0x19 && (op2 & 0x9) == 0x8) {
541 return arm_halfword_multiply(instr);
542 }
543
544 if ((op1 & 0x10) == 0 && op2 == 0x9) {
545 return arm_multiply(instr);
546 }
547
548 if ((op1 & 0x10) == 0x10 && op2 == 0x9) {
549 return arm_sync_primitive(instr);
550 }
551
552 if ((op1 & 0x12) != 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
553 return arm_extra_loadstore(instr);
554 }
555
556 if ((op1 & 0x12) == 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
557 return arm_extra_loadstore_unpriv(instr);
558 }
559 } else {
560 if ((op1 & 0x19) != 0x10) {
561 return arm_dataproc_immed(instr);
562 }
563
564 if (op1 == 0x10) {
565 /* 16 bit immediate load (mov (immed)) [encoding A2] */
566 if (ARM_RD(instr) != REG_PC) {
567 return FASTTRAP_T_COMMON;
568 }
569
570 return FASTTRAP_T_INV;
571 }
572
573 if (op1 == 0x14) {
574 /* high halfword 16 bit immediate load (movt) [encoding A1] */
575 if (ARM_RD(instr) != REG_PC) {
576 return FASTTRAP_T_COMMON;
577 }
578
579 return FASTTRAP_T_INV;
580 }
581
582 if ((op1 & 0x1B) == 0x12) {
583 return arm_msr_hints(instr);
584 }
585 }
586
587 return FASTTRAP_T_INV;
588 }
589
590 int
591 dtrace_decode_arm(uint32_t instr)
592 {
593 int cond = BITS(instr, 28, 0xF), op1 = BITS(instr, 25, 0x7), op = BITS(instr, 4, 0x1);
594
595 if (cond == 0xF) {
596 return arm_unconditional(instr);
597 }
598
599 if ((op1 & 0x6) == 0) {
600 return arm_dataproc_misc(instr);
601 }
602
603 if (op1 == 0x2) {
604 return arm_loadstore_wordbyte(instr);
605 }
606
607 if (op1 == 0x3 && op == 0) {
608 return arm_loadstore_wordbyte(instr);
609 }
610
611 if (op1 == 0x3 && op == 1) {
612 return arm_media(instr);
613 }
614
615 if ((op1 & 0x6) == 0x4) {
616 return arm_branch_link_blockdata(instr);
617 }
618
619 if ((op1 & 0x6) == 0x6) {
620 return arm_syscall_coproc(instr);
621 }
622
623 return FASTTRAP_T_INV;
624 }
625
626
627 /*
628 * Thumb 16-bit decoder
629 */
630
631 static
632 int
633 thumb16_cond_supervisor(uint16_t instr)
634 {
635 int opcode = BITS(instr, 8, 0xF);
636
637 if ((opcode & 0xE) != 0xE) {
638 return FASTTRAP_T_B_COND;
639 }
640
641 return FASTTRAP_T_INV;
642 }
643
644 static
645 int
646 thumb16_misc(uint16_t instr)
647 {
648 int opcode = BITS(instr, 5, 0x7F);
649
650 if ((opcode & 0x70) == 0x30 || (opcode & 0x70) == 0x70) {
651 /* setend, cps, breakpoint, or if-then, not instrumentable */
652 return FASTTRAP_T_INV;
653 } else if ((opcode & 0x78) == 0x28) {
654 /* Doesn't modify pc, but this happens a lot so make this a special case for emulation */
655 return FASTTRAP_T_PUSH_LR;
656 } else if ((opcode & 0x78) == 0x68) {
657 return FASTTRAP_T_POP_PC;
658 } else if ((opcode & 0x28) == 0x08) {
659 return FASTTRAP_T_CB_N_Z;
660 }
661
662 /* All other instructions work on low regs only and are instrumentable */
663 return FASTTRAP_T_COMMON;
664 }
665
666 static
667 int
668 thumb16_loadstore_single(__unused uint16_t instr)
669 {
670 /* These all access the low registers or SP only */
671 return FASTTRAP_T_COMMON;
672 }
673
674 static
675 int
676 thumb16_data_special_and_branch(uint16_t instr)
677 {
678 int opcode = BITS(instr, 6, 0xF);
679
680 if (opcode == 0x4) {
681 /* Unpredictable */
682 return FASTTRAP_T_INV;
683 } else if ((opcode & 0xC) == 0xC) {
684 /* bx or blx */
685 /* Only instrument the bx */
686 if ((opcode & 0x2) == 0) {
687 return FASTTRAP_T_BX_REG;
688 }
689 return FASTTRAP_T_INV;
690 } else {
691 /* Data processing on high registers, only instrument mov pc, reg */
692 if ((opcode & 0xC) == 0x8 && THUMB16_HRD(instr) == REG_PC) {
693 return FASTTRAP_T_CPY_PC;
694 }
695
696 if (THUMB16_HRM(instr) != REG_PC && THUMB16_HRD(instr) != REG_PC) {
697 return FASTTRAP_T_COMMON;
698 }
699 }
700
701 return FASTTRAP_T_INV;
702 }
703
704 static
705 int
706 thumb16_data_proc(__unused uint16_t instr)
707 {
708 /* These all access the low registers only */
709 return FASTTRAP_T_COMMON;
710 }
711
712 static
713 int
714 thumb16_shift_addsub_move_compare(__unused uint16_t instr)
715 {
716 /* These all access the low registers only */
717 return FASTTRAP_T_COMMON;
718 }
719
720 static
721 int
722 dtrace_decode_thumb16(uint16_t instr)
723 {
724 int opcode = BITS(instr, 10, 0x3F);
725
726 if ((opcode & 0x30) == 0) {
727 return thumb16_shift_addsub_move_compare(instr);
728 }
729
730 if (opcode == 0x10) {
731 return thumb16_data_proc(instr);
732 }
733
734 if (opcode == 0x11) {
735 return thumb16_data_special_and_branch(instr);
736 }
737
738 if ((opcode & 0x3E) == 0x12) {
739 /* ldr (literal) */
740 return FASTTRAP_T_LDR_PC_IMMED;
741 }
742
743 if ((opcode & 0x3C) == 0x14 || (opcode & 0x38) == 0x18 || (opcode & 0x38) == 0x20) {
744 return thumb16_loadstore_single(instr);
745 }
746
747 if ((opcode & 0x3E) == 0x28) {
748 /* adr, uses the pc */
749 return FASTTRAP_T_INV;
750 }
751
752 if ((opcode & 0x3E) == 0x2A) {
753 /* add (sp plus immediate) */
754 return FASTTRAP_T_COMMON;
755 }
756
757 if ((opcode & 0x3C) == 0x2C) {
758 return thumb16_misc(instr);
759 }
760
761 if ((opcode & 0x3E) == 0x30) {
762 /* stm - can't access high registers */
763 return FASTTRAP_T_COMMON;
764 }
765
766 if ((opcode & 0x3E) == 0x32) {
767 /* ldm - can't access high registers */
768 return FASTTRAP_T_COMMON;
769 }
770
771 if ((opcode & 0x3C) == 0x34) {
772 return thumb16_cond_supervisor(instr);
773 }
774
775 if ((opcode & 0x3E) == 0x38) {
776 /* b unconditional */
777 return FASTTRAP_T_B_UNCOND;
778 }
779
780 return FASTTRAP_T_INV;
781 }
782
783 /*
784 * Thumb 32-bit decoder
785 */
786
787 static
788 int
789 thumb32_coproc(uint16_t instr1, uint16_t instr2)
790 {
791 /* Instrument any VFP data processing instructions, ignore the rest */
792
793 int op1 = BITS(instr1, 4, 0x3F), coproc = BITS(instr2, 8, 0xF), op = BITS(instr2, 4, 0x1);
794
795 if ((op1 & 0x3E) == 0) {
796 /* Undefined */
797 return FASTTRAP_T_INV;
798 }
799
800 if ((coproc & 0xE) == 0xA || (op1 & 0x30) == 0x30) {
801 /* VFP instruction */
802 uint32_t instr = thumb32_instword_to_arm(instr1, instr2);
803
804 if ((op1 & 0x30) == 0x30) {
805 /* VFP data processing uses its own registers */
806 return FASTTRAP_T_COMMON;
807 }
808
809 if ((op1 & 0x3A) == 0x02 || (op1 & 0x38) == 0x08 || (op1 & 0x30) == 0x10) {
810 return vfp_loadstore(instr);
811 }
812
813 if ((op1 & 0x3E) == 0x04) {
814 return vfp_64transfer(instr);
815 }
816
817 if ((op1 & 0x30) == 0x20) {
818 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
819 if (op == 0) {
820 /* VFP data processing uses its own registers */
821 return FASTTRAP_T_COMMON;
822 } else {
823 return vfp_transfer(instr);
824 }
825 }
826 }
827
828 return FASTTRAP_T_INV;
829 }
830
831 static
832 int
833 thumb32_longmultiply(uint16_t instr1, uint16_t instr2)
834 {
835 int op1 = BITS(instr1, 4, 0x7), op2 = BITS(instr2, 4, 0xF);
836
837 if ((op1 == 1 && op2 == 0xF) || (op1 == 0x3 && op2 == 0xF)) {
838 /* Three register instruction */
839 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
840 return FASTTRAP_T_COMMON;
841 }
842 } else {
843 /* Four register instruction */
844 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC &&
845 THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
846 return FASTTRAP_T_COMMON;
847 }
848 }
849
850 return FASTTRAP_T_INV;
851 }
852
853 static
854 int
855 thumb32_multiply(uint16_t instr1, uint16_t instr2)
856 {
857 int op1 = BITS(instr1, 4, 0x7), op2 = BITS(instr2, 4, 0x3);
858
859 if ((op1 == 0 && op2 == 1) || (op1 == 0x6 && (op2 & 0x2) == 0)) {
860 if (THUMB32_RT(instr1, instr2) == REG_PC) {
861 return FASTTRAP_T_INV;
862 }
863 }
864
865 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
866 return FASTTRAP_T_COMMON;
867 }
868
869 return FASTTRAP_T_INV;
870 }
871
872 static
873 int
874 thumb32_misc(uint16_t instr1, uint16_t instr2)
875 {
876 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
877 return FASTTRAP_T_COMMON;
878 }
879
880 return FASTTRAP_T_INV;
881 }
882
883 static
884 int
885 thumb32_parallel_addsub_unsigned(uint16_t instr1, uint16_t instr2)
886 {
887 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
888 return FASTTRAP_T_COMMON;
889 }
890
891 return FASTTRAP_T_INV;
892 }
893
894 static
895 int
896 thumb32_parallel_addsub_signed(uint16_t instr1, uint16_t instr2)
897 {
898 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
899 return FASTTRAP_T_COMMON;
900 }
901
902 return FASTTRAP_T_INV;
903 }
904
905 static
906 int
907 thumb32_dataproc_reg(uint16_t instr1, uint16_t instr2)
908 {
909 int op1 = BITS(instr1, 4, 0xF), op2 = BITS(instr2, 4, 0xF);
910
911 if (((0 <= op1) && (op1 <= 5)) && (op2 & 0x8) == 0x8) {
912 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC) {
913 return FASTTRAP_T_COMMON;
914 }
915 }
916
917 if ((op1 & 0x8) == 0 && op2 == 0) {
918 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
919 return FASTTRAP_T_COMMON;
920 }
921 }
922
923 if ((op1 & 0x8) == 0x8 && (op2 & 0xC) == 0) {
924 return thumb32_parallel_addsub_signed(instr1, instr2);
925 }
926
927 if ((op1 & 0x8) == 0x8 && (op2 & 0xC) == 0x4) {
928 return thumb32_parallel_addsub_unsigned(instr1, instr2);
929 }
930
931 if ((op1 & 0xC) == 0x8 && (op2 & 0xC) == 0x8) {
932 return thumb32_misc(instr1, instr2);
933 }
934
935 return FASTTRAP_T_INV;
936 }
937
938 static
939 int
940 thumb32_dataproc_regshift(uint16_t instr1, uint16_t instr2)
941 {
942 int op = BITS(instr1, 5, 0xF), S = BITS(instr1, 4, 0x1);
943
944 if (op == 0 || op == 0x4 || op == 0x8 || op == 0xD) {
945 /* These become test instructions if S is 1 and Rd is PC, otherwise they are data instructions. */
946 if (S == 1) {
947 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
948 return FASTTRAP_T_COMMON;
949 }
950 } else {
951 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC &&
952 THUMB32_RN(instr1, instr2) != REG_PC) {
953 return FASTTRAP_T_COMMON;
954 }
955 }
956 } else if (op == 0x2 || op == 0x3) {
957 /* These become moves if RN is PC, otherwise they are data insts. We don't instrument mov pc, reg here */
958 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC) {
959 return FASTTRAP_T_COMMON;
960 }
961 } else {
962 /* Normal three register instruction */
963 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
964 return FASTTRAP_T_COMMON;
965 }
966 }
967
968 return FASTTRAP_T_INV;
969 }
970
971 static
972 int
973 thumb32_store_single(uint16_t instr1, uint16_t instr2)
974 {
975 int op1 = BITS(instr1, 5, 0x7), op2 = BITS(instr2, 6, 0x3F);
976
977 /* Do not support any use of the pc yet */
978 if ((op1 == 0 || op1 == 1 || op1 == 2) && (op2 & 0x20) == 0) {
979 /* str (register) uses RM */
980 if (THUMB32_RM(instr1, instr2) == REG_PC) {
981 return FASTTRAP_T_INV;
982 }
983 }
984
985 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
986 return FASTTRAP_T_COMMON;
987 }
988
989 return FASTTRAP_T_INV;
990 }
991
992 static
993 int
994 thumb32_loadbyte_memhint(uint16_t instr1, uint16_t instr2)
995 {
996 int op1 = BITS(instr1, 7, 0x3), __unused op2 = BITS(instr2, 6, 0x3F);
997
998 /* Do not support any use of the pc yet */
999 if ((op1 == 0 || op1 == 0x2) && THUMB32_RM(instr1, instr2) == REG_PC) {
1000 return FASTTRAP_T_INV;
1001 }
1002
1003 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
1004 return FASTTRAP_T_COMMON;
1005 }
1006
1007 return FASTTRAP_T_INV;
1008 }
1009
1010 static
1011 int
1012 thumb32_loadhalfword_memhint(uint16_t instr1, uint16_t instr2)
1013 {
1014 int op1 = BITS(instr1, 7, 0x3), op2 = BITS(instr2, 6, 0x3F);
1015
1016 /* Do not support any use of the PC yet */
1017 if (op1 == 0 && op2 == 0 && THUMB32_RM(inst1, instr2) == REG_PC) {
1018 return FASTTRAP_T_INV;
1019 }
1020
1021 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
1022 return FASTTRAP_T_COMMON;
1023 }
1024
1025 return FASTTRAP_T_INV;
1026 }
1027
1028 static
1029 int
1030 thumb32_loadword(uint16_t instr1, uint16_t instr2)
1031 {
1032 int op1 = BITS(instr1, 7, 0x3), op2 = BITS(instr2, 6, 0x3F);
1033
1034 if ((op1 & 0x2) == 0 && THUMB32_RN(instr1, instr2) == REG_PC && THUMB32_RT(instr1, instr2) != REG_PC) {
1035 return FASTTRAP_T_LDR_PC_IMMED;
1036 }
1037
1038 if (op1 == 0 && op2 == 0) {
1039 /* ldr (register) uses an additional reg */
1040 if (THUMB32_RM(instr1, instr2) == REG_PC) {
1041 return FASTTRAP_T_INV;
1042 }
1043 }
1044
1045 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
1046 return FASTTRAP_T_COMMON;
1047 }
1048
1049 return FASTTRAP_T_INV;
1050 }
1051
1052 static
1053 int
1054 thumb32_loadstore_double_exclusive_table(__unused uint16_t instr1, __unused uint16_t instr2)
1055 {
1056 /* Don't instrument any of these */
1057
1058 return FASTTRAP_T_INV;
1059 }
1060
1061 static
1062 int
1063 thumb32_loadstore_multiple(uint16_t instr1, uint16_t instr2)
1064 {
1065 int op = BITS(instr1, 7, 0x3), L = BITS(instr1, 4, 0x1), uses_pc = BITS(instr2, 15, 0x1), uses_lr = BITS(instr2, 14, 0x1);
1066
1067 if (op == 0 || op == 0x3) {
1068 /* Privileged instructions: srs, rfe */
1069 return FASTTRAP_T_INV;
1070 }
1071
1072 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc }, aka pop { ... pc } */
1073 if (op == 0x1 && L == 1 && THUMB32_RN(instr1, instr2) == REG_SP && uses_pc == 1) {
1074 return FASTTRAP_T_LDM_PC;
1075 }
1076
1077 /* stmia sp!, { ... lr }, aka push { ... lr } doesn't touch the pc, but it is very common, so special case it */
1078 if (op == 0x2 && L == 0 && THUMB32_RN(instr1, instr2) == REG_SP && uses_lr == 1) {
1079 return FASTTRAP_T_STM_LR;
1080 }
1081
1082 if (THUMB32_RN(instr1, instr2) != REG_PC && uses_pc == 0) {
1083 return FASTTRAP_T_COMMON;
1084 }
1085
1086 return FASTTRAP_T_INV;
1087 }
1088
1089 static
1090 int
1091 thumb32_misc_control(__unused uint16_t instr1, __unused uint16_t instr2)
1092 {
1093 /* Privileged, and instructions dealing with ThumbEE */
1094 return FASTTRAP_T_INV;
1095 }
1096
1097 static
1098 int
1099 thumb32_cps_hints(__unused uint16_t instr1, __unused uint16_t instr2)
1100 {
1101 /* Privileged */
1102 return FASTTRAP_T_INV;
1103 }
1104
1105 static
1106 int
1107 thumb32_b_misc_control(uint16_t instr1, uint16_t instr2)
1108 {
1109 int op = BITS(instr1, 4, 0x7F), op1 = BITS(instr2, 12, 0x7), __unused op2 = BITS(instr2, 8, 0xF);
1110
1111 if ((op1 & 0x5) == 0) {
1112 if ((op & 0x38) != 0x38) {
1113 return FASTTRAP_T_B_COND;
1114 }
1115
1116 if (op == 0x3A) {
1117 return thumb32_cps_hints(instr1, instr2);
1118 }
1119
1120 if (op == 0x3B) {
1121 return thumb32_misc_control(instr1, instr2);
1122 }
1123 }
1124
1125 if ((op1 & 0x5) == 1) {
1126 return FASTTRAP_T_B_UNCOND;
1127 }
1128
1129 return FASTTRAP_T_INV;
1130 }
1131
1132 static
1133 int
1134 thumb32_dataproc_plain_immed(uint16_t instr1, uint16_t instr2)
1135 {
1136 int op = BITS(instr1, 4, 0x1F);
1137
1138 if (op == 0x04 || op == 0x0C || op == 0x16) {
1139 /* mov, movt, bfi, bfc */
1140 /* These use only RD */
1141 if (THUMB32_RD(instr1, instr2) != REG_PC) {
1142 return FASTTRAP_T_COMMON;
1143 }
1144 } else {
1145 if (THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
1146 return FASTTRAP_T_COMMON;
1147 }
1148 }
1149
1150 return FASTTRAP_T_INV;
1151 }
1152
1153 static
1154 int
1155 thumb32_dataproc_mod_immed(uint16_t instr1, uint16_t instr2)
1156 {
1157 int op = BITS(instr1, 5, 0xF), S = BITS(instr1, 4, 0x1);
1158
1159 if (op == 0x2 || op == 0x3) {
1160 /* These allow REG_PC in RN, but it doesn't mean use the PC! */
1161 if (THUMB32_RD(instr1, instr2) != REG_PC) {
1162 return FASTTRAP_T_COMMON;
1163 }
1164 }
1165
1166 if (op == 0 || op == 0x4 || op == 0x8 || op == 0xD) {
1167 /* These are test instructions, if the sign bit is set and RD is the PC. */
1168 if (S && THUMB32_RD(instr1, instr2) == REG_PC) {
1169 return FASTTRAP_T_COMMON;
1170 }
1171 }
1172
1173 if (THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
1174 return FASTTRAP_T_COMMON;
1175 }
1176
1177 return FASTTRAP_T_INV;
1178 }
1179
1180 static
1181 int
1182 dtrace_decode_thumb32(uint16_t instr1, uint16_t instr2)
1183 {
1184 int op1 = BITS(instr1, 11, 0x3), op2 = BITS(instr1, 4, 0x7F), op = BITS(instr2, 15, 0x1);
1185
1186 if (op1 == 0x1) {
1187 if ((op2 & 0x64) == 0) {
1188 return thumb32_loadstore_multiple(instr1, instr2);
1189 }
1190
1191 if ((op2 & 0x64) == 0x04) {
1192 return thumb32_loadstore_double_exclusive_table(instr1, instr2);
1193 }
1194
1195 if ((op2 & 0x60) == 0x20) {
1196 return thumb32_dataproc_regshift(instr1, instr2);
1197 }
1198
1199 if ((op2 & 0x40) == 0x40) {
1200 return thumb32_coproc(instr1, instr2);
1201 }
1202 }
1203
1204 if (op1 == 0x2) {
1205 if ((op2 & 0x20) == 0 && op == 0) {
1206 return thumb32_dataproc_mod_immed(instr1, instr2);
1207 }
1208
1209 if ((op2 & 0x20) == 0x20 && op == 0) {
1210 return thumb32_dataproc_plain_immed(instr1, instr2);
1211 }
1212
1213 if (op == 1) {
1214 return thumb32_b_misc_control(instr1, instr2);
1215 }
1216 }
1217
1218 if (op1 == 0x3) {
1219 if ((op2 & 0x71) == 0) {
1220 return thumb32_store_single(instr1, instr2);
1221 }
1222
1223 if ((op2 & 0x71) == 0x10) {
1224 return vfp_struct_loadstore(thumb32_instword_to_arm(instr1, instr2));
1225 }
1226
1227 if ((op2 & 0x67) == 0x01) {
1228 return thumb32_loadbyte_memhint(instr1, instr2);
1229 }
1230
1231 if ((op2 & 0x67) == 0x03) {
1232 return thumb32_loadhalfword_memhint(instr1, instr2);
1233 }
1234
1235 if ((op2 & 0x67) == 0x05) {
1236 return thumb32_loadword(instr1, instr2);
1237 }
1238
1239 if ((op2 & 0x67) == 0x07) {
1240 /* Undefined instruction */
1241 return FASTTRAP_T_INV;
1242 }
1243
1244 if ((op2 & 0x70) == 0x20) {
1245 return thumb32_dataproc_reg(instr1, instr2);
1246 }
1247
1248 if ((op2 & 0x78) == 0x30) {
1249 return thumb32_multiply(instr1, instr2);
1250 }
1251
1252 if ((op2 & 0x78) == 0x38) {
1253 return thumb32_longmultiply(instr1, instr2);
1254 }
1255
1256 if ((op2 & 0x40) == 0x40) {
1257 return thumb32_coproc(instr1, instr2);
1258 }
1259 }
1260
1261 return FASTTRAP_T_INV;
1262 }
1263
1264 int
1265 dtrace_decode_thumb(uint32_t instr)
1266 {
1267 uint16_t* pInstr = (uint16_t*) &instr;
1268 uint16_t hw1 = pInstr[0], hw2 = pInstr[1];
1269
1270 int size = BITS(hw1, 11, 0x1F);
1271
1272 if (size == 0x1D || size == 0x1E || size == 0x1F) {
1273 return dtrace_decode_thumb32(hw1, hw2);
1274 } else {
1275 return dtrace_decode_thumb16(hw1);
1276 }
1277 }