Coverage Report

Created: 2025-06-13 06:15

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