1 //===-- MBlazeAsmPrinter.cpp - MBlaze LLVM assembly writer ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format MBlaze assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "mblaze-asm-printer"
18 #include "MBlazeSubtarget.h"
19 #include "MBlazeInstrInfo.h"
20 #include "MBlazeTargetMachine.h"
21 #include "MBlazeMachineFunction.h"
22 #include "llvm/Constants.h"
23 #include "llvm/DerivedTypes.h"
24 #include "llvm/Module.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineConstantPool.h"
28 #include "llvm/CodeGen/MachineFrameInfo.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/MC/MCStreamer.h"
31 #include "llvm/MC/MCAsmInfo.h"
32 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/Target/Mangler.h"
34 #include "llvm/Target/TargetData.h"
35 #include "llvm/Target/TargetLoweringObjectFile.h"
36 #include "llvm/Target/TargetMachine.h"
37 #include "llvm/Target/TargetOptions.h"
38 #include "llvm/Target/TargetRegistry.h"
39 #include "llvm/ADT/SmallString.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include "llvm/Support/ErrorHandling.h"
42 #include "llvm/Support/raw_ostream.h"
48 class MBlazeAsmPrinter : public AsmPrinter {
49 const MBlazeSubtarget *Subtarget;
51 explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
52 : AsmPrinter(TM, Streamer) {
53 Subtarget = &TM.getSubtarget<MBlazeSubtarget>();
56 virtual const char *getPassName() const {
57 return "MBlaze Assembly Printer";
60 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
61 unsigned AsmVariant, const char *ExtraCode,
63 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
64 void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O);
65 void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O);
66 void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
67 const char *Modifier = 0);
68 void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
69 const char *Modifier = 0);
70 void printSavedRegsBitmask(raw_ostream &OS);
72 const char *emitCurrentABIString();
73 void emitFrameDirective();
75 void printInstruction(const MachineInstr *MI, raw_ostream &O);
76 void EmitInstruction(const MachineInstr *MI) {
78 raw_svector_ostream OS(Str);
79 printInstruction(MI, OS);
80 OutStreamer.EmitRawText(OS.str());
82 virtual void EmitFunctionBodyStart();
83 virtual void EmitFunctionBodyEnd();
84 static const char *getRegisterName(unsigned RegNo);
86 virtual void EmitFunctionEntryLabel();
88 } // end of anonymous namespace
90 #include "MBlazeGenAsmWriter.inc"
92 //===----------------------------------------------------------------------===//
94 // MBlaze Asm Directives
96 // -- Frame directive "frame Stackpointer, Stacksize, RARegister"
97 // Describe the stack frame.
99 // -- Mask directives "mask bitmask, offset"
100 // Tells the assembler which registers are saved and where.
101 // bitmask - contain a little endian bitset indicating which registers are
102 // saved on function prologue (e.g. with a 0x80000000 mask, the
103 // assembler knows the register 31 (RA) is saved at prologue.
104 // offset - the position before stack pointer subtraction indicating where
105 // the first saved register on prologue is located. (e.g. with a
107 // Consider the following function prologue:
110 // .mask 0xc0000000,-8
115 // With a 0xc0000000 mask, the assembler knows the register 15 (R15) and
116 // 19 (R19) are saved at prologue. As the save order on prologue is from
117 // left to right, R15 is saved first. A -8 offset means that after the
118 // stack pointer subtration, the first register in the mask (R15) will be
119 // saved at address 48-8=40.
121 //===----------------------------------------------------------------------===//
123 //===----------------------------------------------------------------------===//
125 //===----------------------------------------------------------------------===//
127 // Print a 32 bit hex number with all numbers.
128 static void printHex32(unsigned int Value, raw_ostream &O) {
130 for (int i = 7; i >= 0; i--)
131 O << utohexstr((Value & (0xF << (i*4))) >> (i*4));
135 // Create a bitmask with all callee saved registers for CPU or Floating Point
136 // registers. For CPU registers consider RA, GP and FP for saving if necessary.
137 void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) {
138 const TargetRegisterInfo &RI = *TM.getRegisterInfo();
139 const MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>();
141 // CPU Saved Registers Bitmasks
142 unsigned int CPUBitmask = 0;
144 // Set the CPU Bitmasks
145 const MachineFrameInfo *MFI = MF->getFrameInfo();
146 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
147 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
148 unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(CSI[i].getReg());
149 if (CSI[i].getRegClass() == MBlaze::CPURegsRegisterClass)
150 CPUBitmask |= (1 << RegNum);
153 // Return Address and Frame registers must also be set in CPUBitmask.
155 CPUBitmask |= (1 << MBlazeRegisterInfo::
156 getRegisterNumbering(RI.getFrameRegister(*MF)));
159 CPUBitmask |= (1 << MBlazeRegisterInfo::
160 getRegisterNumbering(RI.getRARegister()));
163 O << "\t.mask \t"; printHex32(CPUBitmask, O);
164 O << ',' << MBlazeFI->getCPUTopSavedRegOff() << '\n';
167 //===----------------------------------------------------------------------===//
168 // Frame and Set directives
169 //===----------------------------------------------------------------------===//
172 void MBlazeAsmPrinter::emitFrameDirective() {
173 const TargetRegisterInfo &RI = *TM.getRegisterInfo();
175 unsigned stackReg = RI.getFrameRegister(*MF);
176 unsigned returnReg = RI.getRARegister();
177 unsigned stackSize = MF->getFrameInfo()->getStackSize();
180 OutStreamer.EmitRawText("\t.frame\t" + Twine(getRegisterName(stackReg)) +
181 "," + Twine(stackSize) + "," +
182 Twine(getRegisterName(returnReg)));
185 void MBlazeAsmPrinter::EmitFunctionEntryLabel() {
186 OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
187 OutStreamer.EmitLabel(CurrentFnSym);
190 /// EmitFunctionBodyStart - Targets can override this to emit stuff before
191 /// the first basic block in the function.
192 void MBlazeAsmPrinter::EmitFunctionBodyStart() {
193 emitFrameDirective();
195 SmallString<128> Str;
196 raw_svector_ostream OS(Str);
197 printSavedRegsBitmask(OS);
198 OutStreamer.EmitRawText(OS.str());
201 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
202 /// the last basic block in the function.
203 void MBlazeAsmPrinter::EmitFunctionBodyEnd() {
204 OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
207 // Print out an operand for an inline asm expression.
208 bool MBlazeAsmPrinter::
209 PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
210 unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) {
211 // Does this asm operand have a single letter operand modifier?
212 if (ExtraCode && ExtraCode[0])
213 return true; // Unknown modifier.
215 printOperand(MI, OpNo, O);
219 void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
221 const MachineOperand &MO = MI->getOperand(opNum);
223 switch (MO.getType()) {
224 case MachineOperand::MO_Register:
225 O << getRegisterName(MO.getReg());
228 case MachineOperand::MO_Immediate:
229 O << (int)MO.getImm();
232 case MachineOperand::MO_FPImmediate: {
233 const ConstantFP *fp = MO.getFPImm();
234 printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O);
235 O << ";\t# immediate = " << *fp;
239 case MachineOperand::MO_MachineBasicBlock:
240 O << *MO.getMBB()->getSymbol();
243 case MachineOperand::MO_GlobalAddress:
244 O << *Mang->getSymbol(MO.getGlobal());
247 case MachineOperand::MO_ExternalSymbol:
248 O << *GetExternalSymbolSymbol(MO.getSymbolName());
251 case MachineOperand::MO_JumpTableIndex:
252 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
253 << '_' << MO.getIndex();
256 case MachineOperand::MO_ConstantPoolIndex:
257 O << MAI->getPrivateGlobalPrefix() << "CPI"
258 << getFunctionNumber() << "_" << MO.getIndex();
260 O << "+" << MO.getOffset();
264 llvm_unreachable("<unknown operand type>");
268 void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum,
270 const MachineOperand &MO = MI->getOperand(opNum);
272 O << (unsigned int)MO.getImm();
274 printOperand(MI, opNum, O);
277 void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum,
279 const MachineOperand &MO = MI->getOperand(opNum);
281 O << "rfsl" << (unsigned int)MO.getImm();
283 printOperand(MI, opNum, O);
286 void MBlazeAsmPrinter::
287 printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
288 const char *Modifier) {
289 printOperand(MI, opNum+1, O);
291 printOperand(MI, opNum, O);
294 void MBlazeAsmPrinter::
295 printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
296 const char *Modifier) {
297 const MachineOperand& MO = MI->getOperand(opNum);
298 O << MBlaze::MBlazeFCCToString((MBlaze::CondCode)MO.getImm());
301 // Force static initialization.
302 extern "C" void LLVMInitializeMBlazeAsmPrinter() {
303 RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget);