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