Coverage Report

Created: 2023-09-25 06:24

/src/capstonenext/arch/ARM/ARMMapping.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
/*    Rot127 <unisono@quyllur.org>, 2022-2023 */
4
5
#ifdef CAPSTONE_HAS_ARM
6
7
#include <stdio.h>
8
#include <string.h>
9
10
#include "capstone/arm.h"
11
#include "capstone/capstone.h"
12
13
#include "../../Mapping.h"
14
#include "../../MCDisassembler.h"
15
#include "../../cs_priv.h"
16
#include "../../cs_simple_types.h"
17
18
#include "ARMAddressingModes.h"
19
#include "ARMDisassemblerExtension.h"
20
#include "ARMBaseInfo.h"
21
#include "ARMLinkage.h"
22
#include "ARMInstPrinter.h"
23
#include "ARMMapping.h"
24
25
static const char *get_custom_reg_alias(unsigned reg)
26
755k
{
27
755k
  switch (reg) {
28
5.34k
  case ARM_REG_R9:
29
5.34k
    return "sb";
30
3.44k
  case ARM_REG_R10:
31
3.44k
    return "sl";
32
1.69k
  case ARM_REG_R11:
33
1.69k
    return "fp";
34
3.36k
  case ARM_REG_R12:
35
3.36k
    return "ip";
36
42.4k
  case ARM_REG_R13:
37
42.4k
    return "sp";
38
14.8k
  case ARM_REG_R14:
39
14.8k
    return "lr";
40
9.88k
  case ARM_REG_R15:
41
9.88k
    return "pc";
42
755k
  }
43
674k
  return NULL;
44
755k
}
45
46
const char *ARM_reg_name(csh handle, unsigned int reg)
47
755k
{
48
755k
  int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;
49
755k
  const char *alias = get_custom_reg_alias(reg);
50
755k
  if ((syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS) && alias)
51
0
    return alias;
52
53
755k
  if (reg == ARM_REG_INVALID || reg >= ARM_REG_ENDING) {
54
    // This might be a system register or banked register encoding.
55
    // Note: The system and banked register encodings can overlap.
56
    // So this might return a system register name although a
57
    // banked register name is expected.
58
0
    const ARMSysReg_MClassSysReg *sys_reg =
59
0
      ARMSysReg_lookupMClassSysRegByEncoding(reg);
60
0
    if (sys_reg)
61
0
      return sys_reg->Name;
62
0
    const ARMBankedReg_BankedReg *banked_reg =
63
0
      ARMBankedReg_lookupBankedRegByEncoding(reg);
64
0
    if (banked_reg)
65
0
      return banked_reg->Name;
66
0
  }
67
68
755k
  if (syntax_opt & CS_OPT_SYNTAX_NOREGNAME) {
69
0
    return ARM_LLVM_getRegisterName(reg, ARM_NoRegAltName);
70
0
  }
71
755k
  return ARM_LLVM_getRegisterName(reg, ARM_RegNamesRaw);
72
755k
}
73
74
const insn_map arm_insns[] = {
75
#include "ARMGenCSMappingInsn.inc"
76
};
77
78
void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
79
1.21M
{
80
  // Not used by ARM. Information is set after disassembly.
81
1.21M
}
82
83
/// Patches the register names with Capstone specific alias.
84
/// Those are common alias for registers (e.g. r15 = pc)
85
/// which are not set in LLVM.
86
static void patch_cs_reg_alias(char *asm_str)
87
0
{
88
0
  char *r9 = strstr(asm_str, "r9");
89
0
  while (r9) {
90
0
    r9[0] = 's';
91
0
    r9[1] = 'b';
92
0
    r9 = strstr(asm_str, "r9");
93
0
  }
94
0
  char *r10 = strstr(asm_str, "r10");
95
0
  while (r10) {
96
0
    r10[0] = 's';
97
0
    r10[1] = 'l';
98
0
    memmove(r10 + 2, r10 + 3, strlen(r10 + 3));
99
0
    asm_str[strlen(asm_str) - 1] = '\0';
100
0
    r10 = strstr(asm_str, "r10");
101
0
  }
102
0
  char *r11 = strstr(asm_str, "r11");
103
0
  while (r11) {
104
0
    r11[0] = 'f';
105
0
    r11[1] = 'p';
106
0
    memmove(r11 + 2, r11 + 3, strlen(r11 + 3));
107
0
    asm_str[strlen(asm_str) - 1] = '\0';
108
0
    r11 = strstr(asm_str, "r11");
109
0
  }
110
0
  char *r12 = strstr(asm_str, "r12");
111
0
  while (r12) {
112
0
    r12[0] = 'i';
113
0
    r12[1] = 'p';
114
0
    memmove(r12 + 2, r12 + 3, strlen(r12 + 3));
115
0
    asm_str[strlen(asm_str) - 1] = '\0';
116
0
    r12 = strstr(asm_str, "r12");
117
0
  }
118
0
  char *r13 = strstr(asm_str, "r13");
119
0
  while (r13) {
120
0
    r13[0] = 's';
121
0
    r13[1] = 'p';
122
0
    memmove(r13 + 2, r13 + 3, strlen(r13 + 3));
123
0
    asm_str[strlen(asm_str) - 1] = '\0';
124
0
    r13 = strstr(asm_str, "r13");
125
0
  }
126
0
  char *r14 = strstr(asm_str, "r14");
127
0
  while (r14) {
128
0
    r14[0] = 'l';
129
0
    r14[1] = 'r';
130
0
    memmove(r14 + 2, r14 + 3, strlen(r14 + 3));
131
0
    asm_str[strlen(asm_str) - 1] = '\0';
132
0
    r14 = strstr(asm_str, "r14");
133
0
  }
134
0
  char *r15 = strstr(asm_str, "r15");
135
0
  while (r15) {
136
0
    r15[0] = 'p';
137
0
    r15[1] = 'c';
138
0
    memmove(r15 + 2, r15 + 3, strlen(r15 + 3));
139
0
    asm_str[strlen(asm_str) - 1] = '\0';
140
0
    r15 = strstr(asm_str, "r15");
141
0
  }
142
0
}
143
144
/// Adds group to the instruction which are not defined in LLVM.
145
static void ARM_add_cs_groups(MCInst *MI)
146
1.21M
{
147
1.21M
  unsigned Opcode = MI->flat_insn->id;
148
1.21M
  switch (Opcode) {
149
1.16M
  default:
150
1.16M
    return;
151
1.16M
  case ARM_INS_SVC:
152
7.90k
    add_group(MI, ARM_GRP_INT);
153
7.90k
    break;
154
15.2k
  case ARM_INS_CDP:
155
27.5k
  case ARM_INS_CDP2:
156
30.1k
  case ARM_INS_MCR:
157
33.3k
  case ARM_INS_MCR2:
158
34.1k
  case ARM_INS_MCRR:
159
35.4k
  case ARM_INS_MCRR2:
160
38.2k
  case ARM_INS_MRC:
161
40.9k
  case ARM_INS_MRC2:
162
41.0k
  case ARM_INS_SMC:
163
41.0k
    add_group(MI, ARM_GRP_PRIVILEGE);
164
41.0k
    break;
165
1.21M
  }
166
1.21M
}
167
168
/// Some instructions have their operands not defined but
169
/// hardcoded as string.
170
/// Here we add those oprands to detail.
171
static void ARM_add_not_defined_ops(MCInst *MI)
172
1.21M
{
173
1.21M
  if (!detail_is_set(MI))
174
0
    return;
175
1.21M
  unsigned Opcode = MCInst_getOpcode(MI);
176
1.21M
  switch (Opcode) {
177
1.17M
  default:
178
1.17M
    return;
179
1.17M
  case ARM_t2MOVsra_flag:
180
0
  case ARM_t2MOVsrl_flag:
181
0
    ARM_insert_detail_op_imm_at(MI, 2, 1, CS_AC_READ);
182
0
    break;
183
203
  case ARM_VCMPEZD:
184
561
  case ARM_VCMPZD:
185
1.76k
  case ARM_tRSB:
186
1.83k
  case ARM_VCMPEZH:
187
2.16k
  case ARM_VCMPEZS:
188
2.22k
  case ARM_VCMPZH:
189
2.29k
  case ARM_VCMPZS:
190
2.29k
    ARM_insert_detail_op_imm_at(MI, 1, 0, CS_AC_READ);
191
2.29k
    break;
192
89
  case ARM_MVE_VSHLL_lws16bh:
193
178
  case ARM_MVE_VSHLL_lws16th:
194
392
  case ARM_MVE_VSHLL_lwu16bh:
195
611
  case ARM_MVE_VSHLL_lwu16th:
196
611
    ARM_insert_detail_op_imm_at(MI, 2, 16, CS_AC_READ);
197
611
    break;
198
100
  case ARM_MVE_VSHLL_lws8bh:
199
269
  case ARM_MVE_VSHLL_lws8th:
200
584
  case ARM_MVE_VSHLL_lwu8bh:
201
664
  case ARM_MVE_VSHLL_lwu8th:
202
664
    ARM_insert_detail_op_imm_at(MI, 2, 8, CS_AC_READ);
203
664
    break;
204
260
  case ARM_VCEQzv16i8:
205
549
  case ARM_VCEQzv2f32:
206
665
  case ARM_VCEQzv2i32:
207
888
  case ARM_VCEQzv4f16:
208
934
  case ARM_VCEQzv4f32:
209
1.04k
  case ARM_VCEQzv4i16:
210
1.11k
  case ARM_VCEQzv4i32:
211
1.41k
  case ARM_VCEQzv8f16:
212
1.65k
  case ARM_VCEQzv8i16:
213
1.72k
  case ARM_VCEQzv8i8:
214
1.95k
  case ARM_VCGEzv16i8:
215
2.03k
  case ARM_VCGEzv2f32:
216
2.10k
  case ARM_VCGEzv2i32:
217
2.18k
  case ARM_VCGEzv4f16:
218
2.59k
  case ARM_VCGEzv4f32:
219
2.66k
  case ARM_VCGEzv4i16:
220
2.90k
  case ARM_VCGEzv4i32:
221
2.97k
  case ARM_VCGEzv8f16:
222
3.04k
  case ARM_VCGEzv8i16:
223
3.11k
  case ARM_VCGEzv8i8:
224
3.15k
  case ARM_VCLEzv16i8:
225
3.37k
  case ARM_VCLEzv2f32:
226
3.47k
  case ARM_VCLEzv2i32:
227
3.54k
  case ARM_VCLEzv4f16:
228
3.78k
  case ARM_VCLEzv4f32:
229
3.90k
  case ARM_VCLEzv4i16:
230
3.96k
  case ARM_VCLEzv4i32:
231
4.22k
  case ARM_VCLEzv8f16:
232
4.29k
  case ARM_VCLEzv8i16:
233
4.36k
  case ARM_VCLEzv8i8:
234
4.44k
  case ARM_VCLTzv16i8:
235
4.97k
  case ARM_VCLTzv2f32:
236
5.05k
  case ARM_VCLTzv2i32:
237
5.13k
  case ARM_VCLTzv4f16:
238
5.20k
  case ARM_VCLTzv4f32:
239
5.50k
  case ARM_VCLTzv4i16:
240
5.58k
  case ARM_VCLTzv4i32:
241
5.64k
  case ARM_VCLTzv8f16:
242
5.71k
  case ARM_VCLTzv8i16:
243
5.79k
  case ARM_VCLTzv8i8:
244
5.88k
  case ARM_VCGTzv16i8:
245
5.95k
  case ARM_VCGTzv2f32:
246
6.14k
  case ARM_VCGTzv2i32:
247
6.37k
  case ARM_VCGTzv4f16:
248
6.44k
  case ARM_VCGTzv4f32:
249
6.54k
  case ARM_VCGTzv4i16:
250
6.58k
  case ARM_VCGTzv4i32:
251
6.65k
  case ARM_VCGTzv8f16:
252
6.85k
  case ARM_VCGTzv8i16:
253
6.93k
  case ARM_VCGTzv8i8:
254
6.93k
    ARM_insert_detail_op_imm_at(MI, 2, 0, CS_AC_READ);
255
6.93k
    break;
256
10
  case ARM_BX_RET:
257
10
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_LR, CS_AC_READ);
258
10
    break;
259
66
  case ARM_MOVPCLR:
260
159
  case ARM_t2SUBS_PC_LR:
261
159
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_PC, CS_AC_WRITE);
262
159
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_LR, CS_AC_READ);
263
159
    break;
264
36
  case ARM_FMSTAT:
265
36
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_APSR_NZCV,
266
36
              CS_AC_WRITE);
267
36
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR, CS_AC_READ);
268
36
    break;
269
34
  case ARM_VLDR_FPCXTNS_off:
270
100
  case ARM_VLDR_FPCXTNS_post:
271
172
  case ARM_VLDR_FPCXTNS_pre:
272
172
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTNS,
273
172
              CS_AC_WRITE);
274
172
    break;
275
51
  case ARM_VSTR_FPCXTNS_off:
276
631
  case ARM_VSTR_FPCXTNS_post:
277
1.00k
  case ARM_VSTR_FPCXTNS_pre:
278
1.00k
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTNS, CS_AC_READ);
279
1.00k
    break;
280
165
  case ARM_VLDR_FPCXTS_off:
