Coverage Report

Created: 2026-06-15 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/ARM/ARMInstPrinter.c
Line
Count
Source
1
//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This class prints an ARM MCInst to a .s file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
/* Capstone Disassembly Engine */
15
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
16
17
#ifdef CAPSTONE_HAS_ARM
18
19
#include <stdio.h>  // DEBUG
20
#include <stdlib.h>
21
#include <string.h>
22
#include <capstone/platform.h>
23
24
#include "ARMInstPrinter.h"
25
#include "ARMAddressingModes.h"
26
#include "ARMBaseInfo.h"
27
#include "ARMDisassembler.h"
28
#include "../../MCInst.h"
29
#include "../../SStream.h"
30
#include "../../MCRegisterInfo.h"
31
#include "../../utils.h"
32
#include "ARMMapping.h"
33
34
#define GET_SUBTARGETINFO_ENUM
35
#include "ARMGenSubtargetInfo.inc"
36
37
#include "ARMGenSystemRegister.inc"
38
39
static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo);
40
41
// Autogenerated by tblgen.
42
static void printInstruction(MCInst *MI, SStream *O);
43
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
44
static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
45
static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
46
47
static void printAddrModeTBB(MCInst *MI, unsigned OpNum, SStream *O);
48
static void printAddrModeTBH(MCInst *MI, unsigned OpNum, SStream *O);
49
static void printAddrMode2Operand(MCInst *MI, unsigned OpNum, SStream *O);
50
static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);
51
static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
52
static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
53
static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
54
static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);
55
static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);
56
static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
57
static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
58
static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
59
static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O);
60
static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O);
61
static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
62
63
static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
64
static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O);
65
static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
66
static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
67
static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
68
static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned);
69
static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
70
static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O);
71
static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O);
72
static void printThumbAddrModeRROperand(MCInst *MI, unsigned OpNum, SStream *O);
73
static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale);
74
static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned OpNum, SStream *O);
75
static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned OpNum, SStream *O);
76
static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned OpNum, SStream *O);
77
static void printThumbAddrModeSPOperand(MCInst *MI, unsigned OpNum, SStream *O);
78
static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O);
79
static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
80
static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
81
static void printT2AddrModeImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
82
static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
83
static void printT2AddrModeImm8OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
84
static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
85
static void printT2AddrModeSoRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
86
static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O);
87
static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O);
88
static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O);
89
static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O);
90
static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
91
static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
92
static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O);
93
static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O);
94
static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O);
95
static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O);
96
static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O);
97
static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O);
98
static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
99
static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
100
static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O);
101
static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
102
static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O);
103
static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O);
104
static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O);
105
static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O);
106
static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O);
107
static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O);
108
static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O);
109
static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O);
110
static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O);
111
static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O);
112
static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
113
static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
114
static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
115
static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
116
static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
117
static void printVectorListThreeSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
118
static void printVectorListFourSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
119
static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O);
120
static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O);
121
static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
122
static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
123
124
static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);
125
static void printTraceSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);
126
static void printComplexRotationOp(MCInst *MI, unsigned OpNo, SStream *O, int64_t Angle, int64_t Remainder);
127
static void printAddrMode5FP16Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
128
129
130
#ifndef CAPSTONE_DIET
131
// copy & normalize access info
132
static uint8_t get_op_access(cs_struct *h, unsigned int id, unsigned int index)
133
1.64M
{
134
1.64M
  const uint8_t *arr = ARM_get_op_access(h, id);
135
136
1.64M
  if (!arr || arr[index] == CS_AC_IGNORE)
137
7.22k
    return 0;
138
139
1.63M
  return arr[index];
140
1.64M
}
141
#endif
142
143
static void set_mem_access(MCInst *MI, bool status)
144
698k
{
145
698k
  if (MI->csh->detail != CS_OPT_ON)
146
0
    return;
147
148
698k
  MI->csh->doing_mem = status;
149
698k
  if (status) {
150
349k
#ifndef CAPSTONE_DIET
151
349k
    uint8_t access;
152
349k
#endif
153
154
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
155
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_INVALID;
156
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
157
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
158
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
159
160
349k
#ifndef CAPSTONE_DIET
161
349k
    access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
162
349k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
163
349k
    MI->ac_idx++;
164
349k
#endif
165
349k
  } else {
166
    // done, create the next operand slot
167
349k
    MI->flat_insn->detail->arm.op_count++;
168
349k
  }
169
698k
}
170
171
static void op_addImm(MCInst *MI, int v)
172
1.70k
{
173
1.70k
  if (MI->csh->detail) {
174
1.70k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
175
1.70k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;
176
1.70k
    MI->flat_insn->detail->arm.op_count++;
177
1.70k
  }
178
1.70k
}
179
180
#define GET_INSTRINFO_ENUM
181
#include "ARMGenInstrInfo.inc"
182
183
static void printCustomAliasOperand(MCInst *MI,
184
    unsigned OpIdx, unsigned PrintMethodIdx, SStream *OS);
185
186
#define PRINT_ALIAS_INSTR
187
#include "ARMGenAsmWriter.inc"
188
#include "ARMGenRegisterName.inc"
189
#include "ARMGenRegisterName_digit.inc"
190
191
void ARM_getRegName(cs_struct *handle, int value)
192
12.1k
{
193
12.1k
  if (value == CS_OPT_SYNTAX_NOREGNAME) {
194
0
    handle->get_regname = getRegisterName_digit;
195
0
    handle->reg_name = ARM_reg_name2;
196
12.1k
  } else {
197
12.1k
    handle->get_regname = getRegisterName;
198
12.1k
    handle->reg_name = ARM_reg_name;
199
12.1k
  }
200
12.1k
}
201
202
/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
203
///
204
/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
205
static unsigned translateShiftImm(unsigned imm)
206
60.4k
{
207
  // lsr #32 and asr #32 exist, but should be encoded as a 0.
208
  //assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
209
60.4k
  if (imm == 0)
210
4.02k
    return 32;
211
56.4k
  return imm;
212
60.4k
}
213
214
/// Prints the shift value with an immediate value.
215
static void printRegImmShift(MCInst *MI, SStream *O, ARM_AM_ShiftOpc ShOpc, unsigned ShImm)
216
32.2k
{
217
32.2k
  if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
218
1.15k
    return;
219
220
31.0k
  SStream_concat0(O, ", ");
221
222
  //assert (!(ShOpc == ARM_AM_ror && !ShImm) && "Cannot have ror #0");
223
31.0k
  SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));
224
225
31.0k
  if (MI->csh->detail) {
226
31.0k
    if (MI->csh->doing_mem)
227
6.61k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)ShOpc;
228
24.4k
    else
229
24.4k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = (arm_shifter)ShOpc;
230
31.0k
  }
231
232
31.0k
  if (ShOpc != ARM_AM_rrx) {
233
29.8k
    SStream_concat0(O, " ");
234
29.8k
    SStream_concat(O, "#%u", translateShiftImm(ShImm));
235
29.8k
    if (MI->csh->detail) {
236
29.8k
      if (MI->csh->doing_mem)
237
6.09k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = translateShiftImm(ShImm);
238
23.8k
      else
239
23.8k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = translateShiftImm(ShImm);
240
29.8k
    }
241
29.8k
  }
242
31.0k
}
243
244
static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo)
245
3.46M
{
246
3.46M
#ifndef CAPSTONE_DIET
247
3.46M
  SStream_concat0(OS, h->get_regname(RegNo));
248
3.46M
#endif
249
3.46M
}
250
251
// TODO
252
static const name_map insn_update_flgs[] = {
253
  { ARM_INS_CMN, "cmn" },
254
  { ARM_INS_CMP, "cmp" },
255
  { ARM_INS_TEQ, "teq" },
256
  { ARM_INS_TST, "tst" },
257
258
  { ARM_INS_ADC, "adcs" },
259
  { ARM_INS_ADD, "adds" },
260
  { ARM_INS_AND, "ands" },
261
  { ARM_INS_ASR, "asrs" },
262
  { ARM_INS_BIC, "bics" },
263
  { ARM_INS_EOR, "eors" },
264
  { ARM_INS_LSL, "lsls" },
265
  { ARM_INS_LSR, "lsrs" },
266
  { ARM_INS_MLA, "mlas" },
267
  { ARM_INS_MOV, "movs" },
268
  { ARM_INS_MUL, "muls" },
269
  { ARM_INS_MVN, "mvns" },
270
  { ARM_INS_ORN, "orns" },
271
  { ARM_INS_ORR, "orrs" },
272
  { ARM_INS_ROR, "rors" },
273
  { ARM_INS_RRX, "rrxs" },
274
  { ARM_INS_RSB, "rsbs" },
275
  { ARM_INS_RSC, "rscs" },
276
  { ARM_INS_SBC, "sbcs" },
277
  { ARM_INS_SMLAL, "smlals" },
278
  { ARM_INS_SMULL, "smulls" },
279
  { ARM_INS_SUB, "subs" },
280
  { ARM_INS_UMLAL, "umlals" },
281
  { ARM_INS_UMULL, "umulls" },
282
283
  { ARM_INS_UADD8, "uadd8" },
284
};
285
286
void ARM_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
287
936k
{
288
936k
  if (((cs_struct *)ud)->detail != CS_OPT_ON)
289
0
    return;
290
291
  // check if this insn requests write-back
292
936k
  if (mci->writeback || (strrchr(insn_asm, '!')) != NULL) {
293
79.6k
    insn->detail->arm.writeback = true;
294
856k
  } else if (mci->csh->mode & CS_MODE_THUMB) {
295
    // handle some special instructions with writeback
296
        //printf(">> Opcode = %u\n", mci->Opcode);
297
679k
    switch(mci->Opcode) {
298
669k
      default:
299
669k
        break;
300
669k
      case ARM_t2LDC2L_PRE:
301
0
      case ARM_t2LDC2_PRE:
302
0
      case ARM_t2LDCL_PRE:
303
0
      case ARM_t2LDC_PRE:
304
305
0
      case ARM_t2LDRB_PRE:
306
0
      case ARM_t2LDRD_PRE:
307
0
      case ARM_t2LDRH_PRE:
308
0
      case ARM_t2LDRSB_PRE:
309
0
      case ARM_t2LDRSH_PRE:
310
0
      case ARM_t2LDR_PRE:
311
312
0
      case ARM_t2STC2L_PRE:
313
0
      case ARM_t2STC2_PRE:
314
0
      case ARM_t2STCL_PRE:
315
0
      case ARM_t2STC_PRE:
316
317
0
      case ARM_t2STRB_PRE:
318
0
      case ARM_t2STRD_PRE:
319
0
      case ARM_t2STRH_PRE:
320
0
      case ARM_t2STR_PRE:
321
0
        insn->detail->arm.writeback = true;
322
0
        break;
323
931
      case ARM_t2LDC2L_POST:
324
1.24k
      case ARM_t2LDC2_POST:
325
1.57k
      case ARM_t2LDCL_POST:
326
1.82k
      case ARM_t2LDC_POST:
327
328
1.92k
      case ARM_t2LDRB_POST:
329
2.84k
      case ARM_t2LDRD_POST:
330
3.13k
      case ARM_t2LDRH_POST:
331
3.88k
      case ARM_t2LDRSB_POST:
332
4.24k
      case ARM_t2LDRSH_POST:
333
4.48k
      case ARM_t2LDR_POST:
334
335
5.06k
      case ARM_t2STC2L_POST:
336
5.64k
      case ARM_t2STC2_POST:
337
6.67k
      case ARM_t2STCL_POST:
338
6.87k
      case ARM_t2STC_POST:
339
340
7.35k
      case ARM_t2STRB_POST:
341
8.86k
      case ARM_t2STRD_POST:
342
8.95k
      case ARM_t2STRH_POST:
343
9.36k
      case ARM_t2STR_POST:
344
9.36k
        insn->detail->arm.writeback = true;
345
9.36k
        insn->detail->arm.post_index = true;
346
9.36k
        break;
347
679k
    }
348
679k
  } else { // ARM mode
349
    // handle some special instructions with writeback
350
        //printf(">> Opcode = %u\n", mci->Opcode);
351
177k
    switch(mci->Opcode) {
352
168k
      default:
353
168k
        break;
354
168k
      case ARM_LDC2L_PRE:
355
0
      case ARM_LDC2_PRE:
356
0
      case ARM_LDCL_PRE:
357
0
      case ARM_LDC_PRE:
358
359
0
      case ARM_LDRD_PRE:
360
0
      case ARM_LDRH_PRE:
361
0
      case ARM_LDRSB_PRE:
362
0
      case ARM_LDRSH_PRE:
363
364
0
      case ARM_STC2L_PRE:
365
0
      case ARM_STC2_PRE:
366
0
      case ARM_STCL_PRE:
367
0
      case ARM_STC_PRE:
368
369
0
      case ARM_STRD_PRE:
370
0
      case ARM_STRH_PRE:
371
0
        insn->detail->arm.writeback = true;
372
0
        break;
373
304
      case ARM_LDC2L_POST:
374
741
      case ARM_LDC2_POST:
375
1.20k
      case ARM_LDCL_POST:
376
1.83k
      case ARM_LDC_POST:
377
378
1.83k
      case ARM_LDRBT_POST:
379
1.83k
      case ARM_LDRD_POST:
380
1.83k
      case ARM_LDRH_POST:
381
1.83k
      case ARM_LDRSB_POST:
382
1.83k
      case ARM_LDRSH_POST:
383
384
2.15k
      case ARM_STC2L_POST:
385
2.45k
      case ARM_STC2_POST:
386
3.01k
      case ARM_STCL_POST:
387
3.43k
      case ARM_STC_POST:
388
389
3.43k
      case ARM_STRBT_POST:
390
3.43k
      case ARM_STRD_POST:
391
3.43k
      case ARM_STRH_POST:
392
393
4.06k
      case ARM_LDRB_POST_IMM:
394
5.77k
      case ARM_LDR_POST_IMM:
395
6.21k
      case ARM_LDR_POST_REG:
396
7.11k
      case ARM_STRB_POST_IMM:
397
398
8.34k
      case ARM_STR_POST_IMM:
399
9.17k
      case ARM_STR_POST_REG:
400
9.17k
        insn->detail->arm.writeback = true;
401
9.17k
        insn->detail->arm.post_index = true;
402
9.17k
        break;
403
177k
    }
404
177k
  }
405
406
  // check if this insn requests update flags
407
936k
  if (insn->detail->arm.update_flags == false) {
408
    // some insn still update flags, regardless of tabgen info
409
668k
    unsigned int i, j;
410
411
20.0M
    for (i = 0; i < ARR_SIZE(insn_update_flgs); i++) {
412
19.3M
      if (insn->id == insn_update_flgs[i].id &&
413
54.2k
          !strncmp(insn_asm, insn_update_flgs[i].name,
414
54.2k
            strlen(insn_update_flgs[i].name))) {
415
101
        insn->detail->arm.update_flags = true;
416
        // we have to update regs_write array as well
417
101
        for (j = 0; j < ARR_SIZE(insn->detail->regs_write); j++) {
418
101
          if (insn->detail->regs_write[j] == 0) {
419
101
            insn->detail->regs_write[j] = ARM_REG_CPSR;
420
101
            break;
421
101
          }
422
101
        }
423
101
        break;
424
101
      }
425
19.3M
    }
426
668k
  }
427
428
  // instruction should not have invalid CC
429
936k
  if (insn->detail->arm.cc == ARM_CC_INVALID) {
430
89.0k
    insn->detail->arm.cc = ARM_CC_AL;
431
89.0k
  }
432
433
  // manual fix for some special instructions
434
  // printf(">>> id: %u, mcid: %u\n", insn->id, mci->Opcode);
435
936k
  switch(mci->Opcode) {
436
936k
    default:
437
936k
      break;
438
936k
    case ARM_MOVPCLR:
439
133
      insn->detail->arm.operands[0].type = ARM_OP_REG;
440
133
      insn->detail->arm.operands[0].reg = ARM_REG_PC;
441
133
      insn->detail->arm.operands[0].access = CS_AC_WRITE;
442
133
      insn->detail->arm.operands[1].type = ARM_OP_REG;
443
133
      insn->detail->arm.operands[1].reg = ARM_REG_LR;
444
133
      insn->detail->arm.operands[1].access = CS_AC_READ;
445
133
      insn->detail->arm.op_count = 2;
446
133
      break;
447
936k
  }
448
936k
}
449
450
void ARM_printInst(MCInst *MI, SStream *O, void *Info)
451
936k
{
452
936k
  MCRegisterInfo *MRI = (MCRegisterInfo *)Info;
453
936k
  unsigned Opcode = MCInst_getOpcode(MI), tmp, i;
454
455
  //printf(">>> Opcode = %u\n", Opcode);
456
936k
  switch (Opcode) {
457
    // Check for MOVs and print canonical forms, instead.
458
1.11k
    case ARM_MOVsr: {
459
      // FIXME: Thumb variants?
460
1.11k
      unsigned int opc;
461
1.11k
      MCOperand *Dst = MCInst_getOperand(MI, 0);
462
1.11k
      MCOperand *MO1 = MCInst_getOperand(MI, 1);
463
1.11k
      MCOperand *MO2 = MCInst_getOperand(MI, 2);
464
1.11k
      MCOperand *MO3 = MCInst_getOperand(MI, 3);
465
466
1.11k
      opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));
467
1.11k
      SStream_concat0(O, ARM_AM_getShiftOpcStr(opc));
468
469
1.11k
      switch (opc) {
470
0
        default: break;
471
169
        case ARM_AM_asr:
472
169
           MCInst_setOpcodePub(MI, ARM_INS_ASR);
473
169
           break;
474
183
        case ARM_AM_lsl:
475
183
           MCInst_setOpcodePub(MI, ARM_INS_LSL);
476
183
           break;
477
60
        case ARM_AM_lsr:
478
60
           MCInst_setOpcodePub(MI, ARM_INS_LSR);
479
60
           break;
480
706
        case ARM_AM_ror:
481
706
           MCInst_setOpcodePub(MI, ARM_INS_ROR);
482
706
           break;
483
0
        case ARM_AM_rrx:
484
0
           MCInst_setOpcodePub(MI, ARM_INS_RRX);
485
0
           break;
486
1.11k
      }
487
488
1.11k
      printSBitModifierOperand(MI, 6, O);
489
1.11k
      printPredicateOperand(MI, 4, O);
490
491
1.11k
      SStream_concat0(O, "\t");
492
1.11k
      printRegName(MI->csh, O, MCOperand_getReg(Dst));
493
494
1.11k
      if (MI->csh->detail) {
495
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
496
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
497
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
498
1.11k
        MI->flat_insn->detail->arm.op_count++;
499
1.11k
      }
500
501
1.11k
      SStream_concat0(O, ", ");
502
1.11k
      printRegName(MI->csh, O, MCOperand_getReg(MO1));
503
504
1.11k
      if (MI->csh->detail) {
505
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
506
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
507
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
508
1.11k
        MI->flat_insn->detail->arm.op_count++;
509
1.11k
      }
510
511
1.11k
      SStream_concat0(O, ", ");
512
1.11k
      printRegName(MI->csh, O, MCOperand_getReg(MO2));
513
514
1.11k
      if (MI->csh->detail) {
515
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
516
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);
517
1.11k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
518
1.11k
        MI->flat_insn->detail->arm.op_count++;
519
1.11k
      }
