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