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