Emacs-tag and some comment fix for all ARM, CellSPU, Hexagon, MBlaze, MSP430, PPC...
[oota-llvm.git] / lib / Target / Hexagon / HexagonAsmPrinter.cpp
1 //===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly --===//
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 file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to Hexagon assembly language. This printer is
12 // the output mechanism used by `llc'.
13 //
14 // Documentation at http://developer.apple.com/documentation/DeveloperTools/
15 // Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
16 //
17 //===----------------------------------------------------------------------===//
18
19
20 #define DEBUG_TYPE "asm-printer"
21 #include "Hexagon.h"
22 #include "HexagonTargetMachine.h"
23 #include "HexagonSubtarget.h"
24 #include "HexagonMachineFunctionInfo.h"
25 #include "llvm/Constants.h"
26 #include "llvm/DerivedTypes.h"
27 #include "llvm/Module.h"
28 #include "llvm/Assembly/Writer.h"
29 #include "llvm/CodeGen/AsmPrinter.h"
30 #include "llvm/CodeGen/MachineModuleInfo.h"
31 #include "llvm/CodeGen/MachineFunctionPass.h"
32 #include "llvm/CodeGen/MachineInstr.h"
33 #include "llvm/CodeGen/MachineInstrBuilder.h"
34 #include "llvm/MC/MCStreamer.h"
35 #include "llvm/MC/MCAsmInfo.h"
36 #include "llvm/MC/MCSymbol.h"
37 #include "llvm/Support/MathExtras.h"
38 #include "llvm/Support/MathExtras.h"
39 #include "llvm/Support/CommandLine.h"
40 #include "llvm/Support/Debug.h"
41 #include "llvm/Support/Compiler.h"
42 #include "llvm/Support/raw_ostream.h"
43 #include "llvm/Target/Mangler.h"
44 #include "llvm/Target/TargetData.h"
45 #include "llvm/Target/TargetLoweringObjectFile.h"
46 #include "llvm/Target/TargetRegisterInfo.h"
47 #include "llvm/Target/TargetInstrInfo.h"
48 #include "llvm/Target/TargetOptions.h"
49 #include "llvm/ADT/SmallPtrSet.h"
50 #include "llvm/ADT/SmallString.h"
51 #include "llvm/ADT/StringExtras.h"
52 #include "llvm/Support/TargetRegistry.h"
53 #include "llvm/Support/raw_ostream.h"
54
55 using namespace llvm;
56
57 static cl::opt<bool> AlignCalls(
58          "hexagon-align-calls", cl::Hidden, cl::init(true),
59           cl::desc("Insert falign after call instruction for Hexagon target"));
60
61
62 namespace {
63   class HexagonAsmPrinter : public AsmPrinter {
64     const HexagonSubtarget *Subtarget;
65
66   public:
67     explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
68       : AsmPrinter(TM, Streamer) {
69       Subtarget = &TM.getSubtarget<HexagonSubtarget>();
70     }
71
72     virtual const char *getPassName() const {
73       return "Hexagon Assembly Printer";
74     }
75
76     /// printInstruction - This method is automatically generated by tablegen
77     /// from the instruction set description.  This method returns true if the
78     /// machine instruction was sufficiently described to print it, otherwise it
79     void printInstruction(const MachineInstr *MI, raw_ostream &O);
80     virtual void EmitInstruction(const MachineInstr *MI);
81
82     void printOp(const MachineOperand &MO, raw_ostream &O);
83
84     /// printRegister - Print register according to target requirements.
85     ///
86     void printRegister(const MachineOperand &MO, bool R0AsZero,
87                        raw_ostream &O) {
88       unsigned RegNo = MO.getReg();
89       assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
90       O << getRegisterName(RegNo);
91     }
92
93     void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS) {
94       const MachineOperand &MO = MI->getOperand(OpNo);
95       if (MO.isReg()) {
96         printRegister(MO, false, OS);
97       } else if (MO.isImm()) {
98         OS << MO.getImm();
99       } else {
100         printOp(MO, OS);
101       }
102     }
103
104
105     bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
106
107     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
108                          unsigned AsmVariant, const char *ExtraCode,
109                          raw_ostream &OS);
110     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
111                                unsigned AsmVariant, const char *ExtraCode,
112                                raw_ostream &OS);
113
114
115     void printHexagonImmOperand(const MachineInstr *MI, unsigned OpNo,
116                                 raw_ostream &O) {
117       int value = MI->getOperand(OpNo).getImm();
118       O << value;
119     }
120
121
122     void printHexagonNegImmOperand(const MachineInstr *MI, unsigned OpNo,
123                                    raw_ostream &O) {
124       int value = MI->getOperand(OpNo).getImm();
125       O << -value;
126     }
127
128     void printHexagonNOneImmOperand(const MachineInstr *MI, unsigned OpNo,
129                                     raw_ostream &O) const {
130       O << -1;
131     }
132
133     void printHexagonMEMriOperand(const MachineInstr *MI, unsigned OpNo,
134                                   raw_ostream &O) {
135       const MachineOperand &MO1 = MI->getOperand(OpNo);
136       const MachineOperand &MO2 = MI->getOperand(OpNo+1);
137
138       O << getRegisterName(MO1.getReg())
139         << " + #"
140         << (int) MO2.getImm();
141     }
142
143
144     void printHexagonFrameIndexOperand(const MachineInstr *MI, unsigned OpNo,
145                                        raw_ostream &O) {
146       const MachineOperand &MO1 = MI->getOperand(OpNo);
147       const MachineOperand &MO2 = MI->getOperand(OpNo+1);
148
149       O << getRegisterName(MO1.getReg())
150         << ", #"
151         << MO2.getImm();
152     }
153
154     void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
155                             raw_ostream &O) {
156       // Branches can take an immediate operand.  This is used by the branch
157       // selection pass to print $+8, an eight byte displacement from the PC.
158       if (MI->getOperand(OpNo).isImm()) {
159         O << "$+" << MI->getOperand(OpNo).getImm()*4;
160       } else {
161         printOp(MI->getOperand(OpNo), O);
162       }
163     }
164
165     void printCallOperand(const MachineInstr *MI, unsigned OpNo,
166                           raw_ostream &O) {
167     }
168
169     void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
170                             raw_ostream &O) {
171     }
172
173
174     void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
175       O << "#HI(";
176       if (MI->getOperand(OpNo).isImm()) {
177         printHexagonImmOperand(MI, OpNo, O);
178       } else {
179         printOp(MI->getOperand(OpNo), O);
180       }
181       O << ")";
182     }
183
184     void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
185       O << "#HI(";
186       if (MI->getOperand(OpNo).isImm()) {
187         printHexagonImmOperand(MI, OpNo, O);
188       } else {
189         printOp(MI->getOperand(OpNo), O);
190       }
191       O << ")";
192     }
193
194     void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
195                                raw_ostream &O);
196
197     void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo,
198                                      raw_ostream &O);
199
200     void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O);
201     void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O);
202
203     void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const;
204
205     static const char *getRegisterName(unsigned RegNo);
206   };
207
208 } // end of anonymous namespace
209
210 // Include the auto-generated portion of the assembly writer.
211 #include "HexagonGenAsmWriter.inc"
212
213
214 void HexagonAsmPrinter::EmitAlignment(unsigned NumBits,
215                                       const GlobalValue *GV) const {
216
217   // For basic block level alignment, use falign.
218   if (!GV) {
219     OutStreamer.EmitRawText(StringRef("\t.falign"));
220     return;
221   }
222
223   AsmPrinter::EmitAlignment(NumBits, GV);
224 }
225
226 void HexagonAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) {
227   switch (MO.getType()) {
228   case MachineOperand::MO_Immediate:
229     dbgs() << "printOp() does not handle immediate values\n";
230     abort();
231
232   case MachineOperand::MO_MachineBasicBlock:
233     O << *MO.getMBB()->getSymbol();
234     return;
235   case MachineOperand::MO_JumpTableIndex:
236     O << *GetJTISymbol(MO.getIndex());
237     // FIXME: PIC relocation model.
238     return;
239   case MachineOperand::MO_ConstantPoolIndex:
240     O << *GetCPISymbol(MO.getIndex());
241     return;
242   case MachineOperand::MO_ExternalSymbol:
243     O << *GetExternalSymbolSymbol(MO.getSymbolName());
244     return;
245   case MachineOperand::MO_GlobalAddress: {
246     // Computing the address of a global symbol, not calling it.
247     O << *Mang->getSymbol(MO.getGlobal());
248     printOffset(MO.getOffset(), O);
249     return;
250   }
251
252   default:
253     O << "<unknown operand type: " << MO.getType() << ">";
254     return;
255   }
256 }
257
258
259 //
260 // isBlockOnlyReachableByFallthrough - We need to override this since the
261 // default AsmPrinter does not print labels for any basic block that
262 // is only reachable by a fall through. That works for all cases except
263 // for the case in which the basic block is reachable by a fall through but
264 // through an indirect from a jump table. In this case, the jump table
265 // will contain a label not defined by AsmPrinter.
266 //
267 bool HexagonAsmPrinter::
268 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
269   if (MBB->hasAddressTaken()) {
270     return false;
271   }
272   return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB);
273 }
274
275
276 /// PrintAsmOperand - Print out an operand for an inline asm expression.
277 ///
278 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
279                                         unsigned AsmVariant,
280                                         const char *ExtraCode,
281                                       raw_ostream &OS) {
282   // Does this asm operand have a single letter operand modifier?
283   if (ExtraCode && ExtraCode[0]) {
284     if (ExtraCode[1] != 0) return true; // Unknown modifier.
285
286     switch (ExtraCode[0]) {
287     default: return true;  // Unknown modifier.
288     case 'c': // Don't print "$" before a global var name or constant.
289       // Hexagon never has a prefix.
290       printOperand(MI, OpNo, OS);
291       return false;
292     case 'L': // Write second word of DImode reference.
293       // Verify that this operand has two consecutive registers.
294       if (!MI->getOperand(OpNo).isReg() ||
295           OpNo+1 == MI->getNumOperands() ||
296           !MI->getOperand(OpNo+1).isReg())
297         return true;
298       ++OpNo;   // Return the high-part.
299       break;
300     case 'I':
301       // Write 'i' if an integer constant, otherwise nothing.  Used to print
302       // addi vs add, etc.
303       if (MI->getOperand(OpNo).isImm())
304         OS << "i";
305       return false;
306     }
307   }
308
309   printOperand(MI, OpNo, OS);
310   return false;
311 }
312
313 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
314                                             unsigned OpNo, unsigned AsmVariant,
315                                             const char *ExtraCode,
316                                             raw_ostream &O) {
317   if (ExtraCode && ExtraCode[0])
318     return true; // Unknown modifier.
319
320   const MachineOperand &Base  = MI->getOperand(OpNo);
321   const MachineOperand &Offset = MI->getOperand(OpNo+1);
322
323   if (Base.isReg())
324     printOperand(MI, OpNo, O);
325   else
326     llvm_unreachable("Unimplemented");
327
328   if (Offset.isImm()) {
329     if (Offset.getImm())
330       O << " + #" << Offset.getImm();
331   }
332   else
333     llvm_unreachable("Unimplemented");
334
335   return false;
336 }
337
338 void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI,
339                                               unsigned OpNo,
340                                               raw_ostream &O) {
341   llvm_unreachable("Unimplemented");
342 }
343
344
345 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to
346 /// the current output stream.
347 ///
348 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
349   SmallString<128> Str;
350   raw_svector_ostream O(Str);
351
352   const MachineFunction* MF = MI->getParent()->getParent();
353   const HexagonMachineFunctionInfo* MFI =
354     (const HexagonMachineFunctionInfo*)
355     MF->getInfo<HexagonMachineFunctionInfo>();
356
357
358
359   // Print a brace for the beginning of the packet.
360   if (MFI->isStartPacket(MI)) {
361     O << "\t{" << '\n';
362   }
363
364   DEBUG( O << "// MI = " << *MI << '\n';);
365
366   // Indent
367   O << "\t";
368
369
370   if (MI->getOpcode() == Hexagon::ENDLOOP0) {
371     if (MFI->isEndPacket(MI) && MFI->isStartPacket(MI)) {
372       O << "\t{ nop }";
373     } else {
374     O << "}";
375     }
376     printInstruction(MI, O);
377   } else if (MI->getOpcode() == Hexagon::STriwt) {
378     //
379     // Handle truncated store on Hexagon.
380     //
381     O << "\tmemw(";
382     printHexagonMEMriOperand(MI, 0, O);
383
384     O << ") = ";
385     unsigned SubRegNum =
386       TM.getRegisterInfo()->getSubReg(MI->getOperand(2)
387                                       .getReg(), Hexagon::subreg_loreg);
388     const char *SubRegName = getRegisterName(SubRegNum);
389     O << SubRegName << '\n';
390   } else if (MI->getOpcode() == Hexagon::MPYI_rin) {
391     // Handle multipy with -ve constant on Hexagon:
392     // "$dst =- mpyi($src1, #$src2)"
393       printOperand(MI, 0, O);
394     O << " =- mpyi(";
395     printOperand(MI, 1, O);
396     O << ", #";
397     printHexagonNegImmOperand(MI, 2, O);
398     O << ")";
399   } else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_indexed_MEM_V4) {
400     //
401     // Handle memw(Rs+u6:2) [+-]= #U5
402     //
403     O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
404     int addend = MI->getOperand(2).getImm();
405     if (addend < 0)
406       O << "-= " << "#" << -addend << '\n';
407     else
408       O << "+= " << "#" << addend << '\n';
409   } else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_MEM_V4) {
410     //
411     // Handle memw(Rs+u6:2) [+-]= #U5
412     //
413     O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
414     int addend = MI->getOperand(2).getImm();
415     if (addend < 0)
416       O << "-= " << "#" << -addend << '\n';
417     else
418       O << "+= " << "#" << addend << '\n';
419   } else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_indexed_MEM_V4) {
420     //
421     // Handle memh(Rs+u6:1) [+-]= #U5
422     //
423     O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
424     int addend = MI->getOperand(2).getImm();
425     if (addend < 0)
426       O << "-= " << "#" << -addend << '\n';
427     else
428       O << "+= " << "#" << addend << '\n';
429   } else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_MEM_V4) {
430     //
431     // Handle memh(Rs+u6:1) [+-]= #U5
432     //
433     O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
434     int addend = MI->getOperand(2).getImm();
435     if (addend < 0)
436       O << "-= " << "#" << -addend << '\n';
437     else
438       O << "+= " << "#" << addend << '\n';
439   } else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_indexed_MEM_V4) {
440     //
441     // Handle memb(Rs+u6:1) [+-]= #U5
442     //
443     O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
444     int addend = MI->getOperand(2).getImm();
445     if (addend < 0)
446       O << "-= " << "#" << -addend << '\n';
447     else
448       O << "+= " << "#" << addend << '\n';
449   } else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_MEM_V4) {
450     //
451     // Handle memb(Rs+u6:1) [+-]= #U5
452     //
453     O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
454     int addend = MI->getOperand(2).getImm();
455     if (addend < 0)
456       O << "-= " << "#" << -addend << '\n';
457     else
458       O << "+= " << "#" << addend << '\n';
459   } else if (MI->getOpcode() == Hexagon::CMPbGTri_V4) {
460     //
461     // Handle Pd=cmpb.gt(Rs,#s8)
462     //
463     O << "\t";
464     printRegister(MI->getOperand(0), false, O);
465     O << " = cmpb.gt(";
466     printRegister(MI->getOperand(1), false, O);
467     O << ", ";
468     int val = MI->getOperand(2).getImm() >> 24;
469     O << "#" << val << ")" << '\n';
470   } else if (MI->getOpcode() == Hexagon::CMPhEQri_V4) {
471     //
472     // Handle Pd=cmph.eq(Rs,#8)
473     //
474     O << "\t";
475     printRegister(MI->getOperand(0), false, O);
476     O << " = cmph.eq(";
477     printRegister(MI->getOperand(1), false, O);
478     O << ", ";
479     int val = MI->getOperand(2).getImm();
480     assert((((0 <= val) && (val <= 127)) ||
481             ((65408 <= val) && (val <= 65535))) &&
482            "Not in correct range!");
483     if (val >= 65408) val -= 65536;
484     O << "#" << val << ")" << '\n';
485   } else if (MI->getOpcode() == Hexagon::CMPhGTri_V4) {
486     //
487     // Handle Pd=cmph.gt(Rs,#8)
488     //
489     O << "\t";
490     printRegister(MI->getOperand(0), false, O);
491     O << " = cmph.gt(";
492     printRegister(MI->getOperand(1), false, O);
493     O << ", ";
494     int val = MI->getOperand(2).getImm() >> 16;
495     O << "#" << val << ")" << '\n';
496   } else {
497     printInstruction(MI, O);
498   }
499
500   // Print a brace for the end of the packet.
501   if (MFI->isEndPacket(MI) && MI->getOpcode() != Hexagon::ENDLOOP0) {
502     O << "\n\t}" << '\n';
503   }
504
505   if (AlignCalls && MI->getDesc().isCall()) {
506     O << "\n\t.falign" << "\n";
507   }
508
509   OutStreamer.EmitRawText(O.str());
510   return;
511 }
512
513 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
514 /// Don't print things like \n or \0.
515 // static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
516 //   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
517 //        Name != E; ++Name)
518 //     if (isprint(*Name))
519 //       OS << *Name;
520 // }
521
522
523 void HexagonAsmPrinter::printAddrModeBasePlusOffset(const MachineInstr *MI,
524                                                     int OpNo, raw_ostream &O) {
525   const MachineOperand &MO1 = MI->getOperand(OpNo);
526   const MachineOperand &MO2 = MI->getOperand(OpNo+1);
527
528   O << getRegisterName(MO1.getReg())
529     << " + #"
530     << MO2.getImm();
531 }
532
533
534 void HexagonAsmPrinter::printGlobalOperand(const MachineInstr *MI, int OpNo,
535                                            raw_ostream &O) {
536   const MachineOperand &MO = MI->getOperand(OpNo);
537   assert( (MO.getType() == MachineOperand::MO_GlobalAddress) &&
538          "Expecting global address");
539
540   O << *Mang->getSymbol(MO.getGlobal());
541   if (MO.getOffset() != 0) {
542     O << " + ";
543     O << MO.getOffset();
544   }
545 }
546
547 void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo,
548                                        raw_ostream &O) {
549   const MachineOperand &MO = MI->getOperand(OpNo);
550   assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) &&
551           "Expecting jump table index");
552
553   // Hexagon_TODO: Do we need name mangling?
554   O << *GetJTISymbol(MO.getIndex());
555 }
556
557 extern "C" void LLVMInitializeHexagonAsmPrinter() {
558   RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget);
559 }