520
521
1.11k
      return;
522
1.11k
    }
523
524
941
    case ARM_MOVsi: {
525
      // FIXME: Thumb variants?
526
941
      unsigned int opc;
527
941
      MCOperand *Dst = MCInst_getOperand(MI, 0);
528
941
      MCOperand *MO1 = MCInst_getOperand(MI, 1);
529
941
      MCOperand *MO2 = MCInst_getOperand(MI, 2);
530
531
941
      opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2));
532
941
      SStream_concat0(O, ARM_AM_getShiftOpcStr(opc));
533
534
941
      switch(opc) {
535
0
        default:
536
0
          break;
537
220
        case ARM_AM_asr:
538
220
          MCInst_setOpcodePub(MI, ARM_INS_ASR);
539
220
          break;
540
76
        case ARM_AM_lsl:
541
76
          MCInst_setOpcodePub(MI, ARM_INS_LSL);
542
76
          break;
543
280
        case ARM_AM_lsr:
544
280
          MCInst_setOpcodePub(MI, ARM_INS_LSR);
545
280
          break;
546
129
        case ARM_AM_ror:
547
129
          MCInst_setOpcodePub(MI, ARM_INS_ROR);
548
129
          break;
549
236
        case ARM_AM_rrx:
550
236
          MCInst_setOpcodePub(MI, ARM_INS_RRX);
551
236
          break;
552
941
      }
553
554
941
      printSBitModifierOperand(MI, 5, O);
555
941
      printPredicateOperand(MI, 3, O);
556
557
941
      SStream_concat0(O, "\t");
558
941
      printRegName(MI->csh, O, MCOperand_getReg(Dst));
559
560
941
      if (MI->csh->detail) {
561
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
562
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
563
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
564
941
        MI->flat_insn->detail->arm.op_count++;
565
941
      }
566
567
941
      SStream_concat0(O, ", ");
568
941
      printRegName(MI->csh, O, MCOperand_getReg(MO1));
569
941
      if (MI->csh->detail) {
570
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
571
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
572
941
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
573
941
        MI->flat_insn->detail->arm.op_count++;
574
941
      }
575
576
941
      if (opc == ARM_AM_rrx) {
577
        //printAnnotation(O, Annot);
578
236
        return;
579
236
      }
580
581
705
      SStream_concat0(O, ", ");
582
705
      tmp = translateShiftImm(getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
583
705
      printUInt32Bang(O, tmp);
584
705
      if (MI->csh->detail) {
585
705
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type =
586
705
          (arm_shifter)opc;
587
705
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
588
705
      }
589
590
705
      return;
591
941
    }
592
593
    // A8.6.123 PUSH
594
637
    case ARM_STMDB_UPD:
595
1.58k
    case ARM_t2STMDB_UPD:
596
1.58k
      if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
597
795
            MCInst_getNumOperands(MI) > 5) {
598
        // Should only print PUSH if there are at least two registers in the list.
599
525
        SStream_concat0(O, "push");
600
525
        MCInst_setOpcodePub(MI, ARM_INS_PUSH);
601
525
        printPredicateOperand(MI, 2, O);
602
603
525
        if (Opcode == ARM_t2STMDB_UPD)
604
434
          SStream_concat0(O, ".w");
605
606
525
        SStream_concat0(O, "\t");
607
608
525
        if (MI->csh->detail) {
609
525
          MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
610
525
          MI->flat_insn->detail->regs_read_count++;
611
525
          MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
612
525
          MI->flat_insn->detail->regs_write_count++;
613
525
        }
614
615
525
        printRegisterList(MI, 4, O);
616
525
        return;
617
525
      } else
618
1.05k
        break;
619
620
743
    case ARM_STR_PRE_IMM:
621
743
      if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&
622
240
          MCOperand_getImm(MCInst_getOperand(MI, 3)) == -4) {
623
0
        SStream_concat0(O, "push");
624
0
        MCInst_setOpcodePub(MI, ARM_INS_PUSH);
625
626
0
        printPredicateOperand(MI, 4, O);
627
628
0
        SStream_concat0(O, "\t{");
629
630
0
        printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 1)));
631
632
0
        if (MI->csh->detail) {
633
0
#ifndef CAPSTONE_DIET
634
0
          uint8_t access;
635
0
#endif
636
0
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
637
0
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));
638
0
#ifndef CAPSTONE_DIET
639
0
          access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
640
0
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
641
0
          MI->ac_idx++;
642
0
#endif
643
0
          MI->flat_insn->detail->arm.op_count++;
644
0
        }
645
646
0
        SStream_concat0(O, "}");
647
648
0
        return;
649
0
      } else
650
743
        break;
651
652
    // A8.6.122 POP
653
628
    case ARM_LDMIA_UPD:
654
1.15k
    case ARM_t2LDMIA_UPD:
655
1.15k
      if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
656
700
          MCInst_getNumOperands(MI) > 5) {
657
        // Should only print POP if there are at least two registers in the list.
658
630
        SStream_concat0(O, "pop");
659
630
        MCInst_setOpcodePub(MI, ARM_INS_POP);
660
661
630
        printPredicateOperand(MI, 2, O);
662
630
        if (Opcode == ARM_t2LDMIA_UPD)
663
343
          SStream_concat0(O, ".w");
664
665
630
        SStream_concat0(O, "\t");
666
667
        // unlike LDM, POP only write to registers, so skip the 1st access code
668
630
        MI->ac_idx = 1;
669
630
        if (MI->csh->detail) {
670
630
          MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
671
630
          MI->flat_insn->detail->regs_read_count++;
672
630
          MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
673
630
          MI->flat_insn->detail->regs_write_count++;
674
630
        }
675
676
630
        printRegisterList(MI, 4, O);
677
678
630
        return;
679
630
      }
680
521
      break;
681
682
1.71k
    case ARM_LDR_POST_IMM:
683
1.71k
      if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP) {
684
668
        MCOperand *MO2 = MCInst_getOperand(MI, 4);
685
686
668
        if (getAM2Offset((unsigned int)MCOperand_getImm(MO2)) == 4) {
687
338
          SStream_concat0(O, "pop");
688
338
          MCInst_setOpcodePub(MI, ARM_INS_POP);
689
338
          printPredicateOperand(MI, 5, O);
690
338
          SStream_concat0(O, "\t{");
691
692
338
          printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 0)));
693
694
338
          if (MI->csh->detail) {
695
338
            MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
696
338
            MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
697
338
            MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
698
338
            MI->flat_insn->detail->arm.op_count++;
699
                        // this instruction implicitly read/write SP register
700
338
                        MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
701
338
                        MI->flat_insn->detail->regs_read_count++;
702
338
                        MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
703
338
                        MI->flat_insn->detail->regs_write_count++;
704
338
          }
705
338
          SStream_concat0(O, "}");
706
338
          return;
707
338
        }
708
668
      }
709
1.37k
      break;
710
711
    // A8.6.355 VPUSH
712
1.37k
    case ARM_VSTMSDB_UPD:
713
585
    case ARM_VSTMDDB_UPD:
714
585
      if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
715
459
        SStream_concat0(O, "vpush");
716
459
        MCInst_setOpcodePub(MI, ARM_INS_VPUSH);
717
459
        printPredicateOperand(MI, 2, O);
718
459
        SStream_concat0(O, "\t");
719
459
        printRegisterList(MI, 4, O);
720
459
        return;
721
459
      }
722
126
      break;
723
724
    // A8.6.354 VPOP
725
530
    case ARM_VLDMSIA_UPD:
726
1.08k
    case ARM_VLDMDIA_UPD:
727
1.08k
      if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
728
585
        SStream_concat0(O, "vpop");
729
585
        MCInst_setOpcodePub(MI, ARM_INS_VPOP);
730
585
        printPredicateOperand(MI, 2, O);
731
585
        SStream_concat0(O, "\t");
732
585
        printRegisterList(MI, 4, O);
733
585
        return;
734
585
      }
735
498
      break;
736
737
8.70k
    case ARM_tLDMIA: {
738
8.70k
        bool Writeback = true;
739
8.70k
        unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, 0));
740
8.70k
        unsigned i;
741
742
47.9k
        for (i = 3; i < MCInst_getNumOperands(MI); ++i) {
743
39.2k
          if (MCOperand_getReg(MCInst_getOperand(MI, i)) == BaseReg)
744
4.80k
            Writeback = false;
745
39.2k
        }
746
747
8.70k
        SStream_concat0(O, "ldm");
748
8.70k
        MCInst_setOpcodePub(MI, ARM_INS_LDM);
749
750
8.70k
        printPredicateOperand(MI, 1, O);
751
8.70k
        SStream_concat0(O, "\t");
752
8.70k
        printRegName(MI->csh, O, BaseReg);
753
8.70k
        if (MI->csh->detail) {
754
8.70k
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
755
8.70k
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg;
756
8.70k
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ | CS_AC_WRITE;
757
8.70k
          MI->flat_insn->detail->arm.op_count++;
758
8.70k
        }
759
760
8.70k
        if (Writeback) {
761
3.89k
          MI->writeback = true;
762
3.89k
          SStream_concat0(O, "!");
763
3.89k
        }
764
765
8.70k
        SStream_concat0(O, ", ");
766
8.70k
        printRegisterList(MI, 3, O);
767
8.70k
        return;
768
1.08k
      }
769
770
    // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
771
    // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
772
    // a single GPRPair reg operand is used in the .td file to replace the two
773
    // GPRs. However, when decoding them, the two GRPs cannot be automatically
774
    // expressed as a GPRPair, so we have to manually merge them.
775
    // FIXME: We would really like to be able to tablegen'erate this.
776
704
    case ARM_LDREXD:
777
1.01k
    case ARM_STREXD:
778
1.05k
    case ARM_LDAEXD:
779
1.93k
    case ARM_STLEXD: {
780
1.93k
      const MCRegisterClass *MRC = MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);
781
1.93k
      bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;
