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