Fix -Asserts warning.
[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 #define NO_ASM_WRITER_BOILERPLATE
28 #include "ARMGenAsmWriter.inc"
29 #undef MachineInstr
30 #undef ARMAsmPrinter
31
32 void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
33
34 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
35                                   const char *Modifier) {
36   const MCOperand &Op = MI->getOperand(OpNo);
37   if (Op.isReg()) {
38     unsigned Reg = Op.getReg();
39     if (Modifier && strcmp(Modifier, "dregpair") == 0) {
40       // FIXME: Breaks e.g. ARM/vmul.ll.
41       assert(0);
42       /*
43       unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
44       unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
45       O << '{'
46       << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
47       << '}';*/
48     } else if (Modifier && strcmp(Modifier, "lane") == 0) {
49       assert(0);
50       /*
51       unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
52       unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
53                                                &ARM::DPR_VFP2RegClass);
54       O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
55        */
56     } else {
57       O << getRegisterName(Reg);
58     }
59   } else if (Op.isImm()) {
60     assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
61     O << '#' << Op.getImm();
62   } else {
63     assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
64     assert(Op.isExpr() && "unknown operand kind in printOperand");
65     Op.getExpr()->print(O, &MAI);
66   }
67 }
68
69 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
70                        const MCAsmInfo *MAI) {
71   // Break it up into two parts that make up a shifter immediate.
72   V = ARM_AM::getSOImmVal(V);
73   assert(V != -1 && "Not a valid so_imm value!");
74   
75   unsigned Imm = ARM_AM::getSOImmValImm(V);
76   unsigned Rot = ARM_AM::getSOImmValRot(V);
77   
78   // Print low-level immediate formation info, per
79   // A5.1.3: "Data-processing operands - Immediate".
80   if (Rot) {
81     O << "#" << Imm << ", " << Rot;
82     // Pretty printed version.
83     if (VerboseAsm)
84       O << ' ' << MAI->getCommentString()
85       << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
86   } else {
87     O << "#" << Imm;
88   }
89 }
90
91
92 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
93 /// immediate in bits 0-7.
94 void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum) {
95   const MCOperand &MO = MI->getOperand(OpNum);
96   assert(MO.isImm() && "Not a valid so_imm value!");
97   printSOImm(O, MO.getImm(), VerboseAsm, &MAI);
98 }
99
100 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
101 /// followed by an 'orr' to materialize.
102 void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) {
103   // FIXME: REMOVE this method.
104   abort();
105 }
106
107 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
108 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
109 //    REG 0   0           - e.g. R5
110 //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
111 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
112 void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum) {
113   const MCOperand &MO1 = MI->getOperand(OpNum);
114   const MCOperand &MO2 = MI->getOperand(OpNum+1);
115   const MCOperand &MO3 = MI->getOperand(OpNum+2);
116   
117   O << getRegisterName(MO1.getReg());
118   
119   // Print the shift opc.
120   O << ", "
121     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
122     << ' ';
123   
124   if (MO2.getReg()) {
125     O << getRegisterName(MO2.getReg());
126     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
127   } else {
128     O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
129   }
130 }
131
132
133 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) {
134   const MCOperand &MO1 = MI->getOperand(Op);
135   const MCOperand &MO2 = MI->getOperand(Op+1);
136   const MCOperand &MO3 = MI->getOperand(Op+2);
137   
138   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
139     printOperand(MI, Op);
140     return;
141   }
142   
143   O << "[" << getRegisterName(MO1.getReg());
144   
145   if (!MO2.getReg()) {
146     if (ARM_AM::getAM2Offset(MO3.getImm()))  // Don't print +0.
147       O << ", #"
148       << (char)ARM_AM::getAM2Op(MO3.getImm())
149       << ARM_AM::getAM2Offset(MO3.getImm());
150     O << "]";
151     return;
152   }
153   
154   O << ", "
155   << (char)ARM_AM::getAM2Op(MO3.getImm())
156   << getRegisterName(MO2.getReg());
157   
158   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
159     O << ", "
160     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
161     << " #" << ShImm;
162   O << "]";
163 }  
164
165 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
166                                                  unsigned OpNum) {
167   const MCOperand &MO1 = MI->getOperand(OpNum);
168   const MCOperand &MO2 = MI->getOperand(OpNum+1);
169   
170   if (!MO1.getReg()) {
171     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
172     assert(ImmOffs && "Malformed indexed load / store!");
173     O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
174     return;
175   }
176   
177   O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
178   
179   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
180     O << ", "
181     << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
182     << " #" << ShImm;
183 }
184
185 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) {
186   const MCOperand &MO1 = MI->getOperand(OpNum);
187   const MCOperand &MO2 = MI->getOperand(OpNum+1);
188   const MCOperand &MO3 = MI->getOperand(OpNum+2);
189   
190   O << '[' << getRegisterName(MO1.getReg());
191   
192   if (MO2.getReg()) {
193     O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
194       << getRegisterName(MO2.getReg()) << ']';
195     return;
196   }
197   
198   if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
199     O << ", #"
200     << (char)ARM_AM::getAM3Op(MO3.getImm())
201     << ImmOffs;
202   O << ']';
203 }
204
205 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
206                                                  unsigned OpNum) {
207   const MCOperand &MO1 = MI->getOperand(OpNum);
208   const MCOperand &MO2 = MI->getOperand(OpNum+1);
209   
210   if (MO1.getReg()) {
211     O << (char)ARM_AM::getAM3Op(MO2.getImm())
212     << getRegisterName(MO1.getReg());
213     return;
214   }
215   
216   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
217   assert(ImmOffs && "Malformed indexed load / store!");
218   O << "#"
219   << (char)ARM_AM::getAM3Op(MO2.getImm())
220   << ImmOffs;
221 }
222
223
224 void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
225                                            const char *Modifier) {
226   const MCOperand &MO1 = MI->getOperand(OpNum);
227   const MCOperand &MO2 = MI->getOperand(OpNum+1);
228   ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
229   if (Modifier && strcmp(Modifier, "submode") == 0) {
230     if (MO1.getReg() == ARM::SP) {
231       // FIXME
232       bool isLDM = (MI->getOpcode() == ARM::LDM ||
233                     MI->getOpcode() == ARM::LDM_RET ||
234                     MI->getOpcode() == ARM::t2LDM ||
235                     MI->getOpcode() == ARM::t2LDM_RET);
236       O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
237     } else
238       O << ARM_AM::getAMSubModeStr(Mode);
239   } else if (Modifier && strcmp(Modifier, "wide") == 0) {
240     ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
241     if (Mode == ARM_AM::ia)
242       O << ".w";
243   } else {
244     printOperand(MI, OpNum);
245     if (ARM_AM::getAM4WBFlag(MO2.getImm()))
246       O << "!";
247   }
248 }
249
250 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
251                                            const char *Modifier) {
252   const MCOperand &MO1 = MI->getOperand(OpNum);
253   const MCOperand &MO2 = MI->getOperand(OpNum+1);
254   
255   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
256     printOperand(MI, OpNum);
257     return;
258   }
259   
260   if (Modifier && strcmp(Modifier, "submode") == 0) {
261     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
262     if (MO1.getReg() == ARM::SP) {
263       bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
264                      MI->getOpcode() == ARM::FLDMS);
265       O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
266     } else
267       O << ARM_AM::getAMSubModeStr(Mode);
268     return;
269   } else if (Modifier && strcmp(Modifier, "base") == 0) {
270     // Used for FSTM{D|S} and LSTM{D|S} operations.
271     O << getRegisterName(MO1.getReg());
272     if (ARM_AM::getAM5WBFlag(MO2.getImm()))
273       O << "!";
274     return;
275   }
276   
277   O << "[" << getRegisterName(MO1.getReg());
278   
279   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
280     O << ", #"
281       << (char)ARM_AM::getAM5Op(MO2.getImm())
282       << ImmOffs*4;
283   }
284   O << "]";
285 }
286
287 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) {
288   const MCOperand &MO1 = MI->getOperand(OpNum);
289   const MCOperand &MO2 = MI->getOperand(OpNum+1);
290   const MCOperand &MO3 = MI->getOperand(OpNum+2);
291   
292   // FIXME: No support yet for specifying alignment.
293   O << '[' << getRegisterName(MO1.getReg()) << ']';
294   
295   if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
296     if (MO2.getReg() == 0)
297       O << '!';
298     else
299       O << ", " << getRegisterName(MO2.getReg());
300   }
301 }
302
303 void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
304                                             const char *Modifier) {
305   assert(0 && "FIXME: Implement printAddrModePCOperand");
306 }
307
308 void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
309                                                      unsigned OpNum) {
310   const MCOperand &MO = MI->getOperand(OpNum);
311   uint32_t v = ~MO.getImm();
312   int32_t lsb = CountTrailingZeros_32(v);
313   int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
314   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
315   O << '#' << lsb << ", #" << width;
316 }
317
318 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
319   O << "{";
320   // Always skip the first operand, it's the optional (and implicit writeback).
321   for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
322     if (i != OpNum+1) O << ", ";
323     O << getRegisterName(MI->getOperand(i).getReg());
324   }
325   O << "}";
326 }
327
328 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
329   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
330   if (CC != ARMCC::AL)
331     O << ARMCondCodeToString(CC);
332 }
333
334 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){
335   if (MI->getOperand(OpNum).getReg()) {
336     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
337            "Expect ARM CPSR register!");
338     O << 's';
339   }
340 }
341
342
343
344 void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
345                                         const char *Modifier) {
346   // FIXME: remove this.
347   abort();
348 }
349
350 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum) {
351   O << MI->getOperand(OpNum).getImm();
352 }
353
354
355 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) {
356   // FIXME: remove this.
357   abort();
358 }