782
1.93k
      unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, isStore ? 1 : 0));
783
784
1.93k
      if (MCRegisterClass_contains(MRC, Reg)) {
785
0
          MCInst NewMI;
786
787
0
          MCInst_Init(&NewMI);
788
0
          MCInst_setOpcode(&NewMI, Opcode);
789
790
0
          if (isStore)
791
0
          MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, 0));
792
793
0
          MCOperand_CreateReg0(&NewMI, MCRegisterInfo_getMatchingSuperReg(MRI, Reg, ARM_gsub_0,
794
0
              MCRegisterInfo_getRegClass(MRI, ARM_GPRPairRegClassID)));
795
796
          // Copy the rest operands into NewMI.
797
0
          for(i = isStore ? 3 : 2; i < MCInst_getNumOperands(MI); ++i)
798
0
          MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, i));
799
800
0
          printInstruction(&NewMI, O);
801
0
          return;
802
0
      }
803
1.93k
      break;
804
1.93k
    }
805
806
1.93k
    case ARM_TSB:
807
292
    case ARM_t2TSB:
808
292
      SStream_concat0(O, "tsb\tcsync");
809
292
      MCInst_setOpcodePub(MI, ARM_INS_TSB);
810
      // TODO: add csync to operands[]?
811
292
      return;
812
936k
  }
813
814
922k
  MI->MRI = MRI;
815
816
922k
  if (!printAliasInstr(MI, O)) {
817
914k
    printInstruction(MI, O);
818
914k
  }
819
922k
}
820
821
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
822
1.48M
{
823
1.48M
  int32_t imm;
824
1.48M
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
825
826
1.48M
  if (MCOperand_isReg(Op)) {
827
1.22M
    unsigned Reg = MCOperand_getReg(Op);
828
829
1.22M
    printRegName(MI->csh, O, Reg);
830
831
1.22M
    if (MI->csh->detail) {
832
1.22M
      if (MI->csh->doing_mem) {
833
0
        if (MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base == ARM_REG_INVALID)
834
0
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = Reg;
835
0
        else
836
0
          MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = Reg;
837
1.22M
      } else {
838
1.22M
#ifndef CAPSTONE_DIET
839
1.22M
        uint8_t access;
840
1.22M
#endif
841
842
1.22M
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
843
1.22M
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
844
1.22M
#ifndef CAPSTONE_DIET
845
1.22M
        access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
846
1.22M
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
847
1.22M
        MI->ac_idx++;
848
1.22M
#endif
849
1.22M
        MI->flat_insn->detail->arm.op_count++;
850
1.22M
      }
851
1.22M
    }
852
1.22M
  } else if (MCOperand_isImm(Op)) {
853
262k
    unsigned int opc = MCInst_getOpcode(MI);
854
855
262k
    imm = (int32_t)MCOperand_getImm(Op);
856
857
    // relative branch only has relative offset, so we have to update it
858
    // to reflect absolute address. 
859
    // Note: in ARM, PC is always 2 instructions ahead, so we have to
860
    // add 8 in ARM mode, or 4 in Thumb mode
861
    // printf(">> opcode: %u\n", MCInst_getOpcode(MI));
862
262k
    if (ARM_rel_branch(MI->csh, opc)) {
863
50.1k
      uint32_t address;
864
865
      // only do this for relative branch
866
50.1k
      if (MI->csh->mode & CS_MODE_THUMB) {
867
39.0k
        address = (uint32_t)MI->address + 4;
868
39.0k
        if (ARM_blx_to_arm_mode(MI->csh, opc)) {
869
          // here need to align down to the nearest 4-byte address
870
649
#define _ALIGN_DOWN(v, align_width) ((v/align_width)*align_width)
871
649
          address = _ALIGN_DOWN(address, 4);
872
649
#undef _ALIGN_DOWN
873
649
        }
874
39.0k
      } else {
875
11.1k
        address = (uint32_t)MI->address + 8;
876
11.1k
      }
877
878
50.1k
      imm += address;
879
50.1k
      printUInt32Bang(O, imm);
880
211k
    } else {
881
211k
      switch(MI->flat_insn->id) {
882
209k
        default:
883
209k
          if (MI->csh->imm_unsigned)
884
0
            printUInt32Bang(O, imm);
885
209k
          else
886
209k
            printInt32Bang(O, imm);
887
209k
          break;
888
734
        case ARM_INS_AND:
889
1.29k
        case ARM_INS_ORR:
890
1.79k
        case ARM_INS_EOR:
891
2.67k
        case ARM_INS_BIC:
892
2.82k
        case ARM_INS_MVN:
893
          // do not print number in negative form
894
2.82k
          printUInt32Bang(O, imm);
895
2.82k
          break;
896
211k
      }
897
211k
    }
898
899
262k
    if (MI->csh->detail) {
900
262k
      if (MI->csh->doing_mem)
901
0
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = imm;
902
262k
      else {
903
262k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
904
262k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
905
262k
        MI->flat_insn->detail->arm.op_count++;
906
262k
      }
907
262k
    }
908
262k
  }
909
1.48M
}
910
911
static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O)
912
22.1k
{
913
22.1k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
914
22.1k
  int32_t OffImm;
915
22.1k
  bool isSub;
916
22.1k
  SStream_concat0(O, "[pc, ");
917
918
22.1k
  OffImm = (int32_t)MCOperand_getImm(MO1);
919
22.1k
  isSub = OffImm < 0;
920
921
  // Special value for #-0. All others are normal.
922
22.1k
  if (OffImm == INT32_MIN)
923
530
    OffImm = 0;
924
925
22.1k
  if (isSub) {
926
6.78k
    SStream_concat(O, "#-0x%x", -OffImm);
927
15.3k
  } else {
928
15.3k
    printUInt32Bang(O, OffImm);
929
15.3k
  }
930
931
22.1k
  SStream_concat0(O, "]");
932
933
22.1k
  if (MI->csh->detail) {
934
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
935
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_PC;
936
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
937
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
938
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
939
22.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
940
22.1k
    MI->flat_insn->detail->arm.op_count++;
941
22.1k
  }
942
22.1k
}
943
944
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
945
// "Addressing Mode 1 - Data-processing operands" forms.  This includes:
946
//    REG 0   0           - e.g. R5
947
//    REG REG 0,SH_OPC    - e.g. R5, ROR R3
948
//    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
949
static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
950
8.30k
{
951
8.30k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
952
8.30k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
953
8.30k
  MCOperand *MO3 = MCInst_getOperand(MI, OpNum + 2);
954
8.30k
  ARM_AM_ShiftOpc ShOpc;
955
956
8.30k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
957
958
8.30k
  if (MI->csh->detail) {
959
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
960
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
961
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
962
963
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (MCOperand_getImm(MO3) & 7) + ARM_SFT_ASR_REG - 1;
964
8.30k
    MI->flat_insn->detail->arm.op_count++;
965
8.30k
  }
966
967
  // Print the shift opc.
968
8.30k
  ShOpc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));
969
8.30k
  SStream_concat0(O, ", ");
970
8.30k
  SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));
971
8.30k
  if (ShOpc == ARM_AM_rrx)
972
0
    return;
973
974
8.30k
  SStream_concat0(O, " ");
975
976
8.30k
  printRegName(MI->csh, O, MCOperand_getReg(MO2));
977
978
8.30k
  if (MI->csh->detail)
979
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = MCOperand_getReg(MO2);
980
8.30k
}
981
982
static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
983
15.7k
{
984
15.7k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
985
15.7k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
986
987
15.7k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
988
989
15.7k
  if (MI->csh->detail) {
990
15.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
991
15.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
992
15.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
993
15.7k
    MI->flat_insn->detail->arm.op_count++;
994
15.7k
  }
995
996
  // Print the shift opc.
997
15.7k
  printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
998
15.7k
      getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
999
15.7k
}
1000
1001
//===--------------------------------------------------------------------===//
1002
// Addressing Mode #2
1003
//===--------------------------------------------------------------------===//
1004
1005
static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
1006
6.84k
{
1007
6.84k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1008
6.84k
  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1009
6.84k
  MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
1010
6.84k
  unsigned int imm3 = (unsigned int)MCOperand_getImm(MO3);
1011
6.84k
  ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
1012
1013
6.84k
  SStream_concat0(O, "[");
1014
6.84k
  set_mem_access(MI, true);
1015
1016
6.84k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1017
6.84k
  if (MI->csh->detail) {
1018
6.84k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1019
6.84k
  }
1020
1021
6.84k
  if (!MCOperand_getReg(MO2)) {
1022
0
    unsigned tmp = getAM2Offset(imm3);
1023
0
    if (tmp) { // Don't print +0.
1024
0
      subtracted = getAM2Op(imm3);
1025
1026
0
      SStream_concat0(O, ", ");
1027
0
      if (tmp > HEX_THRESHOLD)
1028
0
        SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);
1029
0
      else
1030
0
        SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);
1031
0
      if (MI->csh->detail) {
1032
0
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op(imm3);
1033
0
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;
1034
0
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1035
0
      }
1036
0
    }
1037
1038
0
    SStream_concat0(O, "]");
1039
0
    set_mem_access(MI, false);
1040
1041
0
    return;
1042
0
  }
1043
1044
6.84k
  SStream_concat0(O, ", ");
1045
6.84k
  SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1046
6.84k
  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1047
6.84k
  if (MI->csh->detail) {
1048
6.84k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1049
6.84k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1050
6.84k
  }
1051
1052
6.84k
  printRegImmShift(MI, O, getAM2ShiftOpc(imm3), getAM2Offset(imm3));
1053
6.84k
  SStream_concat0(O, "]");
1054
6.84k
  set_mem_access(MI, false);
1055
6.84k
}
1056
1057
static void printAddrModeTBB(MCInst *MI, unsigned Op, SStream *O)
1058
365
{
1059
365
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1060
365
  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1061
1062
365
  SStream_concat0(O, "[");
1063
365
  set_mem_access(MI, true);
1064
1065
365
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1066
1067
365
  if (MI->csh->detail)
1068
365
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1069
1070
365
  SStream_concat0(O, ", ");
1071
365
  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1072
1073
365
  if (MI->csh->detail)
1074
365
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1075
1076
365
  SStream_concat0(O, "]");
1077
365
  set_mem_access(MI, false);
1078
365
}
1079
1080
static void printAddrModeTBH(MCInst *MI, unsigned Op, SStream *O)
1081
538
{
1082
538
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1083
538
  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1084
1085
538
  SStream_concat0(O, "[");
1086
538
  set_mem_access(MI, true);
1087
1088
538
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1089
1090
538
  if (MI->csh->detail)
1091
538
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1092
1093
538
  SStream_concat0(O, ", ");
1094
538
  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1095
1096
538
  if (MI->csh->detail)
1097
538
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1098
1099
538
  SStream_concat0(O, ", lsl #1]");
1100
1101
538
  if (MI->csh->detail) {
1102
538
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;
1103
538
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = 1;
1104
538
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.lshift = 1;
1105
538
  }
1106
1107
538
  set_mem_access(MI, false);
1108
538
}
1109
1110
static void printAddrMode2Operand(MCInst *MI, unsigned Op, SStream *O)
1111
10.1k
{
1112
10.1k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1113
1114
10.1k
  if (!MCOperand_isReg(MO1)) {   // FIXME: This is for CP entries, but isn't right.
1115
0
    printOperand(MI, Op, O);
1116
0
    return;
1117
0
  }
1118
1119
//#ifndef NDEBUG
1120
//  const MCOperand &MO3 = MI->getOperand(Op + 2);
1121
//  unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
1122
//  assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
1123
//#endif
1124
1125
10.1k
  printAM2PreOrOffsetIndexOp(MI, Op, O);
1126
10.1k
}
1127
1128
static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1129
13.1k
{
1130
13.1k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1131
13.1k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1132
13.1k
  ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
1133
1134
13.1k
  if (!MCOperand_getReg(MO1)) {
1135
8.86k
    unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));
1136
8.86k
    if (ImmOffs > HEX_THRESHOLD)
1137
8.21k
      SStream_concat(O, "#%s0x%x",
1138
8.21k
          ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1139
654
    else
1140
654
      SStream_concat(O, "#%s%u",
1141
654
          ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1142
1143
8.86k
    if (MI->csh->detail) {
1144
8.86k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1145
8.86k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
1146
8.86k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1147
8.86k
      MI->flat_insn->detail->arm.op_count++;
1148
8.86k
    }
1149
8.86k
    return;
1150
8.86k
  }
1151
1152
4.30k
  SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1153
4.30k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1154
1155
4.30k
  if (MI->csh->detail) {
1156
4.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1157
4.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1158
4.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1159
4.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1160
4.30k
    MI->flat_insn->detail->arm.op_count++;
1161
4.30k
  }
1162
1163
4.30k
  printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO2)),
1164
4.30k
      getAM2Offset((unsigned int)MCOperand_getImm(MO2)));
1165
4.30k
}
1166
1167
//===--------------------------------------------------------------------===//
1168
// Addressing Mode #3
1169
//===--------------------------------------------------------------------===//
1170
1171
static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
1172
    bool AlwaysPrintImm0)
1173
7.14k
{
1174
7.14k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1175
7.14k
  MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
1176
7.14k
  MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
1177
7.14k
  ARM_AM_AddrOpc sign = getAM3Op((unsigned int)MCOperand_getImm(MO3));
1178
7.14k
  unsigned ImmOffs;
1179
1180
7.14k
  SStream_concat0(O, "[");
1181
7.14k
  set_mem_access(MI, true);
1182
1183
7.14k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1184
1185
7.14k
  if (MI->csh->detail)
1186
7.14k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1187
1188
7.14k
  if (MCOperand_getReg(MO2)) {
1189
3.19k
    SStream_concat0(O, ", ");
1190
3.19k
    SStream_concat0(O, ARM_AM_getAddrOpcStr(sign));
1191
1192
3.19k
    printRegName(MI->csh, O, MCOperand_getReg(MO2));
1193
1194
3.19k
    if (MI->csh->detail) {
1195
3.19k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1196
3.19k
      if (sign == ARM_AM_sub) {
1197
1.15k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;
1198
1.15k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1199
1.15k
      }
1200
3.19k
    }
1201
1202
3.19k
    SStream_concat0(O, "]");
1203
3.19k
    set_mem_access(MI, false);
1204
1205
3.19k
    return;
1206
3.19k
  }
1207
1208
  // If the op is sub we have to print the immediate even if it is 0
1209
3.94k
  ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
1210
1211
3.94k
  if (AlwaysPrintImm0 || ImmOffs || (sign == ARM_AM_sub)) {
1212
3.83k
    if (ImmOffs > HEX_THRESHOLD)
1213
2.46k
      SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(sign), ImmOffs);
1214
1.37k
    else
1215
1.37k
      SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(sign), ImmOffs);
