2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * Disassemblers for ARM (arm), Thumb (thumb16), and Thumb2 (thumb32).
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.
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.
13 #include <sys/fasttrap_isa.h>
15 #define BITS(x, n, mask) (((x) >> (n)) & (mask))
18 thumb32_instword_to_arm(uint16_t hw1
, uint16_t hw2
)
20 return (hw1
<< 16) | hw2
;
23 int dtrace_decode_arm(uint32_t instr
);
24 int dtrace_decode_arm64(uint32_t instr
);
25 int dtrace_decode_thumb(uint32_t instr
);
28 * VFP decoder - shared between ARM and THUMB32 mode
33 vfp_struct_loadstore(uint32_t instr
)
35 if (ARM_RM(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
36 return FASTTRAP_T_COMMON
;
39 return FASTTRAP_T_INV
;
44 vfp_64transfer(uint32_t instr
)
46 /* These instructions all use RD and RN */
47 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
48 return FASTTRAP_T_COMMON
;
51 return FASTTRAP_T_INV
;
56 vfp_transfer(uint32_t instr
)
58 /* These instructions all use RD only */
59 if (ARM_RD(instr
) != REG_PC
) {
60 return FASTTRAP_T_COMMON
;
63 return FASTTRAP_T_INV
;
68 vfp_loadstore(uint32_t instr
)
70 int opcode
= BITS(instr
, 20, 0x1F);
73 if ((opcode
& 0x13) == 0x11 && ARM_RN(instr
) == REG_PC
) {
74 return FASTTRAP_T_VLDR_PC_IMMED
;
77 /* These instructions all use RN only */
78 if (ARM_RN(instr
) != REG_PC
) {
79 return FASTTRAP_T_COMMON
;
82 return FASTTRAP_T_INV
;
91 arm_unconditional_misc(uint32_t instr
)
93 int op
= BITS(instr
, 20, 0x7F);
95 if ((op
& 0x60) == 0x20) {
96 /* VFP data processing uses its own registers */
97 return FASTTRAP_T_COMMON
;
100 if ((op
& 0x71) == 0x40) {
101 return vfp_struct_loadstore(instr
);
104 return FASTTRAP_T_INV
;
109 arm_unconditional(uint32_t instr
)
111 if (BITS(instr
, 27, 0x1) == 0) {
112 return arm_unconditional_misc(instr
);
115 /* The rest are privileged or BL/BLX, do not instrument */
117 /* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
119 return FASTTRAP_T_INV
;
124 arm_syscall_coproc(uint32_t instr
)
126 /* Instrument any VFP data processing instructions, ignore the rest */
128 int op1
= BITS(instr
, 20, 0x3F), coproc
= BITS(instr
, 8, 0xF), op
= BITS(instr
, 4, 0x1);
130 if ((op1
& 0x3E) == 0 || (op1
& 0x30) == 0x30) {
131 /* Undefined or swi */
132 return FASTTRAP_T_INV
;
135 if ((coproc
& 0xE) == 0xA) {
136 /* VFP instruction */
138 if ((op1
& 0x20) == 0 && (op1
& 0x3A) != 0) {
139 return vfp_loadstore(instr
);
142 if ((op1
& 0x3E) == 0x04) {
143 return vfp_64transfer(instr
);
146 if ((op1
& 0x30) == 0x20) {
147 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
149 /* VFP data processing uses its own registers */
150 return FASTTRAP_T_COMMON
;
152 return vfp_transfer(instr
);
157 return FASTTRAP_T_INV
;
162 arm_branch_link_blockdata(uint32_t instr
)
164 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);
168 return FASTTRAP_T_B_COND
;
170 return FASTTRAP_T_INV
;
172 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc } */
173 if (op
== 0x0B && ARM_RN(instr
) == REG_SP
&& uses_pc
== 1) {
174 return FASTTRAP_T_LDM_PC
;
177 /* stmia sp!, { ... lr } doesn't touch the pc, but it is very common, so special case it */
178 if (op
== 0x12 && ARM_RN(instr
) == REG_SP
&& uses_lr
== 1) {
179 return FASTTRAP_T_STM_LR
;
182 if (ARM_RN(instr
) != REG_PC
&& uses_pc
== 0) {
183 return FASTTRAP_T_COMMON
;
187 return FASTTRAP_T_INV
;
192 arm_signed_multiplies(uint32_t instr
)
194 int op1
= BITS(instr
, 20, 0x7), op2
= BITS(instr
, 5, 0x7);
196 /* smlald, smlsld, smmls use RD in addition to RM, RS, and RN */
197 if ((op1
== 0x4 && (op2
& 0x4) == 0) || (op1
== 0x5 && (op2
& 0x6) == 0x6)) {
198 if (ARM_RD(instr
) == REG_PC
) {
199 return FASTTRAP_T_INV
;
203 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
204 return FASTTRAP_T_COMMON
;
207 return FASTTRAP_T_INV
;
212 arm_pack_unpack_sat_reversal(uint32_t instr
)
214 int op1
= BITS(instr
, 20, 0x7), op2
= BITS(instr
, 5, 0x7);
216 /* pkh, sel use RN in addition to RD and RM */
217 if ((op1
== 0 && (op2
& 0x1) == 0) || (op1
== 0 && op2
== 0x5)) {
218 if (ARM_RN(instr
) == REG_PC
) {
219 return FASTTRAP_T_INV
;
223 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
) {
224 return FASTTRAP_T_COMMON
;
227 return FASTTRAP_T_INV
;
232 arm_parallel_addsub_unsigned(uint32_t instr
)
234 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
235 return FASTTRAP_T_COMMON
;
238 return FASTTRAP_T_INV
;
243 arm_parallel_addsub_signed(uint32_t instr
)
245 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
246 return FASTTRAP_T_COMMON
;
249 return FASTTRAP_T_INV
;
254 arm_media(uint32_t instr
)
256 int op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 5, 0x7);
258 if ((op1
& 0x1C) == 0) {
259 return arm_parallel_addsub_signed(instr
);
262 if ((op1
& 0x1C) == 0x04) {
263 return arm_parallel_addsub_unsigned(instr
);
266 if ((op1
& 0x18) == 0x08) {
267 return arm_pack_unpack_sat_reversal(instr
);
270 if ((op1
& 0x18) == 0x10) {
271 return arm_signed_multiplies(instr
);
274 if (op1
== 0x1F && op2
== 0x7) {
275 /* Undefined instruction */
276 return FASTTRAP_T_INV
;
279 if (op1
== 0x18 && op2
== 0) {
281 /* The registers are named differently in the reference manual for this instruction
282 * but the following positions are correct */
284 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
285 return FASTTRAP_T_COMMON
;
288 return FASTTRAP_T_INV
;
291 if ((op1
& 0x1E) == 0x1C && (op2
& 0x3) == 0) {
293 if (ARM_RD(instr
) != REG_PC
) {
294 return FASTTRAP_T_COMMON
;
297 return FASTTRAP_T_INV
;
300 if (((op1
& 0x1E) == 0x1A || (op1
& 0x1E) == 0x1E) && ((op2
& 0x3) == 0x2)) {
302 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
) {
303 return FASTTRAP_T_COMMON
;
306 return FASTTRAP_T_INV
;
309 return FASTTRAP_T_INV
;
314 arm_loadstore_wordbyte(uint32_t instr
)
316 /* Instrument PC relative load with immediate, ignore any other uses of the PC */
317 int R
= BITS(instr
, 25, 0x1), L
= BITS(instr
, 20, 0x1);
320 /* Three register load/store */
321 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
322 return FASTTRAP_T_COMMON
;
325 /* Immediate load/store, but still do not support ldr pc, [pc...] */
326 if (L
== 1 && ARM_RN(instr
) == REG_PC
&& ARM_RD(instr
) != REG_PC
) {
327 return FASTTRAP_T_LDR_PC_IMMED
;
330 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
331 return FASTTRAP_T_COMMON
;
335 return FASTTRAP_T_INV
;
340 arm_saturating(uint32_t instr
)
342 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
343 return FASTTRAP_T_COMMON
;
346 return FASTTRAP_T_INV
;
351 arm_misc(uint32_t instr
)
353 int op
= BITS(instr
, 21, 0x3), __unused op1
= BITS(instr
, 16, 0xF), op2
= BITS(instr
, 4, 0x7);
355 if (op2
== 1 && op
== 1) {
356 return FASTTRAP_T_BX_REG
;
359 /* We do not need to emulate BLX for entry/return probes; if we eventually support full offset
360 * tracing, then we will. This is because BLX overwrites the link register, so a function that
361 * can execute this as its first instruction is a special function indeed.
365 return arm_saturating(instr
);
368 return FASTTRAP_T_INV
;
373 arm_msr_hints(__unused
uint32_t instr
)
375 /* These deal with the psr, not instrumented */
377 return FASTTRAP_T_INV
;
382 arm_sync_primitive(__unused
uint32_t instr
)
384 /* TODO will instrumenting these interfere with any kernel usage of these instructions? */
385 /* Don't instrument for now */
387 return FASTTRAP_T_INV
;
392 arm_extra_loadstore_unpriv(uint32_t instr
)
394 int op
= BITS(instr
, 20, 0x1), __unused op2
= BITS(instr
, 5, 0x3), immed
= BITS(instr
, 22, 0x1);
396 if (op
== 0 && (op2
& 0x2) == 0x2) {
397 /* Unpredictable or undefined */
398 return FASTTRAP_T_INV
;
402 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
403 return FASTTRAP_T_COMMON
;
406 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
407 return FASTTRAP_T_COMMON
;
411 return FASTTRAP_T_INV
;
416 arm_extra_loadstore(uint32_t instr
)
418 int op1
= BITS(instr
, 20, 0x1F);
420 /* There are two variants, and we do not instrument either of them that use the PC */
422 if ((op1
& 0x4) == 0) {
423 /* Variant 1, register */
424 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
425 return FASTTRAP_T_COMMON
;
428 /* Variant 2, immediate */
429 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
430 return FASTTRAP_T_COMMON
;
434 return FASTTRAP_T_INV
;
439 arm_halfword_multiply(uint32_t instr
)
441 /* Not all multiply instructions use all four registers. The ones that don't should have those
442 * register locations set to 0, so we can test them anyway.
445 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
) {
446 return FASTTRAP_T_COMMON
;
449 return FASTTRAP_T_INV
;
454 arm_multiply(uint32_t instr
)
456 /* Not all multiply instructions use all four registers. The ones that don't should have those
457 * register locations set to 0, so we can test them anyway.
460 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
) {
461 return FASTTRAP_T_COMMON
;
464 return FASTTRAP_T_INV
;
469 arm_dataproc_immed(uint32_t instr
)
471 /* All these instructions are either two registers, or one register and have 0 where the other reg would be used */
472 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
) {
473 return FASTTRAP_T_COMMON
;
476 return FASTTRAP_T_INV
;
481 arm_dataproc_regshift(uint32_t instr
)
483 /* All these instructions are either four registers, or three registers and have 0 where there last reg would be used */
484 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
) {
485 return FASTTRAP_T_COMMON
;
488 return FASTTRAP_T_INV
;
493 arm_dataproc_reg(uint32_t instr
)
495 int op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 7, 0x1F), op3
= BITS(instr
, 5, 0x3);
497 if (op1
== 0x11 || op1
== 0x13 || op1
== 0x15 || op1
== 0x17) {
498 /* These are comparison flag setting instructions and do not have RD */
499 if (ARM_RN(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
) {
500 return FASTTRAP_T_COMMON
;
503 return FASTTRAP_T_INV
;
506 /* The rest can, in theory, write or use the PC. The only one we instrument is mov pc, reg.
507 * movs pc, reg is a privileged instruction so we don't instrument that variant. The s bit
508 * is bit 0 of op1 and should be zero.
510 if (op1
== 0x1A && op2
== 0 && op3
== 0 && ARM_RD(instr
) == REG_PC
) {
511 return FASTTRAP_T_MOV_PC_REG
;
514 /* Any instruction at this point is a three register instruction or two register instruction with RN = 0 */
515 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
) {
516 return FASTTRAP_T_COMMON
;
519 return FASTTRAP_T_INV
;
524 arm_dataproc_misc(uint32_t instr
)
526 int op
= BITS(instr
, 25, 0x1), op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 4, 0xF);
529 if ((op1
& 0x19) != 0x10 && (op2
& 0x1) == 0) {
530 return arm_dataproc_reg(instr
);
533 if ((op1
& 0x19) != 0x10 && (op2
& 0x9) == 0x1) {
534 return arm_dataproc_regshift(instr
);
537 if ((op1
& 0x19) == 0x10 && (op2
& 0x8) == 0) {
538 return arm_misc(instr
);
541 if ((op1
& 0x19) == 0x19 && (op2
& 0x9) == 0x8) {
542 return arm_halfword_multiply(instr
);
545 if ((op1
& 0x10) == 0 && op2
== 0x9) {
546 return arm_multiply(instr
);
549 if ((op1
& 0x10) == 0x10 && op2
== 0x9) {
550 return arm_sync_primitive(instr
);
553 if ((op1
& 0x12) != 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD)) {
554 return arm_extra_loadstore(instr
);
557 if ((op1
& 0x12) == 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD)) {
558 return arm_extra_loadstore_unpriv(instr
);
561 if ((op1
& 0x19) != 0x10) {
562 return arm_dataproc_immed(instr
);
566 /* 16 bit immediate load (mov (immed)) [encoding A2] */
567 if (ARM_RD(instr
) != REG_PC
) {
568 return FASTTRAP_T_COMMON
;
571 return FASTTRAP_T_INV
;
575 /* high halfword 16 bit immediate load (movt) [encoding A1] */
576 if (ARM_RD(instr
) != REG_PC
) {
577 return FASTTRAP_T_COMMON
;
580 return FASTTRAP_T_INV
;
583 if ((op1
& 0x1B) == 0x12) {
584 return arm_msr_hints(instr
);
588 return FASTTRAP_T_INV
;
592 dtrace_decode_arm(uint32_t instr
)
594 int cond
= BITS(instr
, 28, 0xF), op1
= BITS(instr
, 25, 0x7), op
= BITS(instr
, 4, 0x1);
597 return arm_unconditional(instr
);
600 if ((op1
& 0x6) == 0) {
601 return arm_dataproc_misc(instr
);
605 return arm_loadstore_wordbyte(instr
);
608 if (op1
== 0x3 && op
== 0) {
609 return arm_loadstore_wordbyte(instr
);
612 if (op1
== 0x3 && op
== 1) {
613 return arm_media(instr
);
616 if ((op1
& 0x6) == 0x4) {
617 return arm_branch_link_blockdata(instr
);
620 if ((op1
& 0x6) == 0x6) {
621 return arm_syscall_coproc(instr
);
624 return FASTTRAP_T_INV
;
628 * Thumb 16-bit decoder
633 thumb16_cond_supervisor(uint16_t instr
)
635 int opcode
= BITS(instr
, 8, 0xF);
637 if ((opcode
& 0xE) != 0xE) {
638 return FASTTRAP_T_B_COND
;
641 return FASTTRAP_T_INV
;
646 thumb16_misc(uint16_t instr
)
648 int opcode
= BITS(instr
, 5, 0x7F);
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
;
662 /* All other instructions work on low regs only and are instrumentable */
663 return FASTTRAP_T_COMMON
;
668 thumb16_loadstore_single(__unused
uint16_t instr
)
670 /* These all access the low registers or SP only */
671 return FASTTRAP_T_COMMON
;
676 thumb16_data_special_and_branch(uint16_t instr
)
678 int opcode
= BITS(instr
, 6, 0xF);
682 return FASTTRAP_T_INV
;
683 } else if ((opcode
& 0xC) == 0xC) {
685 /* Only instrument the bx */
686 if ((opcode
& 0x2) == 0) {
687 return FASTTRAP_T_BX_REG
;
689 return FASTTRAP_T_INV
;
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
;
696 if (THUMB16_HRM(instr
) != REG_PC
&& THUMB16_HRD(instr
) != REG_PC
) {
697 return FASTTRAP_T_COMMON
;
701 return FASTTRAP_T_INV
;
706 thumb16_data_proc(__unused
uint16_t instr
)
708 /* These all access the low registers only */
709 return FASTTRAP_T_COMMON
;
714 thumb16_shift_addsub_move_compare(__unused
uint16_t instr
)
716 /* These all access the low registers only */
717 return FASTTRAP_T_COMMON
;
722 dtrace_decode_thumb16(uint16_t instr
)
724 int opcode
= BITS(instr
, 10, 0x3F);
726 if ((opcode
& 0x30) == 0) {
727 return thumb16_shift_addsub_move_compare(instr
);
730 if (opcode
== 0x10) {
731 return thumb16_data_proc(instr
);
734 if (opcode
== 0x11) {
735 return thumb16_data_special_and_branch(instr
);
738 if ((opcode
& 0x3E) == 0x12) {
740 return FASTTRAP_T_LDR_PC_IMMED
;
743 if ((opcode
& 0x3C) == 0x14 || (opcode
& 0x38) == 0x18 || (opcode
& 0x38) == 0x20) {
744 return thumb16_loadstore_single(instr
);
747 if ((opcode
& 0x3E) == 0x28) {
748 /* adr, uses the pc */
749 return FASTTRAP_T_INV
;
752 if ((opcode
& 0x3E) == 0x2A) {
753 /* add (sp plus immediate) */
754 return FASTTRAP_T_COMMON
;
757 if ((opcode
& 0x3C) == 0x2C) {
758 return thumb16_misc(instr
);
761 if ((opcode
& 0x3E) == 0x30) {
762 /* stm - can't access high registers */
763 return FASTTRAP_T_COMMON
;
766 if ((opcode
& 0x3E) == 0x32) {
767 /* ldm - can't access high registers */
768 return FASTTRAP_T_COMMON
;
771 if ((opcode
& 0x3C) == 0x34) {
772 return thumb16_cond_supervisor(instr
);
775 if ((opcode
& 0x3E) == 0x38) {
776 /* b unconditional */
777 return FASTTRAP_T_B_UNCOND
;
780 return FASTTRAP_T_INV
;
784 * Thumb 32-bit decoder
789 thumb32_coproc(uint16_t instr1
, uint16_t instr2
)
791 /* Instrument any VFP data processing instructions, ignore the rest */
793 int op1
= BITS(instr1
, 4, 0x3F), coproc
= BITS(instr2
, 8, 0xF), op
= BITS(instr2
, 4, 0x1);
795 if ((op1
& 0x3E) == 0) {
797 return FASTTRAP_T_INV
;
800 if ((coproc
& 0xE) == 0xA || (op1
& 0x30) == 0x30) {
801 /* VFP instruction */
802 uint32_t instr
= thumb32_instword_to_arm(instr1
, instr2
);
804 if ((op1
& 0x30) == 0x30) {
805 /* VFP data processing uses its own registers */
806 return FASTTRAP_T_COMMON
;
809 if ((op1
& 0x3A) == 0x02 || (op1
& 0x38) == 0x08 || (op1
& 0x30) == 0x10) {
810 return vfp_loadstore(instr
);
813 if ((op1
& 0x3E) == 0x04) {
814 return vfp_64transfer(instr
);
817 if ((op1
& 0x30) == 0x20) {
818 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
820 /* VFP data processing uses its own registers */
821 return FASTTRAP_T_COMMON
;
823 return vfp_transfer(instr
);
828 return FASTTRAP_T_INV
;
833 thumb32_longmultiply(uint16_t instr1
, uint16_t instr2
)
835 int op1
= BITS(instr1
, 4, 0x7), op2
= BITS(instr2
, 4, 0xF);
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
;
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
;
850 return FASTTRAP_T_INV
;
855 thumb32_multiply(uint16_t instr1
, uint16_t instr2
)
857 int op1
= BITS(instr1
, 4, 0x7), op2
= BITS(instr2
, 4, 0x3);
859 if ((op1
== 0 && op2
== 1) || (op1
== 0x6 && (op2
& 0x2) == 0)) {
860 if (THUMB32_RT(instr1
, instr2
) == REG_PC
) {
861 return FASTTRAP_T_INV
;
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
;
869 return FASTTRAP_T_INV
;
874 thumb32_misc(uint16_t instr1
, uint16_t instr2
)
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
;
880 return FASTTRAP_T_INV
;
885 thumb32_parallel_addsub_unsigned(uint16_t instr1
, uint16_t instr2
)
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
;
891 return FASTTRAP_T_INV
;
896 thumb32_parallel_addsub_signed(uint16_t instr1
, uint16_t instr2
)
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
;
902 return FASTTRAP_T_INV
;
907 thumb32_dataproc_reg(uint16_t instr1
, uint16_t instr2
)
909 int op1
= BITS(instr1
, 4, 0xF), op2
= BITS(instr2
, 4, 0xF);
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
;
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
;
923 if ((op1
& 0x8) == 0x8 && (op2
& 0xC) == 0) {
924 return thumb32_parallel_addsub_signed(instr1
, instr2
);
927 if ((op1
& 0x8) == 0x8 && (op2
& 0xC) == 0x4) {
928 return thumb32_parallel_addsub_unsigned(instr1
, instr2
);
931 if ((op1
& 0xC) == 0x8 && (op2
& 0xC) == 0x8) {
932 return thumb32_misc(instr1
, instr2
);
935 return FASTTRAP_T_INV
;
940 thumb32_dataproc_regshift(uint16_t instr1
, uint16_t instr2
)
942 int op
= BITS(instr1
, 5, 0xF), S
= BITS(instr1
, 4, 0x1);
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. */
947 if (THUMB32_RM(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
948 return FASTTRAP_T_COMMON
;
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
;
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
;
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
;
968 return FASTTRAP_T_INV
;
973 thumb32_store_single(uint16_t instr1
, uint16_t instr2
)
975 int op1
= BITS(instr1
, 5, 0x7), op2
= BITS(instr2
, 6, 0x3F);
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
;
985 if (THUMB32_RT(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
986 return FASTTRAP_T_COMMON
;
989 return FASTTRAP_T_INV
;
994 thumb32_loadbyte_memhint(uint16_t instr1
, uint16_t instr2
)
996 int op1
= BITS(instr1
, 7, 0x3), __unused op2
= BITS(instr2
, 6, 0x3F);
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
;
1003 if (THUMB32_RT(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
1004 return FASTTRAP_T_COMMON
;
1007 return FASTTRAP_T_INV
;
1012 thumb32_loadhalfword_memhint(uint16_t instr1
, uint16_t instr2
)
1014 int op1
= BITS(instr1
, 7, 0x3), op2
= BITS(instr2
, 6, 0x3F);
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
;
1021 if (THUMB32_RT(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
1022 return FASTTRAP_T_COMMON
;
1025 return FASTTRAP_T_INV
;
1030 thumb32_loadword(uint16_t instr1
, uint16_t instr2
)
1032 int op1
= BITS(instr1
, 7, 0x3), op2
= BITS(instr2
, 6, 0x3F);
1034 if ((op1
& 0x2) == 0 && THUMB32_RN(instr1
, instr2
) == REG_PC
&& THUMB32_RT(instr1
, instr2
) != REG_PC
) {
1035 return FASTTRAP_T_LDR_PC_IMMED
;
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
;
1045 if (THUMB32_RT(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
1046 return FASTTRAP_T_COMMON
;
1049 return FASTTRAP_T_INV
;
1054 thumb32_loadstore_double_exclusive_table(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
1056 /* Don't instrument any of these */
1058 return FASTTRAP_T_INV
;
1063 thumb32_loadstore_multiple(uint16_t instr1
, uint16_t instr2
)
1065 int op
= BITS(instr1
, 7, 0x3), L
= BITS(instr1
, 4, 0x1), uses_pc
= BITS(instr2
, 15, 0x1), uses_lr
= BITS(instr2
, 14, 0x1);
1067 if (op
== 0 || op
== 0x3) {
1068 /* Privileged instructions: srs, rfe */
1069 return FASTTRAP_T_INV
;
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
;
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
;
1082 if (THUMB32_RN(instr1
, instr2
) != REG_PC
&& uses_pc
== 0) {
1083 return FASTTRAP_T_COMMON
;
1086 return FASTTRAP_T_INV
;
1091 thumb32_misc_control(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
1093 /* Privileged, and instructions dealing with ThumbEE */
1094 return FASTTRAP_T_INV
;
1099 thumb32_cps_hints(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
1102 return FASTTRAP_T_INV
;
1107 thumb32_b_misc_control(uint16_t instr1
, uint16_t instr2
)
1109 int op
= BITS(instr1
, 4, 0x7F), op1
= BITS(instr2
, 12, 0x7), __unused op2
= BITS(instr2
, 8, 0xF);
1111 if ((op1
& 0x5) == 0) {
1112 if ((op
& 0x38) != 0x38) {
1113 return FASTTRAP_T_B_COND
;
1117 return thumb32_cps_hints(instr1
, instr2
);
1121 return thumb32_misc_control(instr1
, instr2
);
1125 if ((op1
& 0x5) == 1) {
1126 return FASTTRAP_T_B_UNCOND
;
1129 return FASTTRAP_T_INV
;
1134 thumb32_dataproc_plain_immed(uint16_t instr1
, uint16_t instr2
)
1136 int op
= BITS(instr1
, 4, 0x1F);
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
;
1145 if (THUMB32_RD(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
1146 return FASTTRAP_T_COMMON
;
1150 return FASTTRAP_T_INV
;
1155 thumb32_dataproc_mod_immed(uint16_t instr1
, uint16_t instr2
)
1157 int op
= BITS(instr1
, 5, 0xF), S
= BITS(instr1
, 4, 0x1);
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
;
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
;
1173 if (THUMB32_RD(instr1
, instr2
) != REG_PC
&& THUMB32_RN(instr1
, instr2
) != REG_PC
) {
1174 return FASTTRAP_T_COMMON
;
1177 return FASTTRAP_T_INV
;
1182 dtrace_decode_thumb32(uint16_t instr1
, uint16_t instr2
)
1184 int op1
= BITS(instr1
, 11, 0x3), op2
= BITS(instr1
, 4, 0x7F), op
= BITS(instr2
, 15, 0x1);
1187 if ((op2
& 0x64) == 0) {
1188 return thumb32_loadstore_multiple(instr1
, instr2
);
1191 if ((op2
& 0x64) == 0x04) {
1192 return thumb32_loadstore_double_exclusive_table(instr1
, instr2
);
1195 if ((op2
& 0x60) == 0x20) {
1196 return thumb32_dataproc_regshift(instr1
, instr2
);
1199 if ((op2
& 0x40) == 0x40) {
1200 return thumb32_coproc(instr1
, instr2
);
1205 if ((op2
& 0x20) == 0 && op
== 0) {
1206 return thumb32_dataproc_mod_immed(instr1
, instr2
);
1209 if ((op2
& 0x20) == 0x20 && op
== 0) {
1210 return thumb32_dataproc_plain_immed(instr1
, instr2
);
1214 return thumb32_b_misc_control(instr1
, instr2
);
1219 if ((op2
& 0x71) == 0) {
1220 return thumb32_store_single(instr1
, instr2
);
1223 if ((op2
& 0x71) == 0x10) {
1224 return vfp_struct_loadstore(thumb32_instword_to_arm(instr1
, instr2
));
1227 if ((op2
& 0x67) == 0x01) {
1228 return thumb32_loadbyte_memhint(instr1
, instr2
);
1231 if ((op2
& 0x67) == 0x03) {
1232 return thumb32_loadhalfword_memhint(instr1
, instr2
);
1235 if ((op2
& 0x67) == 0x05) {
1236 return thumb32_loadword(instr1
, instr2
);
1239 if ((op2
& 0x67) == 0x07) {
1240 /* Undefined instruction */
1241 return FASTTRAP_T_INV
;
1244 if ((op2
& 0x70) == 0x20) {
1245 return thumb32_dataproc_reg(instr1
, instr2
);
1248 if ((op2
& 0x78) == 0x30) {
1249 return thumb32_multiply(instr1
, instr2
);
1252 if ((op2
& 0x78) == 0x38) {
1253 return thumb32_longmultiply(instr1
, instr2
);
1256 if ((op2
& 0x40) == 0x40) {
1257 return thumb32_coproc(instr1
, instr2
);
1261 return FASTTRAP_T_INV
;
1265 dtrace_decode_thumb(uint32_t instr
)
1267 uint16_t* pInstr
= (uint16_t*) &instr
;
1268 uint16_t hw1
= pInstr
[0], hw2
= pInstr
[1];
1270 int size
= BITS(hw1
, 11, 0x1F);
1272 if (size
== 0x1D || size
== 0x1E || size
== 0x1F) {
1273 return dtrace_decode_thumb32(hw1
, hw2
);
1275 return dtrace_decode_thumb16(hw1
);
1279 struct arm64_decode_entry
{
1285 struct arm64_decode_entry arm64_decode_table
[] = {
1286 { .mask
= 0xFFFFFFFF, .value
= FASTTRAP_ARM64_OP_VALUE_FUNC_ENTRY
, .type
= FASTTRAP_T_ARM64_STANDARD_FUNCTION_ENTRY
},
1287 { .mask
= FASTTRAP_ARM64_OP_MASK_LDR_S_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LDR_S_PC_REL
, .type
= FASTTRAP_T_ARM64_LDR_S_PC_REL
},
1288 { .mask
= FASTTRAP_ARM64_OP_MASK_LDR_W_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LDR_W_PC_REL
, .type
= FASTTRAP_T_ARM64_LDR_W_PC_REL
},
1289 { .mask
= FASTTRAP_ARM64_OP_MASK_LDR_D_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LDR_D_PC_REL
, .type
= FASTTRAP_T_ARM64_LDR_D_PC_REL
},
1290 { .mask
= FASTTRAP_ARM64_OP_MASK_LDR_X_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LDR_X_PC_REL
, .type
= FASTTRAP_T_ARM64_LDR_X_PC_REL
},
1291 { .mask
= FASTTRAP_ARM64_OP_MASK_LDR_Q_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LDR_Q_PC_REL
, .type
= FASTTRAP_T_ARM64_LDR_Q_PC_REL
},
1292 { .mask
= FASTTRAP_ARM64_OP_MASK_LRDSW_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LRDSW_PC_REL
, .type
= FASTTRAP_T_ARM64_LDRSW_PC_REL
},
1293 { .mask
= FASTTRAP_ARM64_OP_MASK_B_COND_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_B_COND_PC_REL
, .type
= FASTTRAP_T_ARM64_B_COND
},
1294 { .mask
= FASTTRAP_ARM64_OP_MASK_CBNZ_W_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBNZ_W_PC_REL
, .type
= FASTTRAP_T_ARM64_CBNZ_W
},
1295 { .mask
= FASTTRAP_ARM64_OP_MASK_CBNZ_X_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBNZ_X_PC_REL
, .type
= FASTTRAP_T_ARM64_CBNZ_X
},
1296 { .mask
= FASTTRAP_ARM64_OP_MASK_CBZ_W_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBZ_W_PC_REL
, .type
= FASTTRAP_T_ARM64_CBZ_W
},
1297 { .mask
= FASTTRAP_ARM64_OP_MASK_CBZ_X_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBZ_X_PC_REL
, .type
= FASTTRAP_T_ARM64_CBZ_X
},
1298 { .mask
= FASTTRAP_ARM64_OP_MASK_TBNZ_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_TBNZ_PC_REL
, .type
= FASTTRAP_T_ARM64_TBNZ
},
1299 { .mask
= FASTTRAP_ARM64_OP_MASK_TBZ_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_TBZ_PC_REL
, .type
= FASTTRAP_T_ARM64_TBZ
},
1300 { .mask
= FASTTRAP_ARM64_OP_MASK_B_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_B_PC_REL
, .type
= FASTTRAP_T_ARM64_B
},
1301 { .mask
= FASTTRAP_ARM64_OP_MASK_BL_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_BL_PC_REL
, .type
= FASTTRAP_T_ARM64_BL
},
1302 { .mask
= FASTTRAP_ARM64_OP_MASK_BLR
, .value
= FASTTRAP_ARM64_OP_VALUE_BLR
, .type
= FASTTRAP_T_ARM64_BLR
},
1303 { .mask
= FASTTRAP_ARM64_OP_MASK_BR
, .value
= FASTTRAP_ARM64_OP_VALUE_BR
, .type
= FASTTRAP_T_ARM64_BR
},
1304 { .mask
= FASTTRAP_ARM64_OP_MASK_RET
, .value
= FASTTRAP_ARM64_OP_VALUE_RET
, .type
= FASTTRAP_T_ARM64_RET
},
1305 { .mask
= FASTTRAP_ARM64_OP_MASK_ADRP
, .value
= FASTTRAP_ARM64_OP_VALUE_ADRP
, .type
= FASTTRAP_T_ARM64_ADRP
},
1306 { .mask
= FASTTRAP_ARM64_OP_MASK_ADR
, .value
= FASTTRAP_ARM64_OP_VALUE_ADR
, .type
= FASTTRAP_T_ARM64_ADR
},
1307 { .mask
= FASTTRAP_ARM64_OP_MASK_PRFM
, .value
= FASTTRAP_ARM64_OP_VALUE_PRFM
, .type
= FASTTRAP_T_ARM64_PRFM
},
1308 { .mask
= FASTTRAP_ARM64_OP_MASK_EXCL_MEM
, .value
= FASTTRAP_ARM64_OP_VALUE_EXCL_MEM
, .type
= FASTTRAP_T_ARM64_EXCLUSIVE_MEM
},
1309 { .mask
= FASTTRAP_ARM64_OP_MASK_RETAB
, .value
= FASTTRAP_ARM64_OP_VALUE_RETAB
, .type
= FASTTRAP_T_ARM64_RETAB
}
1312 #define NUM_DECODE_ENTRIES (sizeof(arm64_decode_table) / sizeof(struct arm64_decode_entry))
1317 dtrace_decode_arm64(uint32_t instr
)
1321 for (i
= 0; i
< NUM_DECODE_ENTRIES
; i
++) {
1322 if ((instr
& arm64_decode_table
[i
].mask
) == arm64_decode_table
[i
].value
) {
1323 return arm64_decode_table
[i
].type
;
1327 return FASTTRAP_T_COMMON
;