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