]>
git.saurik.com Git - apple/xnu.git/blob - bsd/dev/arm/disassembler.c
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_thumb(uint32_t instr
);
27 * VFP decoder - shared between ARM and THUMB32 mode
32 vfp_struct_loadstore(uint32_t instr
)
34 if (ARM_RM(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
35 return FASTTRAP_T_COMMON
;
38 return FASTTRAP_T_INV
;
43 vfp_64transfer(uint32_t instr
)
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
;
50 return FASTTRAP_T_INV
;
55 vfp_transfer(uint32_t instr
)
57 /* These instructions all use RD only */
58 if (ARM_RD(instr
) != REG_PC
) {
59 return FASTTRAP_T_COMMON
;
62 return FASTTRAP_T_INV
;
67 vfp_loadstore(uint32_t instr
)
69 int opcode
= BITS(instr
, 20, 0x1F);
72 if ((opcode
& 0x13) == 0x11 && ARM_RN(instr
) == REG_PC
) {
73 return FASTTRAP_T_VLDR_PC_IMMED
;
76 /* These instructions all use RN only */
77 if (ARM_RN(instr
) != REG_PC
) {
78 return FASTTRAP_T_COMMON
;
81 return FASTTRAP_T_INV
;
90 arm_unconditional_misc(uint32_t instr
)
92 int op
= BITS(instr
, 20, 0x7F);
94 if ((op
& 0x60) == 0x20) {
95 /* VFP data processing uses its own registers */
96 return FASTTRAP_T_COMMON
;
99 if ((op
& 0x71) == 0x40) {
100 return vfp_struct_loadstore(instr
);
103 return FASTTRAP_T_INV
;
108 arm_unconditional(uint32_t instr
)
110 if (BITS(instr
, 27, 0x1) == 0) {
111 return arm_unconditional_misc(instr
);
114 /* The rest are privileged or BL/BLX, do not instrument */
116 /* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
118 return FASTTRAP_T_INV
;
123 arm_syscall_coproc(uint32_t instr
)
125 /* Instrument any VFP data processing instructions, ignore the rest */
127 int op1
= BITS(instr
, 20, 0x3F), coproc
= BITS(instr
, 8, 0xF), op
= BITS(instr
, 4, 0x1);
129 if ((op1
& 0x3E) == 0 || (op1
& 0x30) == 0x30) {
130 /* Undefined or swi */
131 return FASTTRAP_T_INV
;
134 if ((coproc
& 0xE) == 0xA) {
135 /* VFP instruction */
137 if ((op1
& 0x20) == 0 && (op1
& 0x3A) != 0) {
138 return vfp_loadstore(instr
);
141 if ((op1
& 0x3E) == 0x04) {
142 return vfp_64transfer(instr
);
145 if ((op1
& 0x30) == 0x20) {
146 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
148 /* VFP data processing uses its own registers */
149 return FASTTRAP_T_COMMON
;
151 return vfp_transfer(instr
);
156 return FASTTRAP_T_INV
;
161 arm_branch_link_blockdata(uint32_t instr
)
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);
167 return FASTTRAP_T_B_COND
;
169 return FASTTRAP_T_INV
;
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
;
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
;
181 if (ARM_RN(instr
) != REG_PC
&& uses_pc
== 0) {
182 return FASTTRAP_T_COMMON
;
186 return FASTTRAP_T_INV
;
191 arm_signed_multiplies(uint32_t instr
)
193 int op1
= BITS(instr
, 20, 0x7), op2
= BITS(instr
, 5, 0x7);
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
;
202 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
203 return FASTTRAP_T_COMMON
;
206 return FASTTRAP_T_INV
;
211 arm_pack_unpack_sat_reversal(uint32_t instr
)
213 int op1
= BITS(instr
, 20, 0x7), op2
= BITS(instr
, 5, 0x7);
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
;
222 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
) {
223 return FASTTRAP_T_COMMON
;
226 return FASTTRAP_T_INV
;
231 arm_parallel_addsub_unsigned(uint32_t instr
)
233 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
234 return FASTTRAP_T_COMMON
;
237 return FASTTRAP_T_INV
;
242 arm_parallel_addsub_signed(uint32_t instr
)
244 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
245 return FASTTRAP_T_COMMON
;
248 return FASTTRAP_T_INV
;
253 arm_media(uint32_t instr
)
255 int op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 5, 0x7);
257 if ((op1
& 0x1C) == 0) {
258 return arm_parallel_addsub_signed(instr
);
261 if ((op1
& 0x1C) == 0x04) {
262 return arm_parallel_addsub_unsigned(instr
);
265 if ((op1
& 0x18) == 0x08) {
266 return arm_pack_unpack_sat_reversal(instr
);
269 if ((op1
& 0x18) == 0x10) {
270 return arm_signed_multiplies(instr
);
273 if (op1
== 0x1F && op2
== 0x7) {
274 /* Undefined instruction */
275 return FASTTRAP_T_INV
;
278 if (op1
== 0x18 && op2
== 0) {
280 /* The registers are named differently in the reference manual for this instruction
281 * but the following positions are correct */
283 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
284 return FASTTRAP_T_COMMON
;
287 return FASTTRAP_T_INV
;
290 if ((op1
& 0x1E) == 0x1C && (op2
& 0x3) == 0) {
292 if (ARM_RD(instr
) != REG_PC
) {
293 return FASTTRAP_T_COMMON
;
296 return FASTTRAP_T_INV
;
299 if (((op1
& 0x1E) == 0x1A || (op1
& 0x1E) == 0x1E) && ((op2
& 0x3) == 0x2)) {
301 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
) {
302 return FASTTRAP_T_COMMON
;
305 return FASTTRAP_T_INV
;
308 return FASTTRAP_T_INV
;
313 arm_loadstore_wordbyte(uint32_t instr
)
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);
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
;
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
;
329 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
330 return FASTTRAP_T_COMMON
;
334 return FASTTRAP_T_INV
;
339 arm_saturating(uint32_t instr
)
341 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
342 return FASTTRAP_T_COMMON
;
345 return FASTTRAP_T_INV
;
350 arm_misc(uint32_t instr
)
352 int op
= BITS(instr
, 21, 0x3), __unused op1
= BITS(instr
, 16, 0xF), op2
= BITS(instr
, 4, 0x7);
354 if (op2
== 1 && op
== 1) {
355 return FASTTRAP_T_BX_REG
;
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.
364 return arm_saturating(instr
);
367 return FASTTRAP_T_INV
;
372 arm_msr_hints(__unused
uint32_t instr
)
374 /* These deal with the psr, not instrumented */
376 return FASTTRAP_T_INV
;
381 arm_sync_primitive(__unused
uint32_t instr
)
383 /* TODO will instrumenting these interfere with any kernel usage of these instructions? */
384 /* Don't instrument for now */
386 return FASTTRAP_T_INV
;
391 arm_extra_loadstore_unpriv(uint32_t instr
)
393 int op
= BITS(instr
, 20, 0x1), __unused op2
= BITS(instr
, 5, 0x3), immed
= BITS(instr
, 22, 0x1);
395 if (op
== 0 && (op2
& 0x2) == 0x2) {
396 /* Unpredictable or undefined */
397 return FASTTRAP_T_INV
;
401 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
402 return FASTTRAP_T_COMMON
;
405 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
406 return FASTTRAP_T_COMMON
;
410 return FASTTRAP_T_INV
;
415 arm_extra_loadstore(uint32_t instr
)
417 int op1
= BITS(instr
, 20, 0x1F);
419 /* There are two variants, and we do not instrument either of them that use the PC */
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
;
427 /* Variant 2, immediate */
428 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
) {
429 return FASTTRAP_T_COMMON
;
433 return FASTTRAP_T_INV
;
438 arm_halfword_multiply(uint32_t instr
)
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.
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
;
448 return FASTTRAP_T_INV
;
453 arm_multiply(uint32_t instr
)
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.
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
;
463 return FASTTRAP_T_INV
;
468 arm_dataproc_immed(uint32_t instr
)
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
;
475 return FASTTRAP_T_INV
;
480 arm_dataproc_regshift(uint32_t instr
)
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
;
487 return FASTTRAP_T_INV
;
492 arm_dataproc_reg(uint32_t instr
)
494 int op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 7, 0x1F), op3
= BITS(instr
, 5, 0x3);
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
;
502 return FASTTRAP_T_INV
;
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.
509 if (op1
== 0x1A && op2
== 0 && op3
== 0 && ARM_RD(instr
) == REG_PC
) {
510 return FASTTRAP_T_MOV_PC_REG
;
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
;
518 return FASTTRAP_T_INV
;
523 arm_dataproc_misc(uint32_t instr
)
525 int op
= BITS(instr
, 25, 0x1), op1
= BITS(instr
, 20, 0x1F), op2
= BITS(instr
, 4, 0xF);
528 if ((op1
& 0x19) != 0x10 && (op2
& 0x1) == 0) {
529 return arm_dataproc_reg(instr
);
532 if ((op1
& 0x19) != 0x10 && (op2
& 0x9) == 0x1) {
533 return arm_dataproc_regshift(instr
);
536 if ((op1
& 0x19) == 0x10 && (op2
& 0x8) == 0) {
537 return arm_misc(instr
);
540 if ((op1
& 0x19) == 0x19 && (op2
& 0x9) == 0x8) {
541 return arm_halfword_multiply(instr
);
544 if ((op1
& 0x10) == 0 && op2
== 0x9) {
545 return arm_multiply(instr
);
548 if ((op1
& 0x10) == 0x10 && op2
== 0x9) {
549 return arm_sync_primitive(instr
);
552 if ((op1
& 0x12) != 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD)) {
553 return arm_extra_loadstore(instr
);
556 if ((op1
& 0x12) == 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD)) {
557 return arm_extra_loadstore_unpriv(instr
);
560 if ((op1
& 0x19) != 0x10) {
561 return arm_dataproc_immed(instr
);
565 /* 16 bit immediate load (mov (immed)) [encoding A2] */
566 if (ARM_RD(instr
) != REG_PC
) {
567 return FASTTRAP_T_COMMON
;
570 return FASTTRAP_T_INV
;
574 /* high halfword 16 bit immediate load (movt) [encoding A1] */
575 if (ARM_RD(instr
) != REG_PC
) {
576 return FASTTRAP_T_COMMON
;
579 return FASTTRAP_T_INV
;
582 if ((op1
& 0x1B) == 0x12) {
583 return arm_msr_hints(instr
);
587 return FASTTRAP_T_INV
;
591 dtrace_decode_arm(uint32_t instr
)
593 int cond
= BITS(instr
, 28, 0xF), op1
= BITS(instr
, 25, 0x7), op
= BITS(instr
, 4, 0x1);
596 return arm_unconditional(instr
);
599 if ((op1
& 0x6) == 0) {
600 return arm_dataproc_misc(instr
);
604 return arm_loadstore_wordbyte(instr
);
607 if (op1
== 0x3 && op
== 0) {
608 return arm_loadstore_wordbyte(instr
);
611 if (op1
== 0x3 && op
== 1) {
612 return arm_media(instr
);
615 if ((op1
& 0x6) == 0x4) {
616 return arm_branch_link_blockdata(instr
);
619 if ((op1
& 0x6) == 0x6) {
620 return arm_syscall_coproc(instr
);
623 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
);