• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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