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