1216
3.83k
  }
1217
1218
3.94k
  if (MI->csh->detail) {
1219
3.94k
    if (sign == ARM_AM_sub) {
1220
1.89k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs;
1221
1.89k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1222
1.89k
    } else
1223
2.05k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)ImmOffs;
1224
3.94k
  }
1225
1226
3.94k
  SStream_concat0(O, "]");
1227
3.94k
  set_mem_access(MI, false);
1228
3.94k
}
1229
1230
static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,
1231
    bool AlwaysPrintImm0)
1232
7.14k
{
1233
7.14k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1234
1235
7.14k
  if (!MCOperand_isReg(MO1)) {   // For label symbolic references.
1236
0
    printOperand(MI, Op, O);
1237
0
    return;
1238
0
  }
1239
1240
7.14k
  printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
1241
7.14k
}
1242
1243
static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1244
7.73k
{
1245
7.73k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1246
7.73k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1247
7.73k
  ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));
1248
7.73k
  unsigned ImmOffs;
1249
1250
7.73k
  if (MCOperand_getReg(MO1)) {
1251
4.52k
    SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1252
4.52k
    printRegName(MI->csh, O, MCOperand_getReg(MO1));
1253
1254
4.52k
    if (MI->csh->detail) {
1255
4.52k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1256
4.52k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1257
4.52k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1258
4.52k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1259
4.52k
      MI->flat_insn->detail->arm.op_count++;
1260
4.52k
    }
1261
1262
4.52k
    return;
1263
4.52k
  }
1264
1265
3.20k
  ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));
1266
3.20k
  if (ImmOffs > HEX_THRESHOLD)
1267
2.35k
    SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1268
851
  else
1269
851
    SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1270
1271
3.20k
  if (MI->csh->detail) {
1272
3.20k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1273
3.20k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
1274
3.20k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1275
3.20k
    MI->flat_insn->detail->arm.op_count++;
1276
3.20k
  }
1277
3.20k
}
1278
1279
static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O)
1280
1.68k
{
1281
1.68k
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1282
1.68k
  unsigned Imm = (unsigned int)MCOperand_getImm(MO);
1283
1284
1.68k
  if ((Imm & 0xff) > HEX_THRESHOLD)
1285
1.29k
    SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
1286
387
  else
1287
387
    SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
1288
1289
1.68k
  if (MI->csh->detail) {
1290
1.68k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1291
1.68k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm & 0xff;
1292
1.68k
    MI->flat_insn->detail->arm.op_count++;
1293
1.68k
  }
1294
1.68k
}
1295
1296
static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1297
1.95k
{
1298
1.95k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1299
1.95k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1300
1301
1.95k
  SStream_concat0(O, (MCOperand_getImm(MO2) ? "" : "-"));
1302
1.95k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1303
1304
1.95k
  if (MI->csh->detail) {
1305
1.95k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1306
1.95k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1307
1.95k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1308
1.95k
    MI->flat_insn->detail->arm.op_count++;
1309
1.95k
  }
1310
1.95k
}
1311
1312
static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
1313
7.64k
{
1314
7.64k
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1315
7.64k
  int Imm = (int)MCOperand_getImm(MO);
1316
1317
7.64k
  if (((Imm & 0xff) << 2) > HEX_THRESHOLD) {
1318
6.99k
    SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
1319
6.99k
  } else {
1320
650
    SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
1321
650
  }
1322
1323
7.64k
  if (MI->csh->detail) {
1324
7.64k
    int v = (Imm & 256) ? ((Imm & 0xff) << 2) : -((Imm & 0xff) << 2);
1325
7.64k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1326
7.64k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;
1327
7.64k
    MI->flat_insn->detail->arm.op_count++;
1328
7.64k
  }
1329
7.64k
}
1330
1331
static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
1332
    bool AlwaysPrintImm0)
1333
19.2k
{
1334
19.2k
  unsigned ImmOffs;
1335
19.2k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1336
19.2k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1337
19.2k
  ARM_AM_AddrOpc Op = ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2));
1338
1339
19.2k
  if (!MCOperand_isReg(MO1)) {   // FIXME: This is for CP entries, but isn't right.
1340
0
    printOperand(MI, OpNum, O);
1341
0
    return;
1342
0
  }
1343
1344
19.2k
  SStream_concat0(O, "[");
1345
19.2k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1346
1347
19.2k
  if (MI->csh->detail) {
1348
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
1349
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1350
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
1351
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
1352
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
1353
19.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1354
19.2k
  }
1355
1356
19.2k
  ImmOffs = ARM_AM_getAM5Offset((unsigned int)MCOperand_getImm(MO2));
1357
19.2k
  if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {
1358
18.9k
    if (ImmOffs * 4 > HEX_THRESHOLD)
1359
17.3k
      SStream_concat(O, ", #%s0x%x",
1360
17.3k
          ARM_AM_getAddrOpcStr(Op),
1361
17.3k
          ImmOffs * 4);
1362
1.58k
    else
1363
1.58k
      SStream_concat(O, ", #%s%u",
1364
1.58k
          ARM_AM_getAddrOpcStr(Op),
1365
1.58k
          ImmOffs * 4);
1366
1367
18.9k
    if (MI->csh->detail) {
1368
18.9k
      if (Op)
1369
8.66k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;
1370
10.2k
      else
1371
10.2k
        MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 4;
1372
18.9k
    }
1373
18.9k
  }
1374
1375
19.2k
  SStream_concat0(O, "]");
1376
1377
19.2k
  if (MI->csh->detail) {
1378
19.2k
    MI->flat_insn->detail->arm.op_count++;
1379
19.2k
  }
1380
19.2k
}
1381
1382
static void printAddrMode5FP16Operand(MCInst *MI, unsigned OpNum, SStream *O,
1383
    bool AlwaysPrintImm0)
1384
990
{
1385
990
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1386
990
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1387
990
  unsigned ImmOffs = getAM5FP16Offset((unsigned)MCOperand_getImm(MO2));
1388
990
  unsigned Op = getAM5FP16Op((unsigned)MCOperand_getImm(MO2));
1389
1390
990
  if (!MCOperand_isReg(MO1)) {  // FIXME: This is for CP entries, but isn't right.
1391
0
    printOperand(MI, OpNum, O);
1392
0
    return;
1393
0
  }
1394
1395
990
  SStream_concat0(O, "[");
1396
990
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1397
1398
990
  if (MI->csh->detail) {
1399
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
1400
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1401
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
1402
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
1403
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
1404
990
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1405
990
  }
1406
1407
990
  if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {
1408
685
  if (ImmOffs * 2 > HEX_THRESHOLD)
1409
474
    SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(Op), ImmOffs * 2);
1410
211
  else
1411
211
    SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(Op), ImmOffs * 2);
1412
1413
685
  if (MI->csh->detail) {
1414
685
    if (Op)
1415
125
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 2;
1416
560
    else
1417
560
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 2;
1418
685
  }
1419
685
  }
1420
1421
990
  SStream_concat0(O, "]");
1422
1423
990
  if (MI->csh->detail) {
1424
990
    MI->flat_insn->detail->arm.op_count++;
1425
990
  }
1426
990
}
1427
1428
static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O)
1429
60.6k
{
1430
60.6k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1431
60.6k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1432
60.6k
  unsigned tmp;
1433
1434
60.6k
  SStream_concat0(O, "[");
1435
60.6k
  set_mem_access(MI, true);
1436
1437
60.6k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1438
1439
60.6k
  if (MI->csh->detail)
1440
60.6k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1441
1442
60.6k
  tmp = (unsigned int)MCOperand_getImm(MO2);
1443
60.6k
  if (tmp) {
1444
22.5k
    if (tmp << 3 > HEX_THRESHOLD)
1445
22.5k
      SStream_concat(O, ":0x%x", (tmp << 3));
1446
0
    else
1447
0
      SStream_concat(O, ":%u", (tmp << 3));
1448
1449
22.5k
    if (MI->csh->detail)
1450
22.5k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp << 3;
1451
22.5k
  }
1452
1453
60.6k
  SStream_concat0(O, "]");
1454
60.6k
  set_mem_access(MI, false);
1455
60.6k
}
1456
1457
static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)
1458
49.2k
{
1459
49.2k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1460
1461
49.2k
  SStream_concat0(O, "[");
1462
49.2k
  set_mem_access(MI, true);
1463
1464
49.2k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1465
1466
49.2k
  if (MI->csh->detail)
1467
49.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1468
1469
49.2k
  SStream_concat0(O, "]");
1470
49.2k
  set_mem_access(MI, false);
1471
49.2k
}
1472
1473
static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1474
18.4k
{
1475
18.4k
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1476
1477
18.4k
  if (MCOperand_getReg(MO) == 0) {
1478
7.01k
    MI->writeback = true;
1479
7.01k
    SStream_concat0(O, "!");
1480
11.4k
  } else {
1481
11.4k
    SStream_concat0(O, ", ");
1482
11.4k
    printRegName(MI->csh, O, MCOperand_getReg(MO));
1483
1484
11.4k
    if (MI->csh->detail) {
1485
11.4k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1486
11.4k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO);
1487
11.4k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1488
11.4k
      MI->flat_insn->detail->arm.op_count++;
1489
11.4k
    }
1490
11.4k
  }
1491
18.4k
}
1492
1493
static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1494
1.89k
{
1495
1.89k
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1496
1.89k
  uint32_t v = ~(uint32_t)MCOperand_getImm(MO);
1497
1.89k
  int32_t lsb = CountTrailingZeros_32(v);
1498
1.89k
  int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
1499
1500
  //assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
1501
1.89k
  printUInt32Bang(O, lsb);
1502
1503
1.89k
  if (width > HEX_THRESHOLD)
1504
646
    SStream_concat(O, ", #0x%x", width);
1505
1.25k
  else
1506
1.25k
    SStream_concat(O, ", #%u", width);
1507
1508
1.89k
  if (MI->csh->detail) {
1509
1.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1510
1.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = lsb;
1511
1.89k
    MI->flat_insn->detail->arm.op_count++;
1512
1.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1513
1.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = width;
1514
1.89k
    MI->flat_insn->detail->arm.op_count++;
1515
1.89k
  }
1516
1.89k
}
1517
1518
static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O)
1519
2.88k
{
1520
2.88k
  unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1521
2.88k
  SStream_concat0(O, ARM_MB_MemBOptToString(val,
1522
2.88k
        ARM_getFeatureBits(MI->csh->mode, ARM_HasV8Ops)));
1523
1524
2.88k
  if (MI->csh->detail) {
1525
2.88k
    MI->flat_insn->detail->arm.mem_barrier = (arm_mem_barrier)(val + 1);
1526
2.88k
  }
1527
2.88k
}
1528
1529
static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)
1530
3.05k
{
1531
3.05k
  unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1532
3.05k
  SStream_concat0(O, ARM_ISB_InstSyncBOptToString(val));
1533
3.05k
}
1534
1535
static void printTraceSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)
1536
0
{
1537
0
  unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1538
0
  SStream_concat0(O, ARM_TSB_TraceSyncBOptToString(val));
1539
  // TODO: add to detail?
1540
0
}
1541
1542
static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1543
2.26k
{
1544
2.26k
  unsigned ShiftOp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1545
2.26k
  bool isASR = (ShiftOp & (1 << 5)) != 0;
1546
2.26k
  unsigned Amt = ShiftOp & 0x1f;
1547
1548
2.26k
  if (isASR) {
1549
1.19k
    unsigned tmp = Amt == 0 ? 32 : Amt;
1550
1.19k
    if (tmp > HEX_THRESHOLD)
1551
682
      SStream_concat(O, ", asr #0x%x", tmp);
1552
513
    else
1553
513
      SStream_concat(O, ", asr #%u", tmp);
1554
1555
1.19k
    if (MI->csh->detail) {
1556
1.19k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1557
1.19k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
1558
1.19k
    }
1559
1.19k
  } else if (Amt) {
1560
786
    if (Amt > HEX_THRESHOLD)
1561
532
      SStream_concat(O, ", lsl #0x%x", Amt);
1562
254
    else
1563
254
      SStream_concat(O, ", lsl #%u", Amt);
1564
1565
786
    if (MI->csh->detail) {
1566
786
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1567
786
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Amt;
1568
786
    }
1569
786
  }
1570
2.26k
}
1571
1572
static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1573
1.45k
{
1574
1.45k
  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1575
1576
1.45k
  if (Imm == 0)
1577
78
    return;
1578
1579
  //assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
1580
1.37k
  if (Imm > HEX_THRESHOLD)
1581
837
    SStream_concat(O, ", lsl #0x%x", Imm);
1582
536
  else
1583
536
    SStream_concat(O, ", lsl #%u", Imm);
1584
1585
1.37k
  if (MI->csh->detail) {
1586
1.37k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1587
1.37k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
1588
1.37k
  }
1589
1.37k
}
1590
1591
static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1592
1.41k
{
1593
1.41k
  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1594
1595
  // A shift amount of 32 is encoded as 0.
1596
1.41k
  if (Imm == 0)
1597
79
    Imm = 32;
1598
1599
  //assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
1600
1.41k
  if (Imm > HEX_THRESHOLD)
1601
783
    SStream_concat(O, ", asr #0x%x", Imm);
1602
628
  else
1603
628
    SStream_concat(O, ", asr #%u", Imm);
1604
1605
1.41k
  if (MI->csh->detail) {
1606
1.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1607
1.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
1608
1.41k
  }
1609
1.41k
}
1610
1611
// FIXME: push {r1, r2, r3, ...} can exceed the number of operands in MCInst struct
1612
static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O)
1613
39.6k
{
1614
39.6k
  unsigned i, e;
1615
39.6k
#ifndef CAPSTONE_DIET
1616
39.6k
  uint8_t access = 0;
1617
39.6k
#endif
1618
1619
39.6k
  SStream_concat0(O, "{");
1620
1621
39.6k
#ifndef CAPSTONE_DIET
1622
39.6k
  if (MI->csh->detail) {
1623
39.6k
    access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1624
39.6k
  }
1625
39.6k
#endif
1626
1627
268k
  for (i = OpNum, e = MCInst_getNumOperands(MI); i != e; ++i) {
1628
229k
    if (i != OpNum)
1629
189k
      SStream_concat0(O, ", ");
1630
1631
229k
    printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, i)));
1632
1633
229k
    if (MI->csh->detail) {
1634
229k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1635
229k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, i));
1636
229k
#ifndef CAPSTONE_DIET
1637
229k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
1638
229k
#endif
1639
229k
      MI->flat_insn->detail->arm.op_count++;
