]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/arm/disassembler.c
xnu-6153.61.1.tar.gz
[apple/xnu.git] / bsd / dev / arm / disassembler.c
CommitLineData
5ba3f43e
A
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
0a7de745 15#define BITS(x, n, mask) (((x) >> (n)) & (mask))
5ba3f43e 16
0a7de745
A
17static uint32_t
18thumb32_instword_to_arm(uint16_t hw1, uint16_t hw2)
5ba3f43e
A
19{
20 return (hw1 << 16) | hw2;
21}
22
23int dtrace_decode_arm(uint32_t instr);
24int dtrace_decode_thumb(uint32_t instr);
25
26/*
27 * VFP decoder - shared between ARM and THUMB32 mode
28 */
29
30static
0a7de745
A
31int
32vfp_struct_loadstore(uint32_t instr)
5ba3f43e 33{
0a7de745 34 if (ARM_RM(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 35 return FASTTRAP_T_COMMON;
0a7de745 36 }
5ba3f43e
A
37
38 return FASTTRAP_T_INV;
39}
40
41static
0a7de745
A
42int
43vfp_64transfer(uint32_t instr)
5ba3f43e
A
44{
45 /* These instructions all use RD and RN */
0a7de745 46 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 47 return FASTTRAP_T_COMMON;
0a7de745 48 }
5ba3f43e
A
49
50 return FASTTRAP_T_INV;
51}
52
53static
0a7de745
A
54int
55vfp_transfer(uint32_t instr)
5ba3f43e
A
56{
57 /* These instructions all use RD only */
0a7de745 58 if (ARM_RD(instr) != REG_PC) {
5ba3f43e 59 return FASTTRAP_T_COMMON;
0a7de745 60 }
5ba3f43e
A
61
62 return FASTTRAP_T_INV;
63}
64
65static
0a7de745
A
66int
67vfp_loadstore(uint32_t instr)
5ba3f43e 68{
0a7de745 69 int opcode = BITS(instr, 20, 0x1F);
5ba3f43e
A
70
71 /* Instrument VLDR */
0a7de745 72 if ((opcode & 0x13) == 0x11 && ARM_RN(instr) == REG_PC) {
5ba3f43e 73 return FASTTRAP_T_VLDR_PC_IMMED;
0a7de745
A
74 }
75
5ba3f43e 76 /* These instructions all use RN only */
0a7de745 77 if (ARM_RN(instr) != REG_PC) {
5ba3f43e 78 return FASTTRAP_T_COMMON;
0a7de745 79 }
5ba3f43e
A
80
81 return FASTTRAP_T_INV;
82}
83
84/*
85 * ARM decoder
86 */
87
88static
0a7de745
A
89int
90arm_unconditional_misc(uint32_t instr)
5ba3f43e 91{
0a7de745 92 int op = BITS(instr, 20, 0x7F);
5ba3f43e
A
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
106static
0a7de745
A
107int
108arm_unconditional(uint32_t instr)
5ba3f43e 109{
0a7de745 110 if (BITS(instr, 27, 0x1) == 0) {
5ba3f43e 111 return arm_unconditional_misc(instr);
0a7de745 112 }
5ba3f43e
A
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
121static
0a7de745
A
122int
123arm_syscall_coproc(uint32_t instr)
5ba3f43e
A
124{
125 /* Instrument any VFP data processing instructions, ignore the rest */
126
0a7de745 127 int op1 = BITS(instr, 20, 0x3F), coproc = BITS(instr, 8, 0xF), op = BITS(instr, 4, 0x1);
5ba3f43e
A
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
0a7de745 137 if ((op1 & 0x20) == 0 && (op1 & 0x3A) != 0) {
5ba3f43e 138 return vfp_loadstore(instr);
0a7de745 139 }
5ba3f43e 140
0a7de745 141 if ((op1 & 0x3E) == 0x04) {
5ba3f43e 142 return vfp_64transfer(instr);
0a7de745 143 }
5ba3f43e
A
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
159static
0a7de745
A
160int
161arm_branch_link_blockdata(uint32_t instr)
5ba3f43e 162{
0a7de745 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);
5ba3f43e
A
164
165 if (branch == 1) {
0a7de745 166 if (link == 0) {
5ba3f43e 167 return FASTTRAP_T_B_COND;
0a7de745 168 }
5ba3f43e
A
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 } */
0a7de745 172 if (op == 0x0B && ARM_RN(instr) == REG_SP && uses_pc == 1) {
5ba3f43e 173 return FASTTRAP_T_LDM_PC;
0a7de745 174 }
5ba3f43e
A
175
176 /* stmia sp!, { ... lr } doesn't touch the pc, but it is very common, so special case it */
0a7de745 177 if (op == 0x12 && ARM_RN(instr) == REG_SP && uses_lr == 1) {
5ba3f43e 178 return FASTTRAP_T_STM_LR;
0a7de745 179 }
5ba3f43e 180
0a7de745 181 if (ARM_RN(instr) != REG_PC && uses_pc == 0) {
5ba3f43e 182 return FASTTRAP_T_COMMON;
0a7de745 183 }
5ba3f43e
A
184 }
185
186 return FASTTRAP_T_INV;
187}
188
189static
0a7de745
A
190int
191arm_signed_multiplies(uint32_t instr)
5ba3f43e 192{
0a7de745 193 int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
5ba3f43e
A
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)) {
0a7de745 197 if (ARM_RD(instr) == REG_PC) {
5ba3f43e 198 return FASTTRAP_T_INV;
0a7de745 199 }
5ba3f43e
A
200 }
201
0a7de745 202 if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 203 return FASTTRAP_T_COMMON;
0a7de745 204 }
5ba3f43e
A
205
206 return FASTTRAP_T_INV;
207}
208
209static
0a7de745
A
210int
211arm_pack_unpack_sat_reversal(uint32_t instr)
5ba3f43e 212{
0a7de745 213 int op1 = BITS(instr, 20, 0x7), op2 = BITS(instr, 5, 0x7);
5ba3f43e
A
214
215 /* pkh, sel use RN in addition to RD and RM */
216 if ((op1 == 0 && (op2 & 0x1) == 0) || (op1 == 0 && op2 == 0x5)) {
0a7de745 217 if (ARM_RN(instr) == REG_PC) {
5ba3f43e 218 return FASTTRAP_T_INV;
0a7de745 219 }
5ba3f43e
A
220 }
221
0a7de745 222 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
5ba3f43e 223 return FASTTRAP_T_COMMON;
0a7de745 224 }
5ba3f43e
A
225
226 return FASTTRAP_T_INV;
227}
228
229static
0a7de745
A
230int
231arm_parallel_addsub_unsigned(uint32_t instr)
5ba3f43e 232{
0a7de745 233 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 234 return FASTTRAP_T_COMMON;
0a7de745 235 }
5ba3f43e
A
236
237 return FASTTRAP_T_INV;
238}
239
240static
0a7de745
A
241int
242arm_parallel_addsub_signed(uint32_t instr)
5ba3f43e 243{
0a7de745 244 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 245 return FASTTRAP_T_COMMON;
0a7de745 246 }
5ba3f43e
A
247
248 return FASTTRAP_T_INV;
249}
250
251static
0a7de745
A
252int
253arm_media(uint32_t instr)
5ba3f43e 254{
0a7de745 255 int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 5, 0x7);
5ba3f43e 256
0a7de745 257 if ((op1 & 0x1C) == 0) {
5ba3f43e 258 return arm_parallel_addsub_signed(instr);
0a7de745 259 }
5ba3f43e 260
0a7de745 261 if ((op1 & 0x1C) == 0x04) {
5ba3f43e 262 return arm_parallel_addsub_unsigned(instr);
0a7de745 263 }
5ba3f43e 264
0a7de745 265 if ((op1 & 0x18) == 0x08) {
5ba3f43e 266 return arm_pack_unpack_sat_reversal(instr);
0a7de745 267 }
5ba3f43e 268
0a7de745 269 if ((op1 & 0x18) == 0x10) {
5ba3f43e 270 return arm_signed_multiplies(instr);
0a7de745 271 }
5ba3f43e
A
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
0a7de745 283 if (ARM_RM(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 284 return FASTTRAP_T_COMMON;
0a7de745 285 }
5ba3f43e
A
286
287 return FASTTRAP_T_INV;
288 }
289
290 if ((op1 & 0x1E) == 0x1C && (op2 & 0x3) == 0) {
291 /* bfc bfi */
0a7de745 292 if (ARM_RD(instr) != REG_PC) {
5ba3f43e 293 return FASTTRAP_T_COMMON;
0a7de745 294 }
5ba3f43e
A
295
296 return FASTTRAP_T_INV;
297 }
298
299 if (((op1 & 0x1E) == 0x1A || (op1 & 0x1E) == 0x1E) && ((op2 & 0x3) == 0x2)) {
300 /* sbfx ubfx */
0a7de745 301 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
5ba3f43e 302 return FASTTRAP_T_COMMON;
0a7de745 303 }
5ba3f43e
A
304
305 return FASTTRAP_T_INV;
306 }
307
308 return FASTTRAP_T_INV;
309}
310
311static
0a7de745
A
312int
313arm_loadstore_wordbyte(uint32_t instr)
5ba3f43e
A
314{
315 /* Instrument PC relative load with immediate, ignore any other uses of the PC */
0a7de745 316 int R = BITS(instr, 25, 0x1), L = BITS(instr, 20, 0x1);
5ba3f43e
A
317
318 if (R == 1) {
319 /* Three register load/store */
0a7de745 320 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 321 return FASTTRAP_T_COMMON;
0a7de745 322 }
5ba3f43e
A
323 } else {
324 /* Immediate load/store, but still do not support ldr pc, [pc...] */
0a7de745 325 if (L == 1 && ARM_RN(instr) == REG_PC && ARM_RD(instr) != REG_PC) {
5ba3f43e 326 return FASTTRAP_T_LDR_PC_IMMED;
0a7de745 327 }
5ba3f43e 328
0a7de745 329 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 330 return FASTTRAP_T_COMMON;
0a7de745 331 }
5ba3f43e
A
332 }
333
334 return FASTTRAP_T_INV;
335}
336
337static
0a7de745
A
338int
339arm_saturating(uint32_t instr)
5ba3f43e 340{
0a7de745 341 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 342 return FASTTRAP_T_COMMON;
0a7de745 343 }
5ba3f43e
A
344
345 return FASTTRAP_T_INV;
346}
347
348static
0a7de745
A
349int
350arm_misc(uint32_t instr)
5ba3f43e 351{
0a7de745 352 int op = BITS(instr, 21, 0x3), __unused op1 = BITS(instr, 16, 0xF), op2 = BITS(instr, 4, 0x7);
5ba3f43e 353
0a7de745 354 if (op2 == 1 && op == 1) {
5ba3f43e 355 return FASTTRAP_T_BX_REG;
0a7de745 356 }
5ba3f43e
A
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
0a7de745 363 if (op2 == 0x5) {
5ba3f43e 364 return arm_saturating(instr);
0a7de745 365 }
5ba3f43e
A
366
367 return FASTTRAP_T_INV;
368}
369
370static
0a7de745
A
371int
372arm_msr_hints(__unused uint32_t instr)
5ba3f43e
A
373{
374 /* These deal with the psr, not instrumented */
375
376 return FASTTRAP_T_INV;
377}
378
379static
0a7de745
A
380int
381arm_sync_primitive(__unused uint32_t instr)
5ba3f43e
A
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
389static
0a7de745
A
390int
391arm_extra_loadstore_unpriv(uint32_t instr)
5ba3f43e 392{
0a7de745 393 int op = BITS(instr, 20, 0x1), __unused op2 = BITS(instr, 5, 0x3), immed = BITS(instr, 22, 0x1);
5ba3f43e
A
394
395 if (op == 0 && (op2 & 0x2) == 0x2) {
396 /* Unpredictable or undefined */
397 return FASTTRAP_T_INV;
398 }
399
400 if (immed == 1) {
0a7de745 401 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 402 return FASTTRAP_T_COMMON;
0a7de745 403 }
5ba3f43e 404 } else {
0a7de745 405 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 406 return FASTTRAP_T_COMMON;
0a7de745 407 }
5ba3f43e 408 }
0a7de745 409
5ba3f43e
A
410 return FASTTRAP_T_INV;
411}
412
413static
0a7de745
A
414int
415arm_extra_loadstore(uint32_t instr)
5ba3f43e 416{
0a7de745 417 int op1 = BITS(instr, 20, 0x1F);
5ba3f43e
A
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 */
0a7de745 423 if (ARM_RM(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 424 return FASTTRAP_T_COMMON;
0a7de745 425 }
5ba3f43e
A
426 } else {
427 /* Variant 2, immediate */
0a7de745 428 if (ARM_RD(instr) != REG_PC && ARM_RN(instr) != REG_PC) {
5ba3f43e 429 return FASTTRAP_T_COMMON;
0a7de745 430 }
5ba3f43e
A
431 }
432
433 return FASTTRAP_T_INV;
434}
435
436static
0a7de745
A
437int
438arm_halfword_multiply(uint32_t instr)
5ba3f43e
A
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
0a7de745 444 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
5ba3f43e 445 return FASTTRAP_T_COMMON;
0a7de745 446 }
5ba3f43e
A
447
448 return FASTTRAP_T_INV;
449}
450
451static
0a7de745
A
452int
453arm_multiply(uint32_t instr)
5ba3f43e
A
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
0a7de745 459 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
5ba3f43e 460 return FASTTRAP_T_COMMON;
0a7de745 461 }
5ba3f43e
A
462
463 return FASTTRAP_T_INV;
464}
465
466static
0a7de745
A
467int
468arm_dataproc_immed(uint32_t instr)
5ba3f43e
A
469{
470 /* All these instructions are either two registers, or one register and have 0 where the other reg would be used */
0a7de745 471 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC) {
5ba3f43e 472 return FASTTRAP_T_COMMON;
0a7de745 473 }
5ba3f43e
A
474
475 return FASTTRAP_T_INV;
476}
477
478static
0a7de745
A
479int
480arm_dataproc_regshift(uint32_t instr)
5ba3f43e
A
481{
482 /* All these instructions are either four registers, or three registers and have 0 where there last reg would be used */
0a7de745 483 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RS(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
5ba3f43e 484 return FASTTRAP_T_COMMON;
0a7de745 485 }
5ba3f43e
A
486
487 return FASTTRAP_T_INV;
488}
489
490static
0a7de745
A
491int
492arm_dataproc_reg(uint32_t instr)
5ba3f43e 493{
0a7de745 494 int op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 7, 0x1F), op3 = BITS(instr, 5, 0x3);
5ba3f43e
A
495
496 if (op1 == 0x11 || op1 == 0x13 || op1 == 0x15 || op1 == 0x17) {
497 /* These are comparison flag setting instructions and do not have RD */
0a7de745 498 if (ARM_RN(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
5ba3f43e 499 return FASTTRAP_T_COMMON;
0a7de745 500 }
5ba3f43e
A
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 */
0a7de745 509 if (op1 == 0x1A && op2 == 0 && op3 == 0 && ARM_RD(instr) == REG_PC) {
5ba3f43e 510 return FASTTRAP_T_MOV_PC_REG;
0a7de745 511 }
5ba3f43e
A
512
513 /* Any instruction at this point is a three register instruction or two register instruction with RN = 0 */
0a7de745 514 if (ARM_RN(instr) != REG_PC && ARM_RD(instr) != REG_PC && ARM_RM(instr) != REG_PC) {
5ba3f43e 515 return FASTTRAP_T_COMMON;
0a7de745 516 }
5ba3f43e
A
517
518 return FASTTRAP_T_INV;
519}
520
521static
0a7de745
A
522int
523arm_dataproc_misc(uint32_t instr)
5ba3f43e 524{
0a7de745 525 int op = BITS(instr, 25, 0x1), op1 = BITS(instr, 20, 0x1F), op2 = BITS(instr, 4, 0xF);
5ba3f43e
A
526
527 if (op == 0) {
0a7de745 528 if ((op1 & 0x19) != 0x10 && (op2 & 0x1) == 0) {
5ba3f43e 529 return arm_dataproc_reg(instr);
0a7de745 530 }
5ba3f43e 531
0a7de745 532 if ((op1 & 0x19) != 0x10 && (op2 & 0x9) == 0x1) {
5ba3f43e 533 return arm_dataproc_regshift(instr);
0a7de745 534 }
5ba3f43e 535
0a7de745 536 if ((op1 & 0x19) == 0x10 && (op2 & 0x8) == 0) {
5ba3f43e 537 return arm_misc(instr);
0a7de745 538 }
5ba3f43e 539
0a7de745 540 if ((op1 & 0x19) == 0x19 && (op2 & 0x9) == 0x8) {
5ba3f43e 541 return arm_halfword_multiply(instr);
0a7de745 542 }
5ba3f43e 543
0a7de745 544 if ((op1 & 0x10) == 0 && op2 == 0x9) {
5ba3f43e 545 return arm_multiply(instr);
0a7de745 546 }
5ba3f43e 547
0a7de745 548 if ((op1 & 0x10) == 0x10 && op2 == 0x9) {
5ba3f43e 549 return arm_sync_primitive(instr);
0a7de745 550 }
5ba3f43e 551
0a7de745 552 if ((op1 & 0x12) != 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
5ba3f43e 553 return arm_extra_loadstore(instr);
0a7de745 554 }
5ba3f43e 555
0a7de745 556 if ((op1 & 0x12) == 0x02 && (op2 == 0xB || (op2 & 0xD) == 0xD)) {
5ba3f43e 557 return arm_extra_loadstore_unpriv(instr);
0a7de745 558 }
5ba3f43e 559 } else {
0a7de745 560 if ((op1 & 0x19) != 0x10) {
5ba3f43e 561 return arm_dataproc_immed(instr);
0a7de745 562 }
5ba3f43e
A
563
564 if (op1 == 0x10) {
565 /* 16 bit immediate load (mov (immed)) [encoding A2] */
0a7de745 566 if (ARM_RD(instr) != REG_PC) {
5ba3f43e 567 return FASTTRAP_T_COMMON;
0a7de745 568 }
5ba3f43e
A
569
570 return FASTTRAP_T_INV;
571 }
572
573 if (op1 == 0x14) {
574 /* high halfword 16 bit immediate load (movt) [encoding A1] */
0a7de745 575 if (ARM_RD(instr) != REG_PC) {
5ba3f43e 576 return FASTTRAP_T_COMMON;
0a7de745 577 }
5ba3f43e
A
578
579 return FASTTRAP_T_INV;
580 }
581
0a7de745 582 if ((op1 & 0x1B) == 0x12) {
5ba3f43e 583 return arm_msr_hints(instr);
0a7de745 584 }
5ba3f43e
A
585 }
586
587 return FASTTRAP_T_INV;
588}
589
0a7de745
A
590int
591dtrace_decode_arm(uint32_t instr)
5ba3f43e 592{
0a7de745 593 int cond = BITS(instr, 28, 0xF), op1 = BITS(instr, 25, 0x7), op = BITS(instr, 4, 0x1);
5ba3f43e 594
0a7de745 595 if (cond == 0xF) {
5ba3f43e 596 return arm_unconditional(instr);
0a7de745 597 }
5ba3f43e 598
0a7de745 599 if ((op1 & 0x6) == 0) {
5ba3f43e 600 return arm_dataproc_misc(instr);
0a7de745 601 }
5ba3f43e 602
0a7de745 603 if (op1 == 0x2) {
5ba3f43e 604 return arm_loadstore_wordbyte(instr);
0a7de745 605 }
5ba3f43e 606
0a7de745 607 if (op1 == 0x3 && op == 0) {
5ba3f43e 608 return arm_loadstore_wordbyte(instr);
0a7de745 609 }
5ba3f43e 610
0a7de745 611 if (op1 == 0x3 && op == 1) {
5ba3f43e 612 return arm_media(instr);
0a7de745 613 }
5ba3f43e 614
0a7de745 615 if ((op1 & 0x6) == 0x4) {
5ba3f43e 616 return arm_branch_link_blockdata(instr);
0a7de745 617 }
5ba3f43e 618
0a7de745 619 if ((op1 & 0x6) == 0x6) {
5ba3f43e 620 return arm_syscall_coproc(instr);
0a7de745 621 }
5ba3f43e
A
622
623 return FASTTRAP_T_INV;
624}
625
626
627/*
628 * Thumb 16-bit decoder
629 */
630
631static
0a7de745
A
632int
633thumb16_cond_supervisor(uint16_t instr)
5ba3f43e 634{
0a7de745 635 int opcode = BITS(instr, 8, 0xF);
5ba3f43e 636
0a7de745 637 if ((opcode & 0xE) != 0xE) {
5ba3f43e 638 return FASTTRAP_T_B_COND;
0a7de745 639 }
5ba3f43e
A
640
641 return FASTTRAP_T_INV;
642}
643
644static
0a7de745
A
645int
646thumb16_misc(uint16_t instr)
5ba3f43e 647{
0a7de745 648 int opcode = BITS(instr, 5, 0x7F);
5ba3f43e
A
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
666static
0a7de745
A
667int
668thumb16_loadstore_single(__unused uint16_t instr)
5ba3f43e
A
669{
670 /* These all access the low registers or SP only */
671 return FASTTRAP_T_COMMON;
672}
673
674static
0a7de745
A
675int
676thumb16_data_special_and_branch(uint16_t instr)
5ba3f43e 677{
0a7de745 678 int opcode = BITS(instr, 6, 0xF);
5ba3f43e
A
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 */
0a7de745 686 if ((opcode & 0x2) == 0) {
5ba3f43e 687 return FASTTRAP_T_BX_REG;
0a7de745 688 }
5ba3f43e
A
689 return FASTTRAP_T_INV;
690 } else {
691 /* Data processing on high registers, only instrument mov pc, reg */
0a7de745 692 if ((opcode & 0xC) == 0x8 && THUMB16_HRD(instr) == REG_PC) {
5ba3f43e 693 return FASTTRAP_T_CPY_PC;
0a7de745 694 }
5ba3f43e 695
0a7de745 696 if (THUMB16_HRM(instr) != REG_PC && THUMB16_HRD(instr) != REG_PC) {
5ba3f43e 697 return FASTTRAP_T_COMMON;
0a7de745 698 }
5ba3f43e
A
699 }
700
701 return FASTTRAP_T_INV;
702}
703
704static
0a7de745
A
705int
706thumb16_data_proc(__unused uint16_t instr)
5ba3f43e
A
707{
708 /* These all access the low registers only */
709 return FASTTRAP_T_COMMON;
710}
711
712static
0a7de745
A
713int
714thumb16_shift_addsub_move_compare(__unused uint16_t instr)
5ba3f43e
A
715{
716 /* These all access the low registers only */
717 return FASTTRAP_T_COMMON;
718}
719
720static
0a7de745
A
721int
722dtrace_decode_thumb16(uint16_t instr)
5ba3f43e 723{
0a7de745 724 int opcode = BITS(instr, 10, 0x3F);
5ba3f43e 725
0a7de745 726 if ((opcode & 0x30) == 0) {
5ba3f43e 727 return thumb16_shift_addsub_move_compare(instr);
0a7de745 728 }
5ba3f43e 729
0a7de745 730 if (opcode == 0x10) {
5ba3f43e 731 return thumb16_data_proc(instr);
0a7de745 732 }
5ba3f43e 733
0a7de745 734 if (opcode == 0x11) {
5ba3f43e 735 return thumb16_data_special_and_branch(instr);
0a7de745 736 }
5ba3f43e
A
737
738 if ((opcode & 0x3E) == 0x12) {
739 /* ldr (literal) */
740 return FASTTRAP_T_LDR_PC_IMMED;
741 }
742
0a7de745 743 if ((opcode & 0x3C) == 0x14 || (opcode & 0x38) == 0x18 || (opcode & 0x38) == 0x20) {
5ba3f43e 744 return thumb16_loadstore_single(instr);
0a7de745 745 }
5ba3f43e
A
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
0a7de745 757 if ((opcode & 0x3C) == 0x2C) {
5ba3f43e 758 return thumb16_misc(instr);
0a7de745 759 }
5ba3f43e
A
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
787static
0a7de745
A
788int
789thumb32_coproc(uint16_t instr1, uint16_t instr2)
5ba3f43e
A
790{
791 /* Instrument any VFP data processing instructions, ignore the rest */
792
0a7de745 793 int op1 = BITS(instr1, 4, 0x3F), coproc = BITS(instr2, 8, 0xF), op = BITS(instr2, 4, 0x1);
5ba3f43e
A
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 */
0a7de745 802 uint32_t instr = thumb32_instword_to_arm(instr1, instr2);
5ba3f43e
A
803
804 if ((op1 & 0x30) == 0x30) {
805 /* VFP data processing uses its own registers */
806 return FASTTRAP_T_COMMON;
807 }
808
0a7de745 809 if ((op1 & 0x3A) == 0x02 || (op1 & 0x38) == 0x08 || (op1 & 0x30) == 0x10) {
5ba3f43e 810 return vfp_loadstore(instr);
0a7de745 811 }
5ba3f43e 812
0a7de745 813 if ((op1 & 0x3E) == 0x04) {
5ba3f43e 814 return vfp_64transfer(instr);
0a7de745 815 }
5ba3f43e
A
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
831static
0a7de745
A
832int
833thumb32_longmultiply(uint16_t instr1, uint16_t instr2)
5ba3f43e 834{
0a7de745 835 int op1 = BITS(instr1, 4, 0x7), op2 = BITS(instr2, 4, 0xF);
5ba3f43e
A
836
837 if ((op1 == 1 && op2 == 0xF) || (op1 == 0x3 && op2 == 0xF)) {
838 /* Three register instruction */
0a7de745 839 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 840 return FASTTRAP_T_COMMON;
0a7de745 841 }
5ba3f43e
A
842 } else {
843 /* Four register instruction */
0a7de745
A
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) {
5ba3f43e 846 return FASTTRAP_T_COMMON;
0a7de745 847 }
5ba3f43e
A
848 }
849
850 return FASTTRAP_T_INV;
851}
852
853static
0a7de745
A
854int
855thumb32_multiply(uint16_t instr1, uint16_t instr2)
5ba3f43e 856{
0a7de745 857 int op1 = BITS(instr1, 4, 0x7), op2 = BITS(instr2, 4, 0x3);
5ba3f43e
A
858
859 if ((op1 == 0 && op2 == 1) || (op1 == 0x6 && (op2 & 0x2) == 0)) {
0a7de745 860 if (THUMB32_RT(instr1, instr2) == REG_PC) {
5ba3f43e 861 return FASTTRAP_T_INV;
0a7de745 862 }
5ba3f43e
A
863 }
864
0a7de745 865 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 866 return FASTTRAP_T_COMMON;
0a7de745 867 }
5ba3f43e
A
868
869 return FASTTRAP_T_INV;
870}
871
872static
0a7de745
A
873int
874thumb32_misc(uint16_t instr1, uint16_t instr2)
5ba3f43e 875{
0a7de745 876 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 877 return FASTTRAP_T_COMMON;
0a7de745 878 }
5ba3f43e
A
879
880 return FASTTRAP_T_INV;
881}
882
883static
0a7de745
A
884int
885thumb32_parallel_addsub_unsigned(uint16_t instr1, uint16_t instr2)
5ba3f43e 886{
0a7de745 887 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 888 return FASTTRAP_T_COMMON;
0a7de745 889 }
5ba3f43e
A
890
891 return FASTTRAP_T_INV;
892}
893
894static
0a7de745
A
895int
896thumb32_parallel_addsub_signed(uint16_t instr1, uint16_t instr2)
5ba3f43e 897{
0a7de745 898 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 899 return FASTTRAP_T_COMMON;
0a7de745 900 }
5ba3f43e
A
901
902 return FASTTRAP_T_INV;
903}
904
905static
0a7de745
A
906int
907thumb32_dataproc_reg(uint16_t instr1, uint16_t instr2)
5ba3f43e 908{
0a7de745 909 int op1 = BITS(instr1, 4, 0xF), op2 = BITS(instr2, 4, 0xF);
5ba3f43e
A
910
911 if (((0 <= op1) && (op1 <= 5)) && (op2 & 0x8) == 0x8) {
0a7de745 912 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC) {
5ba3f43e 913 return FASTTRAP_T_COMMON;
0a7de745 914 }
5ba3f43e
A
915 }
916
917 if ((op1 & 0x8) == 0 && op2 == 0) {
0a7de745 918 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 919 return FASTTRAP_T_COMMON;
0a7de745 920 }
5ba3f43e
A
921 }
922
0a7de745
A
923 if ((op1 & 0x8) == 0x8 && (op2 & 0xC) == 0) {
924 return thumb32_parallel_addsub_signed(instr1, instr2);
925 }
5ba3f43e 926
0a7de745
A
927 if ((op1 & 0x8) == 0x8 && (op2 & 0xC) == 0x4) {
928 return thumb32_parallel_addsub_unsigned(instr1, instr2);
929 }
5ba3f43e 930
0a7de745
A
931 if ((op1 & 0xC) == 0x8 && (op2 & 0xC) == 0x8) {
932 return thumb32_misc(instr1, instr2);
933 }
5ba3f43e
A
934
935 return FASTTRAP_T_INV;
936}
937
938static
0a7de745
A
939int
940thumb32_dataproc_regshift(uint16_t instr1, uint16_t instr2)
5ba3f43e 941{
0a7de745 942 int op = BITS(instr1, 5, 0xF), S = BITS(instr1, 4, 0x1);
5ba3f43e
A
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) {
0a7de745 947 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 948 return FASTTRAP_T_COMMON;
0a7de745 949 }
5ba3f43e 950 } else {
0a7de745
A
951 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC &&
952 THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 953 return FASTTRAP_T_COMMON;
0a7de745 954 }
5ba3f43e
A
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 */
0a7de745 958 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC) {
5ba3f43e 959 return FASTTRAP_T_COMMON;
0a7de745 960 }
5ba3f43e
A
961 } else {
962 /* Normal three register instruction */
0a7de745 963 if (THUMB32_RM(instr1, instr2) != REG_PC && THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 964 return FASTTRAP_T_COMMON;
0a7de745 965 }
5ba3f43e
A
966 }
967
968 return FASTTRAP_T_INV;
969}
970
971static
0a7de745
A
972int
973thumb32_store_single(uint16_t instr1, uint16_t instr2)
5ba3f43e 974{
0a7de745 975 int op1 = BITS(instr1, 5, 0x7), op2 = BITS(instr2, 6, 0x3F);
5ba3f43e
A
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 */
0a7de745 980 if (THUMB32_RM(instr1, instr2) == REG_PC) {
5ba3f43e 981 return FASTTRAP_T_INV;
0a7de745 982 }
5ba3f43e
A
983 }
984
0a7de745 985 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 986 return FASTTRAP_T_COMMON;
0a7de745 987 }
5ba3f43e
A
988
989 return FASTTRAP_T_INV;
990}
991
992static
0a7de745
A
993int
994thumb32_loadbyte_memhint(uint16_t instr1, uint16_t instr2)
5ba3f43e 995{
0a7de745 996 int op1 = BITS(instr1, 7, 0x3), __unused op2 = BITS(instr2, 6, 0x3F);
5ba3f43e
A
997
998 /* Do not support any use of the pc yet */
0a7de745 999 if ((op1 == 0 || op1 == 0x2) && THUMB32_RM(instr1, instr2) == REG_PC) {
5ba3f43e 1000 return FASTTRAP_T_INV;
0a7de745 1001 }
5ba3f43e 1002
0a7de745 1003 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 1004 return FASTTRAP_T_COMMON;
0a7de745 1005 }
5ba3f43e
A
1006
1007 return FASTTRAP_T_INV;
1008}
1009
1010static
0a7de745
A
1011int
1012thumb32_loadhalfword_memhint(uint16_t instr1, uint16_t instr2)
5ba3f43e 1013{
0a7de745 1014 int op1 = BITS(instr1, 7, 0x3), op2 = BITS(instr2, 6, 0x3F);
5ba3f43e
A
1015
1016 /* Do not support any use of the PC yet */
0a7de745 1017 if (op1 == 0 && op2 == 0 && THUMB32_RM(inst1, instr2) == REG_PC) {
5ba3f43e 1018 return FASTTRAP_T_INV;
0a7de745 1019 }
5ba3f43e 1020
0a7de745 1021 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 1022 return FASTTRAP_T_COMMON;
0a7de745 1023 }
5ba3f43e
A
1024
1025 return FASTTRAP_T_INV;
1026}
1027
1028static
0a7de745
A
1029int
1030thumb32_loadword(uint16_t instr1, uint16_t instr2)
5ba3f43e 1031{
0a7de745 1032 int op1 = BITS(instr1, 7, 0x3), op2 = BITS(instr2, 6, 0x3F);
5ba3f43e 1033
0a7de745 1034 if ((op1 & 0x2) == 0 && THUMB32_RN(instr1, instr2) == REG_PC && THUMB32_RT(instr1, instr2) != REG_PC) {
5ba3f43e 1035 return FASTTRAP_T_LDR_PC_IMMED;
0a7de745 1036 }
5ba3f43e
A
1037
1038 if (op1 == 0 && op2 == 0) {
1039 /* ldr (register) uses an additional reg */
0a7de745 1040 if (THUMB32_RM(instr1, instr2) == REG_PC) {
5ba3f43e 1041 return FASTTRAP_T_INV;
0a7de745 1042 }
5ba3f43e
A
1043 }
1044
0a7de745 1045 if (THUMB32_RT(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 1046 return FASTTRAP_T_COMMON;
0a7de745 1047 }
5ba3f43e
A
1048
1049 return FASTTRAP_T_INV;
1050}
1051
1052static
0a7de745
A
1053int
1054thumb32_loadstore_double_exclusive_table(__unused uint16_t instr1, __unused uint16_t instr2)
5ba3f43e
A
1055{
1056 /* Don't instrument any of these */
1057
1058 return FASTTRAP_T_INV;
1059}
1060
1061static
0a7de745
A
1062int
1063thumb32_loadstore_multiple(uint16_t instr1, uint16_t instr2)
5ba3f43e 1064{
0a7de745 1065 int op = BITS(instr1, 7, 0x3), L = BITS(instr1, 4, 0x1), uses_pc = BITS(instr2, 15, 0x1), uses_lr = BITS(instr2, 14, 0x1);
5ba3f43e
A
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 } */
0a7de745 1073 if (op == 0x1 && L == 1 && THUMB32_RN(instr1, instr2) == REG_SP && uses_pc == 1) {
5ba3f43e 1074 return FASTTRAP_T_LDM_PC;
0a7de745 1075 }
5ba3f43e
A
1076
1077 /* stmia sp!, { ... lr }, aka push { ... lr } doesn't touch the pc, but it is very common, so special case it */
0a7de745 1078 if (op == 0x2 && L == 0 && THUMB32_RN(instr1, instr2) == REG_SP && uses_lr == 1) {
5ba3f43e 1079 return FASTTRAP_T_STM_LR;
0a7de745 1080 }
5ba3f43e 1081
0a7de745 1082 if (THUMB32_RN(instr1, instr2) != REG_PC && uses_pc == 0) {
5ba3f43e 1083 return FASTTRAP_T_COMMON;
0a7de745 1084 }
5ba3f43e
A
1085
1086 return FASTTRAP_T_INV;
1087}
1088
1089static
0a7de745
A
1090int
1091thumb32_misc_control(__unused uint16_t instr1, __unused uint16_t instr2)
5ba3f43e
A
1092{
1093 /* Privileged, and instructions dealing with ThumbEE */
1094 return FASTTRAP_T_INV;
1095}
1096
1097static
0a7de745
A
1098int
1099thumb32_cps_hints(__unused uint16_t instr1, __unused uint16_t instr2)
5ba3f43e
A
1100{
1101 /* Privileged */
1102 return FASTTRAP_T_INV;
1103}
1104
1105static
0a7de745
A
1106int
1107thumb32_b_misc_control(uint16_t instr1, uint16_t instr2)
5ba3f43e 1108{
0a7de745 1109 int op = BITS(instr1, 4, 0x7F), op1 = BITS(instr2, 12, 0x7), __unused op2 = BITS(instr2, 8, 0xF);
5ba3f43e
A
1110
1111 if ((op1 & 0x5) == 0) {
0a7de745 1112 if ((op & 0x38) != 0x38) {
5ba3f43e 1113 return FASTTRAP_T_B_COND;
0a7de745 1114 }
5ba3f43e 1115
0a7de745
A
1116 if (op == 0x3A) {
1117 return thumb32_cps_hints(instr1, instr2);
1118 }
5ba3f43e 1119
0a7de745
A
1120 if (op == 0x3B) {
1121 return thumb32_misc_control(instr1, instr2);
1122 }
5ba3f43e
A
1123 }
1124
0a7de745 1125 if ((op1 & 0x5) == 1) {
5ba3f43e 1126 return FASTTRAP_T_B_UNCOND;
0a7de745 1127 }
5ba3f43e
A
1128
1129 return FASTTRAP_T_INV;
1130}
1131
1132static
0a7de745
A
1133int
1134thumb32_dataproc_plain_immed(uint16_t instr1, uint16_t instr2)
5ba3f43e 1135{
0a7de745 1136 int op = BITS(instr1, 4, 0x1F);
5ba3f43e
A
1137
1138 if (op == 0x04 || op == 0x0C || op == 0x16) {
1139 /* mov, movt, bfi, bfc */
1140 /* These use only RD */
0a7de745 1141 if (THUMB32_RD(instr1, instr2) != REG_PC) {
5ba3f43e 1142 return FASTTRAP_T_COMMON;
0a7de745 1143 }
5ba3f43e 1144 } else {
0a7de745 1145 if (THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 1146 return FASTTRAP_T_COMMON;
0a7de745 1147 }
5ba3f43e
A
1148 }
1149
1150 return FASTTRAP_T_INV;
1151}
1152
1153static
0a7de745
A
1154int
1155thumb32_dataproc_mod_immed(uint16_t instr1, uint16_t instr2)
5ba3f43e 1156{
0a7de745 1157 int op = BITS(instr1, 5, 0xF), S = BITS(instr1, 4, 0x1);
5ba3f43e
A
1158
1159 if (op == 0x2 || op == 0x3) {
1160 /* These allow REG_PC in RN, but it doesn't mean use the PC! */
0a7de745 1161 if (THUMB32_RD(instr1, instr2) != REG_PC) {
5ba3f43e 1162 return FASTTRAP_T_COMMON;
0a7de745 1163 }
5ba3f43e
A
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. */
0a7de745 1168 if (S && THUMB32_RD(instr1, instr2) == REG_PC) {
5ba3f43e 1169 return FASTTRAP_T_COMMON;
0a7de745 1170 }
5ba3f43e
A
1171 }
1172
0a7de745 1173 if (THUMB32_RD(instr1, instr2) != REG_PC && THUMB32_RN(instr1, instr2) != REG_PC) {
5ba3f43e 1174 return FASTTRAP_T_COMMON;
0a7de745 1175 }
5ba3f43e
A
1176
1177 return FASTTRAP_T_INV;
1178}
1179
1180static
0a7de745
A
1181int
1182dtrace_decode_thumb32(uint16_t instr1, uint16_t instr2)
5ba3f43e 1183{
0a7de745 1184 int op1 = BITS(instr1, 11, 0x3), op2 = BITS(instr1, 4, 0x7F), op = BITS(instr2, 15, 0x1);
5ba3f43e
A
1185
1186 if (op1 == 0x1) {
0a7de745
A
1187 if ((op2 & 0x64) == 0) {
1188 return thumb32_loadstore_multiple(instr1, instr2);
1189 }
5ba3f43e 1190
0a7de745
A
1191 if ((op2 & 0x64) == 0x04) {
1192 return thumb32_loadstore_double_exclusive_table(instr1, instr2);
1193 }
5ba3f43e 1194
0a7de745
A
1195 if ((op2 & 0x60) == 0x20) {
1196 return thumb32_dataproc_regshift(instr1, instr2);
1197 }
5ba3f43e 1198
0a7de745
A
1199 if ((op2 & 0x40) == 0x40) {
1200 return thumb32_coproc(instr1, instr2);
1201 }
5ba3f43e
A
1202 }
1203
1204 if (op1 == 0x2) {
0a7de745
A
1205 if ((op2 & 0x20) == 0 && op == 0) {
1206 return thumb32_dataproc_mod_immed(instr1, instr2);
1207 }
5ba3f43e 1208
0a7de745
A
1209 if ((op2 & 0x20) == 0x20 && op == 0) {
1210 return thumb32_dataproc_plain_immed(instr1, instr2);
1211 }
5ba3f43e 1212
0a7de745
A
1213 if (op == 1) {
1214 return thumb32_b_misc_control(instr1, instr2);
1215 }
5ba3f43e
A
1216 }
1217
1218 if (op1 == 0x3) {
0a7de745
A
1219 if ((op2 & 0x71) == 0) {
1220 return thumb32_store_single(instr1, instr2);
1221 }
5ba3f43e
A
1222
1223 if ((op2 & 0x71) == 0x10) {
0a7de745 1224 return vfp_struct_loadstore(thumb32_instword_to_arm(instr1, instr2));
5ba3f43e
A
1225 }
1226
0a7de745
A
1227 if ((op2 & 0x67) == 0x01) {
1228 return thumb32_loadbyte_memhint(instr1, instr2);
1229 }
5ba3f43e 1230
0a7de745
A
1231 if ((op2 & 0x67) == 0x03) {
1232 return thumb32_loadhalfword_memhint(instr1, instr2);
1233 }
5ba3f43e 1234
0a7de745
A
1235 if ((op2 & 0x67) == 0x05) {
1236 return thumb32_loadword(instr1, instr2);
1237 }
5ba3f43e
A
1238
1239 if ((op2 & 0x67) == 0x07) {
1240 /* Undefined instruction */
1241 return FASTTRAP_T_INV;
1242 }
1243
0a7de745
A
1244 if ((op2 & 0x70) == 0x20) {
1245 return thumb32_dataproc_reg(instr1, instr2);
1246 }
5ba3f43e 1247
0a7de745
A
1248 if ((op2 & 0x78) == 0x30) {
1249 return thumb32_multiply(instr1, instr2);
1250 }
5ba3f43e 1251
0a7de745
A
1252 if ((op2 & 0x78) == 0x38) {
1253 return thumb32_longmultiply(instr1, instr2);
1254 }
5ba3f43e 1255
0a7de745
A
1256 if ((op2 & 0x40) == 0x40) {
1257 return thumb32_coproc(instr1, instr2);
1258 }
5ba3f43e
A
1259 }
1260
1261 return FASTTRAP_T_INV;
1262}
1263
0a7de745
A
1264int
1265dtrace_decode_thumb(uint32_t instr)
5ba3f43e
A
1266{
1267 uint16_t* pInstr = (uint16_t*) &instr;
1268 uint16_t hw1 = pInstr[0], hw2 = pInstr[1];
1269
0a7de745 1270 int size = BITS(hw1, 11, 0x1F);
5ba3f43e 1271
0a7de745
A
1272 if (size == 0x1D || size == 0x1E || size == 0x1F) {
1273 return dtrace_decode_thumb32(hw1, hw2);
1274 } else {
5ba3f43e 1275 return dtrace_decode_thumb16(hw1);
0a7de745 1276 }
5ba3f43e 1277}