/src/capstonenext/arch/AArch64/AArch64Mapping.c
Line  | Count  | Source  | 
1  |  | /* Capstone Disassembly Engine */  | 
2  |  | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */  | 
3  |  |  | 
4  |  | #ifdef CAPSTONE_HAS_AARCH64  | 
5  |  |  | 
6  |  | #include <stdio.h> // debug  | 
7  |  | #include <string.h>  | 
8  |  |  | 
9  |  | #include "capstone/aarch64.h"  | 
10  |  |  | 
11  |  | #include "../../cs_simple_types.h"  | 
12  |  | #include "../../Mapping.h"  | 
13  |  | #include "../../MathExtras.h"  | 
14  |  | #include "../../utils.h"  | 
15  |  |  | 
16  |  | #include "AArch64AddressingModes.h"  | 
17  |  | #include "AArch64BaseInfo.h"  | 
18  |  | #include "AArch64DisassemblerExtension.h"  | 
19  |  | #include "AArch64Linkage.h"  | 
20  |  | #include "AArch64Mapping.h"  | 
21  |  |  | 
22  | 3.45k  | #define CHAR(c) #c[0]  | 
23  |  |  | 
24  |  | static float aarch64_exact_fp_to_fp(aarch64_exactfpimm exact)  | 
25  | 11.7k  | { | 
26  | 11.7k  |   switch (exact) { | 
27  | 0  |   default:  | 
28  | 0  |     CS_ASSERT(0 && "Not handled.");  | 
29  | 0  |     return 999.0;  | 
30  | 276  |   case AARCH64_EXACTFPIMM_HALF:  | 
31  | 276  |     return 0.5;  | 
32  | 944  |   case AARCH64_EXACTFPIMM_ONE:  | 
33  | 944  |     return 1.0;  | 
34  | 470  |   case AARCH64_EXACTFPIMM_TWO:  | 
35  | 470  |     return 2.0;  | 
36  | 10.0k  |   case AARCH64_EXACTFPIMM_ZERO:  | 
37  | 10.0k  |     return 0.0;  | 
38  | 11.7k  |   }  | 
39  | 11.7k  | }  | 
40  |  |  | 
41  |  | #ifndef CAPSTONE_DIET  | 
42  |  | static const aarch64_reg aarch64_flag_regs[] = { | 
43  |  |   AARCH64_REG_NZCV,  | 
44  |  | };  | 
45  |  |  | 
46  |  | static const aarch64_sysreg aarch64_flag_sys_regs[] = { | 
47  |  |   AARCH64_SYSREG_NZCV, AARCH64_SYSREG_PMOVSCLR_EL0,  | 
48  |  |   AARCH64_SYSREG_PMOVSSET_EL0, AARCH64_SYSREG_SPMOVSCLR_EL0,  | 
49  |  |   AARCH64_SYSREG_SPMOVSSET_EL0  | 
50  |  | };  | 
51  |  | #endif // CAPSTONE_DIET  | 
52  |  |  | 
53  |  | static AArch64Layout_VectorLayout sme_reg_to_vas(aarch64_reg reg)  | 
54  | 0  | { | 
55  | 0  |   switch (reg) { | 
56  | 0  |   default:  | 
57  | 0  |     return AARCH64LAYOUT_INVALID;  | 
58  | 0  |   case AARCH64_REG_ZAB0:  | 
59  | 0  |     return AARCH64LAYOUT_VL_B;  | 
60  | 0  |   case AARCH64_REG_ZAH0:  | 
61  | 0  |   case AARCH64_REG_ZAH1:  | 
62  | 0  |     return AARCH64LAYOUT_VL_H;  | 
63  | 0  |   case AARCH64_REG_ZAS0:  | 
64  | 0  |   case AARCH64_REG_ZAS1:  | 
65  | 0  |   case AARCH64_REG_ZAS2:  | 
66  | 0  |   case AARCH64_REG_ZAS3:  | 
67  | 0  |     return AARCH64LAYOUT_VL_S;  | 
68  | 0  |   case AARCH64_REG_ZAD0:  | 
69  | 0  |   case AARCH64_REG_ZAD1:  | 
70  | 0  |   case AARCH64_REG_ZAD2:  | 
71  | 0  |   case AARCH64_REG_ZAD3:  | 
72  | 0  |   case AARCH64_REG_ZAD4:  | 
73  | 0  |   case AARCH64_REG_ZAD5:  | 
74  | 0  |   case AARCH64_REG_ZAD6:  | 
75  | 0  |   case AARCH64_REG_ZAD7:  | 
76  | 0  |     return AARCH64LAYOUT_VL_D;  | 
77  | 0  |   case AARCH64_REG_ZAQ0:  | 
78  | 0  |   case AARCH64_REG_ZAQ1:  | 
79  | 0  |   case AARCH64_REG_ZAQ2:  | 
80  | 0  |   case AARCH64_REG_ZAQ3:  | 
81  | 0  |   case AARCH64_REG_ZAQ4:  | 
82  | 0  |   case AARCH64_REG_ZAQ5:  | 
83  | 0  |   case AARCH64_REG_ZAQ6:  | 
84  | 0  |   case AARCH64_REG_ZAQ7:  | 
85  | 0  |   case AARCH64_REG_ZAQ8:  | 
86  | 0  |   case AARCH64_REG_ZAQ9:  | 
87  | 0  |   case AARCH64_REG_ZAQ10:  | 
88  | 0  |   case AARCH64_REG_ZAQ11:  | 
89  | 0  |   case AARCH64_REG_ZAQ12:  | 
90  | 0  |   case AARCH64_REG_ZAQ13:  | 
91  | 0  |   case AARCH64_REG_ZAQ14:  | 
92  | 0  |   case AARCH64_REG_ZAQ15:  | 
93  | 0  |     return AARCH64LAYOUT_VL_Q;  | 
94  | 0  |   case AARCH64_REG_ZA:  | 
95  | 0  |     return AARCH64LAYOUT_VL_COMPLETE;  | 
96  | 0  |   }  | 
97  | 0  | }  | 
98  |  |  | 
99  |  | void AArch64_init_mri(MCRegisterInfo *MRI)  | 
100  | 11.9k  | { | 
101  | 11.9k  |   MCRegisterInfo_InitMCRegisterInfo(  | 
102  | 11.9k  |     MRI, AArch64RegDesc, AARCH64_REG_ENDING, 0, 0,  | 
103  | 11.9k  |     AArch64MCRegisterClasses, ARR_SIZE(AArch64MCRegisterClasses), 0,  | 
104  | 11.9k  |     0, AArch64RegDiffLists, 0, AArch64SubRegIdxLists,  | 
105  | 11.9k  |     ARR_SIZE(AArch64SubRegIdxLists), 0);  | 
106  | 11.9k  | }  | 
107  |  |  | 
108  |  | /// Sets up a new SME matrix operand at the currently active detail operand.  | 
109  |  | static void setup_sme_operand(MCInst *MI)  | 
110  | 35.0k  | { | 
111  | 35.0k  |   if (!detail_is_set(MI))  | 
112  | 0  |     return;  | 
113  |  |  | 
114  | 35.0k  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;  | 
115  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_INVALID;  | 
116  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.tile = AARCH64_REG_INVALID;  | 
117  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.slice_reg = AARCH64_REG_INVALID;  | 
118  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm =  | 
119  | 35.0k  |     AARCH64_SLICE_IMM_INVALID;  | 
120  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =  | 
121  | 35.0k  |     AARCH64_SLICE_IMM_RANGE_INVALID;  | 
122  | 35.0k  |   AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset =  | 
123  | 35.0k  |     AARCH64_SLICE_IMM_RANGE_INVALID;  | 
124  | 35.0k  | }  | 
125  |  |  | 
126  |  | static void setup_pred_operand(MCInst *MI)  | 
127  | 94.0k  | { | 
128  | 94.0k  |   if (!detail_is_set(MI))  | 
129  | 0  |     return;  | 
130  |  |  | 
131  | 94.0k  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_PRED;  | 
132  | 94.0k  |   AArch64_get_detail_op(MI, 0)->pred.imm_index = -1;  | 
133  | 94.0k  | }  | 
134  |  |  | 
135  |  | const insn_map aarch64_insns[] = { | 
136  |  | #include "AArch64GenCSMappingInsn.inc"  | 
137  |  | };  | 
138  |  |  | 
139  |  | static const name_map insn_alias_mnem_map[] = { | 
140  |  | #include "AArch64GenCSAliasMnemMap.inc"  | 
141  |  |   { AARCH64_INS_ALIAS_CFP, "cfp" }, | 
142  |  |   { AARCH64_INS_ALIAS_DVP, "dvp" }, | 
143  |  |   { AARCH64_INS_ALIAS_COSP, "cosp" }, | 
144  |  |   { AARCH64_INS_ALIAS_CPP, "cpp" }, | 
145  |  |   { AARCH64_INS_ALIAS_IC, "ic" }, | 
146  |  |   { AARCH64_INS_ALIAS_DC, "dc" }, | 
147  |  |   { AARCH64_INS_ALIAS_AT, "at" }, | 
148  |  |   { AARCH64_INS_ALIAS_TLBI, "tlbi" }, | 
149  |  |   { AARCH64_INS_ALIAS_TLBIP, "tlbip" }, | 
150  |  |   { AARCH64_INS_ALIAS_RPRFM, "rprfm" }, | 
151  |  |   { AARCH64_INS_ALIAS_LSL, "lsl" }, | 
152  |  |   { AARCH64_INS_ALIAS_SBFX, "sbfx" }, | 
153  |  |   { AARCH64_INS_ALIAS_UBFX, "ubfx" }, | 
154  |  |   { AARCH64_INS_ALIAS_SBFIZ, "sbfiz" }, | 
155  |  |   { AARCH64_INS_ALIAS_UBFIZ, "ubfiz" }, | 
156  |  |   { AARCH64_INS_ALIAS_BFC, "bfc" }, | 
157  |  |   { AARCH64_INS_ALIAS_BFI, "bfi" }, | 
158  |  |   { AARCH64_INS_ALIAS_BFXIL, "bfxil" }, | 
159  |  |   { AARCH64_INS_ALIAS_END, NULL }, | 
160  |  | };  | 
161  |  |  | 
162  |  | static const char *get_custom_reg_alias(unsigned reg)  | 
163  | 82.4k  | { | 
164  | 82.4k  |   switch (reg) { | 
165  | 392  |   case AARCH64_REG_X29:  | 
166  | 392  |     return "fp";  | 
167  | 2.35k  |   case AARCH64_REG_X30:  | 
168  | 2.35k  |     return "lr";  | 
169  | 82.4k  |   }  | 
170  | 79.7k  |   return NULL;  | 
171  | 82.4k  | }  | 
172  |  |  | 
173  |  | /// Very annoyingly LLVM hard codes the vector layout post-fixes into the asm string.  | 
174  |  | /// In this function we check for these cases and add the vectorlayout/arrangement  | 
175  |  | /// specifier.  | 
176  |  | void AArch64_add_vas(MCInst *MI, const SStream *OS)  | 
177  | 386k  | { | 
178  | 386k  |   if (!detail_is_set(MI)) { | 
179  | 0  |     return;  | 
180  | 0  |   }  | 
181  |  |  | 
182  | 386k  |   if (AArch64_get_detail(MI)->op_count == 0) { | 
183  | 2.18k  |     return;  | 
184  | 2.18k  |   }  | 
185  | 384k  |   if (MCInst_getOpcode(MI) == AArch64_MUL53HI ||  | 
186  | 384k  |       MCInst_getOpcode(MI) == AArch64_MUL53LO) { | 
187  |  |     // Proprietary Apple instrucions.  | 
188  | 0  |     AArch64_get_detail(MI)->operands[0].vas = AARCH64LAYOUT_VL_2D;  | 
189  | 0  |     AArch64_get_detail(MI)->operands[1].vas = AARCH64LAYOUT_VL_2D;  | 
190  | 0  |     return;  | 
191  | 0  |   }  | 
192  |  |  | 
193  |  |   // Search for r".[0-9]{1,2}[bhsdq]\W" | 
194  |  |   // with poor mans regex  | 
195  | 384k  |   const char *vl_ptr = strchr(OS->buffer, '.');  | 
196  | 861k  |   while (vl_ptr) { | 
197  |  |     // Number after dot?  | 
198  | 476k  |     unsigned num = 0;  | 
199  | 476k  |     if (strchr("1248", vl_ptr[1])) { | 
200  | 107k  |       num = atoi(vl_ptr + 1);  | 
201  | 107k  |       vl_ptr = num > 9 ? vl_ptr + 3 : vl_ptr + 2;  | 
202  | 369k  |     } else { | 
203  | 369k  |       vl_ptr++;  | 
204  | 369k  |     }  | 
205  |  |  | 
206  |  |     // Layout letter  | 
207  | 476k  |     char letter = '\0';  | 
208  | 476k  |     if (strchr("bhsdq", vl_ptr[0])) { | 
209  | 461k  |       letter = vl_ptr[0];  | 
210  | 461k  |     }  | 
211  | 476k  |     if (!letter) { | 
212  | 15.0k  |       goto next_dot_continue;  | 
213  | 15.0k  |     }  | 
214  |  |  | 
215  | 461k  |     AArch64Layout_VectorLayout vl = AARCH64LAYOUT_INVALID;  | 
216  | 461k  |     switch (letter) { | 
217  | 0  |     default:  | 
218  | 0  |       CS_ASSERT_RET(0 && "Unhandled vector layout letter.");  | 
219  | 0  |       return;  | 
220  | 113k  |     case 'b':  | 
221  | 113k  |       vl = AARCH64LAYOUT_VL_B;  | 
222  | 113k  |       break;  | 
223  | 117k  |     case 'h':  | 
224  | 117k  |       vl = AARCH64LAYOUT_VL_H;  | 
225  | 117k  |       break;  | 
226  | 107k  |     case 's':  | 
227  | 107k  |       vl = AARCH64LAYOUT_VL_S;  | 
228  | 107k  |       break;  | 
229  | 115k  |     case 'd':  | 
230  | 115k  |       vl = AARCH64LAYOUT_VL_D;  | 
231  | 115k  |       break;  | 
232  | 8.21k  |     case 'q':  | 
233  | 8.21k  |       vl = AARCH64LAYOUT_VL_Q;  | 
234  | 8.21k  |       break;  | 
235  | 461k  |     }  | 
236  | 461k  |     vl |= (num << 8);  | 
237  |  |  | 
238  |  |     // Determine op index by searching for trailing commata after op string  | 
239  | 461k  |     uint32_t op_idx = 0;  | 
240  | 461k  |     const char *comma_ptr = strchr(OS->buffer, ',');  | 
241  | 461k  |     ;  | 
242  | 996k  |     while (comma_ptr && comma_ptr < vl_ptr) { | 
243  | 534k  |       ++op_idx;  | 
244  | 534k  |       comma_ptr = strchr(comma_ptr + 1, ',');  | 
245  | 534k  |     }  | 
246  | 461k  |     if (!comma_ptr) { | 
247  |  |       // Last op doesn't have a trailing commata.  | 
248  | 66.5k  |       op_idx = AArch64_get_detail(MI)->op_count - 1;  | 
249  | 66.5k  |     }  | 
250  | 461k  |     if (op_idx >= AArch64_get_detail(MI)->op_count) { | 
251  |  |       // A memory operand with a commata in [base, dist]  | 
252  | 13.1k  |       op_idx = AArch64_get_detail(MI)->op_count - 1;  | 
253  | 13.1k  |     }  | 
254  |  |  | 
255  |  |     // Search for the operand this one belongs to.  | 
256  | 461k  |     cs_aarch64_op *op = &AArch64_get_detail(MI)->operands[op_idx];  | 
257  | 461k  |     if ((op->type != AARCH64_OP_REG &&  | 
258  | 66.6k  |          op->type != AARCH64_OP_SME) ||  | 
259  | 422k  |         op->vas != AARCH64LAYOUT_INVALID) { | 
260  | 370k  |       goto next_dot_continue;  | 
261  | 370k  |     }  | 
262  | 91.4k  |     op->vas = vl;  | 
263  |  |  | 
264  | 476k  | next_dot_continue:  | 
265  | 476k  |     vl_ptr = strchr(vl_ptr + 1, '.');  | 
266  | 476k  |   }  | 
267  | 384k  | }  | 
268  |  |  | 
269  |  | const char *AArch64_reg_name(csh handle, unsigned int reg)  | 
270  | 82.4k  | { | 
271  | 82.4k  |   int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;  | 
272  | 82.4k  |   const char *alias = get_custom_reg_alias(reg);  | 
273  | 82.4k  |   if ((syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS) && alias)  | 
274  | 0  |     return alias;  | 
275  |  |  | 
276  | 82.4k  |   if (((cs_struct *)(uintptr_t)handle)->syntax &  | 
277  | 82.4k  |       CS_OPT_SYNTAX_NOREGNAME) { | 
278  | 0  |     return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);  | 
279  | 0  |   }  | 
280  |  |   // TODO Add options for the other register names  | 
281  | 82.4k  |   return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);  | 
282  | 82.4k  | }  | 
283  |  |  | 
284  |  | void AArch64_setup_op(cs_aarch64_op *op)  | 
285  | 6.30M  | { | 
286  | 6.30M  |   memset(op, 0, sizeof(cs_aarch64_op));  | 
287  | 6.30M  |   op->type = AARCH64_OP_INVALID;  | 
288  | 6.30M  |   op->vector_index = -1;  | 
289  | 6.30M  | }  | 
290  |  |  | 
291  |  | void AArch64_init_cs_detail(MCInst *MI)  | 
292  | 392k  | { | 
293  | 392k  |   if (detail_is_set(MI)) { | 
294  | 392k  |     memset(get_detail(MI), 0,  | 
295  | 392k  |            offsetof(cs_detail, aarch64) + sizeof(cs_aarch64));  | 
296  | 6.67M  |     for (int i = 0; i < ARR_SIZE(AArch64_get_detail(MI)->operands);  | 
297  | 6.28M  |          i++)  | 
298  | 6.28M  |       AArch64_setup_op(&AArch64_get_detail(MI)->operands[i]);  | 
299  | 392k  |     AArch64_get_detail(MI)->cc = AArch64CC_Invalid;  | 
300  | 392k  |   }  | 
301  | 392k  | }  | 
302  |  |  | 
303  |  | /// Unfortunately, the AARCH64 definitions do not indicate in any way  | 
304  |  | /// (exception are the instruction identifiers), if memory accesses  | 
305  |  | /// is post- or pre-indexed.  | 
306  |  | /// So the only generic way to determine, if the memory access is in  | 
307  |  | /// post-indexed addressing mode, is by search for "<membase>], #<memdisp>" in  | 
308  |  | /// @p OS.  | 
309  |  | /// Searching the asm string to determine such a property is enormously ugly  | 
310  |  | /// and wastes resources.  | 
311  |  | /// Sorry, I know and do feel bad about it. But for now it works.  | 
312  |  | static bool AArch64_check_post_index_am(const MCInst *MI, const SStream *OS)  | 
313  | 386k  | { | 
314  | 386k  |   if (AArch64_get_detail(MI)->post_index) { | 
315  | 0  |     return true;  | 
316  | 0  |   }  | 
317  | 386k  |   cs_aarch64_op *memop = NULL;  | 
318  | 1.38M  |   for (int i = 0; i < AArch64_get_detail(MI)->op_count; ++i) { | 
319  | 1.12M  |     if (AArch64_get_detail(MI)->operands[i].type & CS_OP_MEM) { | 
320  | 125k  |       memop = &AArch64_get_detail(MI)->operands[i];  | 
321  | 125k  |       break;  | 
322  | 125k  |     }  | 
323  | 1.12M  |   }  | 
324  | 386k  |   if (!memop)  | 
325  | 260k  |     return false;  | 
326  | 125k  |   if (memop->mem.base == AARCH64_REG_INVALID) { | 
327  |  |     // Load/Store from/to label. Has no register base.  | 
328  | 4.42k  |     return false;  | 
329  | 4.42k  |   }  | 
330  | 121k  |   const char *membase = AArch64_LLVM_getRegisterName(  | 
331  | 121k  |     memop->mem.base, AArch64_NoRegAltName);  | 
332  | 121k  |   int64_t memdisp = memop->mem.disp;  | 
333  | 121k  |   SStream pattern = { 0 }; | 
334  | 121k  |   SStream_concat(&pattern, membase);  | 
335  | 121k  |   SStream_concat(&pattern, "], ");  | 
336  | 121k  |   printInt32Bang(&pattern, memdisp);  | 
337  | 121k  |   return strstr(OS->buffer, pattern.buffer) != NULL;  | 
338  | 125k  | }  | 
339  |  |  | 
340  |  | static void AArch64_check_updates_flags(MCInst *MI)  | 
341  | 386k  | { | 
342  | 386k  | #ifndef CAPSTONE_DIET  | 
343  | 386k  |   if (!detail_is_set(MI))  | 
344  | 0  |     return;  | 
345  | 386k  |   cs_detail *detail = get_detail(MI);  | 
346  |  |   // Implicitly written registers  | 
347  | 423k  |   for (int i = 0; i < detail->regs_write_count; ++i) { | 
348  | 56.8k  |     if (detail->regs_write[i] == 0)  | 
349  | 0  |       break;  | 
350  | 93.6k  |     for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j) { | 
351  | 56.8k  |       if (detail->regs_write[i] == aarch64_flag_regs[j]) { | 
352  | 20.1k  |         detail->aarch64.update_flags = true;  | 
353  | 20.1k  |         return;  | 
354  | 20.1k  |       }  | 
355  | 56.8k  |     }  | 
356  | 56.8k  |   }  | 
357  | 1.44M  |   for (int i = 0; i < detail->aarch64.op_count; ++i) { | 
358  | 1.08M  |     if (detail->aarch64.operands[i].type == AARCH64_OP_SYSREG &&  | 
359  | 12.3k  |         detail->aarch64.operands[i].sysop.sub_type ==  | 
360  | 12.3k  |           AARCH64_OP_REG_MSR) { | 
361  | 37.6k  |       for (int j = 0; j < ARR_SIZE(aarch64_flag_sys_regs);  | 
362  | 31.2k  |            ++j)  | 
363  | 31.4k  |         if (detail->aarch64.operands[i]  | 
364  | 31.4k  |               .sysop.reg.sysreg ==  | 
365  | 31.4k  |             aarch64_flag_sys_regs[j]) { | 
366  | 155  |           detail->aarch64.update_flags = true;  | 
367  | 155  |           return;  | 
368  | 155  |         }  | 
369  | 1.07M  |     } else if (detail->aarch64.operands[i].type == AARCH64_OP_REG &&  | 
370  | 683k  |          detail->aarch64.operands[i].access & CS_AC_WRITE) { | 
371  | 652k  |       for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j)  | 
372  | 326k  |         if (detail->aarch64.operands[i].reg ==  | 
373  | 326k  |             aarch64_flag_regs[j]) { | 
374  | 0  |           detail->aarch64.update_flags = true;  | 
375  | 0  |           return;  | 
376  | 0  |         }  | 
377  | 326k  |     }  | 
378  | 1.08M  |   }  | 
379  | 366k  | #endif // CAPSTONE_DIET  | 
380  | 366k  | }  | 
381  |  |  | 
382  |  | static aarch64_shifter id_to_shifter(unsigned Opcode)  | 
383  | 591  | { | 
384  | 591  |   switch (Opcode) { | 
385  | 0  |   default:  | 
386  | 0  |     return AARCH64_SFT_INVALID;  | 
387  | 70  |   case AArch64_RORVXr:  | 
388  | 139  |   case AArch64_RORVWr:  | 
389  | 139  |     return AARCH64_SFT_ROR_REG;  | 
390  | 67  |   case AArch64_LSRVXr:  | 
391  | 101  |   case AArch64_LSRVWr:  | 
392  | 101  |     return AARCH64_SFT_LSR_REG;  | 
393  | 197  |   case AArch64_LSLVXr:  | 
394  | 237  |   case AArch64_LSLVWr:  | 
395  | 237  |     return AARCH64_SFT_LSL_REG;  | 
396  | 41  |   case AArch64_ASRVXr:  | 
397  | 114  |   case AArch64_ASRVWr:  | 
398  | 114  |     return AARCH64_SFT_ASR_REG;  | 
399  | 591  |   }  | 
400  | 591  | }  | 
401  |  |  | 
402  |  | static void add_non_alias_details(MCInst *MI)  | 
403  | 325k  | { | 
404  | 325k  |   unsigned Opcode = MCInst_getOpcode(MI);  | 
405  | 325k  |   switch (Opcode) { | 
406  | 307k  |   default:  | 
407  | 307k  |     break;  | 
408  | 307k  |   case AArch64_RORVXr:  | 
409  | 139  |   case AArch64_RORVWr:  | 
410  | 206  |   case AArch64_LSRVXr:  | 
411  | 240  |   case AArch64_LSRVWr:  | 
412  | 437  |   case AArch64_LSLVXr:  | 
413  | 477  |   case AArch64_LSLVWr:  | 
414  | 518  |   case AArch64_ASRVXr:  | 
415  | 591  |   case AArch64_ASRVWr:  | 
416  | 591  |     if (AArch64_get_detail(MI)->op_count != 3) { | 
417  | 0  |       return;  | 
418  | 0  |     }  | 
419  | 591  |     CS_ASSERT_RET(AArch64_get_detail_op(MI, -1)->type ==  | 
420  | 591  |             AARCH64_OP_REG);  | 
421  |  |  | 
422  |  |     // The shift by register instructions don't set the shift value properly.  | 
423  |  |     // Correct it here.  | 
424  | 591  |     uint64_t shift = AArch64_get_detail_op(MI, -1)->reg;  | 
425  | 591  |     cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);  | 
426  | 591  |     op1->shift.type = id_to_shifter(Opcode);  | 
427  | 591  |     op1->shift.value = shift;  | 
428  | 591  |     AArch64_dec_op_count(MI);  | 
429  | 591  |     break;  | 
430  | 465  |   case AArch64_FCMPDri:  | 
431  | 995  |   case AArch64_FCMPEDri:  | 
432  | 1.33k  |   case AArch64_FCMPEHri:  | 
433  | 1.53k  |   case AArch64_FCMPESri:  | 
434  | 1.98k  |   case AArch64_FCMPHri:  | 
435  | 2.02k  |   case AArch64_FCMPSri:  | 
436  | 2.02k  |     AArch64_insert_detail_op_reg_at(MI, -1, AARCH64_REG_XZR,  | 
437  | 2.02k  |             CS_AC_READ);  | 
438  | 2.02k  |     break;  | 
439  | 105  |   case AArch64_CMEQv16i8rz:  | 
440  | 188  |   case AArch64_CMEQv1i64rz:  | 
441  | 256  |   case AArch64_CMEQv2i32rz:  | 
442  | 345  |   case AArch64_CMEQv2i64rz:  | 
443  | 411  |   case AArch64_CMEQv4i16rz:  | 
444  | 546  |   case AArch64_CMEQv4i32rz:  | 
445  | 619  |   case AArch64_CMEQv8i16rz:  | 
446  | 867  |   case AArch64_CMEQv8i8rz:  | 
447  | 885  |   case AArch64_CMGEv16i8rz:  | 
448  | 951  |   case AArch64_CMGEv1i64rz:  | 
449  | 1.47k  |   case AArch64_CMGEv2i32rz:  | 
450  | 1.67k  |   case AArch64_CMGEv2i64rz:  | 
451  | 1.70k  |   case AArch64_CMGEv4i16rz:  | 
452  | 1.77k  |   case AArch64_CMGEv4i32rz:  | 
453  | 1.85k  |   case AArch64_CMGEv8i16rz:  | 
454  | 2.65k  |   case AArch64_CMGEv8i8rz:  | 
455  | 2.89k  |   case AArch64_CMGTv16i8rz:  | 
456  | 3.01k  |   case AArch64_CMGTv1i64rz:  | 
457  | 3.14k  |   case AArch64_CMGTv2i32rz:  | 
458  | 3.87k  |   case AArch64_CMGTv2i64rz:  | 
459  | 3.91k  |   case AArch64_CMGTv4i16rz:  | 
460  | 3.95k  |   case AArch64_CMGTv4i32rz:  | 
461  | 4.12k  |   case AArch64_CMGTv8i16rz:  | 
462  | 4.40k  |   case AArch64_CMGTv8i8rz:  | 
463  | 4.59k  |   case AArch64_CMLEv16i8rz:  | 
464  | 4.66k  |   case AArch64_CMLEv1i64rz:  | 
465  | 4.70k  |   case AArch64_CMLEv2i32rz:  | 
466  | 4.77k  |   case AArch64_CMLEv2i64rz:  | 
467  | 4.83k  |   case AArch64_CMLEv4i16rz:  | 
468  | 4.90k  |   case AArch64_CMLEv4i32rz:  | 
469  | 5.09k  |   case AArch64_CMLEv8i16rz:  | 
470  | 5.38k  |   case AArch64_CMLEv8i8rz:  | 
471  | 5.45k  |   case AArch64_CMLTv16i8rz:  | 
472  | 5.47k  |   case AArch64_CMLTv1i64rz:  | 
473  | 5.54k  |   case AArch64_CMLTv2i32rz:  | 
474  | 6.42k  |   case AArch64_CMLTv2i64rz:  | 
475  | 6.45k  |   case AArch64_CMLTv4i16rz:  | 
476  | 6.49k  |   case AArch64_CMLTv4i32rz:  | 
477  | 6.56k  |   case AArch64_CMLTv8i16rz:  | 
478  | 6.60k  |   case AArch64_CMLTv8i8rz:  | 
479  | 6.60k  |     AArch64_insert_detail_op_imm_at(MI, -1, 0);  | 
480  | 6.60k  |     break;  | 
481  | 39  |   case AArch64_FCMEQ_PPzZ0_D:  | 
482  | 106  |   case AArch64_FCMEQ_PPzZ0_H:  | 
483  | 140  |   case AArch64_FCMEQ_PPzZ0_S:  | 
484  | 787  |   case AArch64_FCMEQv1i16rz:  | 
485  | 824  |   case AArch64_FCMEQv1i32rz:  | 
486  | 902  |   case AArch64_FCMEQv1i64rz:  | 
487  | 973  |   case AArch64_FCMEQv2i32rz:  | 
488  | 1.03k  |   case AArch64_FCMEQv2i64rz:  | 
489  | 1.10k  |   case AArch64_FCMEQv4i16rz:  | 
490  | 1.14k  |   case AArch64_FCMEQv4i32rz:  | 
491  | 1.32k  |   case AArch64_FCMEQv8i16rz:  | 
492  | 1.75k  |   case AArch64_FCMGE_PPzZ0_D:  | 
493  | 1.82k  |   case AArch64_FCMGE_PPzZ0_H:  | 
494  | 1.85k  |   case AArch64_FCMGE_PPzZ0_S:  | 
495  | 2.35k  |   case AArch64_FCMGEv1i16rz:  | 
496  | 2.44k  |   case AArch64_FCMGEv1i32rz:  | 
497  | 2.47k  |   case AArch64_FCMGEv1i64rz:  | 
498  | 3.10k  |   case AArch64_FCMGEv2i32rz:  | 
499  | 3.13k  |   case AArch64_FCMGEv2i64rz:  | 
500  | 3.20k  |   case AArch64_FCMGEv4i16rz:  | 
501  | 3.47k  |   case AArch64_FCMGEv4i32rz:  | 
502  | 3.53k  |   case AArch64_FCMGEv8i16rz:  | 
503  | 3.68k  |   case AArch64_FCMGT_PPzZ0_D:  | 
504  | 3.76k  |   case AArch64_FCMGT_PPzZ0_H:  | 
505  | 3.83k  |   case AArch64_FCMGT_PPzZ0_S:  | 
506  | 3.86k  |   case AArch64_FCMGTv1i16rz:  | 
507  | 3.99k  |   case AArch64_FCMGTv1i32rz:  | 
508  | 4.05k  |   case AArch64_FCMGTv1i64rz:  | 
509  | 4.77k  |   case AArch64_FCMGTv2i32rz:  | 
510  | 4.97k  |   case AArch64_FCMGTv2i64rz:  | 
511  | 5.17k  |   case AArch64_FCMGTv4i16rz:  | 
512  | 5.39k  |   case AArch64_FCMGTv4i32rz:  | 
513  | 5.49k  |   case AArch64_FCMGTv8i16rz:  | 
514  | 5.56k  |   case AArch64_FCMLE_PPzZ0_D:  | 
515  | 5.63k  |   case AArch64_FCMLE_PPzZ0_H:  | 
516  | 6.48k  |   case AArch64_FCMLE_PPzZ0_S:  | 
517  | 6.55k  |   case AArch64_FCMLEv1i16rz:  | 
518  | 6.58k  |   case AArch64_FCMLEv1i32rz:  | 
519  | 6.62k  |   case AArch64_FCMLEv1i64rz:  | 
520  | 6.70k  |   case AArch64_FCMLEv2i32rz:  | 
521  | 6.77k  |   case AArch64_FCMLEv2i64rz:  | 
522  | 6.81k  |   case AArch64_FCMLEv4i16rz:  | 
523  | 6.84k  |   case AArch64_FCMLEv4i32rz:  | 
524  | 6.91k  |   case AArch64_FCMLEv8i16rz:  | 
525  | 6.94k  |   case AArch64_FCMLT_PPzZ0_D:  | 
526  | 6.98k  |   case AArch64_FCMLT_PPzZ0_H:  | 
527  | 7.11k  |   case AArch64_FCMLT_PPzZ0_S:  | 
528  | 7.49k  |   case AArch64_FCMLTv1i16rz:  | 
529  | 7.52k  |   case AArch64_FCMLTv1i32rz:  | 
530  | 7.55k  |   case AArch64_FCMLTv1i64rz:  | 
531  | 7.76k  |   case AArch64_FCMLTv2i32rz:  | 
532  | 7.83k  |   case AArch64_FCMLTv2i64rz:  | 
533  | 7.90k  |   case AArch64_FCMLTv4i16rz:  | 
534  | 7.97k  |   case AArch64_FCMLTv4i32rz:  | 
535  | 9.00k  |   case AArch64_FCMLTv8i16rz:  | 
536  | 9.07k  |   case AArch64_FCMNE_PPzZ0_D:  | 
537  | 9.14k  |   case AArch64_FCMNE_PPzZ0_H:  | 
538  | 9.17k  |   case AArch64_FCMNE_PPzZ0_S: { | 
539  | 9.17k  |     aarch64_sysop sysop = { 0 }; | 
540  | 9.17k  |     sysop.imm.exactfpimm = AARCH64_EXACTFPIMM_ZERO;  | 
541  | 9.17k  |     sysop.sub_type = AARCH64_OP_EXACTFPIMM;  | 
542  | 9.17k  |     AArch64_insert_detail_op_sys(MI, -1, sysop, AARCH64_OP_SYSIMM);  | 
543  | 9.17k  |     break;  | 
544  | 9.14k  |   }  | 
545  | 325k  |   }  | 
546  | 325k  | }  | 
547  |  |  | 
548  |  | #define ADD_ZA0_S \  | 
549  | 374  |   { \ | 
550  | 374  |     aarch64_op_sme za0_op = { \ | 
551  | 374  |       .type = AARCH64_SME_OP_TILE, \  | 
552  | 374  |       .tile = AARCH64_REG_ZAS0, \  | 
553  | 374  |       .slice_reg = AARCH64_REG_INVALID, \  | 
554  | 374  |       .slice_offset = { -1 }, \ | 
555  | 374  |       .has_range_offset = false, \  | 
556  | 374  |       .is_vertical = false, \  | 
557  | 374  |     }; \  | 
558  | 374  |     AArch64_insert_detail_op_sme(MI, -1, za0_op); \  | 
559  | 374  |     AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \  | 
560  | 374  |     AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \  | 
561  | 374  |   }  | 
562  |  | #define ADD_ZA1_S \  | 
563  | 1.08k  |   { \ | 
564  | 1.08k  |     aarch64_op_sme za1_op = { \ | 
565  | 1.08k  |       .type = AARCH64_SME_OP_TILE, \  | 
566  | 1.08k  |       .tile = AARCH64_REG_ZAS1, \  | 
567  | 1.08k  |       .slice_reg = AARCH64_REG_INVALID, \  | 
568  | 1.08k  |       .slice_offset = { -1 }, \ | 
569  | 1.08k  |       .has_range_offset = false, \  | 
570  | 1.08k  |       .is_vertical = false, \  | 
571  | 1.08k  |     }; \  | 
572  | 1.08k  |     AArch64_insert_detail_op_sme(MI, -1, za1_op); \  | 
573  | 1.08k  |     AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \  | 
574  | 1.08k  |     AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \  | 
575  | 1.08k  |   }  | 
576  |  | #define ADD_ZA2_S \  | 
577  | 1.11k  |   { \ | 
578  | 1.11k  |     aarch64_op_sme za2_op = { \ | 
579  | 1.11k  |       .type = AARCH64_SME_OP_TILE, \  | 
580  | 1.11k  |       .tile = AARCH64_REG_ZAS2, \  | 
581  | 1.11k  |       .slice_reg = AARCH64_REG_INVALID, \  | 
582  | 1.11k  |       .slice_offset = { -1 }, \ | 
583  | 1.11k  |       .has_range_offset = false, \  | 
584  | 1.11k  |       .is_vertical = false, \  | 
585  | 1.11k  |     }; \  | 
586  | 1.11k  |     AArch64_insert_detail_op_sme(MI, -1, za2_op); \  | 
587  | 1.11k  |     AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \  | 
588  | 1.11k  |     AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \  | 
589  | 1.11k  |   }  | 
590  |  | #define ADD_ZA3_S \  | 
591  | 1.20k  |   { \ | 
592  | 1.20k  |     aarch64_op_sme za3_op = { \ | 
593  | 1.20k  |       .type = AARCH64_SME_OP_TILE, \  | 
594  | 1.20k  |       .tile = AARCH64_REG_ZAS3, \  | 
595  | 1.20k  |       .slice_reg = AARCH64_REG_INVALID, \  | 
596  | 1.20k  |       .slice_offset = { -1 }, \ | 
597  | 1.20k  |       .has_range_offset = false, \  | 
598  | 1.20k  |       .is_vertical = false, \  | 
599  | 1.20k  |     }; \  | 
600  | 1.20k  |     AArch64_insert_detail_op_sme(MI, -1, za3_op); \  | 
601  | 1.20k  |     AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \  | 
602  | 1.20k  |     AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \  | 
603  | 1.20k  |   }  | 
604  |  | #define ADD_ZA \  | 
605  | 79  |   { \ | 
606  | 79  |     aarch64_op_sme za_op = { \ | 
607  | 79  |       .type = AARCH64_SME_OP_TILE, \  | 
608  | 79  |       .tile = AARCH64_REG_ZA, \  | 
609  | 79  |       .slice_reg = AARCH64_REG_INVALID, \  | 
610  | 79  |       .slice_offset = { -1 }, \ | 
611  | 79  |       .has_range_offset = false, \  | 
612  | 79  |       .is_vertical = false, \  | 
613  | 79  |     }; \  | 
614  | 79  |     AArch64_insert_detail_op_sme(MI, -1, za_op); \  | 
615  | 79  |     AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \  | 
616  | 79  |   }  | 
617  |  |  | 
618  |  | static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)  | 
619  | 386k  | { | 
620  | 386k  |   if (!detail_is_set(MI))  | 
621  | 0  |     return;  | 
622  |  |  | 
623  | 386k  |   if (!MI->flat_insn->is_alias || !MI->flat_insn->usesAliasDetails) { | 
624  | 325k  |     add_non_alias_details(MI);  | 
625  | 325k  |     return;  | 
626  | 325k  |   }  | 
627  |  |  | 
628  |  |   // Alias details  | 
629  | 60.7k  |   switch (MI->flat_insn->alias_id) { | 
630  | 51.7k  |   default:  | 
631  | 51.7k  |     return;  | 
632  | 51.7k  |   case AARCH64_INS_ALIAS_ROR:  | 
633  | 316  |     if (AArch64_get_detail(MI)->op_count != 3) { | 
634  | 0  |       return;  | 
635  | 0  |     }  | 
636  |  |     // The ROR alias doesn't set the shift value properly.  | 
637  |  |     // Correct it here.  | 
638  | 316  |     bool reg_shift = AArch64_get_detail_op(MI, -1)->type ==  | 
639  | 316  |          AARCH64_OP_REG;  | 
640  | 316  |     uint64_t shift = reg_shift ?  | 
641  | 0  |            AArch64_get_detail_op(MI, -1)->reg :  | 
642  | 316  |            AArch64_get_detail_op(MI, -1)->imm;  | 
643  | 316  |     cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);  | 
644  | 316  |     op1->shift.type = reg_shift ? AARCH64_SFT_ROR_REG :  | 
645  | 316  |                 AARCH64_SFT_ROR;  | 
646  | 316  |     op1->shift.value = shift;  | 
647  | 316  |     AArch64_dec_op_count(MI);  | 
648  | 316  |     break;  | 
649  | 152  |   case AARCH64_INS_ALIAS_FMOV:  | 
650  | 152  |     if (AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_FP) { | 
651  | 152  |       break;  | 
652  | 152  |     }  | 
653  | 0  |     AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);  | 
654  | 0  |     break;  | 
655  | 90  |   case AARCH64_INS_ALIAS_LD1:  | 
656  | 196  |   case AARCH64_INS_ALIAS_LD1R:  | 
657  | 1.19k  |   case AARCH64_INS_ALIAS_LD2:  | 
658  | 1.59k  |   case AARCH64_INS_ALIAS_LD2R:  | 
659  | 1.94k  |   case AARCH64_INS_ALIAS_LD3:  | 
660  | 2.15k  |   case AARCH64_INS_ALIAS_LD3R:  | 
661  | 3.79k  |   case AARCH64_INS_ALIAS_LD4:  | 
662  | 4.21k  |   case AARCH64_INS_ALIAS_LD4R:  | 
663  | 5.39k  |   case AARCH64_INS_ALIAS_ST1:  | 
664  | 5.57k  |   case AARCH64_INS_ALIAS_ST2:  | 
665  | 5.70k  |   case AARCH64_INS_ALIAS_ST3:  | 
666  | 6.56k  |   case AARCH64_INS_ALIAS_ST4: { | 
667  |  |     // Add post-index disp  | 
668  | 6.56k  |     const char *disp_off = strrchr(OS->buffer, '#');  | 
669  | 6.56k  |     if (!disp_off)  | 
670  | 0  |       return;  | 
671  | 6.56k  |     unsigned disp = atoi(disp_off + 1);  | 
672  | 6.56k  |     AArch64_get_detail_op(MI, -1)->type = AARCH64_OP_MEM;  | 
673  | 6.56k  |     AArch64_get_detail_op(MI, -1)->mem.base =  | 
674  | 6.56k  |       AArch64_get_detail_op(MI, -1)->reg;  | 
675  | 6.56k  |     AArch64_get_detail_op(MI, -1)->mem.disp = disp;  | 
676  | 6.56k  |     AArch64_get_detail(MI)->post_index = true;  | 
677  | 6.56k  |     break;  | 
678  | 6.56k  |   }  | 
679  | 5  |   case AARCH64_INS_ALIAS_GCSB:  | 
680  |  |     // TODO  | 
681  |  |     // Only CSYNC is defined in LLVM. So we need to add it.  | 
682  |  |     //     /* 2825 */ "gcsb dsync\0"  | 
683  | 5  |     break;  | 
684  | 262  |   case AARCH64_INS_ALIAS_SMSTART:  | 
685  | 319  |   case AARCH64_INS_ALIAS_SMSTOP: { | 
686  | 319  |     const char *disp_off = NULL;  | 
687  | 319  |     disp_off = strstr(OS->buffer, "smstart\tza");  | 
688  | 319  |     if (disp_off) { | 
689  | 194  |       aarch64_sysop sysop = { 0 }; | 
690  | 194  |       sysop.alias.svcr = AARCH64_SVCR_SVCRZA;  | 
691  | 194  |       sysop.sub_type = AARCH64_OP_SVCR;  | 
692  | 194  |       AArch64_insert_detail_op_sys(MI, -1, sysop,  | 
693  | 194  |                  AARCH64_OP_SYSALIAS);  | 
694  | 194  |       return;  | 
695  | 194  |     }  | 
696  | 125  |     disp_off = strstr(OS->buffer, "smstart\tsm");  | 
697  | 125  |     if (disp_off) { | 
698  | 68  |       aarch64_sysop sysop = { 0 }; | 
699  | 68  |       sysop.alias.svcr = AARCH64_SVCR_SVCRSM;  | 
700  | 68  |       sysop.sub_type = AARCH64_OP_SVCR;  | 
701  | 68  |       AArch64_insert_detail_op_sys(MI, -1, sysop,  | 
702  | 68  |                  AARCH64_OP_SYSALIAS);  | 
703  | 68  |       return;  | 
704  | 68  |     }  | 
705  | 57  |     break;  | 
706  | 125  |   }  | 
707  | 1.65k  |   case AARCH64_INS_ALIAS_ZERO: { | 
708  |  |     // It is ugly, but the hard coded search patterns do it for now.  | 
709  | 1.65k  |     const char *disp_off = NULL;  | 
710  |  |  | 
711  | 1.65k  |     disp_off = strstr(OS->buffer, "{za}"); | 
712  | 1.65k  |     if (disp_off) { | 
713  | 79  |       ADD_ZA;  | 
714  | 79  |       return;  | 
715  | 79  |     }  | 
716  | 1.57k  |     disp_off = strstr(OS->buffer, "{za1.h}"); | 
717  | 1.57k  |     if (disp_off) { | 
718  | 76  |       aarch64_op_sme op = { | 
719  | 76  |         .type = AARCH64_SME_OP_TILE,  | 
720  | 76  |         .tile = AARCH64_REG_ZAH1,  | 
721  | 76  |         .slice_reg = AARCH64_REG_INVALID,  | 
722  | 76  |         .slice_offset = { -1 }, | 
723  | 76  |         .has_range_offset = false,  | 
724  | 76  |         .is_vertical = false,  | 
725  | 76  |       };  | 
726  | 76  |       AArch64_insert_detail_op_sme(MI, -1, op);  | 
727  | 76  |       AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_H;  | 
728  | 76  |       AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE;  | 
729  | 76  |       return;  | 
730  | 76  |     }  | 
731  | 1.50k  |     disp_off = strstr(OS->buffer, "{za0.h}"); | 
732  | 1.50k  |     if (disp_off) { | 
733  | 18  |       aarch64_op_sme op = { | 
734  | 18  |         .type = AARCH64_SME_OP_TILE,  | 
735  | 18  |         .tile = AARCH64_REG_ZAH0,  | 
736  | 18  |         .slice_reg = AARCH64_REG_INVALID,  | 
737  | 18  |         .slice_offset = { -1 }, | 
738  | 18  |         .has_range_offset = false,  | 
739  | 18  |         .is_vertical = false,  | 
740  | 18  |       };  | 
741  | 18  |       AArch64_insert_detail_op_sme(MI, -1, op);  | 
742  | 18  |       AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_H;  | 
743  | 18  |       AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE;  | 
744  | 18  |       return;  | 
745  | 18  |     }  | 
746  | 1.48k  |     disp_off = strstr(OS->buffer, "{za0.s}"); | 
747  | 1.48k  |     if (disp_off) { | 
748  | 35  |       ADD_ZA0_S;  | 
749  | 35  |       return;  | 
750  | 35  |     }  | 
751  | 1.44k  |     disp_off = strstr(OS->buffer, "{za1.s}"); | 
752  | 1.44k  |     if (disp_off) { | 
753  | 34  |       ADD_ZA1_S;  | 
754  | 34  |       return;  | 
755  | 34  |     }  | 
756  | 1.41k  |     disp_off = strstr(OS->buffer, "{za2.s}"); | 
757  | 1.41k  |     if (disp_off) { | 
758  | 70  |       ADD_ZA2_S;  | 
759  | 70  |       return;  | 
760  | 70  |     }  | 
761  | 1.34k  |     disp_off = strstr(OS->buffer, "{za3.s}"); | 
762  | 1.34k  |     if (disp_off) { | 
763  | 78  |       ADD_ZA3_S;  | 
764  | 78  |       return;  | 
765  | 78  |     }  | 
766  | 1.26k  |     disp_off = strstr(OS->buffer, "{za0.s,za1.s}"); | 
767  | 1.26k  |     if (disp_off) { | 
768  | 72  |       ADD_ZA0_S;  | 
769  | 72  |       ADD_ZA1_S;  | 
770  | 72  |       return;  | 
771  | 72  |     }  | 
772  | 1.19k  |     disp_off = strstr(OS->buffer, "{za0.s,za3.s}"); | 
773  | 1.19k  |     if (disp_off) { | 
774  | 66  |       ADD_ZA0_S;  | 
775  | 66  |       ADD_ZA3_S;  | 
776  | 66  |       return;  | 
777  | 66  |     }  | 
778  | 1.12k  |     disp_off = strstr(OS->buffer, "{za1.s,za2.s}"); | 
779  | 1.12k  |     if (disp_off) { | 
780  | 34  |       ADD_ZA1_S;  | 
781  | 34  |       ADD_ZA2_S;  | 
782  | 34  |       return;  | 
783  | 34  |     }  | 
784  | 1.09k  |     disp_off = strstr(OS->buffer, "{za2.s,za3.s}"); | 
785  | 1.09k  |     if (disp_off) { | 
786  | 66  |       ADD_ZA2_S;  | 
787  | 66  |       ADD_ZA3_S;  | 
788  | 66  |       return;  | 
789  | 66  |     }  | 
790  | 1.02k  |     disp_off = strstr(OS->buffer, "{za0.s,za1.s,za2.s}"); | 
791  | 1.02k  |     if (disp_off) { | 
792  | 34  |       ADD_ZA0_S;  | 
793  | 34  |       ADD_ZA1_S;  | 
794  | 34  |       ADD_ZA2_S;  | 
795  | 34  |       return;  | 
796  | 34  |     }  | 
797  | 993  |     disp_off = strstr(OS->buffer, "{za0.s,za1.s,za3.s}"); | 
798  | 993  |     if (disp_off) { | 
799  | 87  |       ADD_ZA0_S;  | 
800  | 87  |       ADD_ZA1_S;  | 
801  | 87  |       ADD_ZA3_S;  | 
802  | 87  |       return;  | 
803  | 87  |     }  | 
804  | 906  |     disp_off = strstr(OS->buffer, "{za0.s,za2.s,za3.s}"); | 
805  | 906  |     if (disp_off) { | 
806  | 80  |       ADD_ZA0_S;  | 
807  | 80  |       ADD_ZA2_S;  | 
808  | 80  |       ADD_ZA3_S;  | 
809  | 80  |       return;  | 
810  | 80  |     }  | 
811  | 826  |     disp_off = strstr(OS->buffer, "{za1.s,za2.s,za3.s}"); | 
812  | 826  |     if (disp_off) { | 
813  | 826  |       ADD_ZA1_S;  | 
814  | 826  |       ADD_ZA2_S;  | 
815  | 826  |       ADD_ZA3_S;  | 
816  | 826  |       return;  | 
817  | 826  |     }  | 
818  | 0  |     break;  | 
819  | 826  |   }  | 
820  | 60.7k  |   }  | 
821  | 60.7k  | }  | 
822  |  |  | 
823  |  | void AArch64_set_instr_map_data(MCInst *MI)  | 
824  | 392k  | { | 
825  | 392k  |   map_cs_id(MI, aarch64_insns, ARR_SIZE(aarch64_insns));  | 
826  | 392k  |   map_implicit_reads(MI, aarch64_insns);  | 
827  | 392k  |   map_implicit_writes(MI, aarch64_insns);  | 
828  | 392k  |   map_groups(MI, aarch64_insns);  | 
829  | 392k  | }  | 
830  |  |  | 
831  |  | bool AArch64_getInstruction(csh handle, const uint8_t *code, size_t code_len,  | 
832  |  |           MCInst *MI, uint16_t *size, uint64_t address,  | 
833  |  |           void *info)  | 
834  | 392k  | { | 
835  | 392k  |   AArch64_init_cs_detail(MI);  | 
836  | 392k  |   DecodeStatus Result = AArch64_LLVM_getInstruction(  | 
837  | 392k  |     handle, code, code_len, MI, size, address, info);  | 
838  | 392k  |   AArch64_set_instr_map_data(MI);  | 
839  | 392k  |   if (Result == MCDisassembler_SoftFail) { | 
840  | 7.93k  |     MCInst_setSoftFail(MI);  | 
841  | 7.93k  |   }  | 
842  | 392k  |   return Result != MCDisassembler_Fail;  | 
843  | 392k  | }  | 
844  |  |  | 
845  |  | /// Patches the register names with Capstone specific alias.  | 
846  |  | /// Those are common alias for registers (e.g. r15 = pc)  | 
847  |  | /// which are not set in LLVM.  | 
848  |  | static void patch_cs_reg_alias(char *asm_str)  | 
849  | 0  | { | 
850  | 0  |   bool skip_sub = false;  | 
851  | 0  |   char *x29 = strstr(asm_str, "x29");  | 
852  | 0  |   if (x29 > asm_str && strstr(asm_str, "0x29") == (x29 - 1)) { | 
853  |  |     // Check for hex prefix  | 
854  | 0  |     skip_sub = true;  | 
855  | 0  |   }  | 
856  | 0  |   while (x29 && !skip_sub) { | 
857  | 0  |     x29[0] = 'f';  | 
858  | 0  |     x29[1] = 'p';  | 
859  | 0  |     memmove(x29 + 2, x29 + 3, strlen(x29 + 3));  | 
860  | 0  |     asm_str[strlen(asm_str) - 1] = '\0';  | 
861  | 0  |     x29 = strstr(asm_str, "x29");  | 
862  | 0  |   }  | 
863  | 0  |   skip_sub = false;  | 
864  | 0  |   char *x30 = strstr(asm_str, "x30");  | 
865  | 0  |   if (x30 > asm_str && strstr(asm_str, "0x30") == (x30 - 1)) { | 
866  |  |     // Check for hex prefix  | 
867  | 0  |     skip_sub = true;  | 
868  | 0  |   }  | 
869  | 0  |   while (x30 && !skip_sub) { | 
870  | 0  |     x30[0] = 'l';  | 
871  | 0  |     x30[1] = 'r';  | 
872  | 0  |     memmove(x30 + 2, x30 + 3, strlen(x30 + 3));  | 
873  | 0  |     asm_str[strlen(asm_str) - 1] = '\0';  | 
874  | 0  |     x30 = strstr(asm_str, "x30");  | 
875  | 0  |   }  | 
876  | 0  | }  | 
877  |  |  | 
878  |  | /// Adds group to the instruction which are not defined in LLVM.  | 
879  |  | static void AArch64_add_cs_groups(MCInst *MI)  | 
880  | 386k  | { | 
881  | 386k  |   unsigned Opcode = MI->flat_insn->id;  | 
882  | 386k  |   switch (Opcode) { | 
883  | 374k  |   default:  | 
884  | 374k  |     return;  | 
885  | 374k  |   case AARCH64_INS_SVC:  | 
886  | 364  |     add_group(MI, AARCH64_GRP_INT);  | 
887  | 364  |     break;  | 
888  | 251  |   case AARCH64_INS_SMC:  | 
889  | 8.32k  |   case AARCH64_INS_MSR:  | 
890  | 11.3k  |   case AARCH64_INS_MRS:  | 
891  | 11.3k  |     add_group(MI, AARCH64_GRP_PRIVILEGE);  | 
892  | 11.3k  |     break;  | 
893  | 34  |   case AARCH64_INS_RET:  | 
894  | 100  |   case AARCH64_INS_RETAA:  | 
895  | 134  |   case AARCH64_INS_RETAB:  | 
896  | 134  |     add_group(MI, AARCH64_GRP_RET);  | 
897  | 134  |     break;  | 
898  | 386k  |   }  | 
899  | 386k  | }  | 
900  |  |  | 
901  |  | static void AArch64_correct_mem_access(MCInst *MI)  | 
902  | 386k  | { | 
903  | 386k  | #ifndef CAPSTONE_DIET  | 
904  | 386k  |   if (!detail_is_set(MI))  | 
905  | 0  |     return;  | 
906  | 386k  |   cs_ac_type access =  | 
907  | 386k  |     aarch64_insns[MI->Opcode].suppl_info.aarch64.mem_acc;  | 
908  | 386k  |   if (access == CS_AC_INVALID) { | 
909  | 265k  |     return;  | 
910  | 265k  |   }  | 
911  | 255k  |   for (int i = 0; i < AArch64_get_detail(MI)->op_count; ++i) { | 
912  | 253k  |     if (AArch64_get_detail_op(MI, -i)->type == AARCH64_OP_MEM) { | 
913  | 118k  |       AArch64_get_detail_op(MI, -i)->access = access;  | 
914  | 118k  |       return;  | 
915  | 118k  |     }  | 
916  | 253k  |   }  | 
917  | 120k  | #endif  | 
918  | 120k  | }  | 
919  |  |  | 
920  |  | void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)  | 
921  | 386k  | { | 
922  | 386k  |   MCRegisterInfo *MRI = (MCRegisterInfo *)info;  | 
923  | 386k  |   MI->MRI = MRI;  | 
924  | 386k  |   MI->fillDetailOps = detail_is_set(MI);  | 
925  | 386k  |   MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);  | 
926  | 386k  |   AArch64_LLVM_printInstruction(MI, O, info);  | 
927  | 386k  |   if (detail_is_set(MI)) { | 
928  | 386k  |     if (AArch64_get_detail(MI)->is_doing_sme) { | 
929  |  |       // Last operand still needs to be closed.  | 
930  | 9.81k  |       AArch64_get_detail(MI)->is_doing_sme = false;  | 
931  | 9.81k  |       AArch64_inc_op_count(MI);  | 
932  | 9.81k  |     }  | 
933  | 386k  |     AArch64_get_detail(MI)->post_index =  | 
934  | 386k  |       AArch64_check_post_index_am(MI, O);  | 
935  | 386k  |   }  | 
936  | 386k  |   AArch64_check_updates_flags(MI);  | 
937  | 386k  |   map_set_alias_id(MI, O, insn_alias_mnem_map,  | 
938  | 386k  |        ARR_SIZE(insn_alias_mnem_map) - 1);  | 
939  | 386k  |   int syntax_opt = MI->csh->syntax;  | 
940  | 386k  |   if (syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS)  | 
941  | 0  |     patch_cs_reg_alias(O->buffer);  | 
942  | 386k  |   AArch64_add_not_defined_ops(MI, O);  | 
943  | 386k  |   AArch64_add_cs_groups(MI);  | 
944  | 386k  |   AArch64_add_vas(MI, O);  | 
945  | 386k  |   AArch64_correct_mem_access(MI);  | 
946  | 386k  | }  | 
947  |  |  | 
948  |  | // given internal insn id, return public instruction info  | 
949  |  | void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)  | 
950  | 386k  | { | 
951  |  |   // Done after disassembly  | 
952  | 386k  |   return;  | 
953  | 386k  | }  | 
954  |  |  | 
955  |  | static const char *const insn_name_maps[] = { | 
956  |  | #include "AArch64GenCSMappingInsnName.inc"  | 
957  |  | };  | 
958  |  |  | 
959  |  | const char *AArch64_insn_name(csh handle, unsigned int id)  | 
960  | 386k  | { | 
961  | 386k  | #ifndef CAPSTONE_DIET  | 
962  | 386k  |   if (id < AARCH64_INS_ALIAS_END && id > AARCH64_INS_ALIAS_BEGIN) { | 
963  | 0  |     if (id - AARCH64_INS_ALIAS_BEGIN >=  | 
964  | 0  |         ARR_SIZE(insn_alias_mnem_map))  | 
965  | 0  |       return NULL;  | 
966  |  |  | 
967  | 0  |     return insn_alias_mnem_map[id - AARCH64_INS_ALIAS_BEGIN - 1]  | 
968  | 0  |       .name;  | 
969  | 0  |   }  | 
970  | 386k  |   if (id >= AARCH64_INS_ENDING)  | 
971  | 0  |     return NULL;  | 
972  |  |  | 
973  | 386k  |   if (id < ARR_SIZE(insn_name_maps))  | 
974  | 386k  |     return insn_name_maps[id];  | 
975  |  |  | 
976  |  |   // not found  | 
977  | 0  |   return NULL;  | 
978  |  | #else  | 
979  |  |   return NULL;  | 
980  |  | #endif  | 
981  | 386k  | }  | 
982  |  |  | 
983  |  | #ifndef CAPSTONE_DIET  | 
984  |  | static const name_map group_name_maps[] = { | 
985  |  |   // generic groups  | 
986  |  |   { AARCH64_GRP_INVALID, NULL }, | 
987  |  |   { AARCH64_GRP_JUMP, "jump" }, | 
988  |  |   { AARCH64_GRP_CALL, "call" }, | 
989  |  |   { AARCH64_GRP_RET, "return" }, | 
990  |  |   { AARCH64_GRP_PRIVILEGE, "privilege" }, | 
991  |  |   { AARCH64_GRP_INT, "int" }, | 
992  |  |   { AARCH64_GRP_BRANCH_RELATIVE, "branch_relative" }, | 
993  |  |  | 
994  |  | // architecture-specific groups  | 
995  |  | #include "AArch64GenCSFeatureName.inc"  | 
996  |  | };  | 
997  |  | #endif  | 
998  |  |  | 
999  |  | const char *AArch64_group_name(csh handle, unsigned int id)  | 
1000  | 494k  | { | 
1001  | 494k  | #ifndef CAPSTONE_DIET  | 
1002  | 494k  |   return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);  | 
1003  |  | #else  | 
1004  |  |   return NULL;  | 
1005  |  | #endif  | 
1006  | 494k  | }  | 
1007  |  |  | 
1008  |  | // map instruction name to public instruction ID  | 
1009  |  | aarch64_insn AArch64_map_insn(const char *name)  | 
1010  | 73.0k  | { | 
1011  | 73.0k  |   unsigned int i;  | 
1012  |  |  | 
1013  | 48.9M  |   for (i = 1; i < ARR_SIZE(insn_name_maps); i++) { | 
1014  | 48.9M  |     if (!strcmp(name, insn_name_maps[i]))  | 
1015  | 72.4k  |       return i;  | 
1016  | 48.9M  |   }  | 
1017  |  |  | 
1018  |  |   // not found  | 
1019  | 590  |   return AARCH64_INS_INVALID;  | 
1020  | 73.0k  | }  | 
1021  |  |  | 
1022  |  | #ifndef CAPSTONE_DIET  | 
1023  |  |  | 
1024  |  | static const map_insn_ops insn_operands[] = { | 
1025  |  | #include "AArch64GenCSMappingInsnOp.inc"  | 
1026  |  | };  | 
1027  |  |  | 
1028  |  | void AArch64_reg_access(const cs_insn *insn, cs_regs regs_read,  | 
1029  |  |       uint8_t *regs_read_count, cs_regs regs_write,  | 
1030  |  |       uint8_t *regs_write_count)  | 
1031  | 0  | { | 
1032  | 0  |   uint8_t i;  | 
1033  | 0  |   uint8_t read_count, write_count;  | 
1034  | 0  |   cs_aarch64 *aarch64 = &(insn->detail->aarch64);  | 
1035  |  | 
  | 
1036  | 0  |   read_count = insn->detail->regs_read_count;  | 
1037  | 0  |   write_count = insn->detail->regs_write_count;  | 
1038  |  |  | 
1039  |  |   // implicit registers  | 
1040  | 0  |   memcpy(regs_read, insn->detail->regs_read,  | 
1041  | 0  |          read_count * sizeof(insn->detail->regs_read[0]));  | 
1042  | 0  |   memcpy(regs_write, insn->detail->regs_write,  | 
1043  | 0  |          write_count * sizeof(insn->detail->regs_write[0]));  | 
1044  |  |  | 
1045  |  |   // explicit registers  | 
1046  | 0  |   for (i = 0; i < aarch64->op_count; i++) { | 
1047  | 0  |     cs_aarch64_op *op = &(aarch64->operands[i]);  | 
1048  | 0  |     switch ((int)op->type) { | 
1049  | 0  |     case AARCH64_OP_REG:  | 
1050  | 0  |       if ((op->access & CS_AC_READ) &&  | 
1051  | 0  |           !arr_exist(regs_read, read_count, op->reg)) { | 
1052  | 0  |         regs_read[read_count] = (uint16_t)op->reg;  | 
1053  | 0  |         read_count++;  | 
1054  | 0  |       }  | 
1055  | 0  |       if ((op->access & CS_AC_WRITE) &&  | 
1056  | 0  |           !arr_exist(regs_write, write_count, op->reg)) { | 
1057  | 0  |         regs_write[write_count] = (uint16_t)op->reg;  | 
1058  | 0  |         write_count++;  | 
1059  | 0  |       }  | 
1060  | 0  |       break;  | 
1061  | 0  |     case AARCH64_OP_MEM:  | 
1062  |  |       // registers appeared in memory references always being read  | 
1063  | 0  |       if ((op->mem.base != AARCH64_REG_INVALID) &&  | 
1064  | 0  |           !arr_exist(regs_read, read_count, op->mem.base)) { | 
1065  | 0  |         regs_read[read_count] = (uint16_t)op->mem.base;  | 
1066  | 0  |         read_count++;  | 
1067  | 0  |       }  | 
1068  | 0  |       if ((op->mem.index != AARCH64_REG_INVALID) &&  | 
1069  | 0  |           !arr_exist(regs_read, read_count, op->mem.index)) { | 
1070  | 0  |         regs_read[read_count] = (uint16_t)op->mem.index;  | 
1071  | 0  |         read_count++;  | 
1072  | 0  |       }  | 
1073  | 0  |       if ((insn->detail->writeback) &&  | 
1074  | 0  |           (op->mem.base != AARCH64_REG_INVALID) &&  | 
1075  | 0  |           !arr_exist(regs_write, write_count, op->mem.base)) { | 
1076  | 0  |         regs_write[write_count] =  | 
1077  | 0  |           (uint16_t)op->mem.base;  | 
1078  | 0  |         write_count++;  | 
1079  | 0  |       }  | 
1080  | 0  |       break;  | 
1081  | 0  |     case AARCH64_OP_SME:  | 
1082  | 0  |       if ((op->access & CS_AC_READ) &&  | 
1083  | 0  |           (op->sme.tile != AARCH64_REG_INVALID) &&  | 
1084  | 0  |           !arr_exist(regs_read, read_count, op->sme.tile)) { | 
1085  | 0  |         regs_read[read_count] = (uint16_t)op->sme.tile;  | 
1086  | 0  |         read_count++;  | 
1087  | 0  |       }  | 
1088  | 0  |       if ((op->access & CS_AC_WRITE) &&  | 
1089  | 0  |           (op->sme.tile != AARCH64_REG_INVALID) &&  | 
1090  | 0  |           !arr_exist(regs_write, write_count, op->sme.tile)) { | 
1091  | 0  |         regs_write[write_count] =  | 
1092  | 0  |           (uint16_t)op->sme.tile;  | 
1093  | 0  |         write_count++;  | 
1094  | 0  |       }  | 
1095  | 0  |       if ((op->sme.slice_reg != AARCH64_REG_INVALID) &&  | 
1096  | 0  |           !arr_exist(regs_read, read_count,  | 
1097  | 0  |                op->sme.slice_reg)) { | 
1098  | 0  |         regs_read[read_count] =  | 
1099  | 0  |           (uint16_t)op->sme.slice_reg;  | 
1100  | 0  |         read_count++;  | 
1101  | 0  |       }  | 
1102  | 0  |       break;  | 
1103  | 0  |     case AARCH64_OP_PRED:  | 
1104  | 0  |       if ((op->access & CS_AC_READ) &&  | 
1105  | 0  |           (op->pred.reg != AARCH64_REG_INVALID) &&  | 
1106  | 0  |           !arr_exist(regs_read, read_count, op->pred.reg)) { | 
1107  | 0  |         regs_read[read_count] = (uint16_t)op->pred.reg;  | 
1108  | 0  |         read_count++;  | 
1109  | 0  |       }  | 
1110  | 0  |       if ((op->access & CS_AC_WRITE) &&  | 
1111  | 0  |           (op->pred.reg != AARCH64_REG_INVALID) &&  | 
1112  | 0  |           !arr_exist(regs_write, write_count, op->pred.reg)) { | 
1113  | 0  |         regs_write[write_count] =  | 
1114  | 0  |           (uint16_t)op->pred.reg;  | 
1115  | 0  |         write_count++;  | 
1116  | 0  |       }  | 
1117  | 0  |       if ((op->pred.vec_select != AARCH64_REG_INVALID) &&  | 
1118  | 0  |           !arr_exist(regs_read, read_count,  | 
1119  | 0  |                op->pred.vec_select)) { | 
1120  | 0  |         regs_read[read_count] =  | 
1121  | 0  |           (uint16_t)op->pred.vec_select;  | 
1122  | 0  |         read_count++;  | 
1123  | 0  |       }  | 
1124  | 0  |       break;  | 
1125  | 0  |     default:  | 
1126  | 0  |       break;  | 
1127  | 0  |     }  | 
1128  | 0  |     if (op->shift.type >= AARCH64_SFT_LSL_REG) { | 
1129  | 0  |       if (!arr_exist(regs_read, read_count,  | 
1130  | 0  |                op->shift.value)) { | 
1131  | 0  |         regs_read[read_count] =  | 
1132  | 0  |           (uint16_t)op->shift.value;  | 
1133  | 0  |         read_count++;  | 
1134  | 0  |       }  | 
1135  | 0  |     }  | 
1136  | 0  |   }  | 
1137  |  |  | 
1138  | 0  |   switch (insn->alias_id) { | 
1139  | 0  |   default:  | 
1140  | 0  |     break;  | 
1141  | 0  |   case AARCH64_INS_ALIAS_RET:  | 
1142  | 0  |     regs_read[read_count] = AARCH64_REG_X30;  | 
1143  | 0  |     read_count++;  | 
1144  | 0  |     break;  | 
1145  | 0  |   }  | 
1146  |  |  | 
1147  | 0  |   *regs_read_count = read_count;  | 
1148  | 0  |   *regs_write_count = write_count;  | 
1149  | 0  | }  | 
1150  |  | #endif  | 
1151  |  |  | 
1152  |  | static AArch64Layout_VectorLayout get_vl_by_suffix(const char suffix)  | 
1153  | 236k  | { | 
1154  | 236k  |   switch (suffix) { | 
1155  | 74.6k  |   default:  | 
1156  | 74.6k  |     return AARCH64LAYOUT_INVALID;  | 
1157  | 37.4k  |   case 'b':  | 
1158  | 37.4k  |   case 'B':  | 
1159  | 37.4k  |     return AARCH64LAYOUT_VL_B;  | 
1160  | 44.6k  |   case 'h':  | 
1161  | 44.6k  |   case 'H':  | 
1162  | 44.6k  |     return AARCH64LAYOUT_VL_H;  | 
1163  | 32.8k  |   case 's':  | 
1164  | 32.8k  |   case 'S':  | 
1165  | 32.8k  |     return AARCH64LAYOUT_VL_S;  | 
1166  | 44.4k  |   case 'd':  | 
1167  | 44.4k  |   case 'D':  | 
1168  | 44.4k  |     return AARCH64LAYOUT_VL_D;  | 
1169  | 2.95k  |   case 'q':  | 
1170  | 2.95k  |   case 'Q':  | 
1171  | 2.95k  |     return AARCH64LAYOUT_VL_Q;  | 
1172  | 236k  |   }  | 
1173  | 236k  | }  | 
1174  |  |  | 
1175  |  | static unsigned get_vec_list_num_regs(MCInst *MI, unsigned Reg)  | 
1176  | 89.9k  | { | 
1177  |  |   // Work out how many registers there are in the list (if there is an actual  | 
1178  |  |   // list).  | 
1179  | 89.9k  |   unsigned NumRegs = 1;  | 
1180  | 89.9k  |   if (MCRegisterClass_contains(  | 
1181  | 89.9k  |         MCRegisterInfo_getRegClass(MI->MRI, AArch64_DDRegClassID),  | 
1182  | 89.9k  |         Reg) ||  | 
1183  | 88.6k  |       MCRegisterClass_contains(  | 
1184  | 88.6k  |         MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR2RegClassID),  | 
1185  | 88.6k  |         Reg) ||  | 
1186  | 72.9k  |       MCRegisterClass_contains(  | 
1187  | 72.9k  |         MCRegisterInfo_getRegClass(MI->MRI, AArch64_QQRegClassID),  | 
1188  | 72.9k  |         Reg) ||  | 
1189  | 64.3k  |       MCRegisterClass_contains(  | 
1190  | 64.3k  |         MCRegisterInfo_getRegClass(MI->MRI, AArch64_PPR2RegClassID),  | 
1191  | 64.3k  |         Reg) ||  | 
1192  | 61.1k  |       MCRegisterClass_contains(  | 
1193  | 61.1k  |         MCRegisterInfo_getRegClass(MI->MRI,  | 
1194  | 61.1k  |                  AArch64_ZPR2StridedRegClassID),  | 
1195  | 61.1k  |         Reg))  | 
1196  | 35.1k  |     NumRegs = 2;  | 
1197  | 54.8k  |   else if (MCRegisterClass_contains(  | 
1198  | 54.8k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1199  | 54.8k  |                 AArch64_DDDRegClassID),  | 
1200  | 54.8k  |        Reg) ||  | 
1201  | 53.8k  |      MCRegisterClass_contains(  | 
1202  | 53.8k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1203  | 53.8k  |                 AArch64_ZPR3RegClassID),  | 
1204  | 53.8k  |        Reg) ||  | 
1205  | 53.5k  |      MCRegisterClass_contains(  | 
1206  | 53.5k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1207  | 53.5k  |                 AArch64_QQQRegClassID),  | 
1208  | 53.5k  |        Reg))  | 
1209  | 7.44k  |     NumRegs = 3;  | 
1210  | 47.4k  |   else if (MCRegisterClass_contains(  | 
1211  | 47.4k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1212  | 47.4k  |                 AArch64_DDDDRegClassID),  | 
1213  | 47.4k  |        Reg) ||  | 
1214  | 46.5k  |      MCRegisterClass_contains(  | 
1215  | 46.5k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1216  | 46.5k  |                 AArch64_ZPR4RegClassID),  | 
1217  | 46.5k  |        Reg) ||  | 
1218  | 33.6k  |      MCRegisterClass_contains(  | 
1219  | 33.6k  |        MCRegisterInfo_getRegClass(MI->MRI,  | 
1220  | 33.6k  |                 AArch64_QQQQRegClassID),  | 
1221  | 33.6k  |        Reg) ||  | 
1222  | 23.9k  |      MCRegisterClass_contains(  | 
1223  | 23.9k  |        MCRegisterInfo_getRegClass(  | 
1224  | 23.9k  |          MI->MRI, AArch64_ZPR4StridedRegClassID),  | 
1225  | 23.9k  |        Reg))  | 
1226  | 25.1k  |     NumRegs = 4;  | 
1227  | 89.9k  |   return NumRegs;  | 
1228  | 89.9k  | }  | 
1229  |  |  | 
1230  |  | static unsigned get_vec_list_stride(MCInst *MI, unsigned Reg)  | 
1231  | 89.9k  | { | 
1232  | 89.9k  |   unsigned Stride = 1;  | 
1233  | 89.9k  |   if (MCRegisterClass_contains(  | 
1234  | 89.9k  |         MCRegisterInfo_getRegClass(MI->MRI,  | 
1235  | 89.9k  |                  AArch64_ZPR2StridedRegClassID),  | 
1236  | 89.9k  |         Reg))  | 
1237  | 6.24k  |     Stride = 8;  | 
1238  | 83.7k  |   else if (MCRegisterClass_contains(  | 
1239  | 83.7k  |        MCRegisterInfo_getRegClass(  | 
1240  | 83.7k  |          MI->MRI, AArch64_ZPR4StridedRegClassID),  | 
1241  | 83.7k  |        Reg))  | 
1242  | 1.68k  |     Stride = 4;  | 
1243  | 89.9k  |   return Stride;  | 
1244  | 89.9k  | }  | 
1245  |  |  | 
1246  |  | static unsigned get_vec_list_first_reg(MCInst *MI, unsigned RegL)  | 
1247  | 89.9k  | { | 
1248  | 89.9k  |   unsigned Reg = RegL;  | 
1249  |  |   // Now forget about the list and find out what the first register is.  | 
1250  | 89.9k  |   if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0))  | 
1251  | 3.28k  |     Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0);  | 
1252  | 86.7k  |   else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0))  | 
1253  | 24.3k  |     Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0);  | 
1254  | 62.3k  |   else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0))  | 
1255  | 36.8k  |     Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0);  | 
1256  | 25.5k  |   else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0))  | 
1257  | 3.27k  |     Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0);  | 
1258  |  |  | 
1259  |  |   // If it's a D-reg, we need to promote it to the equivalent Q-reg before  | 
1260  |  |   // printing (otherwise getRegisterName fails).  | 
1261  | 89.9k  |   if (MCRegisterClass_contains(MCRegisterInfo_getRegClass(  | 
1262  | 89.9k  |                MI->MRI, AArch64_FPR64RegClassID),  | 
1263  | 89.9k  |              Reg)) { | 
1264  | 4.05k  |     const MCRegisterClass *FPR128RC = MCRegisterInfo_getRegClass(  | 
1265  | 4.05k  |       MI->MRI, AArch64_FPR128RegClassID);  | 
1266  | 4.05k  |     Reg = MCRegisterInfo_getMatchingSuperReg(  | 
1267  | 4.05k  |       MI->MRI, Reg, AArch64_dsub, FPR128RC);  | 
1268  | 4.05k  |   }  | 
1269  | 89.9k  |   return Reg;  | 
1270  | 89.9k  | }  | 
1271  |  |  | 
1272  |  | static bool is_vector_reg(unsigned Reg)  | 
1273  | 349k  | { | 
1274  | 349k  |   if ((Reg >= AArch64_Q0) && (Reg <= AArch64_Q31))  | 
1275  | 90.4k  |     return true;  | 
1276  | 259k  |   else if ((Reg >= AArch64_Z0) && (Reg <= AArch64_Z31))  | 
1277  | 252k  |     return true;  | 
1278  | 6.58k  |   else if ((Reg >= AArch64_P0) && (Reg <= AArch64_P15))  | 
1279  | 6.58k  |     return true;  | 
1280  | 0  |   return false;  | 
1281  | 349k  | }  | 
1282  |  |  | 
1283  |  | static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride /* = 1 */)  | 
1284  | 215k  | { | 
1285  | 565k  |   while (Stride--) { | 
1286  | 349k  |     if (!is_vector_reg(Reg)) { | 
1287  | 0  |       CS_ASSERT(0 && "Vector register expected!");  | 
1288  | 0  |       return 0;  | 
1289  | 0  |     }  | 
1290  |  |     // Vector lists can wrap around.  | 
1291  | 349k  |     else if (Reg == AArch64_Q31)  | 
1292  | 1.89k  |       Reg = AArch64_Q0;  | 
1293  |  |     // Vector lists can wrap around.  | 
1294  | 347k  |     else if (Reg == AArch64_Z31)  | 
1295  | 4.35k  |       Reg = AArch64_Z0;  | 
1296  |  |     // Vector lists can wrap around.  | 
1297  | 343k  |     else if (Reg == AArch64_P15)  | 
1298  | 90  |       Reg = AArch64_P0;  | 
1299  | 343k  |     else  | 
1300  |  |       // Assume ordered registers  | 
1301  | 343k  |       ++Reg;  | 
1302  | 349k  |   }  | 
1303  | 215k  |   return Reg;  | 
1304  | 215k  | }  | 
1305  |  |  | 
1306  |  | static aarch64_extender llvm_to_cs_ext(AArch64_AM_ShiftExtendType ExtType)  | 
1307  | 21.5k  | { | 
1308  | 21.5k  |   switch (ExtType) { | 
1309  | 14.4k  |   default:  | 
1310  | 14.4k  |     return AARCH64_EXT_INVALID;  | 
1311  | 1.56k  |   case AArch64_AM_UXTB:  | 
1312  | 1.56k  |     return AARCH64_EXT_UXTB;  | 
1313  | 1.19k  |   case AArch64_AM_UXTH:  | 
1314  | 1.19k  |     return AARCH64_EXT_UXTH;  | 
1315  | 1.33k  |   case AArch64_AM_UXTW:  | 
1316  | 1.33k  |     return AARCH64_EXT_UXTW;  | 
1317  | 1.83k  |   case AArch64_AM_UXTX:  | 
1318  | 1.83k  |     return AARCH64_EXT_UXTX;  | 
1319  | 311  |   case AArch64_AM_SXTB:  | 
1320  | 311  |     return AARCH64_EXT_SXTB;  | 
1321  | 76  |   case AArch64_AM_SXTH:  | 
1322  | 76  |     return AARCH64_EXT_SXTH;  | 
1323  | 227  |   case AArch64_AM_SXTW:  | 
1324  | 227  |     return AARCH64_EXT_SXTW;  | 
1325  | 568  |   case AArch64_AM_SXTX:  | 
1326  | 568  |     return AARCH64_EXT_SXTX;  | 
1327  | 21.5k  |   }  | 
1328  | 21.5k  | }  | 
1329  |  |  | 
1330  |  | static aarch64_shifter llvm_to_cs_shift(AArch64_AM_ShiftExtendType ShiftExtType)  | 
1331  | 14.4k  | { | 
1332  | 14.4k  |   switch (ShiftExtType) { | 
1333  | 0  |   default:  | 
1334  | 0  |     return AARCH64_SFT_INVALID;  | 
1335  | 9.34k  |   case AArch64_AM_LSL:  | 
1336  | 9.34k  |     return AARCH64_SFT_LSL;  | 
1337  | 1.65k  |   case AArch64_AM_LSR:  | 
1338  | 1.65k  |     return AARCH64_SFT_LSR;  | 
1339  | 1.69k  |   case AArch64_AM_ASR:  | 
1340  | 1.69k  |     return AARCH64_SFT_ASR;  | 
1341  | 1.12k  |   case AArch64_AM_ROR:  | 
1342  | 1.12k  |     return AARCH64_SFT_ROR;  | 
1343  | 596  |   case AArch64_AM_MSL:  | 
1344  | 596  |     return AARCH64_SFT_MSL;  | 
1345  | 14.4k  |   }  | 
1346  | 14.4k  | }  | 
1347  |  |  | 
1348  |  | /// Initializes or finishes a memory operand of Capstone (depending on \p  | 
1349  |  | /// status). A memory operand in Capstone can be assembled by two LLVM operands.  | 
1350  |  | /// E.g. the base register and the immediate disponent.  | 
1351  |  | void AArch64_set_mem_access(MCInst *MI, bool status)  | 
1352  | 415k  | { | 
1353  | 415k  |   if (!detail_is_set(MI))  | 
1354  | 0  |     return;  | 
1355  | 415k  |   set_doing_mem(MI, status);  | 
1356  | 415k  |   if (status) { | 
1357  | 207k  |     if (AArch64_get_detail(MI)->op_count > 0 &&  | 
1358  | 205k  |         AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_MEM &&  | 
1359  | 81.9k  |         AArch64_get_detail_op(MI, -1)->mem.index ==  | 
1360  | 81.9k  |           AARCH64_REG_INVALID &&  | 
1361  | 80.8k  |         AArch64_get_detail_op(MI, -1)->mem.disp == 0) { | 
1362  |  |       // Previous memory operand not done yet. Select it.  | 
1363  | 80.8k  |       AArch64_dec_op_count(MI);  | 
1364  | 80.8k  |       return;  | 
1365  | 80.8k  |     }  | 
1366  |  |  | 
1367  |  |     // Init a new one.  | 
1368  | 126k  |     AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_MEM;  | 
1369  | 126k  |     AArch64_get_detail_op(MI, 0)->mem.base = AARCH64_REG_INVALID;  | 
1370  | 126k  |     AArch64_get_detail_op(MI, 0)->mem.index = AARCH64_REG_INVALID;  | 
1371  | 126k  |     AArch64_get_detail_op(MI, 0)->mem.disp = 0;  | 
1372  |  |  | 
1373  | 126k  | #ifndef CAPSTONE_DIET  | 
1374  | 126k  |     uint8_t access =  | 
1375  | 126k  |       map_get_op_access(MI, AArch64_get_detail(MI)->op_count);  | 
1376  | 126k  |     AArch64_get_detail_op(MI, 0)->access = access;  | 
1377  | 126k  | #endif  | 
1378  | 207k  |   } else { | 
1379  |  |     // done, select the next operand slot  | 
1380  | 207k  |     AArch64_inc_op_count(MI);  | 
1381  | 207k  |   }  | 
1382  | 415k  | }  | 
1383  |  |  | 
1384  |  | /// Common prefix for all AArch64_add_cs_detail_* functions  | 
1385  |  | static bool add_cs_detail_begin(MCInst *MI, unsigned op_num)  | 
1386  | 1.18M  | { | 
1387  | 1.18M  |   if (!detail_is_set(MI) || !map_fill_detail_ops(MI))  | 
1388  | 0  |     return false;  | 
1389  |  |  | 
1390  | 1.18M  |   if (AArch64_get_detail(MI)->is_doing_sme) { | 
1391  |  |     // Unset the flag if there is no bound operand anymore.  | 
1392  | 145k  |     if (!(map_get_op_type(MI, op_num) & CS_OP_BOUND)) { | 
1393  | 105k  |       AArch64_get_detail(MI)->is_doing_sme = false;  | 
1394  | 105k  |       AArch64_inc_op_count(MI);  | 
1395  | 105k  |     }  | 
1396  | 145k  |   }  | 
1397  | 1.18M  |   return true;  | 
1398  | 1.18M  | }  | 
1399  |  |  | 
1400  |  | /// Fills cs_detail with the data of the operand.  | 
1401  |  | /// This function handles operands which's original printer function has no  | 
1402  |  | /// specialities.  | 
1403  |  | void AArch64_add_cs_detail_0(MCInst *MI, aarch64_op_group op_group,  | 
1404  |  |            unsigned OpNum)  | 
1405  | 675k  | { | 
1406  | 675k  |   if (!add_cs_detail_begin(MI, OpNum))  | 
1407  | 0  |     return;  | 
1408  |  |  | 
1409  |  |   // Fill cs_detail  | 
1410  | 675k  |   switch (op_group) { | 
1411  | 0  |   default:  | 
1412  | 0  |     printf("ERROR: Operand group %d not handled!\n", op_group); | 
1413  | 0  |     CS_ASSERT_RET(0);  | 
1414  | 465k  |   case AArch64_OP_GROUP_Operand: { | 
1415  | 465k  |     cs_op_type primary_op_type = map_get_op_type(MI, OpNum) &  | 
1416  | 465k  |                ~(CS_OP_MEM | CS_OP_BOUND);  | 
1417  | 465k  |     switch (primary_op_type) { | 
1418  | 0  |     default:  | 
1419  | 0  |       printf("Unhandled operand type 0x%x\n", | 
1420  | 0  |              primary_op_type);  | 
1421  | 0  |       CS_ASSERT_RET(0);  | 
1422  | 394k  |     case AARCH64_OP_REG:  | 
1423  | 394k  |       AArch64_set_detail_op_reg(MI, OpNum,  | 
1424  | 394k  |               MCInst_getOpVal(MI, OpNum));  | 
1425  | 394k  |       break;  | 
1426  | 70.0k  |     case AARCH64_OP_IMM:  | 
1427  | 70.0k  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1428  | 70.0k  |               MCInst_getOpVal(MI, OpNum));  | 
1429  | 70.0k  |       break;  | 
1430  | 925  |     case AARCH64_OP_FP: { | 
1431  |  |       // printOperand does not handle FP operands. But sometimes  | 
1432  |  |       // is used to print FP operands as normal immediate.  | 
1433  | 925  |       AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM;  | 
1434  | 925  |       AArch64_get_detail_op(MI, 0)->imm =  | 
1435  | 925  |         MCInst_getOpVal(MI, OpNum);  | 
1436  | 925  |       AArch64_get_detail_op(MI, 0)->access =  | 
1437  | 925  |         map_get_op_access(MI, OpNum);  | 
1438  | 925  |       AArch64_inc_op_count(MI);  | 
1439  | 925  |       break;  | 
1440  | 0  |     }  | 
1441  | 465k  |     }  | 
1442  | 465k  |     break;  | 
1443  | 465k  |   }  | 
1444  | 465k  |   case AArch64_OP_GROUP_AddSubImm: { | 
1445  | 2.84k  |     unsigned Val = (MCInst_getOpVal(MI, OpNum) & 0xfff);  | 
1446  | 2.84k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);  | 
1447  |  |     // Shift is added in printShifter()  | 
1448  | 2.84k  |     break;  | 
1449  | 465k  |   }  | 
1450  | 0  |   case AArch64_OP_GROUP_AdrLabel: { | 
1451  | 0  |     if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) { | 
1452  | 0  |       int64_t Offset = MCInst_getOpVal(MI, OpNum);  | 
1453  | 0  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1454  | 0  |               (MI->address & -4) + Offset);  | 
1455  | 0  |     } else { | 
1456  |  |       // Expression  | 
1457  | 0  |       AArch64_set_detail_op_imm(  | 
1458  | 0  |         MI, OpNum, AARCH64_OP_IMM,  | 
1459  | 0  |         MCOperand_isImm(MCInst_getOperand(MI, OpNum)));  | 
1460  | 0  |     }  | 
1461  | 0  |     break;  | 
1462  | 465k  |   }  | 
1463  | 0  |   case AArch64_OP_GROUP_AdrpLabel: { | 
1464  | 0  |     if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) { | 
1465  | 0  |       int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4096;  | 
1466  | 0  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1467  | 0  |               (MI->address & -4096) +  | 
1468  | 0  |                 Offset);  | 
1469  | 0  |     } else { | 
1470  |  |       // Expression  | 
1471  | 0  |       AArch64_set_detail_op_imm(  | 
1472  | 0  |         MI, OpNum, AARCH64_OP_IMM,  | 
1473  | 0  |         MCOperand_isImm(MCInst_getOperand(MI, OpNum)));  | 
1474  | 0  |     }  | 
1475  | 0  |     break;  | 
1476  | 465k  |   }  | 
1477  | 4.87k  |   case AArch64_OP_GROUP_AdrAdrpLabel: { | 
1478  | 4.87k  |     if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum))) { | 
1479  |  |       // Expression  | 
1480  | 0  |       AArch64_set_detail_op_imm(  | 
1481  | 0  |         MI, OpNum, AARCH64_OP_IMM,  | 
1482  | 0  |         MCOperand_isImm(MCInst_getOperand(MI, OpNum)));  | 
1483  | 0  |       break;  | 
1484  | 0  |     }  | 
1485  | 4.87k  |     int64_t Offset = MCInst_getOpVal(MI, OpNum);  | 
1486  | 4.87k  |     uint64_t Address = MI->address;  | 
1487  | 4.87k  |     if (MCInst_getOpcode(MI) == AArch64_ADRP) { | 
1488  | 2.03k  |       Offset = Offset * 4096;  | 
1489  | 2.03k  |       Address = Address & -4096;  | 
1490  | 2.03k  |     }  | 
1491  | 4.87k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1492  | 4.87k  |             Address + Offset);  | 
1493  | 4.87k  |     break;  | 
1494  | 4.87k  |   }  | 
1495  | 11.8k  |   case AArch64_OP_GROUP_AlignedLabel: { | 
1496  | 11.8k  |     if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) { | 
1497  | 11.6k  |       int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4;  | 
1498  | 11.6k  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1499  | 11.6k  |               MI->address + Offset);  | 
1500  | 11.6k  |     } else { | 
1501  |  |       // Expression  | 
1502  | 211  |       AArch64_set_detail_op_imm(  | 
1503  | 211  |         MI, OpNum, AARCH64_OP_IMM,  | 
1504  | 211  |         MCOperand_isImm(MCInst_getOperand(MI, OpNum)));  | 
1505  | 211  |     }  | 
1506  | 11.8k  |     break;  | 
1507  | 4.87k  |   }  | 
1508  | 0  |   case AArch64_OP_GROUP_AMNoIndex: { | 
1509  | 0  |     AArch64_set_detail_op_mem(MI, OpNum,  | 
1510  | 0  |             MCInst_getOpVal(MI, OpNum));  | 
1511  | 0  |     break;  | 
1512  | 4.87k  |   }  | 
1513  | 7.11k  |   case AArch64_OP_GROUP_ArithExtend: { | 
1514  | 7.11k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1515  | 7.11k  |     AArch64_AM_ShiftExtendType ExtType =  | 
1516  | 7.11k  |       AArch64_AM_getArithExtendType(Val);  | 
1517  | 7.11k  |     unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);  | 
1518  |  |  | 
1519  | 7.11k  |     AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ExtType);  | 
1520  | 7.11k  |     AArch64_get_detail_op(MI, -1)->shift.value = ShiftVal;  | 
1521  | 7.11k  |     AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;  | 
1522  | 7.11k  |     break;  | 
1523  | 4.87k  |   }  | 
1524  | 381  |   case AArch64_OP_GROUP_BarriernXSOption: { | 
1525  | 381  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1526  | 381  |     aarch64_sysop sysop = { 0 }; | 
1527  | 381  |     const AArch64DBnXS_DBnXS *DB =  | 
1528  | 381  |       AArch64DBnXS_lookupDBnXSByEncoding(Val);  | 
1529  | 381  |     if (DB)  | 
1530  | 381  |       sysop.imm.dbnxs = (aarch64_dbnxs)DB->SysImm.dbnxs;  | 
1531  | 0  |     else  | 
1532  | 0  |       sysop.imm.raw_val = Val;  | 
1533  | 381  |     sysop.sub_type = AARCH64_OP_DBNXS;  | 
1534  | 381  |     AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSIMM);  | 
1535  | 381  |     break;  | 
1536  | 4.87k  |   }  | 
1537  | 640  |   case AArch64_OP_GROUP_AppleSysBarrierOption: { | 
1538  |  |     // Proprietary stuff. We just add the  | 
1539  |  |     // immediate here.  | 
1540  | 640  |     unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));  | 
1541  | 640  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);  | 
1542  | 640  |     break;  | 
1543  | 4.87k  |   }  | 
1544  | 992  |   case AArch64_OP_GROUP_BarrierOption: { | 
1545  | 992  |     unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));  | 
1546  | 992  |     unsigned Opcode = MCInst_getOpcode(MI);  | 
1547  | 992  |     aarch64_sysop sysop = { 0 }; | 
1548  |  |  | 
1549  | 992  |     if (Opcode == AArch64_ISB) { | 
1550  | 34  |       const AArch64ISB_ISB *ISB =  | 
1551  | 34  |         AArch64ISB_lookupISBByEncoding(Val);  | 
1552  | 34  |       if (ISB)  | 
1553  | 0  |         sysop.alias.isb =  | 
1554  | 0  |           (aarch64_isb)ISB->SysAlias.isb;  | 
1555  | 34  |       else  | 
1556  | 34  |         sysop.alias.raw_val = Val;  | 
1557  | 34  |       sysop.sub_type = AARCH64_OP_ISB;  | 
1558  | 34  |       AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1559  | 34  |               AARCH64_OP_SYSALIAS);  | 
1560  | 958  |     } else if (Opcode == AArch64_TSB) { | 
1561  | 131  |       const AArch64TSB_TSB *TSB =  | 
1562  | 131  |         AArch64TSB_lookupTSBByEncoding(Val);  | 
1563  | 131  |       if (TSB)  | 
1564  | 131  |         sysop.alias.tsb =  | 
1565  | 131  |           (aarch64_tsb)TSB->SysAlias.tsb;  | 
1566  | 0  |       else  | 
1567  | 0  |         sysop.alias.raw_val = Val;  | 
1568  | 131  |       sysop.sub_type = AARCH64_OP_TSB;  | 
1569  | 131  |       AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1570  | 131  |               AARCH64_OP_SYSALIAS);  | 
1571  | 827  |     } else { | 
1572  | 827  |       const AArch64DB_DB *DB =  | 
1573  | 827  |         AArch64DB_lookupDBByEncoding(Val);  | 
1574  | 827  |       if (DB)  | 
1575  | 126  |         sysop.alias.db = (aarch64_db)DB->SysAlias.db;  | 
1576  | 701  |       else  | 
1577  | 701  |         sysop.alias.raw_val = Val;  | 
1578  | 827  |       sysop.sub_type = AARCH64_OP_DB;  | 
1579  | 827  |       AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1580  | 827  |               AARCH64_OP_SYSALIAS);  | 
1581  | 827  |     }  | 
1582  | 992  |     break;  | 
1583  | 4.87k  |   }  | 
1584  | 520  |   case AArch64_OP_GROUP_BTIHintOp: { | 
1585  | 520  |     aarch64_sysop sysop = { 0 }; | 
1586  | 520  |     unsigned btihintop = MCInst_getOpVal(MI, OpNum) ^ 32;  | 
1587  | 520  |     const AArch64BTIHint_BTI *BTI =  | 
1588  | 520  |       AArch64BTIHint_lookupBTIByEncoding(btihintop);  | 
1589  | 520  |     if (BTI)  | 
1590  | 520  |       sysop.alias.bti = (aarch64_bti)BTI->SysAlias.bti;  | 
1591  | 0  |     else  | 
1592  | 0  |       sysop.alias.raw_val = btihintop;  | 
1593  | 520  |     sysop.sub_type = AARCH64_OP_BTI;  | 
1594  | 520  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1595  | 520  |             AARCH64_OP_SYSALIAS);  | 
1596  | 520  |     break;  | 
1597  | 4.87k  |   }  | 
1598  | 3.14k  |   case AArch64_OP_GROUP_CondCode: { | 
1599  | 3.14k  |     AArch64_get_detail(MI)->cc = MCInst_getOpVal(MI, OpNum);  | 
1600  | 3.14k  |     break;  | 
1601  | 4.87k  |   }  | 
1602  | 5.44k  |   case AArch64_OP_GROUP_ExtendedRegister: { | 
1603  | 5.44k  |     AArch64_set_detail_op_reg(MI, OpNum,  | 
1604  | 5.44k  |             MCInst_getOpVal(MI, OpNum));  | 
1605  | 5.44k  |     break;  | 
1606  | 4.87k  |   }  | 
1607  | 592  |   case AArch64_OP_GROUP_FPImmOperand: { | 
1608  | 592  |     MCOperand *MO = MCInst_getOperand(MI, (OpNum));  | 
1609  | 592  |     float FPImm =  | 
1610  | 592  |       MCOperand_isDFPImm(MO) ?  | 
1611  | 0  |         BitsToDouble(MCOperand_getImm(MO)) :  | 
1612  | 592  |         AArch64_AM_getFPImmFloat(MCOperand_getImm(MO));  | 
1613  | 592  |     AArch64_set_detail_op_float(MI, OpNum, FPImm);  | 
1614  | 592  |     break;  | 
1615  | 4.87k  |   }  | 
1616  | 10.0k  |   case AArch64_OP_GROUP_GPR64as32: { | 
1617  | 10.0k  |     unsigned Reg = MCInst_getOpVal(MI, OpNum);  | 
1618  | 10.0k  |     AArch64_set_detail_op_reg(MI, OpNum, getWRegFromXReg(Reg));  | 
1619  | 10.0k  |     break;  | 
1620  | 4.87k  |   }  | 
1621  | 138  |   case AArch64_OP_GROUP_GPR64x8: { | 
1622  | 138  |     unsigned Reg = MCInst_getOpVal(MI, (OpNum));  | 
1623  | 138  |     Reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, AArch64_x8sub_0);  | 
1624  | 138  |     AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
1625  | 138  |     break;  | 
1626  | 4.87k  |   }  | 
1627  | 7.36k  |   case AArch64_OP_GROUP_Imm:  | 
1628  | 8.00k  |   case AArch64_OP_GROUP_ImmHex:  | 
1629  | 8.00k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1630  | 8.00k  |             MCInst_getOpVal(MI, OpNum));  | 
1631  | 8.00k  |     break;  | 
1632  | 0  |   case AArch64_OP_GROUP_ImplicitlyTypedVectorList:  | 
1633  |  |     // The TypedVectorList implements the logic of implicitly typed operand.  | 
1634  | 0  |     AArch64_add_cs_detail_2(  | 
1635  | 0  |       MI, AArch64_OP_GROUP_TypedVectorList_0_b, OpNum, 0, 0);  | 
1636  | 0  |     break;  | 
1637  | 712  |   case AArch64_OP_GROUP_InverseCondCode: { | 
1638  | 712  |     AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(  | 
1639  | 712  |       MCInst_getOperand(MI, (OpNum)));  | 
1640  | 712  |     AArch64_get_detail(MI)->cc = AArch64CC_getInvertedCondCode(CC);  | 
1641  | 712  |     break;  | 
1642  | 7.36k  |   }  | 
1643  | 2.64k  |   case AArch64_OP_GROUP_MatrixTile: { | 
1644  | 2.64k  |     const char *RegName = AArch64_LLVM_getRegisterName(  | 
1645  | 2.64k  |       MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);  | 
1646  | 2.64k  |     const char *Dot = strstr(RegName, ".");  | 
1647  | 2.64k  |     AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;  | 
1648  | 2.64k  |     if (!Dot) { | 
1649  |  |       // The matrix dimensions are machine dependent.  | 
1650  |  |       // Currently we do not support differentiation of machines.  | 
1651  |  |       // So we just indicate the use of the complete matrix.  | 
1652  | 0  |       vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));  | 
1653  | 0  |     } else  | 
1654  | 2.64k  |       vas = get_vl_by_suffix(Dot[1]);  | 
1655  | 2.64k  |     AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,  | 
1656  | 2.64k  |             vas);  | 
1657  | 2.64k  |     break;  | 
1658  | 7.36k  |   }  | 
1659  | 907  |   case AArch64_OP_GROUP_MatrixTileList: { | 
1660  | 907  |     unsigned MaxRegs = 8;  | 
1661  | 907  |     unsigned RegMask = MCInst_getOpVal(MI, (OpNum));  | 
1662  |  |  | 
1663  | 8.16k  |     for (unsigned I = 0; I < MaxRegs; ++I) { | 
1664  | 7.25k  |       unsigned Reg = RegMask & (1 << I);  | 
1665  | 7.25k  |       if (Reg == 0)  | 
1666  | 2.85k  |         continue;  | 
1667  | 4.39k  |       AArch64_get_detail_op(MI, 0)->is_list_member = true;  | 
1668  | 4.39k  |       AArch64_set_detail_op_sme(MI, OpNum,  | 
1669  | 4.39k  |               AARCH64_SME_MATRIX_TILE_LIST,  | 
1670  | 4.39k  |               AARCH64LAYOUT_VL_D,  | 
1671  | 4.39k  |               (int)(AARCH64_REG_ZAD0 + I));  | 
1672  | 4.39k  |       AArch64_inc_op_count(MI);  | 
1673  | 4.39k  |     }  | 
1674  | 907  |     AArch64_get_detail(MI)->is_doing_sme = false;  | 
1675  | 907  |     break;  | 
1676  | 7.36k  |   }  | 
1677  | 3.11k  |   case AArch64_OP_GROUP_MRSSystemRegister:  | 
1678  | 9.49k  |   case AArch64_OP_GROUP_MSRSystemRegister: { | 
1679  | 9.49k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1680  | 9.49k  |     const AArch64SysReg_SysReg *Reg =  | 
1681  | 9.49k  |       AArch64SysReg_lookupSysRegByEncoding(Val);  | 
1682  | 9.49k  |     bool Read = (op_group == AArch64_OP_GROUP_MRSSystemRegister) ?  | 
1683  | 9.49k  |             true :  | 
1684  | 9.49k  |             false;  | 
1685  |  |  | 
1686  | 9.49k  |     bool isValidSysReg =  | 
1687  | 9.49k  |       (Reg && (Read ? Reg->Readable : Reg->Writeable) &&  | 
1688  | 1.02k  |        AArch64_testFeatureList(MI->csh->mode,  | 
1689  | 1.02k  |              Reg->FeaturesRequired));  | 
1690  |  |  | 
1691  | 9.49k  |     if (Reg && !isValidSysReg)  | 
1692  | 1.73k  |       Reg = AArch64SysReg_lookupSysRegByName(Reg->AltName);  | 
1693  | 9.49k  |     aarch64_sysop sysop = { 0 }; | 
1694  |  |     // If Reg is NULL it is a generic system register.  | 
1695  | 9.49k  |     if (Reg)  | 
1696  | 2.73k  |       sysop.reg.sysreg = (aarch64_sysreg)Reg->SysReg.sysreg;  | 
1697  | 6.76k  |     else { | 
1698  | 6.76k  |       sysop.reg.raw_val = Val;  | 
1699  | 6.76k  |     }  | 
1700  | 9.49k  |     aarch64_op_type type =  | 
1701  | 9.49k  |       (op_group == AArch64_OP_GROUP_MRSSystemRegister) ?  | 
1702  | 3.11k  |         AARCH64_OP_REG_MRS :  | 
1703  | 9.49k  |         AARCH64_OP_REG_MSR;  | 
1704  | 9.49k  |     sysop.sub_type = type;  | 
1705  | 9.49k  |     AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSREG);  | 
1706  | 9.49k  |     break;  | 
1707  | 3.11k  |   }  | 
1708  | 342  |   case AArch64_OP_GROUP_PSBHintOp: { | 
1709  | 342  |     unsigned psbhintop = MCInst_getOpVal(MI, OpNum);  | 
1710  | 342  |     const AArch64PSBHint_PSB *PSB =  | 
1711  | 342  |       AArch64PSBHint_lookupPSBByEncoding(psbhintop);  | 
1712  | 342  |     aarch64_sysop sysop = { 0 }; | 
1713  | 342  |     if (PSB)  | 
1714  | 342  |       sysop.alias.psb = (aarch64_psb)PSB->SysAlias.psb;  | 
1715  | 0  |     else  | 
1716  | 0  |       sysop.alias.raw_val = psbhintop;  | 
1717  | 342  |     sysop.sub_type = AARCH64_OP_PSB;  | 
1718  | 342  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1719  | 342  |             AARCH64_OP_SYSALIAS);  | 
1720  | 342  |     break;  | 
1721  | 3.11k  |   }  | 
1722  | 975  |   case AArch64_OP_GROUP_RPRFMOperand: { | 
1723  | 975  |     unsigned prfop = MCInst_getOpVal(MI, OpNum);  | 
1724  | 975  |     const AArch64PRFM_PRFM *PRFM =  | 
1725  | 975  |       AArch64PRFM_lookupPRFMByEncoding(prfop);  | 
1726  | 975  |     aarch64_sysop sysop = { 0 }; | 
1727  | 975  |     if (PRFM)  | 
1728  | 938  |       sysop.alias.prfm = (aarch64_prfm)PRFM->SysAlias.prfm;  | 
1729  | 37  |     else  | 
1730  | 37  |       sysop.alias.raw_val = prfop;  | 
1731  | 975  |     sysop.sub_type = AARCH64_OP_PRFM;  | 
1732  | 975  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1733  | 975  |             AARCH64_OP_SYSALIAS);  | 
1734  | 975  |     break;  | 
1735  | 3.11k  |   }  | 
1736  | 6.29k  |   case AArch64_OP_GROUP_ShiftedRegister: { | 
1737  | 6.29k  |     AArch64_set_detail_op_reg(MI, OpNum,  | 
1738  | 6.29k  |             MCInst_getOpVal(MI, OpNum));  | 
1739  |  |     // Shift part is handled in printShifter()  | 
1740  | 6.29k  |     break;  | 
1741  | 3.11k  |   }  | 
1742  | 14.4k  |   case AArch64_OP_GROUP_Shifter: { | 
1743  | 14.4k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1744  | 14.4k  |     AArch64_AM_ShiftExtendType ShExtType =  | 
1745  | 14.4k  |       AArch64_AM_getShiftType(Val);  | 
1746  | 14.4k  |     AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ShExtType);  | 
1747  | 14.4k  |     AArch64_get_detail_op(MI, -1)->shift.type =  | 
1748  | 14.4k  |       llvm_to_cs_shift(ShExtType);  | 
1749  | 14.4k  |     AArch64_get_detail_op(MI, -1)->shift.value =  | 
1750  | 14.4k  |       AArch64_AM_getShiftValue(Val);  | 
1751  | 14.4k  |     break;  | 
1752  | 3.11k  |   }  | 
1753  | 1.15k  |   case AArch64_OP_GROUP_SIMDType10Operand: { | 
1754  | 1.15k  |     unsigned RawVal = MCInst_getOpVal(MI, OpNum);  | 
1755  | 1.15k  |     uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);  | 
1756  | 1.15k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);  | 
1757  | 1.15k  |     break;  | 
1758  | 3.11k  |   }  | 
1759  | 0  |   case AArch64_OP_GROUP_SVCROp: { | 
1760  | 0  |     unsigned svcrop = MCInst_getOpVal(MI, OpNum);  | 
1761  | 0  |     const AArch64SVCR_SVCR *SVCR =  | 
1762  | 0  |       AArch64SVCR_lookupSVCRByEncoding(svcrop);  | 
1763  | 0  |     aarch64_sysop sysop = { 0 }; | 
1764  | 0  |     if (SVCR)  | 
1765  | 0  |       sysop.alias.svcr = (aarch64_svcr)SVCR->SysAlias.svcr;  | 
1766  | 0  |     else  | 
1767  | 0  |       sysop.alias.raw_val = svcrop;  | 
1768  | 0  |     sysop.sub_type = AARCH64_OP_SVCR;  | 
1769  | 0  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1770  | 0  |             AARCH64_OP_SYSALIAS);  | 
1771  | 0  |     break;  | 
1772  | 3.11k  |   }  | 
1773  | 10.8k  |   case AArch64_OP_GROUP_SVEPattern: { | 
1774  | 10.8k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1775  | 10.8k  |     const AArch64SVEPredPattern_SVEPREDPAT *Pat =  | 
1776  | 10.8k  |       AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);  | 
1777  | 10.8k  |     if (!Pat) { | 
1778  | 2.81k  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1779  | 2.81k  |               Val);  | 
1780  | 2.81k  |       break;  | 
1781  | 2.81k  |     }  | 
1782  | 8.04k  |     aarch64_sysop sysop = { 0 }; | 
1783  | 8.04k  |     sysop.alias = Pat->SysAlias;  | 
1784  | 8.04k  |     sysop.sub_type = AARCH64_OP_SVEPREDPAT;  | 
1785  | 8.04k  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1786  | 8.04k  |             AARCH64_OP_SYSALIAS);  | 
1787  | 8.04k  |     break;  | 
1788  | 10.8k  |   }  | 
1789  | 1.24k  |   case AArch64_OP_GROUP_SVEVecLenSpecifier: { | 
1790  | 1.24k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1791  |  |     // Pattern has only 1 bit  | 
1792  | 1.24k  |     if (Val > 1)  | 
1793  | 0  |       CS_ASSERT_RET(0 && "Invalid vector length specifier");  | 
1794  | 1.24k  |     const AArch64SVEVecLenSpecifier_SVEVECLENSPECIFIER *Pat =  | 
1795  | 1.24k  |       AArch64SVEVecLenSpecifier_lookupSVEVECLENSPECIFIERByEncoding(  | 
1796  | 1.24k  |         Val);  | 
1797  | 1.24k  |     if (!Pat)  | 
1798  | 0  |       break;  | 
1799  | 1.24k  |     aarch64_sysop sysop = { 0 }; | 
1800  | 1.24k  |     sysop.alias = Pat->SysAlias;  | 
1801  | 1.24k  |     sysop.sub_type = AARCH64_OP_SVEVECLENSPECIFIER;  | 
1802  | 1.24k  |     AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1803  | 1.24k  |             AARCH64_OP_SYSALIAS);  | 
1804  | 1.24k  |     break;  | 
1805  | 1.24k  |   }  | 
1806  | 10.4k  |   case AArch64_OP_GROUP_SysCROperand: { | 
1807  | 10.4k  |     uint64_t cimm = MCInst_getOpVal(MI, OpNum);  | 
1808  | 10.4k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_CIMM, cimm);  | 
1809  | 10.4k  |     break;  | 
1810  | 1.24k  |   }  | 
1811  | 1.78k  |   case AArch64_OP_GROUP_SyspXzrPair: { | 
1812  | 1.78k  |     unsigned Reg = MCInst_getOpVal(MI, OpNum);  | 
1813  | 1.78k  |     AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
1814  | 1.78k  |     AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
1815  | 1.78k  |     break;  | 
1816  | 1.24k  |   }  | 
1817  | 1.63k  |   case AArch64_OP_GROUP_SystemPStateField: { | 
1818  | 1.63k  |     unsigned Val = MCInst_getOpVal(MI, OpNum);  | 
1819  |  |  | 
1820  | 1.63k  |     aarch64_sysop sysop = { 0 }; | 
1821  | 1.63k  |     const AArch64PState_PStateImm0_15 *PStateImm15 =  | 
1822  | 1.63k  |       AArch64PState_lookupPStateImm0_15ByEncoding(Val);  | 
1823  | 1.63k  |     const AArch64PState_PStateImm0_1 *PStateImm1 =  | 
1824  | 1.63k  |       AArch64PState_lookupPStateImm0_1ByEncoding(Val);  | 
1825  | 1.63k  |     if (PStateImm15 &&  | 
1826  | 1.45k  |         AArch64_testFeatureList(MI->csh->mode,  | 
1827  | 1.45k  |               PStateImm15->FeaturesRequired)) { | 
1828  | 1.45k  |       sysop.alias = PStateImm15->SysAlias;  | 
1829  | 1.45k  |       sysop.sub_type = AARCH64_OP_PSTATEIMM0_15;  | 
1830  | 1.45k  |       AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1831  | 1.45k  |               AARCH64_OP_SYSALIAS);  | 
1832  | 1.45k  |     } else if (PStateImm1 &&  | 
1833  | 179  |          AArch64_testFeatureList(  | 
1834  | 179  |            MI->csh->mode,  | 
1835  | 179  |            PStateImm1->FeaturesRequired)) { | 
1836  | 179  |       sysop.alias = PStateImm1->SysAlias;  | 
1837  | 179  |       sysop.sub_type = AARCH64_OP_PSTATEIMM0_1;  | 
1838  | 179  |       AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
1839  | 179  |               AARCH64_OP_SYSALIAS);  | 
1840  | 179  |     } else { | 
1841  | 0  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1842  | 0  |               Val);  | 
1843  | 0  |     }  | 
1844  | 1.63k  |     break;  | 
1845  | 1.24k  |   }  | 
1846  | 90.8k  |   case AArch64_OP_GROUP_VRegOperand: { | 
1847  | 90.8k  |     unsigned Reg = MCInst_getOpVal(MI, OpNum);  | 
1848  | 90.8k  |     AArch64_get_detail_op(MI, 0)->is_vreg = true;  | 
1849  | 90.8k  |     AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
1850  | 90.8k  |     break;  | 
1851  | 1.24k  |   }  | 
1852  | 675k  |   }  | 
1853  | 675k  | }  | 
1854  |  |  | 
1855  |  | /// Fills cs_detail with the data of the operand.  | 
1856  |  | /// This function handles operands which original printer function is a template  | 
1857  |  | /// with one argument.  | 
1858  |  | void AArch64_add_cs_detail_1(MCInst *MI, aarch64_op_group op_group,  | 
1859  |  |            unsigned OpNum, uint64_t temp_arg_0)  | 
1860  | 377k  | { | 
1861  | 377k  |   if (!add_cs_detail_begin(MI, OpNum))  | 
1862  | 0  |     return;  | 
1863  | 377k  |   switch (op_group) { | 
1864  | 0  |   default:  | 
1865  | 0  |     printf("ERROR: Operand group %d not handled!\n", op_group); | 
1866  | 0  |     CS_ASSERT_RET(0);  | 
1867  | 614  |   case AArch64_OP_GROUP_GPRSeqPairsClassOperand_32:  | 
1868  | 2.81k  |   case AArch64_OP_GROUP_GPRSeqPairsClassOperand_64: { | 
1869  | 2.81k  |     unsigned size = temp_arg_0;  | 
1870  | 2.81k  |     unsigned Reg = MCInst_getOpVal(MI, (OpNum));  | 
1871  |  |  | 
1872  | 2.81k  |     unsigned Sube = (size == 32) ? AArch64_sube32 : AArch64_sube64;  | 
1873  | 2.81k  |     unsigned Subo = (size == 32) ? AArch64_subo32 : AArch64_subo64;  | 
1874  |  |  | 
1875  | 2.81k  |     unsigned Even = MCRegisterInfo_getSubReg(MI->MRI, Reg, Sube);  | 
1876  | 2.81k  |     unsigned Odd = MCRegisterInfo_getSubReg(MI->MRI, Reg, Subo);  | 
1877  | 2.81k  |     AArch64_set_detail_op_reg(MI, OpNum, Even);  | 
1878  | 2.81k  |     AArch64_set_detail_op_reg(MI, OpNum, Odd);  | 
1879  | 2.81k  |     break;  | 
1880  | 614  |   }  | 
1881  | 410  |   case AArch64_OP_GROUP_Imm8OptLsl_int16_t:  | 
1882  | 764  |   case AArch64_OP_GROUP_Imm8OptLsl_int32_t:  | 
1883  | 1.81k  |   case AArch64_OP_GROUP_Imm8OptLsl_int64_t:  | 
1884  | 2.79k  |   case AArch64_OP_GROUP_Imm8OptLsl_int8_t:  | 
1885  | 3.14k  |   case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:  | 
1886  | 3.50k  |   case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:  | 
1887  | 3.91k  |   case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:  | 
1888  | 4.02k  |   case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: { | 
1889  | 4.02k  |     unsigned UnscaledVal = MCInst_getOpVal(MI, (OpNum));  | 
1890  | 4.02k  |     unsigned Shift = MCInst_getOpVal(MI, (OpNum + 1));  | 
1891  |  |  | 
1892  | 4.02k  |     if ((UnscaledVal == 0) &&  | 
1893  | 2.20k  |         (AArch64_AM_getShiftValue(Shift) != 0)) { | 
1894  | 572  |       AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1895  | 572  |               UnscaledVal);  | 
1896  |  |       // Shift is handled in printShifter()  | 
1897  | 572  |       break;  | 
1898  | 572  |     }  | 
1899  |  |  | 
1900  | 3.45k  | #define SCALE_SET(T) \  | 
1901  | 3.45k  |   do { \ | 
1902  | 3.45k  |     T Val; \  | 
1903  | 3.45k  |     if (CHAR(T) == 'i') /* Signed */ \  | 
1904  | 3.45k  |       Val = (int8_t)UnscaledVal * \  | 
1905  | 2.64k  |             (1 << AArch64_AM_getShiftValue(Shift)); \  | 
1906  | 3.45k  |     else \  | 
1907  | 3.45k  |       Val = (uint8_t)UnscaledVal * \  | 
1908  | 812  |             (1 << AArch64_AM_getShiftValue(Shift)); \  | 
1909  | 3.45k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val); \  | 
1910  | 3.45k  |   } while (0)  | 
1911  |  |  | 
1912  | 3.45k  |     switch (op_group) { | 
1913  | 0  |     default:  | 
1914  | 0  |       CS_ASSERT_RET(  | 
1915  | 0  |         0 &&  | 
1916  | 0  |         "Operand group for Imm8OptLsl not handled.");  | 
1917  | 342  |     case AArch64_OP_GROUP_Imm8OptLsl_int16_t: { | 
1918  | 342  |       SCALE_SET(int16_t);  | 
1919  | 342  |       break;  | 
1920  | 0  |     }  | 
1921  | 286  |     case AArch64_OP_GROUP_Imm8OptLsl_int32_t: { | 
1922  | 286  |       SCALE_SET(int32_t);  | 
1923  | 286  |       break;  | 
1924  | 0  |     }  | 
1925  | 1.03k  |     case AArch64_OP_GROUP_Imm8OptLsl_int64_t: { | 
1926  | 1.03k  |       SCALE_SET(int64_t);  | 
1927  | 1.03k  |       break;  | 
1928  | 0  |     }  | 
1929  | 982  |     case AArch64_OP_GROUP_Imm8OptLsl_int8_t: { | 
1930  | 982  |       SCALE_SET(int8_t);  | 
1931  | 982  |       break;  | 
1932  | 0  |     }  | 
1933  | 327  |     case AArch64_OP_GROUP_Imm8OptLsl_uint16_t: { | 
1934  | 327  |       SCALE_SET(uint16_t);  | 
1935  | 327  |       break;  | 
1936  | 0  |     }  | 
1937  | 143  |     case AArch64_OP_GROUP_Imm8OptLsl_uint32_t: { | 
1938  | 143  |       SCALE_SET(uint32_t);  | 
1939  | 143  |       break;  | 
1940  | 0  |     }  | 
1941  | 234  |     case AArch64_OP_GROUP_Imm8OptLsl_uint64_t: { | 
1942  | 234  |       SCALE_SET(uint64_t);  | 
1943  | 234  |       break;  | 
1944  | 0  |     }  | 
1945  | 108  |     case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: { | 
1946  | 108  |       SCALE_SET(uint8_t);  | 
1947  | 108  |       break;  | 
1948  | 0  |     }  | 
1949  | 3.45k  |     }  | 
1950  | 3.45k  |     break;  | 
1951  | 3.45k  |   }  | 
1952  | 4.75k  |   case AArch64_OP_GROUP_ImmScale_16:  | 
1953  | 7.52k  |   case AArch64_OP_GROUP_ImmScale_2:  | 
1954  | 7.66k  |   case AArch64_OP_GROUP_ImmScale_3:  | 
1955  | 7.78k  |   case AArch64_OP_GROUP_ImmScale_32:  | 
1956  | 18.1k  |   case AArch64_OP_GROUP_ImmScale_4:  | 
1957  | 25.3k  |   case AArch64_OP_GROUP_ImmScale_8: { | 
1958  | 25.3k  |     unsigned Scale = temp_arg_0;  | 
1959  | 25.3k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
1960  | 25.3k  |             Scale * MCInst_getOpVal(MI, OpNum));  | 
1961  | 25.3k  |     break;  | 
1962  | 18.1k  |   }  | 
1963  | 1.58k  |   case AArch64_OP_GROUP_LogicalImm_int16_t:  | 
1964  | 4.69k  |   case AArch64_OP_GROUP_LogicalImm_int32_t:  | 
1965  | 8.73k  |   case AArch64_OP_GROUP_LogicalImm_int64_t:  | 
1966  | 11.2k  |   case AArch64_OP_GROUP_LogicalImm_int8_t: { | 
1967  | 11.2k  |     unsigned TypeSize = temp_arg_0;  | 
1968  | 11.2k  |     uint64_t Val = AArch64_AM_decodeLogicalImmediate(  | 
1969  | 11.2k  |       MCInst_getOpVal(MI, OpNum), 8 * TypeSize);  | 
1970  | 11.2k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);  | 
1971  | 11.2k  |     break;  | 
1972  | 8.73k  |   }  | 
1973  | 277  |   case AArch64_OP_GROUP_Matrix_0:  | 
1974  | 1.64k  |   case AArch64_OP_GROUP_Matrix_16:  | 
1975  | 6.51k  |   case AArch64_OP_GROUP_Matrix_32:  | 
1976  | 10.1k  |   case AArch64_OP_GROUP_Matrix_64: { | 
1977  | 10.1k  |     unsigned EltSize = temp_arg_0;  | 
1978  | 10.1k  |     AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,  | 
1979  | 10.1k  |             (AArch64Layout_VectorLayout)EltSize);  | 
1980  | 10.1k  |     break;  | 
1981  | 6.51k  |   }  | 
1982  | 0  |   case AArch64_OP_GROUP_MatrixIndex_0:  | 
1983  | 11.9k  |   case AArch64_OP_GROUP_MatrixIndex_1:  | 
1984  | 13.1k  |   case AArch64_OP_GROUP_MatrixIndex_8: { | 
1985  | 13.1k  |     unsigned scale = temp_arg_0;  | 
1986  | 13.1k  |     if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) { | 
1987  |  |       // The index is part of an SME matrix  | 
1988  | 10.8k  |       AArch64_set_detail_op_sme(  | 
1989  | 10.8k  |         MI, OpNum, AARCH64_SME_MATRIX_SLICE_OFF,  | 
1990  | 10.8k  |         AARCH64LAYOUT_INVALID,  | 
1991  | 10.8k  |         (uint32_t)(MCInst_getOpVal(MI, OpNum) * scale));  | 
1992  | 10.8k  |     } else if (AArch64_get_detail_op(MI, 0)->type ==  | 
1993  | 2.30k  |          AARCH64_OP_PRED) { | 
1994  |  |       // The index is part of a predicate  | 
1995  | 661  |       AArch64_set_detail_op_pred(MI, OpNum);  | 
1996  | 1.64k  |     } else { | 
1997  |  |       // The index is used for an SVE2 instruction.  | 
1998  | 1.64k  |       AArch64_set_detail_op_imm(  | 
1999  | 1.64k  |         MI, OpNum, AARCH64_OP_IMM,  | 
2000  | 1.64k  |         scale * MCInst_getOpVal(MI, OpNum));  | 
2001  | 1.64k  |     }  | 
2002  | 13.1k  |     break;  | 
2003  | 11.9k  |   }  | 
2004  | 4.72k  |   case AArch64_OP_GROUP_MatrixTileVector_0:  | 
2005  | 8.95k  |   case AArch64_OP_GROUP_MatrixTileVector_1: { | 
2006  | 8.95k  |     bool isVertical = temp_arg_0;  | 
2007  | 8.95k  |     const char *RegName = AArch64_LLVM_getRegisterName(  | 
2008  | 8.95k  |       MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);  | 
2009  | 8.95k  |     const char *Dot = strstr(RegName, ".");  | 
2010  | 8.95k  |     AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;  | 
2011  | 8.95k  |     if (!Dot) { | 
2012  |  |       // The matrix dimensions are machine dependent.  | 
2013  |  |       // Currently we do not support differentiation of machines.  | 
2014  |  |       // So we just indicate the use of the complete matrix.  | 
2015  | 0  |       vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));  | 
2016  | 0  |     } else  | 
2017  | 8.95k  |       vas = get_vl_by_suffix(Dot[1]);  | 
2018  | 8.95k  |     setup_sme_operand(MI);  | 
2019  | 8.95k  |     AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,  | 
2020  | 8.95k  |             vas);  | 
2021  | 8.95k  |     AArch64_get_detail_op(MI, 0)->sme.is_vertical = isVertical;  | 
2022  | 8.95k  |     break;  | 
2023  | 4.72k  |   }  | 
2024  | 1.17k  |   case AArch64_OP_GROUP_PostIncOperand_1:  | 
2025  | 1.42k  |   case AArch64_OP_GROUP_PostIncOperand_12:  | 
2026  | 3.49k  |   case AArch64_OP_GROUP_PostIncOperand_16:  | 
2027  | 4.54k  |   case AArch64_OP_GROUP_PostIncOperand_2:  | 
2028  | 5.37k  |   case AArch64_OP_GROUP_PostIncOperand_24:  | 
2029  | 6.38k  |   case AArch64_OP_GROUP_PostIncOperand_3:  | 
2030  | 7.29k  |   case AArch64_OP_GROUP_PostIncOperand_32:  | 
2031  | 8.37k  |   case AArch64_OP_GROUP_PostIncOperand_4:  | 
2032  | 8.84k  |   case AArch64_OP_GROUP_PostIncOperand_48:  | 
2033  | 10.1k  |   case AArch64_OP_GROUP_PostIncOperand_6:  | 
2034  | 10.2k  |   case AArch64_OP_GROUP_PostIncOperand_64:  | 
2035  | 13.5k  |   case AArch64_OP_GROUP_PostIncOperand_8: { | 
2036  | 13.5k  |     uint64_t Imm = temp_arg_0;  | 
2037  | 13.5k  |     unsigned Reg = MCInst_getOpVal(MI, OpNum);  | 
2038  | 13.5k  |     if (Reg == AArch64_XZR) { | 
2039  | 0  |       AArch64_get_detail_op(MI, -1)->mem.disp = Imm;  | 
2040  | 0  |       AArch64_get_detail(MI)->post_index = true;  | 
2041  | 0  |       AArch64_inc_op_count(MI);  | 
2042  | 0  |     } else  | 
2043  | 13.5k  |       AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
2044  | 13.5k  |     break;  | 
2045  | 10.2k  |   }  | 
2046  | 13.5k  |   case AArch64_OP_GROUP_PredicateAsCounter_0:  | 
2047  | 13.8k  |   case AArch64_OP_GROUP_PredicateAsCounter_16:  | 
2048  | 14.1k  |   case AArch64_OP_GROUP_PredicateAsCounter_32:  | 
2049  | 14.4k  |   case AArch64_OP_GROUP_PredicateAsCounter_64:  | 
2050  | 14.8k  |   case AArch64_OP_GROUP_PredicateAsCounter_8: { | 
2051  | 14.8k  |     unsigned EltSize = temp_arg_0;  | 
2052  | 14.8k  |     AArch64_get_detail_op(MI, 0)->vas = EltSize;  | 
2053  | 14.8k  |     AArch64_set_detail_op_reg(MI, OpNum,  | 
2054  | 14.8k  |             MCInst_getOpVal(MI, OpNum));  | 
2055  | 14.8k  |     break;  | 
2056  | 14.4k  |   }  | 
2057  | 1.45k  |   case AArch64_OP_GROUP_PrefetchOp_0:  | 
2058  | 7.77k  |   case AArch64_OP_GROUP_PrefetchOp_1: { | 
2059  | 7.77k  |     bool IsSVEPrefetch = (bool)temp_arg_0;  | 
2060  | 7.77k  |     unsigned prfop = MCInst_getOpVal(MI, (OpNum));  | 
2061  | 7.77k  |     aarch64_sysop sysop = { 0 }; | 
2062  | 7.77k  |     if (IsSVEPrefetch) { | 
2063  | 6.32k  |       const AArch64SVEPRFM_SVEPRFM *PRFM =  | 
2064  | 6.32k  |         AArch64SVEPRFM_lookupSVEPRFMByEncoding(prfop);  | 
2065  | 6.32k  |       if (PRFM) { | 
2066  | 5.55k  |         sysop.alias = PRFM->SysAlias;  | 
2067  | 5.55k  |         sysop.sub_type = AARCH64_OP_SVEPRFM;  | 
2068  | 5.55k  |         AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
2069  | 5.55k  |                 AARCH64_OP_SYSALIAS);  | 
2070  | 5.55k  |         break;  | 
2071  | 5.55k  |       }  | 
2072  | 6.32k  |     } else { | 
2073  | 1.45k  |       const AArch64PRFM_PRFM *PRFM =  | 
2074  | 1.45k  |         AArch64PRFM_lookupPRFMByEncoding(prfop);  | 
2075  | 1.45k  |       if (PRFM &&  | 
2076  | 1.01k  |           AArch64_testFeatureList(MI->csh->mode,  | 
2077  | 1.01k  |                 PRFM->FeaturesRequired)) { | 
2078  | 1.01k  |         sysop.alias = PRFM->SysAlias;  | 
2079  | 1.01k  |         sysop.sub_type = AARCH64_OP_PRFM;  | 
2080  | 1.01k  |         AArch64_set_detail_op_sys(MI, OpNum, sysop,  | 
2081  | 1.01k  |                 AARCH64_OP_SYSALIAS);  | 
2082  | 1.01k  |         break;  | 
2083  | 1.01k  |       }  | 
2084  | 1.45k  |     }  | 
2085  | 1.20k  |     AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM;  | 
2086  | 1.20k  |     AArch64_get_detail_op(MI, 0)->imm = prfop;  | 
2087  | 1.20k  |     AArch64_get_detail_op(MI, 0)->access =  | 
2088  | 1.20k  |       map_get_op_access(MI, OpNum);  | 
2089  | 1.20k  |     AArch64_inc_op_count(MI);  | 
2090  | 1.20k  |     break;  | 
2091  | 7.77k  |   }  | 
2092  | 1.84k  |   case AArch64_OP_GROUP_SImm_16:  | 
2093  | 2.00k  |   case AArch64_OP_GROUP_SImm_8: { | 
2094  | 2.00k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
2095  | 2.00k  |             MCInst_getOpVal(MI, OpNum));  | 
2096  | 2.00k  |     break;  | 
2097  | 1.84k  |   }  | 
2098  | 1.72k  |   case AArch64_OP_GROUP_SVELogicalImm_int16_t:  | 
2099  | 2.99k  |   case AArch64_OP_GROUP_SVELogicalImm_int32_t:  | 
2100  | 3.97k  |   case AArch64_OP_GROUP_SVELogicalImm_int64_t: { | 
2101  |  |     // General issue here that we do not save the operand type  | 
2102  |  |     // for each operand. So we choose the largest type.  | 
2103  | 3.97k  |     uint64_t Val = MCInst_getOpVal(MI, OpNum);  | 
2104  | 3.97k  |     uint64_t DecodedVal =  | 
2105  | 3.97k  |       AArch64_AM_decodeLogicalImmediate(Val, 64);  | 
2106  | 3.97k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
2107  | 3.97k  |             DecodedVal);  | 
2108  | 3.97k  |     break;  | 
2109  | 2.99k  |   }  | 
2110  | 63.5k  |   case AArch64_OP_GROUP_SVERegOp_0:  | 
2111  | 98.0k  |   case AArch64_OP_GROUP_SVERegOp_b:  | 
2112  | 130k  |   case AArch64_OP_GROUP_SVERegOp_d:  | 
2113  | 173k  |   case AArch64_OP_GROUP_SVERegOp_h:  | 
2114  | 175k  |   case AArch64_OP_GROUP_SVERegOp_q:  | 
2115  | 202k  |   case AArch64_OP_GROUP_SVERegOp_s: { | 
2116  | 202k  |     char Suffix = (char)temp_arg_0;  | 
2117  | 202k  |     AArch64_get_detail_op(MI, 0)->vas = get_vl_by_suffix(Suffix);  | 
2118  | 202k  |     AArch64_set_detail_op_reg(MI, OpNum,  | 
2119  | 202k  |             MCInst_getOpVal(MI, OpNum));  | 
2120  | 202k  |     break;  | 
2121  | 175k  |   }  | 
2122  | 1.97k  |   case AArch64_OP_GROUP_UImm12Offset_1:  | 
2123  | 2.41k  |   case AArch64_OP_GROUP_UImm12Offset_16:  | 
2124  | 4.13k  |   case AArch64_OP_GROUP_UImm12Offset_2:  | 
2125  | 5.83k  |   case AArch64_OP_GROUP_UImm12Offset_4:  | 
2126  | 6.96k  |   case AArch64_OP_GROUP_UImm12Offset_8: { | 
2127  |  |     // Otherwise it is an expression. For which we only add the immediate  | 
2128  | 6.96k  |     unsigned Scale = MCOperand_isImm(MCInst_getOperand(MI, OpNum)) ?  | 
2129  | 6.96k  |            temp_arg_0 :  | 
2130  | 6.96k  |            1;  | 
2131  | 6.96k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,  | 
2132  | 6.96k  |             Scale * MCInst_getOpVal(MI, OpNum));  | 
2133  | 6.96k  |     break;  | 
2134  | 5.83k  |   }  | 
2135  | 47.5k  |   case AArch64_OP_GROUP_VectorIndex_1:  | 
2136  | 47.5k  |   case AArch64_OP_GROUP_VectorIndex_8: { | 
2137  | 47.5k  |     CS_ASSERT_RET(AArch64_get_detail(MI)->op_count > 0);  | 
2138  | 47.5k  |     unsigned Scale = temp_arg_0;  | 
2139  | 47.5k  |     unsigned VIndex = Scale * MCInst_getOpVal(MI, OpNum);  | 
2140  |  |     // The index can either be for one operand, or for each operand of a list.  | 
2141  | 47.5k  |     if (!AArch64_get_detail_op(MI, -1)->is_list_member) { | 
2142  | 22.9k  |       AArch64_get_detail_op(MI, -1)->vector_index = VIndex;  | 
2143  | 22.9k  |       break;  | 
2144  | 22.9k  |     }  | 
2145  | 89.8k  |     for (int i = AArch64_get_detail(MI)->op_count - 1; i >= 0;  | 
2146  | 65.2k  |          --i) { | 
2147  | 65.2k  |       if (!AArch64_get_detail(MI)->operands[i].is_list_member)  | 
2148  | 0  |         break;  | 
2149  | 65.2k  |       AArch64_get_detail(MI)->operands[i].vector_index =  | 
2150  | 65.2k  |         VIndex;  | 
2151  | 65.2k  |     }  | 
2152  | 24.5k  |     break;  | 
2153  | 47.5k  |   }  | 
2154  | 36  |   case AArch64_OP_GROUP_ZPRasFPR_128:  | 
2155  | 695  |   case AArch64_OP_GROUP_ZPRasFPR_16:  | 
2156  | 1.13k  |   case AArch64_OP_GROUP_ZPRasFPR_32:  | 
2157  | 2.09k  |   case AArch64_OP_GROUP_ZPRasFPR_64:  | 
2158  | 2.27k  |   case AArch64_OP_GROUP_ZPRasFPR_8: { | 
2159  | 2.27k  |     unsigned Base = AArch64_NoRegister;  | 
2160  | 2.27k  |     unsigned Width = temp_arg_0;  | 
2161  | 2.27k  |     switch (Width) { | 
2162  | 174  |     case 8:  | 
2163  | 174  |       Base = AArch64_B0;  | 
2164  | 174  |       break;  | 
2165  | 659  |     case 16:  | 
2166  | 659  |       Base = AArch64_H0;  | 
2167  | 659  |       break;  | 
2168  | 438  |     case 32:  | 
2169  | 438  |       Base = AArch64_S0;  | 
2170  | 438  |       break;  | 
2171  | 963  |     case 64:  | 
2172  | 963  |       Base = AArch64_D0;  | 
2173  | 963  |       break;  | 
2174  | 36  |     case 128:  | 
2175  | 36  |       Base = AArch64_Q0;  | 
2176  | 36  |       break;  | 
2177  | 0  |     default:  | 
2178  | 0  |       CS_ASSERT_RET(0 && "Unsupported width");  | 
2179  | 2.27k  |     }  | 
2180  | 2.27k  |     unsigned Reg = MCInst_getOpVal(MI, (OpNum));  | 
2181  | 2.27k  |     AArch64_set_detail_op_reg(MI, OpNum, Reg - AArch64_Z0 + Base);  | 
2182  | 2.27k  |     break;  | 
2183  | 2.27k  |   }  | 
2184  | 377k  |   }  | 
2185  | 377k  | }  | 
2186  |  |  | 
2187  |  | /// Fills cs_detail with the data of the operand.  | 
2188  |  | /// This function handles operands which original printer function is a template  | 
2189  |  | /// with two arguments.  | 
2190  |  | void AArch64_add_cs_detail_2(MCInst *MI, aarch64_op_group op_group,  | 
2191  |  |            unsigned OpNum, uint64_t temp_arg_0,  | 
2192  |  |            uint64_t temp_arg_1)  | 
2193  | 106k  | { | 
2194  | 106k  |   if (!add_cs_detail_begin(MI, OpNum))  | 
2195  | 0  |     return;  | 
2196  | 106k  |   switch (op_group) { | 
2197  | 0  |   default:  | 
2198  | 0  |     printf("ERROR: Operand group %d not handled!\n", op_group); | 
2199  | 0  |     CS_ASSERT_RET(0);  | 
2200  | 705  |   case AArch64_OP_GROUP_ComplexRotationOp_180_90:  | 
2201  | 2.83k  |   case AArch64_OP_GROUP_ComplexRotationOp_90_0: { | 
2202  | 2.83k  |     unsigned Angle = temp_arg_0;  | 
2203  | 2.83k  |     unsigned Remainder = temp_arg_1;  | 
2204  | 2.83k  |     unsigned Imm = (MCInst_getOpVal(MI, OpNum) * Angle) + Remainder;  | 
2205  | 2.83k  |     AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Imm);  | 
2206  | 2.83k  |     break;  | 
2207  | 705  |   }  | 
2208  | 622  |   case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_one:  | 
2209  | 1.30k  |   case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_two:  | 
2210  | 2.56k  |   case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_zero_AArch64ExactFPImm_one: { | 
2211  | 2.56k  |     aarch64_exactfpimm ImmIs0 = temp_arg_0;  | 
2212  | 2.56k  |     aarch64_exactfpimm ImmIs1 = temp_arg_1;  | 
2213  | 2.56k  |     const AArch64ExactFPImm_ExactFPImm *Imm0Desc =  | 
2214  | 2.56k  |       AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs0);  | 
2215  | 2.56k  |     const AArch64ExactFPImm_ExactFPImm *Imm1Desc =  | 
2216  | 2.56k  |       AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs1);  | 
2217  | 2.56k  |     unsigned Val = MCInst_getOpVal(MI, (OpNum));  | 
2218  | 2.56k  |     aarch64_sysop sysop = { 0 }; | 
2219  | 2.56k  |     sysop.imm = Val ? Imm1Desc->SysImm : Imm0Desc->SysImm;  | 
2220  | 2.56k  |     sysop.sub_type = AARCH64_OP_EXACTFPIMM;  | 
2221  | 2.56k  |     AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSIMM);  | 
2222  | 2.56k  |     break;  | 
2223  | 1.30k  |   }  | 
2224  | 3.90k  |   case AArch64_OP_GROUP_ImmRangeScale_2_1:  | 
2225  | 8.20k  |   case AArch64_OP_GROUP_ImmRangeScale_4_3: { | 
2226  | 8.20k  |     uint64_t Scale = temp_arg_0;  | 
2227  | 8.20k  |     uint64_t Offset = temp_arg_1;  | 
2228  | 8.20k  |     unsigned FirstImm = Scale * MCInst_getOpVal(MI, (OpNum));  | 
2229  | 8.20k  |     AArch64_set_detail_op_imm_range(MI, OpNum, FirstImm,  | 
2230  | 8.20k  |             FirstImm + Offset);  | 
2231  | 8.20k  |     break;  | 
2232  | 3.90k  |   }  | 
2233  | 34  |   case AArch64_OP_GROUP_MemExtend_w_128:  | 
2234  | 560  |   case AArch64_OP_GROUP_MemExtend_w_16:  | 
2235  | 611  |   case AArch64_OP_GROUP_MemExtend_w_32:  | 
2236  | 922  |   case AArch64_OP_GROUP_MemExtend_w_64:  | 
2237  | 1.37k  |   case AArch64_OP_GROUP_MemExtend_w_8:  | 
2238  | 1.43k  |   case AArch64_OP_GROUP_MemExtend_x_128:  | 
2239  | 1.73k  |   case AArch64_OP_GROUP_MemExtend_x_16:  | 
2240  | 1.78k  |   case AArch64_OP_GROUP_MemExtend_x_32:  | 
2241  | 2.56k  |   case AArch64_OP_GROUP_MemExtend_x_64:  | 
2242  | 3.30k  |   case AArch64_OP_GROUP_MemExtend_x_8: { | 
2243  | 3.30k  |     char SrcRegKind = (char)temp_arg_0;  | 
2244  | 3.30k  |     unsigned ExtWidth = temp_arg_1;  | 
2245  | 3.30k  |     bool SignExtend = MCInst_getOpVal(MI, OpNum);  | 
2246  | 3.30k  |     bool DoShift = MCInst_getOpVal(MI, OpNum + 1);  | 
2247  | 3.30k  |     AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift,  | 
2248  | 3.30k  |                ExtWidth, SrcRegKind);  | 
2249  | 3.30k  |     break;  | 
2250  | 2.56k  |   }  | 
2251  | 20.0k  |   case AArch64_OP_GROUP_TypedVectorList_0_b:  | 
2252  | 44.0k  |   case AArch64_OP_GROUP_TypedVectorList_0_d:  | 
2253  | 61.4k  |   case AArch64_OP_GROUP_TypedVectorList_0_h:  | 
2254  | 63.8k  |   case AArch64_OP_GROUP_TypedVectorList_0_q:  | 
2255  | 80.0k  |   case AArch64_OP_GROUP_TypedVectorList_0_s:  | 
2256  | 80.1k  |   case AArch64_OP_GROUP_TypedVectorList_0_0:  | 
2257  | 83.1k  |   case AArch64_OP_GROUP_TypedVectorList_16_b:  | 
2258  | 83.4k  |   case AArch64_OP_GROUP_TypedVectorList_1_d:  | 
2259  | 84.4k  |   case AArch64_OP_GROUP_TypedVectorList_2_d:  | 
2260  | 85.8k  |   case AArch64_OP_GROUP_TypedVectorList_2_s:  | 
2261  | 87.1k  |   case AArch64_OP_GROUP_TypedVectorList_4_h:  | 
2262  | 87.6k  |   case AArch64_OP_GROUP_TypedVectorList_4_s:  | 
2263  | 88.7k  |   case AArch64_OP_GROUP_TypedVectorList_8_b:  | 
2264  | 89.9k  |   case AArch64_OP_GROUP_TypedVectorList_8_h: { | 
2265  | 89.9k  |     uint8_t NumLanes = (uint8_t)temp_arg_0;  | 
2266  | 89.9k  |     char LaneKind = (char)temp_arg_1;  | 
2267  | 89.9k  |     uint16_t Pair = ((NumLanes << 8) | LaneKind);  | 
2268  |  |  | 
2269  | 89.9k  |     AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;  | 
2270  | 89.9k  |     switch (Pair) { | 
2271  | 0  |     default:  | 
2272  | 0  |       printf("Typed vector list with NumLanes = %d and LaneKind = %c not handled.\n", | 
2273  | 0  |              NumLanes, LaneKind);  | 
2274  | 0  |       CS_ASSERT_RET(0);  | 
2275  | 1.01k  |     case ((8 << 8) | 'b'):  | 
2276  | 1.01k  |       vas = AARCH64LAYOUT_VL_8B;  | 
2277  | 1.01k  |       break;  | 
2278  | 1.26k  |     case ((4 << 8) | 'h'):  | 
2279  | 1.26k  |       vas = AARCH64LAYOUT_VL_4H;  | 
2280  | 1.26k  |       break;  | 
2281  | 1.48k  |     case ((2 << 8) | 's'):  | 
2282  | 1.48k  |       vas = AARCH64LAYOUT_VL_2S;  | 
2283  | 1.48k  |       break;  | 
2284  | 293  |     case ((1 << 8) | 'd'):  | 
2285  | 293  |       vas = AARCH64LAYOUT_VL_1D;  | 
2286  | 293  |       break;  | 
2287  | 2.99k  |     case ((16 << 8) | 'b'):  | 
2288  | 2.99k  |       vas = AARCH64LAYOUT_VL_16B;  | 
2289  | 2.99k  |       break;  | 
2290  | 1.29k  |     case ((8 << 8) | 'h'):  | 
2291  | 1.29k  |       vas = AARCH64LAYOUT_VL_8H;  | 
2292  | 1.29k  |       break;  | 
2293  | 541  |     case ((4 << 8) | 's'):  | 
2294  | 541  |       vas = AARCH64LAYOUT_VL_4S;  | 
2295  | 541  |       break;  | 
2296  | 959  |     case ((2 << 8) | 'd'):  | 
2297  | 959  |       vas = AARCH64LAYOUT_VL_2D;  | 
2298  | 959  |       break;  | 
2299  | 20.0k  |     case 'b':  | 
2300  | 20.0k  |       vas = AARCH64LAYOUT_VL_B;  | 
2301  | 20.0k  |       break;  | 
2302  | 17.3k  |     case 'h':  | 
2303  | 17.3k  |       vas = AARCH64LAYOUT_VL_H;  | 
2304  | 17.3k  |       break;  | 
2305  | 16.2k  |     case 's':  | 
2306  | 16.2k  |       vas = AARCH64LAYOUT_VL_S;  | 
2307  | 16.2k  |       break;  | 
2308  | 24.0k  |     case 'd':  | 
2309  | 24.0k  |       vas = AARCH64LAYOUT_VL_D;  | 
2310  | 24.0k  |       break;  | 
2311  | 2.44k  |     case 'q':  | 
2312  | 2.44k  |       vas = AARCH64LAYOUT_VL_Q;  | 
2313  | 2.44k  |       break;  | 
2314  | 66  |     case '0':  | 
2315  |  |       // Implicitly Typed register  | 
2316  | 66  |       break;  | 
2317  | 89.9k  |     }  | 
2318  |  |  | 
2319  | 89.9k  |     unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));  | 
2320  | 89.9k  |     unsigned NumRegs = get_vec_list_num_regs(MI, Reg);  | 
2321  | 89.9k  |     unsigned Stride = get_vec_list_stride(MI, Reg);  | 
2322  | 89.9k  |     Reg = get_vec_list_first_reg(MI, Reg);  | 
2323  |  |  | 
2324  | 89.9k  |     if ((MCRegisterClass_contains(  | 
2325  | 89.9k  |            MCRegisterInfo_getRegClass(MI->MRI,  | 
2326  | 89.9k  |               AArch64_ZPRRegClassID),  | 
2327  | 89.9k  |            Reg) ||  | 
2328  | 37.7k  |          MCRegisterClass_contains(  | 
2329  | 37.7k  |            MCRegisterInfo_getRegClass(MI->MRI,  | 
2330  | 37.7k  |               AArch64_PPRRegClassID),  | 
2331  | 37.7k  |            Reg)) &&  | 
2332  | 55.5k  |         NumRegs > 1 && Stride == 1 &&  | 
2333  | 32.1k  |         Reg < getNextVectorRegister(Reg, NumRegs - 1)) { | 
2334  | 31.9k  |       AArch64_get_detail_op(MI, 0)->is_list_member = true;  | 
2335  | 31.9k  |       AArch64_get_detail_op(MI, 0)->vas = vas;  | 
2336  | 31.9k  |       AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
2337  | 31.9k  |       if (NumRegs > 1) { | 
2338  |  |         // Add all registers of the list to the details.  | 
2339  | 89.4k  |         for (size_t i = 0; i < NumRegs - 1; ++i) { | 
2340  | 57.5k  |           AArch64_get_detail_op(MI, 0)  | 
2341  | 57.5k  |             ->is_list_member = true;  | 
2342  | 57.5k  |           AArch64_get_detail_op(MI, 0)->vas = vas;  | 
2343  | 57.5k  |           AArch64_set_detail_op_reg(  | 
2344  | 57.5k  |             MI, OpNum,  | 
2345  | 57.5k  |             getNextVectorRegister(Reg + i,  | 
2346  | 57.5k  |                       1));  | 
2347  | 57.5k  |         }  | 
2348  | 31.9k  |       }  | 
2349  | 58.0k  |     } else { | 
2350  | 184k  |       for (unsigned i = 0; i < NumRegs;  | 
2351  | 126k  |            ++i, Reg = getNextVectorRegister(Reg, Stride)) { | 
2352  | 126k  |         if (!(MCRegisterClass_contains(  | 
2353  | 126k  |                 MCRegisterInfo_getRegClass(  | 
2354  | 126k  |                   MI->MRI,  | 
2355  | 126k  |                   AArch64_ZPRRegClassID),  | 
2356  | 126k  |                 Reg) ||  | 
2357  | 90.4k  |               MCRegisterClass_contains(  | 
2358  | 90.4k  |                 MCRegisterInfo_getRegClass(  | 
2359  | 90.4k  |                   MI->MRI,  | 
2360  | 90.4k  |                   AArch64_PPRRegClassID),  | 
2361  | 90.4k  |                 Reg))) { | 
2362  | 90.4k  |           AArch64_get_detail_op(MI, 0)->is_vreg =  | 
2363  | 90.4k  |             true;  | 
2364  | 90.4k  |         }  | 
2365  | 126k  |         AArch64_get_detail_op(MI, 0)->is_list_member =  | 
2366  | 126k  |           true;  | 
2367  | 126k  |         AArch64_get_detail_op(MI, 0)->vas = vas;  | 
2368  | 126k  |         AArch64_set_detail_op_reg(MI, OpNum, Reg);  | 
2369  | 126k  |       }  | 
2370  | 58.0k  |     }  | 
2371  | 89.9k  |   }  | 
2372  | 106k  |   }  | 
2373  | 106k  | }  | 
2374  |  |  | 
2375  |  | /// Fills cs_detail with the data of the operand.  | 
2376  |  | /// This function handles operands which original printer function is a template  | 
2377  |  | /// with four arguments.  | 
2378  |  | void AArch64_add_cs_detail_4(MCInst *MI, aarch64_op_group op_group,  | 
2379  |  |            unsigned OpNum, uint64_t temp_arg_0,  | 
2380  |  |            uint64_t temp_arg_1, uint64_t temp_arg_2,  | 
2381  |  |            uint64_t temp_arg_3)  | 
2382  | 22.7k  | { | 
2383  | 22.7k  |   if (!add_cs_detail_begin(MI, OpNum))  | 
2384  | 0  |     return;  | 
2385  | 22.7k  |   switch (op_group) { | 
2386  | 0  |   default:  | 
2387  | 0  |     printf("ERROR: Operand group %d not handled!\n", op_group); | 
2388  | 0  |     CS_ASSERT_RET(0);  | 
2389  | 1.58k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_128_x_0:  | 
2390  | 1.98k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_d:  | 
2391  | 2.30k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_s:  | 
2392  | 5.19k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_0:  | 
2393  | 5.60k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_d:  | 
2394  | 5.76k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_s:  | 
2395  | 6.04k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_d:  | 
2396  | 6.14k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_s:  | 
2397  | 7.46k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_0:  | 
2398  | 8.44k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_d:  | 
2399  | 8.48k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_s:  | 
2400  | 8.81k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_d:  | 
2401  | 8.88k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_s:  | 
2402  | 9.93k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_0:  | 
2403  | 10.6k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_d:  | 
2404  | 10.6k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_s:  | 
2405  | 12.7k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_d:  | 
2406  | 13.7k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_s:  | 
2407  | 18.0k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_0:  | 
2408  | 19.1k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_d:  | 
2409  | 19.2k  |   case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_s:  | 
2410  | 19.7k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_d:  | 
2411  | 19.9k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_s:  | 
2412  | 20.5k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_d:  | 
2413  | 21.0k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_s:  | 
2414  | 21.2k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_d:  | 
2415  | 21.4k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_s:  | 
2416  | 22.5k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_d:  | 
2417  | 22.7k  |   case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_s: { | 
2418  |  |     // signed (s) and unsigned (u) extend  | 
2419  | 22.7k  |     bool SignExtend = (bool)temp_arg_0;  | 
2420  |  |     // Extend width  | 
2421  | 22.7k  |     int ExtWidth = (int)temp_arg_1;  | 
2422  |  |     // w = word, x = doubleword  | 
2423  | 22.7k  |     char SrcRegKind = (char)temp_arg_2;  | 
2424  |  |     // Vector register element/arrangement specifier:  | 
2425  |  |     // B = 8bit, H = 16bit, S = 32bit, D = 64bit, Q = 128bit  | 
2426  |  |     // No suffix = complete register  | 
2427  |  |     // According to: ARM Reference manual supplement, doc number: DDI 0584  | 
2428  | 22.7k  |     char Suffix = (char)temp_arg_3;  | 
2429  |  |  | 
2430  |  |     // Register will be added in printOperand() afterwards. Here we only handle  | 
2431  |  |     // shift and extend.  | 
2432  | 22.7k  |     AArch64_get_detail_op(MI, -1)->vas = get_vl_by_suffix(Suffix);  | 
2433  |  |  | 
2434  | 22.7k  |     bool DoShift = ExtWidth != 8;  | 
2435  | 22.7k  |     if (!(SignExtend || DoShift || SrcRegKind == 'w'))  | 
2436  | 5.45k  |       return;  | 
2437  |  |  | 
2438  | 17.2k  |     AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift,  | 
2439  | 17.2k  |                ExtWidth, SrcRegKind);  | 
2440  | 17.2k  |     break;  | 
2441  | 22.7k  |   }  | 
2442  | 22.7k  |   }  | 
2443  | 22.7k  | }  | 
2444  |  |  | 
2445  |  | /// Adds a register AArch64 operand at position OpNum and increases the op_count by  | 
2446  |  | /// one.  | 
2447  |  | void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg)  | 
2448  | 990k  | { | 
2449  | 990k  |   if (!detail_is_set(MI))  | 
2450  | 0  |     return;  | 
2451  | 990k  |   AArch64_check_safe_inc(MI);  | 
2452  |  |  | 
2453  | 990k  |   if (Reg == AARCH64_REG_ZA ||  | 
2454  | 990k  |       (Reg >= AARCH64_REG_ZAB0 && Reg < AARCH64_REG_ZT0)) { | 
2455  |  |     // A tile register should be treated as SME operand.  | 
2456  | 0  |     AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,  | 
2457  | 0  |             sme_reg_to_vas(Reg));  | 
2458  | 0  |     return;  | 
2459  | 990k  |   } else if (((Reg >= AARCH64_REG_P0) && (Reg <= AARCH64_REG_P15)) ||  | 
2460  | 907k  |        ((Reg >= AARCH64_REG_PN0) && (Reg <= AARCH64_REG_PN15))) { | 
2461  |  |     // SME/SVE predicate register.  | 
2462  | 97.3k  |     AArch64_set_detail_op_pred(MI, OpNum);  | 
2463  | 97.3k  |     return;  | 
2464  | 892k  |   } else if (AArch64_get_detail(MI)->is_doing_sme) { | 
2465  | 19.7k  |     CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);  | 
2466  | 19.7k  |     if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) { | 
2467  | 19.0k  |       AArch64_set_detail_op_sme(MI, OpNum,  | 
2468  | 19.0k  |               AARCH64_SME_MATRIX_SLICE_REG,  | 
2469  | 19.0k  |               AARCH64LAYOUT_INVALID);  | 
2470  | 19.0k  |     } else if (AArch64_get_detail_op(MI, 0)->type ==  | 
2471  | 661  |          AARCH64_OP_PRED) { | 
2472  | 661  |       AArch64_set_detail_op_pred(MI, OpNum);  | 
2473  | 661  |     } else { | 
2474  | 0  |       CS_ASSERT_RET(0 && "Unkown SME/SVE operand type");  | 
2475  | 0  |     }  | 
2476  | 19.7k  |     return;  | 
2477  | 19.7k  |   }  | 
2478  | 873k  |   if (map_get_op_type(MI, OpNum) & CS_OP_MEM) { | 
2479  | 151k  |     AArch64_set_detail_op_mem(MI, OpNum, Reg);  | 
2480  | 151k  |     return;  | 
2481  | 151k  |   }  | 
2482  |  |  | 
2483  | 721k  |   CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_BOUND));  | 
2484  | 721k  |   CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));  | 
2485  | 721k  |   CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG);  | 
2486  |  |  | 
2487  | 721k  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_REG;  | 
2488  | 721k  |   AArch64_get_detail_op(MI, 0)->reg = Reg;  | 
2489  | 721k  |   AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
2490  | 721k  |   AArch64_inc_op_count(MI);  | 
2491  | 721k  | }  | 
2492  |  |  | 
2493  |  | /// Check if the previous operand is a memory operand  | 
2494  |  | /// with only the base register set AND if this base register  | 
2495  |  | /// is write-back.  | 
2496  |  | /// This indicates the following immediate is a post-indexed  | 
2497  |  | /// memory offset.  | 
2498  |  | static bool prev_is_membase_wb(MCInst *MI)  | 
2499  | 137k  | { | 
2500  | 137k  |   return AArch64_get_detail(MI)->op_count > 0 &&  | 
2501  | 116k  |          AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_MEM &&  | 
2502  | 7.32k  |          AArch64_get_detail_op(MI, -1)->mem.disp == 0 &&  | 
2503  | 7.32k  |          get_detail(MI)->writeback;  | 
2504  | 137k  | }  | 
2505  |  |  | 
2506  |  | /// Adds an immediate AArch64 operand at position OpNum and increases the op_count  | 
2507  |  | /// by one.  | 
2508  |  | void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,  | 
2509  |  |              aarch64_op_type ImmType, int64_t Imm)  | 
2510  | 186k  | { | 
2511  | 186k  |   if (!detail_is_set(MI))  | 
2512  | 0  |     return;  | 
2513  | 186k  |   AArch64_check_safe_inc(MI);  | 
2514  |  |  | 
2515  | 186k  |   if (AArch64_get_detail(MI)->is_doing_sme) { | 
2516  | 0  |     CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);  | 
2517  | 0  |     if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) { | 
2518  | 0  |       AArch64_set_detail_op_sme(MI, OpNum,  | 
2519  | 0  |               AARCH64_SME_MATRIX_SLICE_OFF,  | 
2520  | 0  |               AARCH64LAYOUT_INVALID,  | 
2521  | 0  |               (uint32_t)1);  | 
2522  | 0  |     } else if (AArch64_get_detail_op(MI, 0)->type ==  | 
2523  | 0  |          AARCH64_OP_PRED) { | 
2524  | 0  |       AArch64_set_detail_op_pred(MI, OpNum);  | 
2525  | 0  |     } else { | 
2526  | 0  |       CS_ASSERT_RET(0 && "Unkown SME operand type");  | 
2527  | 0  |     }  | 
2528  | 0  |     return;  | 
2529  | 0  |   }  | 
2530  | 186k  |   if (map_get_op_type(MI, OpNum) & CS_OP_MEM || prev_is_membase_wb(MI)) { | 
2531  | 55.9k  |     AArch64_set_detail_op_mem(MI, OpNum, Imm);  | 
2532  | 55.9k  |     return;  | 
2533  | 55.9k  |   }  | 
2534  |  |  | 
2535  | 130k  |   CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));  | 
2536  | 130k  |   CS_ASSERT_RET((map_get_op_type(MI, OpNum) & ~CS_OP_BOUND) == CS_OP_IMM);  | 
2537  | 130k  |   CS_ASSERT_RET(ImmType == AARCH64_OP_IMM || ImmType == AARCH64_OP_CIMM);  | 
2538  |  |  | 
2539  | 130k  |   AArch64_get_detail_op(MI, 0)->type = ImmType;  | 
2540  | 130k  |   AArch64_get_detail_op(MI, 0)->imm = Imm;  | 
2541  | 130k  |   AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
2542  | 130k  |   AArch64_inc_op_count(MI);  | 
2543  | 130k  | }  | 
2544  |  |  | 
2545  |  | void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,  | 
2546  |  |              uint32_t FirstImm, uint32_t Offset)  | 
2547  | 8.20k  | { | 
2548  | 8.20k  |   if (!detail_is_set(MI))  | 
2549  | 0  |     return;  | 
2550  | 8.20k  |   AArch64_check_safe_inc(MI);  | 
2551  |  |  | 
2552  | 8.20k  |   if (AArch64_get_detail(MI)->is_doing_sme) { | 
2553  | 8.20k  |     CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);  | 
2554  | 8.20k  |     if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) { | 
2555  | 8.20k  |       AArch64_set_detail_op_sme(  | 
2556  | 8.20k  |         MI, OpNum, AARCH64_SME_MATRIX_SLICE_OFF_RANGE,  | 
2557  | 8.20k  |         AARCH64LAYOUT_INVALID, (uint32_t)FirstImm,  | 
2558  | 8.20k  |         (uint32_t)Offset);  | 
2559  | 8.20k  |     } else if (AArch64_get_detail_op(MI, 0)->type ==  | 
2560  | 0  |          AARCH64_OP_PRED) { | 
2561  | 0  |       CS_ASSERT_RET(0 &&  | 
2562  | 0  |               "Unkown SME predicate imm range type");  | 
2563  | 0  |     } else { | 
2564  | 0  |       CS_ASSERT_RET(0 && "Unkown SME operand type");  | 
2565  | 0  |     }  | 
2566  | 8.20k  |     return;  | 
2567  | 8.20k  |   }  | 
2568  |  |  | 
2569  | 0  |   CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));  | 
2570  | 0  |   CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_IMM);  | 
2571  |  |  | 
2572  | 0  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM_RANGE;  | 
2573  | 0  |   AArch64_get_detail_op(MI, 0)->imm_range.first = FirstImm;  | 
2574  | 0  |   AArch64_get_detail_op(MI, 0)->imm_range.offset = Offset;  | 
2575  | 0  |   AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
2576  | 0  |   AArch64_inc_op_count(MI);  | 
2577  | 0  | }  | 
2578  |  |  | 
2579  |  | /// Adds a memory AARCH64 operand at position OpNum. op_count is *not* increased by  | 
2580  |  | /// one. This is done by set_mem_access().  | 
2581  |  | void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val)  | 
2582  | 207k  | { | 
2583  | 207k  |   if (!detail_is_set(MI))  | 
2584  | 0  |     return;  | 
2585  | 207k  |   AArch64_check_safe_inc(MI);  | 
2586  |  |  | 
2587  | 207k  |   AArch64_set_mem_access(MI, true);  | 
2588  |  |  | 
2589  | 207k  |   cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;  | 
2590  | 207k  |   switch (secondary_type) { | 
2591  | 0  |   default:  | 
2592  | 0  |     CS_ASSERT_RET(0 && "Secondary type not supported yet.");  | 
2593  | 151k  |   case CS_OP_REG: { | 
2594  | 151k  |     bool is_index_reg = AArch64_get_detail_op(MI, 0)->mem.base !=  | 
2595  | 151k  |             AARCH64_REG_INVALID;  | 
2596  | 151k  |     if (is_index_reg)  | 
2597  | 30.1k  |       AArch64_get_detail_op(MI, 0)->mem.index = Val;  | 
2598  | 121k  |     else { | 
2599  | 121k  |       AArch64_get_detail_op(MI, 0)->mem.base = Val;  | 
2600  | 121k  |     }  | 
2601  |  |  | 
2602  | 151k  |     if (MCInst_opIsTying(MI, OpNum)) { | 
2603  |  |       // Especially base registers can be writeback registers.  | 
2604  |  |       // For this they tie an MC operand which has write  | 
2605  |  |       // access. But this one is never processed in the printer  | 
2606  |  |       // (because it is never emitted). Therefor it is never  | 
2607  |  |       // added to the modified list.  | 
2608  |  |       // Here we check for this case and add the memory register  | 
2609  |  |       // to the modified list.  | 
2610  | 33.5k  |       map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));  | 
2611  | 33.5k  |     }  | 
2612  | 151k  |     break;  | 
2613  | 0  |   }  | 
2614  | 55.9k  |   case CS_OP_IMM: { | 
2615  | 55.9k  |     AArch64_get_detail_op(MI, 0)->mem.disp = Val;  | 
2616  | 55.9k  |     break;  | 
2617  | 0  |   }  | 
2618  | 207k  |   }  | 
2619  |  |  | 
2620  | 207k  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_MEM;  | 
2621  | 207k  |   AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
2622  | 207k  |   AArch64_set_mem_access(MI, false);  | 
2623  | 207k  | }  | 
2624  |  |  | 
2625  |  | /// Adds the shift and sign extend info to the previous operand.  | 
2626  |  | /// op_count is *not* incremented by one.  | 
2627  |  | void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,  | 
2628  |  |           bool DoShift, unsigned ExtWidth,  | 
2629  |  |           char SrcRegKind)  | 
2630  | 20.5k  | { | 
2631  | 20.5k  |   bool IsLSL = !SignExtend && SrcRegKind == 'x';  | 
2632  | 20.5k  |   if (IsLSL)  | 
2633  | 10.2k  |     AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;  | 
2634  | 10.3k  |   else { | 
2635  | 10.3k  |     aarch64_extender ext = SignExtend ? AARCH64_EXT_SXTB :  | 
2636  | 10.3k  |                 AARCH64_EXT_UXTB;  | 
2637  | 10.3k  |     switch (SrcRegKind) { | 
2638  | 0  |     default:  | 
2639  | 0  |       CS_ASSERT_RET(0 && "Extender not handled\n");  | 
2640  | 0  |     case 'b':  | 
2641  | 0  |       ext += 0;  | 
2642  | 0  |       break;  | 
2643  | 0  |     case 'h':  | 
2644  | 0  |       ext += 1;  | 
2645  | 0  |       break;  | 
2646  | 9.43k  |     case 'w':  | 
2647  | 9.43k  |       ext += 2;  | 
2648  | 9.43k  |       break;  | 
2649  | 870  |     case 'x':  | 
2650  | 870  |       ext += 3;  | 
2651  | 870  |       break;  | 
2652  | 10.3k  |     }  | 
2653  | 10.3k  |     AArch64_get_detail_op(MI, -1)->ext = ext;  | 
2654  | 10.3k  |   }  | 
2655  | 20.5k  |   if (DoShift || IsLSL) { | 
2656  | 15.2k  |     unsigned ShiftAmount = DoShift ? Log2_32(ExtWidth / 8) : 0;  | 
2657  | 15.2k  |     AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;  | 
2658  | 15.2k  |     AArch64_get_detail_op(MI, -1)->shift.value = ShiftAmount;  | 
2659  | 15.2k  |   }  | 
2660  | 20.5k  | }  | 
2661  |  |  | 
2662  |  | /// Transforms the immediate of the operand to a float and stores it.  | 
2663  |  | /// Increments the op_counter by one.  | 
2664  |  | void AArch64_set_detail_op_float(MCInst *MI, unsigned OpNum, float Val)  | 
2665  | 592  | { | 
2666  | 592  |   if (!detail_is_set(MI))  | 
2667  | 0  |     return;  | 
2668  | 592  |   AArch64_check_safe_inc(MI);  | 
2669  |  |  | 
2670  | 592  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_FP;  | 
2671  | 592  |   AArch64_get_detail_op(MI, 0)->fp = Val;  | 
2672  | 592  |   AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
2673  | 592  |   AArch64_inc_op_count(MI);  | 
2674  | 592  | }  | 
2675  |  |  | 
2676  |  | /// Adds a the system operand and increases the op_count by  | 
2677  |  | /// one.  | 
2678  |  | void AArch64_set_detail_op_sys(MCInst *MI, unsigned OpNum, aarch64_sysop sys_op,  | 
2679  |  |              aarch64_op_type type)  | 
2680  | 32.7k  | { | 
2681  | 32.7k  |   if (!detail_is_set(MI))  | 
2682  | 0  |     return;  | 
2683  | 32.7k  |   AArch64_check_safe_inc(MI);  | 
2684  |  |  | 
2685  | 32.7k  |   AArch64_get_detail_op(MI, 0)->type = type;  | 
2686  | 32.7k  |   AArch64_get_detail_op(MI, 0)->sysop = sys_op;  | 
2687  | 32.7k  |   if (sys_op.sub_type == AARCH64_OP_EXACTFPIMM) { | 
2688  | 2.56k  |     AArch64_get_detail_op(MI, 0)->fp =  | 
2689  | 2.56k  |       aarch64_exact_fp_to_fp(sys_op.imm.exactfpimm);  | 
2690  | 2.56k  |   }  | 
2691  | 32.7k  |   AArch64_inc_op_count(MI);  | 
2692  | 32.7k  | }  | 
2693  |  |  | 
2694  |  | void AArch64_set_detail_op_pred(MCInst *MI, unsigned OpNum)  | 
2695  | 98.6k  | { | 
2696  | 98.6k  |   if (!detail_is_set(MI))  | 
2697  | 0  |     return;  | 
2698  | 98.6k  |   AArch64_check_safe_inc(MI);  | 
2699  |  |  | 
2700  | 98.6k  |   if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_INVALID) { | 
2701  | 94.0k  |     setup_pred_operand(MI);  | 
2702  | 94.0k  |   }  | 
2703  | 98.6k  |   aarch64_op_pred *p = &AArch64_get_detail_op(MI, 0)->pred;  | 
2704  | 98.6k  |   if (p->reg == AARCH64_REG_INVALID) { | 
2705  | 94.0k  |     p->reg = MCInst_getOpVal(MI, OpNum);  | 
2706  | 94.0k  |     AArch64_get_detail_op(MI, 0)->access =  | 
2707  | 94.0k  |       map_get_op_access(MI, OpNum);  | 
2708  | 94.0k  |     AArch64_get_detail(MI)->is_doing_sme = true;  | 
2709  | 94.0k  |     return;  | 
2710  | 94.0k  |   } else if (p->vec_select == AARCH64_REG_INVALID) { | 
2711  | 3.93k  |     p->vec_select = MCInst_getOpVal(MI, OpNum);  | 
2712  | 3.93k  |     return;  | 
2713  | 3.93k  |   } else if (p->imm_index == -1) { | 
2714  | 661  |     p->imm_index = MCInst_getOpVal(MI, OpNum);  | 
2715  | 661  |     return;  | 
2716  | 661  |   }  | 
2717  | 0  |   CS_ASSERT_RET(0 && "Should not be reached.");  | 
2718  | 0  | }  | 
2719  |  |  | 
2720  |  | /// Adds a SME matrix component to a SME operand.  | 
2721  |  | void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,  | 
2722  |  |              aarch64_sme_op_part part,  | 
2723  |  |              AArch64Layout_VectorLayout vas, ...)  | 
2724  | 64.2k  | { | 
2725  | 64.2k  |   if (!detail_is_set(MI))  | 
2726  | 0  |     return;  | 
2727  | 64.2k  |   AArch64_check_safe_inc(MI);  | 
2728  |  |  | 
2729  | 64.2k  |   AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;  | 
2730  | 64.2k  |   switch (part) { | 
2731  | 0  |   default:  | 
2732  | 0  |     printf("Unhandled SME operand part %d\n", part); | 
2733  | 0  |     CS_ASSERT_RET(0);  | 
2734  | 4.39k  |   case AARCH64_SME_MATRIX_TILE_LIST: { | 
2735  | 4.39k  |     setup_sme_operand(MI);  | 
2736  | 4.39k  |     va_list args;  | 
2737  | 4.39k  |     va_start(args, vas);  | 
2738  |  |     // NOLINTBEGIN(clang-analyzer-valist.Uninitialized)  | 
2739  | 4.39k  |     int Tile = va_arg(args, int);  | 
2740  |  |     // NOLINTEND(clang-analyzer-valist.Uninitialized)  | 
2741  | 4.39k  |     va_end(args);  | 
2742  | 4.39k  |     AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;  | 
2743  | 4.39k  |     AArch64_get_detail_op(MI, 0)->sme.tile = Tile;  | 
2744  | 4.39k  |     AArch64_get_detail_op(MI, 0)->vas = vas;  | 
2745  | 4.39k  |     AArch64_get_detail_op(MI, 0)->access =  | 
2746  | 4.39k  |       map_get_op_access(MI, OpNum);  | 
2747  | 4.39k  |     AArch64_get_detail(MI)->is_doing_sme = true;  | 
2748  | 4.39k  |     break;  | 
2749  | 0  |   }  | 
2750  | 21.7k  |   case AARCH64_SME_MATRIX_TILE:  | 
2751  | 21.7k  |     CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG);  | 
2752  |  |  | 
2753  | 21.7k  |     setup_sme_operand(MI);  | 
2754  | 21.7k  |     AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;  | 
2755  | 21.7k  |     AArch64_get_detail_op(MI, 0)->sme.tile =  | 
2756  | 21.7k  |       MCInst_getOpVal(MI, OpNum);  | 
2757  | 21.7k  |     AArch64_get_detail_op(MI, 0)->vas = vas;  | 
2758  | 21.7k  |     AArch64_get_detail_op(MI, 0)->access =  | 
2759  | 21.7k  |       map_get_op_access(MI, OpNum);  | 
2760  | 21.7k  |     AArch64_get_detail(MI)->is_doing_sme = true;  | 
2761  | 21.7k  |     break;  | 
2762  | 19.0k  |   case AARCH64_SME_MATRIX_SLICE_REG:  | 
2763  | 19.0k  |     CS_ASSERT_RET((map_get_op_type(MI, OpNum) &  | 
2764  | 19.0k  |              ~(CS_OP_MEM | CS_OP_BOUND)) == CS_OP_REG);  | 
2765  | 19.0k  |     CS_ASSERT_RET(AArch64_get_detail_op(MI, 0)->type ==  | 
2766  | 19.0k  |             AARCH64_OP_SME);  | 
2767  |  |  | 
2768  |  |     // SME operand already present. Add the slice to it.  | 
2769  | 19.0k  |     AArch64_get_detail_op(MI, 0)->sme.type =  | 
2770  | 19.0k  |       AARCH64_SME_OP_TILE_VEC;  | 
2771  | 19.0k  |     AArch64_get_detail_op(MI, 0)->sme.slice_reg =  | 
2772  | 19.0k  |       MCInst_getOpVal(MI, OpNum);  | 
2773  | 19.0k  |     break;  | 
2774  | 10.8k  |   case AARCH64_SME_MATRIX_SLICE_OFF: { | 
2775  | 10.8k  |     CS_ASSERT_RET((map_get_op_type(MI, OpNum) &  | 
2776  | 10.8k  |              ~(CS_OP_MEM | CS_OP_BOUND)) == CS_OP_IMM);  | 
2777  |  |     // Because we took care of the slice register before, the op at -1 must be a SME operand.  | 
2778  | 10.8k  |     CS_ASSERT_RET(AArch64_get_detail_op(MI, 0)->type ==  | 
2779  | 10.8k  |             AARCH64_OP_SME);  | 
2780  | 10.8k  |     CS_ASSERT_RET(  | 
2781  | 10.8k  |       AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm ==  | 
2782  | 10.8k  |       AARCH64_SLICE_IMM_INVALID);  | 
2783  | 10.8k  |     va_list args;  | 
2784  | 10.8k  |     va_start(args, vas);  | 
2785  |  |     // NOLINTBEGIN(clang-analyzer-valist.Uninitialized)  | 
2786  | 10.8k  |     uint16_t offset = va_arg(args, uint32_t);  | 
2787  |  |     // NOLINTEND(clang-analyzer-valist.Uninitialized)  | 
2788  | 10.8k  |     va_end(args);  | 
2789  | 10.8k  |     AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = offset;  | 
2790  | 10.8k  |     break;  | 
2791  | 10.8k  |   }  | 
2792  | 8.20k  |   case AARCH64_SME_MATRIX_SLICE_OFF_RANGE: { | 
2793  | 8.20k  |     va_list args;  | 
2794  | 8.20k  |     va_start(args, vas);  | 
2795  |  |     // NOLINTBEGIN(clang-analyzer-valist.Uninitialized)  | 
2796  | 8.20k  |     uint8_t First = va_arg(args, uint32_t);  | 
2797  | 8.20k  |     uint8_t Offset = va_arg(args, uint32_t);  | 
2798  |  |     // NOLINTEND(clang-analyzer-valist.Uninitialized)  | 
2799  | 8.20k  |     va_end(args);  | 
2800  | 8.20k  |     AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =  | 
2801  | 8.20k  |       First;  | 
2802  | 8.20k  |     AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset =  | 
2803  | 8.20k  |       Offset;  | 
2804  | 8.20k  |     AArch64_get_detail_op(MI, 0)->sme.has_range_offset = true;  | 
2805  | 8.20k  |     break;  | 
2806  | 10.8k  |   }  | 
2807  | 64.2k  |   }  | 
2808  | 64.2k  | }  | 
2809  |  |  | 
2810  |  | static void insert_op(MCInst *MI, unsigned index, cs_aarch64_op op)  | 
2811  | 22.0k  | { | 
2812  | 22.0k  |   if (!detail_is_set(MI)) { | 
2813  | 0  |     return;  | 
2814  | 0  |   }  | 
2815  |  |  | 
2816  | 22.0k  |   AArch64_check_safe_inc(MI);  | 
2817  | 22.0k  |   cs_aarch64_op *ops = AArch64_get_detail(MI)->operands;  | 
2818  | 22.0k  |   int i = AArch64_get_detail(MI)->op_count;  | 
2819  | 22.0k  |   if (index == -1) { | 
2820  | 22.0k  |     ops[i] = op;  | 
2821  | 22.0k  |     AArch64_inc_op_count(MI);  | 
2822  | 22.0k  |     return;  | 
2823  | 22.0k  |   }  | 
2824  | 0  |   for (; i > 0 && i > index; --i) { | 
2825  | 0  |     ops[i] = ops[i - 1];  | 
2826  | 0  |   }  | 
2827  | 0  |   ops[index] = op;  | 
2828  | 0  |   AArch64_inc_op_count(MI);  | 
2829  | 0  | }  | 
2830  |  |  | 
2831  |  | /// Inserts a float to the detail operands at @index.  | 
2832  |  | /// If @index == -1, it pushes the operand to the end of the ops array.  | 
2833  |  | /// Already present operands are moved.  | 
2834  |  | void AArch64_insert_detail_op_float_at(MCInst *MI, unsigned index, double val,  | 
2835  |  |                cs_ac_type access)  | 
2836  | 0  | { | 
2837  | 0  |   if (!detail_is_set(MI))  | 
2838  | 0  |     return;  | 
2839  |  |  | 
2840  | 0  |   AArch64_check_safe_inc(MI);  | 
2841  |  | 
  | 
2842  | 0  |   cs_aarch64_op op;  | 
2843  | 0  |   AArch64_setup_op(&op);  | 
2844  | 0  |   op.type = AARCH64_OP_FP;  | 
2845  | 0  |   op.fp = val;  | 
2846  | 0  |   op.access = access;  | 
2847  |  | 
  | 
2848  | 0  |   insert_op(MI, index, op);  | 
2849  | 0  | }  | 
2850  |  |  | 
2851  |  | /// Inserts a register to the detail operands at @index.  | 
2852  |  | /// If @index == -1, it pushes the operand to the end of the ops array.  | 
2853  |  | /// Already present operands are moved.  | 
2854  |  | void AArch64_insert_detail_op_reg_at(MCInst *MI, unsigned index,  | 
2855  |  |              aarch64_reg Reg, cs_ac_type access)  | 
2856  | 2.02k  | { | 
2857  | 2.02k  |   if (!detail_is_set(MI))  | 
2858  | 0  |     return;  | 
2859  |  |  | 
2860  | 2.02k  |   AArch64_check_safe_inc(MI);  | 
2861  |  |  | 
2862  | 2.02k  |   cs_aarch64_op op;  | 
2863  | 2.02k  |   AArch64_setup_op(&op);  | 
2864  | 2.02k  |   op.type = AARCH64_OP_REG;  | 
2865  | 2.02k  |   op.reg = Reg;  | 
2866  | 2.02k  |   op.access = access;  | 
2867  |  |  | 
2868  | 2.02k  |   insert_op(MI, index, op);  | 
2869  | 2.02k  | }  | 
2870  |  |  | 
2871  |  | /// Inserts a immediate to the detail operands at @index.  | 
2872  |  | /// If @index == -1, it pushes the operand to the end of the ops array.  | 
2873  |  | /// Already present operands are moved.  | 
2874  |  | void AArch64_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Imm)  | 
2875  | 6.60k  | { | 
2876  | 6.60k  |   if (!detail_is_set(MI))  | 
2877  | 0  |     return;  | 
2878  | 6.60k  |   AArch64_check_safe_inc(MI);  | 
2879  |  |  | 
2880  | 6.60k  |   cs_aarch64_op op;  | 
2881  | 6.60k  |   AArch64_setup_op(&op);  | 
2882  | 6.60k  |   op.type = AARCH64_OP_IMM;  | 
2883  | 6.60k  |   op.imm = Imm;  | 
2884  | 6.60k  |   op.access = CS_AC_READ;  | 
2885  |  |  | 
2886  | 6.60k  |   insert_op(MI, index, op);  | 
2887  | 6.60k  | }  | 
2888  |  |  | 
2889  |  | void AArch64_insert_detail_op_sys(MCInst *MI, unsigned index,  | 
2890  |  |           aarch64_sysop sys_op, aarch64_op_type type)  | 
2891  | 9.44k  | { | 
2892  | 9.44k  |   if (!detail_is_set(MI))  | 
2893  | 0  |     return;  | 
2894  | 9.44k  |   AArch64_check_safe_inc(MI);  | 
2895  |  |  | 
2896  | 9.44k  |   cs_aarch64_op op;  | 
2897  | 9.44k  |   AArch64_setup_op(&op);  | 
2898  | 9.44k  |   op.type = type;  | 
2899  | 9.44k  |   op.sysop = sys_op;  | 
2900  | 9.44k  |   if (op.sysop.sub_type == AARCH64_OP_EXACTFPIMM) { | 
2901  | 9.17k  |     op.fp = aarch64_exact_fp_to_fp(op.sysop.imm.exactfpimm);  | 
2902  | 9.17k  |   }  | 
2903  | 9.44k  |   insert_op(MI, index, op);  | 
2904  | 9.44k  | }  | 
2905  |  |  | 
2906  |  | void AArch64_insert_detail_op_sme(MCInst *MI, unsigned index,  | 
2907  |  |           aarch64_op_sme sme_op)  | 
2908  | 3.94k  | { | 
2909  | 3.94k  |   if (!detail_is_set(MI))  | 
2910  | 0  |     return;  | 
2911  | 3.94k  |   AArch64_check_safe_inc(MI);  | 
2912  |  |  | 
2913  | 3.94k  |   cs_aarch64_op op;  | 
2914  | 3.94k  |   AArch64_setup_op(&op);  | 
2915  | 3.94k  |   op.type = AARCH64_OP_SME;  | 
2916  | 3.94k  |   op.sme = sme_op;  | 
2917  | 3.94k  |   insert_op(MI, index, op);  | 
2918  | 3.94k  | }  | 
2919  |  |  | 
2920  |  | #endif  |