1 /*
2 * \file trc_idec_arminst.cpp
3 * \brief OpenCSD :
4 *
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6 */
7
8 /*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 Basic ARM/Thumb/A64 instruction decode, suitable for e.g. basic
37 block identification and trace decode.
38 */
39
40 #include "i_dec/trc_idec_arminst.h"
41
42 #include <stddef.h> /* for NULL */
43 #include <assert.h>
44
inst_ARM_is_direct_branch(uint32_t inst)45 int inst_ARM_is_direct_branch(uint32_t inst)
46 {
47 int is_direct_branch = 1;
48 if ((inst & 0xf0000000) == 0xf0000000) {
49 /* NV space */
50 if ((inst & 0xfe000000) == 0xfa000000){
51 /* BLX (imm) */
52 } else {
53 is_direct_branch = 0;
54 }
55 } else if ((inst & 0x0e000000) == 0x0a000000) {
56 /* B, BL */
57 } else {
58 is_direct_branch = 0;
59 }
60 return is_direct_branch;
61 }
62
inst_ARM_wfiwfe(uint32_t inst)63 int inst_ARM_wfiwfe(uint32_t inst)
64 {
65 if ( ((inst & 0xf0000000) != 0xf0000000) &&
66 ((inst & 0x0ffffffe) == 0x0320f002)
67 )
68 /* WFI & WFE may be traced as branches in etm4.3 ++ */
69 return 1;
70 return 0;
71 }
72
inst_ARM_is_indirect_branch(uint32_t inst,struct decode_info * info)73 int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info)
74 {
75 int is_indirect_branch = 1;
76 if ((inst & 0xf0000000) == 0xf0000000) {
77 /* NV space */
78 if ((inst & 0xfe500000) == 0xf8100000) {
79 /* RFE */
80 } else {
81 is_indirect_branch = 0;
82 }
83 } else if ((inst & 0x0ff000d0) == 0x01200010) {
84 /* BLX (register), BX */
85 if ((inst & 0xFF) == 0x1E)
86 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */
87 } else if ((inst & 0x0ff000f0) == 0x01200020) {
88 /* BXJ: in v8 this behaves like BX */
89 } else if ((inst & 0x0e108000) == 0x08108000) {
90 /* POP {...,pc} or LDMxx {...,pc} */
91 if ((inst & 0x0FFFA000) == 0x08BD8000) /* LDMIA SP!,{...,pc} */
92 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;
93 } else if ((inst & 0x0e50f000) == 0x0410f000) {
94 /* LDR PC,imm... inc. POP {PC} */
95 if ( (inst & 0x01ff0000) == 0x009D0000)
96 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */
97 } else if ((inst & 0x0e50f010) == 0x0610f000) {
98 /* LDR PC,reg */
99 } else if ((inst & 0x0fe0f000) == 0x01a0f000) {
100 /* MOV PC,rx */
101 if ((inst & 0x00100FFF) == 0x00E) /* ensure the S=0, LSL #0 variant - i.e plain MOV */
102 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */
103 } else if ((inst & 0x0f900080) == 0x01000000) {
104 /* "Miscellaneous instructions" - in DP space */
105 is_indirect_branch = 0;
106 } else if ((inst & 0x0f9000f0) == 0x01800090) {
107 /* Some extended loads and stores */
108 is_indirect_branch = 0;
109 } else if ((inst & 0x0fb0f000) == 0x0320f000) {
110 /* MSR #imm */
111 is_indirect_branch = 0;
112 } else if ((inst & 0x0e00f000) == 0x0200f000) {
113 /* DP PC,imm shift */
114 if ((inst & 0x0f90f000) == 0x0310f000) {
115 /* TST/CMP */
116 is_indirect_branch = 0;
117 }
118 } else if ((inst & 0x0e00f000) == 0x0000f000) {
119 /* DP PC,reg */
120 } else {
121 is_indirect_branch = 0;
122 }
123 return is_indirect_branch;
124 }
125
inst_Thumb_is_direct_branch(uint32_t inst,struct decode_info * info)126 int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info)
127 {
128 uint8_t link, cond;
129 return inst_Thumb_is_direct_branch_link(inst, &link, &cond, info);
130 }
131
inst_Thumb_is_direct_branch_link(uint32_t inst,uint8_t * is_link,uint8_t * is_cond,struct decode_info * info)132 int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info)
133 {
134 int is_direct_branch = 1;
135
136 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) {
137 /* B<c> (encoding T1) */
138 *is_cond = 1;
139 } else if ((inst & 0xf8000000) == 0xe0000000) {
140 /* B (encoding T2) */
141 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) {
142 /* B (encoding T3) */
143 *is_cond = 1;
144 } else if ((inst & 0xf8009000) == 0xf0009000) {
145 /* B (encoding T4); BL (encoding T1) */
146 if (inst & 0x00004000) {
147 *is_link = 1;
148 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
149 }
150 } else if ((inst & 0xf800d001) == 0xf000c000) {
151 /* BLX (imm) (encoding T2) */
152 *is_link = 1;
153 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
154 } else if ((inst & 0xf5000000) == 0xb1000000) {
155 /* CB(NZ) */
156 *is_cond = 1;
157 } else {
158 is_direct_branch = 0;
159 }
160 return is_direct_branch;
161 }
162
inst_Thumb_wfiwfe(uint32_t inst)163 int inst_Thumb_wfiwfe(uint32_t inst)
164 {
165 int is_wfiwfe = 1;
166 /* WFI, WFE may be branches in etm4.3++ */
167 if ((inst & 0xfffffffe) == 0xf3af8002) {
168 /* WFI & WFE (encoding T2) */
169 }
170 else if ((inst & 0xffef0000) == 0xbf200000) {
171 /* WFI & WFE (encoding T1) */
172 }
173 else {
174 is_wfiwfe = 0;
175 }
176 return is_wfiwfe;
177 }
178
inst_Thumb_is_indirect_branch(uint32_t inst,struct decode_info * info)179 int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info)
180 {
181 uint8_t link;
182 return inst_Thumb_is_indirect_branch_link(inst, &link, info);
183 }
184
inst_Thumb_is_indirect_branch_link(uint32_t inst,uint8_t * is_link,struct decode_info * info)185 int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)
186 {
187 /* See e.g. PFT Table 2-3 and Table 2-5 */
188 int is_branch = 1;
189
190 if ((inst & 0xff000000) == 0x47000000) {
191 /* BX, BLX (reg) [v8M includes BXNS, BLXNS] */
192 if (inst & 0x00800000) {
193 *is_link = 1;
194 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
195 }
196 else if ((inst & 0x00780000) == 0x00700000) {
197 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */
198 }
199 } else if ((inst & 0xfff0d000) == 0xf3c08000) {
200 /* BXJ: in v8 this behaves like BX */
201 } else if ((inst & 0xff000000) == 0xbd000000) {
202 /* POP {pc} */
203 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET;
204 } else if ((inst & 0xfd870000) == 0x44870000) {
205 /* MOV PC,reg or ADD PC,reg */
206 if ((inst & 0xffff0000) == 0x46f70000)
207 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */
208 } else if ((inst & 0xfff0ffe0) == 0xe8d0f000) {
209 /* TBB/TBH */
210 } else if ((inst & 0xffd00000) == 0xe8100000) {
211 /* RFE (T1) */
212 } else if ((inst & 0xffd00000) == 0xe9900000) {
213 /* RFE (T2) */
214 } else if ((inst & 0xfff0d000) == 0xf3d08000) {
215 /* SUBS PC,LR,#imm inc.ERET */
216 } else if ((inst & 0xfff0f000) == 0xf8d0f000) {
217 /* LDR PC,imm (T3) */
218 } else if ((inst & 0xff7ff000) == 0xf85ff000) {
219 /* LDR PC,literal (T2) */
220 } else if ((inst & 0xfff0f800) == 0xf850f800) {
221 /* LDR PC,imm (T4) */
222 if((inst & 0x000f0f00) == 0x000d0b00)
223 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/
224 } else if ((inst & 0xfff0ffc0) == 0xf850f000) {
225 /* LDR PC,reg (T2) */
226 } else if ((inst & 0xfe508000) == 0xe8108000) {
227 /* LDM PC */
228 if ((inst & 0x0FFF0000) == 0x08BD0000) /* LDMIA [SP]!, */
229 info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */
230 } else {
231 is_branch = 0;
232 }
233 return is_branch;
234 }
235
inst_A64_is_direct_branch(uint32_t inst,struct decode_info * info)236 int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info)
237 {
238 uint8_t link = 0;
239 return inst_A64_is_direct_branch_link(inst, &link, info);
240 }
241
inst_A64_is_direct_branch_link(uint32_t inst,uint8_t * is_link,struct decode_info * info)242 int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)
243 {
244 int is_direct_branch = 1;
245 if ((inst & 0x7c000000) == 0x34000000) {
246 /* CB, TB */
247 } else if ((inst & 0xff000010) == 0x54000000) {
248 /* B<cond> */
249 } else if ((inst & 0x7c000000) == 0x14000000) {
250 /* B, BL imm */
251 if (inst & 0x80000000) {
252 *is_link = 1;
253 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
254 }
255 } else {
256 is_direct_branch = 0;
257 }
258 return is_direct_branch;
259 }
260
inst_A64_wfiwfe(uint32_t inst,struct decode_info * info)261 int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info)
262 {
263 /* WFI, WFE may be traced as branches in etm 4.3++ */
264 if ((inst & 0xffffffdf) == 0xd503205f)
265 return 1;
266
267 /* new feature introduced post v8.3 */
268 if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64))
269 {
270 /* WFIT / WFET for later archs */
271 if ((inst & 0xffffffc0) == 0xd5031000)
272 return 1;
273 }
274 return 0;
275 }
276
inst_A64_Tstart(uint32_t inst)277 int inst_A64_Tstart(uint32_t inst)
278 {
279 if ((inst & 0xffffffe0) == 0xd5233060)
280 return 1;
281 return 0;
282 }
283
inst_A64_is_indirect_branch(uint32_t inst,struct decode_info * info)284 int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info)
285 {
286 uint8_t link = 0;
287 return inst_A64_is_indirect_branch_link(inst, &link, info);
288 }
289
inst_A64_is_indirect_branch_link(uint32_t inst,uint8_t * is_link,struct decode_info * info)290 int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)
291 {
292 int is_indirect_branch = 1;
293
294 if ((inst & 0xffdffc1f) == 0xd61f0000) {
295 /* BR, BLR */
296 if (inst & 0x00200000) {
297 *is_link = 1;
298 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
299 }
300 } else if ((inst & 0xfffffc1f) == 0xd65f0000) {
301 info->instr_sub_type = OCSD_S_INSTR_V8_RET;
302 /* RET */
303 } else if ((inst & 0xffffffff) == 0xd69f03e0) {
304 /* ERET */
305 info->instr_sub_type = OCSD_S_INSTR_V8_ERET;
306 } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
307 /* new pointer auth instr for v8.3 arch */
308 if ((inst & 0xffdff800) == 0xd71f0800) {
309 /* BRAA, BRAB, BLRAA, BLRBB */
310 if (inst & 0x00200000) {
311 *is_link = 1;
312 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
313 }
314 } else if ((inst & 0xffdff81F) == 0xd61f081F) {
315 /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */
316 if (inst & 0x00200000) {
317 *is_link = 1;
318 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
319 }
320 } else if ((inst & 0xfffffbff) == 0xd69f0bff) {
321 /* ERETAA, ERETAB */
322 info->instr_sub_type = OCSD_S_INSTR_V8_ERET;
323 } else if ((inst & 0xfffffbff) == 0xd65f0bff) {
324 /* RETAA, RETAB */
325 info->instr_sub_type = OCSD_S_INSTR_V8_RET;
326 } else {
327 is_indirect_branch = 0;
328 }
329 } else {
330 is_indirect_branch = 0;
331 }
332 return is_indirect_branch;
333 }
334
inst_ARM_branch_destination(uint32_t addr,uint32_t inst,uint32_t * pnpc)335 int inst_ARM_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc)
336 {
337 uint32_t npc;
338 int is_direct_branch = 1;
339 if ((inst & 0x0e000000) == 0x0a000000) {
340 /*
341 B: cccc:1010:imm24
342 BL: cccc:1011:imm24
343 BLX: 1111:101H:imm24
344 */
345 npc = addr + 8 + ((int32_t)((inst & 0xffffff) << 8) >> 6);
346 if ((inst & 0xf0000000) == 0xf0000000) {
347 npc |= 1; /* indicate ISA is now Thumb */
348 npc |= ((inst >> 23) & 2); /* apply the H bit */
349 }
350 } else {
351 is_direct_branch = 0;
352 }
353 if (is_direct_branch && pnpc != NULL) {
354 *pnpc = npc;
355 }
356 return is_direct_branch;
357 }
358
inst_Thumb_branch_destination(uint32_t addr,uint32_t inst,uint32_t * pnpc)359 int inst_Thumb_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc)
360 {
361 uint32_t npc;
362 int is_direct_branch = 1;
363 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) {
364 /* B<c> (encoding T1) */
365 npc = addr + 4 + ((int32_t)((inst & 0x00ff0000) << 8) >> 23);
366 npc |= 1;
367 } else if ((inst & 0xf8000000) == 0xe0000000) {
368 /* B (encoding T2) */
369 npc = addr + 4 + ((int32_t)((inst & 0x07ff0000) << 5) >> 20);
370 npc |= 1;
371 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) {
372 /* B (encoding T3) */
373 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
374 ((inst & 0x0800) << 19) |
375 ((inst & 0x2000) << 16) |
376 ((inst & 0x003f0000) << 7) |
377 ((inst & 0x000007ff) << 12)) >> 11);
378 npc |= 1;
379 } else if ((inst & 0xf8009000) == 0xf0009000) {
380 /* B (encoding T4); BL (encoding T1) */
381 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */
382 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
383 (((inst^S) & 0x2000) << 17) |
384 (((inst^S) & 0x0800) << 18) |
385 ((inst & 0x03ff0000) << 3) |
386 ((inst & 0x000007ff) << 8)) >> 7);
387 npc |= 1;
388 } else if ((inst & 0xf800d001) == 0xf000c000) {
389 /* BLX (encoding T2) */
390 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */
391 addr &= 0xfffffffc; /* Align(PC,4) */
392 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
393 (((inst^S) & 0x2000) << 17) |
394 (((inst^S) & 0x0800) << 18) |
395 ((inst & 0x03ff0000) << 3) |
396 ((inst & 0x000007fe) << 8)) >> 7);
397 /* don't set the Thumb bit, as we're transferring to ARM */
398 } else if ((inst & 0xf5000000) == 0xb1000000) {
399 /* CB(NZ) */
400 /* Note that it's zero-extended - always a forward branch */
401 npc = addr + 4 + ((((inst & 0x02000000) << 6) |
402 ((inst & 0x00f80000) << 7)) >> 25);
403 npc |= 1;
404 } else {
405 is_direct_branch = 0;
406 }
407 if (is_direct_branch && pnpc != NULL) {
408 *pnpc = npc;
409 }
410 return is_direct_branch;
411 }
412
inst_A64_branch_destination(uint64_t addr,uint32_t inst,uint64_t * pnpc)413 int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc)
414 {
415 uint64_t npc;
416 int is_direct_branch = 1;
417 if ((inst & 0xff000010) == 0x54000000) {
418 /* B<cond> */
419 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);
420 } else if ((inst & 0x7c000000) == 0x14000000) {
421 /* B, BL imm */
422 npc = addr + ((int32_t)((inst & 0x03ffffff) << 6) >> 4);
423 } else if ((inst & 0x7e000000) == 0x34000000) {
424 /* CB */
425 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);
426 } else if ((inst & 0x7e000000) == 0x36000000) {
427 /* TB */
428 npc = addr + ((int32_t)((inst & 0x0007ffe0) << 13) >> 16);
429 } else {
430 is_direct_branch = 0;
431 }
432 if (is_direct_branch && pnpc != NULL) {
433 *pnpc = npc;
434 }
435 return is_direct_branch;
436 }
437
inst_ARM_is_branch(uint32_t inst,struct decode_info * info)438 int inst_ARM_is_branch(uint32_t inst, struct decode_info *info)
439 {
440 return inst_ARM_is_indirect_branch(inst, info) ||
441 inst_ARM_is_direct_branch(inst);
442 }
443
inst_Thumb_is_branch(uint32_t inst,struct decode_info * info)444 int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info)
445 {
446 return inst_Thumb_is_indirect_branch(inst, info) ||
447 inst_Thumb_is_direct_branch(inst, info);
448 }
449
inst_A64_is_branch(uint32_t inst,struct decode_info * info)450 int inst_A64_is_branch(uint32_t inst, struct decode_info *info)
451 {
452 return inst_A64_is_indirect_branch(inst, info) ||
453 inst_A64_is_direct_branch(inst, info);
454 }
455
inst_ARM_is_branch_and_link(uint32_t inst,struct decode_info * info)456 int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info)
457 {
458 int is_branch = 1;
459 if ((inst & 0xf0000000) == 0xf0000000) {
460 if ((inst & 0xfe000000) == 0xfa000000){
461 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
462 /* BLX (imm) */
463 } else {
464 is_branch = 0;
465 }
466 } else if ((inst & 0x0f000000) == 0x0b000000) {
467 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
468 /* BL */
469 } else if ((inst & 0x0ff000f0) == 0x01200030) {
470 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
471 /* BLX (reg) */
472 } else {
473 is_branch = 0;
474 }
475 return is_branch;
476 }
477
inst_Thumb_is_branch_and_link(uint32_t inst,struct decode_info * info)478 int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info)
479 {
480 int is_branch = 1;
481 if ((inst & 0xff800000) == 0x47800000) {
482 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
483 /* BLX (reg) */
484 } else if ((inst & 0xf800c000) == 0xf000c000) {
485 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
486 /* BL, BLX (imm) */
487 } else {
488 is_branch = 0;
489 }
490 return is_branch;
491 }
492
inst_A64_is_branch_and_link(uint32_t inst,struct decode_info * info)493 int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info)
494 {
495 int is_branch = 1;
496 if ((inst & 0xfffffc1f) == 0xd63f0000) {
497 /* BLR */
498 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
499 } else if ((inst & 0xfc000000) == 0x94000000) {
500 /* BL */
501 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
502 } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
503 /* new pointer auth instr for v8.3 arch */
504 if ((inst & 0xfffff800) == 0xd73f0800) {
505 /* BLRAA, BLRBB */
506 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
507 } else if ((inst & 0xfffff81F) == 0xd63f081F) {
508 /* BLRAAZ, BLRBBZ */
509 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
510 } else {
511 is_branch = 0;
512 }
513 } else {
514 is_branch = 0;
515 }
516 return is_branch;
517 }
518
inst_ARM_is_conditional(uint32_t inst)519 int inst_ARM_is_conditional(uint32_t inst)
520 {
521 return (inst & 0xe0000000) != 0xe0000000;
522 }
523
inst_Thumb_is_conditional(uint32_t inst)524 int inst_Thumb_is_conditional(uint32_t inst)
525 {
526 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) {
527 /* B<c> (encoding T1) */
528 return 1;
529 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) {
530 /* B<c> (encoding T3) */
531 return 1;
532 } else if ((inst & 0xf5000000) == 0xb1000000) {
533 /* CB(N)Z */
534 return 1;
535 }
536 return 0;
537 }
538
inst_Thumb_is_IT(uint32_t inst)539 unsigned int inst_Thumb_is_IT(uint32_t inst)
540 {
541 if ((inst & 0xff000000) == 0xbf000000 &&
542 (inst & 0x000f0000) != 0x00000000) {
543 if (inst & 0x00010000) {
544 return 4;
545 } else if (inst & 0x00020000) {
546 return 3;
547 } else if (inst & 0x00040000) {
548 return 2;
549 } else {
550 assert(inst & 0x00080000);
551 return 1;
552 }
553 } else {
554 return 0;
555 }
556 }
557
558 /*
559 Test whether an A64 instruction is conditional.
560
561 Instructions like CSEL, CSINV, CCMP are not classed as conditional.
562 They use the condition code but do one of two things with it,
563 neither a NOP. The "intruction categories" section of ETMv4
564 lists no (non branch) conditional instructions for A64.
565 */
inst_A64_is_conditional(uint32_t inst)566 int inst_A64_is_conditional(uint32_t inst)
567 {
568 if ((inst & 0x7c000000) == 0x34000000) {
569 /* CB, TB */
570 return 1;
571 } else if ((inst & 0xff000010) == 0x54000000) {
572 /* B.cond */
573 return 1;
574 }
575 return 0;
576 }
577
inst_ARM_barrier(uint32_t inst)578 arm_barrier_t inst_ARM_barrier(uint32_t inst)
579 {
580 if ((inst & 0xfff00000) == 0xf5700000) {
581 switch (inst & 0xf0) {
582 case 0x40:
583 return ARM_BARRIER_DSB;
584 case 0x50:
585 return ARM_BARRIER_DMB;
586 case 0x60:
587 return ARM_BARRIER_ISB;
588 default:
589 return ARM_BARRIER_NONE;
590 }
591 } else if ((inst & 0x0fff0f00) == 0x0e070f00) {
592 switch (inst & 0xff) {
593 case 0x9a:
594 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */
595 case 0xba:
596 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */
597 case 0x95:
598 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */
599 default:
600 return ARM_BARRIER_NONE;
601 }
602 } else {
603 return ARM_BARRIER_NONE;
604 }
605 }
606
inst_Thumb_barrier(uint32_t inst)607 arm_barrier_t inst_Thumb_barrier(uint32_t inst)
608 {
609 if ((inst & 0xffffff00) == 0xf3bf8f00) {
610 switch (inst & 0xf0) {
611 case 0x40:
612 return ARM_BARRIER_DSB;
613 case 0x50:
614 return ARM_BARRIER_DMB;
615 case 0x60:
616 return ARM_BARRIER_ISB;
617 default:
618 return ARM_BARRIER_NONE;
619 }
620 } else if ((inst & 0xffff0f00) == 0xee070f00) {
621 /* Thumb2 CP15 barriers are unlikely... 1156T2 only? */
622 switch (inst & 0xff) {
623 case 0x9a:
624 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */
625 case 0xba:
626 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */
627 case 0x95:
628 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */
629 default:
630 return ARM_BARRIER_NONE;
631 }
632 return ARM_BARRIER_NONE;
633 } else {
634 return ARM_BARRIER_NONE;
635 }
636 }
637
inst_A64_barrier(uint32_t inst)638 arm_barrier_t inst_A64_barrier(uint32_t inst)
639 {
640 if ((inst & 0xfffff09f) == 0xd503309f) {
641 switch (inst & 0x60) {
642 case 0x0:
643 return ARM_BARRIER_DSB;
644 case 0x20:
645 return ARM_BARRIER_DMB;
646 case 0x40:
647 return ARM_BARRIER_ISB;
648 default:
649 return ARM_BARRIER_NONE;
650 }
651 } else {
652 return ARM_BARRIER_NONE;
653 }
654 }
655
inst_ARM_is_UDF(uint32_t inst)656 int inst_ARM_is_UDF(uint32_t inst)
657 {
658 return (inst & 0xfff000f0) == 0xe7f000f0;
659 }
660
inst_Thumb_is_UDF(uint32_t inst)661 int inst_Thumb_is_UDF(uint32_t inst)
662 {
663 return (inst & 0xff000000) == 0xde000000 || /* T1 */
664 (inst & 0xfff0f000) == 0xf7f0a000; /* T2 */
665 }
666
inst_A64_is_UDF(uint32_t inst)667 int inst_A64_is_UDF(uint32_t inst)
668 {
669 /* No A64 encodings are formally allocated as permanently undefined,
670 but it is intended not to allocate any instructions in the 21-bit
671 regions at the bottom or top of the range. */
672 return (inst & 0xffe00000) == 0x00000000 ||
673 (inst & 0xffe00000) == 0xffe00000;
674 }
675
676 /* End of File trc_idec_arminst.cpp */
677