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