281
188
  case ARM_VLDR_FPCXTS_post:
282
260
  case ARM_VLDR_FPCXTS_pre:
283
260
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTS, CS_AC_WRITE);
284
260
    break;
285
187
  case ARM_VSTR_FPCXTS_off:
286
268
  case ARM_VSTR_FPCXTS_post:
287
396
  case ARM_VSTR_FPCXTS_pre:
288
396
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTS, CS_AC_READ);
289
396
    break;
290
721
  case ARM_VLDR_FPSCR_NZCVQC_off:
291
790
  case ARM_VLDR_FPSCR_NZCVQC_post:
292
913
  case ARM_VLDR_FPSCR_NZCVQC_pre:
293
913
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR_NZCVQC,
294
913
              CS_AC_WRITE);
295
913
    break;
296
90
  case ARM_VSTR_FPSCR_NZCVQC_off:
297
125
  case ARM_VSTR_FPSCR_NZCVQC_post:
298
197
  case ARM_VSTR_FPSCR_NZCVQC_pre:
299
197
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR_NZCVQC,
300
197
              CS_AC_READ);
301
197
    break;
302
86
  case ARM_VMSR:
303
263
  case ARM_VLDR_FPSCR_off:
304
337
  case ARM_VLDR_FPSCR_post:
305
513
  case ARM_VLDR_FPSCR_pre:
306
513
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR, CS_AC_WRITE);
307
513
    break;
308
209
  case ARM_VSTR_FPSCR_off:
309
279
  case ARM_VSTR_FPSCR_post:
310
605
  case ARM_VSTR_FPSCR_pre:
311
605
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR, CS_AC_READ);
312
605
    break;
313
0
  case ARM_VLDR_P0_off:
314
0
  case ARM_VLDR_P0_post:
315
0
  case ARM_VLDR_P0_pre:
316
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_P0, CS_AC_WRITE);
317
0
    break;
318
0
  case ARM_VSTR_P0_off:
319
0
  case ARM_VSTR_P0_post:
320
0
  case ARM_VSTR_P0_pre:
321
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_P0, CS_AC_READ);
322
0
    break;
323
0
  case ARM_VLDR_VPR_off:
324
0
  case ARM_VLDR_VPR_post:
325
0
  case ARM_VLDR_VPR_pre:
326
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_VPR, CS_AC_WRITE);
327
0
    break;
328
0
  case ARM_VSTR_VPR_off:
329
0
  case ARM_VSTR_VPR_post:
330
0
  case ARM_VSTR_VPR_pre:
331
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_VPR, CS_AC_READ);
332
0
    break;
333
118
  case ARM_VMSR_FPEXC:
334
118
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPEXC, CS_AC_WRITE);
335
118
    break;
336
217
  case ARM_VMSR_FPINST:
337
217
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPINST, CS_AC_WRITE);
338
217
    break;
339
47
  case ARM_VMSR_FPINST2:
340
47
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPINST2,
341
47
              CS_AC_WRITE);
342
47
    break;
343
197
  case ARM_VMSR_FPSID:
344
197
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSID, CS_AC_WRITE);
345
197
    break;
346
67
  case ARM_t2SRSDB:
347
133
  case ARM_t2SRSIA:
348
133
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_SP, CS_AC_WRITE);
349
133
    break;
350
66
  case ARM_t2SRSDB_UPD:
351
100
  case ARM_t2SRSIA_UPD:
352
100
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_SP,
353
100
              CS_AC_READ | CS_AC_WRITE);
354
100
    break;
355
79
  case ARM_MRSsys:
356
209
  case ARM_t2MRSsys_AR:
357
209
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_SPSR, CS_AC_READ);
358
209
    break;
359
295
  case ARM_MRS:
360
329
  case ARM_t2MRS_AR:
361
329
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_APSR, CS_AC_READ);
362
329
    break;
363
669
  case ARM_VMRS:
364
669
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR, CS_AC_READ);
365
669
    break;
366
34
  case ARM_VMRS_FPCXTNS:
367
34
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPCXTNS, CS_AC_READ);
368
34
    break;
369
103
  case ARM_VMRS_FPCXTS:
370
103
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPCXTS, CS_AC_READ);
371
103
    break;
372
66
  case ARM_VMRS_FPEXC:
373
66
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPEXC, CS_AC_READ);
374
66
    break;
375
67
  case ARM_VMRS_FPINST:
376
67
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPINST, CS_AC_READ);
377
67
    break;
378
70
  case ARM_VMRS_FPINST2:
379
70
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPINST2, CS_AC_READ);
380
70
    break;
381
18
  case ARM_VMRS_FPSCR_NZCVQC:
382
18
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR_NZCVQC,
383
18
              CS_AC_READ);
384
18
    break;
385
72
  case ARM_VMRS_FPSID:
386
72
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSID, CS_AC_READ);
387
72
    break;
388
72
  case ARM_VMRS_MVFR0:
389
72
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR0, CS_AC_READ);
390
72
    break;
391
99
  case ARM_VMRS_MVFR1:
392
99
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR1, CS_AC_READ);
393
99
    break;
394
77
  case ARM_VMRS_MVFR2:
395
77
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR2, CS_AC_READ);
396
77
    break;
397
0
  case ARM_VMRS_P0:
398
0
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_P0, CS_AC_READ);
399
0
    break;
400
0
  case ARM_VMRS_VPR:
401
0
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_VPR, CS_AC_READ);
402
0
    break;
403
501
  case ARM_MOVsr:
404
    // Add shift information
405
501
    ARM_get_detail(MI)->operands[1].shift.type =
406
501
      (arm_shifter)ARM_AM_getSORegShOp(
407
501
        MCInst_getOpVal(MI, 3)) +
408
501
      ARM_SFT_ASR_REG - 1;
409
501
    ARM_get_detail(MI)->operands[1].shift.value =
410
501
      MCInst_getOpVal(MI, 2);
411
501
    break;
412
666
  case ARM_MOVsi:
413
666
    if (ARM_AM_getSORegShOp(MCInst_getOpVal(MI, 2)) == ARM_AM_rrx) {
414
236
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_RRX;
415
236
      ARM_get_detail_op(MI, -1)->shift.value =
416
236
        translateShiftImm(ARM_AM_getSORegOffset(
417
236
          MCInst_getOpVal(MI, 2)));
418
236
      return;
419
236
    }
420
421
430
    ARM_get_detail_op(MI, -1)->shift.type =
422
430
      (arm_shifter)ARM_AM_getSORegShOp(
423
430
        MCInst_getOpVal(MI, 2));
424
430
    ARM_get_detail_op(MI, -1)->shift.value = translateShiftImm(
425
430
      ARM_AM_getSORegOffset(MCInst_getOpVal(MI, 2)));
426
430
    break;
427
967
  case ARM_STMDB_UPD:
428
1.36k
  case ARM_t2STMDB_UPD:
429
1.36k
    if (MCInst_getOpVal(MI, 0) == ARM_SP &&
430
1.36k
        MCInst_getNumOperands(MI) > 5)
431
518
      MI->flat_insn->id = ARM_INS_PUSH;
432
1.36k
    break;
433
1.41k
  case ARM_STR_PRE_IMM:
434
1.41k
    if (MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP &&
435
1.41k
        MCOperand_getImm(MCInst_getOperand(MI, (3))) == -4)
436
0
      MI->flat_insn->id = ARM_INS_PUSH;
437
1.41k
    break;
438
872
  case ARM_LDMIA_UPD:
439
1.13k
  case ARM_t2LDMIA_UPD:
440
1.13k
    if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP &&
441
1.13k
        MCInst_getNumOperands(MI) > 5)
442
496
      MI->flat_insn->id = ARM_INS_POP;
443
1.13k
    break;
444
1.75k
  case ARM_LDR_POST_IMM:
445
1.75k
    if (MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP &&
446
1.75k
        ARM_AM_getAM2Offset(
447
277
          MCOperand_getImm(MCInst_getOperand(MI, (4)))) == 4)
448
67
      MI->flat_insn->id = ARM_INS_POP;
449
1.75k
    break;
450
490
  case ARM_t2LDR_POST:
451
490
    if ((MCOperand_getReg(MCInst_getOperand(MI, (2))) == ARM_SP) &&
452
490
        (Opcode == ARM_t2LDR_POST &&
453
403
         (MCOperand_getImm(MCInst_getOperand(MI, (3))) == 4)))
454
66
      MI->flat_insn->id = ARM_INS_POP;
455
490
    break;
456
150
  case ARM_VSTMSDB_UPD:
457
320
  case ARM_VSTMDDB_UPD:
458
320
    if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP)
459
138
      MI->flat_insn->id = ARM_INS_VPUSH;
460
320
    break;
461
191
  case ARM_VLDMSIA_UPD:
462
637
  case ARM_VLDMDIA_UPD:
463
637
    if (MCOperand_getReg(MCInst_getOperand(MI, (0))) == ARM_SP)
464
178
      MI->flat_insn->id = ARM_INS_VPOP;
465
637
    break;
466
13.3k
  case ARM_tLDMIA: {
467
13.3k
    bool Writeback = true;
468
13.3k
    unsigned BaseReg = MCInst_getOpVal(MI, 0);
469
76.5k
    for (unsigned i = 3; i < MCInst_getNumOperands(MI); ++i) {
470
63.2k
      if (MCInst_getOpVal(MI, i) == BaseReg)
471
7.55k
        Writeback = false;
472
63.2k
    }
473
13.3k
    if (Writeback && detail_is_set(MI)) {
474
5.78k
      ARM_get_detail(MI)->operands[0].access |= CS_AC_WRITE;
475
5.78k
      MI->flat_insn->detail->writeback = true;
476
5.78k
    }
477
13.3k
    break;
478
191
  }
479
1.21M
  }
480
38.8k
  if (MI->flat_insn->id == ARM_INS_PUSH ||
481
38.8k
      MI->flat_insn->id == ARM_INS_POP ||
482
38.8k
      MI->flat_insn->id == ARM_INS_VPUSH ||
483
38.8k
      MI->flat_insn->id == ARM_INS_VPOP) {
484
1.46k
    map_add_implicit_read(MI, ARM_REG_SP);
485
1.46k
    map_add_implicit_write(MI, ARM_REG_SP);
486
1.46k
  }