1640
229k
    }
1641
229k
  }
1642
1643
39.6k
  SStream_concat0(O, "}");
1644
1645
39.6k
#ifndef CAPSTONE_DIET
1646
39.6k
  if (MI->csh->detail) {
1647
39.6k
    MI->ac_idx++;
1648
39.6k
  }
1649
39.6k
#endif
1650
39.6k
}
1651
1652
static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O)
1653
1.93k
{
1654
1.93k
  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1655
1656
1.93k
  printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_0));
1657
1658
1.93k
  if (MI->csh->detail) {
1659
1.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1660
1.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_0);
1661
1.93k
    MI->flat_insn->detail->arm.op_count++;
1662
1.93k
  }
1663
1664
1.93k
  SStream_concat0(O, ", ");
1665
1666
1.93k
  printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_1));
1667
1668
1.93k
  if (MI->csh->detail) {
1669
1.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1670
1.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_gsub_1);
1671
1.93k
    MI->flat_insn->detail->arm.op_count++;
1672
1.93k
  }
1673
1.93k
}
1674
1675
// SETEND BE/LE
1676
static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O)
1677
239
{
1678
239
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1679
1680
239
  if (MCOperand_getImm(Op)) {
1681
171
    SStream_concat0(O, "be");
1682
1683
171
    if (MI->csh->detail) {
1684
171
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1685
171
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_BE;
1686
171
      MI->flat_insn->detail->arm.op_count++;
1687
171
    }
1688
171
  } else {
1689
68
    SStream_concat0(O, "le");
1690
1691
68
    if (MI->csh->detail) {
1692
68
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1693
68
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_LE;
1694
68
      MI->flat_insn->detail->arm.op_count++;
1695
68
    }
1696
68
  }
1697
239
}
1698
1699
static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O)
1700
1.37k
{
1701
1.37k
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1702
1.37k
  unsigned int mode = (unsigned int)MCOperand_getImm(Op);
1703
1704
1.37k
  SStream_concat0(O, ARM_PROC_IModToString(mode));
1705
1706
1.37k
  if (MI->csh->detail) {
1707
1.37k
    MI->flat_insn->detail->arm.cps_mode = mode;
1708
1.37k
  }
1709
1.37k
}
1710
1711
static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O)
1712
1.37k
{
1713
1.37k
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1714
1.37k
  unsigned IFlags = (unsigned int)MCOperand_getImm(Op);
1715
1.37k
  int i;
1716
1717
5.48k
  for (i = 2; i >= 0; --i)
1718
4.11k
    if (IFlags & (1 << i)) {
1719
2.45k
      SStream_concat0(O, ARM_PROC_IFlagsToString(1 << i));
1720
2.45k
    }
1721
1722
1.37k
  if (IFlags == 0) {
1723
80
    SStream_concat0(O, "none");
1724
80
    IFlags = ARM_CPSFLAG_NONE;
1725
80
  }
1726
1727
1.37k
  if (MI->csh->detail) {
1728
1.37k
    MI->flat_insn->detail->arm.cps_flag = IFlags;
1729
1.37k
  }
1730
1.37k
}
1731
1732
static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O)
1733
8.74k
{
1734
8.74k
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1735
8.74k
  unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;
1736
8.74k
  unsigned Mask = (unsigned)MCOperand_getImm(Op) & 0xf;
1737
8.74k
  unsigned reg;
1738
1739
8.74k
  if (ARM_getFeatureBits(MI->csh->mode, ARM_FeatureMClass)) {
1740
6.58k
    const MClassSysReg *TheReg;
1741
6.58k
    unsigned SYSm = (unsigned)MCOperand_getImm(Op) & 0xFFF;  // 12-bit SYMm
1742
6.58k
    unsigned Opcode = MCInst_getOpcode(MI);
1743
1744
6.58k
    if (Opcode == ARM_t2MSR_M && ARM_getFeatureBits(MI->csh->mode, ARM_FeatureDSP)) {
1745
5.38k
      TheReg = lookupMClassSysRegBy12bitSYSmValue(SYSm);
1746
5.38k
      if (TheReg && MClassSysReg_isInRequiredFeatures(TheReg, ARM_FeatureDSP)) {
1747
562
        SStream_concat0(O, TheReg->Name);
1748
562
        ARM_addSysReg(MI, TheReg->sysreg);
1749
562
        return;
1750
562
      }
1751
5.38k
    }
1752
1753
    // Handle the basic 8-bit mask.
1754
6.02k
    SYSm &= 0xff;
1755
6.02k
    if (Opcode == ARM_t2MSR_M && ARM_getFeatureBits(MI->csh->mode, ARM_HasV7Ops)) {
1756
      // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
1757
      // alias for MSR APSR_nzcvq.
1758
4.82k
      TheReg = lookupMClassSysRegAPSRNonDeprecated(SYSm);
1759
4.82k
      if (TheReg) {
1760
241
        SStream_concat0(O, TheReg->Name);
1761
241
        ARM_addSysReg(MI, TheReg->sysreg);
1762
241
        return;
1763
241
      }
1764
4.82k
    }
1765
1766
5.78k
    TheReg = lookupMClassSysRegBy8bitSYSmValue(SYSm);
1767
5.78k
    if (TheReg) {
1768
4.95k
      SStream_concat0(O, TheReg->Name);
1769
4.95k
      ARM_addSysReg(MI, TheReg->sysreg);
1770
4.95k
      return;
1771
4.95k
    }
1772
1773
824
    if (SYSm > HEX_THRESHOLD)
1774
756
      SStream_concat(O, "%x", SYSm);
1775
68
    else
1776
68
      SStream_concat(O, "%u", SYSm);
1777
1778
824
    if (MI->csh->detail)
1779
824
      MCOperand_CreateImm0(MI, SYSm);
1780
1781
824
    return;
1782
5.78k
  }
1783
1784
  // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
1785
  // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
1786
2.16k
  if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
1787
958
    SStream_concat0(O, "apsr_");
1788
958
    switch (Mask) {
1789
0
      default: // llvm_unreachable("Unexpected mask value!");
1790
135
      case 4:  SStream_concat0(O, "g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;
1791
535
      case 8:  SStream_concat0(O, "nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQ); return;
1792
288
      case 12: SStream_concat0(O, "nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;
1793
958
    }
1794
958
  }
1795
1796
1.20k
  if (SpecRegRBit) {
1797
620
    SStream_concat0(O, "spsr");
1798
620
  } else {
1799
585
    SStream_concat0(O, "cpsr");
1800
585
  }
1801
1802
1.20k
  reg = 0;
1803
1.20k
  if (Mask) {
1804
1.12k
    SStream_concat0(O, "_");
1805
1806
1.12k
    if (Mask & 8) {
1807
367
      SStream_concat0(O, "f");
1808
367
      reg += SpecRegRBit ? ARM_SYSREG_SPSR_F : ARM_SYSREG_CPSR_F;
1809
367
    }
1810
1811
1.12k
    if (Mask & 4) {
1812
936
      SStream_concat0(O, "s");
1813
936
      reg += SpecRegRBit ? ARM_SYSREG_SPSR_S : ARM_SYSREG_CPSR_S;
1814
936
    }
1815
1816
1.12k
    if (Mask & 2) {
1817
581
      SStream_concat0(O, "x");
1818
581
      reg += SpecRegRBit ? ARM_SYSREG_SPSR_X : ARM_SYSREG_CPSR_X;
1819
581
    }
1820
1821
1.12k
    if (Mask & 1) {
1822
760
      SStream_concat0(O, "c");
1823
760
      reg += SpecRegRBit ? ARM_SYSREG_SPSR_C : ARM_SYSREG_CPSR_C;
1824
760
    }
1825
1826
1.12k
    ARM_addSysReg(MI, reg);
1827
1.12k
  }
1828
1.20k
}
1829
1830
static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1831
1.64k
{
1832
1.64k
  uint32_t Banked = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1833
1.64k
  const BankedReg *TheReg = lookupBankedRegByEncoding(Banked);
1834
1835
1.64k
  SStream_concat0(O, TheReg->Name);
1836
1.64k
  ARM_addSysReg(MI, TheReg->sysreg);
1837
1.64k
}
1838
1839
static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1840
839k
{
1841
839k
  ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1842
  // Handle the undefined 15 CC value here for printing so we don't abort().
1843
839k
  if ((unsigned)CC == 15) {
1844
557
    SStream_concat0(O, "<und>");
1845
1846
557
    if (MI->csh->detail)
1847
557
      MI->flat_insn->detail->arm.cc = ARM_CC_INVALID;
1848
839k
  } else {
1849
839k
    if (CC != ARMCC_AL) {
1850
199k
      SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));
1851
199k
    }
1852
1853
839k
    if (MI->csh->detail)
1854
839k
      MI->flat_insn->detail->arm.cc = CC + 1;
1855
839k
  }
1856
839k
}
1857
1858
static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1859
7.87k
{
1860
7.87k
  ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1861
7.87k
  SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));
1862
1863
7.87k
  if (MI->csh->detail)
1864
7.87k
    MI->flat_insn->detail->arm.cc = CC + 1;
1865
7.87k
}
1866
1867
static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O)
1868
221k
{
1869
221k
  if (MCOperand_getReg(MCInst_getOperand(MI, OpNum))) {
1870
    //assert(MCOperand_getReg(MCInst_getOperand(MI, OpNum)) == ARM_CPSR &&
1871
    //       "Expect ARM CPSR register!");
1872
183k
    SStream_concat0(O, "s");
1873
1874
183k
    if (MI->csh->detail)
1875
183k
      MI->flat_insn->detail->arm.update_flags = true;
1876
183k
  }
1877
221k
}
1878
1879
static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1880
39.4k
{
1881
39.4k
  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1882
1883
39.4k
  printUInt32(O, tmp);
1884
1885
39.4k
  if (MI->csh->detail) {
1886
39.4k
    if (MI->csh->doing_mem) {
1887
39.4k
      MI->flat_insn->detail->arm.op_count--;
1888
39.4k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].neon_lane = (int8_t)tmp;
1889
39.4k
      MI->ac_idx--; // consecutive operands share the same access right
1890
39.4k
    } else {
1891
0
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1892
0
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1893
0
      MI->flat_insn->detail->arm.op_count++;
1894
0
    }
1895
39.4k
  }
1896
39.4k
}
1897
1898
static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1899
49.1k
{
1900
49.1k
  unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1901
1902
49.1k
  SStream_concat(O, "p%u", imm);
1903
1904
49.1k
  if (MI->csh->detail) {
1905
49.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_PIMM;
1906
49.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
1907
49.1k
    MI->flat_insn->detail->arm.op_count++;
1908
49.1k
  }
1909
49.1k
}
1910
1911
static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1912
71.7k
{
1913
71.7k
  unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1914
1915
71.7k
  SStream_concat(O, "c%u", imm);
1916
1917
71.7k
  if (MI->csh->detail) {
1918
71.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_CIMM;
1919
71.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
1920
71.7k
    MI->flat_insn->detail->arm.op_count++;
1921
71.7k
  }
1922
71.7k
}
1923
1924
static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)
1925
3.93k
{
1926
3.93k
  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1927
3.93k
  if (tmp > HEX_THRESHOLD)
1928
3.34k
    SStream_concat(O, "{0x%x}", tmp);
1929
590
  else
1930
590
    SStream_concat(O, "{%u}", tmp);
1931
1932
3.93k
  if (MI->csh->detail) {
1933
3.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1934
3.93k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1935
3.93k
    MI->flat_insn->detail->arm.op_count++;
1936
3.93k
  }
1937
3.93k
}
1938
1939
static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned scale)
1940
11.0k
{
1941
11.0k
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1942
1943
11.0k
  int32_t OffImm = (int32_t)MCOperand_getImm(MO) << scale;
1944
1945
11.0k
  if (OffImm == INT32_MIN) {
1946
0
    SStream_concat0(O, "#-0");
1947
1948
0
    if (MI->csh->detail) {
1949
0
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1950
0
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
1951
0
      MI->flat_insn->detail->arm.op_count++;
1952
0
    }
1953
11.0k
  } else {
1954
11.0k
    if (OffImm < 0)
1955
0
      SStream_concat(O, "#-0x%x", -OffImm);
1956
11.0k
    else {
1957
11.0k
      if (OffImm > HEX_THRESHOLD)
1958
10.0k
        SStream_concat(O, "#0x%x", OffImm);
1959
1.01k
      else
1960
1.01k
        SStream_concat(O, "#%u", OffImm);
1961
11.0k
    }
1962
1963
11.0k
    if (MI->csh->detail) {
1964
11.0k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1965
11.0k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
1966
11.0k
      MI->flat_insn->detail->arm.op_count++;
1967
11.0k
    }
1968
11.0k
  }
1969
11.0k
}
1970
1971
static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1972
13.2k
{
1973
13.2k
  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;
1974
1975
13.2k
  printUInt32Bang(O, tmp);
1976
1977
13.2k
  if (MI->csh->detail) {
1978
13.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1979
13.2k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1980
13.2k
    MI->flat_insn->detail->arm.op_count++;
1981
13.2k
  }
1982
13.2k
}
1983
1984
static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O)
1985
39.9k
{
1986
39.9k
  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1987
39.9k
  unsigned tmp = Imm == 0 ? 32 : Imm;
1988
1989
39.9k
  printUInt32Bang(O, tmp);
1990
1991
39.9k
  if (MI->csh->detail) {
1992
39.9k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1993
39.9k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1994
39.9k
    MI->flat_insn->detail->arm.op_count++;
1995
39.9k
  }
1996
39.9k
}
1997
1998
static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O)
1999
7.87k
{
2000
  // (3 - the number of trailing zeros) is the number of then / else.
2001
7.87k
  unsigned Mask = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2002
7.87k
  unsigned Firstcond = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum - 1));
2003
7.87k
  unsigned CondBit0 = Firstcond & 1;
2004
7.87k
  unsigned NumTZ = CountTrailingZeros_32(Mask);
2005
  //assert(NumTZ <= 3 && "Invalid IT mask!");
2006
7.87k
  unsigned Pos, e;
2007
2008
29.1k
  for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
2009
21.2k
    bool T = ((Mask >> Pos) & 1) == CondBit0;
2010
21.2k
    if (T)
2011
9.84k
      SStream_concat0(O, "t");
2012
11.3k
    else
2013
11.3k
      SStream_concat0(O, "e");
2014
    // TODO: detail for this t/e
2015
21.2k
  }
