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