487
38.8k
}
488
489
/// Unfortunately there is currently no way to easily extract
490
/// informaion about the vector data usage (sign and width used).
491
/// See: https://github.com/capstone-engine/capstone/issues/2152
492
void ARM_add_vector_data(MCInst *MI, arm_vectordata_type data_type)
493
79.2k
{
494
79.2k
  if (!detail_is_set(MI))
495
0
    return;
496
79.2k
  ARM_get_detail(MI)->vector_data = data_type;
497
79.2k
}
498
499
/// Unfortunately there is currently no way to easily extract
500
/// informaion about the vector size.
501
/// See: https://github.com/capstone-engine/capstone/issues/2152
502
void ARM_add_vector_size(MCInst *MI, unsigned size)
503
78.9k
{
504
78.9k
  if (!detail_is_set(MI))
505
0
    return;
506
78.9k
  ARM_get_detail(MI)->vector_size = size;
507
78.9k
}
508
509
/// For ARM the attributation of post-indexed instructions is poor.
510
/// Disponents or index register are sometimes not defined as such.
511
/// Here we try to detect such cases. We check if the base register
512
/// is a writeback register, but no other memory operand
513
/// was disassembled.
514
/// Because there must be a second memory operand (disponent/index)
515
/// We assume that the following operand is actually
516
/// the disponent/index reg.
517
static void ARM_post_index_detection(MCInst *MI)
518
1.21M
{
519
1.21M
  if (!detail_is_set(MI) || ARM_get_detail(MI)->post_index)
520
40.3k
    return;
521
522
1.17M
  int i = 0;
523
3.88M
  for (; i < ARM_get_detail(MI)->op_count; ++i) {
524
3.08M
    if (ARM_get_detail(MI)->operands[i].type & ARM_OP_MEM)
525
373k
      break;
526
3.08M
  }
527
1.17M
  if (i >= ARM_get_detail(MI)->op_count) {
528
    // Last operand
529
799k
    return;
530
799k
  }
531
532
373k
  cs_arm_op *op = &ARM_get_detail(MI)->operands[i];
533
373k
  cs_arm_op op_next = ARM_get_detail(MI)->operands[i + 1];
534
373k
  if (op_next.type == ARM_OP_INVALID || op->mem.disp != 0 || op->mem.index != ARM_REG_INVALID)
535
356k
    return;
536
537
16.8k
  if (op_next.type & CS_OP_IMM)
538
6.20k
    op->mem.disp = op_next.imm;
539
10.6k
  else if (op_next.type & CS_OP_REG)
540
10.6k
    op->mem.index = op_next.reg;
541
542
16.8k
  op->subtracted = op_next.subtracted;
543
16.8k
  ARM_get_detail(MI)->post_index = true;
544
16.8k
  MI->flat_insn->detail->writeback = true;
545
16.8k
  ARM_dec_op_count(MI);
546
16.8k
}
547
548
/// Decodes the asm string for a given instruction
549
/// and fills the detail information about the instruction and its operands.
550
void ARM_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
551
1.21M
{
552
1.21M
  ARM_LLVM_printInstruction(MI, O, info);
553
1.21M
  ARM_add_not_defined_ops(MI);
554
1.21M
  ARM_post_index_detection(MI);
555
1.21M
  ARM_add_cs_groups(MI);
556
1.21M
  int syntax_opt = MI->csh->syntax;
557
1.21M
  if (syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS)
558
0
    patch_cs_reg_alias(O->buffer);
559
1.21M
}
560
561
#ifndef CAPSTONE_DIET
562
static const char *const insn_name_maps[] = {
563
#include "ARMGenCSMappingInsnName.inc"
564
  // Hard coded alias in LLVM, not defined as alias or instruction.
565
  // We give them a unique ID for convenience.
566
  "vpop",
567
  "vpush",
568
};
569
#endif
570
571
#ifndef CAPSTONE_DIET
572
static arm_reg arm_flag_regs[] = {
573
  ARM_REG_APSR,       ARM_REG_APSR_NZCV, ARM_REG_CPSR,
574
  ARM_REG_FPCXTNS,      ARM_REG_FPCXTS,  ARM_REG_FPEXC,
575
  ARM_REG_FPINST,       ARM_REG_FPSCR,   ARM_REG_FPSCR_NZCV,
576
  ARM_REG_FPSCR_NZCVQC,
577
};
578
#endif // CAPSTONE_DIET
579
580
const char *ARM_insn_name(csh handle, unsigned int id)
581
1.52M
{
582
1.52M
#ifndef CAPSTONE_DIET
583
1.52M
  if (id >= ARM_INS_ENDING)
584
0
    return NULL;
585
586
1.52M
  return insn_name_maps[id];
587
#else
588
  return NULL;
589
#endif
590
1.52M
}
591
592
#ifndef CAPSTONE_DIET
593
static const name_map group_name_maps[] = {
594
  // generic groups
595
  { ARM_GRP_INVALID, NULL },
596
  { ARM_GRP_JUMP, "jump" },
597
  { ARM_GRP_CALL, "call" },
598
  { ARM_GRP_INT, "int" },
599
  { ARM_GRP_PRIVILEGE, "privilege" },
600
  { ARM_GRP_BRANCH_RELATIVE, "branch_relative" },
601
602
// architecture-specific groups
603
#include "ARMGenCSFeatureName.inc"
604
};
605
#endif
606
607
const char *ARM_group_name(csh handle, unsigned int id)
608
2.06M
{
609
2.06M
#ifndef CAPSTONE_DIET
610
2.06M
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
611
#else
612
  return NULL;
613
#endif
614
2.06M
}
615
616
// list all relative branch instructions
617
// ie: insns[i].branch && !insns[i].indirect_branch
618
static const unsigned int insn_rel[] = {
619
  ARM_BL,   ARM_BLX_pred, ARM_Bcc,   ARM_t2B,  ARM_t2Bcc,
620
  ARM_tB,   ARM_tBcc, ARM_tCBNZ, ARM_tCBZ, ARM_BL_pred,
621
  ARM_BLXi, ARM_tBL,  ARM_tBLXi, 0
622
};
623
624
static const unsigned int insn_blx_rel_to_arm[] = { ARM_tBLXi, 0 };
625
626
// check if this insn is relative branch
627
bool ARM_rel_branch(cs_struct *h, unsigned int id)
628
430k
{
629
430k
  int i;
630
631
5.90M
  for (i = 0; insn_rel[i]; i++) {
632
5.48M
    if (id == insn_rel[i]) {
633
17.8k
      return true;
634
17.8k
    }
635
5.48M
  }
636
637
  // not found
638
412k
  return false;
639
430k
}
640
641
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id)
642
12.8k
{
643
12.8k
  int i;
644
645
25.5k
  for (i = 0; insn_blx_rel_to_arm[i]; i++)
646
12.8k
    if (id == insn_blx_rel_to_arm[i])
647
171
      return true;
648
649
  // not found
650
12.6k
  return false;
651
12.8k
}
652
653
void ARM_check_updates_flags(MCInst *MI)
654
1.22M
{
655
1.22M
#ifndef CAPSTONE_DIET
656
1.22M
  if (!detail_is_set(MI))
657
0
    return;
658
1.22M
  cs_detail *detail = get_detail(MI);
659
1.25M
  for (int i = 0; i < detail->regs_write_count; ++i) {
660
185k
    if (detail->regs_write[i] == 0)
661
0
      return;
662
857k
    for (int j = 0; j < ARR_SIZE(arm_flag_regs); ++j) {
663
822k
      if (detail->regs_write[i] == arm_flag_regs[j]) {
664
150k
        detail->arm.update_flags = true;
665
150k
        return;
666
150k
      }
667
822k
    }
668
185k
  }
669
1.22M
#endif // CAPSTONE_DIET
670
1.22M
}
671
672
void ARM_set_instr_map_data(MCInst *MI)
673
1.22M
{
674
1.22M
  map_cs_id(MI, arm_insns, ARR_SIZE(arm_insns));
675
1.22M
  map_implicit_reads(MI, arm_insns);
676
1.22M
  map_implicit_writes(MI, arm_insns);
677
1.22M
  ARM_check_updates_flags(MI);
678
1.22M
  map_groups(MI, arm_insns);
679
1.22M
}
680
681
bool ARM_getInstruction(csh handle, const uint8_t *code, size_t code_len,
682
      MCInst *instr, uint16_t *size, uint64_t address,
683
      void *info)
684
1.22M
{
685
1.22M
  ARM_init_cs_detail(instr);
686
1.22M
  bool Result = ARM_LLVM_getInstruction(handle, code, code_len, instr,
687
1.22M
                size, address,
688
1.22M
                info) != MCDisassembler_Fail;
689
1.22M
  ARM_set_instr_map_data(instr);
690
1.22M
  return Result;
691
1.22M
}
692
693
#define GET_REGINFO_MC_DESC
694
#include "ARMGenRegisterInfo.inc"
695
696
void ARM_init_mri(MCRegisterInfo *MRI)
697
14.1k
{
698
14.1k
  MCRegisterInfo_InitMCRegisterInfo(MRI, ARMRegDesc, ARM_REG_ENDING, 0, 0,
699
14.1k
            ARMMCRegisterClasses,
700
14.1k
            ARR_SIZE(ARMMCRegisterClasses), 0, 0,
701
14.1k
            ARMRegDiffLists, 0, ARMSubRegIdxLists,
702
14.1k
            ARR_SIZE(ARMSubRegIdxLists), 0);
703
14.1k
}
704
705
static const map_insn_ops insn_operands[] = {
706
#include "ARMGenCSMappingInsnOp.inc"
707
};
708
709
#ifndef CAPSTONE_DIET
710
void ARM_reg_access(const cs_insn *insn, cs_regs regs_read,
711
        uint8_t *regs_read_count, cs_regs regs_write,
712
        uint8_t *regs_write_count)
713
0
{
714
0
  uint8_t i;
715
0
  uint8_t read_count, write_count;
716
0
  cs_arm *arm = &(insn->detail->arm);
717
718
0
  read_count = insn->detail->regs_read_count;
719
0
  write_count = insn->detail->regs_write_count;
720
721
  // implicit registers
722
0
  memcpy(regs_read, insn->detail->regs_read,
723
0
         read_count * sizeof(insn->detail->regs_read[0]));
724
0
  memcpy(regs_write, insn->detail->regs_write,
725
0
         write_count * sizeof(insn->detail->regs_write[0]));
726
727
  // explicit registers
728
0
  for (i = 0; i < arm->op_count; i++) {
729
0
    cs_arm_op *op = &(arm->operands[i]);
730
0
    switch ((int)op->type) {
731
0
    case ARM_OP_REG:
732
0
      if ((op->access & CS_AC_READ) &&
733
0
          !arr_exist(regs_read, read_count, op->reg)) {
734
0
        regs_read[read_count] = (uint16_t)op->reg;
735
0
        read_count++;
736
0
      }
737
0
      if ((op->access & CS_AC_WRITE) &&
738
0
          !arr_exist(regs_write, write_count, op->reg)) {
739
0
        regs_write[write_count] = (uint16_t)op->reg;
740
0
        write_count++;
741
0
      }
742
0
      break;
743
0
    case ARM_OP_MEM:
744
      // registers appeared in memory references always being read
745
0
      if ((op->mem.base != ARM_REG_INVALID) &&
746
0
          !arr_exist(regs_read, read_count, op->mem.base)) {
747
0
        regs_read[read_count] = (uint16_t)op->mem.base;
748
0
        read_count++;
749
0
      }
750
0
      if ((op->mem.index != ARM_REG_INVALID) &&
751
0
          !arr_exist(regs_read, read_count, op->mem.index)) {
752
0
        regs_read[read_count] = (uint16_t)op->mem.index;
753
0
        read_count++;
754
0
      }
755
0
      if ((insn->detail->writeback) &&
756
0
          (op->mem.base != ARM_REG_INVALID) &&
757
0
          !arr_exist(regs_write, write_count, op->mem.base)) {
758
0
        regs_write[write_count] =
759
0
          (uint16_t)op->mem.base;
760
0
        write_count++;
761
0
      }
762
0
    default:
763
0
      break;
764
0
    }
765
0
  }
766
767
0
  *regs_read_count = read_count;
768
0
  *regs_write_count = write_count;
769
0
}
770
#endif
771
772
void ARM_setup_op(cs_arm_op *op)
773
43.9M
{
774
43.9M
  memset(op, 0, sizeof(cs_arm_op));
775
43.9M
  op->type = ARM_OP_INVALID;
776
43.9M
  op->vector_index = -1;
777
43.9M
  op->neon_lane = -1;
778
43.9M
}
779
780
void ARM_init_cs_detail(MCInst *MI)
781
1.22M
{
782
1.22M
  if (detail_is_set(MI)) {
783
1.22M
    unsigned int i;
784
785
1.22M
    memset(get_detail(MI), 0,
786
1.22M
           offsetof(cs_detail, arm) + sizeof(cs_arm));
787
788
45.1M
    for (i = 0; i < ARR_SIZE(ARM_get_detail(MI)->operands); i++)
789
43.9M
      ARM_setup_op(&ARM_get_detail(MI)->operands[i]);
790
1.22M
    ARM_get_detail(MI)->cc = ARMCC_UNDEF;
791
1.22M
    ARM_get_detail(MI)->vcc = ARMVCC_None;
792
1.22M
  }
793
1.22M
}
794
795
static uint64_t t_add_pc(MCInst *MI, uint64_t v)
796
347k
{
797
347k
  int32_t imm = (int32_t)v;
798
347k
  if (ARM_rel_branch(MI->csh, MI->Opcode)) {
799
0
    uint32_t address;
800
801
    // only do this for relative branch
802
0
    if (MI->csh->mode & CS_MODE_THUMB) {
803
0
      address = (uint32_t)MI->address + 4;
804
0
      if (ARM_blx_to_arm_mode(MI->csh, MI->Opcode)) {
805
        // here need to align down to the nearest 4-byte address
806
0
#define _ALIGN_DOWN(v, align_width) ((v / align_width) * align_width)
807
0
        address = _ALIGN_DOWN(address, 4);
808
0
#undef _ALIGN_DOWN
809
0
      }
810
0
    } else {
811
0
      address = (uint32_t)MI->address + 8;
812
0
    }
813
814
0
    imm += address;
815
0
    return imm;
816
0
  }
817
347k
  return v;
818
347k
}
819
820
/// Transform a Qs register to its corresponding Ds + Offset register.
821
static uint64_t t_qpr_to_dpr_list(MCInst *MI, unsigned OpNum, uint8_t offset)
822
38.9k
{
823
38.9k
  uint64_t v = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
824
38.9k
  if (v >= ARM_REG_Q0 && v <= ARM_REG_Q15)
825
0
    return ARM_REG_D0 + offset + (v - ARM_REG_Q0) * 2;
826
38.9k
  return v + offset;
827
38.9k
}
828
829
static uint64_t t_mod_imm_rotate(uint64_t v)
830
15.8k
{
831
15.8k
  unsigned Bits = v & 0xFF;
832
15.8k
  unsigned Rot = (v & 0xF00) >> 7;
833
15.8k
  int32_t Rotated = ARM_AM_rotr32(Bits, Rot);
834
15.8k
  return Rotated;
835
15.8k
}
836
837
inline static uint64_t t_mod_imm_bits(uint64_t v)
838
1.45k
{
839
1.45k
  unsigned Bits = v & 0xFF;
840
1.45k
  return Bits;
841
1.45k
}
842
843
inline static uint64_t t_mod_imm_rot(uint64_t v)
844
1.45k
{
845
1.45k
  unsigned Rot = (v & 0xF00) >> 7;
846
1.45k
  return Rot;
847
1.45k
}
848
849
static uint64_t t_vmov_mod_imm(uint64_t v)
850
5.31k
{
851
5.31k
  unsigned EltBits;
852
5.31k
  uint64_t Val = ARM_AM_decodeVMOVModImm(v, &EltBits);
853
5.31k
  return Val;
854
5.31k
}
855
856
/// Initializes or finishes a memory operand of Capstone (depending on \p
857
/// status). A memory operand in Capstone can be assembled by two LLVM operands.
858
/// E.g. the base register and the immediate disponent.
859
static void ARM_set_mem_access(MCInst *MI, bool status)
860
727k
{
861
727k
  if (!detail_is_set(MI))
862
0
    return;
863
727k
  set_doing_mem(MI, status);
864
727k
  if (status) {
865
363k
    ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
866
363k
    ARM_get_detail_op(MI, 0)->mem.base = ARM_REG_INVALID;
867
363k
    ARM_get_detail_op(MI, 0)->mem.index = ARM_REG_INVALID;
868
363k
    ARM_get_detail_op(MI, 0)->mem.scale = 1;
869
363k
    ARM_get_detail_op(MI, 0)->mem.disp = 0;
870
871
363k
#ifndef CAPSTONE_DIET
872
363k
    uint8_t access =
873
363k
      map_get_op_access(MI, ARM_get_detail(MI)->op_count);
874
363k
    ARM_get_detail_op(MI, 0)->access = access;
875
363k
#endif
876
363k
  } else {
877
    // done, select the next operand slot
878
363k
    ARM_inc_op_count(MI);
879
363k
  }
880
727k
}
881
882
/// Fills cs_detail with operand shift information for the last added operand.
883
static void add_cs_detail_RegImmShift(MCInst *MI, ARM_AM_ShiftOpc ShOpc,
884
              unsigned ShImm)
