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 & 0xff000000) == 0x54000000) {
248 /* B<cond> */
249 /* BC<cond> 8.8 / 9.3 arch - bit 4 = 1'b1 */
250 } else if ((inst & 0x7c000000) == 0x14000000) {
251 /* B, BL imm */
252 if (inst & 0x80000000) {
253 *is_link = 1;
254 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
255 }
256 } else {
257 is_direct_branch = 0;
258 }
259 return is_direct_branch;
260 }
261
inst_A64_wfiwfe(uint32_t inst,struct decode_info * info)262 int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info)
263 {
264 /* WFI, WFE may be traced as branches in etm 4.3++ */
265 if ((inst & 0xffffffdf) == 0xd503205f)
266 return 1;
267
268 /* new feature introduced post v8.3 */
269 if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64))
270 {
271 /* WFIT / WFET for later archs */
272 if ((inst & 0xffffffc0) == 0xd5031000)
273 return 1;
274 }
275 return 0;
276 }
277
inst_A64_Tstart(uint32_t inst)278 int inst_A64_Tstart(uint32_t inst)
279 {
280 if ((inst & 0xffffffe0) == 0xd5233060)
281 return 1;
282 return 0;
283 }
284
inst_A64_is_indirect_branch(uint32_t inst,struct decode_info * info)285 int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info)
286 {
287 uint8_t link = 0;
288 return inst_A64_is_indirect_branch_link(inst, &link, info);
289 }
290
inst_A64_is_indirect_branch_link(uint32_t inst,uint8_t * is_link,struct decode_info * info)291 int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info)
292 {
293 int is_indirect_branch = 1;
294
295 if ((inst & 0xffdffc1f) == 0xd61f0000) {
296 /* BR, BLR */
297 if (inst & 0x00200000) {
298 *is_link = 1;
299 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
300 }
301 } else if ((inst & 0xfffffc1f) == 0xd65f0000) {
302 info->instr_sub_type = OCSD_S_INSTR_V8_RET;
303 /* RET */
304 } else if ((inst & 0xffffffff) == 0xd69f03e0) {
305 /* ERET */
306 info->instr_sub_type = OCSD_S_INSTR_V8_ERET;
307 } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
308 /* new pointer auth instr for v8.3 arch */
309 if ((inst & 0xffdff800) == 0xd71f0800) {
310 /* BRAA, BRAB, BLRAA, BLRBB */
311 if (inst & 0x00200000) {
312 *is_link = 1;
313 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
314 }
315 } else if ((inst & 0xffdff81F) == 0xd61f081F) {
316 /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */
317 if (inst & 0x00200000) {
318 *is_link = 1;
319 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
320 }
321 } else if ((inst & 0xfffffbff) == 0xd69f0bff) {
322 /* ERETAA, ERETAB */
323 info->instr_sub_type = OCSD_S_INSTR_V8_ERET;
324 } else if ((inst & 0xfffffbff) == 0xd65f0bff) {
325 /* RETAA, RETAB */
326 info->instr_sub_type = OCSD_S_INSTR_V8_RET;
327 } else {
328 is_indirect_branch = 0;
329 }
330 } else {
331 is_indirect_branch = 0;
332 }
333 return is_indirect_branch;
334 }
335
inst_ARM_branch_destination(uint32_t addr,uint32_t inst,uint32_t * pnpc)336 int inst_ARM_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc)
337 {
338 uint32_t npc;
339 int is_direct_branch = 1;
340 if ((inst & 0x0e000000) == 0x0a000000) {
341 /*
342 B: cccc:1010:imm24
343 BL: cccc:1011:imm24
344 BLX: 1111:101H:imm24
345 */
346 npc = addr + 8 + ((int32_t)((inst & 0xffffff) << 8) >> 6);
347 if ((inst & 0xf0000000) == 0xf0000000) {
348 npc |= 1; /* indicate ISA is now Thumb */
349 npc |= ((inst >> 23) & 2); /* apply the H bit */
350 }
351 } else {
352 is_direct_branch = 0;
353 }
354 if (is_direct_branch && pnpc != NULL) {
355 *pnpc = npc;
356 }
357 return is_direct_branch;
358 }
359
inst_Thumb_branch_destination(uint32_t addr,uint32_t inst,uint32_t * pnpc)360 int inst_Thumb_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc)
361 {
362 uint32_t npc;
363 int is_direct_branch = 1;
364 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) {
365 /* B<c> (encoding T1) */
366 npc = addr + 4 + ((int32_t)((inst & 0x00ff0000) << 8) >> 23);
367 npc |= 1;
368 } else if ((inst & 0xf8000000) == 0xe0000000) {
369 /* B (encoding T2) */
370 npc = addr + 4 + ((int32_t)((inst & 0x07ff0000) << 5) >> 20);
371 npc |= 1;
372 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) {
373 /* B (encoding T3) */
374 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
375 ((inst & 0x0800) << 19) |
376 ((inst & 0x2000) << 16) |
377 ((inst & 0x003f0000) << 7) |
378 ((inst & 0x000007ff) << 12)) >> 11);
379 npc |= 1;
380 } else if ((inst & 0xf8009000) == 0xf0009000) {
381 /* B (encoding T4); BL (encoding T1) */
382 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */
383 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
384 (((inst^S) & 0x2000) << 17) |
385 (((inst^S) & 0x0800) << 18) |
386 ((inst & 0x03ff0000) << 3) |
387 ((inst & 0x000007ff) << 8)) >> 7);
388 npc |= 1;
389 } else if ((inst & 0xf800d001) == 0xf000c000) {
390 /* BLX (encoding T2) */
391 uint32_t S = ((inst & 0x04000000) >> 26)-1; /* ffffffff or 0 according to S bit */
392 addr &= 0xfffffffc; /* Align(PC,4) */
393 npc = addr + 4 + ((int32_t)(((inst & 0x04000000) << 5) |
394 (((inst^S) & 0x2000) << 17) |
395 (((inst^S) & 0x0800) << 18) |
396 ((inst & 0x03ff0000) << 3) |
397 ((inst & 0x000007fe) << 8)) >> 7);
398 /* don't set the Thumb bit, as we're transferring to ARM */
399 } else if ((inst & 0xf5000000) == 0xb1000000) {
400 /* CB(NZ) */
401 /* Note that it's zero-extended - always a forward branch */
402 npc = addr + 4 + ((((inst & 0x02000000) << 6) |
403 ((inst & 0x00f80000) << 7)) >> 25);
404 npc |= 1;
405 } else {
406 is_direct_branch = 0;
407 }
408 if (is_direct_branch && pnpc != NULL) {
409 *pnpc = npc;
410 }
411 return is_direct_branch;
412 }
413
inst_A64_branch_destination(uint64_t addr,uint32_t inst,uint64_t * pnpc)414 int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc)
415 {
416 uint64_t npc;
417 int is_direct_branch = 1;
418 if ((inst & 0xff000000) == 0x54000000) {
419 /* B<cond> */
420 /* BC<cond> */
421 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);
422 } else if ((inst & 0x7c000000) == 0x14000000) {
423 /* B, BL imm */
424 npc = addr + ((int32_t)((inst & 0x03ffffff) << 6) >> 4);
425 } else if ((inst & 0x7e000000) == 0x34000000) {
426 /* CB */
427 npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);
428 } else if ((inst & 0x7e000000) == 0x36000000) {
429 /* TB */
430 npc = addr + ((int32_t)((inst & 0x0007ffe0) << 13) >> 16);
431 } else {
432 is_direct_branch = 0;
433 }
434 if (is_direct_branch && pnpc != NULL) {
435 *pnpc = npc;
436 }
437 return is_direct_branch;
438 }
439
inst_ARM_is_branch(uint32_t inst,struct decode_info * info)440 int inst_ARM_is_branch(uint32_t inst, struct decode_info *info)
441 {
442 return inst_ARM_is_indirect_branch(inst, info) ||
443 inst_ARM_is_direct_branch(inst);
444 }
445
inst_Thumb_is_branch(uint32_t inst,struct decode_info * info)446 int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info)
447 {
448 return inst_Thumb_is_indirect_branch(inst, info) ||
449 inst_Thumb_is_direct_branch(inst, info);
450 }
451
inst_A64_is_branch(uint32_t inst,struct decode_info * info)452 int inst_A64_is_branch(uint32_t inst, struct decode_info *info)
453 {
454 return inst_A64_is_indirect_branch(inst, info) ||
455 inst_A64_is_direct_branch(inst, info);
456 }
457
inst_ARM_is_branch_and_link(uint32_t inst,struct decode_info * info)458 int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info)
459 {
460 int is_branch = 1;
461 if ((inst & 0xf0000000) == 0xf0000000) {
462 if ((inst & 0xfe000000) == 0xfa000000){
463 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
464 /* BLX (imm) */
465 } else {
466 is_branch = 0;
467 }
468 } else if ((inst & 0x0f000000) == 0x0b000000) {
469 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
470 /* BL */
471 } else if ((inst & 0x0ff000f0) == 0x01200030) {
472 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
473 /* BLX (reg) */
474 } else {
475 is_branch = 0;
476 }
477 return is_branch;
478 }
479
inst_Thumb_is_branch_and_link(uint32_t inst,struct decode_info * info)480 int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info)
481 {
482 int is_branch = 1;
483 if ((inst & 0xff800000) == 0x47800000) {
484 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
485 /* BLX (reg) */
486 } else if ((inst & 0xf800c000) == 0xf000c000) {
487 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
488 /* BL, BLX (imm) */
489 } else {
490 is_branch = 0;
491 }
492 return is_branch;
493 }
494
inst_A64_is_branch_and_link(uint32_t inst,struct decode_info * info)495 int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info)
496 {
497 int is_branch = 1;
498 if ((inst & 0xfffffc1f) == 0xd63f0000) {
499 /* BLR */
500 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
501 } else if ((inst & 0xfc000000) == 0x94000000) {
502 /* BL */
503 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
504 } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
505 /* new pointer auth instr for v8.3 arch */
506 if ((inst & 0xfffff800) == 0xd73f0800) {
507 /* BLRAA, BLRBB */
508 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
509 } else if ((inst & 0xfffff81F) == 0xd63f081F) {
510 /* BLRAAZ, BLRBBZ */
511 info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
512 } else {
513 is_branch = 0;
514 }
515 } else {
516 is_branch = 0;
517 }
518 return is_branch;
519 }
520
inst_ARM_is_conditional(uint32_t inst)521 int inst_ARM_is_conditional(uint32_t inst)
522 {
523 return (inst & 0xe0000000) != 0xe0000000;
524 }
525
inst_Thumb_is_conditional(uint32_t inst)526 int inst_Thumb_is_conditional(uint32_t inst)
527 {
528 if ((inst & 0xf0000000) == 0xd0000000 && (inst & 0x0e000000) != 0x0e000000) {
529 /* B<c> (encoding T1) */
530 return 1;
531 } else if ((inst & 0xf800d000) == 0xf0008000 && (inst & 0x03800000) != 0x03800000) {
532 /* B<c> (encoding T3) */
533 return 1;
534 } else if ((inst & 0xf5000000) == 0xb1000000) {
535 /* CB(N)Z */
536 return 1;
537 }
538 return 0;
539 }
540
inst_Thumb_is_IT(uint32_t inst)541 unsigned int inst_Thumb_is_IT(uint32_t inst)
542 {
543 if ((inst & 0xff000000) == 0xbf000000 &&
544 (inst & 0x000f0000) != 0x00000000) {
545 if (inst & 0x00010000) {
546 return 4;
547 } else if (inst & 0x00020000) {
548 return 3;
549 } else if (inst & 0x00040000) {
550 return 2;
551 } else {
552 assert(inst & 0x00080000);
553 return 1;
554 }
555 } else {
556 return 0;
557 }
558 }
559
560 /*
561 Test whether an A64 instruction is conditional.
562
563 Instructions like CSEL, CSINV, CCMP are not classed as conditional.
564 They use the condition code but do one of two things with it,
565 neither a NOP. The "intruction categories" section of ETMv4
566 lists no (non branch) conditional instructions for A64.
567 */
inst_A64_is_conditional(uint32_t inst)568 int inst_A64_is_conditional(uint32_t inst)
569 {
570 if ((inst & 0x7c000000) == 0x34000000) {
571 /* CB, TB */
572 return 1;
573 } else if ((inst & 0xff000000) == 0x54000000) {
574 /* B.cond */
575 /* BC.cond */
576 return 1;
577 }
578 return 0;
579 }
580
inst_ARM_barrier(uint32_t inst)581 arm_barrier_t inst_ARM_barrier(uint32_t inst)
582 {
583 if ((inst & 0xfff00000) == 0xf5700000) {
584 switch (inst & 0xf0) {
585 case 0x40:
586 return ARM_BARRIER_DSB;
587 case 0x50:
588 return ARM_BARRIER_DMB;
589 case 0x60:
590 return ARM_BARRIER_ISB;
591 default:
592 return ARM_BARRIER_NONE;
593 }
594 } else if ((inst & 0x0fff0f00) == 0x0e070f00) {
595 switch (inst & 0xff) {
596 case 0x9a:
597 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */
598 case 0xba:
599 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */
600 case 0x95:
601 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */
602 default:
603 return ARM_BARRIER_NONE;
604 }
605 } else {
606 return ARM_BARRIER_NONE;
607 }
608 }
609
inst_Thumb_barrier(uint32_t inst)610 arm_barrier_t inst_Thumb_barrier(uint32_t inst)
611 {
612 if ((inst & 0xffffff00) == 0xf3bf8f00) {
613 switch (inst & 0xf0) {
614 case 0x40:
615 return ARM_BARRIER_DSB;
616 case 0x50:
617 return ARM_BARRIER_DMB;
618 case 0x60:
619 return ARM_BARRIER_ISB;
620 default:
621 return ARM_BARRIER_NONE;
622 }
623 } else if ((inst & 0xffff0f00) == 0xee070f00) {
624 /* Thumb2 CP15 barriers are unlikely... 1156T2 only? */
625 switch (inst & 0xff) {
626 case 0x9a:
627 return ARM_BARRIER_DSB; /* mcr p15,0,Rt,c7,c10,4 */
628 case 0xba:
629 return ARM_BARRIER_DMB; /* mcr p15,0,Rt,c7,c10,5 */
630 case 0x95:
631 return ARM_BARRIER_ISB; /* mcr p15,0,Rt,c7,c5,4 */
632 default:
633 return ARM_BARRIER_NONE;
634 }
635 return ARM_BARRIER_NONE;
636 } else {
637 return ARM_BARRIER_NONE;
638 }
639 }
640
inst_A64_barrier(uint32_t inst)641 arm_barrier_t inst_A64_barrier(uint32_t inst)
642 {
643 if ((inst & 0xfffff09f) == 0xd503309f) {
644 switch (inst & 0x60) {
645 case 0x0:
646 return ARM_BARRIER_DSB;
647 case 0x20:
648 return ARM_BARRIER_DMB;
649 case 0x40:
650 return ARM_BARRIER_ISB;
651 default:
652 return ARM_BARRIER_NONE;
653 }
654 } else {
655 return ARM_BARRIER_NONE;
656 }
657 }
658
inst_ARM_is_UDF(uint32_t inst)659 int inst_ARM_is_UDF(uint32_t inst)
660 {
661 return (inst & 0xfff000f0) == 0xe7f000f0;
662 }
663
inst_Thumb_is_UDF(uint32_t inst)664 int inst_Thumb_is_UDF(uint32_t inst)
665 {
666 return (inst & 0xff000000) == 0xde000000 || /* T1 */
667 (inst & 0xfff0f000) == 0xf7f0a000; /* T2 */
668 }
669
inst_A64_is_UDF(uint32_t inst)670 int inst_A64_is_UDF(uint32_t inst)
671 {
672 /* No A64 encodings are formally allocated as permanently undefined,
673 but it is intended not to allocate any instructions in the 21-bit
674 regions at the bottom or top of the range. */
675 return (inst & 0xffe00000) == 0x00000000 ||
676 (inst & 0xffe00000) == 0xffe00000;
677 }
678
679 /* End of File trc_idec_arminst.cpp */
680