2016
7.87k
}
2017
2018
static void printThumbAddrModeRROperand(MCInst *MI, unsigned Op, SStream *O)
2019
18.7k
{
2020
18.7k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
2021
18.7k
  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
2022
18.7k
  unsigned RegNum;
2023
2024
18.7k
  if (!MCOperand_isReg(MO1)) {   // FIXME: This is for CP entries, but isn't right.
2025
0
    printOperand(MI, Op, O);
2026
0
    return;
2027
0
  }
2028
2029
18.7k
  SStream_concat0(O, "[");
2030
18.7k
  set_mem_access(MI, true);
2031
2032
18.7k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2033
2034
18.7k
  if (MI->csh->detail)
2035
18.7k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2036
2037
18.7k
  RegNum = MCOperand_getReg(MO2);
2038
18.7k
  if (RegNum) {
2039
18.7k
    SStream_concat0(O, ", ");
2040
18.7k
    printRegName(MI->csh, O, RegNum);
2041
2042
18.7k
    if (MI->csh->detail)
2043
18.7k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = RegNum;
2044
18.7k
  }
2045
2046
18.7k
  SStream_concat0(O, "]");
2047
18.7k
  set_mem_access(MI, false);
2048
18.7k
}
2049
2050
static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned Op, SStream *O,
2051
    unsigned Scale)
2052
134k
{
2053
134k
  MCOperand *MO1 = MCInst_getOperand(MI, Op);
2054
134k
  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
2055
134k
  unsigned ImmOffs, tmp;
2056
2057
134k
  if (!MCOperand_isReg(MO1)) {   // FIXME: This is for CP entries, but isn't right.
2058
0
    printOperand(MI, Op, O);
2059
0
    return;
2060
0
  }
2061
2062
134k
  SStream_concat0(O, "[");
2063
134k
  set_mem_access(MI, true);
2064
2065
134k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2066
2067
134k
  if (MI->csh->detail)
2068
134k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2069
2070
134k
  ImmOffs = (unsigned int)MCOperand_getImm(MO2);
2071
134k
  if (ImmOffs) {
2072
127k
    tmp = ImmOffs * Scale;
2073
127k
    SStream_concat0(O, ", ");
2074
127k
    printUInt32Bang(O, tmp);
2075
2076
127k
    if (MI->csh->detail)
2077
127k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
2078
127k
  }
2079
2080
134k
  SStream_concat0(O, "]");
2081
134k
  set_mem_access(MI, false);
2082
134k
}
2083
2084
static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned Op, SStream *O)
2085
61.5k
{
2086
61.5k
  printThumbAddrModeImm5SOperand(MI, Op, O, 1);
2087
61.5k
}
2088
2089
static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned Op, SStream *O)
2090
64.8k
{
2091
64.8k
  printThumbAddrModeImm5SOperand(MI, Op, O, 2);
2092
64.8k
}
2093
2094
static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned Op, SStream *O)
2095
80.8k
{
2096
80.8k
  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
2097
80.8k
}
2098
2099
static void printThumbAddrModeSPOperand(MCInst *MI, unsigned Op, SStream *O)
2100
36.2k
{
2101
36.2k
  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
2102
36.2k
}
2103
2104
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
2105
// register with shift forms.
2106
// REG 0   0           - e.g. R5
2107
// REG IMM, SH_OPC     - e.g. R5, LSL #3
2108
static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O)
2109
5.32k
{
2110
5.32k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2111
5.32k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
2112
5.32k
  unsigned Reg = MCOperand_getReg(MO1);
2113
2114
5.32k
  printRegName(MI->csh, O, Reg);
2115
2116
5.32k
  if (MI->csh->detail) {
2117
5.32k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2118
5.32k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
2119
5.32k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
2120
5.32k
    MI->flat_insn->detail->arm.op_count++;
2121
5.32k
  }
2122
2123
  // Print the shift opc.
2124
  //assert(MO2.isImm() && "Not a valid t2_so_reg value!");
2125
5.32k
  printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
2126
5.32k
      getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
2127
5.32k
}
2128
2129
static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum,
2130
    SStream *O, bool AlwaysPrintImm0)
2131
12.5k
{
2132
12.5k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2133
12.5k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2134
12.5k
  int32_t OffImm;
2135
12.5k
  bool isSub;
2136
2137
12.5k
  if (!MCOperand_isReg(MO1)) {   // FIXME: This is for CP entries, but isn't right.
2138
0
    printOperand(MI, OpNum, O);
2139
0
    return;
2140
0
  }
2141
2142
12.5k
  SStream_concat0(O, "[");
2143
12.5k
  set_mem_access(MI, true);
2144
2145
12.5k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2146
2147
12.5k
  if (MI->csh->detail)
2148
12.5k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2149
2150
12.5k
  OffImm = (int32_t)MCOperand_getImm(MO2);
2151
12.5k
  isSub = OffImm < 0;
2152
2153
  // Special value for #-0. All others are normal.
2154
12.5k
  if (OffImm == INT32_MIN)
2155
437
    OffImm = 0;
2156
2157
12.5k
  if (isSub) {
2158
4.65k
    if (OffImm < -HEX_THRESHOLD)
2159
4.05k
      SStream_concat(O, ", #-0x%x", -OffImm);
2160
601
    else
2161
601
      SStream_concat(O, ", #-%u", -OffImm);
2162
7.90k
  } else if (AlwaysPrintImm0 || OffImm > 0) {
2163
7.54k
    if (OffImm >= 0) {
2164
7.54k
      if (OffImm > HEX_THRESHOLD)
2165
7.06k
        SStream_concat(O, ", #0x%x", OffImm);
2166
486
      else
2167
486
        SStream_concat(O, ", #%u", OffImm);
2168
7.54k
    } else {
2169
0
      if (OffImm < -HEX_THRESHOLD)
2170
0
        SStream_concat(O, ", #-0x%x", -OffImm);
2171
0
      else
2172
0
        SStream_concat(O, ", #-%u", -OffImm);
2173
0
    }
2174
7.54k
  }
2175
2176
12.5k
  if (MI->csh->detail)
2177
12.5k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2178
2179
12.5k
  SStream_concat0(O, "]");
2180
12.5k
  set_mem_access(MI, false);
2181
12.5k
}
2182
2183
static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O,
2184
    bool AlwaysPrintImm0)
2185
4.92k
{
2186
4.92k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2187
4.92k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2188
4.92k
  int32_t OffImm;
2189
4.92k
  bool isSub;
2190
2191
4.92k
  SStream_concat0(O, "[");
2192
4.92k
  set_mem_access(MI, true);
2193
2194
4.92k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2195
2196
4.92k
  if (MI->csh->detail)
2197
4.92k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2198
2199
4.92k
  OffImm = (int32_t)MCOperand_getImm(MO2);
2200
4.92k
  isSub = OffImm < 0;
2201
2202
  // Don't print +0.
2203
4.92k
  if (OffImm == INT32_MIN)
2204
454
    OffImm = 0;
2205
2206
4.92k
  if (isSub)
2207
2.17k
    SStream_concat(O, ", #-0x%x", -OffImm);
2208
2.75k
  else if (AlwaysPrintImm0 || OffImm > 0) {
2209
2.46k
    if (OffImm > HEX_THRESHOLD)
2210
2.14k
      SStream_concat(O, ", #0x%x", OffImm);
2211
326
    else
2212
326
      SStream_concat(O, ", #%u", OffImm);
2213
2.46k
  }
2214
2215
4.92k
  if (MI->csh->detail)
2216
4.92k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2217
2218
4.92k
  SStream_concat0(O, "]");
2219
4.92k
  set_mem_access(MI, false);
2220
4.92k
}
2221
2222
static void printT2AddrModeImm8s4Operand(MCInst *MI,
2223
    unsigned OpNum, SStream *O, bool AlwaysPrintImm0)
2224
8.30k
{
2225
8.30k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2226
8.30k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
2227
8.30k
  int32_t OffImm;
2228
8.30k
  bool isSub;
2229
2230
8.30k
  if (!MCOperand_isReg(MO1)) {   //  For label symbolic references.
2231
0
    printOperand(MI, OpNum, O);
2232
0
    return;
2233
0
  }
2234
2235
8.30k
  SStream_concat0(O, "[");
2236
8.30k
  set_mem_access(MI, true);
2237
2238
8.30k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2239
2240
8.30k
  if (MI->csh->detail)
2241
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2242
2243
8.30k
  OffImm = (int32_t)MCOperand_getImm(MO2);
2244
8.30k
  isSub = OffImm < 0;
2245
2246
  //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
2247
2248
  // Don't print +0.
2249
8.30k
  if (OffImm == INT32_MIN)
2250
592
    OffImm = 0;
2251
2252
8.30k
  if (isSub) {
2253
2.65k
    SStream_concat(O, ", #-0x%x", -OffImm);
2254
5.65k
  } else if (AlwaysPrintImm0 || OffImm > 0) {
2255
5.47k
    if (OffImm > HEX_THRESHOLD)
2256
4.47k
      SStream_concat(O, ", #0x%x", OffImm);
2257
998
    else
2258
998
      SStream_concat(O, ", #%u", OffImm);
2259
5.47k
  }
2260
2261
8.30k
  if (MI->csh->detail)
2262
8.30k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2263
2264
8.30k
  SStream_concat0(O, "]");
2265
8.30k
  set_mem_access(MI, false);
2266
8.30k
}
2267
2268
static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
2269
2.01k
{
2270
2.01k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2271
2.01k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
2272
2.01k
  unsigned tmp;
2273
2274
2.01k
  SStream_concat0(O, "[");
2275
2.01k
  set_mem_access(MI, true);
2276
2277
2.01k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2278
2279
2.01k
  if (MI->csh->detail)
2280
2.01k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2281
2282
2.01k
  if (MCOperand_getImm(MO2)) {
2283
1.83k
    SStream_concat0(O, ", ");
2284
1.83k
    tmp = (unsigned int)MCOperand_getImm(MO2) * 4;
2285
1.83k
    printUInt32Bang(O, tmp);
2286
2287
1.83k
    if (MI->csh->detail)
2288
1.83k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
2289
1.83k
  }
2290
2291
2.01k
  SStream_concat0(O, "]");
2292
2.01k
  set_mem_access(MI, false);
2293
2.01k
}
2294
2295
static void printT2AddrModeImm8OffsetOperand(MCInst *MI,
2296
    unsigned OpNum, SStream *O)
2297
2.72k
{
2298
2.72k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2299
2.72k
  int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
2300
2301
2.72k
  SStream_concat0(O, ", ");
2302
2.72k
  if (OffImm == INT32_MIN) {
2303
1.28k
    SStream_concat0(O, "#-0");
2304
2305
1.28k
    if (MI->csh->detail) {
2306
1.28k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2307
1.28k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2308
1.28k
      MI->flat_insn->detail->arm.op_count++;
2309
1.28k
    }
2310
1.43k
  } else {
2311
1.43k
    printInt32Bang(O, OffImm);
2312
2313
1.43k
    if (MI->csh->detail) {
2314
1.43k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2315
1.43k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2316
1.43k
      MI->flat_insn->detail->arm.op_count++;
2317
1.43k
    }
2318
1.43k
  }
2319
2.72k
}
2320
2321
static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI,
2322
    unsigned OpNum, SStream *O)
2323
2.43k
{
2324
2.43k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2325
2.43k
  int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
2326
2327
  //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
2328
2329
2.43k
  SStream_concat0(O, ", ");
2330
2331
2.43k
  if (OffImm == INT32_MIN) {
2332
72
    SStream_concat0(O, "#-0");
2333
2334
72
    if (MI->csh->detail) {
2335
72
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2336
72
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2337
72
      MI->flat_insn->detail->arm.op_count++;
2338
72
    }
2339
2.36k
  } else {
2340
2.36k
    printInt32Bang(O, OffImm);
2341
2342
2.36k
    if (MI->csh->detail) {
2343
2.36k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2344
2.36k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2345
2.36k
      MI->flat_insn->detail->arm.op_count++;
2346
2.36k
    }
2347
2.36k
  }
2348
2.43k
}
2349
2350
static void printT2AddrModeSoRegOperand(MCInst *MI,
2351
    unsigned OpNum, SStream *O)
2352
3.76k
{
2353
3.76k
  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2354
3.76k
  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2355
3.76k
  MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
2356
3.76k
  unsigned ShAmt;
2357
2358
3.76k
  SStream_concat0(O, "[");
2359
3.76k
  set_mem_access(MI, true);
2360
2361
3.76k
  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2362
2363
3.76k
  if (MI->csh->detail)
2364
3.76k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2365
2366
  //assert(MCOperand_getReg(MO2.getReg() && "Invalid so_reg load / store address!");
2367
3.76k
  SStream_concat0(O, ", ");
2368
3.76k
  printRegName(MI->csh, O, MCOperand_getReg(MO2));
2369
2370
3.76k
  if (MI->csh->detail)
2371
3.76k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
2372
2373
3.76k
  ShAmt = (unsigned int)MCOperand_getImm(MO3);
2374
3.76k
  if (ShAmt) {
2375
    //assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
2376
2.59k
    SStream_concat0(O, ", lsl ");
2377
2.59k
    SStream_concat(O, "#%u", ShAmt);
2378
2379
2.59k
    if (MI->csh->detail) {
2380
2.59k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;
2381
2.59k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = ShAmt;
2382
2.59k
    }
2383
2.59k
  }
2384
2385
3.76k
  SStream_concat0(O, "]");
2386
3.76k
  set_mem_access(MI, false);
2387
3.76k
}
2388
2389
static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2390
887
{
2391
887
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
2392
2393
#if defined(_KERNEL_MODE)
2394
  // Issue #681: Windows kernel does not support formatting float point
2395
  SStream_concat(O, "#<float_point_unsupported>");
2396
#else
2397
887
  SStream_concat(O, "#%e", getFPImmFloat((unsigned int)MCOperand_getImm(MO)));
2398
887
#endif
2399
2400
887
  if (MI->csh->detail) {
2401
887
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_FP;
2402
887
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].fp = getFPImmFloat((unsigned int)MCOperand_getImm(MO));
2403
887
    MI->flat_insn->detail->arm.op_count++;
2404
887
  }