885
44.7k
{
886
44.7k
  if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
887
1.01k
    return;
888
889
43.6k
  if (!detail_is_set(MI))
890
0
    return;
891
892
43.6k
  if (doing_mem(MI))
893
3.86k
    ARM_get_detail_op(MI, 0)->shift.type = (arm_shifter)ShOpc;
894
39.8k
  else
895
39.8k
    ARM_get_detail_op(MI, -1)->shift.type = (arm_shifter)ShOpc;
896
897
43.6k
  if (ShOpc != ARM_AM_rrx) {
898
40.1k
    if (doing_mem(MI))
899
3.47k
      ARM_get_detail_op(MI, 0)->shift.value =
900
3.47k
        translateShiftImm(ShImm);
901
36.7k
    else
902
36.7k
      ARM_get_detail_op(MI, -1)->shift.value =
903
36.7k
        translateShiftImm(ShImm);
904
40.1k
  }
905
43.6k
}
906
907
/// Fills cs_detail with the data of the operand.
908
/// This function handles operands which's original printer function has no
909
/// specialities.
910
static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
911
          unsigned OpNum)
912
4.31M
{
913
4.31M
  if (!detail_is_set(MI))
914
0
    return;
915
4.31M
  cs_op_type op_type = map_get_op_type(MI, OpNum);
916
917
  // Fill cs_detail
918
4.31M
  switch (op_group) {
919
0
  default:
920
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
921
0
    assert(0);
922
1.02M
  case ARM_OP_GROUP_PredicateOperand:
923
1.04M
  case ARM_OP_GROUP_MandatoryPredicateOperand:
924
1.04M
  case ARM_OP_GROUP_MandatoryInvertedPredicateOperand:
925
1.05M
  case ARM_OP_GROUP_MandatoryRestrictedPredicateOperand: {
926
1.05M
    ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(
927
1.05M
      MCInst_getOperand(MI, OpNum));
928
1.05M
    if ((unsigned)CC == 15 &&
929
1.05M
        op_group == ARM_OP_GROUP_PredicateOperand) {
930
1.65k
      ARM_get_detail(MI)->cc = ARMCC_UNDEF;
931
1.65k
      return;
932
1.65k
    }
933
1.05M
    if (CC == ARMCC_HS &&
934
1.05M
        op_group ==
935
9.85k
          ARM_OP_GROUP_MandatoryRestrictedPredicateOperand) {
936
1.42k
      ARM_get_detail(MI)->cc = ARMCC_HS;
937
1.42k
      return;
938
1.42k
    }
939
1.05M
    ARM_get_detail(MI)->cc = CC;
940
1.05M
    if (CC != ARMCC_AL)
941
186k
      map_add_implicit_read(MI, ARM_REG_CPSR);
942
1.05M
    break;
943
1.05M
  }
944
39.9k
  case ARM_OP_GROUP_VPTPredicateOperand: {
945
39.9k
    ARMVCC_VPTCodes VCC = (ARMVCC_VPTCodes)MCOperand_getImm(
946
39.9k
      MCInst_getOperand(MI, OpNum));
947
39.9k
    assert(VCC <= ARMVCC_Else);
948
39.9k
    if (VCC != ARMVCC_None)
949
4.19k
      ARM_get_detail(MI)->vcc = VCC;
950
39.9k
    break;
951
39.9k
  }
952
1.99M
  case ARM_OP_GROUP_Operand:
953
1.99M
    if (op_type == CS_OP_IMM) {
954
347k
      if (doing_mem(MI)) {
955
0
        ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
956
0
                  MCInst_getOpVal(MI,
957
0
                      OpNum));
958
347k
      } else {
959
347k
        ARM_set_detail_op_imm(
960
347k
          MI, OpNum, ARM_OP_IMM,
961
347k
          t_add_pc(MI,
962
347k
             MCInst_getOpVal(MI, OpNum)));
963
347k
      }
964
1.65M
    } else if (op_type == CS_OP_REG)
965
1.65M
      if (doing_mem(MI)) {
966
0
        bool is_index_reg = map_get_op_type(MI, OpNum) &
967
0
                CS_OP_MEM;
968
0
        ARM_set_detail_op_mem(
969
0
          MI, OpNum, is_index_reg, 0, 0,
970
0
          MCInst_getOpVal(MI, OpNum));
971
1.65M
      } else {
972
1.65M
        ARM_set_detail_op_reg(
973
1.65M
          MI, OpNum, MCInst_getOpVal(MI, OpNum));
974
1.65M
      }
975
0
    else
976
0
      assert(0 && "Op type not handled.");
977
1.99M
    break;
978
1.99M
  case ARM_OP_GROUP_PImmediate:
979
81.7k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_PIMM,
980
81.7k
              MCInst_getOpVal(MI, OpNum));
981
81.7k
    break;
982
148k
  case ARM_OP_GROUP_CImmediate:
983
148k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_CIMM,
984
148k
              MCInst_getOpVal(MI, OpNum));
985
148k
    break;
986
58.8k
  case ARM_OP_GROUP_AddrMode6Operand:
987
58.8k
    if (!doing_mem(MI))
988
58.8k
      ARM_set_mem_access(MI, true);
989
58.8k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
990
58.8k
              MCInst_getOpVal(MI, OpNum));
991
58.8k
    ARM_get_detail_op(MI, 0)->mem.align =
992
58.8k
      MCInst_getOpVal(MI, OpNum + 1) << 3;
993
58.8k
    ARM_set_mem_access(MI, false);
994
58.8k
    break;
995
18.6k
  case ARM_OP_GROUP_AddrMode6OffsetOperand: {
996
18.6k
    arm_reg reg = MCInst_getOpVal(MI, OpNum);
997
18.6k
    if (reg != 0) {
998
12.5k
      ARM_set_detail_op_mem_offset(MI, OpNum, reg, false);
999
12.5k
    }
1000
18.6k
    break;
1001
1.99M
  }
1002
49.8k
  case ARM_OP_GROUP_AddrMode7Operand:
1003
49.8k
    if (!doing_mem(MI))
1004
49.8k
      ARM_set_mem_access(MI, true);
1005
49.8k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1006
49.8k
              MCInst_getOpVal(MI, OpNum));
1007
49.8k
    ARM_set_mem_access(MI, false);
1008
49.8k
    break;
1009
295k
  case ARM_OP_GROUP_SBitModifierOperand: {
1010
295k
    unsigned SBit = MCInst_getOpVal(MI, OpNum);
1011
1012
295k
    if (SBit == 0) {
1013
      // Does not edit set flags.
1014
32.2k
      map_remove_implicit_write(MI, ARM_CPSR);
1015
32.2k
      ARM_get_detail(MI)->update_flags = false;
1016
32.2k
      break;
1017
32.2k
    }
1018
    // Add the implicit write again. Some instruction miss it.
1019
263k
    map_add_implicit_write(MI, ARM_CPSR);
1020
263k
    ARM_get_detail(MI)->update_flags = true;
1021
263k
    break;
1022
295k
  }
1023
3.31k
  case ARM_OP_GROUP_VectorListOne:
1024
3.97k
  case ARM_OP_GROUP_VectorListOneAllLanes:
1025
3.97k
    ARM_set_detail_op_reg(MI, OpNum,
1026
3.97k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1027
3.97k
    break;
1028
8.15k
  case ARM_OP_GROUP_VectorListTwo:
1029
9.96k
  case ARM_OP_GROUP_VectorListTwoAllLanes: {
1030
9.96k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1031
9.96k
    ARM_set_detail_op_reg(MI, OpNum,
1032
9.96k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1033
9.96k
                     ARM_dsub_0));
1034
9.96k
    ARM_set_detail_op_reg(MI, OpNum,
1035
9.96k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1036
9.96k
                     ARM_dsub_1));
1037
9.96k
    break;
1038
8.15k
  }
1039
1.45k
  case ARM_OP_GROUP_VectorListTwoSpacedAllLanes:
1040
5.28k
  case ARM_OP_GROUP_VectorListTwoSpaced: {
1041
5.28k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1042
5.28k
    ARM_set_detail_op_reg(MI, OpNum,
1043
5.28k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1044
5.28k
                     ARM_dsub_0));
1045
5.28k
    ARM_set_detail_op_reg(MI, OpNum,
1046
5.28k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1047
5.28k
                     ARM_dsub_2));
1048
5.28k
    break;
1049
1.45k
  }
1050
2.77k
  case ARM_OP_GROUP_VectorListThree:
1051
2.77k
  case ARM_OP_GROUP_VectorListThreeAllLanes:
1052
2.77k
    ARM_set_detail_op_reg(MI, OpNum,
1053
2.77k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1054
2.77k
    ARM_set_detail_op_reg(MI, OpNum,
1055
2.77k
              t_qpr_to_dpr_list(MI, OpNum, 1));
1056
2.77k
    ARM_set_detail_op_reg(MI, OpNum,
1057
2.77k
              t_qpr_to_dpr_list(MI, OpNum, 2));
1058
2.77k
    break;
1059
0
  case ARM_OP_GROUP_VectorListThreeSpacedAllLanes:
1060
0
  case ARM_OP_GROUP_VectorListThreeSpaced:
1061
0
    ARM_set_detail_op_reg(MI, OpNum,
1062
0
              t_qpr_to_dpr_list(MI, OpNum, 0));
1063
0
    ARM_set_detail_op_reg(MI, OpNum,
1064
0
              t_qpr_to_dpr_list(MI, OpNum, 2));
1065
0
    ARM_set_detail_op_reg(MI, OpNum,
1066
0
              t_qpr_to_dpr_list(MI, OpNum, 4));
1067
0
    break;
1068
6.67k
  case ARM_OP_GROUP_VectorListFour:
1069
6.67k
  case ARM_OP_GROUP_VectorListFourAllLanes:
1070
6.67k
    ARM_set_detail_op_reg(MI, OpNum,
1071
6.67k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1072
6.67k
    ARM_set_detail_op_reg(MI, OpNum,
1073
6.67k
              t_qpr_to_dpr_list(MI, OpNum, 1));
1074
6.67k
    ARM_set_detail_op_reg(MI, OpNum,
1075
6.67k
              t_qpr_to_dpr_list(MI, OpNum, 2));
1076
6.67k
    ARM_set_detail_op_reg(MI, OpNum,
1077
6.67k
              t_qpr_to_dpr_list(MI, OpNum, 3));
1078
6.67k
    break;
1079
0
  case ARM_OP_GROUP_VectorListFourSpacedAllLanes:
1080
0
  case ARM_OP_GROUP_VectorListFourSpaced:
1081
0
    ARM_set_detail_op_reg(MI, OpNum,
1082
0
              t_qpr_to_dpr_list(MI, OpNum, 0));
1083
0
    ARM_set_detail_op_reg(MI, OpNum,
1084
0
              t_qpr_to_dpr_list(MI, OpNum, 2));
1085
0
    ARM_set_detail_op_reg(MI, OpNum,
1086
0
              t_qpr_to_dpr_list(MI, OpNum, 4));
1087
0
    ARM_set_detail_op_reg(MI, OpNum,
1088
0
              t_qpr_to_dpr_list(MI, OpNum, 6));
1089
0
    break;
1090
41.3k
  case ARM_OP_GROUP_NoHashImmediate:
1091
41.3k
    ARM_set_detail_op_neon_lane(MI, OpNum);
1092
41.3k
    break;
1093
43.7k
  case ARM_OP_GROUP_RegisterList: {
1094
    // All operands n MI from OpNum on are registers.
1095
    // But the MappingInsnOps.inc has only a single entry for the whole
1096
    // list. So all registers in the list share those attributes.
1097
43.7k
    unsigned access = map_get_op_access(MI, OpNum);
1098
288k
    for (unsigned i = OpNum, e = MCInst_getNumOperands(MI); i != e;
1099
245k
         ++i) {
1100
245k
      unsigned Reg =
1101
245k
        MCOperand_getReg(MCInst_getOperand(MI, i));
1102
1103
245k
      ARM_get_detail_op(MI, 0)->type = ARM_OP_REG;
1104
245k
      ARM_get_detail_op(MI, 0)->reg = Reg;
1105
245k
      ARM_get_detail_op(MI, 0)->access = access;
1106
245k
      ARM_inc_op_count(MI);
1107
245k
    }
1108
43.7k
    break;
1109
0
  }
1110
11.2k
  case ARM_OP_GROUP_ThumbITMask: {
1111
11.2k
    unsigned Mask = MCInst_getOpVal(MI, OpNum);
1112
11.2k
    unsigned Firstcond = MCInst_getOpVal(MI, OpNum - 1);
1113
11.2k
    unsigned CondBit0 = Firstcond & 1;
1114
11.2k
    unsigned NumTZ = CountTrailingZeros_32(Mask);
1115
11.2k
    unsigned Pos, e;
1116
11.2k
    ARM_PredBlockMask PredMask = 0;
1117
1118
    // Check the documentation of ARM_PredBlockMask how the bits are set.
1119
40.8k
    for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
1120
29.5k
      bool Then = ((Mask >> Pos) & 1) == CondBit0;
1121
29.5k
      if (Then)
1122
5.58k
        PredMask <<= 1;
1123
23.9k
      else {
1124
23.9k
        PredMask |= 1;
1125
23.9k
        PredMask <<= 1;
1126
23.9k
      }
1127
29.5k
    }
1128
11.2k
    PredMask |= 1;
1129
11.2k
    ARM_get_detail(MI)->pred_mask = PredMask;
1130
11.2k
    break;
1131
0
  }
1132
9.69k
  case ARM_OP_GROUP_VPTMask: {
1133
9.69k
    unsigned Mask = MCInst_getOpVal(MI, OpNum);
1134
9.69k
    unsigned NumTZ = CountTrailingZeros_32(Mask);
1135
9.69k
    ARM_PredBlockMask PredMask = 0;
1136
1137
    // Check the documentation of ARM_PredBlockMask how the bits are set.
1138
34.3k
    for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1139
24.6k
      bool T = ((Mask >> Pos) & 1) == 0;
1140
24.6k
      if (T)
1141
12.2k
        PredMask <<= 1;
1142
12.3k
      else {
1143
12.3k
        PredMask |= 1;
1144
12.3k
        PredMask <<= 1;
1145
12.3k
      }
1146
24.6k
    }
1147
9.69k
    PredMask |= 1;
1148
9.69k
    ARM_get_detail(MI)->pred_mask = PredMask;
1149
9.69k
    break;
1150
0
  }
