blob: 76f894e9753c308ea5bc57efccc834c19a1424b9 [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
14/* Capstone Disassembler Engine */
15/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
16
17#include <stdio.h> // DEBUG
18#include <stdbool.h>
19#include <stdlib.h>
20#include <string.h>
21#include <inttypes.h>
22
23#include "ARMInstPrinter.h"
24#include "ARMAddressingModes.h"
25#include "ARMBaseInfo.h"
26#include "../../MCInst.h"
27#include "../../SStream.h"
28#include "../../MCRegisterInfo.h"
29#include "../../utils.h"
30#include "mapping.h"
31
32static void printRegName(SStream *OS, unsigned RegNo);
33
34// Autogenerated by tblgen.
35static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
36static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
37static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
38static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
39
40static void printAddrModeTBB(MCInst *MI, unsigned OpNum, SStream *O);
41static void printAddrModeTBH(MCInst *MI, unsigned OpNum, SStream *O);
42static void printAddrMode2Operand(MCInst *MI, unsigned OpNum, SStream *O);
43static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);
44static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
45static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
46static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
47static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O);
48static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);
49static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);
50static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
51static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
52static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
53static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O);
54static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O);
55static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
56
57static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
58static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O);
59static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
60static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
61static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
62static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned);
63static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
64static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O);
65static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O);
66static void printThumbAddrModeRROperand(MCInst *MI, unsigned OpNum, SStream *O);
67static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale);
68static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned OpNum, SStream *O);
69static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned OpNum, SStream *O);
70static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned OpNum, SStream *O);
71static void printThumbAddrModeSPOperand(MCInst *MI, unsigned OpNum, SStream *O);
72static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O);
73static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
74static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
75static void printT2AddrModeImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
76static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
77static void printT2AddrModeImm8OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
78static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
79static void printT2AddrModeSoRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
80static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O);
81static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O);
82static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O);
83static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O);
84static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
85static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
86static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O);
87static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O);
88static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O);
89static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O);
90static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O);
91static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O);
92static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
93static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
94static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O);
95static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
96static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
97static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O);
98static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O);
99static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O);
100static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O);
101static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O);
102static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
103static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
104static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O);
105static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O);
106static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
107static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
108static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
109static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
110static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
111static void printVectorListThreeSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
112static void printVectorListFourSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
113static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O);
114static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O);
115
116static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);
117
118// FIXME: make this status session's specific, not global like this
119static bool doing_mem = false;
120static void set_mem_access(MCInst *MI, bool status)
121{
122 doing_mem = status;
123 if (doing_mem) {
124 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_MEM;
125 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = ARM_REG_INVALID;
126 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = ARM_REG_INVALID;
127 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.scale = 1;
128 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = 0;
129 } else {
130 // done, create the next operand slot
131 MI->pub_insn.arm.op_count++;
132 }
133}
134
135#define GET_INSTRINFO_ENUM
136#include "ARMGenInstrInfo.inc"
137
138//#define PRINT_ALIAS_INSTR
139#include "ARMGenAsmWriter.inc"
140
141#define UseMarkup false
142#define markup(x) (UseMarkup? (x) : "")
143
144/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
145///
146/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
147static unsigned translateShiftImm(unsigned imm)
148{
149 // lsr #32 and asr #32 exist, but should be encoded as a 0.
150 //assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
151 if (imm == 0)
152 return 32;
153 return imm;
154}
155
156/// Prints the shift value with an immediate value.
157static void printRegImmShift(MCInst *MI, SStream *O, ARM_AM_ShiftOpc ShOpc,
158 unsigned ShImm, bool _UseMarkup)
159{
160 if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
161 return;
162 SStream_concat(O, ", ");
163
164 //assert (!(ShOpc == ARM_AM_ror && !ShImm) && "Cannot have ror #0");
165 SStream_concat(O, ARM_AM_getShiftOpcStr(ShOpc));
166 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ShOpc;
167
168 if (ShOpc != ARM_AM_rrx) {
169 SStream_concat(O, " ");
170 if (_UseMarkup)
171 SStream_concat(O, "<imm:");
172 SStream_concat(O, "#0x%x", translateShiftImm(ShImm));
173 if (_UseMarkup)
174 SStream_concat(O, ">");
175 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = translateShiftImm(ShImm);
176 }
177}
178
179static void printRegName(SStream *OS, unsigned RegNo)
180{
181 SStream_concat(OS, markup("<reg:"));
182 SStream_concat(OS, getRegisterName(RegNo));
183 SStream_concat(OS, markup(">"));
184}
185
186static name_map insn_update_flgs[] = {
187 { ARM_INS_CMN, "cmn" },
188 { ARM_INS_CMP, "cmp" },
189 { ARM_INS_TEQ, "teq" },
190 { ARM_INS_TST, "tst" },
191
192 { ARM_INS_ADC, "adcs" },
193 { ARM_INS_ADD, "adds" },
194 { ARM_INS_AND, "ands" },
195 { ARM_INS_ASR, "asrs" },
196 { ARM_INS_BIC, "bics" },
197 { ARM_INS_EOR, "eors" },
198 { ARM_INS_LSL, "lsls" },
199 { ARM_INS_LSR, "lsrs" },
200 { ARM_INS_MLA, "mlas" },
201 { ARM_INS_MOV, "movs" },
202 { ARM_INS_MUL, "muls" },
203 { ARM_INS_MVN, "mvns" },
204 { ARM_INS_ORN, "orns" },
205 { ARM_INS_ORR, "orrs" },
206 { ARM_INS_ROR, "rors" },
207 { ARM_INS_RRX, "rrxs" },
208 { ARM_INS_RSB, "rsbs" },
209 { ARM_INS_RSC, "rscs" },
210 { ARM_INS_SBC, "sbcs" },
211 { ARM_INS_SMLAL, "smlals" },
212 { ARM_INS_SMULL, "smulls" },
213 { ARM_INS_SUB, "subs" },
214 { ARM_INS_UMLAL, "umlals" },
215 { ARM_INS_UMULL, "umulls" },
216};
217
218void ARM_post_printer(unsigned int insn, cs_insn *pub_insn, char *insn_asm)
219{
220 // check if this insn requests write-back
221 if (strrchr(insn_asm, '!') != NULL) {
222 pub_insn->arm.writeback = true;
223 }
224
225 // check if this insn requests update flags
226 if (pub_insn->arm.update_flags == false) {
227 // some insn still update flags, regardless of tabgen info
228 int i;
229
230 for (i = 0; i < ARR_SIZE(insn_update_flgs); i++) {
231 if (insn == insn_update_flgs[i].id &&
232 !strncmp(insn_asm, insn_update_flgs[i].name,
233 strlen(insn_update_flgs[i].name))) {
234 pub_insn->arm.update_flags = true;
235 // we have to update regs_write array as well
236 int j;
237 for (j = 0; j < ARR_SIZE(pub_insn->regs_write); j++) {
238 if (pub_insn->regs_write[j] == 0) {
239 pub_insn->regs_write[j] = ARM_REG_CPSR;
240 break;
241 }
242 }
243 break;
244 }
245 }
246 }
247}
248
249void ARM_printInst(MCInst *MI, SStream *O, void *Info)
250{
251 MCRegisterInfo *MRI = (MCRegisterInfo *)Info;
252
253 unsigned Opcode = MCInst_getOpcode(MI);
254
255 // Check for HINT instructions w/ canonical names.
256 if (Opcode == ARM_HINT || Opcode == ARM_t2HINT) {
257 switch (MCOperand_getImm(MCInst_getOperand(MI, 0))) {
258 case 0: SStream_concat(O, "nop"); break;
259 case 1: SStream_concat(O, "yield"); break;
260 case 2: SStream_concat(O, "wfe"); break;
261 case 3: SStream_concat(O, "wfi"); break;
262 case 4: SStream_concat(O, "sev"); break;
263 case 5:
264 /*
265 if ((getAvailableFeatures() & ARM_HasV8Ops)) {
266 O << "\tsevl";
267 break;
268 } // Fallthrough for non-v8
269 */
270 SStream_concat(O, "sevl"); break;
271 default:
272 // Anything else should just print normally.
273 printInstruction(MI, O, MRI);
274 return;
275 }
276 printPredicateOperand(MI, 1, O);
277 if (Opcode == ARM_t2HINT)
278 SStream_concat(O, ".w"); // FIXME: expose this in register-size of insn?
279 return;
280 }
281
282 // Check for MOVs and print canonical forms, instead.
283 if (Opcode == ARM_MOVsr) {
284 // FIXME: Thumb variants?
285 MCOperand *Dst = MCInst_getOperand(MI, 0);
286 MCOperand *MO1 = MCInst_getOperand(MI, 1);
287 MCOperand *MO2 = MCInst_getOperand(MI, 2);
288 MCOperand *MO3 = MCInst_getOperand(MI, 3);
289
290 SStream_concat(O, ARM_AM_getShiftOpcStr(ARM_AM_getSORegShOp(MCOperand_getImm(MO3))));
291 printSBitModifierOperand(MI, 6, O);
292 printPredicateOperand(MI, 4, O);
293
294 SStream_concat(O, "\t");
295 printRegName(O, MCOperand_getReg(Dst));
296 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
297 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(Dst);
298 MI->pub_insn.arm.op_count++;
299
300 SStream_concat(O, ", ");
301 printRegName(O, MCOperand_getReg(MO1));
302 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
303 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
304 MI->pub_insn.arm.op_count++;
305
306 SStream_concat(O, ", ");
307 printRegName(O, MCOperand_getReg(MO2));
308 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
309 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO2);
310 MI->pub_insn.arm.op_count++;
311 //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
312 return;
313 }
314
315 if (Opcode == ARM_MOVsi) {
316 // FIXME: Thumb variants?
317 MCOperand *Dst = MCInst_getOperand(MI, 0);
318 MCOperand *MO1 = MCInst_getOperand(MI, 1);
319 MCOperand *MO2 = MCInst_getOperand(MI, 2);
320
321 SStream_concat(O, ARM_AM_getShiftOpcStr(ARM_AM_getSORegShOp(MCOperand_getImm(MO2))));
322 printSBitModifierOperand(MI, 5, O);
323 printPredicateOperand(MI, 3, O);
324
325 SStream_concat(O, "\t");
326 printRegName(O, MCOperand_getReg(Dst));
327 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
328 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(Dst);
329 MI->pub_insn.arm.op_count++;
330
331 SStream_concat(O, ", ");
332 printRegName(O, MCOperand_getReg(MO1));
333 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
334 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
335 MI->pub_insn.arm.op_count++;
336
337 if (ARM_AM_getSORegShOp(MCOperand_getImm(MO2)) == ARM_AM_rrx) {
338 //printAnnotation(O, Annot);
339 return;
340 }
341
342 SStream_concat(O, ", %s", markup("<imm:"));
343 SStream_concat(O, "#0x%x", translateShiftImm(getSORegOffset(MCOperand_getImm(MO2))));
344 SStream_concat(O, markup(">"));
345 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_AM_getSORegShOp(MCOperand_getImm(MO2));
346 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = translateShiftImm(getSORegOffset(MCOperand_getImm(MO2)));
347 return;
348 }
349
350 // A8.6.123 PUSH
351 if ((Opcode == ARM_STMDB_UPD || Opcode == ARM_t2STMDB_UPD) &&
352 MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
353 MCInst_getNumOperands(MI) > 5) {
354 // Should only print PUSH if there are at least two registers in the list.
355 SStream_concat(O, "push");
356 printPredicateOperand(MI, 2, O);
357 if (Opcode == ARM_t2STMDB_UPD)
358 SStream_concat(O, ".w");
359 SStream_concat(O, "\t");
360 printRegisterList(MI, 4, O);
361 return;
362 }
363
364 if (Opcode == ARM_STR_PRE_IMM && MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&
365 MCOperand_getImm(MCInst_getOperand(MI, 3)) == -4) {
366 SStream_concat(O, "push");
367 printPredicateOperand(MI, 4, O);
368 SStream_concat(O, "\t{");
369 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, 1)));
370 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
371 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));
372 MI->pub_insn.arm.op_count++;
373 SStream_concat(O, "}");
374 return;
375 }
376
377 // A8.6.122 POP
378 if ((Opcode == ARM_LDMIA_UPD || Opcode == ARM_t2LDMIA_UPD) &&
379 MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
380 MCInst_getNumOperands(MI) > 5) {
381 // Should only print POP if there are at least two registers in the list.
382 SStream_concat(O, "pop");
383 printPredicateOperand(MI, 2, O);
384 if (Opcode == ARM_t2LDMIA_UPD)
385 SStream_concat(O, ".w");
386 SStream_concat(O, "\t");
387 printRegisterList(MI, 4, O);
388 return;
389 }
390
391 if (Opcode == ARM_LDR_POST_IMM && MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&
392 MCOperand_getImm(MCInst_getOperand(MI, 4)) == 4) {
393 SStream_concat(O, "pop");
394 printPredicateOperand(MI, 5, O);
395 SStream_concat(O, "\t{");
396 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, 0)));
397 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
398 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
399 MI->pub_insn.arm.op_count++;
400 SStream_concat(O, "}");
401 return;
402 }
403
404 // A8.6.355 VPUSH
405 if ((Opcode == ARM_VSTMSDB_UPD || Opcode == ARM_VSTMDDB_UPD) &&
406 MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
407 SStream_concat(O, "vpush");
408 printPredicateOperand(MI, 2, O);
409 SStream_concat(O, "\t");
410 printRegisterList(MI, 4, O);
411 return;
412 }
413
414 // A8.6.354 VPOP
415 if ((Opcode == ARM_VLDMSIA_UPD || Opcode == ARM_VLDMDIA_UPD) &&
416 MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
417 SStream_concat(O, "vpop");
418 printPredicateOperand(MI, 2, O);
419 SStream_concat(O, "\t");
420 printRegisterList(MI, 4, O);
421 return;
422 }
423
424 if (Opcode == ARM_tLDMIA) {
425 bool Writeback = true; // FIXME: expose this
426 unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, 0));
427 unsigned i;
428 for (i = 3; i < MCInst_getNumOperands(MI); ++i) {
429 if (MCOperand_getReg(MCInst_getOperand(MI, i)) == BaseReg)
430 Writeback = false;
431 }
432
433 SStream_concat(O, "ldm");
434
435 printPredicateOperand(MI, 1, O);
436 SStream_concat(O, "\t");
437 printRegName(O, BaseReg);
438 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
439 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = BaseReg;
440 MI->pub_insn.arm.op_count++;
441 if (Writeback) SStream_concat(O, "!");
442 SStream_concat(O, ", ");
443 printRegisterList(MI, 3, O);
444 return;
445 }
446
447 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
448 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
449 // a single GPRPair reg operand is used in the .td file to replace the two
450 // GPRs. However, when decoding them, the two GRPs cannot be automatically
451 // expressed as a GPRPair, so we have to manually merge them.
452 // FIXME: We would really like to be able to tablegen'erate this.
453 if (Opcode == ARM_LDREXD || Opcode == ARM_STREXD ||
454 Opcode == ARM_LDAEXD || Opcode == ARM_STLEXD) {
455 MCRegisterClass* MRC = MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);
456 bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;
457
458 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, isStore ? 1 : 0));
459 if (MCRegisterClass_contains(MRC, Reg)) {
460 MCInst NewMI;
461 MCOperand *NewReg;
462 MCInst_setOpcode(&NewMI, Opcode);
463
464 if (isStore)
465 MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, 0));
466 NewReg = MCOperand_CreateReg(MCRegisterInfo_getMatchingSuperReg(MRI, Reg, ARM_gsub_0,
467 MCRegisterInfo_getRegClass(MRI, ARM_GPRPairRegClassID)));
468 MCInst_addOperand2(&NewMI, NewReg);
469 free(NewReg);
470
471 // Copy the rest operands into NewMI.
472 unsigned i;
473 for(i= isStore ? 3 : 2; i < MCInst_getNumOperands(MI); ++i)
474 MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, i));
475 printInstruction(&NewMI, O, MRI);
476 return;
477 }
478 }
479
480 //if (printAliasInstr(MI, O, MRI))
481 // printInstruction(MI, O, MRI);
482 printInstruction(MI, O, MRI);
483}
484
485static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
486{
487 MCOperand *Op = MCInst_getOperand(MI, OpNo);
488 if (MCOperand_isReg(Op)) {
489 unsigned Reg = MCOperand_getReg(Op);
490 printRegName(O, Reg);
491 if (doing_mem) {
492 if (MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base == ARM_REG_INVALID)
493 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = Reg;
494 else
495 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = Reg;
496 } else {
497 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
498 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg;
499 MI->pub_insn.arm.op_count++;
500 }
501 } else if (MCOperand_isImm(Op)) {
502 SStream_concat(O, markup("<imm:"));
503 //O << "#" << formatImm(Op.getImm());
504 int64_t imm = MCOperand_getImm(Op);
505
506 // relative branch only has relative offset, so we have to update it
507 // to reflect absolute address.
508 // Note: in ARM, PC is always 2 instructions ahead, so we have to
509 // add 8 in ARM mode, or 4 in Thumb mode
510 if (ARM_rel_branch(MCInst_getOpcode(MI))) {
511 // only do this for relative branch
512 if (MI->mode & CS_MODE_THUMB)
513 imm += MI->pub_insn.address + 4;
514 else
515 imm += MI->pub_insn.address + 8;
516 }
517
518 if (imm == 0)
519 SStream_concat(O, "#0");
520 else if (imm > 0)
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +0800521 SStream_concat(O, "#0x%x", imm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800522 else
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +0800523 SStream_concat(O, "#-0x%x", -imm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800524 SStream_concat(O, markup(">"));
525 if (doing_mem)
526 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = imm;
527 else {
528 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
529 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = imm;
530 MI->pub_insn.arm.op_count++;
531 }
532 }
533}
534
535static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O)
536{
537 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
538
539 SStream_concat(O, "%s[pc, ", markup("<mem:"));
540
541 int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
542 bool isSub = OffImm < 0;
543
544 // Special value for #-0. All others are normal.
545 if (OffImm == INT32_MIN)
546 OffImm = 0;
547 if (isSub) {
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +0800548 SStream_concat(O, "%s#-0x%x%s", markup("<imm:"), -OffImm, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800549 } else {
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +0800550 SStream_concat(O, "%s#0x%x%s", markup("<imm:"), OffImm, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800551 }
552
553 SStream_concat(O, "]%s", markup(">"));
554}
555
556// so_reg is a 4-operand unit corresponding to register forms of the A5.1
557// "Addressing Mode 1 - Data-processing operands" forms. This includes:
558// REG 0 0 - e.g. R5
559// REG REG 0,SH_OPC - e.g. R5, ROR R3
560// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
561static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
562{
563 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
564 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
565 MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
566
567 printRegName(O, MCOperand_getReg(MO1));
568
569 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
570 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
571
572 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.type = (MCOperand_getImm(MO3) & 7) + ARM_SFT_ASR_REG - 1;
573 MI->pub_insn.arm.op_count++;
574
575 // Print the shift opc.
576 ARM_AM_ShiftOpc ShOpc = ARM_AM_getSORegShOp(MCOperand_getImm(MO3));
577 SStream_concat(O, ", ");
578 SStream_concat(O, ARM_AM_getShiftOpcStr(ShOpc));
579 if (ShOpc == ARM_AM_rrx)
580 return;
581
582 SStream_concat(O, " ");
583 printRegName(O, MCOperand_getReg(MO2));
584 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = MCOperand_getReg(MO2);
585 //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
586}
587
588static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
589{
590 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
591 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
592
593 printRegName(O, MCOperand_getReg(MO1));
594 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
595 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
596 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.type = MCOperand_getImm(MO2) & 7;
597 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.value = MCOperand_getImm(MO2) >> 3;
598 MI->pub_insn.arm.op_count++;
599
600 // Print the shift opc.
601 printRegImmShift(MI, O, ARM_AM_getSORegShOp(MCOperand_getImm(MO2)),
602 getSORegOffset(MCOperand_getImm(MO2)), UseMarkup);
603}
604
605//===--------------------------------------------------------------------===//
606// Addressing Mode #2
607//===--------------------------------------------------------------------===//
608
609static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
610{
611 MCOperand *MO1 = MCInst_getOperand(MI, Op);
612 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
613 MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
614
615 SStream_concat(O, "%s[", markup("<mem:"));
616 set_mem_access(MI, true);
617
618 printRegName(O, MCOperand_getReg(MO1));
619 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
620
621 if (!MCOperand_getReg(MO2)) {
622 if (getAM2Offset(MCOperand_getImm(MO3))) { // Don't print +0.
623 SStream_concat(O, ", %s", markup("<imm:"));
624 SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(getAM2Op(MCOperand_getImm(MO3))), getAM2Offset(MCOperand_getImm(MO3)));
625 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.type = getAM2Op(MCOperand_getImm(MO3));
626 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.value = getAM2Offset(MCOperand_getImm(MO3));
627 SStream_concat(O, markup(">"));
628 }
629 SStream_concat(O, "]%s", markup(">"));
630 set_mem_access(MI, false);
631 return;
632 }
633
634 SStream_concat(O, ", ");
635 SStream_concat(O, ARM_AM_getAddrOpcStr(getAM2Op(MCOperand_getImm(MO3))));
636 printRegName(O, MCOperand_getReg(MO2));
637 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = MCOperand_getReg(MO2);
638
639 printRegImmShift(MI, O, getAM2ShiftOpc(MCOperand_getImm(MO3)),
640 getAM2Offset(MCOperand_getImm(MO3)), UseMarkup);
641 SStream_concat(O, "]%s", markup(">"));
642 set_mem_access(MI, false);
643}
644
645static void printAddrModeTBB(MCInst *MI, unsigned Op, SStream *O)
646{
647 MCOperand *MO1 = MCInst_getOperand(MI, Op);
648 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
649 SStream_concat(O, "%s[", markup("<mem:"));
650 set_mem_access(MI, true);
651 printRegName(O, MCOperand_getReg(MO1));
652 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
653 SStream_concat(O, ", ");
654 printRegName(O, MCOperand_getReg(MO2));
655 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = MCOperand_getReg(MO2);
656 SStream_concat(O, "]%s", markup(">"));
657 set_mem_access(MI, false);
658}
659
660static void printAddrModeTBH(MCInst *MI, unsigned Op, SStream *O)
661{
662 MCOperand *MO1 = MCInst_getOperand(MI, Op);
663 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
664 SStream_concat(O, "%s[", markup("<mem:"));
665 set_mem_access(MI, true);
666 printRegName(O, MCOperand_getReg(MO1));
667 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
668 SStream_concat(O, ", ");
669 printRegName(O, MCOperand_getReg(MO2));
670 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = MCOperand_getReg(MO2);
671 SStream_concat(O, ", lsl %s #1%s]%s", markup("<imm:"), markup(">"), markup(">"));
672 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.type = ARM_SFT_LSL;
673 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].shift.value = 1;
674 set_mem_access(MI, false);
675}
676
677static void printAddrMode2Operand(MCInst *MI, unsigned Op, SStream *O)
678{
679 MCOperand *MO1 = MCInst_getOperand(MI, Op);
680
681 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
682 printOperand(MI, Op, O);
683 return;
684 }
685
686 printAM2PreOrOffsetIndexOp(MI, Op, O);
687}
688
689static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
690{
691 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
692 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
693
694 if (!MCOperand_getReg(MO1)) {
695 unsigned ImmOffs = getAM2Offset(MCOperand_getImm(MO2));
696 SStream_concat(O, "%s #%s0x%x%s", markup("<imm:"),
697 ARM_AM_getAddrOpcStr(getAM2Op(MCOperand_getImm(MO2))), ImmOffs,
698 markup(">"));
699 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
700 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = ImmOffs;
701 MI->pub_insn.arm.op_count++;
702 return;
703 }
704
705 SStream_concat(O, ARM_AM_getAddrOpcStr(getAM2Op(MCOperand_getImm(MO2))));
706 printRegName(O, MCOperand_getReg(MO1));
707 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
708 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
709 MI->pub_insn.arm.op_count++;
710
711 printRegImmShift(MI, O, getAM2ShiftOpc(MCOperand_getImm(MO2)),
712 getAM2Offset(MCOperand_getImm(MO2)), UseMarkup);
713}
714
715//===--------------------------------------------------------------------===//
716// Addressing Mode #3
717//===--------------------------------------------------------------------===//
718
719static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O)
720{
721 MCOperand *MO1 = MCInst_getOperand(MI, Op);
722 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
723 MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
724
725 SStream_concat(O, "%s[", markup("<mem:"));
726 set_mem_access(MI, true);
727 printRegName(O, MCOperand_getReg(MO1));
728 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
729 SStream_concat(O, "], %s", markup(">"));
730 set_mem_access(MI, false);
731
732 if (MCOperand_getReg(MO2)) {
733 SStream_concat(O, "%c", (char)getAM3Op(MCOperand_getImm(MO3)));
734 printRegName(O, MCOperand_getReg(MO2));
735 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
736 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO2);
737 MI->pub_insn.arm.op_count++;
738 return;
739 }
740
741 unsigned ImmOffs = getAM3Offset(MCOperand_getImm(MO3));
742 SStream_concat(O, "%s#%s0x%x%s", markup("<imm:"),
743 ARM_AM_getAddrOpcStr(getAM3Op(MCOperand_getImm(MO3))), ImmOffs,
744 markup(">"));
745 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
746 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = ImmOffs;
747 MI->pub_insn.arm.op_count++;
748}
749
750static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
751 bool AlwaysPrintImm0)
752{
753 MCOperand *MO1 = MCInst_getOperand(MI, Op);
754 MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
755 MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
756
757 SStream_concat(O, "%s[", markup("<mem:"));
758 set_mem_access(MI, true);
759 printRegName(O, MCOperand_getReg(MO1));
760 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
761
762 if (MCOperand_getReg(MO2)) {
763 SStream_concat(O, ", %s", ARM_AM_getAddrOpcStr(getAM3Op(MCOperand_getImm(MO3))));
764 printRegName(O, MCOperand_getReg(MO2));
765 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = MCOperand_getReg(MO2);
766 if (getAM3Op(MCOperand_getImm(MO3)))
767 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.scale = -1;
768 SStream_concat(O, "]%s", markup(">"));
769 set_mem_access(MI, false);
770 return;
771 }
772
773 //If the op is sub we have to print the immediate even if it is 0
774 unsigned ImmOffs = getAM3Offset(MCOperand_getImm(MO3));
775 ARM_AM_AddrOpc op = getAM3Op(MCOperand_getImm(MO3));
776
777 if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM_sub)) {
778 SStream_concat(O, ", %s#%s0x%x%s", markup("<imm:"), ARM_AM_getAddrOpcStr(op),
779 ImmOffs, markup(">"));
780 }
781 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = MCOperand_getImm(MO3);
782 SStream_concat(O, "]%s", markup(">"));
783 set_mem_access(MI, false);
784}
785
786static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,
787 bool AlwaysPrintImm0)
788{
789 MCOperand *MO1 = MCInst_getOperand(MI, Op);
790 if (!MCOperand_isReg(MO1)) { // For label symbolic references.
791 printOperand(MI, Op, O);
792 return;
793 }
794
795 MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
796 unsigned IdxMode = getAM3IdxMode(MCOperand_getImm(MO3));
797
798 if (IdxMode == ARMII_IndexModePost) {
799 printAM3PostIndexOp(MI, Op, O);
800 return;
801 }
802 printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
803}
804
805static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
806{
807 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
808 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
809
810 if (MCOperand_getReg(MO1)) {
811 SStream_concat(O, ARM_AM_getAddrOpcStr(getAM3Op(MCOperand_getImm(MO2))));
812 printRegName(O, MCOperand_getReg(MO1));
813 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
814 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getReg(MO1);
815 MI->pub_insn.arm.op_count++;
816 return;
817 }
818
819 unsigned ImmOffs = getAM3Offset(MCOperand_getImm(MO2));
820 SStream_concat(O, "%s#%s0x%x%s", markup("<imm:"),
821 ARM_AM_getAddrOpcStr(getAM3Op(MCOperand_getImm(MO2))), ImmOffs,
822 markup(">"));
823 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
824 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = ImmOffs;
825 MI->pub_insn.arm.op_count++;
826}
827
828static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O)
829{
830 MCOperand *MO = MCInst_getOperand(MI, OpNum);
831 unsigned Imm = MCOperand_getImm(MO);
832 SStream_concat(O, "%s#0x%s0x%x%s", markup("<imm:"), ((Imm & 256) ? "" : "-"),
833 (Imm & 0xff), markup(">"));
834 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
835 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = Imm & 0xff;
836 MI->pub_insn.arm.op_count++;
837}
838
839static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
840{
841 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
842 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
843
844 SStream_concat(O, (MCOperand_getImm(MO2) ? "" : "-"));
845 printRegName(O, MCOperand_getReg(MO1));
846 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
847 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO1);
848 MI->pub_insn.arm.op_count++;
849}
850
851static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
852{
853 MCOperand *MO = MCInst_getOperand(MI, OpNum);
854 unsigned Imm = MCOperand_getImm(MO);
855 SStream_concat(O, "%s#%s0x%x%s", markup("<imm:"), ((Imm & 256) ? "" : "-"),
856 ((Imm & 0xff) << 2), markup(">"));
857}
858
859static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
860 bool AlwaysPrintImm0)
861{
862 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
863 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
864
865 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
866 printOperand(MI, OpNum, O);
867 return;
868 }
869
870 SStream_concat(O, "%s[", markup("<mem:"));
871 printRegName(O, MCOperand_getReg(MO1));
872
873 unsigned ImmOffs = ARM_AM_getAM5Offset(MCOperand_getImm(MO2));
874 unsigned Op = ARM_AM_getAM5Op(MCOperand_getImm(MO2));
875 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {
876 SStream_concat(O, ", %s#%s0x%x%s", markup("<imm:"),
877 ARM_AM_getAddrOpcStr(ARM_AM_getAM5Op(MCOperand_getImm(MO2))),
878 ImmOffs * 4, markup(">"));
879 }
880 SStream_concat(O, "]%s", markup(">"));
881}
882
883static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O)
884{
885 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
886 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
887
888 SStream_concat(O, "%s[", markup("<mem:"));
889 set_mem_access(MI, true);
890 printRegName(O, MCOperand_getReg(MO1));
891 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
892 if (MCOperand_getImm(MO2)) {
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +0800893 SStream_concat(O, ":0x%x", (MCOperand_getImm(MO2) << 3));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800894 // FIXME below line??
895 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = MCOperand_getImm(MO2) << 3;
896 }
897 SStream_concat(O, "]%s", markup(">"));
898 set_mem_access(MI, false);
899}
900
901static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)
902{
903 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
904 SStream_concat(O, "%s[", markup("<mem:"));
905 set_mem_access(MI, true);
906 printRegName(O, MCOperand_getReg(MO1));
907 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
908 SStream_concat(O, "]%s", markup(">"));
909 set_mem_access(MI, false);
910}
911
912static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
913{
914 MCOperand *MO = MCInst_getOperand(MI, OpNum);
915 if (MCOperand_getReg(MO) == 0)
916 SStream_concat(O, "!");
917 else {
918 SStream_concat(O, ", ");
919 printRegName(O, MCOperand_getReg(MO));
920 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
921 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MO);
922 MI->pub_insn.arm.op_count++;
923 }
924}
925
926static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
927{
928 MCOperand *MO = MCInst_getOperand(MI, OpNum);
929 uint32_t v = ~MCOperand_getImm(MO);
930 int32_t lsb = CountTrailingZeros_32(v);
931 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
932 //assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
933 SStream_concat(O, "%s#0x%x%s, %s#0x%x%s", markup("<imm:"), lsb, markup(">"),
934 markup("<imm:"), width, markup(">"));
935 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
936 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = lsb;
937 MI->pub_insn.arm.op_count++;
938 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
939 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = width;
940 MI->pub_insn.arm.op_count++;
941}
942
943static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O)
944{
945 unsigned val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
946 //SStream_concat(O, ARM_MB_MemBOptToString(val), (getAvailableFeatures() & ARM::HasV8Ops));
947 SStream_concat(O, ARM_MB_MemBOptToString(val, true));
948}
949
950void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)
951{
952 unsigned val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
953 SStream_concat(O, "%s", ARM_ISB_InstSyncBOptToString(val));
954}
955
956static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
957{
958 unsigned ShiftOp = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
959 bool isASR = (ShiftOp & (1 << 5)) != 0;
960 unsigned Amt = ShiftOp & 0x1f;
961 if (isASR) {
962 SStream_concat(O, ", asr %s#0x%x%s", markup("<imm:"), (Amt == 0 ? 32 : Amt),
963 markup(">"));
964 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_ASR;
965 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = (Amt == 0 ? 32 : Amt);
966 } else if (Amt) {
967 SStream_concat(O, ", lsl %s#0x%x%s", markup("<imm:"), Amt, markup(">"));
968 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_LSL;
969 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = Amt;
970 }
971}
972
973static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
974{
975 unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
976 if (Imm == 0)
977 return;
978 //assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
979 SStream_concat(O, ", lsl %s#0x%x%s", markup("<imm:"), Imm, markup(">"));
980 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_LSL;
981 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = Imm;
982}
983
984static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
985{
986 unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
987 // A shift amount of 32 is encoded as 0.
988 if (Imm == 0)
989 Imm = 32;
990 //assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
991 SStream_concat(O, ", asr %s#0x%x%s", markup("<imm:"), Imm, markup(">"));
992 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_ASR;
993 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = Imm;
994}
995
996// FIXME: push {r1, r2, r3, ...} can exceed the number of operands in MCInst struct
997static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O)
998{
999 SStream_concat(O, "{");
1000 unsigned i, e;
1001 for (i = OpNum, e = MCInst_getNumOperands(MI); i != e; ++i) {
1002 if (i != OpNum) SStream_concat(O, ", ");
1003 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, i)));
1004 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1005 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, i));
1006 MI->pub_insn.arm.op_count++;
1007 }
1008 SStream_concat(O, "}");
1009}
1010
1011static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O,
1012 MCRegisterInfo *MRI)
1013{
1014 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1015 printRegName(O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0));
1016 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1017 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0);
1018 MI->pub_insn.arm.op_count++;
1019 SStream_concat(O, ", ");
1020 printRegName(O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1));
1021 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1022 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1);
1023 MI->pub_insn.arm.op_count++;
1024}
1025
1026// SETEND BE/LE
1027static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O)
1028{
1029 MCOperand *Op = MCInst_getOperand(MI, OpNum);
1030 if (MCOperand_getImm(Op))
1031 SStream_concat(O, "be");
1032 else
1033 SStream_concat(O, "le");
1034}
1035
1036static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O)
1037{
1038 MCOperand *Op = MCInst_getOperand(MI, OpNum);
1039 SStream_concat(O, ARM_PROC_IModToString(MCOperand_getImm(Op)));
1040 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1041 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(Op);
1042 MI->pub_insn.arm.op_count++;
1043}
1044
1045static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O)
1046{
1047 MCOperand *Op = MCInst_getOperand(MI, OpNum);
1048 unsigned IFlags = MCOperand_getImm(Op);
1049 int i;
1050 for (i=2; i >= 0; --i)
1051 if (IFlags & (1 << i))
1052 SStream_concat(O, ARM_PROC_IFlagsToString(1 << i));
1053
1054 if (IFlags == 0)
1055 SStream_concat(O, "none");
1056
1057 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1058 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = IFlags;
1059 MI->pub_insn.arm.op_count++;
1060}
1061
1062// TODO
1063static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O)
1064{
1065 MCOperand *Op = MCInst_getOperand(MI, OpNum);
1066 unsigned SpecRegRBit = MCOperand_getImm(Op) >> 4;
1067 unsigned Mask = MCOperand_getImm(Op) & 0xf;
1068
1069 //if (getAvailableFeatures() & ARM_FeatureMClass) {
1070 if (true) {
1071 unsigned SYSm = MCOperand_getImm(Op);
1072 unsigned Opcode = MCInst_getOpcode(MI);
1073 // For reads of the special registers ignore the "mask encoding" bits
1074 // which are only for writes.
1075 if (Opcode == ARM_t2MRS_M)
1076 SYSm &= 0xff;
1077 switch (SYSm) {
1078 default: return; //llvm_unreachable("Unexpected mask value!");
1079 case 0:
1080 case 0x800: SStream_concat(O, "apsr"); return; // with _nzcvq bits is an alias for aspr
1081 case 0x400: SStream_concat(O, "apsr_g"); return;
1082 case 0xc00: SStream_concat(O, "apsr_nzcvqg"); return;
1083 case 1:
1084 case 0x801: SStream_concat(O, "iapsr"); return; // with _nzcvq bits is an alias for iapsr
1085 case 0x401: SStream_concat(O, "iapsr_g"); return;
1086 case 0xc01: SStream_concat(O, "iapsr_nzcvqg"); return;
1087 case 2:
1088 case 0x802: SStream_concat(O, "eapsr"); return; // with _nzcvq bits is an alias for eapsr
1089 case 0x402: SStream_concat(O, "eapsr_g"); return;
1090 case 0xc02: SStream_concat(O, "eapsr_nzcvqg"); return;
1091 case 3:
1092 case 0x803: SStream_concat(O, "xpsr"); return; // with _nzcvq bits is an alias for xpsr
1093 case 0x403: SStream_concat(O, "xpsr_g"); return;
1094 case 0xc03: SStream_concat(O, "xpsr_nzcvqg"); return;
1095 case 5:
1096 case 0x805: SStream_concat(O, "ipsr"); return;
1097 case 6:
1098 case 0x806: SStream_concat(O, "epsr"); return;
1099 case 7:
1100 case 0x807: SStream_concat(O, "iepsr"); return;
1101 case 8:
1102 case 0x808: SStream_concat(O, "msp"); return;
1103 case 9:
1104 case 0x809: SStream_concat(O, "psp"); return;
1105 case 0x10:
1106 case 0x810: SStream_concat(O, "primask"); return;
1107 case 0x11:
1108 case 0x811: SStream_concat(O, "basepri"); return;
1109 case 0x12:
1110 case 0x812: SStream_concat(O, "basepri_max"); return;
1111 case 0x13:
1112 case 0x813: SStream_concat(O, "faultmask"); return;
1113 case 0x14:
1114 case 0x814: SStream_concat(O, "control"); return;
1115 }
1116 }
1117
1118 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
1119 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
1120 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
1121 SStream_concat(O, "APSR_");
1122 switch (Mask) {
1123 default: return; //llvm_unreachable("Unexpected mask value!");
1124 case 4: SStream_concat(O, "g"); return;
1125 case 8: SStream_concat(O, "nzcvq"); return;
1126 case 12: SStream_concat(O, "nzcvqg"); return;
1127 }
1128 }
1129
1130 if (SpecRegRBit)
1131 SStream_concat(O, "SPSR");
1132 else
1133 SStream_concat(O, "CPSR");
1134
1135 if (Mask) {
1136 SStream_concat(O, "_");
1137 if (Mask & 8) SStream_concat(O, "f");
1138 if (Mask & 4) SStream_concat(O, "s");
1139 if (Mask & 2) SStream_concat(O, "x");
1140 if (Mask & 1) SStream_concat(O, "c");
1141 }
1142}
1143
1144static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1145{
1146 ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1147 // Handle the undefined 15 CC value here for printing so we don't abort().
1148 if ((unsigned)CC == 15) {
1149 SStream_concat(O, "<und>");
1150 MI->pub_insn.arm.cc = ARM_CC_INVALID;
1151 } else {
1152 if (CC != ARMCC_AL) {
1153 SStream_concat(O, ARMCC_ARMCondCodeToString(CC));
1154 }
1155 MI->pub_insn.arm.cc = CC + 1;
1156 }
1157}
1158
1159// TODO: test this
1160static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1161{
1162 ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1163 SStream_concat(O, ARMCC_ARMCondCodeToString(CC));
1164 MI->pub_insn.arm.cc = CC + 1;
1165}
1166
1167static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O)
1168{
1169 if (MCOperand_getReg(MCInst_getOperand(MI, OpNum))) {
1170 //assert(MCOperand_getReg(MCInst_getOperand(MI, OpNum)) == ARM_CPSR &&
1171 // "Expect ARM CPSR register!");
1172 MI->pub_insn.arm.update_flags = true;
1173 SStream_concat(O, "s");
1174 }
1175}
1176
1177static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1178{
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001179 SStream_concat(O, "0x%x", MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001180 if (doing_mem) {
1181 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1182 } else {
1183 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1184 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1185 MI->pub_insn.arm.op_count++;
1186 }
1187}
1188
1189static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1190{
1191 SStream_concat(O, "p%02"PRIu64, MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1192 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_PIMM;
1193 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1194 MI->pub_insn.arm.op_count++;
1195}
1196
1197static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1198{
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001199 SStream_concat(O, "c%02u", MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001200 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_CIMM;
1201 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1202 MI->pub_insn.arm.op_count++;
1203}
1204
1205static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)
1206{
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001207 SStream_concat(O, "{0x%x}", MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001208 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1209 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1210 MI->pub_insn.arm.op_count++;
1211}
1212
1213static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned scale)
1214{
1215 MCOperand *MO = MCInst_getOperand(MI, OpNum);
1216
1217 int32_t OffImm = (int32_t)MCOperand_getImm(MO) << scale;
1218
1219 SStream_concat(O, markup("<imm:"));
1220 if (OffImm == INT32_MIN) {
1221 SStream_concat(O, "#-0");
1222 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1223 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = 0;
1224 MI->pub_insn.arm.op_count++;
1225 } else {
1226 if (OffImm < 0)
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001227 SStream_concat(O, "#-0x%x", -OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001228 else
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001229 SStream_concat(O, "#0x%x", OffImm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001230 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1231 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = OffImm;
1232 MI->pub_insn.arm.op_count++;
1233 }
1234 SStream_concat(O, markup(">"));
1235}
1236
1237static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1238{
1239 //<< "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001240 SStream_concat(O, "%s#0x%x", markup("<imm:"), MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001241 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1242 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;
1243 MI->pub_insn.arm.op_count++;
1244 SStream_concat(O, markup(">"));
1245}
1246
1247static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O)
1248{
1249 unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1250 // << "#" << formatImm((Imm == 0 ? 32 : Imm))
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001251 SStream_concat(O, "%s#0x%x", markup("<imm:"), Imm == 0 ? 32 : Imm);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001252 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1253 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = Imm == 0 ? 32 : Imm;
1254 MI->pub_insn.arm.op_count++;
1255 SStream_concat(O, markup(">"));
1256}
1257
1258// TODO
1259static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O)
1260{
1261 // (3 - the number of trailing zeros) is the number of then / else.
1262 unsigned Mask = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1263 unsigned Firstcond = MCOperand_getImm(MCInst_getOperand(MI, OpNum-1));
1264 unsigned CondBit0 = Firstcond & 1;
1265 unsigned NumTZ = CountTrailingZeros_32(Mask);
1266 //assert(NumTZ <= 3 && "Invalid IT mask!");
1267 unsigned Pos, e;
1268 for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
1269 bool T = ((Mask >> Pos) & 1) == CondBit0;
1270 if (T)
1271 SStream_concat(O, "t");
1272 else
1273 SStream_concat(O, "e");
1274 }
1275}
1276
1277static void printThumbAddrModeRROperand(MCInst *MI, unsigned Op, SStream *O)
1278{
1279 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1280 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1281
1282 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1283 printOperand(MI, Op, O);
1284 return;
1285 }
1286
1287 SStream_concat(O, markup("<mem:"));
1288 SStream_concat(O, "[");
1289 set_mem_access(MI, true);
1290 printRegName(O, MCOperand_getReg(MO1));
1291 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1292 unsigned RegNum = MCOperand_getReg(MO2);
1293 if (RegNum) {
1294 SStream_concat(O, ", ");
1295 printRegName(O, RegNum);
1296 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = RegNum;
1297 }
1298 SStream_concat(O, "]");
1299 set_mem_access(MI, false);
1300 SStream_concat(O, markup(">"));
1301}
1302
1303static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned Op, SStream *O,
1304 unsigned Scale)
1305{
1306 MCOperand *MO1 = MCInst_getOperand(MI, Op);
1307 MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1308
1309 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1310 printOperand(MI, Op, O);
1311 return;
1312 }
1313
1314 SStream_concat(O, markup("<mem:"));
1315 SStream_concat(O, "[");
1316 set_mem_access(MI, true);
1317 printRegName(O, MCOperand_getReg(MO1));
1318 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1319 unsigned ImmOffs = MCOperand_getImm(MO2);
1320 if (ImmOffs) {
1321 SStream_concat(O, ", %s", markup("<imm:"));
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001322 SStream_concat(O, "#0x%x", ImmOffs * Scale);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001323 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = ImmOffs * Scale;
1324 SStream_concat(O, markup(">"));
1325 }
1326 SStream_concat(O, "]");
1327 set_mem_access(MI, false);
1328 SStream_concat(O, markup(">"));
1329}
1330
1331static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned Op, SStream *O)
1332{
1333 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
1334}
1335
1336static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned Op, SStream *O)
1337{
1338 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
1339}
1340
1341static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned Op, SStream *O)
1342{
1343 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
1344}
1345
1346static void printThumbAddrModeSPOperand(MCInst *MI, unsigned Op, SStream *O)
1347{
1348 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
1349}
1350
1351// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1352// register with shift forms.
1353// REG 0 0 - e.g. R5
1354// REG IMM, SH_OPC - e.g. R5, LSL #3
1355static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O)
1356{
1357 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1358 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1359
1360 unsigned Reg = MCOperand_getReg(MO1);
1361 printRegName(O, Reg);
1362 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1363 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg;
1364 MI->pub_insn.arm.op_count++;
1365
1366 // Print the shift opc.
1367 //assert(MO2.isImm() && "Not a valid t2_so_reg value!");
1368 printRegImmShift(MI, O, ARM_AM_getSORegShOp(MCOperand_getImm(MO2)),
1369 getSORegOffset(MCOperand_getImm(MO2)), UseMarkup);
1370}
1371
1372static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum,
1373 SStream *O, bool AlwaysPrintImm0)
1374{
1375 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1376 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1377
1378 if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1379 printOperand(MI, OpNum, O);
1380 return;
1381 }
1382
1383 SStream_concat(O, markup("<mem:"));
1384 SStream_concat(O, "[");
1385 set_mem_access(MI, true);
1386 printRegName(O, MCOperand_getReg(MO1));
1387
1388 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1389
1390 int32_t OffImm = (int32_t)MCOperand_getImm(MO2);
1391 bool isSub = OffImm < 0;
1392 // Special value for #-0. All others are normal.
1393 if (OffImm == INT32_MIN)
1394 OffImm = 0;
1395 if (isSub) {
1396 SStream_concat(O, ", %s#-0x%x%s", markup("<imm:"), -OffImm, markup(">"));
1397 } else if (AlwaysPrintImm0 || OffImm > 0) {
1398 SStream_concat(O, ", %s#0x%x%s", markup("<imm:"), OffImm, markup(">"));
1399 }
1400 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = OffImm;
1401 SStream_concat(O, "]%s", markup(">"));
1402 set_mem_access(MI, false);
1403}
1404
1405static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O,
1406 bool AlwaysPrintImm0)
1407{
1408 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1409 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1410
1411 SStream_concat(O, "%s[", markup("<mem:"));
1412 set_mem_access(MI, true);
1413
1414 printRegName(O, MCOperand_getReg(MO1));
1415 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1416
1417 int32_t OffImm = (int32_t)MCOperand_getImm(MO2);
1418 bool isSub = OffImm < 0;
1419 // Don't print +0.
1420 if (OffImm == INT32_MIN)
1421 OffImm = 0;
1422
1423 if (isSub)
1424 SStream_concat(O, ", %s#-0x%x%s", markup("<imm:"), -OffImm, markup(">"));
1425 else if (AlwaysPrintImm0 || OffImm > 0)
1426 SStream_concat(O, ", %s#0x%x%s", markup("<imm:"), OffImm, markup(">"));
1427
1428 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = OffImm;
1429 SStream_concat(O, "]%s", markup(">"));
1430 set_mem_access(MI, false);
1431}
1432
1433static void printT2AddrModeImm8s4Operand(MCInst *MI,
1434 unsigned OpNum, SStream *O, bool AlwaysPrintImm0)
1435{
1436 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1437 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1438
1439 if (!MCOperand_isReg(MO1)) { // For label symbolic references.
1440 printOperand(MI, OpNum, O);
1441 return;
1442 }
1443
1444 SStream_concat(O, markup("<mem:"));
1445 SStream_concat(O, "[");
1446 set_mem_access(MI, true);
1447 printRegName(O, MCOperand_getReg(MO1));
1448 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1449
1450 int32_t OffImm = (int32_t)MCOperand_getImm(MO2);
1451 bool isSub = OffImm < 0;
1452
1453 //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1454
1455 // Don't print +0.
1456 if (OffImm == INT32_MIN)
1457 OffImm = 0;
1458 if (isSub) {
1459 SStream_concat(O, ", %s#-0x%x%s", markup("<imm:"), -OffImm, markup(">"));
1460 } else if (AlwaysPrintImm0 || OffImm > 0) {
1461 SStream_concat(O, ", %s#0x%x%s", markup("<imm:"), OffImm, markup(">"));
1462 }
1463 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = OffImm;
1464
1465 SStream_concat(O, "]%s", markup(">"));
1466 set_mem_access(MI, false);
1467}
1468
1469static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
1470{
1471 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1472 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1473
1474 SStream_concat(O, markup("<mem:"));
1475 SStream_concat(O, "[");
1476 set_mem_access(MI, true);
1477 printRegName(O, MCOperand_getReg(MO1));
1478 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1479 if (MCOperand_getImm(MO2)) {
1480 SStream_concat(O, ", ");
1481 SStream_concat(O, markup("<imm:"));
1482 //<< "#" <<
1483 // formatImm(MCOperand_getImm(MO2.getImm() * 4)
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001484 SStream_concat(O, "#0x%x", MCOperand_getImm(MO2) * 4);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001485 SStream_concat(O, markup(">"));
1486 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.disp = MCOperand_getImm(MO2) * 4;
1487 }
1488 SStream_concat(O, "]%s", markup(">"));
1489 set_mem_access(MI, false);
1490}
1491
1492static void printT2AddrModeImm8OffsetOperand(MCInst *MI,
1493 unsigned OpNum, SStream *O)
1494{
1495 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1496 int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
1497 SStream_concat(O, ", %s", markup("<imm:"));
1498 if (OffImm == INT32_MIN) {
1499 SStream_concat(O, "#-0%s", markup(">"));
1500 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1501 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = 0;
1502 MI->pub_insn.arm.op_count++;
1503 } else {
1504 if (OffImm < 0)
1505 SStream_concat(O, "#-0x%x%s", -OffImm, markup(">"));
1506 else
1507 SStream_concat(O, "#0x%x%s", OffImm, markup(">"));
1508 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1509 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = OffImm;
1510 MI->pub_insn.arm.op_count++;
1511 }
1512}
1513
1514static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI,
1515 unsigned OpNum, SStream *O)
1516{
1517 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1518 int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
1519
1520 //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1521
1522 SStream_concat(O, ", %s", markup("<imm:"));
1523 if (OffImm == INT32_MIN) {
1524 SStream_concat(O, "#-0%s", markup(">"));
1525 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1526 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = 0;
1527 MI->pub_insn.arm.op_count++;
1528 } else {
1529 if (OffImm < 0)
1530 SStream_concat(O, "#-0x%x%s", -OffImm, markup(">"));
1531 else
1532 SStream_concat(O, "#0x%x%s", OffImm, markup(">"));
1533 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1534 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = OffImm;
1535 MI->pub_insn.arm.op_count++;
1536 }
1537}
1538
1539static void printT2AddrModeSoRegOperand(MCInst *MI,
1540 unsigned OpNum, SStream *O)
1541{
1542 MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1543 MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1544 MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
1545
1546 SStream_concat(O, "%s[", markup("<mem:"));
1547 set_mem_access(MI, true);
1548 printRegName(O, MCOperand_getReg(MO1));
1549 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.base = MCOperand_getReg(MO1);
1550
1551 //assert(MCOperand_getReg(MO2.getReg() && "Invalid so_reg load / store address!");
1552 SStream_concat(O, ", ");
1553 printRegName(O, MCOperand_getReg(MO2));
1554 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].mem.index = MCOperand_getReg(MO2);
1555
1556 unsigned ShAmt = MCOperand_getImm(MO3);
1557 if (ShAmt) {
1558 //assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
1559 SStream_concat(O, ", lsl ");
1560 SStream_concat(O, markup("<imm:"));
1561 SStream_concat(O, "#%d", ShAmt);
1562 SStream_concat(O, markup(">"));
1563 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_LSL;
1564 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = ShAmt;
1565 }
1566
1567 SStream_concat(O, "]%s", markup(">"));
1568 set_mem_access(MI, false);
1569}
1570
1571static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1572{
1573 MCOperand *MO = MCInst_getOperand(MI, OpNum);
1574 SStream_concat(O, "%s#%f%s", markup("<imm:"), getFPImmFloat(MCOperand_getImm(MO)), markup(">"));
1575 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_FP;
1576 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].fp = getFPImmFloat(MCOperand_getImm(MO));
1577 MI->pub_insn.arm.op_count++;
1578}
1579
1580static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1581{
1582 unsigned EncodedImm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1583 unsigned EltBits;
1584 uint64_t Val = ARM_AM_decodeNEONModImm(EncodedImm, &EltBits);
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001585 SStream_concat(O, "%s#0x%x%s", markup("<imm:"), Val, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001586 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1587 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = Val;
1588 MI->pub_insn.arm.op_count++;
1589}
1590
1591static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O)
1592{
1593 unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001594 SStream_concat(O, "%s#0x%x%s", markup("<imm:"), Imm + 1, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001595 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1596 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = Imm + 1;
1597 MI->pub_insn.arm.op_count++;
1598}
1599
1600static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1601{
1602 unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1603 if (Imm == 0)
1604 return;
1605 SStream_concat(O, ", ror %s#", markup("<imm:"));
1606 switch (Imm) {
1607 default: //assert (0 && "illegal ror immediate!");
1608 case 1: SStream_concat(O, "8"); break;
1609 case 2: SStream_concat(O, "16"); break;
1610 case 3: SStream_concat(O, "24"); break;
1611 }
1612 SStream_concat(O, markup(">"));
1613 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.type = ARM_SFT_ROR;
1614 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count - 1].shift.value = Imm * 8;
1615}
1616
1617static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)
1618{
1619 SStream_concat(O, markup("<imm:"));
1620 SStream_concat(O, "#0x%x", 16 - MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1621 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1622 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = 16 - MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1623 MI->pub_insn.arm.op_count++;
1624 SStream_concat(O, markup(">"));
1625}
1626
1627static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O)
1628{
1629 SStream_concat(O, markup("<imm:"));
1630 SStream_concat(O, "#0x%x", 32 - MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1631 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1632 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = 32 - MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1633 MI->pub_insn.arm.op_count++;
1634 SStream_concat(O, markup(">"));
1635}
1636
1637static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
1638{
Nguyen Anh Quynh741a9de2013-11-28 16:02:08 +08001639 SStream_concat(O, "[0x%x]", MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001640 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_IMM;
1641 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1642 MI->pub_insn.arm.op_count++;
1643}
1644
1645static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O)
1646{
1647 SStream_concat(O, "{");
1648 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1649 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1650 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1651 MI->pub_insn.arm.op_count++;
1652 SStream_concat(O, "}");
1653}
1654
1655static void printVectorListTwo(MCInst *MI, unsigned OpNum,
1656 SStream *O, MCRegisterInfo *MRI)
1657{
1658 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1659 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
1660 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
1661 SStream_concat(O, "{");
1662 printRegName(O, Reg0);
1663 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1664 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg0;
1665 MI->pub_insn.arm.op_count++;
1666 SStream_concat(O, ", ");
1667 printRegName(O, Reg1);
1668 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1669 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg1;
1670 MI->pub_insn.arm.op_count++;
1671 SStream_concat(O, "}");
1672}
1673
1674static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum,
1675 SStream *O, MCRegisterInfo *MRI)
1676{
1677 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1678 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
1679 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
1680 SStream_concat(O, "{");
1681 printRegName(O, Reg0);
1682 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1683 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg0;
1684 MI->pub_insn.arm.op_count++;
1685 SStream_concat(O, ", ");
1686 printRegName(O, Reg1);
1687 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1688 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg1;
1689 MI->pub_insn.arm.op_count++;
1690 SStream_concat(O, "}");
1691}
1692
1693static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O)
1694{
1695 // Normally, it's not safe to use register enum values directly with
1696 // addition to get the next register, but for VFP registers, the
1697 // sort order is guaranteed because they're all of the form D<n>.
1698 SStream_concat(O, "{");
1699 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1700 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1701 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1702 MI->pub_insn.arm.op_count++;
1703 SStream_concat(O, ", ");
1704 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
1705 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1706 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
1707 MI->pub_insn.arm.op_count++;
1708 SStream_concat(O, ", ");
1709 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1710 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1711 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1712 MI->pub_insn.arm.op_count++;
1713 SStream_concat(O, "}");
1714}
1715
1716static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O)
1717{
1718 // Normally, it's not safe to use register enum values directly with
1719 // addition to get the next register, but for VFP registers, the
1720 // sort order is guaranteed because they're all of the form D<n>.
1721 SStream_concat(O, "{");
1722 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1723 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1724 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1725 MI->pub_insn.arm.op_count++;
1726 SStream_concat(O, ", ");
1727 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
1728 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1729 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
1730 MI->pub_insn.arm.op_count++;
1731 SStream_concat(O, ", ");
1732 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1733 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1734 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1735 MI->pub_insn.arm.op_count++;
1736 SStream_concat(O, ", ");
1737 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
1738 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1739 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
1740 MI->pub_insn.arm.op_count++;
1741 SStream_concat(O, "}");
1742}
1743
1744static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
1745{
1746 SStream_concat(O, "{");
1747 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1748 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1749 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1750 MI->pub_insn.arm.op_count++;
1751 SStream_concat(O, "[]}");
1752}
1753
1754static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum,
1755 SStream *O, MCRegisterInfo *MRI)
1756{
1757 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1758 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
1759 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
1760 SStream_concat(O, "{");
1761 printRegName(O, Reg0);
1762 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1763 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg0;
1764 MI->pub_insn.arm.op_count++;
1765 SStream_concat(O, "[], ");
1766 printRegName(O, Reg1);
1767 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1768 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg1;
1769 MI->pub_insn.arm.op_count++;
1770 SStream_concat(O, "[]}");
1771}
1772
1773static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
1774{
1775 // Normally, it's not safe to use register enum values directly with
1776 // addition to get the next register, but for VFP registers, the
1777 // sort order is guaranteed because they're all of the form D<n>.
1778 SStream_concat(O, "{");
1779 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1780 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1781 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1782 MI->pub_insn.arm.op_count++;
1783 SStream_concat(O, "[], ");
1784 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
1785 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1786 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
1787 MI->pub_insn.arm.op_count++;
1788 SStream_concat(O, "[], ");
1789 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1790 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1791 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1792 MI->pub_insn.arm.op_count++;
1793 SStream_concat(O, "[]}");
1794}
1795
1796static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
1797{
1798 // Normally, it's not safe to use register enum values directly with
1799 // addition to get the next register, but for VFP registers, the
1800 // sort order is guaranteed because they're all of the form D<n>.
1801 SStream_concat(O, "{");
1802 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1803 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1804 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1805 MI->pub_insn.arm.op_count++;
1806 SStream_concat(O, "[], ");
1807 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
1808 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1809 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
1810 MI->pub_insn.arm.op_count++;
1811 SStream_concat(O, "[], ");
1812 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1813 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1814 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1815 MI->pub_insn.arm.op_count++;
1816 SStream_concat(O, "[], ");
1817 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
1818 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1819 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
1820 MI->pub_insn.arm.op_count++;
1821 SStream_concat(O, "[]}");
1822}
1823
1824static void printVectorListTwoSpacedAllLanes(MCInst *MI,
1825 unsigned OpNum, SStream *O, MCRegisterInfo *MRI)
1826{
1827 unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1828 unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
1829 unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
1830 SStream_concat(O, "{");
1831 printRegName(O, Reg0);
1832 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1833 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg0;
1834 MI->pub_insn.arm.op_count++;
1835 SStream_concat(O, "[], ");
1836 printRegName(O, Reg1);
1837 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1838 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = Reg1;
1839 MI->pub_insn.arm.op_count++;
1840 SStream_concat(O, "[]}");
1841}
1842
1843static void printVectorListThreeSpacedAllLanes(MCInst *MI,
1844 unsigned OpNum, SStream *O)
1845{
1846 // Normally, it's not safe to use register enum values directly with
1847 // addition to get the next register, but for VFP registers, the
1848 // sort order is guaranteed because they're all of the form D<n>.
1849 SStream_concat(O, "{");
1850 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1851 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1852 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1853 MI->pub_insn.arm.op_count++;
1854 SStream_concat(O, "[], ");
1855 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1856 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1857 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1858 MI->pub_insn.arm.op_count++;
1859 SStream_concat(O, "[], ");
1860 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
1861 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1862 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
1863 MI->pub_insn.arm.op_count++;
1864 SStream_concat(O, "[]}");
1865}
1866
1867static void printVectorListFourSpacedAllLanes(MCInst *MI,
1868 unsigned OpNum, SStream *O)
1869{
1870 // Normally, it's not safe to use register enum values directly with
1871 // addition to get the next register, but for VFP registers, the
1872 // sort order is guaranteed because they're all of the form D<n>.
1873 SStream_concat(O, "{");
1874 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1875 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1876 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1877 MI->pub_insn.arm.op_count++;
1878 SStream_concat(O, "[], ");
1879 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1880 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1881 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1882 MI->pub_insn.arm.op_count++;
1883 SStream_concat(O, "[], ");
1884 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
1885 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1886 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
1887 MI->pub_insn.arm.op_count++;
1888 SStream_concat(O, "[], ");
1889 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
1890 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1891 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
1892 MI->pub_insn.arm.op_count++;
1893 SStream_concat(O, "[]}");
1894}
1895
1896static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O)
1897{
1898 // Normally, it's not safe to use register enum values directly with
1899 // addition to get the next register, but for VFP registers, the
1900 // sort order is guaranteed because they're all of the form D<n>.
1901 SStream_concat(O, "{");
1902 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1903 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1904 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1905 MI->pub_insn.arm.op_count++;
1906 SStream_concat(O, ", ");
1907 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1908 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1909 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1910 MI->pub_insn.arm.op_count++;
1911 SStream_concat(O, ", ");
1912 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
1913 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1914 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
1915 MI->pub_insn.arm.op_count++;
1916 SStream_concat(O, "}");
1917}
1918
1919static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O)
1920{
1921 // Normally, it's not safe to use register enum values directly with
1922 // addition to get the next register, but for VFP registers, the
1923 // sort order is guaranteed because they're all of the form D<n>.
1924 SStream_concat(O, "{");
1925 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
1926 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1927 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1928 MI->pub_insn.arm.op_count++;
1929 SStream_concat(O, ", ");
1930 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
1931 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1932 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
1933 MI->pub_insn.arm.op_count++;
1934 SStream_concat(O, ", ");
1935 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
1936 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1937 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
1938 MI->pub_insn.arm.op_count++;
1939 SStream_concat(O, ", ");
1940 printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
1941 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].type = ARM_OP_REG;
1942 MI->pub_insn.arm.operands[MI->pub_insn.arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
1943 MI->pub_insn.arm.op_count++;
1944 SStream_concat(O, "}");
1945}