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))
17 static uint32_t thumb32_instword_to_arm(uint16_t hw1
, uint16_t hw2
)
19 return (hw1
<< 16) | hw2
;
22 int dtrace_decode_arm(uint32_t instr
);
23 int dtrace_decode_arm64(uint32_t instr
);
24 int dtrace_decode_thumb(uint32_t instr
);
27 * VFP decoder - shared between ARM and THUMB32 mode
31 int vfp_struct_loadstore(uint32_t instr
)
33 if (ARM_RM(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
34 return FASTTRAP_T_COMMON
;
36 return FASTTRAP_T_INV
;
40 int vfp_64transfer(uint32_t instr
)
42 /* These instructions all use RD and RN */
43 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
44 return FASTTRAP_T_COMMON
;
46 return FASTTRAP_T_INV
;
50 int vfp_transfer(uint32_t instr
)
52 /* These instructions all use RD only */
53 if (ARM_RD(instr
) != REG_PC
)
54 return FASTTRAP_T_COMMON
;
56 return FASTTRAP_T_INV
;
60 int vfp_loadstore(uint32_t instr
)
62 int opcode
= BITS(instr
,20,0x1F);
65 if ((opcode
& 0x13) == 0x11 && ARM_RN(instr
) == REG_PC
)
66 return FASTTRAP_T_VLDR_PC_IMMED
;
68 /* These instructions all use RN only */
69 if (ARM_RN(instr
) != REG_PC
)
70 return FASTTRAP_T_COMMON
;
72 return FASTTRAP_T_INV
;
80 int arm_unconditional_misc(uint32_t instr
)
82 int op
= BITS(instr
,20,0x7F);
84 if ((op
& 0x60) == 0x20) {
85 /* VFP data processing uses its own registers */
86 return FASTTRAP_T_COMMON
;
89 if ((op
& 0x71) == 0x40) {
90 return vfp_struct_loadstore(instr
);
93 return FASTTRAP_T_INV
;
97 int arm_unconditional(uint32_t instr
)
99 if (BITS(instr
,27,0x1) == 0)
100 return arm_unconditional_misc(instr
);
102 /* The rest are privileged or BL/BLX, do not instrument */
104 /* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
106 return FASTTRAP_T_INV
;
110 int arm_syscall_coproc(uint32_t instr
)
112 /* Instrument any VFP data processing instructions, ignore the rest */
114 int op1
= BITS(instr
,20,0x3F), coproc
= BITS(instr
,8,0xF), op
= BITS(instr
,4,0x1);
116 if ((op1
& 0x3E) == 0 || (op1
& 0x30) == 0x30) {
117 /* Undefined or swi */
118 return FASTTRAP_T_INV
;
121 if ((coproc
& 0xE) == 0xA) {
122 /* VFP instruction */
124 if ((op1
& 0x20) == 0 && (op1
& 0x3A) != 0)
125 return vfp_loadstore(instr
);
127 if ((op1
& 0x3E) == 0x04)
128 return vfp_64transfer(instr
);
130 if ((op1
& 0x30) == 0x20) {
131 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
133 /* VFP data processing uses its own registers */
134 return FASTTRAP_T_COMMON
;
136 return vfp_transfer(instr
);
141 return FASTTRAP_T_INV
;
145 int arm_branch_link_blockdata(uint32_t instr
)
147 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);
151 return FASTTRAP_T_B_COND
;
152 return FASTTRAP_T_INV
;
154 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc } */
155 if (op
== 0x0B && ARM_RN(instr
) == REG_SP
&& uses_pc
== 1)
156 return FASTTRAP_T_LDM_PC
;
158 /* stmia sp!, { ... lr } doesn't touch the pc, but it is very common, so special case it */
159 if (op
== 0x12 && ARM_RN(instr
) == REG_SP
&& uses_lr
== 1)
160 return FASTTRAP_T_STM_LR
;
162 if (ARM_RN(instr
) != REG_PC
&& uses_pc
== 0)
163 return FASTTRAP_T_COMMON
;
166 return FASTTRAP_T_INV
;
170 int arm_signed_multiplies(uint32_t instr
)
172 int op1
= BITS(instr
,20,0x7), op2
= BITS(instr
,5,0x7);
174 /* smlald, smlsld, smmls use RD in addition to RM, RS, and RN */
175 if ((op1
== 0x4 && (op2
& 0x4) == 0) || (op1
== 0x5 && (op2
& 0x6) == 0x6)) {
176 if (ARM_RD(instr
) == REG_PC
)
177 return FASTTRAP_T_INV
;
180 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
181 return FASTTRAP_T_COMMON
;
183 return FASTTRAP_T_INV
;
187 int arm_pack_unpack_sat_reversal(uint32_t instr
)
189 int op1
= BITS(instr
,20,0x7), op2
= BITS(instr
,5,0x7);
191 /* pkh, sel use RN in addition to RD and RM */
192 if ((op1
== 0 && (op2
& 0x1) == 0) || (op1
== 0 && op2
== 0x5)) {
193 if (ARM_RN(instr
) == REG_PC
)
194 return FASTTRAP_T_INV
;
197 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
198 return FASTTRAP_T_COMMON
;
200 return FASTTRAP_T_INV
;
204 int arm_parallel_addsub_unsigned(uint32_t instr
)
206 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
207 return FASTTRAP_T_COMMON
;
209 return FASTTRAP_T_INV
;
213 int arm_parallel_addsub_signed(uint32_t instr
)
215 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
216 return FASTTRAP_T_COMMON
;
218 return FASTTRAP_T_INV
;
222 int arm_media(uint32_t instr
)
224 int op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,5,0x7);
226 if ((op1
& 0x1C) == 0)
227 return arm_parallel_addsub_signed(instr
);
229 if ((op1
& 0x1C) == 0x04)
230 return arm_parallel_addsub_unsigned(instr
);
232 if ((op1
& 0x18) == 0x08)
233 return arm_pack_unpack_sat_reversal(instr
);
235 if ((op1
& 0x18) == 0x10)
236 return arm_signed_multiplies(instr
);
238 if (op1
== 0x1F && op2
== 0x7) {
239 /* Undefined instruction */
240 return FASTTRAP_T_INV
;
243 if (op1
== 0x18 && op2
== 0) {
245 /* The registers are named differently in the reference manual for this instruction
246 * but the following positions are correct */
248 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
249 return FASTTRAP_T_COMMON
;
251 return FASTTRAP_T_INV
;
254 if ((op1
& 0x1E) == 0x1C && (op2
& 0x3) == 0) {
256 if (ARM_RD(instr
) != REG_PC
)
257 return FASTTRAP_T_COMMON
;
259 return FASTTRAP_T_INV
;
262 if (((op1
& 0x1E) == 0x1A || (op1
& 0x1E) == 0x1E) && ((op2
& 0x3) == 0x2)) {
264 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
265 return FASTTRAP_T_COMMON
;
267 return FASTTRAP_T_INV
;
270 return FASTTRAP_T_INV
;
274 int arm_loadstore_wordbyte(uint32_t instr
)
276 /* Instrument PC relative load with immediate, ignore any other uses of the PC */
277 int R
= BITS(instr
,25,0x1), L
= BITS(instr
,20,0x1);
280 /* Three register load/store */
281 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
282 return FASTTRAP_T_COMMON
;
284 /* Immediate load/store, but still do not support ldr pc, [pc...] */
285 if (L
== 1 && ARM_RN(instr
) == REG_PC
&& ARM_RD(instr
) != REG_PC
)
286 return FASTTRAP_T_LDR_PC_IMMED
;
288 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
289 return FASTTRAP_T_COMMON
;
292 return FASTTRAP_T_INV
;
296 int arm_saturating(uint32_t instr
)
298 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
299 return FASTTRAP_T_COMMON
;
301 return FASTTRAP_T_INV
;
305 int arm_misc(uint32_t instr
)
307 int op
= BITS(instr
,21,0x3), __unused op1
= BITS(instr
,16,0xF), op2
= BITS(instr
,4,0x7);
309 if (op2
== 1 && op
== 1)
310 return FASTTRAP_T_BX_REG
;
312 /* We do not need to emulate BLX for entry/return probes; if we eventually support full offset
313 * tracing, then we will. This is because BLX overwrites the link register, so a function that
314 * can execute this as its first instruction is a special function indeed.
318 return arm_saturating(instr
);
320 return FASTTRAP_T_INV
;
324 int arm_msr_hints(__unused
uint32_t instr
)
326 /* These deal with the psr, not instrumented */
328 return FASTTRAP_T_INV
;
332 int arm_sync_primitive(__unused
uint32_t instr
)
334 /* TODO will instrumenting these interfere with any kernel usage of these instructions? */
335 /* Don't instrument for now */
337 return FASTTRAP_T_INV
;
341 int arm_extra_loadstore_unpriv(uint32_t instr
)
343 int op
= BITS(instr
,20,0x1), __unused op2
= BITS(instr
,5,0x3), immed
= BITS(instr
,22,0x1);
345 if (op
== 0 && (op2
& 0x2) == 0x2) {
346 /* Unpredictable or undefined */
347 return FASTTRAP_T_INV
;
351 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
352 return FASTTRAP_T_COMMON
;
354 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
355 return FASTTRAP_T_COMMON
;
358 return FASTTRAP_T_INV
;
362 int arm_extra_loadstore(uint32_t instr
)
364 int op1
= BITS(instr
,20,0x1F);
366 /* There are two variants, and we do not instrument either of them that use the PC */
368 if ((op1
& 0x4) == 0) {
369 /* Variant 1, register */
370 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
371 return FASTTRAP_T_COMMON
;
373 /* Variant 2, immediate */
374 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
375 return FASTTRAP_T_COMMON
;
378 return FASTTRAP_T_INV
;
382 int arm_halfword_multiply(uint32_t instr
)
384 /* Not all multiply instructions use all four registers. The ones that don't should have those
385 * register locations set to 0, so we can test them anyway.
388 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
389 return FASTTRAP_T_COMMON
;
391 return FASTTRAP_T_INV
;
395 int arm_multiply(uint32_t instr
)
397 /* Not all multiply instructions use all four registers. The ones that don't should have those
398 * register locations set to 0, so we can test them anyway.
401 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
402 return FASTTRAP_T_COMMON
;
404 return FASTTRAP_T_INV
;
408 int arm_dataproc_immed(uint32_t instr
)
410 /* All these instructions are either two registers, or one register and have 0 where the other reg would be used */
411 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
412 return FASTTRAP_T_COMMON
;
414 return FASTTRAP_T_INV
;
418 int arm_dataproc_regshift(uint32_t instr
)
420 /* All these instructions are either four registers, or three registers and have 0 where there last reg would be used */
421 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
422 return FASTTRAP_T_COMMON
;
424 return FASTTRAP_T_INV
;
428 int arm_dataproc_reg(uint32_t instr
)
430 int op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,7,0x1F), op3
= BITS(instr
,5,0x3);
432 if (op1
== 0x11 || op1
== 0x13 || op1
== 0x15 || op1
== 0x17) {
433 /* These are comparison flag setting instructions and do not have RD */
434 if (ARM_RN(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
435 return FASTTRAP_T_COMMON
;
437 return FASTTRAP_T_INV
;
440 /* The rest can, in theory, write or use the PC. The only one we instrument is mov pc, reg.
441 * movs pc, reg is a privileged instruction so we don't instrument that variant. The s bit
442 * is bit 0 of op1 and should be zero.
444 if (op1
== 0x1A && op2
== 0 && op3
== 0 && ARM_RD(instr
) == REG_PC
)
445 return FASTTRAP_T_MOV_PC_REG
;
447 /* Any instruction at this point is a three register instruction or two register instruction with RN = 0 */
448 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
449 return FASTTRAP_T_COMMON
;
451 return FASTTRAP_T_INV
;
455 int arm_dataproc_misc(uint32_t instr
)
457 int op
= BITS(instr
,25,0x1), op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,4,0xF);
460 if ((op1
& 0x19) != 0x10 && (op2
& 0x1) == 0)
461 return arm_dataproc_reg(instr
);
463 if ((op1
& 0x19) != 0x10 && (op2
& 0x9) == 0x1)
464 return arm_dataproc_regshift(instr
);
466 if ((op1
& 0x19) == 0x10 && (op2
& 0x8) == 0)
467 return arm_misc(instr
);
469 if ((op1
& 0x19) == 0x19 && (op2
& 0x9) == 0x8)
470 return arm_halfword_multiply(instr
);
472 if ((op1
& 0x10) == 0 && op2
== 0x9)
473 return arm_multiply(instr
);
475 if ((op1
& 0x10) == 0x10 && op2
== 0x9)
476 return arm_sync_primitive(instr
);
478 if ((op1
& 0x12) != 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD))
479 return arm_extra_loadstore(instr
);
481 if ((op1
& 0x12) == 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD))
482 return arm_extra_loadstore_unpriv(instr
);
484 if ((op1
& 0x19) != 0x10)
485 return arm_dataproc_immed(instr
);
488 /* 16 bit immediate load (mov (immed)) [encoding A2] */
489 if (ARM_RD(instr
) != REG_PC
)
490 return FASTTRAP_T_COMMON
;
492 return FASTTRAP_T_INV
;
496 /* high halfword 16 bit immediate load (movt) [encoding A1] */
497 if (ARM_RD(instr
) != REG_PC
)
498 return FASTTRAP_T_COMMON
;
500 return FASTTRAP_T_INV
;
503 if ((op1
& 0x1B) == 0x12)
504 return arm_msr_hints(instr
);
507 return FASTTRAP_T_INV
;
510 int dtrace_decode_arm(uint32_t instr
)
512 int cond
= BITS(instr
,28,0xF), op1
= BITS(instr
,25,0x7), op
= BITS(instr
,4,0x1);
515 return arm_unconditional(instr
);
517 if ((op1
& 0x6) == 0)
518 return arm_dataproc_misc(instr
);
521 return arm_loadstore_wordbyte(instr
);
523 if (op1
== 0x3 && op
== 0)
524 return arm_loadstore_wordbyte(instr
);
526 if (op1
== 0x3 && op
== 1)
527 return arm_media(instr
);
529 if ((op1
& 0x6) == 0x4)
530 return arm_branch_link_blockdata(instr
);
532 if ((op1
& 0x6) == 0x6)
533 return arm_syscall_coproc(instr
);
535 return FASTTRAP_T_INV
;
539 * Thumb 16-bit decoder
543 int thumb16_cond_supervisor(uint16_t instr
)
545 int opcode
= BITS(instr
,8,0xF);
547 if ((opcode
& 0xE) != 0xE)
548 return FASTTRAP_T_B_COND
;
550 return FASTTRAP_T_INV
;
554 int thumb16_misc(uint16_t instr
)
556 int opcode
= BITS(instr
,5,0x7F);
558 if ((opcode
& 0x70) == 0x30 || (opcode
& 0x70) == 0x70) {
559 /* setend, cps, breakpoint, or if-then, not instrumentable */
560 return FASTTRAP_T_INV
;
561 } else if ((opcode
& 0x78) == 0x28) {
562 /* Doesn't modify pc, but this happens a lot so make this a special case for emulation */
563 return FASTTRAP_T_PUSH_LR
;
564 } else if ((opcode
& 0x78) == 0x68) {
565 return FASTTRAP_T_POP_PC
;
566 } else if ((opcode
& 0x28) == 0x08) {
567 return FASTTRAP_T_CB_N_Z
;
570 /* All other instructions work on low regs only and are instrumentable */
571 return FASTTRAP_T_COMMON
;
575 int thumb16_loadstore_single(__unused
uint16_t instr
)
577 /* These all access the low registers or SP only */
578 return FASTTRAP_T_COMMON
;
582 int thumb16_data_special_and_branch(uint16_t instr
)
584 int opcode
= BITS(instr
,6,0xF);
588 return FASTTRAP_T_INV
;
589 } else if ((opcode
& 0xC) == 0xC) {
591 /* Only instrument the bx */
592 if ((opcode
& 0x2) == 0)
593 return FASTTRAP_T_BX_REG
;
594 return FASTTRAP_T_INV
;
596 /* Data processing on high registers, only instrument mov pc, reg */
597 if ((opcode
& 0xC) == 0x8 && THUMB16_HRD(instr
) == REG_PC
)
598 return FASTTRAP_T_CPY_PC
;
600 if (THUMB16_HRM(instr
) != REG_PC
&& THUMB16_HRD(instr
) != REG_PC
)
601 return FASTTRAP_T_COMMON
;
604 return FASTTRAP_T_INV
;
608 int thumb16_data_proc(__unused
uint16_t instr
)
610 /* These all access the low registers only */
611 return FASTTRAP_T_COMMON
;
615 int thumb16_shift_addsub_move_compare(__unused
uint16_t instr
)
617 /* These all access the low registers only */
618 return FASTTRAP_T_COMMON
;
622 int dtrace_decode_thumb16(uint16_t instr
)
624 int opcode
= BITS(instr
,10,0x3F);
626 if ((opcode
& 0x30) == 0)
627 return thumb16_shift_addsub_move_compare(instr
);
630 return thumb16_data_proc(instr
);
633 return thumb16_data_special_and_branch(instr
);
635 if ((opcode
& 0x3E) == 0x12) {
637 return FASTTRAP_T_LDR_PC_IMMED
;
640 if ((opcode
& 0x3C) == 0x14 || (opcode
& 0x38) == 0x18 || (opcode
& 0x38) == 0x20)
641 return thumb16_loadstore_single(instr
);
643 if ((opcode
& 0x3E) == 0x28) {
644 /* adr, uses the pc */
645 return FASTTRAP_T_INV
;
648 if ((opcode
& 0x3E) == 0x2A) {
649 /* add (sp plus immediate) */
650 return FASTTRAP_T_COMMON
;
653 if ((opcode
& 0x3C) == 0x2C)
654 return thumb16_misc(instr
);
656 if ((opcode
& 0x3E) == 0x30) {
657 /* stm - can't access high registers */
658 return FASTTRAP_T_COMMON
;
661 if ((opcode
& 0x3E) == 0x32) {
662 /* ldm - can't access high registers */
663 return FASTTRAP_T_COMMON
;
666 if ((opcode
& 0x3C) == 0x34) {
667 return thumb16_cond_supervisor(instr
);
670 if ((opcode
& 0x3E) == 0x38) {
671 /* b unconditional */
672 return FASTTRAP_T_B_UNCOND
;
675 return FASTTRAP_T_INV
;
679 * Thumb 32-bit decoder
683 int thumb32_coproc(uint16_t instr1
, uint16_t instr2
)
685 /* Instrument any VFP data processing instructions, ignore the rest */
687 int op1
= BITS(instr1
,4,0x3F), coproc
= BITS(instr2
,8,0xF), op
= BITS(instr2
,4,0x1);
689 if ((op1
& 0x3E) == 0) {
691 return FASTTRAP_T_INV
;
694 if ((coproc
& 0xE) == 0xA || (op1
& 0x30) == 0x30) {
695 /* VFP instruction */
696 uint32_t instr
= thumb32_instword_to_arm(instr1
,instr2
);
698 if ((op1
& 0x30) == 0x30) {
699 /* VFP data processing uses its own registers */
700 return FASTTRAP_T_COMMON
;
703 if ((op1
& 0x3A) == 0x02 || (op1
& 0x38) == 0x08 || (op1
& 0x30) == 0x10)
704 return vfp_loadstore(instr
);
706 if ((op1
& 0x3E) == 0x04)
707 return vfp_64transfer(instr
);
709 if ((op1
& 0x30) == 0x20) {
710 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
712 /* VFP data processing uses its own registers */
713 return FASTTRAP_T_COMMON
;
715 return vfp_transfer(instr
);
720 return FASTTRAP_T_INV
;
724 int thumb32_longmultiply(uint16_t instr1
, uint16_t instr2
)
726 int op1
= BITS(instr1
,4,0x7), op2
= BITS(instr2
,4,0xF);
728 if ((op1
== 1 && op2
== 0xF) || (op1
== 0x3 && op2
== 0xF)) {
729 /* Three register instruction */
730 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
731 return FASTTRAP_T_COMMON
;
733 /* Four register instruction */
734 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&&
735 THUMB32_RT(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
736 return FASTTRAP_T_COMMON
;
739 return FASTTRAP_T_INV
;
743 int thumb32_multiply(uint16_t instr1
, uint16_t instr2
)
745 int op1
= BITS(instr1
,4,0x7), op2
= BITS(instr2
,4,0x3);
747 if ((op1
== 0 && op2
== 1) || (op1
== 0x6 && (op2
& 0x2) == 0)) {
748 if (THUMB32_RT(instr1
,instr2
) == REG_PC
)
749 return FASTTRAP_T_INV
;
752 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
753 return FASTTRAP_T_COMMON
;
755 return FASTTRAP_T_INV
;
759 int thumb32_misc(uint16_t instr1
, uint16_t instr2
)
761 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
762 return FASTTRAP_T_COMMON
;
764 return FASTTRAP_T_INV
;
768 int thumb32_parallel_addsub_unsigned(uint16_t instr1
, uint16_t instr2
)
770 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
771 return FASTTRAP_T_COMMON
;
773 return FASTTRAP_T_INV
;
777 int thumb32_parallel_addsub_signed(uint16_t instr1
, uint16_t instr2
)
779 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
780 return FASTTRAP_T_COMMON
;
782 return FASTTRAP_T_INV
;
786 int thumb32_dataproc_reg(uint16_t instr1
, uint16_t instr2
)
788 int op1
= BITS(instr1
,4,0xF), op2
= BITS(instr2
,4,0xF);
790 if (((0 <= op1
) && (op1
<= 5)) && (op2
& 0x8) == 0x8) {
791 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
)
792 return FASTTRAP_T_COMMON
;
795 if ((op1
& 0x8) == 0 && op2
== 0) {
796 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
797 return FASTTRAP_T_COMMON
;
800 if ((op1
& 0x8) == 0x8 && (op2
& 0xC) == 0)
801 return thumb32_parallel_addsub_signed(instr1
,instr2
);
803 if ((op1
& 0x8) == 0x8 && (op2
& 0xC) == 0x4)
804 return thumb32_parallel_addsub_unsigned(instr1
,instr2
);
806 if ((op1
& 0xC) == 0x8 && (op2
& 0xC) == 0x8)
807 return thumb32_misc(instr1
,instr2
);
809 return FASTTRAP_T_INV
;
813 int thumb32_dataproc_regshift(uint16_t instr1
, uint16_t instr2
)
815 int op
= BITS(instr1
,5,0xF), S
= BITS(instr1
,4,0x1);
817 if (op
== 0 || op
== 0x4 || op
== 0x8 || op
== 0xD) {
818 /* These become test instructions if S is 1 and Rd is PC, otherwise they are data instructions. */
820 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
821 return FASTTRAP_T_COMMON
;
823 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&&
824 THUMB32_RN(instr1
,instr2
) != REG_PC
)
825 return FASTTRAP_T_COMMON
;
827 } else if (op
== 0x2 || op
== 0x3) {
828 /* These become moves if RN is PC, otherwise they are data insts. We don't instrument mov pc, reg here */
829 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
)
830 return FASTTRAP_T_COMMON
;
832 /* Normal three register instruction */
833 if (THUMB32_RM(instr1
,instr2
) != REG_PC
&& THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
834 return FASTTRAP_T_COMMON
;
837 return FASTTRAP_T_INV
;
841 int thumb32_store_single(uint16_t instr1
, uint16_t instr2
)
843 int op1
= BITS(instr1
,5,0x7), op2
= BITS(instr2
,6,0x3F);
845 /* Do not support any use of the pc yet */
846 if ((op1
== 0 || op1
== 1 || op1
== 2) && (op2
& 0x20) == 0) {
847 /* str (register) uses RM */
848 if (THUMB32_RM(instr1
,instr2
) == REG_PC
)
849 return FASTTRAP_T_INV
;
852 if (THUMB32_RT(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
853 return FASTTRAP_T_COMMON
;
855 return FASTTRAP_T_INV
;
859 int thumb32_loadbyte_memhint(uint16_t instr1
, uint16_t instr2
)
861 int op1
= BITS(instr1
,7,0x3), __unused op2
= BITS(instr2
,6,0x3F);
863 /* Do not support any use of the pc yet */
864 if ((op1
== 0 || op1
== 0x2) && THUMB32_RM(instr1
,instr2
) == REG_PC
)
865 return FASTTRAP_T_INV
;
867 if (THUMB32_RT(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
868 return FASTTRAP_T_COMMON
;
870 return FASTTRAP_T_INV
;
874 int thumb32_loadhalfword_memhint(uint16_t instr1
, uint16_t instr2
)
876 int op1
= BITS(instr1
,7,0x3), op2
= BITS(instr2
,6,0x3F);
878 /* Do not support any use of the PC yet */
879 if (op1
== 0 && op2
== 0 && THUMB32_RM(inst1
,instr2
) == REG_PC
)
880 return FASTTRAP_T_INV
;
882 if (THUMB32_RT(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
883 return FASTTRAP_T_COMMON
;
885 return FASTTRAP_T_INV
;
889 int thumb32_loadword(uint16_t instr1
, uint16_t instr2
)
891 int op1
= BITS(instr1
,7,0x3), op2
= BITS(instr2
,6,0x3F);
893 if ((op1
& 0x2) == 0 && THUMB32_RN(instr1
,instr2
) == REG_PC
&& THUMB32_RT(instr1
,instr2
) != REG_PC
)
894 return FASTTRAP_T_LDR_PC_IMMED
;
896 if (op1
== 0 && op2
== 0) {
897 /* ldr (register) uses an additional reg */
898 if (THUMB32_RM(instr1
,instr2
) == REG_PC
)
899 return FASTTRAP_T_INV
;
902 if (THUMB32_RT(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
903 return FASTTRAP_T_COMMON
;
905 return FASTTRAP_T_INV
;
909 int thumb32_loadstore_double_exclusive_table(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
911 /* Don't instrument any of these */
913 return FASTTRAP_T_INV
;
917 int thumb32_loadstore_multiple(uint16_t instr1
, uint16_t instr2
)
919 int op
= BITS(instr1
,7,0x3), L
= BITS(instr1
,4,0x1), uses_pc
= BITS(instr2
,15,0x1), uses_lr
= BITS(instr2
,14,0x1);
921 if (op
== 0 || op
== 0x3) {
922 /* Privileged instructions: srs, rfe */
923 return FASTTRAP_T_INV
;
926 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc }, aka pop { ... pc } */
927 if (op
== 0x1 && L
== 1 && THUMB32_RN(instr1
,instr2
) == REG_SP
&& uses_pc
== 1)
928 return FASTTRAP_T_LDM_PC
;
930 /* stmia sp!, { ... lr }, aka push { ... lr } doesn't touch the pc, but it is very common, so special case it */
931 if (op
== 0x2 && L
== 0 && THUMB32_RN(instr1
,instr2
) == REG_SP
&& uses_lr
== 1)
932 return FASTTRAP_T_STM_LR
;
934 if (THUMB32_RN(instr1
,instr2
) != REG_PC
&& uses_pc
== 0)
935 return FASTTRAP_T_COMMON
;
937 return FASTTRAP_T_INV
;
941 int thumb32_misc_control(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
943 /* Privileged, and instructions dealing with ThumbEE */
944 return FASTTRAP_T_INV
;
948 int thumb32_cps_hints(__unused
uint16_t instr1
, __unused
uint16_t instr2
)
951 return FASTTRAP_T_INV
;
955 int thumb32_b_misc_control(uint16_t instr1
, uint16_t instr2
)
957 int op
= BITS(instr1
,4,0x7F), op1
= BITS(instr2
,12,0x7), __unused op2
= BITS(instr2
,8,0xF);
959 if ((op1
& 0x5) == 0) {
960 if ((op
& 0x38) != 0x38)
961 return FASTTRAP_T_B_COND
;
964 return thumb32_cps_hints(instr1
,instr2
);
967 return thumb32_misc_control(instr1
,instr2
);
970 if ((op1
& 0x5) == 1)
971 return FASTTRAP_T_B_UNCOND
;
973 return FASTTRAP_T_INV
;
977 int thumb32_dataproc_plain_immed(uint16_t instr1
, uint16_t instr2
)
979 int op
= BITS(instr1
,4,0x1F);
981 if (op
== 0x04 || op
== 0x0C || op
== 0x16) {
982 /* mov, movt, bfi, bfc */
983 /* These use only RD */
984 if (THUMB32_RD(instr1
,instr2
) != REG_PC
)
985 return FASTTRAP_T_COMMON
;
987 if (THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
988 return FASTTRAP_T_COMMON
;
991 return FASTTRAP_T_INV
;
995 int thumb32_dataproc_mod_immed(uint16_t instr1
, uint16_t instr2
)
997 int op
= BITS(instr1
,5,0xF), S
= BITS(instr1
,4,0x1);
999 if (op
== 0x2 || op
== 0x3) {
1000 /* These allow REG_PC in RN, but it doesn't mean use the PC! */
1001 if (THUMB32_RD(instr1
,instr2
) != REG_PC
)
1002 return FASTTRAP_T_COMMON
;
1005 if (op
== 0 || op
== 0x4 || op
== 0x8 || op
== 0xD) {
1006 /* These are test instructions, if the sign bit is set and RD is the PC. */
1007 if (S
&& THUMB32_RD(instr1
,instr2
) == REG_PC
)
1008 return FASTTRAP_T_COMMON
;
1011 if (THUMB32_RD(instr1
,instr2
) != REG_PC
&& THUMB32_RN(instr1
,instr2
) != REG_PC
)
1012 return FASTTRAP_T_COMMON
;
1014 return FASTTRAP_T_INV
;
1018 int dtrace_decode_thumb32(uint16_t instr1
, uint16_t instr2
)
1020 int op1
= BITS(instr1
,11,0x3), op2
= BITS(instr1
,4,0x7F), op
= BITS(instr2
,15,0x1);
1023 if ((op2
& 0x64) == 0)
1024 return thumb32_loadstore_multiple(instr1
,instr2
);
1026 if ((op2
& 0x64) == 0x04)
1027 return thumb32_loadstore_double_exclusive_table(instr1
,instr2
);
1029 if ((op2
& 0x60) == 0x20)
1030 return thumb32_dataproc_regshift(instr1
,instr2
);
1032 if ((op2
& 0x40) == 0x40)
1033 return thumb32_coproc(instr1
,instr2
);
1037 if ((op2
& 0x20) == 0 && op
== 0)
1038 return thumb32_dataproc_mod_immed(instr1
,instr2
);
1040 if ((op2
& 0x20) == 0x20 && op
== 0)
1041 return thumb32_dataproc_plain_immed(instr1
,instr2
);
1044 return thumb32_b_misc_control(instr1
,instr2
);
1048 if ((op2
& 0x71) == 0)
1049 return thumb32_store_single(instr1
,instr2
);
1051 if ((op2
& 0x71) == 0x10) {
1052 return vfp_struct_loadstore(thumb32_instword_to_arm(instr1
,instr2
));
1055 if ((op2
& 0x67) == 0x01)
1056 return thumb32_loadbyte_memhint(instr1
,instr2
);
1058 if ((op2
& 0x67) == 0x03)
1059 return thumb32_loadhalfword_memhint(instr1
,instr2
);
1061 if ((op2
& 0x67) == 0x05)
1062 return thumb32_loadword(instr1
,instr2
);
1064 if ((op2
& 0x67) == 0x07) {
1065 /* Undefined instruction */
1066 return FASTTRAP_T_INV
;
1069 if ((op2
& 0x70) == 0x20)
1070 return thumb32_dataproc_reg(instr1
,instr2
);
1072 if ((op2
& 0x78) == 0x30)
1073 return thumb32_multiply(instr1
,instr2
);
1075 if ((op2
& 0x78) == 0x38)
1076 return thumb32_longmultiply(instr1
,instr2
);
1078 if ((op2
& 0x40) == 0x40)
1079 return thumb32_coproc(instr1
,instr2
);
1082 return FASTTRAP_T_INV
;
1085 int dtrace_decode_thumb(uint32_t instr
)
1087 uint16_t* pInstr
= (uint16_t*) &instr
;
1088 uint16_t hw1
= pInstr
[0], hw2
= pInstr
[1];
1090 int size
= BITS(hw1
,11,0x1F);
1092 if (size
== 0x1D || size
== 0x1E || size
== 0x1F)
1093 return dtrace_decode_thumb32(hw1
,hw2
);
1095 return dtrace_decode_thumb16(hw1
);
1098 struct arm64_decode_entry
{
1104 struct arm64_decode_entry arm64_decode_table
[] = {
1105 { .mask
= 0xFFFFFFFF, .value
= FASTTRAP_ARM64_OP_VALUE_FUNC_ENTRY
, .type
= FASTTRAP_T_ARM64_STANDARD_FUNCTION_ENTRY
},
1106 { .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
},
1107 { .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
},
1108 { .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
},
1109 { .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
},
1110 { .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
},
1111 { .mask
= FASTTRAP_ARM64_OP_MASK_LRDSW_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_LRDSW_PC_REL
, .type
= FASTTRAP_T_ARM64_LDRSW_PC_REL
},
1112 { .mask
= FASTTRAP_ARM64_OP_MASK_B_COND_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_B_COND_PC_REL
, .type
= FASTTRAP_T_ARM64_B_COND
},
1113 { .mask
= FASTTRAP_ARM64_OP_MASK_CBNZ_W_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBNZ_W_PC_REL
, .type
= FASTTRAP_T_ARM64_CBNZ_W
},
1114 { .mask
= FASTTRAP_ARM64_OP_MASK_CBNZ_X_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBNZ_X_PC_REL
, .type
= FASTTRAP_T_ARM64_CBNZ_X
},
1115 { .mask
= FASTTRAP_ARM64_OP_MASK_CBZ_W_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBZ_W_PC_REL
, .type
= FASTTRAP_T_ARM64_CBZ_W
},
1116 { .mask
= FASTTRAP_ARM64_OP_MASK_CBZ_X_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_CBZ_X_PC_REL
, .type
= FASTTRAP_T_ARM64_CBZ_X
},
1117 { .mask
= FASTTRAP_ARM64_OP_MASK_TBNZ_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_TBNZ_PC_REL
, .type
= FASTTRAP_T_ARM64_TBNZ
},
1118 { .mask
= FASTTRAP_ARM64_OP_MASK_TBZ_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_TBZ_PC_REL
, .type
= FASTTRAP_T_ARM64_TBZ
},
1119 { .mask
= FASTTRAP_ARM64_OP_MASK_B_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_B_PC_REL
, .type
= FASTTRAP_T_ARM64_B
},
1120 { .mask
= FASTTRAP_ARM64_OP_MASK_BL_PC_REL
, .value
= FASTTRAP_ARM64_OP_VALUE_BL_PC_REL
, .type
= FASTTRAP_T_ARM64_BL
},
1121 { .mask
= FASTTRAP_ARM64_OP_MASK_BLR
, .value
= FASTTRAP_ARM64_OP_VALUE_BLR
, .type
= FASTTRAP_T_ARM64_BLR
},
1122 { .mask
= FASTTRAP_ARM64_OP_MASK_BR
, .value
= FASTTRAP_ARM64_OP_VALUE_BR
, .type
= FASTTRAP_T_ARM64_BR
},
1123 { .mask
= FASTTRAP_ARM64_OP_MASK_RET
, .value
= FASTTRAP_ARM64_OP_VALUE_RET
, .type
= FASTTRAP_T_ARM64_RET
},
1124 { .mask
= FASTTRAP_ARM64_OP_MASK_ADRP
, .value
= FASTTRAP_ARM64_OP_VALUE_ADRP
, .type
= FASTTRAP_T_ARM64_ADRP
},
1125 { .mask
= FASTTRAP_ARM64_OP_MASK_ADR
, .value
= FASTTRAP_ARM64_OP_VALUE_ADR
, .type
= FASTTRAP_T_ARM64_ADR
},
1126 { .mask
= FASTTRAP_ARM64_OP_MASK_PRFM
, .value
= FASTTRAP_ARM64_OP_VALUE_PRFM
, .type
= FASTTRAP_T_ARM64_PRFM
},
1127 { .mask
= FASTTRAP_ARM64_OP_MASK_EXCL_MEM
, .value
= FASTTRAP_ARM64_OP_VALUE_EXCL_MEM
, .type
= FASTTRAP_T_ARM64_EXCLUSIVE_MEM
},
1128 { .mask
= FASTTRAP_ARM64_OP_MASK_RETAB
, .value
= FASTTRAP_ARM64_OP_VALUE_RETAB
, .type
= FASTTRAP_T_ARM64_RETAB
}};
1130 #define NUM_DECODE_ENTRIES (sizeof(arm64_decode_table) / sizeof(struct arm64_decode_entry))
1134 int dtrace_decode_arm64(uint32_t instr
)
1138 for (i
= 0; i
< NUM_DECODE_ENTRIES
; i
++) {
1139 if ((instr
& arm64_decode_table
[i
].mask
) == arm64_decode_table
[i
].value
) {
1140 return arm64_decode_table
[i
].type
;
1144 return FASTTRAP_T_COMMON
;