]>
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))
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_thumb(uint32_t instr
);
26 * VFP decoder - shared between ARM and THUMB32 mode
30 int vfp_struct_loadstore(uint32_t instr
)
32 if (ARM_RM(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
33 return FASTTRAP_T_COMMON
;
35 return FASTTRAP_T_INV
;
39 int vfp_64transfer(uint32_t instr
)
41 /* These instructions all use RD and RN */
42 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
43 return FASTTRAP_T_COMMON
;
45 return FASTTRAP_T_INV
;
49 int vfp_transfer(uint32_t instr
)
51 /* These instructions all use RD only */
52 if (ARM_RD(instr
) != REG_PC
)
53 return FASTTRAP_T_COMMON
;
55 return FASTTRAP_T_INV
;
59 int vfp_loadstore(uint32_t instr
)
61 int opcode
= BITS(instr
,20,0x1F);
64 if ((opcode
& 0x13) == 0x11 && ARM_RN(instr
) == REG_PC
)
65 return FASTTRAP_T_VLDR_PC_IMMED
;
67 /* These instructions all use RN only */
68 if (ARM_RN(instr
) != REG_PC
)
69 return FASTTRAP_T_COMMON
;
71 return FASTTRAP_T_INV
;
79 int arm_unconditional_misc(uint32_t instr
)
81 int op
= BITS(instr
,20,0x7F);
83 if ((op
& 0x60) == 0x20) {
84 /* VFP data processing uses its own registers */
85 return FASTTRAP_T_COMMON
;
88 if ((op
& 0x71) == 0x40) {
89 return vfp_struct_loadstore(instr
);
92 return FASTTRAP_T_INV
;
96 int arm_unconditional(uint32_t instr
)
98 if (BITS(instr
,27,0x1) == 0)
99 return arm_unconditional_misc(instr
);
101 /* The rest are privileged or BL/BLX, do not instrument */
103 /* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
105 return FASTTRAP_T_INV
;
109 int arm_syscall_coproc(uint32_t instr
)
111 /* Instrument any VFP data processing instructions, ignore the rest */
113 int op1
= BITS(instr
,20,0x3F), coproc
= BITS(instr
,8,0xF), op
= BITS(instr
,4,0x1);
115 if ((op1
& 0x3E) == 0 || (op1
& 0x30) == 0x30) {
116 /* Undefined or swi */
117 return FASTTRAP_T_INV
;
120 if ((coproc
& 0xE) == 0xA) {
121 /* VFP instruction */
123 if ((op1
& 0x20) == 0 && (op1
& 0x3A) != 0)
124 return vfp_loadstore(instr
);
126 if ((op1
& 0x3E) == 0x04)
127 return vfp_64transfer(instr
);
129 if ((op1
& 0x30) == 0x20) {
130 /* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
132 /* VFP data processing uses its own registers */
133 return FASTTRAP_T_COMMON
;
135 return vfp_transfer(instr
);
140 return FASTTRAP_T_INV
;
144 int arm_branch_link_blockdata(uint32_t instr
)
146 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);
150 return FASTTRAP_T_B_COND
;
151 return FASTTRAP_T_INV
;
153 /* Only emulate a use of the pc if it's a return from function: ldmia sp!, { ... pc } */
154 if (op
== 0x0B && ARM_RN(instr
) == REG_SP
&& uses_pc
== 1)
155 return FASTTRAP_T_LDM_PC
;
157 /* stmia sp!, { ... lr } doesn't touch the pc, but it is very common, so special case it */
158 if (op
== 0x12 && ARM_RN(instr
) == REG_SP
&& uses_lr
== 1)
159 return FASTTRAP_T_STM_LR
;
161 if (ARM_RN(instr
) != REG_PC
&& uses_pc
== 0)
162 return FASTTRAP_T_COMMON
;
165 return FASTTRAP_T_INV
;
169 int arm_signed_multiplies(uint32_t instr
)
171 int op1
= BITS(instr
,20,0x7), op2
= BITS(instr
,5,0x7);
173 /* smlald, smlsld, smmls use RD in addition to RM, RS, and RN */
174 if ((op1
== 0x4 && (op2
& 0x4) == 0) || (op1
== 0x5 && (op2
& 0x6) == 0x6)) {
175 if (ARM_RD(instr
) == REG_PC
)
176 return FASTTRAP_T_INV
;
179 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
180 return FASTTRAP_T_COMMON
;
182 return FASTTRAP_T_INV
;
186 int arm_pack_unpack_sat_reversal(uint32_t instr
)
188 int op1
= BITS(instr
,20,0x7), op2
= BITS(instr
,5,0x7);
190 /* pkh, sel use RN in addition to RD and RM */
191 if ((op1
== 0 && (op2
& 0x1) == 0) || (op1
== 0 && op2
== 0x5)) {
192 if (ARM_RN(instr
) == REG_PC
)
193 return FASTTRAP_T_INV
;
196 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
197 return FASTTRAP_T_COMMON
;
199 return FASTTRAP_T_INV
;
203 int arm_parallel_addsub_unsigned(uint32_t instr
)
205 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
206 return FASTTRAP_T_COMMON
;
208 return FASTTRAP_T_INV
;
212 int arm_parallel_addsub_signed(uint32_t instr
)
214 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
215 return FASTTRAP_T_COMMON
;
217 return FASTTRAP_T_INV
;
221 int arm_media(uint32_t instr
)
223 int op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,5,0x7);
225 if ((op1
& 0x1C) == 0)
226 return arm_parallel_addsub_signed(instr
);
228 if ((op1
& 0x1C) == 0x04)
229 return arm_parallel_addsub_unsigned(instr
);
231 if ((op1
& 0x18) == 0x08)
232 return arm_pack_unpack_sat_reversal(instr
);
234 if ((op1
& 0x18) == 0x10)
235 return arm_signed_multiplies(instr
);
237 if (op1
== 0x1F && op2
== 0x7) {
238 /* Undefined instruction */
239 return FASTTRAP_T_INV
;
242 if (op1
== 0x18 && op2
== 0) {
244 /* The registers are named differently in the reference manual for this instruction
245 * but the following positions are correct */
247 if (ARM_RM(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
248 return FASTTRAP_T_COMMON
;
250 return FASTTRAP_T_INV
;
253 if ((op1
& 0x1E) == 0x1C && (op2
& 0x3) == 0) {
255 if (ARM_RD(instr
) != REG_PC
)
256 return FASTTRAP_T_COMMON
;
258 return FASTTRAP_T_INV
;
261 if (((op1
& 0x1E) == 0x1A || (op1
& 0x1E) == 0x1E) && ((op2
& 0x3) == 0x2)) {
263 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
264 return FASTTRAP_T_COMMON
;
266 return FASTTRAP_T_INV
;
269 return FASTTRAP_T_INV
;
273 int arm_loadstore_wordbyte(uint32_t instr
)
275 /* Instrument PC relative load with immediate, ignore any other uses of the PC */
276 int R
= BITS(instr
,25,0x1), L
= BITS(instr
,20,0x1);
279 /* Three register load/store */
280 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
281 return FASTTRAP_T_COMMON
;
283 /* Immediate load/store, but still do not support ldr pc, [pc...] */
284 if (L
== 1 && ARM_RN(instr
) == REG_PC
&& ARM_RD(instr
) != REG_PC
)
285 return FASTTRAP_T_LDR_PC_IMMED
;
287 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
288 return FASTTRAP_T_COMMON
;
291 return FASTTRAP_T_INV
;
295 int arm_saturating(uint32_t instr
)
297 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
298 return FASTTRAP_T_COMMON
;
300 return FASTTRAP_T_INV
;
304 int arm_misc(uint32_t instr
)
306 int op
= BITS(instr
,21,0x3), __unused op1
= BITS(instr
,16,0xF), op2
= BITS(instr
,4,0x7);
308 if (op2
== 1 && op
== 1)
309 return FASTTRAP_T_BX_REG
;
311 /* We do not need to emulate BLX for entry/return probes; if we eventually support full offset
312 * tracing, then we will. This is because BLX overwrites the link register, so a function that
313 * can execute this as its first instruction is a special function indeed.
317 return arm_saturating(instr
);
319 return FASTTRAP_T_INV
;
323 int arm_msr_hints(__unused
uint32_t instr
)
325 /* These deal with the psr, not instrumented */
327 return FASTTRAP_T_INV
;
331 int arm_sync_primitive(__unused
uint32_t instr
)
333 /* TODO will instrumenting these interfere with any kernel usage of these instructions? */
334 /* Don't instrument for now */
336 return FASTTRAP_T_INV
;
340 int arm_extra_loadstore_unpriv(uint32_t instr
)
342 int op
= BITS(instr
,20,0x1), __unused op2
= BITS(instr
,5,0x3), immed
= BITS(instr
,22,0x1);
344 if (op
== 0 && (op2
& 0x2) == 0x2) {
345 /* Unpredictable or undefined */
346 return FASTTRAP_T_INV
;
350 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
351 return FASTTRAP_T_COMMON
;
353 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
354 return FASTTRAP_T_COMMON
;
357 return FASTTRAP_T_INV
;
361 int arm_extra_loadstore(uint32_t instr
)
363 int op1
= BITS(instr
,20,0x1F);
365 /* There are two variants, and we do not instrument either of them that use the PC */
367 if ((op1
& 0x4) == 0) {
368 /* Variant 1, register */
369 if (ARM_RM(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
370 return FASTTRAP_T_COMMON
;
372 /* Variant 2, immediate */
373 if (ARM_RD(instr
) != REG_PC
&& ARM_RN(instr
) != REG_PC
)
374 return FASTTRAP_T_COMMON
;
377 return FASTTRAP_T_INV
;
381 int arm_halfword_multiply(uint32_t instr
)
383 /* Not all multiply instructions use all four registers. The ones that don't should have those
384 * register locations set to 0, so we can test them anyway.
387 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
388 return FASTTRAP_T_COMMON
;
390 return FASTTRAP_T_INV
;
394 int arm_multiply(uint32_t instr
)
396 /* Not all multiply instructions use all four registers. The ones that don't should have those
397 * register locations set to 0, so we can test them anyway.
400 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
401 return FASTTRAP_T_COMMON
;
403 return FASTTRAP_T_INV
;
407 int arm_dataproc_immed(uint32_t instr
)
409 /* All these instructions are either two registers, or one register and have 0 where the other reg would be used */
410 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
)
411 return FASTTRAP_T_COMMON
;
413 return FASTTRAP_T_INV
;
417 int arm_dataproc_regshift(uint32_t instr
)
419 /* All these instructions are either four registers, or three registers and have 0 where there last reg would be used */
420 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RS(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
421 return FASTTRAP_T_COMMON
;
423 return FASTTRAP_T_INV
;
427 int arm_dataproc_reg(uint32_t instr
)
429 int op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,7,0x1F), op3
= BITS(instr
,5,0x3);
431 if (op1
== 0x11 || op1
== 0x13 || op1
== 0x15 || op1
== 0x17) {
432 /* These are comparison flag setting instructions and do not have RD */
433 if (ARM_RN(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
434 return FASTTRAP_T_COMMON
;
436 return FASTTRAP_T_INV
;
439 /* The rest can, in theory, write or use the PC. The only one we instrument is mov pc, reg.
440 * movs pc, reg is a privileged instruction so we don't instrument that variant. The s bit
441 * is bit 0 of op1 and should be zero.
443 if (op1
== 0x1A && op2
== 0 && op3
== 0 && ARM_RD(instr
) == REG_PC
)
444 return FASTTRAP_T_MOV_PC_REG
;
446 /* Any instruction at this point is a three register instruction or two register instruction with RN = 0 */
447 if (ARM_RN(instr
) != REG_PC
&& ARM_RD(instr
) != REG_PC
&& ARM_RM(instr
) != REG_PC
)
448 return FASTTRAP_T_COMMON
;
450 return FASTTRAP_T_INV
;
454 int arm_dataproc_misc(uint32_t instr
)
456 int op
= BITS(instr
,25,0x1), op1
= BITS(instr
,20,0x1F), op2
= BITS(instr
,4,0xF);
459 if ((op1
& 0x19) != 0x10 && (op2
& 0x1) == 0)
460 return arm_dataproc_reg(instr
);
462 if ((op1
& 0x19) != 0x10 && (op2
& 0x9) == 0x1)
463 return arm_dataproc_regshift(instr
);
465 if ((op1
& 0x19) == 0x10 && (op2
& 0x8) == 0)
466 return arm_misc(instr
);
468 if ((op1
& 0x19) == 0x19 && (op2
& 0x9) == 0x8)
469 return arm_halfword_multiply(instr
);
471 if ((op1
& 0x10) == 0 && op2
== 0x9)
472 return arm_multiply(instr
);
474 if ((op1
& 0x10) == 0x10 && op2
== 0x9)
475 return arm_sync_primitive(instr
);
477 if ((op1
& 0x12) != 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD))
478 return arm_extra_loadstore(instr
);
480 if ((op1
& 0x12) == 0x02 && (op2
== 0xB || (op2
& 0xD) == 0xD))
481 return arm_extra_loadstore_unpriv(instr
);
483 if ((op1
& 0x19) != 0x10)
484 return arm_dataproc_immed(instr
);
487 /* 16 bit immediate load (mov (immed)) [encoding A2] */
488 if (ARM_RD(instr
) != REG_PC
)
489 return FASTTRAP_T_COMMON
;
491 return FASTTRAP_T_INV
;
495 /* high halfword 16 bit immediate load (movt) [encoding A1] */
496 if (ARM_RD(instr
) != REG_PC
)
497 return FASTTRAP_T_COMMON
;
499 return FASTTRAP_T_INV
;
502 if ((op1
& 0x1B) == 0x12)
503 return arm_msr_hints(instr
);
506 return FASTTRAP_T_INV
;
509 int dtrace_decode_arm(uint32_t instr
)
511 int cond
= BITS(instr
,28,0xF), op1
= BITS(instr
,25,0x7), op
= BITS(instr
,4,0x1);
514 return arm_unconditional(instr
);
516 if ((op1
& 0x6) == 0)
517 return arm_dataproc_misc(instr
);
520 return arm_loadstore_wordbyte(instr
);
522 if (op1
== 0x3 && op
== 0)
523 return arm_loadstore_wordbyte(instr
);
525 if (op1
== 0x3 && op
== 1)
526 return arm_media(instr
);
528 if ((op1
& 0x6) == 0x4)
529 return arm_branch_link_blockdata(instr
);
531 if ((op1
& 0x6) == 0x6)
532 return arm_syscall_coproc(instr
);
534 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
);