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