1151
10.0k
  case ARM_OP_GROUP_MSRMaskOperand: {
1152
10.0k
    MCOperand *Op = MCInst_getOperand(MI, OpNum);
1153
10.0k
    unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;
1154
10.0k
    unsigned Mask = (unsigned)MCOperand_getImm(Op) & 0xf;
1155
10.0k
    bool IsOutReg = OpNum == 0;
1156
1157
10.0k
    if (ARM_getFeatureBits(MI->csh->mode, ARM_FeatureMClass)) {
1158
8.34k
      const ARMSysReg_MClassSysReg *TheReg;
1159
8.34k
      unsigned SYSm = (unsigned)MCOperand_getImm(Op) &
1160
8.34k
          0xFFF; // 12-bit SYMm
1161
8.34k
      unsigned Opcode = MCInst_getOpcode(MI);
1162
1163
8.34k
      if (Opcode == ARM_t2MSR_M &&
1164
8.34k
          ARM_getFeatureBits(MI->csh->mode, ARM_FeatureDSP)) {
1165
5.76k
        TheReg =
1166
5.76k
          ARMSysReg_lookupMClassSysRegBy12bitSYSmValue(
1167
5.76k
            SYSm);
1168
5.76k
        if (TheReg && MClassSysReg_isInRequiredFeatures(
1169
1.67k
                  TheReg, ARM_FeatureDSP)) {
1170
404
          ARM_set_detail_op_sysop(
1171
404
            MI, TheReg->sysreg.mclasssysreg,
1172
404
            ARM_OP_SYSREG, IsOutReg, Mask,
1173
404
            SYSm);
1174
404
          return;
1175
404
        }
1176
5.76k
      }
1177
1178
7.94k
      SYSm &= 0xff;
1179
7.94k
      if (Opcode == ARM_t2MSR_M &&
1180
7.94k
          ARM_getFeatureBits(MI->csh->mode, ARM_HasV7Ops)) {
1181
5.36k
        TheReg =
1182
5.36k
          ARMSysReg_lookupMClassSysRegAPSRNonDeprecated(
1183
5.36k
            SYSm);
1184
5.36k
        if (TheReg) {
1185
733
          ARM_set_detail_op_sysop(
1186
733
            MI, TheReg->sysreg.mclasssysreg,
1187
733
            ARM_OP_SYSREG, IsOutReg, Mask,
1188
733
            SYSm);
1189
733
          return;
1190
733
        }
1191
5.36k
      }
1192
1193
7.21k
      TheReg = ARMSysReg_lookupMClassSysRegBy8bitSYSmValue(
1194
7.21k
        SYSm);
1195
7.21k
      if (TheReg) {
1196
6.35k
        ARM_set_detail_op_sysop(
1197
6.35k
          MI, TheReg->sysreg.mclasssysreg,
1198
6.35k
          ARM_OP_SYSREG, IsOutReg, Mask, SYSm);
1199
6.35k
        return;
1200
6.35k
      }
1201
1202
856
      if (detail_is_set(MI))
1203
856
        MCOperand_CreateImm0(MI, SYSm);
1204
1205
856
      ARM_set_detail_op_sysop(MI, SYSm, ARM_OP_SYSREG,
1206
856
            IsOutReg, Mask, SYSm);
1207
1208
856
      return;
1209
7.21k
    }
1210
1211
1.67k
    if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
1212
534
      switch (Mask) {
1213
0
      default:
1214
0
        assert(0 && "Unexpected mask value!");
1215
246
      case 4:
1216
246
        ARM_set_detail_op_sysop(MI,
1217
246
              ARM_MCLASSSYSREG_APSR_G,
1218
246
              ARM_OP_SYSREG, IsOutReg,
1219
246
              Mask, UINT16_MAX);
1220
246
        return;
1221
72
      case 8:
1222
72
        ARM_set_detail_op_sysop(
1223
72
          MI, ARM_MCLASSSYSREG_APSR_NZCVQ,
1224
72
          ARM_OP_SYSREG, IsOutReg, Mask,
1225
72
          UINT16_MAX);
1226
72
        return;
1227
216
      case 12:
1228
216
        ARM_set_detail_op_sysop(
1229
216
          MI, ARM_MCLASSSYSREG_APSR_NZCVQG,
1230
216
          ARM_OP_SYSREG, IsOutReg, Mask,
1231
216
          UINT16_MAX);
1232
216
        return;
1233
534
      }
1234
534
    }
1235
1236
1.13k
    unsigned field = 0;
1237
1.13k
    if (Mask) {
1238
1.06k
      if (Mask & 8)
1239
825
        field += SpecRegRBit ? ARM_FIELD_SPSR_F :
1240
825
                   ARM_FIELD_CPSR_F;
1241
1.06k
      if (Mask & 4)
1242
791
        field += SpecRegRBit ? ARM_FIELD_SPSR_S :
1243
791
                   ARM_FIELD_CPSR_S;
1244
1.06k
      if (Mask & 2)
1245
442
        field += SpecRegRBit ? ARM_FIELD_SPSR_X :
1246
442
                   ARM_FIELD_CPSR_X;
1247
1.06k
      if (Mask & 1)
1248
944
        field += SpecRegRBit ? ARM_FIELD_SPSR_C :
1249
944
                   ARM_FIELD_CPSR_C;
1250
1251
1.06k
      ARM_set_detail_op_sysop(MI, field,
1252
1.06k
            SpecRegRBit ? ARM_OP_SPSR :
1253
1.06k
                    ARM_OP_CPSR,
1254
1.06k
            IsOutReg, Mask, UINT16_MAX);
1255
1.06k
    }
1256
1.13k
    break;
1257
1.67k
  }
1258
4.75k
  case ARM_OP_GROUP_SORegRegOperand: {
1259
4.75k
    int64_t imm =
1260
4.75k
      MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2));
1261
4.75k
    ARM_get_detail_op(MI, 0)->shift.type =
1262
4.75k
      (imm & 7) + ARM_SFT_ASR_REG - 1;
1263
4.75k
    if (ARM_AM_getSORegShOp(imm) != ARM_AM_rrx)
1264
4.75k
      ARM_get_detail_op(MI, 0)->shift.value =
1265
4.75k
        MCInst_getOpVal(MI, OpNum + 1);
1266
1267
4.75k
    ARM_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1268
4.75k
    break;
1269
1.67k
  }
1270
8.67k
  case ARM_OP_GROUP_ModImmOperand: {
1271
8.67k
    int64_t imm = MCInst_getOpVal(MI, OpNum);
1272
8.67k
    int32_t Rotated = t_mod_imm_rotate(imm);
1273
8.67k
    if (ARM_AM_getSOImmVal(Rotated) == imm) {
1274
7.22k
      ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1275
7.22k
                t_mod_imm_rotate(imm));
1276
7.22k
      return;
1277
7.22k
    }
1278
1.45k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1279
1.45k
              t_mod_imm_bits(imm));
1280
1.45k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1281
1.45k
              t_mod_imm_rot(imm));
1282
1.45k
    break;
1283
8.67k
  }
1284
5.31k
  case ARM_OP_GROUP_VMOVModImmOperand:
1285
5.31k
    ARM_set_detail_op_imm(
1286
5.31k
      MI, OpNum, ARM_OP_IMM,
1287
5.31k
      t_vmov_mod_imm(MCInst_getOpVal(MI, OpNum)));
1288
5.31k
    break;
1289
608
  case ARM_OP_GROUP_FPImmOperand:
1290
608
    ARM_set_detail_op_float(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1291
608
    break;
1292
1.86k
  case ARM_OP_GROUP_ImmPlusOneOperand:
1293
1.86k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1294
1.86k
              MCInst_getOpVal(MI, OpNum) + 1);
1295
1.86k
    break;
1296
840
  case ARM_OP_GROUP_RotImmOperand: {
1297
840
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1298
840
    if (Imm == 0)
1299
454
      return;
1300
386
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ROR;
1301
386
    ARM_get_detail_op(MI, -1)->shift.value = Imm * 8;
1302
386
    break;
1303
840
  }
1304
1.82k
  case ARM_OP_GROUP_FBits16:
1305
1.82k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1306
1.82k
              16 - MCInst_getOpVal(MI, OpNum));
1307
1.82k
    break;
1308
207
  case ARM_OP_GROUP_FBits32:
1309
207
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1310
207
              32 - MCInst_getOpVal(MI, OpNum));
1311
207
    break;
1312
2.50k
  case ARM_OP_GROUP_T2SOOperand:
1313
13.6k
  case ARM_OP_GROUP_SORegImmOperand:
1314
13.6k
    ARM_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1315
13.6k
    uint64_t imm = MCInst_getOpVal(MI, OpNum + 1);
1316
13.6k
    ARM_AM_ShiftOpc ShOpc = ARM_AM_getSORegShOp(imm);
1317
13.6k
    unsigned ShImm = ARM_AM_getSORegOffset(imm);
1318
13.6k
    if (op_group == ARM_OP_GROUP_SORegImmOperand) {
1319
11.1k
      if (ShOpc == ARM_AM_no_shift ||
1320
11.1k
          (ShOpc == ARM_AM_lsl && !ShImm))
1321
0
        return;
1322
11.1k
    }
1323
13.6k
    add_cs_detail_RegImmShift(MI, ShOpc, ShImm);
1324
13.6k
    break;
1325
1.52k
  case ARM_OP_GROUP_PostIdxRegOperand: {
1326
1.52k
    bool sub = MCInst_getOpVal(MI, OpNum + 1) ? false : true;
1327
1.52k
    ARM_set_detail_op_mem_offset(MI, OpNum,
1328
1.52k
               MCInst_getOpVal(MI, OpNum), sub);
1329
1.52k
    ARM_get_detail(MI)->post_index = true;
1330
1.52k
    break;
1331
13.6k
  }
1332
1.18k
  case ARM_OP_GROUP_PostIdxImm8Operand: {
1333
1.18k
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1334
1.18k
    bool sub = !(Imm & 256);
1335
1.18k
    ARM_set_detail_op_mem_offset(MI, OpNum, (Imm & 0xff), sub);
1336
1.18k
    ARM_get_detail(MI)->post_index = true;
1337
1.18k
    break;
1338
13.6k
  }
1339
12.3k
  case ARM_OP_GROUP_PostIdxImm8s4Operand: {
1340
12.3k
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1341
12.3k
    bool sub = !(Imm & 256);
1342
12.3k
    ARM_set_detail_op_mem_offset(MI, OpNum, (Imm & 0xff) << 2, sub);
1343
12.3k
    ARM_get_detail(MI)->post_index = true;
1344
12.3k
    break;
1345
13.6k
  }
1346
106
  case ARM_OP_GROUP_AddrModeTBB:
1347
477
  case ARM_OP_GROUP_AddrModeTBH:
1348
477
    ARM_set_mem_access(MI, true);
1349
477
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1350
477
              MCInst_getOpVal(MI, OpNum));
