1 //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an ARM MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMInstPrinter.h"
15 #include "MCTargetDesc/ARMAddressingModes.h"
16 #include "MCTargetDesc/ARMBaseInfo.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/raw_ostream.h"
24 using namespace llvm;
25
26 #define DEBUG_TYPE "asm-printer"
27
28 #define PRINT_ALIAS_INSTR
29 #include "ARMGenAsmWriter.inc"
30
31 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
32 ///
33 /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
translateShiftImm(unsigned imm)34 static unsigned translateShiftImm(unsigned imm) {
35 // lsr #32 and asr #32 exist, but should be encoded as a 0.
36 assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
37
38 if (imm == 0)
39 return 32;
40 return imm;
41 }
42
43 /// Prints the shift value with an immediate value.
printRegImmShift(raw_ostream & O,ARM_AM::ShiftOpc ShOpc,unsigned ShImm,bool UseMarkup)44 static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
45 unsigned ShImm, bool UseMarkup) {
46 if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
47 return;
48 O << ", ";
49
50 assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
51 O << getShiftOpcStr(ShOpc);
52
53 if (ShOpc != ARM_AM::rrx) {
54 O << " ";
55 if (UseMarkup)
56 O << "<imm:";
57 O << "#" << translateShiftImm(ShImm);
58 if (UseMarkup)
59 O << ">";
60 }
61 }
62
ARMInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)63 ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
64 const MCRegisterInfo &MRI)
65 : MCInstPrinter(MAI, MII, MRI) {}
66
printRegName(raw_ostream & OS,unsigned RegNo) const67 void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
68 OS << markup("<reg:") << getRegisterName(RegNo) << markup(">");
69 }
70
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)71 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
72 StringRef Annot, const MCSubtargetInfo &STI) {
73 unsigned Opcode = MI->getOpcode();
74
75 switch (Opcode) {
76
77 // Check for MOVs and print canonical forms, instead.
78 case ARM::MOVsr: {
79 // FIXME: Thumb variants?
80 const MCOperand &Dst = MI->getOperand(0);
81 const MCOperand &MO1 = MI->getOperand(1);
82 const MCOperand &MO2 = MI->getOperand(2);
83 const MCOperand &MO3 = MI->getOperand(3);
84
85 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
86 printSBitModifierOperand(MI, 6, STI, O);
87 printPredicateOperand(MI, 4, STI, O);
88
89 O << '\t';
90 printRegName(O, Dst.getReg());
91 O << ", ";
92 printRegName(O, MO1.getReg());
93
94 O << ", ";
95 printRegName(O, MO2.getReg());
96 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
97 printAnnotation(O, Annot);
98 return;
99 }
100
101 case ARM::MOVsi: {
102 // FIXME: Thumb variants?
103 const MCOperand &Dst = MI->getOperand(0);
104 const MCOperand &MO1 = MI->getOperand(1);
105 const MCOperand &MO2 = MI->getOperand(2);
106
107 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
108 printSBitModifierOperand(MI, 5, STI, O);
109 printPredicateOperand(MI, 3, STI, O);
110
111 O << '\t';
112 printRegName(O, Dst.getReg());
113 O << ", ";
114 printRegName(O, MO1.getReg());
115
116 if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
117 printAnnotation(O, Annot);
118 return;
119 }
120
121 O << ", " << markup("<imm:") << "#"
122 << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())) << markup(">");
123 printAnnotation(O, Annot);
124 return;
125 }
126
127 // A8.6.123 PUSH
128 case ARM::STMDB_UPD:
129 case ARM::t2STMDB_UPD:
130 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
131 // Should only print PUSH if there are at least two registers in the list.
132 O << '\t' << "push";
133 printPredicateOperand(MI, 2, STI, O);
134 if (Opcode == ARM::t2STMDB_UPD)
135 O << ".w";
136 O << '\t';
137 printRegisterList(MI, 4, STI, O);
138 printAnnotation(O, Annot);
139 return;
140 } else
141 break;
142
143 case ARM::STR_PRE_IMM:
144 if (MI->getOperand(2).getReg() == ARM::SP &&
145 MI->getOperand(3).getImm() == -4) {
146 O << '\t' << "push";
147 printPredicateOperand(MI, 4, STI, O);
148 O << "\t{";
149 printRegName(O, MI->getOperand(1).getReg());
150 O << "}";
151 printAnnotation(O, Annot);
152 return;
153 } else
154 break;
155
156 // A8.6.122 POP
157 case ARM::LDMIA_UPD:
158 case ARM::t2LDMIA_UPD:
159 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
160 // Should only print POP if there are at least two registers in the list.
161 O << '\t' << "pop";
162 printPredicateOperand(MI, 2, STI, O);
163 if (Opcode == ARM::t2LDMIA_UPD)
164 O << ".w";
165 O << '\t';
166 printRegisterList(MI, 4, STI, O);
167 printAnnotation(O, Annot);
168 return;
169 } else
170 break;
171
172 case ARM::LDR_POST_IMM:
173 if (MI->getOperand(2).getReg() == ARM::SP &&
174 MI->getOperand(4).getImm() == 4) {
175 O << '\t' << "pop";
176 printPredicateOperand(MI, 5, STI, O);
177 O << "\t{";
178 printRegName(O, MI->getOperand(0).getReg());
179 O << "}";
180 printAnnotation(O, Annot);
181 return;
182 } else
183 break;
184
185 // A8.6.355 VPUSH
186 case ARM::VSTMSDB_UPD:
187 case ARM::VSTMDDB_UPD:
188 if (MI->getOperand(0).getReg() == ARM::SP) {
189 O << '\t' << "vpush";
190 printPredicateOperand(MI, 2, STI, O);
191 O << '\t';
192 printRegisterList(MI, 4, STI, O);
193 printAnnotation(O, Annot);
194 return;
195 } else
196 break;
197
198 // A8.6.354 VPOP
199 case ARM::VLDMSIA_UPD:
200 case ARM::VLDMDIA_UPD:
201 if (MI->getOperand(0).getReg() == ARM::SP) {
202 O << '\t' << "vpop";
203 printPredicateOperand(MI, 2, STI, O);
204 O << '\t';
205 printRegisterList(MI, 4, STI, O);
206 printAnnotation(O, Annot);
207 return;
208 } else
209 break;
210
211 case ARM::tLDMIA: {
212 bool Writeback = true;
213 unsigned BaseReg = MI->getOperand(0).getReg();
214 for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
215 if (MI->getOperand(i).getReg() == BaseReg)
216 Writeback = false;
217 }
218
219 O << "\tldm";
220
221 printPredicateOperand(MI, 1, STI, O);
222 O << '\t';
223 printRegName(O, BaseReg);
224 if (Writeback)
225 O << "!";
226 O << ", ";
227 printRegisterList(MI, 3, STI, O);
228 printAnnotation(O, Annot);
229 return;
230 }
231
232 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
233 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
234 // a single GPRPair reg operand is used in the .td file to replace the two
235 // GPRs. However, when decoding them, the two GRPs cannot be automatically
236 // expressed as a GPRPair, so we have to manually merge them.
237 // FIXME: We would really like to be able to tablegen'erate this.
238 case ARM::LDREXD:
239 case ARM::STREXD:
240 case ARM::LDAEXD:
241 case ARM::STLEXD: {
242 const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
243 bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
244 unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
245 if (MRC.contains(Reg)) {
246 MCInst NewMI;
247 MCOperand NewReg;
248 NewMI.setOpcode(Opcode);
249
250 if (isStore)
251 NewMI.addOperand(MI->getOperand(0));
252 NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
253 Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
254 NewMI.addOperand(NewReg);
255
256 // Copy the rest operands into NewMI.
257 for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
258 NewMI.addOperand(MI->getOperand(i));
259 printInstruction(&NewMI, STI, O);
260 return;
261 }
262 break;
263 }
264 }
265
266 if (!printAliasInstr(MI, STI, O))
267 printInstruction(MI, STI, O);
268
269 printAnnotation(O, Annot);
270 }
271
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)272 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
273 const MCSubtargetInfo &STI, raw_ostream &O) {
274 const MCOperand &Op = MI->getOperand(OpNo);
275 if (Op.isReg()) {
276 unsigned Reg = Op.getReg();
277 printRegName(O, Reg);
278 } else if (Op.isImm()) {
279 O << markup("<imm:") << '#' << formatImm(Op.getImm()) << markup(">");
280 } else {
281 assert(Op.isExpr() && "unknown operand kind in printOperand");
282 const MCExpr *Expr = Op.getExpr();
283 switch (Expr->getKind()) {
284 case MCExpr::Binary:
285 O << '#';
286 Expr->print(O, &MAI);
287 break;
288 case MCExpr::Constant: {
289 // If a symbolic branch target was added as a constant expression then
290 // print that address in hex. And only print 32 unsigned bits for the
291 // address.
292 const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
293 int64_t TargetAddress;
294 if (!Constant->evaluateAsAbsolute(TargetAddress)) {
295 O << '#';
296 Expr->print(O, &MAI);
297 } else {
298 O << "0x";
299 O.write_hex(static_cast<uint32_t>(TargetAddress));
300 }
301 break;
302 }
303 default:
304 // FIXME: Should we always treat this as if it is a constant literal and
305 // prefix it with '#'?
306 Expr->print(O, &MAI);
307 break;
308 }
309 }
310 }
311
printThumbLdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)312 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
313 const MCSubtargetInfo &STI,
314 raw_ostream &O) {
315 const MCOperand &MO1 = MI->getOperand(OpNum);
316 if (MO1.isExpr()) {
317 MO1.getExpr()->print(O, &MAI);
318 return;
319 }
320
321 O << markup("<mem:") << "[pc, ";
322
323 int32_t OffImm = (int32_t)MO1.getImm();
324 bool isSub = OffImm < 0;
325
326 // Special value for #-0. All others are normal.
327 if (OffImm == INT32_MIN)
328 OffImm = 0;
329 if (isSub) {
330 O << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
331 } else {
332 O << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
333 }
334 O << "]" << markup(">");
335 }
336
337 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
338 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
339 // REG 0 0 - e.g. R5
340 // REG REG 0,SH_OPC - e.g. R5, ROR R3
341 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
printSORegRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)342 void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
343 const MCSubtargetInfo &STI,
344 raw_ostream &O) {
345 const MCOperand &MO1 = MI->getOperand(OpNum);
346 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
347 const MCOperand &MO3 = MI->getOperand(OpNum + 2);
348
349 printRegName(O, MO1.getReg());
350
351 // Print the shift opc.
352 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
353 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
354 if (ShOpc == ARM_AM::rrx)
355 return;
356
357 O << ' ';
358 printRegName(O, MO2.getReg());
359 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
360 }
361
printSORegImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)362 void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
363 const MCSubtargetInfo &STI,
364 raw_ostream &O) {
365 const MCOperand &MO1 = MI->getOperand(OpNum);
366 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
367
368 printRegName(O, MO1.getReg());
369
370 // Print the shift opc.
371 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
372 ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
373 }
374
375 //===--------------------------------------------------------------------===//
376 // Addressing Mode #2
377 //===--------------------------------------------------------------------===//
378
printAM2PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)379 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
380 const MCSubtargetInfo &STI,
381 raw_ostream &O) {
382 const MCOperand &MO1 = MI->getOperand(Op);
383 const MCOperand &MO2 = MI->getOperand(Op + 1);
384 const MCOperand &MO3 = MI->getOperand(Op + 2);
385
386 O << markup("<mem:") << "[";
387 printRegName(O, MO1.getReg());
388
389 if (!MO2.getReg()) {
390 if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
391 O << ", " << markup("<imm:") << "#"
392 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
393 << ARM_AM::getAM2Offset(MO3.getImm()) << markup(">");
394 }
395 O << "]" << markup(">");
396 return;
397 }
398
399 O << ", ";
400 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
401 printRegName(O, MO2.getReg());
402
403 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
404 ARM_AM::getAM2Offset(MO3.getImm()), UseMarkup);
405 O << "]" << markup(">");
406 }
407
printAddrModeTBB(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)408 void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
409 const MCSubtargetInfo &STI,
410 raw_ostream &O) {
411 const MCOperand &MO1 = MI->getOperand(Op);
412 const MCOperand &MO2 = MI->getOperand(Op + 1);
413 O << markup("<mem:") << "[";
414 printRegName(O, MO1.getReg());
415 O << ", ";
416 printRegName(O, MO2.getReg());
417 O << "]" << markup(">");
418 }
419
printAddrModeTBH(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)420 void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
421 const MCSubtargetInfo &STI,
422 raw_ostream &O) {
423 const MCOperand &MO1 = MI->getOperand(Op);
424 const MCOperand &MO2 = MI->getOperand(Op + 1);
425 O << markup("<mem:") << "[";
426 printRegName(O, MO1.getReg());
427 O << ", ";
428 printRegName(O, MO2.getReg());
429 O << ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
430 }
431
printAddrMode2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)432 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
433 const MCSubtargetInfo &STI,
434 raw_ostream &O) {
435 const MCOperand &MO1 = MI->getOperand(Op);
436
437 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
438 printOperand(MI, Op, STI, O);
439 return;
440 }
441
442 #ifndef NDEBUG
443 const MCOperand &MO3 = MI->getOperand(Op + 2);
444 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
445 assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
446 #endif
447
448 printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
449 }
450
printAddrMode2OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)451 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
452 unsigned OpNum,
453 const MCSubtargetInfo &STI,
454 raw_ostream &O) {
455 const MCOperand &MO1 = MI->getOperand(OpNum);
456 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
457
458 if (!MO1.getReg()) {
459 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
460 O << markup("<imm:") << '#'
461 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << ImmOffs
462 << markup(">");
463 return;
464 }
465
466 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
467 printRegName(O, MO1.getReg());
468
469 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
470 ARM_AM::getAM2Offset(MO2.getImm()), UseMarkup);
471 }
472
473 //===--------------------------------------------------------------------===//
474 // Addressing Mode #3
475 //===--------------------------------------------------------------------===//
476
printAM3PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,raw_ostream & O,bool AlwaysPrintImm0)477 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
478 raw_ostream &O,
479 bool AlwaysPrintImm0) {
480 const MCOperand &MO1 = MI->getOperand(Op);
481 const MCOperand &MO2 = MI->getOperand(Op + 1);
482 const MCOperand &MO3 = MI->getOperand(Op + 2);
483
484 O << markup("<mem:") << '[';
485 printRegName(O, MO1.getReg());
486
487 if (MO2.getReg()) {
488 O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
489 printRegName(O, MO2.getReg());
490 O << ']' << markup(">");
491 return;
492 }
493
494 // If the op is sub we have to print the immediate even if it is 0
495 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
496 ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
497
498 if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
499 O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs
500 << markup(">");
501 }
502 O << ']' << markup(">");
503 }
504
505 template <bool AlwaysPrintImm0>
printAddrMode3Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)506 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
507 const MCSubtargetInfo &STI,
508 raw_ostream &O) {
509 const MCOperand &MO1 = MI->getOperand(Op);
510 if (!MO1.isReg()) { // For label symbolic references.
511 printOperand(MI, Op, STI, O);
512 return;
513 }
514
515 assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
516 ARMII::IndexModePost &&
517 "unexpected idxmode");
518 printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
519 }
520
printAddrMode3OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)521 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
522 unsigned OpNum,
523 const MCSubtargetInfo &STI,
524 raw_ostream &O) {
525 const MCOperand &MO1 = MI->getOperand(OpNum);
526 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
527
528 if (MO1.getReg()) {
529 O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
530 printRegName(O, MO1.getReg());
531 return;
532 }
533
534 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
535 O << markup("<imm:") << '#'
536 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) << ImmOffs
537 << markup(">");
538 }
539
printPostIdxImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)540 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
541 const MCSubtargetInfo &STI,
542 raw_ostream &O) {
543 const MCOperand &MO = MI->getOperand(OpNum);
544 unsigned Imm = MO.getImm();
545 O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff)
546 << markup(">");
547 }
548
printPostIdxRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)549 void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
550 const MCSubtargetInfo &STI,
551 raw_ostream &O) {
552 const MCOperand &MO1 = MI->getOperand(OpNum);
553 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
554
555 O << (MO2.getImm() ? "" : "-");
556 printRegName(O, MO1.getReg());
557 }
558
printPostIdxImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)559 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
560 const MCSubtargetInfo &STI,
561 raw_ostream &O) {
562 const MCOperand &MO = MI->getOperand(OpNum);
563 unsigned Imm = MO.getImm();
564 O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2)
565 << markup(">");
566 }
567
printLdStmModeOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)568 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
569 const MCSubtargetInfo &STI,
570 raw_ostream &O) {
571 ARM_AM::AMSubMode Mode =
572 ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
573 O << ARM_AM::getAMSubModeStr(Mode);
574 }
575
576 template <bool AlwaysPrintImm0>
printAddrMode5Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)577 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
578 const MCSubtargetInfo &STI,
579 raw_ostream &O) {
580 const MCOperand &MO1 = MI->getOperand(OpNum);
581 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
582
583 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
584 printOperand(MI, OpNum, STI, O);
585 return;
586 }
587
588 O << markup("<mem:") << "[";
589 printRegName(O, MO1.getReg());
590
591 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
592 ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
593 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
594 O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op)
595 << ImmOffs * 4 << markup(">");
596 }
597 O << "]" << markup(">");
598 }
599
600 template <bool AlwaysPrintImm0>
printAddrMode5FP16Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)601 void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,
602 const MCSubtargetInfo &STI,
603 raw_ostream &O) {
604 const MCOperand &MO1 = MI->getOperand(OpNum);
605 const MCOperand &MO2 = MI->getOperand(OpNum+1);
606
607 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
608 printOperand(MI, OpNum, STI, O);
609 return;
610 }
611
612 O << markup("<mem:") << "[";
613 printRegName(O, MO1.getReg());
614
615 unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
616 unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());
617 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
618 O << ", "
619 << markup("<imm:")
620 << "#"
621 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))
622 << ImmOffs * 2
623 << markup(">");
624 }
625 O << "]" << markup(">");
626 }
627
printAddrMode6Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)628 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
629 const MCSubtargetInfo &STI,
630 raw_ostream &O) {
631 const MCOperand &MO1 = MI->getOperand(OpNum);
632 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
633
634 O << markup("<mem:") << "[";
635 printRegName(O, MO1.getReg());
636 if (MO2.getImm()) {
637 O << ":" << (MO2.getImm() << 3);
638 }
639 O << "]" << markup(">");
640 }
641
printAddrMode7Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)642 void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
643 const MCSubtargetInfo &STI,
644 raw_ostream &O) {
645 const MCOperand &MO1 = MI->getOperand(OpNum);
646 O << markup("<mem:") << "[";
647 printRegName(O, MO1.getReg());
648 O << "]" << markup(">");
649 }
650
printAddrMode6OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)651 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
652 unsigned OpNum,
653 const MCSubtargetInfo &STI,
654 raw_ostream &O) {
655 const MCOperand &MO = MI->getOperand(OpNum);
656 if (MO.getReg() == 0)
657 O << "!";
658 else {
659 O << ", ";
660 printRegName(O, MO.getReg());
661 }
662 }
663
printBitfieldInvMaskImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)664 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
665 unsigned OpNum,
666 const MCSubtargetInfo &STI,
667 raw_ostream &O) {
668 const MCOperand &MO = MI->getOperand(OpNum);
669 uint32_t v = ~MO.getImm();
670 int32_t lsb = countTrailingZeros(v);
671 int32_t width = (32 - countLeadingZeros(v)) - lsb;
672 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
673 O << markup("<imm:") << '#' << lsb << markup(">") << ", " << markup("<imm:")
674 << '#' << width << markup(">");
675 }
676
printMemBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)677 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
678 const MCSubtargetInfo &STI,
679 raw_ostream &O) {
680 unsigned val = MI->getOperand(OpNum).getImm();
681 O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
682 }
683
printInstSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)684 void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
685 const MCSubtargetInfo &STI,
686 raw_ostream &O) {
687 unsigned val = MI->getOperand(OpNum).getImm();
688 O << ARM_ISB::InstSyncBOptToString(val);
689 }
690
printShiftImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)691 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
692 const MCSubtargetInfo &STI,
693 raw_ostream &O) {
694 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
695 bool isASR = (ShiftOp & (1 << 5)) != 0;
696 unsigned Amt = ShiftOp & 0x1f;
697 if (isASR) {
698 O << ", asr " << markup("<imm:") << "#" << (Amt == 0 ? 32 : Amt)
699 << markup(">");
700 } else if (Amt) {
701 O << ", lsl " << markup("<imm:") << "#" << Amt << markup(">");
702 }
703 }
704
printPKHLSLShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)705 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
706 const MCSubtargetInfo &STI,
707 raw_ostream &O) {
708 unsigned Imm = MI->getOperand(OpNum).getImm();
709 if (Imm == 0)
710 return;
711 assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
712 O << ", lsl " << markup("<imm:") << "#" << Imm << markup(">");
713 }
714
printPKHASRShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)715 void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
716 const MCSubtargetInfo &STI,
717 raw_ostream &O) {
718 unsigned Imm = MI->getOperand(OpNum).getImm();
719 // A shift amount of 32 is encoded as 0.
720 if (Imm == 0)
721 Imm = 32;
722 assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
723 O << ", asr " << markup("<imm:") << "#" << Imm << markup(">");
724 }
725
printRegisterList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)726 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
727 const MCSubtargetInfo &STI,
728 raw_ostream &O) {
729 O << "{";
730 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
731 if (i != OpNum)
732 O << ", ";
733 printRegName(O, MI->getOperand(i).getReg());
734 }
735 O << "}";
736 }
737
printGPRPairOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)738 void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
739 const MCSubtargetInfo &STI,
740 raw_ostream &O) {
741 unsigned Reg = MI->getOperand(OpNum).getReg();
742 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
743 O << ", ";
744 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
745 }
746
printSetendOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)747 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
748 const MCSubtargetInfo &STI,
749 raw_ostream &O) {
750 const MCOperand &Op = MI->getOperand(OpNum);
751 if (Op.getImm())
752 O << "be";
753 else
754 O << "le";
755 }
756
printCPSIMod(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)757 void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
758 const MCSubtargetInfo &STI, raw_ostream &O) {
759 const MCOperand &Op = MI->getOperand(OpNum);
760 O << ARM_PROC::IModToString(Op.getImm());
761 }
762
printCPSIFlag(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)763 void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
764 const MCSubtargetInfo &STI, raw_ostream &O) {
765 const MCOperand &Op = MI->getOperand(OpNum);
766 unsigned IFlags = Op.getImm();
767 for (int i = 2; i >= 0; --i)
768 if (IFlags & (1 << i))
769 O << ARM_PROC::IFlagsToString(1 << i);
770
771 if (IFlags == 0)
772 O << "none";
773 }
774
printMSRMaskOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)775 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
776 const MCSubtargetInfo &STI,
777 raw_ostream &O) {
778 const MCOperand &Op = MI->getOperand(OpNum);
779 unsigned SpecRegRBit = Op.getImm() >> 4;
780 unsigned Mask = Op.getImm() & 0xf;
781 const FeatureBitset &FeatureBits = STI.getFeatureBits();
782
783 if (FeatureBits[ARM::FeatureMClass]) {
784 unsigned SYSm = Op.getImm();
785 unsigned Opcode = MI->getOpcode();
786
787 // For writes, handle extended mask bits if the DSP extension is present.
788 if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
789 switch (SYSm) {
790 case 0x400:
791 O << "apsr_g";
792 return;
793 case 0xc00:
794 O << "apsr_nzcvqg";
795 return;
796 case 0x401:
797 O << "iapsr_g";
798 return;
799 case 0xc01:
800 O << "iapsr_nzcvqg";
801 return;
802 case 0x402:
803 O << "eapsr_g";
804 return;
805 case 0xc02:
806 O << "eapsr_nzcvqg";
807 return;
808 case 0x403:
809 O << "xpsr_g";
810 return;
811 case 0xc03:
812 O << "xpsr_nzcvqg";
813 return;
814 }
815 }
816
817 // Handle the basic 8-bit mask.
818 SYSm &= 0xff;
819
820 if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
821 // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
822 // alias for MSR APSR_nzcvq.
823 switch (SYSm) {
824 case 0:
825 O << "apsr_nzcvq";
826 return;
827 case 1:
828 O << "iapsr_nzcvq";
829 return;
830 case 2:
831 O << "eapsr_nzcvq";
832 return;
833 case 3:
834 O << "xpsr_nzcvq";
835 return;
836 }
837 }
838
839 switch (SYSm) {
840 default:
841 llvm_unreachable("Unexpected mask value!");
842 case 0:
843 O << "apsr";
844 return;
845 case 1:
846 O << "iapsr";
847 return;
848 case 2:
849 O << "eapsr";
850 return;
851 case 3:
852 O << "xpsr";
853 return;
854 case 5:
855 O << "ipsr";
856 return;
857 case 6:
858 O << "epsr";
859 return;
860 case 7:
861 O << "iepsr";
862 return;
863 case 8:
864 O << "msp";
865 return;
866 case 9:
867 O << "psp";
868 return;
869 case 16:
870 O << "primask";
871 return;
872 case 17:
873 O << "basepri";
874 return;
875 case 18:
876 O << "basepri_max";
877 return;
878 case 19:
879 O << "faultmask";
880 return;
881 case 20:
882 O << "control";
883 return;
884 case 10:
885 O << "msplim";
886 return;
887 case 11:
888 O << "psplim";
889 return;
890 case 0x88:
891 O << "msp_ns";
892 return;
893 case 0x89:
894 O << "psp_ns";
895 return;
896 case 0x8a:
897 O << "msplim_ns";
898 return;
899 case 0x8b:
900 O << "psplim_ns";
901 return;
902 case 0x90:
903 O << "primask_ns";
904 return;
905 case 0x91:
906 O << "basepri_ns";
907 return;
908 case 0x92:
909 O << "basepri_max_ns";
910 return;
911 case 0x93:
912 O << "faultmask_ns";
913 return;
914 case 0x94:
915 O << "control_ns";
916 return;
917 case 0x98:
918 O << "sp_ns";
919 return;
920 }
921 }
922
923 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
924 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
925 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
926 O << "APSR_";
927 switch (Mask) {
928 default:
929 llvm_unreachable("Unexpected mask value!");
930 case 4:
931 O << "g";
932 return;
933 case 8:
934 O << "nzcvq";
935 return;
936 case 12:
937 O << "nzcvqg";
938 return;
939 }
940 }
941
942 if (SpecRegRBit)
943 O << "SPSR";
944 else
945 O << "CPSR";
946
947 if (Mask) {
948 O << '_';
949 if (Mask & 8)
950 O << 'f';
951 if (Mask & 4)
952 O << 's';
953 if (Mask & 2)
954 O << 'x';
955 if (Mask & 1)
956 O << 'c';
957 }
958 }
959
printBankedRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)960 void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
961 const MCSubtargetInfo &STI,
962 raw_ostream &O) {
963 uint32_t Banked = MI->getOperand(OpNum).getImm();
964 uint32_t R = (Banked & 0x20) >> 5;
965 uint32_t SysM = Banked & 0x1f;
966
967 // Nothing much we can do about this, the encodings are specified in B9.2.3 of
968 // the ARM ARM v7C, and are all over the shop.
969 if (R) {
970 O << "SPSR_";
971
972 switch (SysM) {
973 case 0x0e:
974 O << "fiq";
975 return;
976 case 0x10:
977 O << "irq";
978 return;
979 case 0x12:
980 O << "svc";
981 return;
982 case 0x14:
983 O << "abt";
984 return;
985 case 0x16:
986 O << "und";
987 return;
988 case 0x1c:
989 O << "mon";
990 return;
991 case 0x1e:
992 O << "hyp";
993 return;
994 default:
995 llvm_unreachable("Invalid banked SPSR register");
996 }
997 }
998
999 assert(!R && "should have dealt with SPSR regs");
1000 const char *RegNames[] = {
1001 "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "sp_usr", "lr_usr",
1002 "", "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "sp_fiq",
1003 "lr_fiq", "", "lr_irq", "sp_irq", "lr_svc", "sp_svc", "lr_abt",
1004 "sp_abt", "lr_und", "sp_und", "", "", "", "",
1005 "lr_mon", "sp_mon", "elr_hyp", "sp_hyp"};
1006 const char *Name = RegNames[SysM];
1007 assert(Name[0] && "invalid banked register operand");
1008
1009 O << Name;
1010 }
1011
printPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1012 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
1013 const MCSubtargetInfo &STI,
1014 raw_ostream &O) {
1015 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
1016 // Handle the undefined 15 CC value here for printing so we don't abort().
1017 if ((unsigned)CC == 15)
1018 O << "<und>";
1019 else if (CC != ARMCC::AL)
1020 O << ARMCondCodeToString(CC);
1021 }
1022
printMandatoryPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1023 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
1024 unsigned OpNum,
1025 const MCSubtargetInfo &STI,
1026 raw_ostream &O) {
1027 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
1028 O << ARMCondCodeToString(CC);
1029 }
1030
printSBitModifierOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1031 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
1032 const MCSubtargetInfo &STI,
1033 raw_ostream &O) {
1034 if (MI->getOperand(OpNum).getReg()) {
1035 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
1036 "Expect ARM CPSR register!");
1037 O << 's';
1038 }
1039 }
1040
printNoHashImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1041 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
1042 const MCSubtargetInfo &STI,
1043 raw_ostream &O) {
1044 O << MI->getOperand(OpNum).getImm();
1045 }
1046
printPImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1047 void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
1048 const MCSubtargetInfo &STI,
1049 raw_ostream &O) {
1050 O << "p" << MI->getOperand(OpNum).getImm();
1051 }
1052
printCImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1053 void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
1054 const MCSubtargetInfo &STI,
1055 raw_ostream &O) {
1056 O << "c" << MI->getOperand(OpNum).getImm();
1057 }
1058
printCoprocOptionImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1059 void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
1060 const MCSubtargetInfo &STI,
1061 raw_ostream &O) {
1062 O << "{" << MI->getOperand(OpNum).getImm() << "}";
1063 }
1064
printPCLabel(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1065 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
1066 const MCSubtargetInfo &STI, raw_ostream &O) {
1067 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
1068 }
1069
1070 template <unsigned scale>
printAdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1071 void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
1072 const MCSubtargetInfo &STI,
1073 raw_ostream &O) {
1074 const MCOperand &MO = MI->getOperand(OpNum);
1075
1076 if (MO.isExpr()) {
1077 MO.getExpr()->print(O, &MAI);
1078 return;
1079 }
1080
1081 int32_t OffImm = (int32_t)MO.getImm() << scale;
1082
1083 O << markup("<imm:");
1084 if (OffImm == INT32_MIN)
1085 O << "#-0";
1086 else if (OffImm < 0)
1087 O << "#-" << -OffImm;
1088 else
1089 O << "#" << OffImm;
1090 O << markup(">");
1091 }
1092
printThumbS4ImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1093 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
1094 const MCSubtargetInfo &STI,
1095 raw_ostream &O) {
1096 O << markup("<imm:") << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
1097 << markup(">");
1098 }
1099
printThumbSRImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1100 void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
1101 const MCSubtargetInfo &STI,
1102 raw_ostream &O) {
1103 unsigned Imm = MI->getOperand(OpNum).getImm();
1104 O << markup("<imm:") << "#" << formatImm((Imm == 0 ? 32 : Imm))
1105 << markup(">");
1106 }
1107
printThumbITMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1108 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
1109 const MCSubtargetInfo &STI,
1110 raw_ostream &O) {
1111 // (3 - the number of trailing zeros) is the number of then / else.
1112 unsigned Mask = MI->getOperand(OpNum).getImm();
1113 unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
1114 unsigned CondBit0 = Firstcond & 1;
1115 unsigned NumTZ = countTrailingZeros(Mask);
1116 assert(NumTZ <= 3 && "Invalid IT mask!");
1117 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1118 bool T = ((Mask >> Pos) & 1) == CondBit0;
1119 if (T)
1120 O << 't';
1121 else
1122 O << 'e';
1123 }
1124 }
1125
printThumbAddrModeRROperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1126 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
1127 const MCSubtargetInfo &STI,
1128 raw_ostream &O) {
1129 const MCOperand &MO1 = MI->getOperand(Op);
1130 const MCOperand &MO2 = MI->getOperand(Op + 1);
1131
1132 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1133 printOperand(MI, Op, STI, O);
1134 return;
1135 }
1136
1137 O << markup("<mem:") << "[";
1138 printRegName(O, MO1.getReg());
1139 if (unsigned RegNum = MO2.getReg()) {
1140 O << ", ";
1141 printRegName(O, RegNum);
1142 }
1143 O << "]" << markup(">");
1144 }
1145
printThumbAddrModeImm5SOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O,unsigned Scale)1146 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
1147 unsigned Op,
1148 const MCSubtargetInfo &STI,
1149 raw_ostream &O,
1150 unsigned Scale) {
1151 const MCOperand &MO1 = MI->getOperand(Op);
1152 const MCOperand &MO2 = MI->getOperand(Op + 1);
1153
1154 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1155 printOperand(MI, Op, STI, O);
1156 return;
1157 }
1158
1159 O << markup("<mem:") << "[";
1160 printRegName(O, MO1.getReg());
1161 if (unsigned ImmOffs = MO2.getImm()) {
1162 O << ", " << markup("<imm:") << "#" << formatImm(ImmOffs * Scale)
1163 << markup(">");
1164 }
1165 O << "]" << markup(">");
1166 }
1167
printThumbAddrModeImm5S1Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1168 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
1169 unsigned Op,
1170 const MCSubtargetInfo &STI,
1171 raw_ostream &O) {
1172 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
1173 }
1174
printThumbAddrModeImm5S2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1175 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
1176 unsigned Op,
1177 const MCSubtargetInfo &STI,
1178 raw_ostream &O) {
1179 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
1180 }
1181
printThumbAddrModeImm5S4Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1182 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
1183 unsigned Op,
1184 const MCSubtargetInfo &STI,
1185 raw_ostream &O) {
1186 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1187 }
1188
printThumbAddrModeSPOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1189 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
1190 const MCSubtargetInfo &STI,
1191 raw_ostream &O) {
1192 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1193 }
1194
1195 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1196 // register with shift forms.
1197 // REG 0 0 - e.g. R5
1198 // REG IMM, SH_OPC - e.g. R5, LSL #3
printT2SOOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1199 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
1200 const MCSubtargetInfo &STI,
1201 raw_ostream &O) {
1202 const MCOperand &MO1 = MI->getOperand(OpNum);
1203 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1204
1205 unsigned Reg = MO1.getReg();
1206 printRegName(O, Reg);
1207
1208 // Print the shift opc.
1209 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
1210 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
1211 ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
1212 }
1213
1214 template <bool AlwaysPrintImm0>
printAddrModeImm12Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1215 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
1216 const MCSubtargetInfo &STI,
1217 raw_ostream &O) {
1218 const MCOperand &MO1 = MI->getOperand(OpNum);
1219 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1220
1221 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1222 printOperand(MI, OpNum, STI, O);
1223 return;
1224 }
1225
1226 O << markup("<mem:") << "[";
1227 printRegName(O, MO1.getReg());
1228
1229 int32_t OffImm = (int32_t)MO2.getImm();
1230 bool isSub = OffImm < 0;
1231 // Special value for #-0. All others are normal.
1232 if (OffImm == INT32_MIN)
1233 OffImm = 0;
1234 if (isSub) {
1235 O << ", " << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
1236 } else if (AlwaysPrintImm0 || OffImm > 0) {
1237 O << ", " << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
1238 }
1239 O << "]" << markup(">");
1240 }
1241
1242 template <bool AlwaysPrintImm0>
printT2AddrModeImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1243 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
1244 unsigned OpNum,
1245 const MCSubtargetInfo &STI,
1246 raw_ostream &O) {
1247 const MCOperand &MO1 = MI->getOperand(OpNum);
1248 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1249
1250 O << markup("<mem:") << "[";
1251 printRegName(O, MO1.getReg());
1252
1253 int32_t OffImm = (int32_t)MO2.getImm();
1254 bool isSub = OffImm < 0;
1255 // Don't print +0.
1256 if (OffImm == INT32_MIN)
1257 OffImm = 0;
1258 if (isSub) {
1259 O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1260 } else if (AlwaysPrintImm0 || OffImm > 0) {
1261 O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1262 }
1263 O << "]" << markup(">");
1264 }
1265
1266 template <bool AlwaysPrintImm0>
printT2AddrModeImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1267 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
1268 unsigned OpNum,
1269 const MCSubtargetInfo &STI,
1270 raw_ostream &O) {
1271 const MCOperand &MO1 = MI->getOperand(OpNum);
1272 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1273
1274 if (!MO1.isReg()) { // For label symbolic references.
1275 printOperand(MI, OpNum, STI, O);
1276 return;
1277 }
1278
1279 O << markup("<mem:") << "[";
1280 printRegName(O, MO1.getReg());
1281
1282 int32_t OffImm = (int32_t)MO2.getImm();
1283 bool isSub = OffImm < 0;
1284
1285 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1286
1287 // Don't print +0.
1288 if (OffImm == INT32_MIN)
1289 OffImm = 0;
1290 if (isSub) {
1291 O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1292 } else if (AlwaysPrintImm0 || OffImm > 0) {
1293 O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1294 }
1295 O << "]" << markup(">");
1296 }
1297
printT2AddrModeImm0_1020s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1298 void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
1299 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1300 raw_ostream &O) {
1301 const MCOperand &MO1 = MI->getOperand(OpNum);
1302 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1303
1304 O << markup("<mem:") << "[";
1305 printRegName(O, MO1.getReg());
1306 if (MO2.getImm()) {
1307 O << ", " << markup("<imm:") << "#" << formatImm(MO2.getImm() * 4)
1308 << markup(">");
1309 }
1310 O << "]" << markup(">");
1311 }
1312
printT2AddrModeImm8OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1313 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
1314 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1315 raw_ostream &O) {
1316 const MCOperand &MO1 = MI->getOperand(OpNum);
1317 int32_t OffImm = (int32_t)MO1.getImm();
1318 O << ", " << markup("<imm:");
1319 if (OffImm == INT32_MIN)
1320 O << "#-0";
1321 else if (OffImm < 0)
1322 O << "#-" << -OffImm;
1323 else
1324 O << "#" << OffImm;
1325 O << markup(">");
1326 }
1327
printT2AddrModeImm8s4OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1328 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
1329 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1330 raw_ostream &O) {
1331 const MCOperand &MO1 = MI->getOperand(OpNum);
1332 int32_t OffImm = (int32_t)MO1.getImm();
1333
1334 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1335
1336 O << ", " << markup("<imm:");
1337 if (OffImm == INT32_MIN)
1338 O << "#-0";
1339 else if (OffImm < 0)
1340 O << "#-" << -OffImm;
1341 else
1342 O << "#" << OffImm;
1343 O << markup(">");
1344 }
1345
printT2AddrModeSoRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1346 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
1347 unsigned OpNum,
1348 const MCSubtargetInfo &STI,
1349 raw_ostream &O) {
1350 const MCOperand &MO1 = MI->getOperand(OpNum);
1351 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1352 const MCOperand &MO3 = MI->getOperand(OpNum + 2);
1353
1354 O << markup("<mem:") << "[";
1355 printRegName(O, MO1.getReg());
1356
1357 assert(MO2.getReg() && "Invalid so_reg load / store address!");
1358 O << ", ";
1359 printRegName(O, MO2.getReg());
1360
1361 unsigned ShAmt = MO3.getImm();
1362 if (ShAmt) {
1363 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
1364 O << ", lsl " << markup("<imm:") << "#" << ShAmt << markup(">");
1365 }
1366 O << "]" << markup(">");
1367 }
1368
printFPImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1369 void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
1370 const MCSubtargetInfo &STI,
1371 raw_ostream &O) {
1372 const MCOperand &MO = MI->getOperand(OpNum);
1373 O << markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO.getImm())
1374 << markup(">");
1375 }
1376
printNEONModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1377 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
1378 const MCSubtargetInfo &STI,
1379 raw_ostream &O) {
1380 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
1381 unsigned EltBits;
1382 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
1383 O << markup("<imm:") << "#0x";
1384 O.write_hex(Val);
1385 O << markup(">");
1386 }
1387
printImmPlusOneOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1388 void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
1389 const MCSubtargetInfo &STI,
1390 raw_ostream &O) {
1391 unsigned Imm = MI->getOperand(OpNum).getImm();
1392 O << markup("<imm:") << "#" << formatImm(Imm + 1) << markup(">");
1393 }
1394
printRotImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1395 void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
1396 const MCSubtargetInfo &STI,
1397 raw_ostream &O) {
1398 unsigned Imm = MI->getOperand(OpNum).getImm();
1399 if (Imm == 0)
1400 return;
1401 assert(Imm <= 3 && "illegal ror immediate!");
1402 O << ", ror " << markup("<imm:") << "#" << 8 * Imm << markup(">");
1403 }
1404
printModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1405 void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
1406 const MCSubtargetInfo &STI,
1407 raw_ostream &O) {
1408 MCOperand Op = MI->getOperand(OpNum);
1409
1410 // Support for fixups (MCFixup)
1411 if (Op.isExpr())
1412 return printOperand(MI, OpNum, STI, O);
1413
1414 unsigned Bits = Op.getImm() & 0xFF;
1415 unsigned Rot = (Op.getImm() & 0xF00) >> 7;
1416
1417 bool PrintUnsigned = false;
1418 switch (MI->getOpcode()) {
1419 case ARM::MOVi:
1420 // Movs to PC should be treated unsigned
1421 PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
1422 break;
1423 case ARM::MSRi:
1424 // Movs to special registers should be treated unsigned
1425 PrintUnsigned = true;
1426 break;
1427 }
1428
1429 int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
1430 if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
1431 // #rot has the least possible value
1432 O << "#" << markup("<imm:");
1433 if (PrintUnsigned)
1434 O << static_cast<uint32_t>(Rotated);
1435 else
1436 O << Rotated;
1437 O << markup(">");
1438 return;
1439 }
1440
1441 // Explicit #bits, #rot implied
1442 O << "#" << markup("<imm:") << Bits << markup(">") << ", #" << markup("<imm:")
1443 << Rot << markup(">");
1444 }
1445
printFBits16(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1446 void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
1447 const MCSubtargetInfo &STI, raw_ostream &O) {
1448 O << markup("<imm:") << "#" << 16 - MI->getOperand(OpNum).getImm()
1449 << markup(">");
1450 }
1451
printFBits32(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1452 void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
1453 const MCSubtargetInfo &STI, raw_ostream &O) {
1454 O << markup("<imm:") << "#" << 32 - MI->getOperand(OpNum).getImm()
1455 << markup(">");
1456 }
1457
printVectorIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1458 void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
1459 const MCSubtargetInfo &STI,
1460 raw_ostream &O) {
1461 O << "[" << MI->getOperand(OpNum).getImm() << "]";
1462 }
1463
printVectorListOne(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1464 void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
1465 const MCSubtargetInfo &STI,
1466 raw_ostream &O) {
1467 O << "{";
1468 printRegName(O, MI->getOperand(OpNum).getReg());
1469 O << "}";
1470 }
1471
printVectorListTwo(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1472 void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
1473 const MCSubtargetInfo &STI,
1474 raw_ostream &O) {
1475 unsigned Reg = MI->getOperand(OpNum).getReg();
1476 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1477 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1478 O << "{";
1479 printRegName(O, Reg0);
1480 O << ", ";
1481 printRegName(O, Reg1);
1482 O << "}";
1483 }
1484
printVectorListTwoSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1485 void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
1486 const MCSubtargetInfo &STI,
1487 raw_ostream &O) {
1488 unsigned Reg = MI->getOperand(OpNum).getReg();
1489 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1490 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1491 O << "{";
1492 printRegName(O, Reg0);
1493 O << ", ";
1494 printRegName(O, Reg1);
1495 O << "}";
1496 }
1497
printVectorListThree(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1498 void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
1499 const MCSubtargetInfo &STI,
1500 raw_ostream &O) {
1501 // Normally, it's not safe to use register enum values directly with
1502 // addition to get the next register, but for VFP registers, the
1503 // sort order is guaranteed because they're all of the form D<n>.
1504 O << "{";
1505 printRegName(O, MI->getOperand(OpNum).getReg());
1506 O << ", ";
1507 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1508 O << ", ";
1509 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1510 O << "}";
1511 }
1512
printVectorListFour(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1513 void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
1514 const MCSubtargetInfo &STI,
1515 raw_ostream &O) {
1516 // Normally, it's not safe to use register enum values directly with
1517 // addition to get the next register, but for VFP registers, the
1518 // sort order is guaranteed because they're all of the form D<n>.
1519 O << "{";
1520 printRegName(O, MI->getOperand(OpNum).getReg());
1521 O << ", ";
1522 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1523 O << ", ";
1524 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1525 O << ", ";
1526 printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1527 O << "}";
1528 }
1529
printVectorListOneAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1530 void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
1531 unsigned OpNum,
1532 const MCSubtargetInfo &STI,
1533 raw_ostream &O) {
1534 O << "{";
1535 printRegName(O, MI->getOperand(OpNum).getReg());
1536 O << "[]}";
1537 }
1538
printVectorListTwoAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1539 void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
1540 unsigned OpNum,
1541 const MCSubtargetInfo &STI,
1542 raw_ostream &O) {
1543 unsigned Reg = MI->getOperand(OpNum).getReg();
1544 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1545 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1546 O << "{";
1547 printRegName(O, Reg0);
1548 O << "[], ";
1549 printRegName(O, Reg1);
1550 O << "[]}";
1551 }
1552
printVectorListThreeAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1553 void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
1554 unsigned OpNum,
1555 const MCSubtargetInfo &STI,
1556 raw_ostream &O) {
1557 // Normally, it's not safe to use register enum values directly with
1558 // addition to get the next register, but for VFP registers, the
1559 // sort order is guaranteed because they're all of the form D<n>.
1560 O << "{";
1561 printRegName(O, MI->getOperand(OpNum).getReg());
1562 O << "[], ";
1563 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1564 O << "[], ";
1565 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1566 O << "[]}";
1567 }
1568
printVectorListFourAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1569 void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
1570 unsigned OpNum,
1571 const MCSubtargetInfo &STI,
1572 raw_ostream &O) {
1573 // Normally, it's not safe to use register enum values directly with
1574 // addition to get the next register, but for VFP registers, the
1575 // sort order is guaranteed because they're all of the form D<n>.
1576 O << "{";
1577 printRegName(O, MI->getOperand(OpNum).getReg());
1578 O << "[], ";
1579 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1580 O << "[], ";
1581 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1582 O << "[], ";
1583 printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1584 O << "[]}";
1585 }
1586
printVectorListTwoSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1587 void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
1588 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1589 raw_ostream &O) {
1590 unsigned Reg = MI->getOperand(OpNum).getReg();
1591 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1592 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1593 O << "{";
1594 printRegName(O, Reg0);
1595 O << "[], ";
1596 printRegName(O, Reg1);
1597 O << "[]}";
1598 }
1599
printVectorListThreeSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1600 void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
1601 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1602 raw_ostream &O) {
1603 // Normally, it's not safe to use register enum values directly with
1604 // addition to get the next register, but for VFP registers, the
1605 // sort order is guaranteed because they're all of the form D<n>.
1606 O << "{";
1607 printRegName(O, MI->getOperand(OpNum).getReg());
1608 O << "[], ";
1609 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1610 O << "[], ";
1611 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1612 O << "[]}";
1613 }
1614
printVectorListFourSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1615 void ARMInstPrinter::printVectorListFourSpacedAllLanes(
1616 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1617 raw_ostream &O) {
1618 // Normally, it's not safe to use register enum values directly with
1619 // addition to get the next register, but for VFP registers, the
1620 // sort order is guaranteed because they're all of the form D<n>.
1621 O << "{";
1622 printRegName(O, MI->getOperand(OpNum).getReg());
1623 O << "[], ";
1624 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1625 O << "[], ";
1626 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1627 O << "[], ";
1628 printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1629 O << "[]}";
1630 }
1631
printVectorListThreeSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1632 void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
1633 unsigned OpNum,
1634 const MCSubtargetInfo &STI,
1635 raw_ostream &O) {
1636 // Normally, it's not safe to use register enum values directly with
1637 // addition to get the next register, but for VFP registers, the
1638 // sort order is guaranteed because they're all of the form D<n>.
1639 O << "{";
1640 printRegName(O, MI->getOperand(OpNum).getReg());
1641 O << ", ";
1642 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1643 O << ", ";
1644 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1645 O << "}";
1646 }
1647
printVectorListFourSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1648 void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
1649 const MCSubtargetInfo &STI,
1650 raw_ostream &O) {
1651 // Normally, it's not safe to use register enum values directly with
1652 // addition to get the next register, but for VFP registers, the
1653 // sort order is guaranteed because they're all of the form D<n>.
1654 O << "{";
1655 printRegName(O, MI->getOperand(OpNum).getReg());
1656 O << ", ";
1657 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1658 O << ", ";
1659 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1660 O << ", ";
1661 printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1662 O << "}";
1663 }
1664