2405
887
}
2406
2407
static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2408
5.03k
{
2409
5.03k
  unsigned EncodedImm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2410
5.03k
  unsigned EltBits;
2411
5.03k
  uint64_t Val = ARM_AM_decodeNEONModImm(EncodedImm, &EltBits);
2412
2413
5.03k
  if (Val > HEX_THRESHOLD)
2414
4.51k
    SStream_concat(O, "#0x%"PRIx64, Val);
2415
524
  else
2416
524
    SStream_concat(O, "#%"PRIu64, Val);
2417
2418
5.03k
  if (MI->csh->detail) {
2419
5.03k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2420
5.03k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = (unsigned int)Val;
2421
5.03k
    MI->flat_insn->detail->arm.op_count++;
2422
5.03k
  }
2423
5.03k
}
2424
2425
static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O)
2426
3.51k
{
2427
3.51k
  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2428
2429
3.51k
  printUInt32Bang(O, Imm + 1);
2430
2431
3.51k
  if (MI->csh->detail) {
2432
3.51k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2433
3.51k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm + 1;
2434
3.51k
    MI->flat_insn->detail->arm.op_count++;
2435
3.51k
  }
2436
3.51k
}
2437
2438
static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2439
2.51k
{
2440
2.51k
  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2441
2442
2.51k
  if (Imm == 0)
2443
353
    return;
2444
2445
2.16k
  SStream_concat0(O, ", ror #");
2446
2447
2.16k
  switch (Imm) {
2448
0
    default: //assert (0 && "illegal ror immediate!");
2449
383
    case 1: SStream_concat0(O, "8"); break;
2450
210
    case 2: SStream_concat0(O, "16"); break;
2451
1.57k
    case 3: SStream_concat0(O, "24"); break;
2452
2.16k
  }
2453
2454
2.16k
  if (MI->csh->detail) {
2455
2.16k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ROR;
2456
2.16k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm * 8;
2457
2.16k
  }
2458
2.16k
}
2459
2460
static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2461
12.2k
{
2462
12.2k
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
2463
12.2k
  unsigned Bits = MCOperand_getImm(Op) & 0xFF;
2464
12.2k
  unsigned Rot = (MCOperand_getImm(Op) & 0xF00) >> 7;
2465
12.2k
  int32_t Rotated;
2466
12.2k
  bool  PrintUnsigned = false;
2467
2468
12.2k
  switch (MCInst_getOpcode(MI)) {
2469
431
    case ARM_MOVi:
2470
      // Movs to PC should be treated unsigned
2471
431
      PrintUnsigned = (MCOperand_getReg(MCInst_getOperand(MI, OpNum - 1)) == ARM_PC);
2472
431
      break;
2473
1.52k
    case ARM_MSRi:
2474
      // Movs to special registers should be treated unsigned
2475
1.52k
      PrintUnsigned = true;
2476
1.52k
      break;
2477
12.2k
  }
2478
2479
12.2k
  Rotated = rotr32(Bits, Rot);
2480
12.2k
  if (getSOImmVal(Rotated) == MCOperand_getImm(Op)) {
2481
    // #rot has the least possible value
2482
9.87k
    if (PrintUnsigned) {
2483
1.48k
      if (Rotated > HEX_THRESHOLD || Rotated < -HEX_THRESHOLD)
2484
791
        SStream_concat(O, "#0x%x", Rotated);
2485
690
      else
2486
690
        SStream_concat(O, "#%u", Rotated);
2487
8.39k
    } else if (Rotated >= 0) {
2488
6.86k
      if (Rotated > HEX_THRESHOLD)
2489
6.10k
        SStream_concat(O, "#0x%x", Rotated);
2490
755
      else
2491
755
        SStream_concat(O, "#%u", Rotated);
2492
6.86k
    } else {
2493
1.52k
      SStream_concat(O, "#0x%x", Rotated);
2494
1.52k
    }
2495
2496
9.87k
    if (MI->csh->detail) {
2497
9.87k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2498
9.87k
      MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rotated;
2499
9.87k
      MI->flat_insn->detail->arm.op_count++;
2500
9.87k
    }
2501
2502
9.87k
    return;
2503
9.87k
  }
2504
2505
  // Explicit #bits, #rot implied
2506
2.41k
  SStream_concat(O, "#%u, #%u", Bits, Rot);
2507
2508
2.41k
  if (MI->csh->detail) {
2509
2.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2510
2.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Bits;
2511
2.41k
    MI->flat_insn->detail->arm.op_count++;
2512
2.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2513
2.41k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rot;
2514
2.41k
    MI->flat_insn->detail->arm.op_count++;
2515
2.41k
  }
2516
2.41k
}
2517
2518
static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)
2519
3.06k
{
2520
3.06k
  unsigned tmp;
2521
2522
3.06k
  tmp = 16 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2523
2524
3.06k
  printUInt32Bang(O, tmp);
2525
2526
3.06k
  if (MI->csh->detail) {
2527
3.06k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2528
3.06k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2529
3.06k
    MI->flat_insn->detail->arm.op_count++;
2530
3.06k
  }
2531
3.06k
}
2532
2533
static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O)
2534
571
{
2535
571
  unsigned tmp;
2536
2537
571
  tmp = 32 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2538
2539
571
  printUInt32Bang(O, tmp);
2540
2541
571
  if (MI->csh->detail) {
2542
571
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2543
571
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2544
571
    MI->flat_insn->detail->arm.op_count++;
2545
571
  }
2546
571
}
2547
2548
static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
2549
6.05k
{
2550
6.05k
  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2551
2552
6.05k
  if (tmp > HEX_THRESHOLD)
2553
0
    SStream_concat(O, "[0x%x]", tmp);
2554
6.05k
  else
2555
6.05k
    SStream_concat(O, "[%u]", tmp);
2556
2557
6.05k
  if (MI->csh->detail) {
2558
6.05k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].vector_index = tmp;
2559
6.05k
  }
2560
6.05k
}
2561
2562
static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O)
2563
3.54k
{
2564
3.54k
  SStream_concat0(O, "{");
2565
2566
3.54k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2567
2568
3.54k
  if (MI->csh->detail) {
2569
3.54k
#ifndef CAPSTONE_DIET
2570
3.54k
    uint8_t access;
2571
2572
3.54k
    access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2573
3.54k
#endif
2574
2575
3.54k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2576
3.54k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2577
3.54k
#ifndef CAPSTONE_DIET
2578
3.54k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2579
3.54k
#endif
2580
3.54k
    MI->flat_insn->detail->arm.op_count++;
2581
2582
3.54k
#ifndef CAPSTONE_DIET
2583
3.54k
  MI->ac_idx++;
2584
3.54k
#endif
2585
3.54k
  }
2586
2587
3.54k
  SStream_concat0(O, "}");
2588
3.54k
}
2589
2590
static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O)
2591
10.1k
{
2592
10.1k
#ifndef CAPSTONE_DIET
2593
10.1k
  uint8_t access;
2594
10.1k
#endif
2595
10.1k
  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2596
10.1k
  unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);
2597
10.1k
  unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_1);
2598
2599
10.1k
#ifndef CAPSTONE_DIET
2600
10.1k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2601
10.1k
#endif
2602
2603
10.1k
  SStream_concat0(O, "{");
2604
2605
10.1k
  printRegName(MI->csh, O, Reg0);
2606
2607
10.1k
  if (MI->csh->detail) {
2608
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2609
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2610
10.1k
#ifndef CAPSTONE_DIET
2611
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2612
10.1k
#endif
2613
10.1k
    MI->flat_insn->detail->arm.op_count++;
2614
10.1k
  }
2615
2616
10.1k
  SStream_concat0(O, ", ");
2617
2618
10.1k
  printRegName(MI->csh, O, Reg1);
2619
2620
10.1k
  if (MI->csh->detail) {
2621
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2622
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2623
10.1k
#ifndef CAPSTONE_DIET
2624
10.1k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2625
10.1k
#endif
2626
10.1k
    MI->flat_insn->detail->arm.op_count++;
2627
10.1k
  }
2628
2629
10.1k
  SStream_concat0(O, "}");
2630
2631
10.1k
#ifndef CAPSTONE_DIET
2632
10.1k
  MI->ac_idx++;
2633
10.1k
#endif
2634
10.1k
}
2635
2636
static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O)
2637
4.89k
{
2638
4.89k
#ifndef CAPSTONE_DIET
2639
4.89k
  uint8_t access;
2640
4.89k
#endif
2641
4.89k
  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2642
4.89k
  unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);
2643
4.89k
  unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_2);
2644
2645
4.89k
#ifndef CAPSTONE_DIET
2646
4.89k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2647
4.89k
#endif
2648
2649
4.89k
  SStream_concat0(O, "{");
2650
2651
4.89k
  printRegName(MI->csh, O, Reg0);
2652
2653
4.89k
  if (MI->csh->detail) {
2654
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2655
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2656
4.89k
#ifndef CAPSTONE_DIET
2657
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2658
4.89k
#endif
2659
4.89k
    MI->flat_insn->detail->arm.op_count++;
2660
4.89k
  }
2661
2662
4.89k
  SStream_concat0(O, ", ");
2663
2664
4.89k
  printRegName(MI->csh, O, Reg1);
2665
2666
4.89k
  if (MI->csh->detail) {
2667
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2668
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2669
4.89k
#ifndef CAPSTONE_DIET
2670
4.89k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2671
4.89k
#endif
2672
4.89k
    MI->flat_insn->detail->arm.op_count++;
2673
4.89k
  }
2674
2675
4.89k
  SStream_concat0(O, "}");
2676
2677
4.89k
#ifndef CAPSTONE_DIET
2678
4.89k
  MI->ac_idx++;
2679
4.89k
#endif
2680
4.89k
}
2681
2682
static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O)
2683
3.96k
{
2684
3.96k
#ifndef CAPSTONE_DIET
2685
3.96k
  uint8_t access;
2686
2687
3.96k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2688
3.96k
#endif
2689
2690
  // Normally, it's not safe to use register enum values directly with
2691
  // addition to get the next register, but for VFP registers, the
2692
  // sort order is guaranteed because they're all of the form D<n>.
2693
3.96k
  SStream_concat0(O, "{");
2694
2695
3.96k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2696
2697
3.96k
  if (MI->csh->detail) {
2698
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2699
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2700
3.96k
#ifndef CAPSTONE_DIET
2701
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2702
3.96k
#endif
2703
3.96k
    MI->flat_insn->detail->arm.op_count++;
2704
3.96k
  }
2705
2706
3.96k
  SStream_concat0(O, ", ");
2707
2708
3.96k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2709
2710
3.96k
  if (MI->csh->detail) {
2711
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2712
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2713
3.96k
#ifndef CAPSTONE_DIET
2714
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2715
3.96k
#endif
2716
3.96k
    MI->flat_insn->detail->arm.op_count++;
2717
3.96k
  }
2718
2719
3.96k
  SStream_concat0(O, ", ");
2720
2721
3.96k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2722
2723
3.96k
  if (MI->csh->detail) {
2724
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2725
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2726
3.96k
#ifndef CAPSTONE_DIET
2727
3.96k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2728
3.96k
#endif
2729
3.96k
    MI->flat_insn->detail->arm.op_count++;
2730
3.96k
  }
2731
2732
3.96k
  SStream_concat0(O, "}");
2733
2734
3.96k
#ifndef CAPSTONE_DIET
2735
3.96k
  MI->ac_idx++;
2736
3.96k
#endif
2737
3.96k
}
2738
2739
static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O)
2740
6.48k
{
2741
6.48k
#ifndef CAPSTONE_DIET
2742
6.48k
  uint8_t access;
2743
2744
6.48k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2745
6.48k
#endif
2746
2747
  // Normally, it's not safe to use register enum values directly with
2748
  // addition to get the next register, but for VFP registers, the
2749
  // sort order is guaranteed because they're all of the form D<n>.
2750
6.48k
  SStream_concat0(O, "{");
2751
2752
6.48k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2753
2754
6.48k
  if (MI->csh->detail) {
2755
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2756
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2757
6.48k
#ifndef CAPSTONE_DIET
2758
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2759
6.48k
#endif
2760
6.48k
    MI->flat_insn->detail->arm.op_count++;
2761
6.48k
  }
2762
2763
6.48k
  SStream_concat0(O, ", ");
2764
2765
6.48k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2766
2767
6.48k
  if (MI->csh->detail) {
2768
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2769
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2770
6.48k
#ifndef CAPSTONE_DIET
2771
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2772
6.48k
#endif
2773
6.48k
    MI->flat_insn->detail->arm.op_count++;
2774
6.48k
  }
2775
2776
6.48k
  SStream_concat0(O, ", ");
2777
2778
6.48k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2779
2780
6.48k
  if (MI->csh->detail) {
2781
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2782
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2783
6.48k
#ifndef CAPSTONE_DIET
2784
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2785
6.48k
#endif
2786
6.48k
    MI->flat_insn->detail->arm.op_count++;
2787
6.48k
  }
2788
2789
6.48k
  SStream_concat0(O, ", ");
2790
2791
6.48k
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
2792
2793
6.48k
  if (MI->csh->detail) {
2794
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2795
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2796
6.48k
#ifndef CAPSTONE_DIET
2797
6.48k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2798
6.48k
#endif
2799
6.48k
    MI->flat_insn->detail->arm.op_count++;
2800
6.48k
  }
2801
2802
6.48k
  SStream_concat0(O, "}");
2803
2804
6.48k
#ifndef CAPSTONE_DIET
2805
6.48k
  MI->ac_idx++;
2806
6.48k
#endif
2807
6.48k
}
2808
2809
static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2810
168
{
2811
168
#ifndef CAPSTONE_DIET
2812
168
  uint8_t access;
2813
2814
168
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2815
168
#endif
2816
2817
168
  SStream_concat0(O, "{");
2818
2819
168
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2820
2821
168
  if (MI->csh->detail) {
2822
168
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2823
168
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2824
168
#ifndef CAPSTONE_DIET
2825
168
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2826
168
#endif
2827
168
    MI->flat_insn->detail->arm.op_count++;
2828
168
  }
2829
2830
168
  SStream_concat0(O, "[]}");
2831
2832
168
#ifndef CAPSTONE_DIET
2833
168
  MI->ac_idx++;
2834
168
#endif
2835
168
}
2836
2837
static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2838
2.46k
{
2839
2.46k
#ifndef CAPSTONE_DIET
2840
2.46k
  uint8_t access;
2841
2.46k
#endif
2842
2.46k
  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2843
2.46k
  unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);
2844
2.46k
  unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_1);
2845
2846
2.46k
#ifndef CAPSTONE_DIET
2847
2.46k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2848
2.46k
#endif
2849
2850
2.46k
  SStream_concat0(O, "{");
2851
2852
2.46k
  printRegName(MI->csh, O, Reg0);
2853
2854
2.46k
  if (MI->csh->detail) {
2855
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2856
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2857
2.46k
#ifndef CAPSTONE_DIET
2858
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2859
2.46k
#endif
2860
2.46k
    MI->flat_insn->detail->arm.op_count++;
2861
2.46k
  }
2862
2863
2.46k
  SStream_concat0(O, "[], ");
