Coverage Report

Created: 2023-12-08 06:05

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