1351
477
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1352
477
              MCInst_getOpVal(MI, OpNum + 1));
1353
477
    if (op_group == ARM_OP_GROUP_AddrModeTBH) {
1354
371
      ARM_get_detail_op(MI, 0)->shift.type = ARM_SFT_LSL;
1355
371
      ARM_get_detail_op(MI, 0)->shift.value = 1;
1356
371
      ARM_get_detail_op(MI, 0)->mem.lshift = 1;
1357
371
    }
1358
477
    ARM_set_mem_access(MI, false);
1359
477
    break;
1360
3.75k
  case ARM_OP_GROUP_AddrMode2Operand: {
1361
3.75k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1362
3.75k
    if (!MCOperand_isReg(MO1))
1363
      // Handled in printOperand
1364
0
      break;
1365
1366
3.75k
    ARM_set_mem_access(MI, true);
1367
3.75k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1368
3.75k
              MCInst_getOpVal(MI, OpNum));
1369
3.75k
    unsigned int imm3 = MCInst_getOpVal(MI, OpNum + 2);
1370
3.75k
    unsigned ShOff = ARM_AM_getAM2Offset(imm3);
1371
3.75k
    ARM_AM_AddrOpc subtracted = ARM_AM_getAM2Op(imm3);
1372
3.75k
    if (!MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)) &&
1373
3.75k
        ShOff) {
1374
0
      ARM_get_detail_op(MI, 0)->shift.type =
1375
0
        (arm_shifter)subtracted;
1376
0
      ARM_get_detail_op(MI, 0)->shift.value = ShOff;
1377
0
      ARM_get_detail_op(MI, 0)->subtracted = subtracted ==
1378
0
                     ARM_AM_sub;
1379
0
      ARM_set_mem_access(MI, false);
1380
0
      break;
1381
0
    }
1382
3.75k
    ARM_get_detail_op(MI, 0)->shift.type = subtracted == ARM_AM_sub;
1383
3.75k
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1384
3.75k
              MCInst_getOpVal(MI, OpNum + 1));
1385
3.75k
    add_cs_detail_RegImmShift(MI, ARM_AM_getAM2ShiftOpc(imm3),
1386
3.75k
            ARM_AM_getAM2Offset(imm3));
1387
3.75k
    ARM_set_mem_access(MI, false);
1388
3.75k
    break;
1389
3.75k
  }
1390
10.7k
  case ARM_OP_GROUP_AddrMode2OffsetOperand: {
1391
10.7k
    uint64_t imm2 = MCInst_getOpVal(MI, OpNum + 1);
1392
10.7k
    ARM_AM_AddrOpc subtracted = ARM_AM_getAM2Op(imm2);
1393
10.7k
    if (!MCInst_getOpVal(MI, OpNum)) {
1394
6.23k
      ARM_set_detail_op_mem_offset(MI, OpNum + 1,
1395
6.23k
                 ARM_AM_getAM2Offset(imm2),
1396
6.23k
                 subtracted == ARM_AM_sub);
1397
6.23k
      ARM_get_detail(MI)->post_index = true;
1398
6.23k
      return;
1399
6.23k
    }
1400
4.47k
    ARM_set_detail_op_mem_offset(MI, OpNum,
1401
4.47k
               MCInst_getOpVal(MI, OpNum),
1402
4.47k
               subtracted == ARM_AM_sub);
1403
4.47k
    ARM_get_detail(MI)->post_index = true;
1404
4.47k
    add_cs_detail_RegImmShift(MI, ARM_AM_getAM2ShiftOpc(imm2),
1405
4.47k
            ARM_AM_getAM2Offset(imm2));
1406
4.47k
    break;
1407
10.7k
  }
1408
6.46k
  case ARM_OP_GROUP_AddrMode3OffsetOperand: {
1409
6.46k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1410
6.46k
    MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1411
6.46k
    ARM_AM_AddrOpc subtracted =
1412
6.46k
      ARM_AM_getAM3Op(MCOperand_getImm(MO2));
1413
6.46k
    if (MCOperand_getReg(MO1)) {
1414
4.78k
      ARM_set_detail_op_mem_offset(MI, OpNum,
1415
4.78k
                 MCInst_getOpVal(MI, OpNum),
1416
4.78k
                 subtracted == ARM_AM_sub);
1417
4.78k
      ARM_get_detail(MI)->post_index = true;
1418
4.78k
      return;
1419
4.78k
    }
1420
1.67k
    ARM_set_detail_op_mem_offset(
1421
1.67k
      MI, OpNum + 1,
1422
1.67k
      ARM_AM_getAM3Offset(MCInst_getOpVal(MI, OpNum + 1)),
1423
1.67k
      subtracted == ARM_AM_sub);
1424
1.67k
    ARM_get_detail(MI)->post_index = true;
1425
1.67k
    break;
1426
6.46k
  }
1427
26.2k
  case ARM_OP_GROUP_ThumbAddrModeSPOperand:
1428
67.9k
  case ARM_OP_GROUP_ThumbAddrModeImm5S1Operand:
1429
121k
  case ARM_OP_GROUP_ThumbAddrModeImm5S2Operand:
1430
180k
  case ARM_OP_GROUP_ThumbAddrModeImm5S4Operand: {
1431
180k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1432
180k
    if (!MCOperand_isReg(MO1))
1433
      // Handled in printOperand
1434
0
      break;
1435
1436
180k
    ARM_set_mem_access(MI, true);
1437
180k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1438
180k
              MCInst_getOpVal(MI, OpNum));
1439
180k
    unsigned ImmOffs = MCInst_getOpVal(MI, OpNum + 1);
1440
180k
    if (ImmOffs) {
1441
169k
      unsigned Scale = 0;
1442
169k
      switch (op_group) {
1443
0
      default:
1444
0
        assert(0 &&
1445
0
               "Cannot determine scale. Operand group not handled.");
1446
39.5k
      case ARM_OP_GROUP_ThumbAddrModeImm5S1Operand:
1447
39.5k
        Scale = 1;
1448
39.5k
        break;
1449
48.6k
      case ARM_OP_GROUP_ThumbAddrModeImm5S2Operand:
1450
48.6k
        Scale = 2;
1451
48.6k
        break;
1452
57.9k
      case ARM_OP_GROUP_ThumbAddrModeImm5S4Operand:
1453
81.4k
      case ARM_OP_GROUP_ThumbAddrModeSPOperand:
1454
81.4k
        Scale = 4;
1455
81.4k
        break;
1456
169k
      }
1457
169k
      ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0,
1458
169k
                ImmOffs * Scale);
1459
169k
    }
1460
180k
    ARM_set_mem_access(MI, false);
1461
180k
    break;
1462
180k
  }
1463
23.5k
  case ARM_OP_GROUP_ThumbAddrModeRROperand: {
1464
23.5k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1465
23.5k
    if (!MCOperand_isReg(MO1))
1466
      // Handled in printOperand
1467
0
      break;
1468
1469
23.5k
    ARM_set_mem_access(MI, true);
1470
23.5k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1471
23.5k
              MCInst_getOpVal(MI, OpNum));
1472
23.5k
    arm_reg RegNum = MCInst_getOpVal(MI, OpNum + 1);
1473
23.5k
    if (RegNum)
1474
23.5k
      ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1475
23.5k
                RegNum);
1476
23.5k
    ARM_set_mem_access(MI, false);
1477
23.5k
    break;
1478
23.5k
  }
1479
5.14k
  case ARM_OP_GROUP_T2AddrModeImm8OffsetOperand:
1480
8.17k
  case ARM_OP_GROUP_T2AddrModeImm8s4OffsetOperand: {
1481
8.17k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum);
1482
8.17k
    if (OffImm == INT32_MIN)
1483
2.03k
      ARM_set_detail_op_mem_offset(MI, OpNum, 0, false);
1484
6.14k
    else {
1485
6.14k
      bool sub = OffImm < 0;
1486
6.14k
      OffImm = OffImm < 0 ? OffImm * -1 : OffImm;
1487
6.14k
      ARM_set_detail_op_mem_offset(MI, OpNum, OffImm, sub);
1488
6.14k
    }
1489
8.17k
    ARM_get_detail(MI)->post_index = true;
1490
8.17k
    break;
1491
5.14k
  }
1492
1.79k
  case ARM_OP_GROUP_T2AddrModeSoRegOperand: {
1493
1.79k
    if (!doing_mem(MI))
1494
1.79k
      ARM_set_mem_access(MI, true);
1495
1496
1.79k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1497
1.79k
              MCInst_getOpVal(MI, OpNum));
1498
1.79k
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1499
1.79k
              MCInst_getOpVal(MI, OpNum + 1));
1500
1.79k
    unsigned ShAmt = MCInst_getOpVal(MI, OpNum + 2);
1501
1.79k
    if (ShAmt) {
1502
1.35k
      ARM_get_detail_op(MI, 0)->shift.type = ARM_SFT_LSL;
1503
1.35k
      ARM_get_detail_op(MI, 0)->shift.value = ShAmt;
1504
1.35k
    }
1505
1.79k
    ARM_set_mem_access(MI, false);
1506
1.79k
    break;
1507
5.14k
  }
1508
671
  case ARM_OP_GROUP_T2AddrModeImm0_1020s4Operand:
1509
671
    ARM_set_mem_access(MI, true);
1510
671
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1511
671
              MCInst_getOpVal(MI, OpNum));
1512
671
    int64_t Imm = MCInst_getOpVal(MI, OpNum + 1);
1513
671
    if (Imm)
1514
566
      ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0,
1515
566
                Imm * 4);
1516
671
    ARM_set_mem_access(MI, false);
1517
671
    break;
1518
422
  case ARM_OP_GROUP_PKHLSLShiftImm: {
1519
422
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1520
422
    if (Imm == 0)
1521
158
      return;
1522
264
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_LSL;
1523
264
    ARM_get_detail_op(MI, -1)->shift.value = Imm;
1524
264
    break;
1525
422
  }
1526
343
  case ARM_OP_GROUP_PKHASRShiftImm: {
1527
343
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1528
343
    if (Imm == 0)
1529
72
      Imm = 32;
1530
343
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ASR;
1531
343
    ARM_get_detail_op(MI, -1)->shift.value = Imm;
1532
343
    break;
1533
422
  }
1534
23.9k
  case ARM_OP_GROUP_ThumbS4ImmOperand:
1535
23.9k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1536
23.9k
              MCInst_getOpVal(MI, OpNum) * 4);
1537
23.9k
    break;
1538
54.3k
  case ARM_OP_GROUP_ThumbSRImm: {
1539
54.3k
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1540
54.3k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1541
54.3k
              Imm == 0 ? 32 : Imm);
1542
54.3k
    break;
1543
422
  }
1544
1.29k
  case ARM_OP_GROUP_BitfieldInvMaskImmOperand: {
1545
1.29k
    uint32_t v = ~MCInst_getOpVal(MI, OpNum);
1546
1.29k
    int32_t lsb = CountTrailingZeros_32(v);
1547
1.29k
    int32_t width = (32 - countLeadingZeros(v)) - lsb;
1548
1.29k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, lsb);
1549
1.29k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, width);
1550
1.29k
    break;
1551
422
  }
1552
1.59k
  case ARM_OP_GROUP_CPSIMod: {
1553
1.59k
    unsigned Imm = MCInst_getOpVal(MI, OpNum);
1554
1.59k
    ARM_get_detail(MI)->cps_mode = Imm;
1555
1.59k
    break;
1556
422
  }
1557
1.59k
  case ARM_OP_GROUP_CPSIFlag: {
1558
1.59k
    unsigned IFlags = MCInst_getOpVal(MI, OpNum);
1559
1.59k
    ARM_get_detail(MI)->cps_flag = IFlags == 0 ? ARM_CPSFLAG_NONE :
1560
1.59k
                   IFlags;
1561
1.59k
    break;
1562
422
  }
1563
1.06k
  case ARM_OP_GROUP_GPRPairOperand: {
1564
1.06k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1565
1.06k
    ARM_set_detail_op_reg(MI, OpNum,
1566
1.06k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1567
1.06k
                     ARM_gsub_0));
1568
1.06k
    ARM_set_detail_op_reg(MI, OpNum,
1569
1.06k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1570
1.06k
                     ARM_gsub_1));
1571
1.06k
    break;
1572
422
  }
1573
1.88k
  case ARM_OP_GROUP_MemBOption:
1574
2.23k
  case ARM_OP_GROUP_InstSyncBOption:
1575
2.23k
  case ARM_OP_GROUP_TraceSyncBOption:
1576
2.23k
    ARM_get_detail(MI)->mem_barrier = MCInst_getOpVal(MI, OpNum);
1577
2.23k
    break;
1578
1.88k
  case ARM_OP_GROUP_ShiftImmOperand: {
1579
1.88k
    unsigned ShiftOp = MCInst_getOpVal(MI, OpNum);
1580
1.88k
    bool isASR = (ShiftOp & (1 << 5)) != 0;
1581
1.88k
    unsigned Amt = ShiftOp & 0x1f;
1582
1.88k
    if (isASR) {
1583
450
      unsigned tmp = Amt == 0 ? 32 : Amt;
1584
450
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ASR;
1585
450
      ARM_get_detail_op(MI, -1)->shift.value = tmp;
1586
1.43k
    } else if (Amt) {
1587
913
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_LSL;
1588
913
      ARM_get_detail_op(MI, -1)->shift.value = Amt;
1589
913
    }
1590
1.88k
    break;
1591
2.23k
  }
