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