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