blob: 148c9fe1a2ce48d435efa87ec4511eeda6822a60 [file] [log] [blame]
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001//===-- 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
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +080014/* Capstone Disassembly Engine */
15/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
16
17#ifdef CAPSTONE_HAS_ARM
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080018
19#include <stdio.h> // DEBUG
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080020#include <stdlib.h>
21#include <string.h>
Cr4sh9d606072015-03-29 18:29:06 +080022#include "../../myinttypes.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080023
24#include "ARMInstPrinter.h"
25#include "ARMAddressingModes.h"
26#include "ARMBaseInfo.h"
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +080027#include "ARMDisassembler.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080028#include "../../MCInst.h"
29#include "../../SStream.h"
30#include "../../MCRegisterInfo.h"
31#include "../../utils.h"
Nguyen Anh Quynh37327252014-01-20 09:47:21 +080032#include "ARMMapping.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080033
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +080034#define GET_SUBTARGETINFO_ENUM
35#include "ARMGenSubtargetInfo.inc"
36
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +080037static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080038
39// Autogenerated by tblgen.
40static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
41static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
42static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
43static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
44
45static void printAddrModeTBB(MCInst *MI, unsigned OpNum, SStream *O);
46static void printAddrModeTBH(MCInst *MI, unsigned OpNum, SStream *O);
47static void printAddrMode2Operand(MCInst *MI, unsigned OpNum, SStream *O);
48static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);
49static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
50static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
51static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080052static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);
53static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);
54static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
55static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
56static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
57static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O);
58static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O);
59static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
60
61static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
62static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O);
63static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
64static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
65static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
66static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned);
67static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
68static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O);
69static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O);
70static void printThumbAddrModeRROperand(MCInst *MI, unsigned OpNum, SStream *O);
71static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale);
72static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned OpNum, SStream *O);
73static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned OpNum, SStream *O);
74static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned OpNum, SStream *O);
75static void printThumbAddrModeSPOperand(MCInst *MI, unsigned OpNum, SStream *O);
76static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O);
77static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
78static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
79static void printT2AddrModeImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
80static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
81static void printT2AddrModeImm8OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
82static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
83static void printT2AddrModeSoRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
84static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O);
85static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O);
86static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O);
87static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O);
88static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
89static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
90static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O);
91static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O);
92static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O);
93static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O);
94static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O);
95static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O);
96static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
97static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
98static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O);
99static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
100static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
101static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O);
102static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O);
103static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O);
104static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O);
105static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O);
106static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
107static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
108static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O);
109static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O);
110static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
111static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
112static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
113static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
114static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
115static void printVectorListThreeSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
116static void printVectorListFourSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
117static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O);
118static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O);
119
120static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);
121
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800122static void set_mem_access(MCInst *MI, bool status)
123{
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800124 if (MI->csh->detail != CS_OPT_ON)
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800125 return;
126
Nguyen Anh Quynh19b0de32013-12-31 22:40:04 +0800127 MI->csh->doing_mem = status;
128 if (status) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700129 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
130 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_INVALID;
131 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
132 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
133 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800134 } else {
135 // done, create the next operand slot
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700136 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800137 }
138}
139
Nguyen Anh Quynhebe24432014-06-17 13:56:01 +0800140static void op_addImm(MCInst *MI, int v)
141{
Nguyen Anh Quynh73eb5d52014-06-17 18:08:29 +0800142 if (MI->csh->detail) {
143 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
144 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;
145 MI->flat_insn->detail->arm.op_count++;
146 }
Nguyen Anh Quynhebe24432014-06-17 13:56:01 +0800147}
148
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800149#define GET_INSTRINFO_ENUM
150#include "ARMGenInstrInfo.inc"
151
152//#define PRINT_ALIAS_INSTR
153#include "ARMGenAsmWriter.inc"
154
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800155void ARM_getRegName(cs_struct *handle, int value)
156{
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800157 if (value == CS_OPT_SYNTAX_NOREGNAME) {
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800158 handle->get_regname = getRegisterName2;
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800159 handle->reg_name = ARM_reg_name2;;
160 } else {
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800161 handle->get_regname = getRegisterName;
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800162 handle->reg_name = ARM_reg_name;;
163 }
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800164}
165
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800166/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
167///
168/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
169static unsigned translateShiftImm(unsigned imm)
170{
171 // lsr #32 and asr #32 exist, but should be encoded as a 0.
172 //assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
173 if (imm == 0)
174 return 32;
175 return imm;
176}
177
178/// Prints the shift value with an immediate value.
Nguyen Anh Quynh8c1104b2014-06-10 00:39:06 +0700179static void printRegImmShift(MCInst *MI, SStream *O, ARM_AM_ShiftOpc ShOpc, unsigned ShImm)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800180{
181 if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
182 return;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700183 SStream_concat0(O, ", ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800184
185 //assert (!(ShOpc == ARM_AM_ror && !ShImm) && "Cannot have ror #0");
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700186 SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));
Nguyen Anh Quynhc70442e2014-06-01 11:35:34 +0700187 if (MI->csh->detail) {
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800188 if (MI->csh->doing_mem)
189 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)ShOpc;
190 else
191 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = (arm_shifter)ShOpc;
Nguyen Anh Quynhc70442e2014-06-01 11:35:34 +0700192 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800193
194 if (ShOpc != ARM_AM_rrx) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700195 SStream_concat0(O, " ");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800196 SStream_concat(O, "#%u", translateShiftImm(ShImm));
Nguyen Anh Quynhc70442e2014-06-01 11:35:34 +0700197 if (MI->csh->detail) {
198 if (MI->csh->doing_mem)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700199 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = translateShiftImm(ShImm);
Nguyen Anh Quynhc70442e2014-06-01 11:35:34 +0700200 else
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700201 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = translateShiftImm(ShImm);
Nguyen Anh Quynhc70442e2014-06-01 11:35:34 +0700202 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800203 }
204}
205
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800206static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800207{
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800208#ifndef CAPSTONE_DIET
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700209 SStream_concat0(OS, h->get_regname(RegNo));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800210#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800211}
212
213static name_map insn_update_flgs[] = {
214 { ARM_INS_CMN, "cmn" },
215 { ARM_INS_CMP, "cmp" },
216 { ARM_INS_TEQ, "teq" },
217 { ARM_INS_TST, "tst" },
218
219 { ARM_INS_ADC, "adcs" },
220 { ARM_INS_ADD, "adds" },
221 { ARM_INS_AND, "ands" },
222 { ARM_INS_ASR, "asrs" },
223 { ARM_INS_BIC, "bics" },
224 { ARM_INS_EOR, "eors" },
225 { ARM_INS_LSL, "lsls" },
226 { ARM_INS_LSR, "lsrs" },
227 { ARM_INS_MLA, "mlas" },
228 { ARM_INS_MOV, "movs" },
229 { ARM_INS_MUL, "muls" },
230 { ARM_INS_MVN, "mvns" },
231 { ARM_INS_ORN, "orns" },
232 { ARM_INS_ORR, "orrs" },
233 { ARM_INS_ROR, "rors" },
234 { ARM_INS_RRX, "rrxs" },
235 { ARM_INS_RSB, "rsbs" },
236 { ARM_INS_RSC, "rscs" },
237 { ARM_INS_SBC, "sbcs" },
238 { ARM_INS_SMLAL, "smlals" },
239 { ARM_INS_SMULL, "smulls" },
240 { ARM_INS_SUB, "subs" },
241 { ARM_INS_UMLAL, "umlals" },
242 { ARM_INS_UMULL, "umulls" },
243};
244
Nguyen Anh Quynh64564812014-05-19 16:46:31 +0800245void ARM_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800246{
Nguyen Anh Quynh5ef633c2014-01-04 10:41:17 +0800247 if (((cs_struct *)ud)->detail != CS_OPT_ON)
248 return;
249
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800250 // check if this insn requests write-back
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +0800251 if (mci->writeback || (strrchr(insn_asm, '!')) != NULL) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800252 insn->detail->arm.writeback = true;
Nguyen Anh Quynh7bbb4332015-01-21 12:16:15 +0800253 } else if (mci->csh->mode & CS_MODE_THUMB) {
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +0800254 // handle some special instructions with writeback
255 switch(mci->Opcode) {
256 default:
257 break;
258 case ARM_t2LDC2L_PRE:
259 case ARM_t2LDC2_PRE:
260 case ARM_t2LDCL_PRE:
261 case ARM_t2LDC_PRE:
262
263 case ARM_t2LDRB_PRE:
264 case ARM_t2LDRD_PRE:
265 case ARM_t2LDRH_PRE:
266 case ARM_t2LDRSB_PRE:
267 case ARM_t2LDRSH_PRE:
268 case ARM_t2LDR_PRE:
269
270 case ARM_t2STC2L_PRE:
271 case ARM_t2STC2_PRE:
272 case ARM_t2STCL_PRE:
273 case ARM_t2STC_PRE:
274
275 case ARM_t2STRB_PRE:
276 case ARM_t2STRD_PRE:
277 case ARM_t2STRH_PRE:
278 case ARM_t2STR_PRE:
279
280 case ARM_t2LDC2L_POST:
281 case ARM_t2LDC2_POST:
282 case ARM_t2LDCL_POST:
283 case ARM_t2LDC_POST:
284
285 case ARM_t2LDRB_POST:
286 case ARM_t2LDRD_POST:
287 case ARM_t2LDRH_POST:
288 case ARM_t2LDRSB_POST:
289 case ARM_t2LDRSH_POST:
290 case ARM_t2LDR_POST:
291
292 case ARM_t2STC2L_POST:
293 case ARM_t2STC2_POST:
294 case ARM_t2STCL_POST:
295 case ARM_t2STC_POST:
296
297 case ARM_t2STRB_POST:
298 case ARM_t2STRD_POST:
299 case ARM_t2STRH_POST:
300 case ARM_t2STR_POST:
301 insn->detail->arm.writeback = true;
302 break;
303 }
304 } else { // ARM mode
305 // handle some special instructions with writeback
306 switch(mci->Opcode) {
307 default:
308 break;
309 case ARM_LDC2L_PRE:
310 case ARM_LDC2_PRE:
311 case ARM_LDCL_PRE:
312 case ARM_LDC_PRE:
313
314 case ARM_LDRD_PRE:
315 case ARM_LDRH_PRE:
316 case ARM_LDRSB_PRE:
317 case ARM_LDRSH_PRE:
318
319 case ARM_STC2L_PRE:
320 case ARM_STC2_PRE:
321 case ARM_STCL_PRE:
322 case ARM_STC_PRE:
323
324 case ARM_STRD_PRE:
325 case ARM_STRH_PRE:
326
327 case ARM_LDC2L_POST:
328 case ARM_LDC2_POST:
329 case ARM_LDCL_POST:
330 case ARM_LDC_POST:
331
332 case ARM_LDRBT_POST:
333 case ARM_LDRD_POST:
334 case ARM_LDRH_POST:
335 case ARM_LDRSB_POST:
336 case ARM_LDRSH_POST:
337
338 case ARM_STC2L_POST:
339 case ARM_STC2_POST:
340 case ARM_STCL_POST:
341 case ARM_STC_POST:
342
343 case ARM_STRBT_POST:
344 case ARM_STRD_POST:
345 case ARM_STRH_POST:
Nguyen Anh Quynh9426ad52015-01-21 12:25:36 +0800346
347 case ARM_LDRB_POST_IMM:
348 case ARM_LDR_POST_IMM:
349 case ARM_STRB_POST_IMM:
350 case ARM_STR_POST_IMM:
351
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +0800352 insn->detail->arm.writeback = true;
353 break;
354 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800355 }
356
357 // check if this insn requests update flags
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800358 if (insn->detail->arm.update_flags == false) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800359 // some insn still update flags, regardless of tabgen info
Nguyen Anh Quynhf6c7cbc2014-03-12 12:50:54 +0800360 unsigned int i, j;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800361
362 for (i = 0; i < ARR_SIZE(insn_update_flgs); i++) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800363 if (insn->id == insn_update_flgs[i].id &&
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800364 !strncmp(insn_asm, insn_update_flgs[i].name,
365 strlen(insn_update_flgs[i].name))) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800366 insn->detail->arm.update_flags = true;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800367 // we have to update regs_write array as well
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800368 for (j = 0; j < ARR_SIZE(insn->detail->regs_write); j++) {
369 if (insn->detail->regs_write[j] == 0) {
370 insn->detail->regs_write[j] = ARM_REG_CPSR;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800371 break;
372 }
373 }
374 break;
375 }
376 }
377 }
Nguyen Anh Quynh48b6cb42014-06-01 09:45:19 +0700378
379 // instruction should not have invalid CC
380 if (insn->detail->arm.cc == ARM_CC_INVALID) {
381 insn->detail->arm.cc = ARM_CC_AL;
382 }
383
Nguyen Anh Quynh6eb55cf2014-06-01 10:03:14 +0700384 // manual fix for some special instructions
385 // printf(">>> id: %u, mcid: %u\n", insn->id, mci->Opcode);
386 switch(mci->Opcode) {
387 default:
388 break;
389 case ARM_MOVPCLR:
390 insn->detail->arm.operands[0].type = ARM_OP_REG;
391 insn->detail->arm.operands[0].reg = ARM_REG_PC;
392 insn->detail->arm.operands[1].type = ARM_OP_REG;
393 insn->detail->arm.operands[1].reg = ARM_REG_LR;
394 insn->detail->arm.op_count = 2;
395 break;
396 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800397}
398
399void ARM_printInst(MCInst *MI, SStream *O, void *Info)
400{
401 MCRegisterInfo *MRI = (MCRegisterInfo *)Info;
402
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800403 unsigned Opcode = MCInst_getOpcode(MI), tmp, i, pubOpcode;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800404
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800405 switch(Opcode) {
406 // Check for HINT instructions w/ canonical names.
407 case ARM_HINT:
408 case ARM_tHINT:
409 case ARM_t2HINT:
410 switch (MCOperand_getImm(MCInst_getOperand(MI, 0))) {
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800411 case 0: SStream_concat0(O, "nop"); pubOpcode = ARM_INS_NOP; break;
412 case 1: SStream_concat0(O, "yield"); pubOpcode = ARM_INS_YIELD; break;
413 case 2: SStream_concat0(O, "wfe"); pubOpcode = ARM_INS_WFE; break;
414 case 3: SStream_concat0(O, "wfi"); pubOpcode = ARM_INS_WFI; break;
415 case 4: SStream_concat0(O, "sev"); pubOpcode = ARM_INS_SEV; break;
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800416 case 5:
Nguyen Anh Quynh2593e222014-11-10 16:35:38 +0800417 if ((ARM_getFeatureBits(MI->csh->mode) & ARM_HasV8Ops)) {
418 SStream_concat0(O, "sevl");
419 pubOpcode = ARM_INS_SEVL;
420 break;
421 }
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800422 // Fallthrough for non-v8
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800423 default:
424 // Anything else should just print normally.
425 printInstruction(MI, O, MRI);
426 return;
427 }
428 printPredicateOperand(MI, 1, O);
429 if (Opcode == ARM_t2HINT)
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800430 SStream_concat0(O, ".w");
431
432 MCInst_setOpcodePub(MI, pubOpcode);
433
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800434 return;
435
436 // Check for MOVs and print canonical forms, instead.
437 case ARM_MOVsr: {
438 // FIXME: Thumb variants?
439 MCOperand *Dst = MCInst_getOperand(MI, 0);
440 MCOperand *MO1 = MCInst_getOperand(MI, 1);
441 MCOperand *MO2 = MCInst_getOperand(MI, 2);
442 MCOperand *MO3 = MCInst_getOperand(MI, 3);
443
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700444 SStream_concat0(O, ARM_AM_getShiftOpcStr(ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3))));
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800445 printSBitModifierOperand(MI, 6, O);
446 printPredicateOperand(MI, 4, O);
447
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700448 SStream_concat0(O, "\t");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800449 printRegName(MI->csh, O, MCOperand_getReg(Dst));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800450 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700451 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
452 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
453 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800454 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800455
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700456 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800457 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800458
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800459 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700460 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
461 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
462 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800463 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800464
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700465 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800466 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800467 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700468 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
469 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);
470 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800471 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800472 //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
473 return;
474 }
475
476 case ARM_MOVsi: {
477 // FIXME: Thumb variants?
478 MCOperand *Dst = MCInst_getOperand(MI, 0);
479 MCOperand *MO1 = MCInst_getOperand(MI, 1);
480 MCOperand *MO2 = MCInst_getOperand(MI, 2);
481
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700482 SStream_concat0(O, ARM_AM_getShiftOpcStr(ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2))));
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800483 printSBitModifierOperand(MI, 5, O);
484 printPredicateOperand(MI, 3, O);
485
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700486 SStream_concat0(O, "\t");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800487 printRegName(MI->csh, O, MCOperand_getReg(Dst));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800488 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700489 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
490 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
491 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800492 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800493
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700494 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800495 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800496 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700497 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
498 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
499 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800500 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800501
Alex Ionescu46018db2014-01-22 09:45:00 -0800502 if (ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)) == ARM_AM_rrx) {
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800503 //printAnnotation(O, Annot);
504 return;
505 }
506
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700507 SStream_concat0(O, ", ");
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100508 tmp = translateShiftImm(getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800509 if (tmp > HEX_THRESHOLD)
510 SStream_concat(O, "#0x%x", tmp);
511 else
512 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800513 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700514 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type =
Alex Ionescu46018db2014-01-22 09:45:00 -0800515 (arm_shifter)ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700516 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800517 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800518 return;
519 }
520
521 // A8.6.123 PUSH
522 case ARM_STMDB_UPD:
523 case ARM_t2STMDB_UPD:
524 if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
525 MCInst_getNumOperands(MI) > 5) {
526 // Should only print PUSH if there are at least two registers in the list.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700527 SStream_concat0(O, "push");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800528 MCInst_setOpcodePub(MI, ARM_INS_PUSH);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800529 printPredicateOperand(MI, 2, O);
530 if (Opcode == ARM_t2STMDB_UPD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700531 SStream_concat0(O, ".w");
532 SStream_concat0(O, "\t");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800533 printRegisterList(MI, 4, O);
534 return;
535 }
536 break;
537
538 case ARM_STR_PRE_IMM:
539 if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&
540 MCOperand_getImm(MCInst_getOperand(MI, 3)) == -4) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700541 SStream_concat0(O, "push");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800542 MCInst_setOpcodePub(MI, ARM_INS_PUSH);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800543 printPredicateOperand(MI, 4, O);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700544 SStream_concat0(O, "\t{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800545 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 1)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800546 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700547 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
548 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));
549 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800550 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700551 SStream_concat0(O, "}");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800552 return;
553 }
554 break;
555
556 // A8.6.122 POP
557 case ARM_LDMIA_UPD:
558 case ARM_t2LDMIA_UPD:
559 if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
560 MCInst_getNumOperands(MI) > 5) {
561 // Should only print POP if there are at least two registers in the list.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700562 SStream_concat0(O, "pop");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800563 MCInst_setOpcodePub(MI, ARM_INS_POP);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800564 printPredicateOperand(MI, 2, O);
565 if (Opcode == ARM_t2LDMIA_UPD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700566 SStream_concat0(O, ".w");
567 SStream_concat0(O, "\t");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800568 printRegisterList(MI, 4, O);
569 return;
570 }
571 break;
572
573 case ARM_LDR_POST_IMM:
Nguyen Anh Quynh3caf8372014-11-27 14:34:40 +0800574 if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP) {
575 MCOperand *MO2 = MCInst_getOperand(MI, 4);
576 if ((getAM2Op((unsigned int)MCOperand_getImm(MO2)) == ARM_AM_add &&
577 getAM2Offset((unsigned int)MCOperand_getImm(MO2)) == 4) ||
578 MCOperand_getImm(MO2) == 4) {
579 SStream_concat0(O, "pop");
580 MCInst_setOpcodePub(MI, ARM_INS_POP);
581 printPredicateOperand(MI, 5, O);
582 SStream_concat0(O, "\t{");
583 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 0)));
584 if (MI->csh->detail) {
585 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
586 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
587 MI->flat_insn->detail->arm.op_count++;
588 }
589 SStream_concat0(O, "}");
590 return;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800591 }
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800592 }
593 break;
594
595 // A8.6.355 VPUSH
596 case ARM_VSTMSDB_UPD:
597 case ARM_VSTMDDB_UPD:
598 if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700599 SStream_concat0(O, "vpush");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800600 MCInst_setOpcodePub(MI, ARM_INS_VPUSH);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800601 printPredicateOperand(MI, 2, O);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700602 SStream_concat0(O, "\t");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800603 printRegisterList(MI, 4, O);
604 return;
605 }
606 break;
607
608 // A8.6.354 VPOP
609 case ARM_VLDMSIA_UPD:
610 case ARM_VLDMDIA_UPD:
611 if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700612 SStream_concat0(O, "vpop");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800613 MCInst_setOpcodePub(MI, ARM_INS_VPOP);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800614 printPredicateOperand(MI, 2, O);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700615 SStream_concat0(O, "\t");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800616 printRegisterList(MI, 4, O);
617 return;
618 }
619 break;
620
621 case ARM_tLDMIA: {
Nguyen Anh Quynh8cdafda2014-11-11 22:30:30 +0800622 bool Writeback = true;
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800623 unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, 0));
624 unsigned i;
625 for (i = 3; i < MCInst_getNumOperands(MI); ++i) {
626 if (MCOperand_getReg(MCInst_getOperand(MI, i)) == BaseReg)
627 Writeback = false;
628 }
629
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700630 SStream_concat0(O, "ldm");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +0800631 MCInst_setOpcodePub(MI, ARM_INS_LDM);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800632
633 printPredicateOperand(MI, 1, O);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700634 SStream_concat0(O, "\t");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800635 printRegName(MI->csh, O, BaseReg);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800636 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700637 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
638 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg;
639 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800640 }
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +0800641 if (Writeback) {
642 MI->writeback = true;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700643 SStream_concat0(O, "!");
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +0800644 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700645 SStream_concat0(O, ", ");
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800646 printRegisterList(MI, 3, O);
647 return;
648 }
649
650 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
651 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
652 // a single GPRPair reg operand is used in the .td file to replace the two
653 // GPRs. However, when decoding them, the two GRPs cannot be automatically
654 // expressed as a GPRPair, so we have to manually merge them.
655 // FIXME: We would really like to be able to tablegen'erate this.
656 case ARM_LDREXD:
657 case ARM_STREXD:
658 case ARM_LDAEXD:
659 case ARM_STLEXD: {
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800660 MCRegisterClass* MRC = MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);
661 bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800662
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800663 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, isStore ? 1 : 0));
664 if (MCRegisterClass_contains(MRC, Reg)) {
665 MCInst NewMI;
Nguyen Anh Quynh5e2e6602014-05-30 17:43:36 +0800666
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800667 MCInst_Init(&NewMI);
668 MCInst_setOpcode(&NewMI, Opcode);
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800669
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800670 if (isStore)
671 MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, 0));
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800672
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800673 MCOperand_CreateReg0(&NewMI, MCRegisterInfo_getMatchingSuperReg(MRI, Reg, ARM_gsub_0,
674 MCRegisterInfo_getRegClass(MRI, ARM_GPRPairRegClassID)));
Nguyen Anh Quynh96787052014-06-10 13:59:55 +0700675
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800676 // Copy the rest operands into NewMI.
677 for(i = isStore ? 3 : 2; i < MCInst_getNumOperands(MI); ++i)
678 MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, i));
Nguyen Anh Quynh96787052014-06-10 13:59:55 +0700679
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800680 printInstruction(&NewMI, O, MRI);
681 return;
Nguyen Anh Quynh173ed2b2013-12-01 22:19:27 +0800682 }
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800683 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800684 }
685
686 //if (printAliasInstr(MI, O, MRI))
687 // printInstruction(MI, O, MRI);
688 printInstruction(MI, O, MRI);
689}
690
691static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
692{
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +0800693 int32_t imm;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800694 MCOperand *Op = MCInst_getOperand(MI, OpNo);
695 if (MCOperand_isReg(Op)) {
696 unsigned Reg = MCOperand_getReg(Op);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800697 printRegName(MI->csh, O, Reg);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800698 if (MI->csh->detail) {
Nguyen Anh Quynh19b0de32013-12-31 22:40:04 +0800699 if (MI->csh->doing_mem) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700700 if (MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base == ARM_REG_INVALID)
701 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = Reg;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800702 else
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700703 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = Reg;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800704 } else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700705 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
706 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
707 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800708 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800709 }
710 } else if (MCOperand_isImm(Op)) {
Nguyen Anh Quynh0c235e12014-07-31 21:16:54 +0800711 unsigned int opc = MCInst_getOpcode(MI);
flyingsymbols298d4132014-06-30 01:45:40 -0400712
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100713 imm = (int32_t)MCOperand_getImm(Op);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800714
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800715 // relative branch only has relative offset, so we have to update it
716 // to reflect absolute address.
717 // Note: in ARM, PC is always 2 instructions ahead, so we have to
718 // add 8 in ARM mode, or 4 in Thumb mode
Nguyen Anh Quynhbc80b3d2014-05-09 17:31:41 +0800719 // printf(">> opcode: %u\n", MCInst_getOpcode(MI));
flyingsymbols298d4132014-06-30 01:45:40 -0400720 if (ARM_rel_branch(MI->csh, opc)) {
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800721 // only do this for relative branch
flyingsymbols298d4132014-06-30 01:45:40 -0400722 if (MI->csh->mode & CS_MODE_THUMB) {
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800723 imm += (int32_t)MI->address + 4;
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800724 if (ARM_blx_to_arm_mode(MI->csh, opc)) {
Nguyen Anh Quynh0c235e12014-07-31 21:16:54 +0800725 // here need to align down to the nearest 4-byte address
flyingsymbols298d4132014-06-30 01:45:40 -0400726#define _ALIGN_DOWN(v, align_width) ((v/align_width)*align_width)
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800727 imm = _ALIGN_DOWN(imm, 4);
flyingsymbols298d4132014-06-30 01:45:40 -0400728#undef _ALIGN_DOWN
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800729 }
730 } else {
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800731 imm += (int32_t)MI->address + 8;
Nguyen Anh Quynh26dfbc62014-07-31 18:24:51 +0800732 }
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800733
734 if (imm >= 0) {
735 if (imm > HEX_THRESHOLD)
736 SStream_concat(O, "#0x%x", imm);
737 else
738 SStream_concat(O, "#%u", imm);
739 } else {
Nguyen Anh Quynh4e876752014-09-23 16:49:12 +0800740 SStream_concat(O, "#0x%x", imm);
Nguyen Anh Quynh79e1dcb2014-05-07 14:12:50 +0800741 }
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +0800742 } else {
Nguyen Anh Quynh278e7272014-11-11 12:50:43 +0800743 switch(MI->flat_insn->id) {
744 default:
745 if (imm >= 0) {
746 if (imm > HEX_THRESHOLD)
747 SStream_concat(O, "#0x%x", imm);
748 else
749 SStream_concat(O, "#%u", imm);
750 } else {
751 if (imm < -HEX_THRESHOLD)
752 SStream_concat(O, "#-0x%x", -imm);
753 else
754 SStream_concat(O, "#-%u", -imm);
755 }
756 break;
757 case ARM_INS_AND:
758 case ARM_INS_ORR:
759 case ARM_INS_EOR:
760 case ARM_INS_BIC:
Nguyen Anh Quynha2934a72014-11-25 21:02:18 +0800761 case ARM_INS_MVN:
Nguyen Anh Quynh278e7272014-11-11 12:50:43 +0800762 // do not print number in negative form
763 if (imm >= 0 && imm <= HEX_THRESHOLD)
764 SStream_concat(O, "#%u", imm);
765 else
766 SStream_concat(O, "#0x%x", imm);
767 break;
768 }
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +0800769 }
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800770
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800771 if (MI->csh->detail) {
Nguyen Anh Quynh19b0de32013-12-31 22:40:04 +0800772 if (MI->csh->doing_mem)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700773 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = imm;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800774 else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700775 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
776 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
777 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800778 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800779 }
780 }
781}
782
783static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O)
784{
785 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +0800786 int32_t OffImm;
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800787 bool isSub;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700788 SStream_concat0(O, "[pc, ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800789
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100790 OffImm = (int32_t)MCOperand_getImm(MO1);
791 isSub = OffImm < 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800792
793 // Special value for #-0. All others are normal.
794 if (OffImm == INT32_MIN)
795 OffImm = 0;
796 if (isSub) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700797 SStream_concat(O, "#-0x%x", -OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800798 } else {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800799 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700800 SStream_concat(O, "#0x%x", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800801 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700802 SStream_concat(O, "#%u", OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800803 }
804
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700805 SStream_concat0(O, "]");
Nguyen Anh Quynhbb71c132014-06-01 10:14:31 +0700806
807 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700808 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
809 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_PC;
810 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
811 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
812 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
813 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynhbb71c132014-06-01 10:14:31 +0700814 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800815}
816
817// so_reg is a 4-operand unit corresponding to register forms of the A5.1
818// "Addressing Mode 1 - Data-processing operands" forms. This includes:
819// REG 0 0 - e.g. R5
820// REG REG 0,SH_OPC - e.g. R5, ROR R3
821// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
822static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
823{
824 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
825 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
826 MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800827 ARM_AM_ShiftOpc ShOpc;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800828
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800829 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800830
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800831 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700832 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
833 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800834
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700835 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (MCOperand_getImm(MO3) & 7) + ARM_SFT_ASR_REG - 1;
836 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800837 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800838
839 // Print the shift opc.
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100840 ShOpc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700841 SStream_concat0(O, ", ");
842 SStream_concat0(O, ARM_AM_getShiftOpcStr(ShOpc));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800843 if (ShOpc == ARM_AM_rrx)
844 return;
845
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700846 SStream_concat0(O, " ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800847 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800848 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700849 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = MCOperand_getReg(MO2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800850 //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
851}
852
853static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
854{
855 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
856 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
857
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800858 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800859 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700860 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
861 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
862 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = MCOperand_getImm(MO2) & 7;
863 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = (unsigned int)MCOperand_getImm(MO2) >> 3;
864 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800865 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800866
867 // Print the shift opc.
Alex Ionescu46018db2014-01-22 09:45:00 -0800868 printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
Nguyen Anh Quynh8c1104b2014-06-10 00:39:06 +0700869 getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800870}
871
872//===--------------------------------------------------------------------===//
873// Addressing Mode #2
874//===--------------------------------------------------------------------===//
875
876static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
877{
878 MCOperand *MO1 = MCInst_getOperand(MI, Op);
879 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
880 MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800881 ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800882
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700883 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800884 set_mem_access(MI, true);
885
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800886 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800887 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700888 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800889 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800890
891 if (!MCOperand_getReg(MO2)) {
Alex Ionescu46018db2014-01-22 09:45:00 -0800892 unsigned tmp = getAM2Offset((unsigned int)MCOperand_getImm(MO3));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800893 if (tmp) { // Don't print +0.
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800894 subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
895
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700896 SStream_concat0(O, ", ");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800897 if (tmp > HEX_THRESHOLD)
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800898 SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800899 else
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800900 SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800901 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700902 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op((unsigned int)MCOperand_getImm(MO3));
903 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800904 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800905 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800906 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700907 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800908 set_mem_access(MI, false);
909 return;
910 }
911
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700912 SStream_concat0(O, ", ");
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800913 SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800914 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800915 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700916 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800917 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800918 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800919
Alex Ionescu46018db2014-01-22 09:45:00 -0800920 printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO3)),
Nguyen Anh Quynh8c1104b2014-06-10 00:39:06 +0700921 getAM2Offset((unsigned int)MCOperand_getImm(MO3)));
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700922 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800923 set_mem_access(MI, false);
924}
925
926static void printAddrModeTBB(MCInst *MI, unsigned Op, SStream *O)
927{
928 MCOperand *MO1 = MCInst_getOperand(MI, Op);
929 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700930 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800931 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800932 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800933 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700934 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700935 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800936 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800937 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700938 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700939 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800940 set_mem_access(MI, false);
941}
942
943static void printAddrModeTBH(MCInst *MI, unsigned Op, SStream *O)
944{
945 MCOperand *MO1 = MCInst_getOperand(MI, Op);
946 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700947 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800948 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800949 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800950 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700951 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700952 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +0800953 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800954 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700955 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700956 SStream_concat0(O, ", lsl #1]");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800957 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700958 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;
959 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = 1;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800960 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800961 set_mem_access(MI, false);
962}
963
964static void printAddrMode2Operand(MCInst *MI, unsigned Op, SStream *O)
965{
966 MCOperand *MO1 = MCInst_getOperand(MI, Op);
967
968 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
969 printOperand(MI, Op, O);
970 return;
971 }
972
973 printAM2PreOrOffsetIndexOp(MI, Op, O);
974}
975
976static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
977{
978 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
979 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800980 ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800981
982 if (!MCOperand_getReg(MO1)) {
Alex Ionescu46018db2014-01-22 09:45:00 -0800983 unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800984 if (ImmOffs > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700985 SStream_concat(O, "#%s0x%x",
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800986 ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +0800987 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +0700988 SStream_concat(O, "#%s%u",
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800989 ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800990 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700991 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
992 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800993 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700994 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800995 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800996 return;
997 }
998
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +0800999 SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001000 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001001 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001002 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1003 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001004 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001005 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001006 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001007
Alex Ionescu46018db2014-01-22 09:45:00 -08001008 printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO2)),
Nguyen Anh Quynh8c1104b2014-06-10 00:39:06 +07001009 getAM2Offset((unsigned int)MCOperand_getImm(MO2)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001010}
1011
1012//===--------------------------------------------------------------------===//
1013// Addressing Mode #3
1014//===--------------------------------------------------------------------===//
1015
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001016static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
1017 bool AlwaysPrintImm0)
1018{
1019 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1020 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
1021 MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001022 ARM_AM_AddrOpc sign = getAM3Op((unsigned int)MCOperand_getImm(MO3));
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001023 unsigned ImmOffs;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001024
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001025 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001026 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001027 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001028 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001029 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001030
1031 if (MCOperand_getReg(MO2)) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001032 SStream_concat0(O, ", ");
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001033 SStream_concat0(O, ARM_AM_getAddrOpcStr(sign));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001034 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001035 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001036 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001037 if (!sign) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001038 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001039 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1040 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001041 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001042 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001043 set_mem_access(MI, false);
1044 return;
1045 }
1046
1047 //If the op is sub we have to print the immediate even if it is 0
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001048 ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001049
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001050 if (AlwaysPrintImm0 || ImmOffs || (sign == ARM_AM_sub)) {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001051 if (ImmOffs > HEX_THRESHOLD)
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001052 SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(sign), ImmOffs);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001053 else
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001054 SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(sign), ImmOffs);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001055 }
Nguyen Anh Quynh6677b992013-12-08 22:20:35 +08001056
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001057 if (MI->csh->detail) {
Nguyen Anh Quynh8b012d52015-08-15 14:16:39 +08001058 if (!sign) {
pzread55983012015-02-15 18:22:51 +09001059 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)ImmOffs;
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001060 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1061 } else
Nguyen Anh Quynhb756aed2015-02-25 18:01:02 +08001062 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001063 }
Nguyen Anh Quynh6677b992013-12-08 22:20:35 +08001064
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001065 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001066 set_mem_access(MI, false);
1067}
1068
1069static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,
1070 bool AlwaysPrintImm0)
1071{
1072 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1073 if (!MCOperand_isReg(MO1)) { // For label symbolic references.
1074 printOperand(MI, Op, O);
1075 return;
1076 }
1077
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001078 printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
1079}
1080
1081static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1082{
1083 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1084 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001085 ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001086 unsigned ImmOffs;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001087
1088 if (MCOperand_getReg(MO1)) {
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001089 SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001090 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001091 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001092 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
Nguyen Anh Quynh8693fcd2014-06-17 13:28:33 +08001093 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001094 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001095 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001096 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001097 return;
1098 }
1099
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001100 ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001101 if (ImmOffs > HEX_THRESHOLD)
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001102 SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001103 else
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001104 SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001105 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001106 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
Nguyen Anh Quynh6677b992013-12-08 22:20:35 +08001107
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001108 if (subtracted) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001109 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001110 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1111 } else
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001112 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = -(int)ImmOffs;
Nguyen Anh Quynh6677b992013-12-08 22:20:35 +08001113
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001114 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001115 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001116}
1117
1118static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O)
1119{
1120 MCOperand *MO = MCInst_getOperand(MI, OpNum);
Alex Ionescu46018db2014-01-22 09:45:00 -08001121 unsigned Imm = (unsigned int)MCOperand_getImm(MO);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001122 if ((Imm & 0xff) > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001123 SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001124 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001125 SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001126 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001127 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1128 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm & 0xff;
1129 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001130 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001131}
1132
1133static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1134{
1135 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1136 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1137
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001138 SStream_concat0(O, (MCOperand_getImm(MO2) ? "" : "-"));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001139 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001140 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001141 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1142 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1143 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001144 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001145}
1146
1147static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
1148{
1149 MCOperand *MO = MCInst_getOperand(MI, OpNum);
Alex Ionescu46018db2014-01-22 09:45:00 -08001150 unsigned Imm = (unsigned int)MCOperand_getImm(MO);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001151 if (((Imm & 0xff) << 2) > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001152 SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001153 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001154 SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001155}
1156
1157static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
1158 bool AlwaysPrintImm0)
1159{
Nguyen Anh Quynh6acaaa52014-11-10 17:41:05 +08001160 unsigned ImmOffs;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001161 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1162 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynh6acaaa52014-11-10 17:41:05 +08001163 ARM_AM_AddrOpc subtracted = ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001164
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001165 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1166 printOperand(MI, OpNum, O);
1167 return;
1168 }
1169
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001170 SStream_concat0(O, "[");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001171 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001172
Nguyen Anh Quynhb79d9152014-06-01 10:48:55 +07001173 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001174 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
1175 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1176 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
1177 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
1178 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
Nguyen Anh Quynhb79d9152014-06-01 10:48:55 +07001179 }
1180
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001181 ImmOffs = ARM_AM_getAM5Offset((unsigned int)MCOperand_getImm(MO2));
Nguyen Anh Quynh6acaaa52014-11-10 17:41:05 +08001182 if (AlwaysPrintImm0 || ImmOffs || subtracted == ARM_AM_sub) {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001183 if (ImmOffs * 4 > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001184 SStream_concat(O, ", #%s0x%x",
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001185 ARM_AM_getAddrOpcStr(subtracted),
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001186 ImmOffs * 4);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001187 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001188 SStream_concat(O, ", #%s%u",
Nguyen Anh Quynh8fb2eab2014-10-06 20:27:25 +08001189 ARM_AM_getAddrOpcStr(subtracted),
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001190 ImmOffs * 4);
Nguyen Anh Quynha04ee4f2014-06-01 10:52:01 +07001191 if (MI->csh->detail) {
Nguyen Anh Quynh6acaaa52014-11-10 17:41:05 +08001192 if (subtracted)
1193 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;
1194 else
Nguyen Anh Quynh51888c32014-11-11 23:59:23 +08001195 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 4;
Nguyen Anh Quynha04ee4f2014-06-01 10:52:01 +07001196 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001197 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001198 SStream_concat0(O, "]");
Nguyen Anh Quynhb79d9152014-06-01 10:48:55 +07001199
1200 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001201 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynhb79d9152014-06-01 10:48:55 +07001202 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001203}
1204
1205static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O)
1206{
1207 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1208 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001209 unsigned tmp;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001210
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001211 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001212 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001213 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001214 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001215 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001216 tmp = (unsigned int)MCOperand_getImm(MO2);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001217 if (tmp) {
1218 if (tmp << 3 > HEX_THRESHOLD)
1219 SStream_concat(O, ":0x%x", (tmp << 3));
1220 else
1221 SStream_concat(O, ":%u", (tmp << 3));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001222 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001223 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp << 3;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001224 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001225 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001226 set_mem_access(MI, false);
1227}
1228
1229static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)
1230{
1231 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001232 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001233 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001234 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001235 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001236 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001237 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001238 set_mem_access(MI, false);
1239}
1240
1241static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1242{
1243 MCOperand *MO = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +08001244 if (MCOperand_getReg(MO) == 0) {
1245 MI->writeback = true;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001246 SStream_concat0(O, "!");
Nguyen Anh Quynhe19490e2015-01-21 12:15:14 +08001247 } else {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001248 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001249 printRegName(MI->csh, O, MCOperand_getReg(MO));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001250 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001251 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1252 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO);
1253 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001254 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001255 }
1256}
1257
1258static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1259{
1260 MCOperand *MO = MCInst_getOperand(MI, OpNum);
Alex Ionescu46018db2014-01-22 09:45:00 -08001261 uint32_t v = ~(uint32_t)MCOperand_getImm(MO);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001262 int32_t lsb = CountTrailingZeros_32(v);
1263 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001264
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001265 //assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001266 if (lsb > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001267 SStream_concat(O, "#0x%x", lsb);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001268 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001269 SStream_concat(O, "#%u", lsb);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001270
1271 if (width > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001272 SStream_concat(O, ", #0x%x", width);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001273 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001274 SStream_concat(O, ", #%u", width);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001275
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001276 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001277 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1278 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = lsb;
1279 MI->flat_insn->detail->arm.op_count++;
1280 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1281 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = width;
1282 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001283 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001284}
1285
1286static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O)
1287{
Alex Ionescu46018db2014-01-22 09:45:00 -08001288 unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh8cdafda2014-11-11 22:30:30 +08001289 SStream_concat0(O, ARM_MB_MemBOptToString(val + 1,
Nguyen Anh Quynhded15772015-05-24 21:33:17 +08001290 (ARM_getFeatureBits(MI->csh->mode) & ARM_HasV8Ops) != 0));
Nguyen Anh Quynh8cdafda2014-11-11 22:30:30 +08001291
1292 if (MI->csh->detail) {
Nguyen Anh Quynh51888c32014-11-11 23:59:23 +08001293 MI->flat_insn->detail->arm.mem_barrier = (arm_mem_barrier)(val + 1);
Nguyen Anh Quynh8cdafda2014-11-11 22:30:30 +08001294 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001295}
1296
1297void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)
1298{
Alex Ionescu46018db2014-01-22 09:45:00 -08001299 unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001300 SStream_concat0(O, ARM_ISB_InstSyncBOptToString(val));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001301}
1302
1303static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1304{
Alex Ionescu46018db2014-01-22 09:45:00 -08001305 unsigned ShiftOp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001306 bool isASR = (ShiftOp & (1 << 5)) != 0;
1307 unsigned Amt = ShiftOp & 0x1f;
1308 if (isASR) {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001309 unsigned tmp = Amt == 0 ? 32 : Amt;
1310 if (tmp > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001311 SStream_concat(O, ", asr #0x%x", tmp);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001312 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001313 SStream_concat(O, ", asr #%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001314 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001315 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1316 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001317 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001318 } else if (Amt) {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001319 if (Amt > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001320 SStream_concat(O, ", lsl #0x%x", Amt);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001321 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001322 SStream_concat(O, ", lsl #%u", Amt);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001323 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001324 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1325 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Amt;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001326 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001327 }
1328}
1329
1330static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1331{
Alex Ionescu46018db2014-01-22 09:45:00 -08001332 unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001333 if (Imm == 0)
1334 return;
1335 //assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001336 if (Imm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001337 SStream_concat(O, ", lsl #0x%x", Imm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001338 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001339 SStream_concat(O, ", lsl #%u", Imm);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001340 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001341 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1342 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001343 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001344}
1345
1346static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1347{
Alex Ionescu46018db2014-01-22 09:45:00 -08001348 unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001349 // A shift amount of 32 is encoded as 0.
1350 if (Imm == 0)
1351 Imm = 32;
1352 //assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001353 if (Imm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001354 SStream_concat(O, ", asr #0x%x", Imm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001355 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001356 SStream_concat(O, ", asr #%u", Imm);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001357 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001358 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1359 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001360 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001361}
1362
1363// FIXME: push {r1, r2, r3, ...} can exceed the number of operands in MCInst struct
1364static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O)
1365{
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +08001366 unsigned i, e;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001367 SStream_concat0(O, "{");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001368 for (i = OpNum, e = MCInst_getNumOperands(MI); i != e; ++i) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001369 if (i != OpNum) SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001370 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, i)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001371 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001372 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1373 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, i));
1374 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001375 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001376 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001377 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001378}
1379
1380static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O,
1381 MCRegisterInfo *MRI)
1382{
1383 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001384 printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001385 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001386 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1387 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0);
1388 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001389 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001390 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001391 printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001392 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001393 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1394 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1);
1395 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001396 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001397}
1398
1399// SETEND BE/LE
1400static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O)
1401{
1402 MCOperand *Op = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001403 if (MCOperand_getImm(Op)) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001404 SStream_concat0(O, "be");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001405 if (MI->csh->detail) {
1406 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1407 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_BE;
1408 MI->flat_insn->detail->arm.op_count++;
1409 }
1410 } else {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001411 SStream_concat0(O, "le");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001412 if (MI->csh->detail) {
1413 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1414 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_LE;
1415 MI->flat_insn->detail->arm.op_count++;
1416 }
1417 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001418}
1419
1420static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O)
1421{
1422 MCOperand *Op = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001423 unsigned int mode = (unsigned int)MCOperand_getImm(Op);
1424
1425 SStream_concat0(O, ARM_PROC_IModToString(mode));
1426
1427 if (MI->csh->detail) {
1428 MI->flat_insn->detail->arm.cps_mode = mode;
1429 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001430}
1431
1432static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O)
1433{
1434 MCOperand *Op = MCInst_getOperand(MI, OpNum);
Alex Ionescu46018db2014-01-22 09:45:00 -08001435 unsigned IFlags = (unsigned int)MCOperand_getImm(Op);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001436 int i;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001437
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001438 for (i = 2; i >= 0; --i)
1439 if (IFlags & (1 << i)) {
1440 SStream_concat0(O, ARM_PROC_IFlagsToString(1 << i));
1441 }
1442
1443 if (IFlags == 0) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001444 SStream_concat0(O, "none");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001445 IFlags = ARM_CPSFLAG_NONE;
1446 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001447
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001448 if (MI->csh->detail) {
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001449 MI->flat_insn->detail->arm.cps_flag = IFlags;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001450 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001451}
1452
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001453static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O)
1454{
1455 MCOperand *Op = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynh07c92ec2014-08-26 15:35:11 +08001456 unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;
Nguyen Anh Quynhb52f11f2014-08-13 22:38:15 +08001457 unsigned Mask = MCOperand_getImm(Op) & 0xf;
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001458 unsigned reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001459
Nguyen Anh Quynhb52f11f2014-08-13 22:38:15 +08001460 if (ARM_getFeatureBits(MI->csh->mode) & ARM_FeatureMClass) {
Nguyen Anh Quynh07c92ec2014-08-26 15:35:11 +08001461 unsigned SYSm = (unsigned)MCOperand_getImm(Op);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001462 unsigned Opcode = MCInst_getOpcode(MI);
1463 // For reads of the special registers ignore the "mask encoding" bits
1464 // which are only for writes.
1465 if (Opcode == ARM_t2MRS_M)
1466 SYSm &= 0xff;
1467 switch (SYSm) {
Nguyen Anh Quynhb52f11f2014-08-13 22:38:15 +08001468 default: //llvm_unreachable("Unexpected mask value!");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001469 case 0:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001470 case 0x800: SStream_concat0(O, "apsr"); ARM_addSysReg(MI, ARM_SYSREG_APSR); return; // with _nzcvq bits is an alias for aspr
1471 case 0x400: SStream_concat0(O, "apsr_g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;
1472 case 0xc00: SStream_concat0(O, "apsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001473 case 1:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001474 case 0x801: SStream_concat0(O, "iapsr"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR); return; // with _nzcvq bits is an alias for iapsr
1475 case 0x401: SStream_concat0(O, "iapsr_g"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR_G); return;
1476 case 0xc01: SStream_concat0(O, "iapsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR_NZCVQG); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001477 case 2:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001478 case 0x802: SStream_concat0(O, "eapsr"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR); return; // with _nzcvq bits is an alias for eapsr
1479 case 0x402: SStream_concat0(O, "eapsr_g"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR_G); return;
1480 case 0xc02: SStream_concat0(O, "eapsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR_NZCVQG); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001481 case 3:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001482 case 0x803: SStream_concat0(O, "xpsr"); ARM_addSysReg(MI, ARM_SYSREG_XPSR); return; // with _nzcvq bits is an alias for xpsr
1483 case 0x403: SStream_concat0(O, "xpsr_g"); ARM_addSysReg(MI, ARM_SYSREG_XPSR_G); return;
1484 case 0xc03: SStream_concat0(O, "xpsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_XPSR_NZCVQG); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001485 case 5:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001486 case 0x805: SStream_concat0(O, "ipsr"); ARM_addSysReg(MI, ARM_SYSREG_IPSR); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001487 case 6:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001488 case 0x806: SStream_concat0(O, "epsr"); ARM_addSysReg(MI, ARM_SYSREG_EPSR); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001489 case 7:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001490 case 0x807: SStream_concat0(O, "iepsr"); ARM_addSysReg(MI, ARM_SYSREG_IEPSR); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001491 case 8:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001492 case 0x808: SStream_concat0(O, "msp"); ARM_addSysReg(MI, ARM_SYSREG_MSP); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001493 case 9:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001494 case 0x809: SStream_concat0(O, "psp"); ARM_addSysReg(MI, ARM_SYSREG_PSP); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001495 case 0x10:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001496 case 0x810: SStream_concat0(O, "primask"); ARM_addSysReg(MI, ARM_SYSREG_PRIMASK); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001497 case 0x11:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001498 case 0x811: SStream_concat0(O, "basepri"); ARM_addSysReg(MI, ARM_SYSREG_BASEPRI); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001499 case 0x12:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001500 case 0x812: SStream_concat0(O, "basepri_max"); ARM_addSysReg(MI, ARM_SYSREG_BASEPRI_MAX); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001501 case 0x13:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001502 case 0x813: SStream_concat0(O, "faultmask"); ARM_addSysReg(MI, ARM_SYSREG_FAULTMASK); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001503 case 0x14:
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001504 case 0x814: SStream_concat0(O, "control"); ARM_addSysReg(MI, ARM_SYSREG_CONTROL); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001505 }
1506 }
Nguyen Anh Quynhb52f11f2014-08-13 22:38:15 +08001507
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001508 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
1509 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
1510 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
Nguyen Anh Quynhd865f392014-11-10 16:38:17 +08001511 SStream_concat0(O, "apsr_");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001512 switch (Mask) {
Nguyen Anh Quynhb52f11f2014-08-13 22:38:15 +08001513 default: // llvm_unreachable("Unexpected mask value!");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001514 case 4: SStream_concat0(O, "g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;
1515 case 8: SStream_concat0(O, "nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQ); return;
1516 case 12: SStream_concat0(O, "nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001517 }
1518 }
1519
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001520 reg = 0;
1521 if (SpecRegRBit) {
Nguyen Anh Quynhd865f392014-11-10 16:38:17 +08001522 SStream_concat0(O, "spsr");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001523 if (Mask) {
1524 SStream_concat0(O, "_");
1525 if (Mask & 8) {
1526 SStream_concat0(O, "f");
1527 reg += ARM_SYSREG_SPSR_F;
1528 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001529
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001530 if (Mask & 4) {
1531 SStream_concat0(O, "s");
1532 reg += ARM_SYSREG_SPSR_S;
1533 }
1534
1535 if (Mask & 2) {
1536 SStream_concat0(O, "x");
1537 reg += ARM_SYSREG_SPSR_X;
1538 }
1539
1540 if (Mask & 1) {
1541 SStream_concat0(O, "c");
1542 reg += ARM_SYSREG_SPSR_C;
1543 }
1544 ARM_addSysReg(MI, reg);
1545 }
1546 } else {
Nguyen Anh Quynhd865f392014-11-10 16:38:17 +08001547 SStream_concat0(O, "cpsr");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001548 if (Mask) {
1549 SStream_concat0(O, "_");
1550 if (Mask & 8) {
1551 SStream_concat0(O, "f");
1552 reg += ARM_SYSREG_CPSR_F;
1553 }
1554
1555 if (Mask & 4) {
1556 SStream_concat0(O, "s");
1557 reg += ARM_SYSREG_CPSR_S;
1558 }
1559
1560 if (Mask & 2) {
1561 SStream_concat0(O, "x");
1562 reg += ARM_SYSREG_CPSR_X;
1563 }
1564
1565 if (Mask & 1) {
1566 SStream_concat0(O, "c");
1567 reg += ARM_SYSREG_CPSR_C;
1568 }
1569 ARM_addSysReg(MI, reg);
1570 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001571 }
1572}
1573
1574static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1575{
1576 ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1577 // Handle the undefined 15 CC value here for printing so we don't abort().
1578 if ((unsigned)CC == 15) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001579 SStream_concat0(O, "<und>");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001580 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001581 MI->flat_insn->detail->arm.cc = ARM_CC_INVALID;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001582 } else {
1583 if (CC != ARMCC_AL) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001584 SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001585 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001586 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001587 MI->flat_insn->detail->arm.cc = CC + 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001588 }
1589}
1590
1591// TODO: test this
1592static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1593{
1594 ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001595 SStream_concat0(O, ARMCC_ARMCondCodeToString(CC));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001596 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001597 MI->flat_insn->detail->arm.cc = CC + 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001598}
1599
1600static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O)
1601{
1602 if (MCOperand_getReg(MCInst_getOperand(MI, OpNum))) {
1603 //assert(MCOperand_getReg(MCInst_getOperand(MI, OpNum)) == ARM_CPSR &&
1604 // "Expect ARM CPSR register!");
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001605 SStream_concat0(O, "s");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001606 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001607 MI->flat_insn->detail->arm.update_flags = true;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001608 }
1609}
1610
1611static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1612{
Alex Ionescu46018db2014-01-22 09:45:00 -08001613 unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001614 if (tmp > HEX_THRESHOLD)
1615 SStream_concat(O, "0x%x", tmp);
1616 else
1617 SStream_concat(O, "%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001618 if (MI->csh->detail) {
Nguyen Anh Quynh19b0de32013-12-31 22:40:04 +08001619 if (MI->csh->doing_mem) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001620 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001621 } else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001622 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1623 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1624 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001625 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001626 }
1627}
1628
1629static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1630{
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001631 unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1632
1633 SStream_concat(O, "p%u", imm);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001634 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001635 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_PIMM;
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001636 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001637 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001638 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001639}
1640
1641static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1642{
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001643 unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1644
1645 SStream_concat(O, "c%u", imm);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001646 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001647 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_CIMM;
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08001648 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001649 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001650 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001651}
1652
1653static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)
1654{
Alex Ionescu46018db2014-01-22 09:45:00 -08001655 unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001656 if (tmp > HEX_THRESHOLD)
1657 SStream_concat(O, "{0x%x}", tmp);
1658 else
1659 SStream_concat(O, "{%u}", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001660 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001661 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1662 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1663 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001664 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001665}
1666
1667static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned scale)
1668{
1669 MCOperand *MO = MCInst_getOperand(MI, OpNum);
1670
1671 int32_t OffImm = (int32_t)MCOperand_getImm(MO) << scale;
1672
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001673 if (OffImm == INT32_MIN) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001674 SStream_concat0(O, "#-0");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001675 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001676 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1677 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
1678 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001679 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001680 } else {
1681 if (OffImm < 0)
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001682 SStream_concat(O, "#-0x%x", -OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001683 else {
1684 if (OffImm > HEX_THRESHOLD)
1685 SStream_concat(O, "#0x%x", OffImm);
1686 else
1687 SStream_concat(O, "#%u", OffImm);
1688 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001689 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001690 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1691 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
1692 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001693 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001694 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001695}
1696
1697static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1698{
Alex Ionescu46018db2014-01-22 09:45:00 -08001699 unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001700 if (tmp > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001701 SStream_concat(O, "#0x%x", tmp);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001702 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001703 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynhaa078a12014-01-23 22:29:04 +08001704 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001705 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1706 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1707 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynhaa078a12014-01-23 22:29:04 +08001708 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001709}
1710
1711static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O)
1712{
Alex Ionescu46018db2014-01-22 09:45:00 -08001713 unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001714 unsigned tmp = Imm == 0 ? 32 : Imm;
1715 if (tmp > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001716 SStream_concat(O, "#0x%x", tmp);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001717 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001718 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001719
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001720 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001721 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1722 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1723 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001724 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001725}
1726
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001727static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O)
1728{
1729 // (3 - the number of trailing zeros) is the number of then / else.
Alex Ionescu46018db2014-01-22 09:45:00 -08001730 unsigned Mask = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1731 unsigned Firstcond = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum-1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001732 unsigned CondBit0 = Firstcond & 1;
1733 unsigned NumTZ = CountTrailingZeros_32(Mask);
1734 //assert(NumTZ <= 3 && "Invalid IT mask!");
1735 unsigned Pos, e;
1736 for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
1737 bool T = ((Mask >> Pos) & 1) == CondBit0;
1738 if (T)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001739 SStream_concat0(O, "t");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001740 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001741 SStream_concat0(O, "e");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001742 }
1743}
1744
1745static void printThumbAddrModeRROperand(MCInst *MI, unsigned Op, SStream *O)
1746{
1747 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1748 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001749 unsigned RegNum;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001750
1751 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1752 printOperand(MI, Op, O);
1753 return;
1754 }
1755
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001756 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001757 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001758 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001759 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001760 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001761 RegNum = MCOperand_getReg(MO2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001762 if (RegNum) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001763 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001764 printRegName(MI->csh, O, RegNum);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001765 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001766 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = RegNum;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001767 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001768 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001769 set_mem_access(MI, false);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001770}
1771
1772static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned Op, SStream *O,
1773 unsigned Scale)
1774{
1775 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1776 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001777 unsigned ImmOffs, tmp;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001778
1779 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1780 printOperand(MI, Op, O);
1781 return;
1782 }
1783
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001784 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001785 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001786 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001787 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001788 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001789 ImmOffs = (unsigned int)MCOperand_getImm(MO2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001790 if (ImmOffs) {
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001791 tmp = ImmOffs * Scale;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001792 SStream_concat0(O, ", ");
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001793 if (tmp > HEX_THRESHOLD)
1794 SStream_concat(O, "#0x%x", tmp);
1795 else
1796 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001797 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001798 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001799 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001800 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001801 set_mem_access(MI, false);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001802}
1803
1804static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned Op, SStream *O)
1805{
1806 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
1807}
1808
1809static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned Op, SStream *O)
1810{
1811 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
1812}
1813
1814static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned Op, SStream *O)
1815{
1816 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
1817}
1818
1819static void printThumbAddrModeSPOperand(MCInst *MI, unsigned Op, SStream *O)
1820{
1821 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
1822}
1823
1824// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1825// register with shift forms.
1826// REG 0 0 - e.g. R5
1827// REG IMM, SH_OPC - e.g. R5, LSL #3
1828static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O)
1829{
1830 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1831 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1832
1833 unsigned Reg = MCOperand_getReg(MO1);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001834 printRegName(MI->csh, O, Reg);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001835 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001836 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1837 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
1838 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08001839 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001840
1841 // Print the shift opc.
1842 //assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Alex Ionescu46018db2014-01-22 09:45:00 -08001843 printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
Nguyen Anh Quynh8c1104b2014-06-10 00:39:06 +07001844 getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001845}
1846
1847static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum,
1848 SStream *O, bool AlwaysPrintImm0)
1849{
1850 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1851 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynhaa078a12014-01-23 22:29:04 +08001852 int32_t OffImm;
1853 bool isSub;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001854
1855 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1856 printOperand(MI, OpNum, O);
1857 return;
1858 }
1859
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001860 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001861 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001862 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001863
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001864 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001865 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001866
Alex Ionescu46018db2014-01-22 09:45:00 -08001867 OffImm = (int32_t)MCOperand_getImm(MO2);
1868 isSub = OffImm < 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001869 // Special value for #-0. All others are normal.
1870 if (OffImm == INT32_MIN)
1871 OffImm = 0;
1872 if (isSub) {
Nguyen Anh Quynha247dc12014-04-12 00:19:42 +08001873 if (OffImm < -HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001874 SStream_concat(O, ", #-0x%x", -OffImm);
Nguyen Anh Quynha247dc12014-04-12 00:19:42 +08001875 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001876 SStream_concat(O, ", #-%u", -OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001877 } else if (AlwaysPrintImm0 || OffImm > 0) {
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08001878 if (OffImm >= 0) {
1879 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001880 SStream_concat(O, ", #0x%x", OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08001881 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001882 SStream_concat(O, ", #%u", OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08001883 } else {
1884 if (OffImm < -HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001885 SStream_concat(O, ", #-0x%x", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08001886 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001887 SStream_concat(O, ", #-%u", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08001888 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001889 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001890 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001891 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001892 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001893 set_mem_access(MI, false);
1894}
1895
1896static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O,
1897 bool AlwaysPrintImm0)
1898{
1899 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1900 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynhaa078a12014-01-23 22:29:04 +08001901 int32_t OffImm;
1902 bool isSub;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001903
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001904 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001905 set_mem_access(MI, true);
1906
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001907 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001908 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001909 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001910
Alex Ionescu46018db2014-01-22 09:45:00 -08001911 OffImm = (int32_t)MCOperand_getImm(MO2);
1912 isSub = OffImm < 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001913 // Don't print +0.
1914 if (OffImm == INT32_MIN)
1915 OffImm = 0;
1916
1917 if (isSub)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001918 SStream_concat(O, ", #-0x%x", -OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001919 else if (AlwaysPrintImm0 || OffImm > 0) {
1920 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001921 SStream_concat(O, ", #0x%x", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001922 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001923 SStream_concat(O, ", #%u", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001924 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001925
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001926 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001927 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001928 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001929 set_mem_access(MI, false);
1930}
1931
1932static void printT2AddrModeImm8s4Operand(MCInst *MI,
1933 unsigned OpNum, SStream *O, bool AlwaysPrintImm0)
1934{
1935 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1936 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynhaa078a12014-01-23 22:29:04 +08001937 int32_t OffImm;
1938 bool isSub;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001939
1940 if (!MCOperand_isReg(MO1)) { // For label symbolic references.
1941 printOperand(MI, OpNum, O);
1942 return;
1943 }
1944
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001945 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001946 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001947 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001948 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001949 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001950
Alex Ionescu46018db2014-01-22 09:45:00 -08001951 OffImm = (int32_t)MCOperand_getImm(MO2);
1952 isSub = OffImm < 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001953
1954 //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1955
1956 // Don't print +0.
1957 if (OffImm == INT32_MIN)
1958 OffImm = 0;
1959 if (isSub) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001960 SStream_concat(O, ", #-0x%x", -OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001961 } else if (AlwaysPrintImm0 || OffImm > 0) {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001962 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001963 SStream_concat(O, ", #0x%x", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001964 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001965 SStream_concat(O, ", #%u", OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001966 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001967 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001968 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001969
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001970 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001971 set_mem_access(MI, false);
1972}
1973
1974static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
1975{
1976 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1977 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08001978 unsigned tmp;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001979
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001980 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001981 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08001982 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001983 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001984 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001985 if (MCOperand_getImm(MO2)) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001986 SStream_concat0(O, ", ");
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01001987 tmp = (unsigned int)MCOperand_getImm(MO2) * 4;
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08001988 if (tmp > HEX_THRESHOLD)
1989 SStream_concat(O, "#0x%x", tmp);
1990 else
1991 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08001992 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07001993 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001994 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07001995 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001996 set_mem_access(MI, false);
1997}
1998
1999static void printT2AddrModeImm8OffsetOperand(MCInst *MI,
2000 unsigned OpNum, SStream *O)
2001{
2002 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2003 int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002004 SStream_concat0(O, ", ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002005 if (OffImm == INT32_MIN) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002006 SStream_concat0(O, "#-0");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002007 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002008 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2009 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2010 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002011 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002012 } else {
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002013 if (OffImm < 0) {
2014 if (OffImm < -HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002015 SStream_concat(O, "#-0x%x", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002016 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002017 SStream_concat(O, "#-%u", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002018 } else {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002019 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002020 SStream_concat(O, "#0x%x", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002021 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002022 SStream_concat(O, "#%u", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002023 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002024 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002025 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2026 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2027 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002028 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002029 }
2030}
2031
2032static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI,
2033 unsigned OpNum, SStream *O)
2034{
2035 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2036 int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
2037
2038 //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
2039
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002040 SStream_concat0(O, ", ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002041 if (OffImm == INT32_MIN) {
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002042 SStream_concat0(O, "#-0");
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002043 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002044 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2045 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2046 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002047 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002048 } else {
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002049 if (OffImm < 0) {
2050 if (OffImm < -HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002051 SStream_concat(O, "#-0x%x", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002052 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002053 SStream_concat(O, "#-%u", -OffImm);
Nguyen Anh Quynhffff7562014-03-26 16:21:31 +08002054 } else {
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002055 if (OffImm > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002056 SStream_concat(O, "#0x%x", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002057 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002058 SStream_concat(O, "#%u", OffImm);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002059 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002060 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002061 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2062 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2063 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002064 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002065 }
2066}
2067
2068static void printT2AddrModeSoRegOperand(MCInst *MI,
2069 unsigned OpNum, SStream *O)
2070{
2071 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2072 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2073 MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08002074 unsigned ShAmt;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002075
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002076 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002077 set_mem_access(MI, true);
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002078 printRegName(MI->csh, O, MCOperand_getReg(MO1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002079 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002080 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002081
2082 //assert(MCOperand_getReg(MO2.getReg() && "Invalid so_reg load / store address!");
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002083 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002084 printRegName(MI->csh, O, MCOperand_getReg(MO2));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002085 if (MI->csh->detail)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002086 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002087
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01002088 ShAmt = (unsigned int)MCOperand_getImm(MO3);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002089 if (ShAmt) {
2090 //assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002091 SStream_concat0(O, ", lsl ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002092 SStream_concat(O, "#%d", ShAmt);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002093 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002094 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
2095 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = ShAmt;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002096 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002097 }
2098
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002099 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002100 set_mem_access(MI, false);
2101}
2102
2103static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2104{
2105 MCOperand *MO = MCInst_getOperand(MI, OpNum);
Nguyen Anh Quynh2ac5d792014-11-10 21:46:34 +08002106 SStream_concat(O, "#%e", getFPImmFloat((unsigned int)MCOperand_getImm(MO)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002107 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002108 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_FP;
2109 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].fp = getFPImmFloat((unsigned int)MCOperand_getImm(MO));
2110 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002111 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002112}
2113
2114static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2115{
Alex Ionescu46018db2014-01-22 09:45:00 -08002116 unsigned EncodedImm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002117 unsigned EltBits;
2118 uint64_t Val = ARM_AM_decodeNEONModImm(EncodedImm, &EltBits);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002119 if (Val > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002120 SStream_concat(O, "#0x%"PRIx64, Val);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002121 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002122 SStream_concat(O, "#%"PRIu64, Val);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002123 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002124 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2125 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = (unsigned int)Val;
2126 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002127 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002128}
2129
2130static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O)
2131{
Alex Ionescu46018db2014-01-22 09:45:00 -08002132 unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002133 if (Imm + 1 > HEX_THRESHOLD)
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002134 SStream_concat(O, "#0x%x", Imm + 1);
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002135 else
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002136 SStream_concat(O, "#%u", Imm + 1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002137 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002138 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2139 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm + 1;
2140 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002141 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002142}
2143
2144static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2145{
Alex Ionescu46018db2014-01-22 09:45:00 -08002146 unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002147 if (Imm == 0)
2148 return;
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002149 SStream_concat0(O, ", ror #");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002150 switch (Imm) {
2151 default: //assert (0 && "illegal ror immediate!");
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002152 case 1: SStream_concat0(O, "8"); break;
2153 case 2: SStream_concat0(O, "16"); break;
2154 case 3: SStream_concat0(O, "24"); break;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002155 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002156 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002157 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ROR;
2158 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm * 8;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002159 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002160}
2161
2162static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)
2163{
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08002164 unsigned tmp;
2165
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01002166 tmp = 16 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002167 if (tmp > HEX_THRESHOLD)
2168 SStream_concat(O, "#0x%x", tmp);
2169 else
2170 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002171 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002172 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2173 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2174 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002175 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002176}
2177
2178static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O)
2179{
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +08002180 unsigned tmp;
2181
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +01002182 tmp = 32 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002183 if (tmp > HEX_THRESHOLD)
2184 SStream_concat(O, "#0x%x", tmp);
2185 else
2186 SStream_concat(O, "#%u", tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002187 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002188 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2189 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2190 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002191 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002192}
2193
2194static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
2195{
Alex Ionescu46018db2014-01-22 09:45:00 -08002196 unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh462f2912013-12-11 17:35:27 +08002197 if (tmp > HEX_THRESHOLD)
2198 SStream_concat(O, "[0x%x]",tmp);
2199 else
2200 SStream_concat(O, "[%u]",tmp);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002201 if (MI->csh->detail) {
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08002202 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].vector_index = tmp;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002203 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002204}
2205
2206static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O)
2207{
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002208 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002209 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002210 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002211 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2212 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2213 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002214 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002215 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002216}
2217
2218static void printVectorListTwo(MCInst *MI, unsigned OpNum,
2219 SStream *O, MCRegisterInfo *MRI)
2220{
2221 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2222 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2223 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002224 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002225 printRegName(MI->csh, O, Reg0);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002226 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002227 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2228 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2229 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002230 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002231 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002232 printRegName(MI->csh, O, Reg1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002233 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002234 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2235 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2236 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002237 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002238 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002239}
2240
2241static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum,
2242 SStream *O, MCRegisterInfo *MRI)
2243{
2244 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2245 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2246 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002247 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002248 printRegName(MI->csh, O, Reg0);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002249 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002250 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2251 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2252 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002253 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002254 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002255 printRegName(MI->csh, O, Reg1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002256 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002257 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2258 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2259 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002260 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002261 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002262}
2263
2264static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O)
2265{
2266 // Normally, it's not safe to use register enum values directly with
2267 // addition to get the next register, but for VFP registers, the
2268 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002269 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002270 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002271 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002272 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2273 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2274 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002275 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002276 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002277 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002278 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002279 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2280 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2281 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002282 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002283 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002284 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002285 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002286 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2287 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2288 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002289 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002290 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002291}
2292
2293static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O)
2294{
2295 // Normally, it's not safe to use register enum values directly with
2296 // addition to get the next register, but for VFP registers, the
2297 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002298 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002299 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002300 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002301 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2302 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2303 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002304 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002305 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002306 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002307 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002308 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2309 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2310 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002311 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002312 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002313 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002314 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002315 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2316 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2317 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002318 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002319 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002320 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002321 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002322 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2323 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2324 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002325 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002326 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002327}
2328
2329static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2330{
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002331 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002332 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002333 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002334 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2335 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2336 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002337 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002338 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002339}
2340
2341static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum,
2342 SStream *O, MCRegisterInfo *MRI)
2343{
2344 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2345 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2346 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002347 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002348 printRegName(MI->csh, O, Reg0);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002349 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002350 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2351 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2352 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002353 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002354 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002355 printRegName(MI->csh, O, Reg1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002356 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002357 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2358 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2359 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002360 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002361 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002362}
2363
2364static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2365{
2366 // Normally, it's not safe to use register enum values directly with
2367 // addition to get the next register, but for VFP registers, the
2368 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002369 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002370 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002371 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002372 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2373 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2374 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002375 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002376 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002377 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002378 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002379 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2380 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2381 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002382 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002383 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002384 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002385 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002386 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2387 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2388 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002389 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002390 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002391}
2392
2393static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2394{
2395 // Normally, it's not safe to use register enum values directly with
2396 // addition to get the next register, but for VFP registers, the
2397 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002398 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002399 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002400 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002401 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2402 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2403 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002404 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002405 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002406 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002407 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002408 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2409 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2410 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002411 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002412 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002413 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002414 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002415 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2416 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2417 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002418 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002419 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002420 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002421 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002422 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2423 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2424 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002425 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002426 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002427}
2428
2429static void printVectorListTwoSpacedAllLanes(MCInst *MI,
2430 unsigned OpNum, SStream *O, MCRegisterInfo *MRI)
2431{
2432 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2433 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2434 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002435 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002436 printRegName(MI->csh, O, Reg0);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002437 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002438 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2439 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2440 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002441 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002442 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002443 printRegName(MI->csh, O, Reg1);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002444 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002445 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2446 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2447 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002448 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002449 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002450}
2451
2452static void printVectorListThreeSpacedAllLanes(MCInst *MI,
2453 unsigned OpNum, SStream *O)
2454{
2455 // Normally, it's not safe to use register enum values directly with
2456 // addition to get the next register, but for VFP registers, the
2457 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002458 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002459 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002460 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002461 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2462 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2463 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002464 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002465 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002466 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002467 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002468 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2469 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2470 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002471 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002472 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002473 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002474 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002475 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2476 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2477 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002478 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002479 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002480}
2481
2482static void printVectorListFourSpacedAllLanes(MCInst *MI,
2483 unsigned OpNum, SStream *O)
2484{
2485 // Normally, it's not safe to use register enum values directly with
2486 // addition to get the next register, but for VFP registers, the
2487 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002488 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002489 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002490 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002491 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2492 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2493 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002494 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002495 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002496 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002497 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002498 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2499 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2500 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002501 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002502 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002503 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002504 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002505 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2506 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2507 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002508 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002509 SStream_concat0(O, "[], ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002510 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002511 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002512 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2513 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
2514 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002515 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002516 SStream_concat0(O, "[]}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002517}
2518
2519static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O)
2520{
2521 // Normally, it's not safe to use register enum values directly with
2522 // addition to get the next register, but for VFP registers, the
2523 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002524 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002525 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002526 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002527 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2528 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2529 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002530 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002531 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002532 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002533 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002534 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2535 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2536 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002537 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002538 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002539 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002540 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002541 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2542 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2543 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002544 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002545 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002546}
2547
2548static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O)
2549{
2550 // Normally, it's not safe to use register enum values directly with
2551 // addition to get the next register, but for VFP registers, the
2552 // sort order is guaranteed because they're all of the form D<n>.
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002553 SStream_concat0(O, "{");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002554 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002555 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002556 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2557 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2558 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002559 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002560 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002561 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002562 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002563 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2564 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2565 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002566 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002567 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002568 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002569 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002570 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2571 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2572 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002573 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002574 SStream_concat0(O, ", ");
Nguyen Anh Quynh2ff665a2014-03-11 00:18:50 +08002575 printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +08002576 if (MI->csh->detail) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +07002577 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2578 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
2579 MI->flat_insn->detail->arm.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +08002580 }
Nguyen Anh Quynhdd9225b2014-06-10 00:37:53 +07002581 SStream_concat0(O, "}");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08002582}
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +08002583
Nguyen Anh Quynh04d9f8e2014-09-01 23:27:24 +08002584void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd)
2585{
2586 if (MI->csh->detail) {
2587 MI->flat_insn->detail->arm.vector_data = vd;
2588 }
2589}
2590
2591void ARM_addVectorDataSize(MCInst *MI, int size)
2592{
2593 if (MI->csh->detail) {
2594 MI->flat_insn->detail->arm.vector_size = size;
2595 }
2596}
2597
2598void ARM_addReg(MCInst *MI, int reg)
2599{
2600 if (MI->csh->detail) {
2601 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2602 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
2603 MI->flat_insn->detail->arm.op_count++;
2604 }
2605}
2606
2607void ARM_addUserMode(MCInst *MI)
2608{
2609 if (MI->csh->detail) {
2610 MI->flat_insn->detail->arm.usermode = true;
2611 }
2612}
2613
2614void ARM_addSysReg(MCInst *MI, arm_sysreg reg)
2615{
2616 if (MI->csh->detail) {
2617 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SYSREG;
2618 MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
2619 MI->flat_insn->detail->arm.op_count++;
2620 }
2621}
2622
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +08002623#endif