Improve handling of #-0 offsets for many more pre-indexed addressing modes.
[oota-llvm.git] / lib / Target / ARM / InstPrinter / 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 "ARMInstPrinter.h"
16 #include "MCTargetDesc/ARMBaseInfo.h"
17 #include "MCTargetDesc/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 #define GET_INSTRUCTION_NAME
26 #include "ARMGenAsmWriter.inc"
27
28 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
29 ///
30 /// getSORegOffset returns an integer from 0-31, but '0' should actually be printed
31 /// 32 as the immediate shouldbe within the range 1-32.
32 static unsigned translateShiftImm(unsigned imm) {
33   if (imm == 0)
34     return 32;
35   return imm;
36 }
37
38 StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
39   return getInstructionName(Opcode);
40 }
41
42 void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
43   OS << getRegisterName(RegNo);
44 }
45
46 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
47   unsigned Opcode = MI->getOpcode();
48
49   // Check for MOVs and print canonical forms, instead.
50   if (Opcode == ARM::MOVsr) {
51     // FIXME: Thumb variants?
52     const MCOperand &Dst = MI->getOperand(0);
53     const MCOperand &MO1 = MI->getOperand(1);
54     const MCOperand &MO2 = MI->getOperand(2);
55     const MCOperand &MO3 = MI->getOperand(3);
56
57     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
58     printSBitModifierOperand(MI, 6, O);
59     printPredicateOperand(MI, 4, O);
60
61     O << '\t' << getRegisterName(Dst.getReg())
62       << ", " << getRegisterName(MO1.getReg());
63
64     O << ", " << getRegisterName(MO2.getReg());
65     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
66     return;
67   }
68
69   if (Opcode == ARM::MOVsi) {
70     // FIXME: Thumb variants?
71     const MCOperand &Dst = MI->getOperand(0);
72     const MCOperand &MO1 = MI->getOperand(1);
73     const MCOperand &MO2 = MI->getOperand(2);
74
75     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
76     printSBitModifierOperand(MI, 5, O);
77     printPredicateOperand(MI, 3, O);
78
79     O << '\t' << getRegisterName(Dst.getReg())
80       << ", " << getRegisterName(MO1.getReg());
81
82     if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx)
83       return;
84
85     O << ", #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
86     return;
87   }
88
89
90   // A8.6.123 PUSH
91   if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
92       MI->getOperand(0).getReg() == ARM::SP) {
93     O << '\t' << "push";
94     printPredicateOperand(MI, 2, O);
95     if (Opcode == ARM::t2STMDB_UPD)
96       O << ".w";
97     O << '\t';
98     printRegisterList(MI, 4, O);
99     return;
100   }
101   if (Opcode == ARM::STR_PRE_IMM && MI->getOperand(2).getReg() == ARM::SP &&
102       MI->getOperand(3).getImm() == -4) {
103     O << '\t' << "push";
104     printPredicateOperand(MI, 4, O);
105     O << "\t{" << getRegisterName(MI->getOperand(1).getReg()) << "}";
106     return;
107   }
108
109   // A8.6.122 POP
110   if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
111       MI->getOperand(0).getReg() == ARM::SP) {
112     O << '\t' << "pop";
113     printPredicateOperand(MI, 2, O);
114     if (Opcode == ARM::t2LDMIA_UPD)
115       O << ".w";
116     O << '\t';
117     printRegisterList(MI, 4, O);
118     return;
119   }
120   if (Opcode == ARM::LDR_POST_IMM && MI->getOperand(2).getReg() == ARM::SP &&
121       MI->getOperand(4).getImm() == 4) {
122     O << '\t' << "pop";
123     printPredicateOperand(MI, 5, O);
124     O << "\t{" << getRegisterName(MI->getOperand(0).getReg()) << "}";
125     return;
126   }
127
128
129   // A8.6.355 VPUSH
130   if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
131       MI->getOperand(0).getReg() == ARM::SP) {
132     O << '\t' << "vpush";
133     printPredicateOperand(MI, 2, O);
134     O << '\t';
135     printRegisterList(MI, 4, O);
136     return;
137   }
138
139   // A8.6.354 VPOP
140   if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
141       MI->getOperand(0).getReg() == ARM::SP) {
142     O << '\t' << "vpop";
143     printPredicateOperand(MI, 2, O);
144     O << '\t';
145     printRegisterList(MI, 4, O);
146     return;
147   }
148
149   if (Opcode == ARM::tLDMIA) {
150     bool Writeback = true;
151     unsigned BaseReg = MI->getOperand(0).getReg();
152     for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
153       if (MI->getOperand(i).getReg() == BaseReg)
154         Writeback = false;
155     }
156
157     O << "\tldm";
158
159     printPredicateOperand(MI, 1, O);
160     O << '\t' << getRegisterName(BaseReg);
161     if (Writeback) O << "!";
162     O << ", ";
163     printRegisterList(MI, 3, O);
164     return;
165   }
166
167   // Thumb1 NOP
168   if (Opcode == ARM::tMOVr && MI->getOperand(0).getReg() == ARM::R8 &&
169       MI->getOperand(1).getReg() == ARM::R8) {
170     O << "\tnop";
171     printPredicateOperand(MI, 2, O);
172     return;
173   }
174
175   printInstruction(MI, O);
176 }
177
178 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
179                                   raw_ostream &O) {
180   const MCOperand &Op = MI->getOperand(OpNo);
181   if (Op.isReg()) {
182     unsigned Reg = Op.getReg();
183     O << getRegisterName(Reg);
184   } else if (Op.isImm()) {
185     O << '#' << Op.getImm();
186   } else {
187     assert(Op.isExpr() && "unknown operand kind in printOperand");
188     O << *Op.getExpr();
189   }
190 }
191
192 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
193 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
194 //    REG 0   0           - e.g. R5
195 //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
196 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
197 void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
198                                        raw_ostream &O) {
199   const MCOperand &MO1 = MI->getOperand(OpNum);
200   const MCOperand &MO2 = MI->getOperand(OpNum+1);
201   const MCOperand &MO3 = MI->getOperand(OpNum+2);
202
203   O << getRegisterName(MO1.getReg());
204
205   // Print the shift opc.
206   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
207   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
208   if (ShOpc == ARM_AM::rrx)
209     return;
210   
211   O << ' ' << getRegisterName(MO2.getReg());
212   assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
213 }
214
215 void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
216                                        raw_ostream &O) {
217   const MCOperand &MO1 = MI->getOperand(OpNum);
218   const MCOperand &MO2 = MI->getOperand(OpNum+1);
219
220   O << getRegisterName(MO1.getReg());
221
222   // Print the shift opc.
223   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
224   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
225   if (ShOpc == ARM_AM::rrx)
226     return;
227   O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
228 }
229
230
231 //===--------------------------------------------------------------------===//
232 // Addressing Mode #2
233 //===--------------------------------------------------------------------===//
234
235 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
236                                                 raw_ostream &O) {
237   const MCOperand &MO1 = MI->getOperand(Op);
238   const MCOperand &MO2 = MI->getOperand(Op+1);
239   const MCOperand &MO3 = MI->getOperand(Op+2);
240
241   O << "[" << getRegisterName(MO1.getReg());
242
243   if (!MO2.getReg()) {
244     if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
245       O << ", #"
246         << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
247         << ARM_AM::getAM2Offset(MO3.getImm());
248     O << "]";
249     return;
250   }
251
252   O << ", "
253     << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
254     << getRegisterName(MO2.getReg());
255
256   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
257     O << ", "
258     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
259     << " #" << ShImm;
260   O << "]";
261 }
262
263 void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
264                                          raw_ostream &O) {
265   const MCOperand &MO1 = MI->getOperand(Op);
266   const MCOperand &MO2 = MI->getOperand(Op+1);
267   const MCOperand &MO3 = MI->getOperand(Op+2);
268
269   O << "[" << getRegisterName(MO1.getReg()) << "], ";
270
271   if (!MO2.getReg()) {
272     unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
273     O << '#'
274       << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
275       << ImmOffs;
276     return;
277   }
278
279   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
280     << getRegisterName(MO2.getReg());
281
282   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
283     O << ", "
284     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
285     << " #" << ShImm;
286 }
287
288 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
289                                            raw_ostream &O) {
290   const MCOperand &MO1 = MI->getOperand(Op);
291
292   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
293     printOperand(MI, Op, O);
294     return;
295   }
296
297   const MCOperand &MO3 = MI->getOperand(Op+2);
298   unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
299
300   if (IdxMode == ARMII::IndexModePost) {
301     printAM2PostIndexOp(MI, Op, O);
302     return;
303   }
304   printAM2PreOrOffsetIndexOp(MI, Op, O);
305 }
306
307 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
308                                                  unsigned OpNum,
309                                                  raw_ostream &O) {
310   const MCOperand &MO1 = MI->getOperand(OpNum);
311   const MCOperand &MO2 = MI->getOperand(OpNum+1);
312
313   if (!MO1.getReg()) {
314     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
315     O << '#'
316       << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
317       << ImmOffs;
318     return;
319   }
320
321   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
322     << getRegisterName(MO1.getReg());
323
324   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
325     O << ", "
326     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
327     << " #" << ShImm;
328 }
329
330 //===--------------------------------------------------------------------===//
331 // Addressing Mode #3
332 //===--------------------------------------------------------------------===//
333
334 void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
335                                          raw_ostream &O) {
336   const MCOperand &MO1 = MI->getOperand(Op);
337   const MCOperand &MO2 = MI->getOperand(Op+1);
338   const MCOperand &MO3 = MI->getOperand(Op+2);
339
340   O << "[" << getRegisterName(MO1.getReg()) << "], ";
341
342   if (MO2.getReg()) {
343     O << (char)ARM_AM::getAM3Op(MO3.getImm())
344     << getRegisterName(MO2.getReg());
345     return;
346   }
347
348   unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
349   O << '#'
350     << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
351     << ImmOffs;
352 }
353
354 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
355                                                 raw_ostream &O) {
356   const MCOperand &MO1 = MI->getOperand(Op);
357   const MCOperand &MO2 = MI->getOperand(Op+1);
358   const MCOperand &MO3 = MI->getOperand(Op+2);
359
360   O << '[' << getRegisterName(MO1.getReg());
361
362   if (MO2.getReg()) {
363     O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
364       << getRegisterName(MO2.getReg()) << ']';
365     return;
366   }
367
368   if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
369     O << ", #"
370       << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
371       << ImmOffs;
372   O << ']';
373 }
374
375 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
376                                            raw_ostream &O) {
377   const MCOperand &MO3 = MI->getOperand(Op+2);
378   unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
379
380   if (IdxMode == ARMII::IndexModePost) {
381     printAM3PostIndexOp(MI, Op, O);
382     return;
383   }
384   printAM3PreOrOffsetIndexOp(MI, Op, O);
385 }
386
387 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
388                                                  unsigned OpNum,
389                                                  raw_ostream &O) {
390   const MCOperand &MO1 = MI->getOperand(OpNum);
391   const MCOperand &MO2 = MI->getOperand(OpNum+1);
392
393   if (MO1.getReg()) {
394     O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
395       << getRegisterName(MO1.getReg());
396     return;
397   }
398
399   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
400   O << '#'
401     << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
402     << ImmOffs;
403 }
404
405 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI,
406                                              unsigned OpNum,
407                                              raw_ostream &O) {
408   const MCOperand &MO = MI->getOperand(OpNum);
409   unsigned Imm = MO.getImm();
410   O << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);
411 }
412
413 void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
414                                             raw_ostream &O) {
415   const MCOperand &MO1 = MI->getOperand(OpNum);
416   const MCOperand &MO2 = MI->getOperand(OpNum+1);
417
418   O << (MO2.getImm() ? "" : "-") << getRegisterName(MO1.getReg());
419 }
420
421 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI,
422                                              unsigned OpNum,
423                                              raw_ostream &O) {
424   const MCOperand &MO = MI->getOperand(OpNum);
425   unsigned Imm = MO.getImm();
426   O << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2);
427 }
428
429
430 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
431                                            raw_ostream &O) {
432   ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
433                                                  .getImm());
434   O << ARM_AM::getAMSubModeStr(Mode);
435 }
436
437 void ARMInstPrinter::printAddrMode5Operand(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   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
443     printOperand(MI, OpNum, O);
444     return;
445   }
446
447   O << "[" << getRegisterName(MO1.getReg());
448
449   unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
450   unsigned Op = ARM_AM::getAM5Op(MO2.getImm());
451   if (ImmOffs || Op == ARM_AM::sub) {
452     O << ", #"
453       << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
454       << ImmOffs * 4;
455   }
456   O << "]";
457 }
458
459 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
460                                            raw_ostream &O) {
461   const MCOperand &MO1 = MI->getOperand(OpNum);
462   const MCOperand &MO2 = MI->getOperand(OpNum+1);
463
464   O << "[" << getRegisterName(MO1.getReg());
465   if (MO2.getImm()) {
466     // FIXME: Both darwin as and GNU as violate ARM docs here.
467     O << ", :" << (MO2.getImm() << 3);
468   }
469   O << "]";
470 }
471
472 void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
473                                            raw_ostream &O) {
474   const MCOperand &MO1 = MI->getOperand(OpNum);
475   O << "[" << getRegisterName(MO1.getReg()) << "]";
476 }
477
478 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
479                                                  unsigned OpNum,
480                                                  raw_ostream &O) {
481   const MCOperand &MO = MI->getOperand(OpNum);
482   if (MO.getReg() == 0)
483     O << "!";
484   else
485     O << ", " << getRegisterName(MO.getReg());
486 }
487
488 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
489                                                     unsigned OpNum,
490                                                     raw_ostream &O) {
491   const MCOperand &MO = MI->getOperand(OpNum);
492   uint32_t v = ~MO.getImm();
493   int32_t lsb = CountTrailingZeros_32(v);
494   int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
495   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
496   O << '#' << lsb << ", #" << width;
497 }
498
499 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
500                                      raw_ostream &O) {
501   unsigned val = MI->getOperand(OpNum).getImm();
502   O << ARM_MB::MemBOptToString(val);
503 }
504
505 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
506                                           raw_ostream &O) {
507   unsigned ShiftOp = MI->getOperand(OpNum).getImm();
508   bool isASR = (ShiftOp & (1 << 5)) != 0;
509   unsigned Amt = ShiftOp & 0x1f;
510   if (isASR)
511     O << ", asr #" << (Amt == 0 ? 32 : Amt);
512   else if (Amt)
513     O << ", lsl #" << Amt;
514 }
515
516 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
517                                          raw_ostream &O) {
518   unsigned Imm = MI->getOperand(OpNum).getImm();
519   if (Imm == 0)
520     return;
521   assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
522   O << ", lsl #" << Imm;
523 }
524
525 void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
526                                          raw_ostream &O) {
527   unsigned Imm = MI->getOperand(OpNum).getImm();
528   // A shift amount of 32 is encoded as 0.
529   if (Imm == 0)
530     Imm = 32;
531   assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
532   O << ", asr #" << Imm;
533 }
534
535 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
536                                        raw_ostream &O) {
537   O << "{";
538   for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
539     if (i != OpNum) O << ", ";
540     O << getRegisterName(MI->getOperand(i).getReg());
541   }
542   O << "}";
543 }
544
545 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
546                                         raw_ostream &O) {
547   const MCOperand &Op = MI->getOperand(OpNum);
548   if (Op.getImm())
549     O << "be";
550   else
551     O << "le";
552 }
553
554 void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
555                                   raw_ostream &O) {
556   const MCOperand &Op = MI->getOperand(OpNum);
557   O << ARM_PROC::IModToString(Op.getImm());
558 }
559
560 void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
561                                    raw_ostream &O) {
562   const MCOperand &Op = MI->getOperand(OpNum);
563   unsigned IFlags = Op.getImm();
564   for (int i=2; i >= 0; --i)
565     if (IFlags & (1 << i))
566       O << ARM_PROC::IFlagsToString(1 << i);
567 }
568
569 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
570                                          raw_ostream &O) {
571   const MCOperand &Op = MI->getOperand(OpNum);
572   unsigned SpecRegRBit = Op.getImm() >> 4;
573   unsigned Mask = Op.getImm() & 0xf;
574
575   // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
576   // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
577   if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
578     O << "APSR_";
579     switch (Mask) {
580     default: assert(0);
581     case 4:  O << "g"; return;
582     case 8:  O << "nzcvq"; return;
583     case 12: O << "nzcvqg"; return;
584     }
585     llvm_unreachable("Unexpected mask value!");
586   }
587
588   if (SpecRegRBit)
589     O << "SPSR";
590   else
591     O << "CPSR";
592
593   if (Mask) {
594     O << '_';
595     if (Mask & 8) O << 'f';
596     if (Mask & 4) O << 's';
597     if (Mask & 2) O << 'x';
598     if (Mask & 1) O << 'c';
599   }
600 }
601
602 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
603                                            raw_ostream &O) {
604   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
605   if (CC != ARMCC::AL)
606     O << ARMCondCodeToString(CC);
607 }
608
609 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
610                                                     unsigned OpNum,
611                                                     raw_ostream &O) {
612   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
613   O << ARMCondCodeToString(CC);
614 }
615
616 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
617                                               raw_ostream &O) {
618   if (MI->getOperand(OpNum).getReg()) {
619     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
620            "Expect ARM CPSR register!");
621     O << 's';
622   }
623 }
624
625 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
626                                           raw_ostream &O) {
627   O << MI->getOperand(OpNum).getImm();
628 }
629
630 void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
631                                           raw_ostream &O) {
632   O << "p" << MI->getOperand(OpNum).getImm();
633 }
634
635 void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
636                                           raw_ostream &O) {
637   O << "c" << MI->getOperand(OpNum).getImm();
638 }
639
640 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
641                                   raw_ostream &O) {
642   llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
643 }
644
645 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
646                                             raw_ostream &O) {
647   O << "#" << MI->getOperand(OpNum).getImm() * 4;
648 }
649
650 void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
651                                      raw_ostream &O) {
652   unsigned Imm = MI->getOperand(OpNum).getImm();
653   O << "#" << (Imm == 0 ? 32 : Imm);
654 }
655
656 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
657                                       raw_ostream &O) {
658   // (3 - the number of trailing zeros) is the number of then / else.
659   unsigned Mask = MI->getOperand(OpNum).getImm();
660   unsigned CondBit0 = Mask >> 4 & 1;
661   unsigned NumTZ = CountTrailingZeros_32(Mask);
662   assert(NumTZ <= 3 && "Invalid IT mask!");
663   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
664     bool T = ((Mask >> Pos) & 1) == CondBit0;
665     if (T)
666       O << 't';
667     else
668       O << 'e';
669   }
670 }
671
672 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
673                                                  raw_ostream &O) {
674   const MCOperand &MO1 = MI->getOperand(Op);
675   const MCOperand &MO2 = MI->getOperand(Op + 1);
676
677   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
678     printOperand(MI, Op, O);
679     return;
680   }
681
682   O << "[" << getRegisterName(MO1.getReg());
683   if (unsigned RegNum = MO2.getReg())
684     O << ", " << getRegisterName(RegNum);
685   O << "]";
686 }
687
688 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
689                                                     unsigned Op,
690                                                     raw_ostream &O,
691                                                     unsigned Scale) {
692   const MCOperand &MO1 = MI->getOperand(Op);
693   const MCOperand &MO2 = MI->getOperand(Op + 1);
694
695   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
696     printOperand(MI, Op, O);
697     return;
698   }
699
700   O << "[" << getRegisterName(MO1.getReg());
701   if (unsigned ImmOffs = MO2.getImm())
702     O << ", #" << ImmOffs * Scale;
703   O << "]";
704 }
705
706 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
707                                                      unsigned Op,
708                                                      raw_ostream &O) {
709   printThumbAddrModeImm5SOperand(MI, Op, O, 1);
710 }
711
712 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
713                                                      unsigned Op,
714                                                      raw_ostream &O) {
715   printThumbAddrModeImm5SOperand(MI, Op, O, 2);
716 }
717
718 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
719                                                      unsigned Op,
720                                                      raw_ostream &O) {
721   printThumbAddrModeImm5SOperand(MI, Op, O, 4);
722 }
723
724 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
725                                                  raw_ostream &O) {
726   printThumbAddrModeImm5SOperand(MI, Op, O, 4);
727 }
728
729 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
730 // register with shift forms.
731 // REG 0   0           - e.g. R5
732 // REG IMM, SH_OPC     - e.g. R5, LSL #3
733 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
734                                       raw_ostream &O) {
735   const MCOperand &MO1 = MI->getOperand(OpNum);
736   const MCOperand &MO2 = MI->getOperand(OpNum+1);
737
738   unsigned Reg = MO1.getReg();
739   O << getRegisterName(Reg);
740
741   // Print the shift opc.
742   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
743   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
744   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
745   if (ShOpc != ARM_AM::rrx)
746     O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
747 }
748
749 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
750                                                raw_ostream &O) {
751   const MCOperand &MO1 = MI->getOperand(OpNum);
752   const MCOperand &MO2 = MI->getOperand(OpNum+1);
753
754   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
755     printOperand(MI, OpNum, O);
756     return;
757   }
758
759   O << "[" << getRegisterName(MO1.getReg());
760
761   int32_t OffImm = (int32_t)MO2.getImm();
762   bool isSub = OffImm < 0;
763   // Special value for #-0. All others are normal.
764   if (OffImm == INT32_MIN)
765     OffImm = 0;
766   if (isSub)
767     O << ", #-" << -OffImm;
768   else if (OffImm > 0)
769     O << ", #" << OffImm;
770   O << "]";
771 }
772
773 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
774                                                 unsigned OpNum,
775                                                 raw_ostream &O) {
776   const MCOperand &MO1 = MI->getOperand(OpNum);
777   const MCOperand &MO2 = MI->getOperand(OpNum+1);
778
779   O << "[" << getRegisterName(MO1.getReg());
780
781   int32_t OffImm = (int32_t)MO2.getImm();
782   // Don't print +0.
783   if (OffImm < 0)
784     O << ", #-" << -OffImm;
785   else if (OffImm > 0)
786     O << ", #" << OffImm;
787   O << "]";
788 }
789
790 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
791                                                   unsigned OpNum,
792                                                   raw_ostream &O) {
793   const MCOperand &MO1 = MI->getOperand(OpNum);
794   const MCOperand &MO2 = MI->getOperand(OpNum+1);
795
796   O << "[" << getRegisterName(MO1.getReg());
797
798   int32_t OffImm = (int32_t)MO2.getImm() / 4;
799   // Don't print +0.
800   if (OffImm < 0)
801     O << ", #-" << -OffImm * 4;
802   else if (OffImm > 0)
803     O << ", #" << OffImm * 4;
804   O << "]";
805 }
806
807 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
808                                                       unsigned OpNum,
809                                                       raw_ostream &O) {
810   const MCOperand &MO1 = MI->getOperand(OpNum);
811   int32_t OffImm = (int32_t)MO1.getImm();
812   // Don't print +0.
813   if (OffImm < 0)
814     O << "#-" << -OffImm;
815   else if (OffImm > 0)
816     O << "#" << OffImm;
817 }
818
819 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
820                                                         unsigned OpNum,
821                                                         raw_ostream &O) {
822   const MCOperand &MO1 = MI->getOperand(OpNum);
823   int32_t OffImm = (int32_t)MO1.getImm() / 4;
824   // Don't print +0.
825   if (OffImm < 0)
826     O << "#-" << -OffImm * 4;
827   else if (OffImm > 0)
828     O << "#" << OffImm * 4;
829 }
830
831 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
832                                                  unsigned OpNum,
833                                                  raw_ostream &O) {
834   const MCOperand &MO1 = MI->getOperand(OpNum);
835   const MCOperand &MO2 = MI->getOperand(OpNum+1);
836   const MCOperand &MO3 = MI->getOperand(OpNum+2);
837
838   O << "[" << getRegisterName(MO1.getReg());
839
840   assert(MO2.getReg() && "Invalid so_reg load / store address!");
841   O << ", " << getRegisterName(MO2.getReg());
842
843   unsigned ShAmt = MO3.getImm();
844   if (ShAmt) {
845     assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
846     O << ", lsl #" << ShAmt;
847   }
848   O << "]";
849 }
850
851 void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
852                                            raw_ostream &O) {
853   const MCOperand &MO = MI->getOperand(OpNum);
854   O << '#';
855   if (MO.isFPImm()) {
856     O << (float)MO.getFPImm();
857   } else {
858     union {
859       uint32_t I;
860       float F;
861     } FPUnion;
862
863     FPUnion.I = MO.getImm();
864     O << FPUnion.F;
865   }
866 }
867
868 void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
869                                            raw_ostream &O) {
870   const MCOperand &MO = MI->getOperand(OpNum);
871   O << '#';
872   if (MO.isFPImm()) {
873     O << MO.getFPImm();
874   } else {
875     // We expect the binary encoding of a floating point number here.
876     union {
877       uint64_t I;
878       double D;
879     } FPUnion;
880
881     FPUnion.I = MO.getImm();
882     O << FPUnion.D;
883   }
884 }
885
886 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
887                                             raw_ostream &O) {
888   unsigned EncodedImm = MI->getOperand(OpNum).getImm();
889   unsigned EltBits;
890   uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
891   O << "#0x" << utohexstr(Val);
892 }
893
894 void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
895                                             raw_ostream &O) {
896   unsigned Imm = MI->getOperand(OpNum).getImm();
897   O << "#" << Imm + 1;
898 }
899
900 void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
901                                         raw_ostream &O) {
902   unsigned Imm = MI->getOperand(OpNum).getImm();
903   if (Imm == 0)
904     return;
905   O << ", ror #";
906   switch (Imm) {
907   default: assert (0 && "illegal ror immediate!");
908   case 1: O << "8"; break;
909   case 2: O << "16"; break;
910   case 3: O << "24"; break;
911   }
912 }