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