1592
9.82k
  case ARM_OP_GROUP_VectorIndex:
1593
9.82k
    ARM_get_detail_op(MI, -1)->vector_index =
1594
9.82k
      MCInst_getOpVal(MI, OpNum);
1595
9.82k
    break;
1596
6.20k
  case ARM_OP_GROUP_CoprocOptionImm:
1597
6.20k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1598
6.20k
              MCInst_getOpVal(MI, OpNum));
1599
6.20k
    break;
1600
28.1k
  case ARM_OP_GROUP_ThumbLdrLabelOperand: {
1601
28.1k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum);
1602
28.1k
    if (OffImm == INT32_MIN)
1603
252
      OffImm = 0;
1604
28.1k
    ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
1605
28.1k
    ARM_get_detail_op(MI, 0)->mem.base = ARM_REG_PC;
1606
28.1k
    ARM_get_detail_op(MI, 0)->mem.index = ARM_REG_INVALID;
1607
28.1k
    ARM_get_detail_op(MI, 0)->mem.scale = 1;
1608
28.1k
    ARM_get_detail_op(MI, 0)->mem.disp = OffImm;
1609
28.1k
    ARM_get_detail_op(MI, 0)->access = CS_AC_READ;
1610
28.1k
    ARM_inc_op_count(MI);
1611
28.1k
    break;
1612
2.23k
  }
1613
490
  case ARM_OP_GROUP_BankedRegOperand: {
1614
490
    uint32_t Banked = MCInst_getOpVal(MI, OpNum);
1615
490
    const ARMBankedReg_BankedReg *TheReg =
1616
490
      ARMBankedReg_lookupBankedRegByEncoding(Banked);
1617
490
    bool IsOutReg = OpNum == 0;
1618
490
    ARM_set_detail_op_sysop(MI, TheReg->sysreg.bankedreg,
1619
490
          ARM_OP_BANKEDREG, IsOutReg, UINT8_MAX,
1620
490
          TheReg->Encoding &
1621
490
            0xf); // Bit[4:0] are SYSm
1622
490
    break;
1623
2.23k
  }
1624
312
  case ARM_OP_GROUP_SetendOperand: {
1625
312
    bool be = MCInst_getOpVal(MI, OpNum) != 0;
1626
312
    if (be) {
1627
117
      ARM_get_detail_op(MI, 0)->type = ARM_OP_SETEND;
1628
117
      ARM_get_detail_op(MI, 0)->setend = ARM_SETEND_BE;
1629
195
    } else {
1630
195
      ARM_get_detail_op(MI, 0)->type = ARM_OP_SETEND;
1631
195
      ARM_get_detail_op(MI, 0)->setend = ARM_SETEND_LE;
1632
195
    }
1633
312
    ARM_inc_op_count(MI);
1634
312
    break;
1635
2.23k
  }
1636
0
  case ARM_OP_GROUP_MveSaturateOp: {
1637
0
    uint32_t Val = MCInst_getOpVal(MI, OpNum);
1638
0
    Val = Val == 1 ? 48 : 64;
1639
0
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, Val);
1640
0
    break;
1641
2.23k
  }
1642
4.31M
  }
1643
4.31M
}
1644
1645
/// Fills cs_detail with the data of the operand.
1646
/// This function handles operands which original printer function is a template
1647
/// with one argument.
1648
static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
1649
             unsigned OpNum, uint64_t temp_arg_0)
1650
86.4k
{
1651
86.4k
  if (!detail_is_set(MI))
1652
0
    return;
1653
86.4k
  switch (op_group) {
1654
0
  default:
1655
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1656
0
    assert(0);
1657
6.70k
  case ARM_OP_GROUP_AddrModeImm12Operand_0:
1658
10.8k
  case ARM_OP_GROUP_AddrModeImm12Operand_1:
1659
13.4k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_0:
1660
21.6k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_1: {
1661
21.6k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1662
21.6k
    if (!MCOperand_isReg(MO1))
1663
      // Handled in printOperand
1664
0
      return;
1665
21.6k
  }
1666
  // fallthrough
1667
32.7k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_0:
1668
36.8k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_1: {
1669
36.8k
    bool AlwaysPrintImm0 = temp_arg_0;
1670
36.8k
    ARM_set_mem_access(MI, true);
1671
36.8k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1672
36.8k
              MCInst_getOpVal(MI, OpNum));
1673
36.8k
    int32_t Imm = MCInst_getOpVal(MI, OpNum + 1);
1674
36.8k
    if (Imm == INT32_MIN)
1675
3.92k
      Imm = 0;
1676
36.8k
    ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0, Imm);
1677
36.8k
    if (AlwaysPrintImm0)
1678
16.5k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
1679
1680
36.8k
    ARM_set_mem_access(MI, false);
1681
36.8k
    break;
1682
32.7k
  }
1683
1.38k
  case ARM_OP_GROUP_AdrLabelOperand_0:
1684
19.4k
  case ARM_OP_GROUP_AdrLabelOperand_2: {
1685
19.4k
    unsigned Scale = temp_arg_0;
1686
19.4k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum) << Scale;
1687
19.4k
    if (OffImm == INT32_MIN)
1688
0
      OffImm = 0;
1689
19.4k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, OffImm);
1690
19.4k
    break;
1691
1.38k
  }
1692
2.96k
  case ARM_OP_GROUP_AddrMode3Operand_0:
1693
6.22k
  case ARM_OP_GROUP_AddrMode3Operand_1: {
1694
6.22k
    bool AlwaysPrintImm0 = temp_arg_0;
1695
6.22k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1696
6.22k
    if (!MCOperand_isReg(MO1))
1697
      // Handled in printOperand
1698
0
      break;
1699
1700
6.22k
    ARM_set_mem_access(MI, true);
1701
6.22k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1702
6.22k
              MCInst_getOpVal(MI, OpNum));
1703
1704
6.22k
    MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1705
6.22k
    ARM_AM_AddrOpc Sign =
1706
6.22k
      ARM_AM_getAM3Op(MCInst_getOpVal(MI, OpNum + 2));
1707
1708
6.22k
    if (MCOperand_getReg(MO2)) {
1709
2.72k
      ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1710
2.72k
                MCInst_getOpVal(MI, OpNum + 1));
1711
2.72k
      ARM_get_detail_op(MI, 0)->subtracted = Sign ==
1712
2.72k
                     ARM_AM_sub;
1713
2.72k
      ARM_set_mem_access(MI, false);
1714
2.72k
      break;
1715
2.72k
    }
1716
3.50k
    unsigned ImmOffs =
1717
3.50k
      ARM_AM_getAM3Offset(MCInst_getOpVal(MI, OpNum + 2));
1718
1719
3.50k
    if (AlwaysPrintImm0 || ImmOffs || Sign == ARM_AM_sub) {
1720
3.43k
      ARM_set_detail_op_mem(MI, OpNum + 2, false, 0, 0,
1721
3.43k
                ImmOffs);
1722
3.43k
      ARM_get_detail_op(MI, 0)->subtracted = Sign ==
1723
3.43k
                     ARM_AM_sub;
1724
3.43k
    }
1725
3.50k
    ARM_set_mem_access(MI, false);
1726
3.50k
    break;
1727
6.22k
  }
1728
10.4k
  case ARM_OP_GROUP_AddrMode5Operand_0:
1729
21.3k
  case ARM_OP_GROUP_AddrMode5Operand_1:
1730
21.9k
  case ARM_OP_GROUP_AddrMode5FP16Operand_0: {
1731
21.9k
    bool AlwaysPrintImm0 = temp_arg_0;
1732
1733
21.9k
    if (AlwaysPrintImm0)
1734
10.8k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
1735
1736
21.9k
    cs_arm_op *Op = ARM_get_detail_op(MI, 0);
1737
21.9k
    Op->type = ARM_OP_MEM;
1738
21.9k
    Op->mem.base = MCInst_getOpVal(MI, OpNum);
1739
21.9k
    Op->mem.index = ARM_REG_INVALID;
1740
21.9k
    Op->mem.scale = 1;
1741
21.9k
    Op->mem.disp = 0;
1742
21.9k
    Op->access = CS_AC_READ;
1743
1744
21.9k
    ARM_AM_AddrOpc SubFlag =
1745
21.9k
      ARM_AM_getAM5Op(MCInst_getOpVal(MI, OpNum + 1));
1746
21.9k
    unsigned ImmOffs =
1747
21.9k
      ARM_AM_getAM5Offset(MCInst_getOpVal(MI, OpNum + 1));
1748
1749
21.9k
    if (AlwaysPrintImm0 || ImmOffs || SubFlag == ARM_AM_sub) {
1750
21.2k
      if (op_group == ARM_OP_GROUP_AddrMode5FP16Operand_0) {
1751
533
        Op->mem.disp = ImmOffs * 2;
1752
20.7k
      } else {
1753
20.7k
        Op->mem.disp = ImmOffs * 4;
1754
20.7k
      }
1755
21.2k
      Op->subtracted = SubFlag == ARM_AM_sub;
1756
21.2k
    }
1757
21.9k
    ARM_inc_op_count(MI);
1758
21.9k
    break;
1759
21.3k
  }
1760
114
  case ARM_OP_GROUP_MveAddrModeRQOperand_0:
1761
187
  case ARM_OP_GROUP_MveAddrModeRQOperand_1:
1762
419
  case ARM_OP_GROUP_MveAddrModeRQOperand_2:
1763
613
  case ARM_OP_GROUP_MveAddrModeRQOperand_3: {
1764
613
    unsigned Shift = temp_arg_0;
1765
613
    ARM_set_mem_access(MI, true);
1766
613
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
1767
613
              MCInst_getOpVal(MI, OpNum));
1768
613
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
1769
613
              MCInst_getOpVal(MI, OpNum + 1));
1770
613
    if (Shift > 0) {
1771
499
      add_cs_detail_RegImmShift(MI, ARM_AM_uxtw, Shift);
1772
499
    }
1773
613
    ARM_set_mem_access(MI, false);
1774
613
    break;
1775
419
  }
1776
715
  case ARM_OP_GROUP_MVEVectorList_2:
1777
1.32k
  case ARM_OP_GROUP_MVEVectorList_4: {
1778
1.32k
    unsigned NumRegs = temp_arg_0;
1779
1.32k
    arm_reg Reg = MCInst_getOpVal(MI, OpNum);
1780
5.17k
    for (unsigned i = 0; i < NumRegs; ++i) {
1781
3.85k
      arm_reg SubReg = MCRegisterInfo_getSubReg(
1782
3.85k
        MI->MRI, Reg, ARM_qsub_0 + i);
1783
3.85k
      ARM_set_detail_op_reg(MI, OpNum, SubReg);
1784
3.85k
    }
1785
1.32k
    break;
1786
715
  }
1787
86.4k
  }
1788
86.4k
}
1789
1790
/// Fills cs_detail with the data of the operand.
1791
/// This function handles operands which's original printer function is a
1792
/// template with two arguments.
1793
static void add_cs_detail_template_2(MCInst *MI, arm_op_group op_group,
1794
             unsigned OpNum, uint64_t temp_arg_0,
1795
             uint64_t temp_arg_1)
1796
3.91k
{
1797
3.91k
  if (!detail_is_set(MI))
1798
0
    return;
1799
3.91k
  switch (op_group) {
1800
0
  default:
1801
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1802
0
    assert(0);
1803
1.93k
  case ARM_OP_GROUP_ComplexRotationOp_90_0:
1804
3.91k
  case ARM_OP_GROUP_ComplexRotationOp_180_90: {
1805
3.91k
    unsigned Angle = temp_arg_0;
1806
3.91k
    unsigned Remainder = temp_arg_1;
1807
3.91k
    unsigned Imm = (MCInst_getOpVal(MI, OpNum) * Angle) + Remainder;
1808
3.91k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, Imm);
1809
3.91k
    break;
1810
1.93k
  }
1811
3.91k
  }
1812
3.91k
}
1813
1814
/// Fills cs_detail with the data of the operand.
1815
/// Calls to this function are should not be added by hand! Please checkout the
1816
/// patch `AddCSDetail` of the CppTranslator.
1817
void ARM_add_cs_detail(MCInst *MI, int /* arm_op_group */ op_group,
1818
           va_list args)
