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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
278 int inst_A64_Tstart(uint32_t inst)
279 {
280     if ((inst & 0xffffffe0) == 0xd5233060)
281         return 1;
282     return 0;
283 }
284 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
521 int inst_ARM_is_conditional(uint32_t inst)
522 {
523     return (inst & 0xe0000000) != 0xe0000000;
524 }
525 
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 
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 */
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 
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 
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 
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 
659 int inst_ARM_is_UDF(uint32_t inst)
660 {
661     return (inst & 0xfff000f0) == 0xe7f000f0;
662 }
663 
664 int inst_Thumb_is_UDF(uint32_t inst)
665 {
666     return (inst & 0xff000000) == 0xde000000 ||   /* T1 */
667            (inst & 0xfff0f000) == 0xf7f0a000;     /* T2 */
668 }
669 
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