Silence compiler warnings.
[oota-llvm.git] / lib / Target / ARM / AsmPrinter / ARMInstPrinter.cpp
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 #define DEBUG_TYPE "asm-printer"
15 #include "ARM.h" // FIXME: FACTOR ENUMS BETTER.
16 #include "ARMInstPrinter.h"
17 #include "ARMAddressingModes.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/raw_ostream.h"
23 using namespace llvm;
24
25 // Include the auto-generated portion of the assembly writer.
26 #define MachineInstr MCInst
27 #define ARMAsmPrinter ARMInstPrinter  // FIXME: REMOVE.
28 #include "ARMGenAsmWriter.inc"
29 #undef MachineInstr
30 #undef ARMAsmPrinter
31
32 static unsigned NextReg(unsigned Reg) {
33   switch (Reg) {
34   default:
35     assert(0 && "Unexpected register enum");
36
37   case ARM::D0:
38     return ARM::D1;
39   case ARM::D1:
40     return ARM::D2;
41   case ARM::D2:
42     return ARM::D3;
43   case ARM::D3:
44     return ARM::D4;
45   case ARM::D4:
46     return ARM::D5;
47   case ARM::D5:
48     return ARM::D6;
49   case ARM::D6:
50     return ARM::D7;
51   case ARM::D7:
52     return ARM::D8;
53   case ARM::D8:
54     return ARM::D9;
55   case ARM::D9:
56     return ARM::D10;
57   case ARM::D10:
58     return ARM::D11;
59   case ARM::D11:
60     return ARM::D12;
61   case ARM::D12:
62     return ARM::D13;
63   case ARM::D13:
64     return ARM::D14;
65   case ARM::D14:
66     return ARM::D15;
67   case ARM::D15:
68     return ARM::D16;
69   case ARM::D16:
70     return ARM::D17;
71   case ARM::D17:
72     return ARM::D18;
73   case ARM::D18:
74     return ARM::D19;
75   case ARM::D19:
76     return ARM::D20;
77   case ARM::D20:
78     return ARM::D21;
79   case ARM::D21:
80     return ARM::D22;
81   case ARM::D22:
82     return ARM::D23;
83   case ARM::D23:
84     return ARM::D24;
85   case ARM::D24:
86     return ARM::D25;
87   case ARM::D25:
88     return ARM::D26;
89   case ARM::D26:
90     return ARM::D27;
91   case ARM::D27:
92     return ARM::D28;
93   case ARM::D28:
94     return ARM::D29;
95   case ARM::D29:
96     return ARM::D30;
97   case ARM::D30:
98     return ARM::D31;
99   }
100 }
101
102 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
103   // Check for MOVs and print canonical forms, instead.
104   if (MI->getOpcode() == ARM::MOVs) {
105     const MCOperand &Dst = MI->getOperand(0);
106     const MCOperand &MO1 = MI->getOperand(1);
107     const MCOperand &MO2 = MI->getOperand(2);
108     const MCOperand &MO3 = MI->getOperand(3);
109
110     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
111     printSBitModifierOperand(MI, 6, O);
112     printPredicateOperand(MI, 4, O);
113
114     O << '\t' << getRegisterName(Dst.getReg())
115       << ", " << getRegisterName(MO1.getReg());
116
117     if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
118       return;
119
120     O << ", ";
121
122     if (MO2.getReg()) {
123       O << getRegisterName(MO2.getReg());
124       assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
125     } else {
126       O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
127     }
128     return;
129   }
130
131   // A8.6.123 PUSH
132   if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
133       MI->getOperand(0).getReg() == ARM::SP) {
134     const MCOperand &MO1 = MI->getOperand(2);
135     if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
136       O << '\t' << "push";
137       printPredicateOperand(MI, 3, O);
138       O << '\t';
139       printRegisterList(MI, 5, O);
140       return;
141     }
142   }
143
144   // A8.6.122 POP
145   if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
146       MI->getOperand(0).getReg() == ARM::SP) {
147     const MCOperand &MO1 = MI->getOperand(2);
148     if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
149       O << '\t' << "pop";
150       printPredicateOperand(MI, 3, O);
151       O << '\t';
152       printRegisterList(MI, 5, O);
153       return;
154     }
155   }
156
157   // A8.6.355 VPUSH
158   if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
159       MI->getOperand(0).getReg() == ARM::SP) {
160     const MCOperand &MO1 = MI->getOperand(2);
161     if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
162       O << '\t' << "vpush";
163       printPredicateOperand(MI, 3, O);
164       O << '\t';
165       printRegisterList(MI, 5, O);
166       return;
167     }
168   }
169
170   // A8.6.354 VPOP
171   if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
172       MI->getOperand(0).getReg() == ARM::SP) {
173     const MCOperand &MO1 = MI->getOperand(2);
174     if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
175       O << '\t' << "vpop";
176       printPredicateOperand(MI, 3, O);
177       O << '\t';
178       printRegisterList(MI, 5, O);
179       return;
180     }
181   }
182
183   printInstruction(MI, O);
184  }
185
186 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
187                                   raw_ostream &O, const char *Modifier) {
188   const MCOperand &Op = MI->getOperand(OpNo);
189   if (Op.isReg()) {
190     unsigned Reg = Op.getReg();
191     if (Modifier && strcmp(Modifier, "dregpair") == 0) {
192       O << '{' << getRegisterName(Reg) << ", "
193                << getRegisterName(NextReg(Reg)) << '}';
194 #if 0
195       // FIXME: Breaks e.g. ARM/vmul.ll.
196       assert(0);
197       /*
198       unsigned DRegLo = TRI->getSubReg(Reg, ARM::dsub_0);
199       unsigned DRegHi = TRI->getSubReg(Reg, ARM::dsub_1);
200       O << '{'
201       << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
202       << '}';*/
203 #endif
204     } else if (Modifier && strcmp(Modifier, "lane") == 0) {
205       assert(0);
206       /*
207       unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
208       unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
209                                                &ARM::DPR_VFP2RegClass);
210       O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
211        */
212     } else {
213       O << getRegisterName(Reg);
214     }
215   } else if (Op.isImm()) {
216     assert((Modifier && !strcmp(Modifier, "call")) ||
217            ((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
218     O << '#' << Op.getImm();
219   } else {
220     if (Modifier && Modifier[0] != 0 && strcmp(Modifier, "call") != 0)
221       llvm_unreachable("Unsupported modifier");
222     assert(Op.isExpr() && "unknown operand kind in printOperand");
223     O << *Op.getExpr();
224   }
225 }
226
227 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
228                        const MCAsmInfo *MAI) {
229   // Break it up into two parts that make up a shifter immediate.
230   V = ARM_AM::getSOImmVal(V);
231   assert(V != -1 && "Not a valid so_imm value!");
232   
233   unsigned Imm = ARM_AM::getSOImmValImm(V);
234   unsigned Rot = ARM_AM::getSOImmValRot(V);
235   
236   // Print low-level immediate formation info, per
237   // A5.1.3: "Data-processing operands - Immediate".
238   if (Rot) {
239     O << "#" << Imm << ", " << Rot;
240     // Pretty printed version.
241     if (VerboseAsm)
242       O << ' ' << MAI->getCommentString()
243       << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
244   } else {
245     O << "#" << Imm;
246   }
247 }
248
249
250 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
251 /// immediate in bits 0-7.
252 void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
253                                        raw_ostream &O) {
254   const MCOperand &MO = MI->getOperand(OpNum);
255   assert(MO.isImm() && "Not a valid so_imm value!");
256   printSOImm(O, MO.getImm(), VerboseAsm, &MAI);
257 }
258
259 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
260 /// followed by an 'orr' to materialize.
261 void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum,
262                                             raw_ostream &O) {
263   // FIXME: REMOVE this method.
264   abort();
265 }
266
267 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
268 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
269 //    REG 0   0           - e.g. R5
270 //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
271 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
272 void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
273                                        raw_ostream &O) {
274   const MCOperand &MO1 = MI->getOperand(OpNum);
275   const MCOperand &MO2 = MI->getOperand(OpNum+1);
276   const MCOperand &MO3 = MI->getOperand(OpNum+2);
277   
278   O << getRegisterName(MO1.getReg());
279   
280   // Print the shift opc.
281   O << ", "
282     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
283     << ' ';
284   
285   if (MO2.getReg()) {
286     O << getRegisterName(MO2.getReg());
287     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
288   } else {
289     O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
290   }
291 }
292
293
294 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
295                                            raw_ostream &O) {
296   const MCOperand &MO1 = MI->getOperand(Op);
297   const MCOperand &MO2 = MI->getOperand(Op+1);
298   const MCOperand &MO3 = MI->getOperand(Op+2);
299   
300   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
301     printOperand(MI, Op, O);
302     return;
303   }
304   
305   O << "[" << getRegisterName(MO1.getReg());
306   
307   if (!MO2.getReg()) {
308     if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
309       O << ", #"
310         << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
311         << ARM_AM::getAM2Offset(MO3.getImm());
312     O << "]";
313     return;
314   }
315   
316   O << ", "
317     << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
318     << getRegisterName(MO2.getReg());
319   
320   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
321     O << ", "
322     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
323     << " #" << ShImm;
324   O << "]";
325 }  
326
327 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
328                                                  unsigned OpNum,
329                                                  raw_ostream &O) {
330   const MCOperand &MO1 = MI->getOperand(OpNum);
331   const MCOperand &MO2 = MI->getOperand(OpNum+1);
332   
333   if (!MO1.getReg()) {
334     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
335     O << '#'
336       << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
337       << ImmOffs;
338     return;
339   }
340   
341   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
342     << getRegisterName(MO1.getReg());
343   
344   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
345     O << ", "
346     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
347     << " #" << ShImm;
348 }
349
350 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
351                                            raw_ostream &O) {
352   const MCOperand &MO1 = MI->getOperand(OpNum);
353   const MCOperand &MO2 = MI->getOperand(OpNum+1);
354   const MCOperand &MO3 = MI->getOperand(OpNum+2);
355   
356   O << '[' << getRegisterName(MO1.getReg());
357   
358   if (MO2.getReg()) {
359     O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
360       << getRegisterName(MO2.getReg()) << ']';
361     return;
362   }
363   
364   if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
365     O << ", #"
366       << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
367       << ImmOffs;
368   O << ']';
369 }
370
371 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
372                                                  unsigned OpNum,
373                                                  raw_ostream &O) {
374   const MCOperand &MO1 = MI->getOperand(OpNum);
375   const MCOperand &MO2 = MI->getOperand(OpNum+1);
376   
377   if (MO1.getReg()) {
378     O << (char)ARM_AM::getAM3Op(MO2.getImm())
379     << getRegisterName(MO1.getReg());
380     return;
381   }
382   
383   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
384   O << '#'
385     << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
386     << ImmOffs;
387 }
388
389
390 void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
391                                            raw_ostream &O,
392                                            const char *Modifier) {
393   const MCOperand &MO2 = MI->getOperand(OpNum+1);
394   ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
395   if (Modifier && strcmp(Modifier, "submode") == 0) {
396     O << ARM_AM::getAMSubModeStr(Mode);
397   } else if (Modifier && strcmp(Modifier, "wide") == 0) {
398     ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
399     if (Mode == ARM_AM::ia)
400       O << ".w";
401   } else {
402     printOperand(MI, OpNum, O);
403   }
404 }
405
406 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
407                                            raw_ostream &O,
408                                            const char *Modifier) {
409   const MCOperand &MO1 = MI->getOperand(OpNum);
410   const MCOperand &MO2 = MI->getOperand(OpNum+1);
411   
412   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
413     printOperand(MI, OpNum, O);
414     return;
415   }
416   
417   if (Modifier && strcmp(Modifier, "submode") == 0) {
418     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
419     O << ARM_AM::getAMSubModeStr(Mode);
420     return;
421   } else if (Modifier && strcmp(Modifier, "base") == 0) {
422     // Used for FSTM{D|S} and LSTM{D|S} operations.
423     O << getRegisterName(MO1.getReg());
424     return;
425   }
426   
427   O << "[" << getRegisterName(MO1.getReg());
428   
429   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
430     O << ", #"
431       << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
432       << ImmOffs*4;
433   }
434   O << "]";
435 }
436
437 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
438                                            raw_ostream &O) {
439   const MCOperand &MO1 = MI->getOperand(OpNum);
440   const MCOperand &MO2 = MI->getOperand(OpNum+1);
441   
442   O << "[" << getRegisterName(MO1.getReg());
443   if (MO2.getImm()) {
444     // FIXME: Both darwin as and GNU as violate ARM docs here.
445     O << ", :" << MO2.getImm();
446   }
447   O << "]";
448 }
449
450 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
451                                                  unsigned OpNum,
452                                                  raw_ostream &O) {
453   const MCOperand &MO = MI->getOperand(OpNum);
454   if (MO.getReg() == 0)
455     O << "!";
456   else
457     O << ", " << getRegisterName(MO.getReg());
458 }
459
460 void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
461                                             raw_ostream &O,
462                                             const char *Modifier) {
463   assert(0 && "FIXME: Implement printAddrModePCOperand");
464 }
465
466 void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
467                                                      unsigned OpNum,
468                                                      raw_ostream &O) {
469   const MCOperand &MO = MI->getOperand(OpNum);
470   uint32_t v = ~MO.getImm();
471   int32_t lsb = CountTrailingZeros_32(v);
472   int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
473   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
474   O << '#' << lsb << ", #" << width;
475 }
476
477 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
478                                        raw_ostream &O) {
479   O << "{";
480   for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
481     if (i != OpNum) O << ", ";
482     O << getRegisterName(MI->getOperand(i).getReg());
483   }
484   O << "}";
485 }
486
487 void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
488                                            raw_ostream &O) {
489   const MCOperand &Op = MI->getOperand(OpNum);
490   unsigned option = Op.getImm();
491   unsigned mode = option & 31;
492   bool changemode = option >> 5 & 1;
493   unsigned AIF = option >> 6 & 7;
494   unsigned imod = option >> 9 & 3;
495   if (imod == 2)
496     O << "ie";
497   else if (imod == 3)
498     O << "id";
499   O << '\t';
500   if (imod > 1) {
501     if (AIF & 4) O << 'a';
502     if (AIF & 2) O << 'i';
503     if (AIF & 1) O << 'f';
504     if (AIF > 0 && changemode) O << ", ";
505   }
506   if (changemode)
507     O << '#' << mode;
508 }
509
510 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
511                                          raw_ostream &O) {
512   const MCOperand &Op = MI->getOperand(OpNum);
513   unsigned Mask = Op.getImm();
514   if (Mask) {
515     O << '_';
516     if (Mask & 8) O << 'f';
517     if (Mask & 4) O << 's';
518     if (Mask & 2) O << 'x';
519     if (Mask & 1) O << 'c';
520   }
521 }
522
523 void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
524                                          raw_ostream &O) {
525   const MCOperand &Op = MI->getOperand(OpNum);
526   O << '#';
527   if (Op.getImm() < 0)
528     O << '-' << (-Op.getImm() - 1);
529   else
530     O << Op.getImm();
531 }
532
533 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
534                                            raw_ostream &O) {
535   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
536   if (CC != ARMCC::AL)
537     O << ARMCondCodeToString(CC);
538 }
539
540 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, 
541                                                     unsigned OpNum,
542                                                     raw_ostream &O) {
543   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
544   O << ARMCondCodeToString(CC);
545 }
546
547 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
548                                               raw_ostream &O) {
549   if (MI->getOperand(OpNum).getReg()) {
550     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
551            "Expect ARM CPSR register!");
552     O << 's';
553   }
554 }
555
556
557
558 void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
559                                         raw_ostream &O,
560                                         const char *Modifier) {
561   // FIXME: remove this.
562   abort();
563 }
564
565 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
566                                           raw_ostream &O) {
567   O << MI->getOperand(OpNum).getImm();
568 }
569
570
571 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
572                                   raw_ostream &O) {
573   // FIXME: remove this.
574   abort();
575 }
576
577 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
578                                             raw_ostream &O) {
579   O << "#" <<  MI->getOperand(OpNum).getImm() * 4;
580 }
581
582 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
583                                       raw_ostream &O) {
584   // (3 - the number of trailing zeros) is the number of then / else.
585   unsigned Mask = MI->getOperand(OpNum).getImm();
586   unsigned CondBit0 = Mask >> 4 & 1;
587   unsigned NumTZ = CountTrailingZeros_32(Mask);
588   assert(NumTZ <= 3 && "Invalid IT mask!");
589   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
590     bool T = ((Mask >> Pos) & 1) == CondBit0;
591     if (T)
592       O << 't';
593     else
594       O << 'e';
595   }
596 }
597
598 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
599                                                  raw_ostream &O) {
600   const MCOperand &MO1 = MI->getOperand(Op);
601   const MCOperand &MO2 = MI->getOperand(Op+1);
602   O << "[" << getRegisterName(MO1.getReg());
603   O << ", " << getRegisterName(MO2.getReg()) << "]";
604 }
605
606 void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
607                                                   raw_ostream &O,
608                                                   unsigned Scale) {
609   const MCOperand &MO1 = MI->getOperand(Op);
610   const MCOperand &MO2 = MI->getOperand(Op+1);
611   const MCOperand &MO3 = MI->getOperand(Op+2);
612
613   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
614     printOperand(MI, Op, O);
615     return;
616   }
617
618   O << "[" << getRegisterName(MO1.getReg());
619   if (MO3.getReg())
620     O << ", " << getRegisterName(MO3.getReg());
621   else if (unsigned ImmOffs = MO2.getImm())
622     O << ", #" << ImmOffs * Scale;
623   O << "]";
624 }
625
626 void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
627                                                  raw_ostream &O) {
628   printThumbAddrModeRI5Operand(MI, Op, O, 1);
629 }
630
631 void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
632                                                  raw_ostream &O) {
633   printThumbAddrModeRI5Operand(MI, Op, O, 2);
634 }
635
636 void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
637                                                  raw_ostream &O) {
638   printThumbAddrModeRI5Operand(MI, Op, O, 4);
639 }
640
641 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
642                                                  raw_ostream &O) {
643   const MCOperand &MO1 = MI->getOperand(Op);
644   const MCOperand &MO2 = MI->getOperand(Op+1);
645   O << "[" << getRegisterName(MO1.getReg());
646   if (unsigned ImmOffs = MO2.getImm())
647     O << ", #" << ImmOffs*4;
648   O << "]";
649 }
650
651 void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
652                                      raw_ostream &O) {
653   O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
654   if (MI->getOpcode() == ARM::t2TBH)
655     O << ", lsl #1";
656   O << ']';
657 }
658
659 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
660 // register with shift forms.
661 // REG 0   0           - e.g. R5
662 // REG IMM, SH_OPC     - e.g. R5, LSL #3
663 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
664                                       raw_ostream &O) {
665   const MCOperand &MO1 = MI->getOperand(OpNum);
666   const MCOperand &MO2 = MI->getOperand(OpNum+1);
667
668   unsigned Reg = MO1.getReg();
669   O << getRegisterName(Reg);
670
671   // Print the shift opc.
672   O << ", "
673     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
674     << " ";
675
676   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
677   O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
678 }
679
680 void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
681                                                  unsigned OpNum,
682                                                  raw_ostream &O) {
683   const MCOperand &MO1 = MI->getOperand(OpNum);
684   const MCOperand &MO2 = MI->getOperand(OpNum+1);
685
686   O << "[" << getRegisterName(MO1.getReg());
687
688   unsigned OffImm = MO2.getImm();
689   if (OffImm)  // Don't print +0.
690     O << ", #" << OffImm;
691   O << "]";
692 }
693
694 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
695                                                 unsigned OpNum,
696                                                 raw_ostream &O) {
697   const MCOperand &MO1 = MI->getOperand(OpNum);
698   const MCOperand &MO2 = MI->getOperand(OpNum+1);
699
700   O << "[" << getRegisterName(MO1.getReg());
701
702   int32_t OffImm = (int32_t)MO2.getImm();
703   // Don't print +0.
704   if (OffImm < 0)
705     O << ", #-" << -OffImm;
706   else if (OffImm > 0)
707     O << ", #" << OffImm;
708   O << "]";
709 }
710
711 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
712                                                   unsigned OpNum,
713                                                   raw_ostream &O) {
714   const MCOperand &MO1 = MI->getOperand(OpNum);
715   const MCOperand &MO2 = MI->getOperand(OpNum+1);
716
717   O << "[" << getRegisterName(MO1.getReg());
718
719   int32_t OffImm = (int32_t)MO2.getImm() / 4;
720   // Don't print +0.
721   if (OffImm < 0)
722     O << ", #-" << -OffImm * 4;
723   else if (OffImm > 0)
724     O << ", #" << OffImm * 4;
725   O << "]";
726 }
727
728 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
729                                                       unsigned OpNum,
730                                                       raw_ostream &O) {
731   const MCOperand &MO1 = MI->getOperand(OpNum);
732   int32_t OffImm = (int32_t)MO1.getImm();
733   // Don't print +0.
734   if (OffImm < 0)
735     O << "#-" << -OffImm;
736   else if (OffImm > 0)
737     O << "#" << OffImm;
738 }
739
740 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
741                                                         unsigned OpNum,
742                                                         raw_ostream &O) {
743   const MCOperand &MO1 = MI->getOperand(OpNum);
744   int32_t OffImm = (int32_t)MO1.getImm() / 4;
745   // Don't print +0.
746   if (OffImm < 0)
747     O << "#-" << -OffImm * 4;
748   else if (OffImm > 0)
749     O << "#" << OffImm * 4;
750 }
751
752 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
753                                                  unsigned OpNum,
754                                                  raw_ostream &O) {
755   const MCOperand &MO1 = MI->getOperand(OpNum);
756   const MCOperand &MO2 = MI->getOperand(OpNum+1);
757   const MCOperand &MO3 = MI->getOperand(OpNum+2);
758
759   O << "[" << getRegisterName(MO1.getReg());
760
761   assert(MO2.getReg() && "Invalid so_reg load / store address!");
762   O << ", " << getRegisterName(MO2.getReg());
763
764   unsigned ShAmt = MO3.getImm();
765   if (ShAmt) {
766     assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
767     O << ", lsl #" << ShAmt;
768   }
769   O << "]";
770 }
771
772 void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
773                                            raw_ostream &O) {
774   O << '#' << MI->getOperand(OpNum).getImm();
775 }
776
777 void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
778                                            raw_ostream &O) {
779   O << '#' << MI->getOperand(OpNum).getImm();
780 }
781
782 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
783                                             raw_ostream &O) {
784   unsigned Imm = MI->getOperand(OpNum).getImm();
785   unsigned OpCmode = (Imm >> 8) & 0x1f;
786   unsigned Imm8 = Imm & 0xff;
787   uint64_t Val = 0;
788
789   if (OpCmode == 0xe) {
790     // 8-bit vector elements
791     Val = Imm8;
792   } else if ((OpCmode & 0xc) == 0x8) {
793     // 16-bit vector elements
794     unsigned ByteNum = (OpCmode & 0x6) >> 1;
795     Val = Imm8 << (8 * ByteNum);
796   } else if ((OpCmode & 0x8) == 0) {
797     // 32-bit vector elements, zero with one byte set
798     unsigned ByteNum = (OpCmode & 0x6) >> 1;
799     Val = Imm8 << (8 * ByteNum);
800   } else if ((OpCmode & 0xe) == 0xc) {
801     // 32-bit vector elements, one byte with low bits set
802     unsigned ByteNum = (OpCmode & 0x1);
803     Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (1 - ByteNum)));
804   } else if (OpCmode == 0x1e) {
805     // 64-bit vector elements
806     for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
807       if ((Imm >> ByteNum) & 1)
808         Val |= (uint64_t)0xff << (8 * ByteNum);
809     }
810   } else {
811     assert(false && "Unsupported NEON immediate");
812   }
813   O << "#0x" << utohexstr(Val);
814 }