1819
4.43M
{
1820
4.43M
  if (!detail_is_set(MI))
1821
0
    return;
1822
4.43M
  switch (op_group) {
1823
22.3k
  case ARM_OP_GROUP_RegImmShift: {
1824
22.3k
    ARM_AM_ShiftOpc shift_opc = va_arg(args, ARM_AM_ShiftOpc);
1825
22.3k
    unsigned shift_imm = va_arg(args, unsigned);
1826
22.3k
    add_cs_detail_RegImmShift(MI, shift_opc, shift_imm);
1827
22.3k
    return;
1828
0
  }
1829
1.38k
  case ARM_OP_GROUP_AdrLabelOperand_0:
1830
19.4k
  case ARM_OP_GROUP_AdrLabelOperand_2:
1831
22.4k
  case ARM_OP_GROUP_AddrMode3Operand_0:
1832
25.7k
  case ARM_OP_GROUP_AddrMode3Operand_1:
1833
36.1k
  case ARM_OP_GROUP_AddrMode5Operand_0:
1834
47.0k
  case ARM_OP_GROUP_AddrMode5Operand_1:
1835
53.7k
  case ARM_OP_GROUP_AddrModeImm12Operand_0:
1836
57.9k
  case ARM_OP_GROUP_AddrModeImm12Operand_1:
1837
68.9k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_0:
1838
73.0k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_1:
1839
75.5k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_0:
1840
83.8k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_1:
1841
84.5k
  case ARM_OP_GROUP_MVEVectorList_2:
1842
85.1k
  case ARM_OP_GROUP_MVEVectorList_4:
1843
85.8k
  case ARM_OP_GROUP_AddrMode5FP16Operand_0:
1844
85.9k
  case ARM_OP_GROUP_MveAddrModeRQOperand_0:
1845
86.1k
  case ARM_OP_GROUP_MveAddrModeRQOperand_3:
1846
86.1k
  case ARM_OP_GROUP_MveAddrModeRQOperand_1:
1847
86.4k
  case ARM_OP_GROUP_MveAddrModeRQOperand_2: {
1848
86.4k
    unsigned op_num = va_arg(args, unsigned);
1849
86.4k
    uint64_t templ_arg_0 = va_arg(args, uint64_t);
1850
86.4k
    add_cs_detail_template_1(MI, op_group, op_num, templ_arg_0);
1851
86.4k
    return;
1852
86.1k
  }
1853
1.98k
  case ARM_OP_GROUP_ComplexRotationOp_180_90:
1854
3.91k
  case ARM_OP_GROUP_ComplexRotationOp_90_0: {
1855
3.91k
    unsigned op_num = va_arg(args, unsigned);
1856
3.91k
    uint64_t templ_arg_0 = va_arg(args, uint64_t);
1857
3.91k
    uint64_t templ_arg_1 = va_arg(args, uint64_t);
1858
3.91k
    add_cs_detail_template_2(MI, op_group, op_num, templ_arg_0,
1859
3.91k
           templ_arg_1);
1860
3.91k
    return;
1861
1.98k
  }
1862
4.43M
  }
1863
4.31M
  unsigned op_num = va_arg(args, unsigned);
1864
4.31M
  add_cs_detail_general(MI, op_group, op_num);
1865
4.31M
}
1866
1867
/// Inserts a register to the detail operands at @index.
1868
/// Already present operands are moved.
1869
void ARM_insert_detail_op_reg_at(MCInst *MI, unsigned index, arm_reg Reg,
1870
         cs_ac_type access)
1871
7.15k
{
1872
7.15k
  if (!detail_is_set(MI))
1873
0
    return;
1874
1875
7.15k
  assert(ARM_get_detail(MI)->op_count < MAX_ARM_OPS);
1876
1877
7.15k
  cs_arm_op op;
1878
7.15k
  ARM_setup_op(&op);
1879
7.15k
  op.type = ARM_OP_REG;
1880
7.15k
  op.reg = Reg;
1881
7.15k
  op.access = access;
1882
1883
7.15k
  cs_arm_op *ops = ARM_get_detail(MI)->operands;
1884
7.15k
  int i = ARM_get_detail(MI)->op_count;
1885
7.15k
  assert(i < MAX_ARM_OPS);
1886
12.2k
  for (; i > 0 && i > index; --i) {
1887
5.04k
    ops[i] = ops[i - 1];
1888
5.04k
  }
1889
7.15k
  ops[index] = op;
1890
7.15k
  ARM_inc_op_count(MI);
1891
7.15k
}
1892
1893
/// Inserts a immediate to the detail operands at @index.
1894
/// Already present operands are moved.
1895
void ARM_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
1896
         cs_ac_type access)
1897
10.5k
{
1898
10.5k
  if (!detail_is_set(MI))
1899
0
    return;
1900
1901
10.5k
  assert(ARM_get_detail(MI)->op_count < MAX_ARM_OPS);
1902
1903
10.5k
  cs_arm_op op;
1904
10.5k
  ARM_setup_op(&op);
1905
10.5k
  op.type = ARM_OP_IMM;
1906
10.5k
  op.imm = Val;
1907
10.5k
  op.access = access;
1908
1909
10.5k
  cs_arm_op *ops = ARM_get_detail(MI)->operands;
1910
10.5k
  int i = ARM_get_detail(MI)->op_count;
1911
10.5k
  assert(i < MAX_ARM_OPS);
1912
11.7k
  for (; i > 0 && i > index; --i) {
1913
1.20k
    ops[i] = ops[i - 1];
1914
1.20k
  }
1915
10.5k
  ops[index] = op;
1916
10.5k
  ARM_inc_op_count(MI);
1917
10.5k
}
1918
1919
/// Adds a register ARM operand at position OpNum and increases the op_count by
1920
/// one.
1921
void ARM_set_detail_op_reg(MCInst *MI, unsigned OpNum, arm_reg Reg)
1922
1.74M
{
1923
1.74M
  if (!detail_is_set(MI))
1924
0
    return;
1925
1.74M
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
1926
1.74M
  assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
1927
1928
1.74M
  ARM_get_detail_op(MI, 0)->type = ARM_OP_REG;
1929
1.74M
  ARM_get_detail_op(MI, 0)->reg = Reg;
1930
1.74M
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
1931
1.74M
  ARM_inc_op_count(MI);
1932
1.74M
}
1933
1934
/// Adds an immediate ARM operand at position OpNum and increases the op_count
1935
/// by one.
1936
void ARM_set_detail_op_imm(MCInst *MI, unsigned OpNum, arm_op_type ImmType,
1937
         int64_t Imm)
1938
766k
{
1939
766k
  if (!detail_is_set(MI))
1940
0
    return;
1941
766k
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
1942
766k
  assert(map_get_op_type(MI, OpNum) == CS_OP_IMM);
1943
766k
  assert(ImmType == ARM_OP_IMM || ImmType == ARM_OP_PIMM ||
1944
766k
         ImmType == ARM_OP_CIMM);
1945
1946
766k
  ARM_get_detail_op(MI, 0)->type = ImmType;
1947
766k
  ARM_get_detail_op(MI, 0)->imm = Imm;
1948
766k
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
1949
766k
  ARM_inc_op_count(MI);
1950
766k
}
1951
1952
/// Adds the operand as to the previously added memory operand.
1953
void ARM_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val,
1954
          bool subtracted)
1955
52.9k
{
1956
52.9k
  assert(map_get_op_type(MI, OpNum) & CS_OP_MEM);
1957
1958
52.9k
  if (!doing_mem(MI)) {
1959
52.9k
    assert((ARM_get_detail_op(MI, -1) != NULL) &&
1960
52.9k
           (ARM_get_detail_op(MI, -1)->type == ARM_OP_MEM));
1961
52.9k
    ARM_dec_op_count(MI);
1962
52.9k
  }
1963
1964
52.9k
  if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM)
1965
29.5k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, 0, Val);
1966
23.3k
  else if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG)
1967
23.3k
    ARM_set_detail_op_mem(MI, OpNum, true, 0, 0, Val);
1968
0
  else
1969
0
    assert(0 && "Memory type incorrect.");
1970
52.9k
  ARM_get_detail_op(MI, 0)->subtracted = subtracted;
1971
1972
52.9k
  if (!doing_mem(MI))
1973
52.9k
    ARM_inc_op_count(MI);
1974
52.9k
}
1975
1976
/// Adds a memory ARM operand at position OpNum. op_count is *not* increased by
1977
/// one. This is done by ARM_set_mem_access().
1978
void ARM_set_detail_op_mem(MCInst *MI, unsigned OpNum, bool is_index_reg,
1979
         int scale, int lshift, uint64_t Val)
1980
660k
{
1981
660k
  if (!detail_is_set(MI))
1982
0
    return;
1983
660k
  assert(map_get_op_type(MI, OpNum) & CS_OP_MEM);
1984
660k
  cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
1985
660k
  switch (secondary_type) {
1986
0
  default:
1987
0
    assert(0 && "Secondary type not supported yet.");
1988
420k
  case CS_OP_REG: {
1989
420k
    assert(secondary_type == CS_OP_REG);
1990
420k
    if (!is_index_reg) {
1991
363k
      ARM_get_detail_op(MI, 0)->mem.base = Val;
1992
363k
      if (MCInst_opIsTying(MI, OpNum) || MCInst_opIsTied(MI, OpNum)) {
1993
        // Base registers can be writeback registers.
1994
        // For this they tie an MC operand which has write
1995
        // access. But this one is never processed in the printer
1996
        // (because it is never emitted). Therefor it is never
1997
        // added to the modified list.
1998
        // Here we check for this case and add the memory register
1999
        // to the modified list.
2000
93.1k
        map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
2001
93.1k
        MI->flat_insn->detail->writeback = true;
2002
270k
      } else {
2003
        // If the base register is not tied, set the writebak flag to false.
2004
        // Writeback for ARM only refers to the memory base register.
2005
        // But other registers might be marked as tied as well.
2006
270k
        MI->flat_insn->detail->writeback = false;
2007
270k
      }
2008
363k
    } else {
2009
56.3k
      ARM_get_detail_op(MI, 0)->mem.index = Val;
2010
56.3k
    }
2011
420k
    ARM_get_detail_op(MI, 0)->mem.scale = scale;
2012
420k
    ARM_get_detail_op(MI, 0)->mem.lshift = lshift;
2013
2014
420k
    break;
2015
420k
  }
2016
240k
  case CS_OP_IMM: {
2017
240k
    assert(secondary_type == CS_OP_IMM);
2018
240k
    if (((int32_t)Val) < 0)
2019
13.4k
      ARM_get_detail_op(MI, 0)->subtracted = true;
2020
240k
    ARM_get_detail_op(MI, 0)->mem.disp = ((int64_t)Val < 0) ? -Val :
2021
240k
                    Val;
2022
240k
    break;
2023
240k
  }
2024
660k
  }
2025
2026
660k
  ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
2027
660k
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2028
660k
}
2029
2030
/// Sets the neon_lane in the previous operand to the value of
2031
/// MI->operands[OpNum] Decrements op_count by 1.
2032
void ARM_set_detail_op_neon_lane(MCInst *MI, unsigned OpNum)
2033
41.3k
{
2034
41.3k
  if (!detail_is_set(MI))
2035
0
    return;
2036
41.3k
  assert(map_get_op_type(MI, OpNum) == CS_OP_IMM);
2037
41.3k
  unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2038
2039
41.3k
  ARM_get_detail_op(MI, -1)->neon_lane = Val;
2040
41.3k
}
2041
2042
/// Adds a System Register and increments op_count by one.
2043
/// @type ARM_OP_SYSREG, ARM_OP_BANKEDREG, ARM_OP_SYSM...
2044
/// @p Mask is the MSR mask or UINT8_MAX if not set.
2045
void ARM_set_detail_op_sysop(MCInst *MI, int Val, arm_op_type type,
2046
           bool IsOutReg, uint8_t Mask, uint16_t Sysm)
2047
10.4k
{
2048
10.4k
  if (!detail_is_set(MI))
2049
0
    return;
2050
10.4k
  ARM_get_detail_op(MI, 0)->type = type;
2051
10.4k
  switch (type) {
2052
0
  default:
2053
0
    assert(0 && "Unkown system operand type.");
2054
8.88k
  case ARM_OP_SYSREG:
2055
8.88k
    ARM_get_detail_op(MI, 0)->sysop.reg.mclasssysreg = Val;
2056
8.88k
    break;
2057
490
  case ARM_OP_BANKEDREG:
2058
490
    ARM_get_detail_op(MI, 0)->sysop.reg.bankedreg = Val;
2059
490
    break;
2060
282
  case ARM_OP_SPSR:
2061
1.06k
  case ARM_OP_CPSR:
2062
1.06k
    ARM_get_detail_op(MI, 0)->reg =
2063
1.06k
      type == ARM_OP_SPSR ? ARM_REG_SPSR : ARM_REG_CPSR;
2064
1.06k
    ARM_get_detail_op(MI, 0)->sysop.psr_bits = Val;
2065
1.06k
    break;
2066
10.4k
  }
2067
10.4k
  ARM_get_detail_op(MI, 0)->sysop.sysm = Sysm;
2068
10.4k
  ARM_get_detail_op(MI, 0)->sysop.msr_mask = Mask;
2069
10.4k
  ARM_get_detail_op(MI, 0)->access = IsOutReg ? CS_AC_WRITE : CS_AC_READ;
2070
10.4k
  ARM_inc_op_count(MI);
2071
10.4k
}
2072
2073
/// Transforms the immediate of the operand to a float and stores it.
2074
/// Increments the op_counter by one.
2075
void ARM_set_detail_op_float(MCInst *MI, unsigned OpNum, uint64_t Imm)
2076
608
{
2077
608
  if (!detail_is_set(MI))
2078
0
    return;
2079
608
  ARM_get_detail_op(MI, 0)->type = ARM_OP_FP;
2080
608
  ARM_get_detail_op(MI, 0)->fp = ARM_AM_getFPImmFloat(Imm);
2081
608
  ARM_inc_op_count(MI);
2082
608
}
2083
2084
#endif