MBlazeAsmPrinter.cpp revision 6e749f31c6373b31b780ce29d2900f965f42a2f0
1//===-- MBlazeAsmPrinter.cpp - MBlaze LLVM assembly writer ----------------===// 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 GAS-format MBlaze assembly language. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "mblaze-asm-printer" 16 17#include "MBlaze.h" 18#include "MBlazeSubtarget.h" 19#include "MBlazeInstrInfo.h" 20#include "MBlazeTargetMachine.h" 21#include "MBlazeMachineFunction.h" 22#include "MBlazeMCInstLower.h" 23#include "InstPrinter/MBlazeInstPrinter.h" 24#include "llvm/Constants.h" 25#include "llvm/DerivedTypes.h" 26#include "llvm/Module.h" 27#include "llvm/CodeGen/AsmPrinter.h" 28#include "llvm/CodeGen/MachineFunctionPass.h" 29#include "llvm/CodeGen/MachineConstantPool.h" 30#include "llvm/CodeGen/MachineFrameInfo.h" 31#include "llvm/CodeGen/MachineInstr.h" 32#include "llvm/MC/MCInst.h" 33#include "llvm/MC/MCStreamer.h" 34#include "llvm/MC/MCAsmInfo.h" 35#include "llvm/MC/MCSymbol.h" 36#include "llvm/Target/Mangler.h" 37#include "llvm/Target/TargetData.h" 38#include "llvm/Target/TargetLoweringObjectFile.h" 39#include "llvm/Target/TargetMachine.h" 40#include "llvm/Target/TargetOptions.h" 41#include "llvm/Target/TargetRegistry.h" 42#include "llvm/ADT/SmallString.h" 43#include "llvm/ADT/StringExtras.h" 44#include "llvm/Support/ErrorHandling.h" 45#include "llvm/Support/raw_ostream.h" 46#include <cctype> 47 48using namespace llvm; 49 50namespace { 51 class MBlazeAsmPrinter : public AsmPrinter { 52 const MBlazeSubtarget *Subtarget; 53 public: 54 explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 55 : AsmPrinter(TM, Streamer) { 56 Subtarget = &TM.getSubtarget<MBlazeSubtarget>(); 57 } 58 59 virtual const char *getPassName() const { 60 return "MBlaze Assembly Printer"; 61 } 62 63 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 64 unsigned AsmVariant, const char *ExtraCode, 65 raw_ostream &O); 66 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); 67 void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); 68 void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O); 69 void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 70 const char *Modifier = 0); 71 72 void EmitInstruction(const MachineInstr *MI); 73 }; 74} // end of anonymous namespace 75 76// #include "MBlazeGenAsmWriter.inc" 77 78//===----------------------------------------------------------------------===// 79// 80// MBlaze Asm Directives 81// 82// -- Frame directive "frame Stackpointer, Stacksize, RARegister" 83// Describe the stack frame. 84// 85// -- Mask directives "mask bitmask, offset" 86// Tells the assembler which registers are saved and where. 87// bitmask - contain a little endian bitset indicating which registers are 88// saved on function prologue (e.g. with a 0x80000000 mask, the 89// assembler knows the register 31 (RA) is saved at prologue. 90// offset - the position before stack pointer subtraction indicating where 91// the first saved register on prologue is located. (e.g. with a 92// 93// Consider the following function prologue: 94// 95// .frame R19,48,R15 96// .mask 0xc0000000,-8 97// addiu R1, R1, -48 98// sw R15, 40(R1) 99// sw R19, 36(R1) 100// 101// With a 0xc0000000 mask, the assembler knows the register 15 (R15) and 102// 19 (R19) are saved at prologue. As the save order on prologue is from 103// left to right, R15 is saved first. A -8 offset means that after the 104// stack pointer subtration, the first register in the mask (R15) will be 105// saved at address 48-8=40. 106// 107//===----------------------------------------------------------------------===// 108 109//===----------------------------------------------------------------------===// 110void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { 111 MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this); 112 113 MCInst TmpInst; 114 MCInstLowering.Lower(MI, TmpInst); 115 OutStreamer.EmitInstruction(TmpInst); 116} 117 118// Print a 32 bit hex number with all numbers. 119static void printHex32(unsigned int Value, raw_ostream &O) { 120 O << "0x"; 121 for (int i = 7; i >= 0; i--) 122 O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); 123} 124 125 126// Print out an operand for an inline asm expression. 127bool MBlazeAsmPrinter:: 128PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 129 unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { 130 // Does this asm operand have a single letter operand modifier? 131 if (ExtraCode && ExtraCode[0]) 132 return true; // Unknown modifier. 133 134 printOperand(MI, OpNo, O); 135 return false; 136} 137 138void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 139 raw_ostream &O) { 140 const MachineOperand &MO = MI->getOperand(opNum); 141 142 switch (MO.getType()) { 143 case MachineOperand::MO_Register: 144 O << MBlazeInstPrinter::getRegisterName(MO.getReg()); 145 break; 146 147 case MachineOperand::MO_Immediate: 148 O << (int32_t)MO.getImm(); 149 break; 150 151 case MachineOperand::MO_FPImmediate: { 152 const ConstantFP *fp = MO.getFPImm(); 153 printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O); 154 O << ";\t# immediate = " << *fp; 155 break; 156 } 157 158 case MachineOperand::MO_MachineBasicBlock: 159 O << *MO.getMBB()->getSymbol(); 160 return; 161 162 case MachineOperand::MO_GlobalAddress: 163 O << *Mang->getSymbol(MO.getGlobal()); 164 break; 165 166 case MachineOperand::MO_ExternalSymbol: 167 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 168 break; 169 170 case MachineOperand::MO_JumpTableIndex: 171 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 172 << '_' << MO.getIndex(); 173 break; 174 175 case MachineOperand::MO_ConstantPoolIndex: 176 O << MAI->getPrivateGlobalPrefix() << "CPI" 177 << getFunctionNumber() << "_" << MO.getIndex(); 178 if (MO.getOffset()) 179 O << "+" << MO.getOffset(); 180 break; 181 182 default: 183 llvm_unreachable("<unknown operand type>"); 184 } 185} 186 187void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, 188 raw_ostream &O) { 189 const MachineOperand &MO = MI->getOperand(opNum); 190 if (MO.isImm()) 191 O << (uint32_t)MO.getImm(); 192 else 193 printOperand(MI, opNum, O); 194} 195 196void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum, 197 raw_ostream &O) { 198 const MachineOperand &MO = MI->getOperand(opNum); 199 if (MO.isImm()) 200 O << "rfsl" << (unsigned int)MO.getImm(); 201 else 202 printOperand(MI, opNum, O); 203} 204 205void MBlazeAsmPrinter:: 206printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 207 const char *Modifier) { 208 printOperand(MI, opNum, O); 209 O << ", "; 210 printOperand(MI, opNum+1, O); 211} 212 213static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, 214 unsigned SyntaxVariant, 215 const MCAsmInfo &MAI) { 216 if (SyntaxVariant == 0) 217 return new MBlazeInstPrinter(MAI); 218 return 0; 219} 220 221// Force static initialization. 222extern "C" void LLVMInitializeMBlazeAsmPrinter() { 223 RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget); 224 TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget, 225 createMBlazeMCInstPrinter); 226 227} 228