2864
2865
2.46k
  printRegName(MI->csh, O, Reg1);
2866
2867
2.46k
  if (MI->csh->detail) {
2868
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2869
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2870
2.46k
#ifndef CAPSTONE_DIET
2871
2.46k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2872
2.46k
#endif
2873
2.46k
    MI->flat_insn->detail->arm.op_count++;
2874
2.46k
  }
2875
2876
2.46k
  SStream_concat0(O, "[]}");
2877
2878
2.46k
#ifndef CAPSTONE_DIET
2879
2.46k
  MI->ac_idx++;
2880
2.46k
#endif
2881
2.46k
}
2882
2883
static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2884
0
{
2885
0
#ifndef CAPSTONE_DIET
2886
0
  uint8_t access;
2887
2888
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2889
0
#endif
2890
2891
  // Normally, it's not safe to use register enum values directly with
2892
  // addition to get the next register, but for VFP registers, the
2893
  // sort order is guaranteed because they're all of the form D<n>.
2894
0
  SStream_concat0(O, "{");
2895
2896
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2897
2898
0
  if (MI->csh->detail) {
2899
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2900
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2901
0
#ifndef CAPSTONE_DIET
2902
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2903
0
#endif
2904
0
    MI->flat_insn->detail->arm.op_count++;
2905
0
  }
2906
2907
0
  SStream_concat0(O, "[], ");
2908
2909
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2910
2911
0
  if (MI->csh->detail) {
2912
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2913
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2914
0
#ifndef CAPSTONE_DIET
2915
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2916
0
#endif
2917
0
    MI->flat_insn->detail->arm.op_count++;
2918
0
  }
2919
2920
0
  SStream_concat0(O, "[], ");
2921
2922
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2923
2924
0
  if (MI->csh->detail) {
2925
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2926
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2927
0
#ifndef CAPSTONE_DIET
2928
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2929
0
#endif
2930
0
    MI->flat_insn->detail->arm.op_count++;
2931
0
  }
2932
2933
0
  SStream_concat0(O, "[]}");
2934
2935
0
#ifndef CAPSTONE_DIET
2936
0
  MI->ac_idx++;
2937
0
#endif
2938
0
}
2939
2940
static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2941
0
{
2942
0
#ifndef CAPSTONE_DIET
2943
0
  uint8_t access;
2944
2945
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2946
0
#endif
2947
2948
  // Normally, it's not safe to use register enum values directly with
2949
  // addition to get the next register, but for VFP registers, the
2950
  // sort order is guaranteed because they're all of the form D<n>.
2951
0
  SStream_concat0(O, "{");
2952
2953
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2954
2955
0
  if (MI->csh->detail) {
2956
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2957
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2958
0
#ifndef CAPSTONE_DIET
2959
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2960
0
#endif
2961
0
    MI->flat_insn->detail->arm.op_count++;
2962
0
  }
2963
2964
0
  SStream_concat0(O, "[], ");
2965
2966
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2967
2968
0
  if (MI->csh->detail) {
2969
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2970
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2971
0
#ifndef CAPSTONE_DIET
2972
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2973
0
#endif
2974
0
    MI->flat_insn->detail->arm.op_count++;
2975
0
  }
2976
2977
0
  SStream_concat0(O, "[], ");
2978
2979
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2980
2981
0
  if (MI->csh->detail) {
2982
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2983
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2984
0
#ifndef CAPSTONE_DIET
2985
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2986
0
#endif
2987
0
    MI->flat_insn->detail->arm.op_count++;
2988
0
  }
2989
2990
0
  SStream_concat0(O, "[], ");
2991
2992
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
2993
2994
0
  if (MI->csh->detail) {
2995
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2996
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2997
0
#ifndef CAPSTONE_DIET
2998
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2999
0
#endif
3000
0
    MI->flat_insn->detail->arm.op_count++;
3001
0
  }
3002
3003
0
  SStream_concat0(O, "[]}");
3004
3005
0
#ifndef CAPSTONE_DIET
3006
0
  MI->ac_idx++;
3007
0
#endif
3008
0
}
3009
3010
static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
3011
2.52k
{
3012
2.52k
#ifndef CAPSTONE_DIET
3013
2.52k
  uint8_t access;
3014
2.52k
#endif
3015
2.52k
  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3016
2.52k
  unsigned Reg0 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_0);
3017
2.52k
  unsigned Reg1 = MCRegisterInfo_getSubReg(MI->MRI, Reg, ARM_dsub_2);
3018
3019
2.52k
#ifndef CAPSTONE_DIET
3020
2.52k
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3021
2.52k
#endif
3022
3023
2.52k
  SStream_concat0(O, "{");
3024
3025
2.52k
  printRegName(MI->csh, O, Reg0);
3026
3027
2.52k
  if (MI->csh->detail) {
3028
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3029
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
3030
2.52k
#ifndef CAPSTONE_DIET
3031
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3032
2.52k
#endif
3033
2.52k
    MI->flat_insn->detail->arm.op_count++;
3034
2.52k
  }
3035
3036
2.52k
  SStream_concat0(O, "[], ");
3037
3038
2.52k
  printRegName(MI->csh, O, Reg1);
3039
3040
2.52k
  if (MI->csh->detail) {
3041
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3042
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
3043
2.52k
#ifndef CAPSTONE_DIET
3044
2.52k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3045
2.52k
#endif
3046
2.52k
    MI->flat_insn->detail->arm.op_count++;
3047
2.52k
  }
3048
3049
2.52k
  SStream_concat0(O, "[]}");
3050
3051
2.52k
#ifndef CAPSTONE_DIET
3052
2.52k
  MI->ac_idx++;
3053
2.52k
#endif
3054
2.52k
}
3055
3056
static void printVectorListThreeSpacedAllLanes(MCInst *MI,
3057
    unsigned OpNum, SStream *O)
3058
0
{
3059
0
#ifndef CAPSTONE_DIET
3060
0
  uint8_t access;
3061
3062
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3063
0
#endif
3064
3065
  // Normally, it's not safe to use register enum values directly with
3066
  // addition to get the next register, but for VFP registers, the
3067
  // sort order is guaranteed because they're all of the form D<n>.
3068
0
  SStream_concat0(O, "{");
3069
3070
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
3071
3072
0
  if (MI->csh->detail) {
3073
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3074
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3075
0
#ifndef CAPSTONE_DIET
3076
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3077
0
#endif
3078
0
    MI->flat_insn->detail->arm.op_count++;
3079
0
  }
3080
3081
0
  SStream_concat0(O, "[], ");
3082
3083
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
3084
3085
0
  if (MI->csh->detail) {
3086
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3087
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
3088
0
#ifndef CAPSTONE_DIET
3089
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3090
0
#endif
3091
0
    MI->flat_insn->detail->arm.op_count++;
3092
0
  }
3093
3094
0
  SStream_concat0(O, "[], ");
3095
3096
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3097
3098
0
  if (MI->csh->detail) {
3099
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3100
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3101
0
#ifndef CAPSTONE_DIET
3102
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3103
0
#endif
3104
0
    MI->flat_insn->detail->arm.op_count++;
3105
0
  }
3106
3107
0
  SStream_concat0(O, "[]}");
3108
3109
0
#ifndef CAPSTONE_DIET
3110
0
  MI->ac_idx++;
3111
0
#endif
3112
0
}
3113
3114
static void printVectorListFourSpacedAllLanes(MCInst *MI,
3115
    unsigned OpNum, SStream *O)
3116
0
{
3117
0
#ifndef CAPSTONE_DIET
3118
0
  uint8_t access;
3119
3120
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3121
0
#endif
3122
3123
  // Normally, it's not safe to use register enum values directly with
3124
  // addition to get the next register, but for VFP registers, the
3125
  // sort order is guaranteed because they're all of the form D<n>.
3126
0
  SStream_concat0(O, "{");
3127
3128
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
3129
3130
0
  if (MI->csh->detail) {
3131
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3132
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3133
0
#ifndef CAPSTONE_DIET
3134
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3135
0
#endif
3136
0
    MI->flat_insn->detail->arm.op_count++;
3137
0
  }
3138
3139
0
  SStream_concat0(O, "[], ");
3140
3141
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
3142
3143
0
  if (MI->csh->detail) {
3144
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3145
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
3146
0
#ifndef CAPSTONE_DIET
3147
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3148
0
#endif
3149
0
    MI->flat_insn->detail->arm.op_count++;
3150
0
  }
3151
3152
0
  SStream_concat0(O, "[], ");
3153
3154
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3155
3156
0
  if (MI->csh->detail) {
3157
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3158
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3159
0
#ifndef CAPSTONE_DIET
3160
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3161
0
#endif
3162
0
    MI->flat_insn->detail->arm.op_count++;
3163
0
  }
3164
3165
0
  SStream_concat0(O, "[], ");
3166
3167
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
3168
3169
0
  if (MI->csh->detail) {
3170
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3171
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
3172
0
#ifndef CAPSTONE_DIET
3173
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3174
0
#endif
3175
0
    MI->flat_insn->detail->arm.op_count++;
3176
0
  }
3177
3178
0
  SStream_concat0(O, "[]}");
3179
3180
0
#ifndef CAPSTONE_DIET
3181
0
  MI->ac_idx++;
3182
0
#endif
3183
0
}
3184
3185
static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O)
3186
0
{
3187
0
#ifndef CAPSTONE_DIET
3188
0
  uint8_t access;
3189
3190
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3191
0
#endif
3192
3193
  // Normally, it's not safe to use register enum values directly with
3194
  // addition to get the next register, but for VFP registers, the
3195
  // sort order is guaranteed because they're all of the form D<n>.
3196
0
  SStream_concat0(O, "{");
3197
3198
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
3199
3200
0
  if (MI->csh->detail) {
3201
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3202
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3203
0
#ifndef CAPSTONE_DIET
3204
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3205
0
#endif
3206
0
    MI->flat_insn->detail->arm.op_count++;
3207
0
  }
3208
3209
0
  SStream_concat0(O, ", ");
3210
3211
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
3212
3213
0
  if (MI->csh->detail) {
3214
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3215
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
3216
0
#ifndef CAPSTONE_DIET
3217
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3218
0
#endif
3219
0
    MI->flat_insn->detail->arm.op_count++;
3220
0
  }
3221
3222
0
  SStream_concat0(O, ", ");
3223
3224
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3225
3226
0
  if (MI->csh->detail) {
3227
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3228
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3229
0
#ifndef CAPSTONE_DIET
3230
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3231
0
#endif
3232
0
    MI->flat_insn->detail->arm.op_count++;
3233
0
  }
3234
3235
0
  SStream_concat0(O, "}");
3236
3237
0
#ifndef CAPSTONE_DIET
3238
0
  MI->ac_idx++;
3239
0
#endif
3240
0
}
3241
3242
static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O)
3243
0
{
3244
0
#ifndef CAPSTONE_DIET
3245
0
  uint8_t access;
3246
3247
0
  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3248
0
#endif
3249
3250
  // Normally, it's not safe to use register enum values directly with
3251
  // addition to get the next register, but for VFP registers, the
3252
  // sort order is guaranteed because they're all of the form D<n>.
3253
0
  SStream_concat0(O, "{");
3254
3255
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
3256
3257
0
  if (MI->csh->detail) {
3258
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3259
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3260
0
#ifndef CAPSTONE_DIET
3261
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3262
0
#endif
3263
0
    MI->flat_insn->detail->arm.op_count++;
3264
0
  }
3265
3266
0
  SStream_concat0(O, ", ");
3267
3268
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
3269
3270
0
  if (MI->csh->detail) {
3271
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3272
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
3273
0
#ifndef CAPSTONE_DIET
3274
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3275
0
#endif
3276
0
    MI->flat_insn->detail->arm.op_count++;
3277
0
  }
3278
3279
0
  SStream_concat0(O, ", ");
3280
3281
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3282
3283
0
  if (MI->csh->detail) {
3284
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3285
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3286
0
#ifndef CAPSTONE_DIET
3287
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3288
0
#endif
3289
0
    MI->flat_insn->detail->arm.op_count++;
3290
0
  }
3291
3292
0
  SStream_concat0(O, ", ");
3293
3294
0
  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
3295
3296
0
  if (MI->csh->detail) {
3297
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3298
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
3299
0
#ifndef CAPSTONE_DIET
3300
0
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3301
0
#endif
3302
0
    MI->flat_insn->detail->arm.op_count++;
3303
0
  }
3304
3305
0
  SStream_concat0(O, "}");
3306
3307
0
#ifndef CAPSTONE_DIET
3308
0
  MI->ac_idx++;
3309
0
#endif
3310
0
}
3311
3312
static void printComplexRotationOp(MCInst *MI, unsigned OpNo, SStream *O, int64_t Angle, int64_t Remainder)
3313
2.25k
{
3314
2.25k
  unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
3315
2.25k
  unsigned tmp = (unsigned)((Val * Angle) + Remainder);
3316
3317
2.25k
  printUInt32Bang(O, tmp);
3318
2.25k
  if (MI->csh->detail) {
3319
2.25k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
3320
2.25k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
3321
2.25k
    MI->flat_insn->detail->arm.op_count++;
3322
2.25k
  }
3323
2.25k
}
3324
3325
void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd)
3326
33.1k
{
3327
33.1k
  if (MI->csh->detail) {
3328
33.1k
    MI->flat_insn->detail->arm.vector_data = vd;
3329
33.1k
  }
3330
33.1k
}
3331
3332
void ARM_addVectorDataSize(MCInst *MI, int size)
3333
69.0k
{
3334
69.0k
  if (MI->csh->detail) {
3335
69.0k
    MI->flat_insn->detail->arm.vector_size = size;
3336
69.0k
  }
3337
69.0k
}
3338
3339
void ARM_addReg(MCInst *MI, int reg)
3340
4.32k
{
3341
4.32k
  if (MI->csh->detail) {
3342
4.32k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3343
4.32k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
3344
4.32k
    MI->flat_insn->detail->arm.op_count++;
3345
4.32k
  }
3346
4.32k
}
3347
3348
void ARM_addUserMode(MCInst *MI)
3349
5.01k
{
3350
5.01k
  if (MI->csh->detail) {
3351
5.01k
    MI->flat_insn->detail->arm.usermode = true;
3352
5.01k
  }
3353
5.01k
}
3354
3355
void ARM_addSysReg(MCInst *MI, arm_sysreg reg)
3356
8.98k
{
3357
8.98k
  if (MI->csh->detail) {
3358
8.98k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SYSREG;
3359
8.98k
    MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
3360
8.98k
    MI->flat_insn->detail->arm.op_count++;
3361
8.98k
  }
3362
8.98k
}
3363
3364
#endif