xref: /xnu-8019.80.24/bsd/dev/arm/disassembler.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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
thumb32_instword_to_arm(uint16_t hw1,uint16_t hw2)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_thumb(uint32_t instr);
25 
26 /*
27  * VFP decoder - shared between ARM and THUMB32 mode
28  */
29 
30 static
31 int
vfp_struct_loadstore(uint32_t instr)32 vfp_struct_loadstore(uint32_t instr)
33 {
34 	if (ARM_RM(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
35 		return FASTTRAP_T_COMMON;
36 	}
37 
38 	return FASTTRAP_T_INV;
39 }
40 
41 static
42 int
vfp_64transfer(uint32_t instr)43 vfp_64transfer(uint32_t instr)
44 {
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;
48 	}
49 
50 	return FASTTRAP_T_INV;
51 }
52 
53 static
54 int
vfp_transfer(uint32_t instr)55 vfp_transfer(uint32_t instr)
56 {
57 	/* These instructions all use RD only */
58 	if (ARM_RD(instr) != REG_PC) {
59 		return FASTTRAP_T_COMMON;
60 	}
61 
62 	return FASTTRAP_T_INV;
63 }
64 
65 static
66 int
vfp_loadstore(uint32_t instr)67 vfp_loadstore(uint32_t instr)
68 {
69 	int opcode = BITS(instr, 20, 0x1F);
70 
71 	/* Instrument VLDR */
72 	if ((opcode & 0x13) == 0x11 && ARM_RN(instr) == REG_PC) {
73 		return FASTTRAP_T_VLDR_PC_IMMED;
74 	}
75 
76 	/* These instructions all use RN only */
77 	if (ARM_RN(instr) != REG_PC) {
78 		return FASTTRAP_T_COMMON;
79 	}
80 
81 	return FASTTRAP_T_INV;
82 }
83 
84 /*
85  * ARM decoder
86  */
87 
88 static
89 int
arm_unconditional_misc(uint32_t instr)90 arm_unconditional_misc(uint32_t instr)
91 {
92 	int op = BITS(instr, 20, 0x7F);
93 
94 	if ((op & 0x60) == 0x20) {
95 		/* VFP data processing uses its own registers */
96 		return FASTTRAP_T_COMMON;
97 	}
98 
99 	if ((op & 0x71) == 0x40) {
100 		return vfp_struct_loadstore(instr);
101 	}
102 
103 	return FASTTRAP_T_INV;
104 }
105 
106 static
107 int
arm_unconditional(uint32_t instr)108 arm_unconditional(uint32_t instr)
109 {
110 	if (BITS(instr, 27, 0x1) == 0) {
111 		return arm_unconditional_misc(instr);
112 	}
113 
114 	/* The rest are privileged or BL/BLX, do not instrument */
115 
116 	/* Do not need to instrument BL/BLX either, see comment in arm_misc(uint32_t) */
117 
118 	return FASTTRAP_T_INV;
119 }
120 
121 static
122 int
arm_syscall_coproc(uint32_t instr)123 arm_syscall_coproc(uint32_t instr)
124 {
125 	/* Instrument any VFP data processing instructions, ignore the rest */
126 
127 	int op1 = BITS(instr, 20, 0x3F), coproc = BITS(instr, 8, 0xF), op = BITS(instr, 4, 0x1);
128 
129 	if ((op1 & 0x3E) == 0 || (op1 & 0x30) == 0x30) {
130 		/* Undefined or swi */
131 		return FASTTRAP_T_INV;
132 	}
133 
134 	if ((coproc & 0xE) == 0xA) {
135 		/* VFP instruction */
136 
137 		if ((op1 & 0x20) == 0 && (op1 & 0x3A) != 0) {
138 			return vfp_loadstore(instr);
139 		}
140 
141 		if ((op1 & 0x3E) == 0x04) {
142 			return vfp_64transfer(instr);
143 		}
144 
145 		if ((op1 & 0x30) == 0x20) {
146 			/* VFP data processing or 8, 16, or 32 bit move between ARM reg and VFP reg */
147 			if (op == 0) {
148 				/* VFP data processing uses its own registers */
149 				return FASTTRAP_T_COMMON;
150 			} else {
151 				return vfp_transfer(instr);
152 			}
153 		}
154 	}
155 
156 	return FASTTRAP_T_INV;
157 }
158 
159 static
160 int
arm_branch_link_blockdata(uint32_t instr)161 arm_branch_link_blockdata(uint32_t instr)
162 {
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);
164 
165 	if (branch == 1) {
166 		if (link == 0) {
167 			return FASTTRAP_T_B_COND;
168 		}
169 		return FASTTRAP_T_INV;
170 	} else {
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;
174 		}
175 
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;
179 		}
180 
181 		if (ARM_RN(instr) != REG_PC && uses_pc == 0) {
182 			return FASTTRAP_T_COMMON;
183 		}
184 	}
185 
186 	return FASTTRAP_T_INV;
187 }
188 
189 static
190 int
arm_signed_multiplies(uint32_t instr)191 arm_signed_multiplies(uint32_t instr)
192 {
193 	int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
194 
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;
199 		}
200 	}
201 
202 	if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
203 		return FASTTRAP_T_COMMON;
204 	}
205 
206 	return FASTTRAP_T_INV;
207 }
208 
209 static
210 int
arm_pack_unpack_sat_reversal(uint32_t instr)211 arm_pack_unpack_sat_reversal(uint32_t instr)
212 {
213 	int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
214 
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;
219 		}
220 	}
221 
222 	if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
223 		return FASTTRAP_T_COMMON;
224 	}
225 
226 	return FASTTRAP_T_INV;
227 }
228 
229 static
230 int
arm_parallel_addsub_unsigned(uint32_t instr)231 arm_parallel_addsub_unsigned(uint32_t instr)
232 {
233 	if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
234 		return FASTTRAP_T_COMMON;
235 	}
236 
237 	return FASTTRAP_T_INV;
238 }
239 
240 static
241 int
arm_parallel_addsub_signed(uint32_t instr)242 arm_parallel_addsub_signed(uint32_t instr)
243 {
244 	if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
245 		return FASTTRAP_T_COMMON;
246 	}
247 
248 	return FASTTRAP_T_INV;
249 }
250 
251 static
252 int
arm_media(uint32_t instr)253 arm_media(uint32_t instr)
254 {
255 	int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 5, 0x7);
256 
257 	if ((op1 & 0x1C) == 0) {
258 		return arm_parallel_addsub_signed(instr);
259 	}
260 
261 	if ((op1 & 0x1C) == 0x04) {
262 		return arm_parallel_addsub_unsigned(instr);
263 	}
264 
265 	if ((op1 & 0x18) == 0x08) {
266 		return arm_pack_unpack_sat_reversal(instr);
267 	}
268 
269 	if ((op1 & 0x18) == 0x10) {
270 		return arm_signed_multiplies(instr);
271 	}
272 
273 	if (op1 == 0x1F && op2 == 0x7) {
274 		/* Undefined instruction */
275 		return FASTTRAP_T_INV;
276 	}
277 
278 	if (op1 == 0x18 && op2 == 0) {
279 		/* usad8 usada8 */
280 		/* The registers are named differently in the reference manual for this instruction
281 		 * but the following positions are correct */
282 
283 		if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
284 			return FASTTRAP_T_COMMON;
285 		}
286 
287 		return FASTTRAP_T_INV;
288 	}
289 
290 	if ((op1 & 0x1E) == 0x1C && (op2 & 0x3) == 0) {
291 		/* bfc bfi */
292 		if (ARM_RD(instr) != REG_PC) {
293 			return FASTTRAP_T_COMMON;
294 		}
295 
296 		return FASTTRAP_T_INV;
297 	}
298 
299 	if (((op1 & 0x1E) == 0x1A || (op1 & 0x1E) == 0x1E) && ((op2 & 0x3) == 0x2)) {
300 		/* sbfx ubfx */
301 		if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
302 			return FASTTRAP_T_COMMON;
303 		}
304 
305 		return FASTTRAP_T_INV;
306 	}
307 
308 	return FASTTRAP_T_INV;
309 }
310 
311 static
312 int
arm_loadstore_wordbyte(uint32_t instr)313 arm_loadstore_wordbyte(uint32_t instr)
314 {
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);
317 
318 	if (R == 1) {
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;
322 		}
323 	} else {
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;
327 		}
328 
329 		if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
330 			return FASTTRAP_T_COMMON;
331 		}
332 	}
333 
334 	return FASTTRAP_T_INV;
335 }
336 
337 static
338 int
arm_saturating(uint32_t instr)339 arm_saturating(uint32_t instr)
340 {
341 	if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
342 		return FASTTRAP_T_COMMON;
343 	}
344 
345 	return FASTTRAP_T_INV;
346 }
347 
348 static
349 int
arm_misc(uint32_t instr)350 arm_misc(uint32_t instr)
351 {
352 	int op = BITS(instr, 21, 0x3), __unused op1 = BITS(instr, 16, 0xF), op2 = BITS(instr, 4, 0x7);
353 
354 	if (op2 == 1 && op == 1) {
355 		return FASTTRAP_T_BX_REG;
356 	}
357 
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.
361 	 */
362 
363 	if (op2 == 0x5) {
364 		return arm_saturating(instr);
365 	}
366 
367 	return FASTTRAP_T_INV;
368 }
369 
370 static
371 int
arm_msr_hints(__unused uint32_t instr)372 arm_msr_hints(__unused uint32_t instr)
373 {
374 	/* These deal with the psr, not instrumented */
375 
376 	return FASTTRAP_T_INV;
377 }
378 
379 static
380 int
arm_sync_primitive(__unused uint32_t instr)381 arm_sync_primitive(__unused uint32_t instr)
382 {
383 	/* TODO will instrumenting these interfere with any kernel usage of these instructions? */
384 	/* Don't instrument for now */
385 
386 	return FASTTRAP_T_INV;
387 }
388 
389 static
390 int
arm_extra_loadstore_unpriv(uint32_t instr)391 arm_extra_loadstore_unpriv(uint32_t instr)
392 {
393 	int op = BITS(instr, 20, 0x1), __unused op2 = BITS(instr, 5, 0x3), immed = BITS(instr, 22, 0x1);
394 
395 	if (op == 0 && (op2 & 0x2) == 0x2) {
396 		/* Unpredictable or undefined */
397 		return FASTTRAP_T_INV;
398 	}
399 
400 	if (immed == 1) {
401 		if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
402 			return FASTTRAP_T_COMMON;
403 		}
404 	} else {
405 		if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
406 			return FASTTRAP_T_COMMON;
407 		}
408 	}
409 
410 	return FASTTRAP_T_INV;
411 }
412 
413 static
414 int
arm_extra_loadstore(uint32_t instr)415 arm_extra_loadstore(uint32_t instr)
416 {
417 	int op1 = BITS(instr, 20, 0x1F);
418 
419 	/* There are two variants, and we do not instrument either of them that use the PC */
420 
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;
425 		}
426 	} else {
427 		/* Variant 2, immediate */
428 		if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
429 			return FASTTRAP_T_COMMON;
430 		}
431 	}
432 
433 	return FASTTRAP_T_INV;
434 }
435 
436 static
437 int
arm_halfword_multiply(uint32_t instr)438 arm_halfword_multiply(uint32_t instr)
439 {
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.
442 	 */
443 
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;
446 	}
447 
448 	return FASTTRAP_T_INV;
449 }
450 
451 static
452 int
arm_multiply(uint32_t instr)453 arm_multiply(uint32_t instr)
454 {
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.
457 	 */
458 
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;
461 	}
462 
463 	return FASTTRAP_T_INV;
464 }
465 
466 static
467 int
arm_dataproc_immed(uint32_t instr)468 arm_dataproc_immed(uint32_t instr)
469 {
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;
473 	}
474 
475 	return FASTTRAP_T_INV;
476 }
477 
478 static
479 int
arm_dataproc_regshift(uint32_t instr)480 arm_dataproc_regshift(uint32_t instr)
481 {
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;
485 	}
486 
487 	return FASTTRAP_T_INV;
488 }
489 
490 static
491 int
arm_dataproc_reg(uint32_t instr)492 arm_dataproc_reg(uint32_t instr)
493 {
494 	int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 7, 0x1F), op3 = BITS(instr, 5, 0x3);
495 
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;
500 		}
501 
502 		return FASTTRAP_T_INV;
503 	}
504 
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.
508 	 */
509 	if (op1 == 0x1A && op2 == 0 && op3 == 0 && ARM_RD(instr) == REG_PC) {
510 		return FASTTRAP_T_MOV_PC_REG;
511 	}
512 
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;
516 	}
517 
518 	return FASTTRAP_T_INV;
519 }
520 
521 static
522 int
arm_dataproc_misc(uint32_t instr)523 arm_dataproc_misc(uint32_t instr)
524 {
525 	int op = BITS(instr, 25, 0x1), op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 4, 0xF);
526 
527 	if (op == 0) {
528 		if ((op1 & 0x19) != 0x10 && (op2 & 0x1) == 0) {
529 			return arm_dataproc_reg(instr);
530 		}
531 
532 		if ((op1 & 0x19) != 0x10 && (op2 & 0x9) == 0x1) {
533 			return arm_dataproc_regshift(instr);
534 		}
535 
536 		if ((op1 & 0x19) == 0x10 && (op2 & 0x8) == 0) {
537 			return arm_misc(instr);
538 		}
539 
540 		if ((op1 & 0x19) == 0x19 && (op2 & 0x9) == 0x8) {
541 			return arm_halfword_multiply(instr);
542 		}
543 
544 		if ((op1 & 0x10) == 0 && op2 == 0x9) {
545 			return arm_multiply(instr);
546 		}
547 
548 		if ((op1 & 0x10) == 0x10 && op2 == 0x9) {
549 			return arm_sync_primitive(instr);
550 		}
551 
552 		if ((op1 & 0x12) != 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
553 			return arm_extra_loadstore(instr);
554 		}
555 
556 		if ((op1 & 0x12) == 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
557 			return arm_extra_loadstore_unpriv(instr);
558 		}
559 	} else {
560 		if ((op1 & 0x19) != 0x10) {
561 			return arm_dataproc_immed(instr);
562 		}
563 
564 		if (op1 == 0x10) {
565 			/* 16 bit immediate load (mov (immed)) [encoding A2] */
566 			if (ARM_RD(instr) != REG_PC) {
567 				return FASTTRAP_T_COMMON;
568 			}
569 
570 			return FASTTRAP_T_INV;
571 		}
572 
573 		if (op1 == 0x14) {
574 			/* high halfword 16 bit immediate load (movt) [encoding A1] */
575 			if (ARM_RD(instr) != REG_PC) {
576 				return FASTTRAP_T_COMMON;
577 			}
578 
579 			return FASTTRAP_T_INV;
580 		}
581 
582 		if ((op1 & 0x1B) == 0x12) {
583 			return arm_msr_hints(instr);
584 		}
585 	}
586 
587 	return FASTTRAP_T_INV;
588 }
589 
590 int
dtrace_decode_arm(uint32_t instr)591 dtrace_decode_arm(uint32_t instr)
592 {
593 	int cond = BITS(instr, 28, 0xF), op1 = BITS(instr, 25, 0x7), op = BITS(instr, 4, 0x1);
594 
595 	if (cond == 0xF) {
596 		return arm_unconditional(instr);
597 	}
598 
599 	if ((op1 & 0x6) == 0) {
600 		return arm_dataproc_misc(instr);
601 	}
602 
603 	if (op1 == 0x2) {
604 		return arm_loadstore_wordbyte(instr);
605 	}
606 
607 	if (op1 == 0x3 && op == 0) {
608 		return arm_loadstore_wordbyte(instr);
609 	}
610 
611 	if (op1 == 0x3 && op == 1) {
612 		return arm_media(instr);
613 	}
614 
615 	if ((op1 & 0x6) == 0x4) {
616 		return arm_branch_link_blockdata(instr);
617 	}
618 
619 	if ((op1 & 0x6) == 0x6) {
620 		return arm_syscall_coproc(instr);
621 	}
622 
623 	return FASTTRAP_T_INV;
624 }
625 
626 
627 /*
628  * Thumb 16-bit decoder
629  */
630 
631 static
632 int
thumb16_cond_supervisor(uint16_t instr)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
thumb16_misc(uint16_t instr)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
thumb16_loadstore_single(__unused uint16_t instr)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
thumb16_data_special_and_branch(uint16_t instr)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
thumb16_data_proc(__unused uint16_t instr)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
thumb16_shift_addsub_move_compare(__unused uint16_t instr)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
dtrace_decode_thumb16(uint16_t instr)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
thumb32_coproc(uint16_t instr1,uint16_t instr2)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
thumb32_longmultiply(uint16_t instr1,uint16_t instr2)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
thumb32_multiply(uint16_t instr1,uint16_t instr2)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
thumb32_misc(uint16_t instr1,uint16_t instr2)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
thumb32_parallel_addsub_unsigned(uint16_t instr1,uint16_t instr2)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
thumb32_parallel_addsub_signed(uint16_t instr1,uint16_t instr2)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
thumb32_dataproc_reg(uint16_t instr1,uint16_t instr2)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
thumb32_dataproc_regshift(uint16_t instr1,uint16_t instr2)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
thumb32_store_single(uint16_t instr1,uint16_t instr2)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
thumb32_loadbyte_memhint(uint16_t instr1,uint16_t instr2)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
thumb32_loadhalfword_memhint(uint16_t instr1,uint16_t instr2)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
thumb32_loadword(uint16_t instr1,uint16_t instr2)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
thumb32_loadstore_double_exclusive_table(__unused uint16_t instr1,__unused uint16_t instr2)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
thumb32_loadstore_multiple(uint16_t instr1,uint16_t instr2)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
thumb32_misc_control(__unused uint16_t instr1,__unused uint16_t instr2)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
thumb32_cps_hints(__unused uint16_t instr1,__unused uint16_t instr2)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
thumb32_b_misc_control(uint16_t instr1,uint16_t instr2)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
thumb32_dataproc_plain_immed(uint16_t instr1,uint16_t instr2)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
thumb32_dataproc_mod_immed(uint16_t instr1,uint16_t instr2)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
dtrace_decode_thumb32(uint16_t instr1,uint16_t instr2)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
dtrace_decode_thumb(uint32_t instr)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