MSP430AsmPrinter.cpp revision 218885
1167514Skmacy//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 2167514Skmacy// 3167514Skmacy// The LLVM Compiler Infrastructure 4167514Skmacy// 5167514Skmacy// This file is distributed under the University of Illinois Open Source 6167514Skmacy// License. See LICENSE.TXT for details. 7167514Skmacy// 8167514Skmacy//===----------------------------------------------------------------------===// 9167514Skmacy// 10167514Skmacy// This file contains a printer that converts from our internal representation 11167514Skmacy// of machine-dependent LLVM code to the MSP430 assembly language. 12167514Skmacy// 13167514Skmacy//===----------------------------------------------------------------------===// 14167514Skmacy 15167514Skmacy#define DEBUG_TYPE "asm-printer" 16167514Skmacy#include "MSP430.h" 17167514Skmacy#include "MSP430InstrInfo.h" 18167514Skmacy#include "MSP430MCAsmInfo.h" 19167514Skmacy#include "MSP430MCInstLower.h" 20167514Skmacy#include "MSP430TargetMachine.h" 21167514Skmacy#include "InstPrinter/MSP430InstPrinter.h" 22167514Skmacy#include "llvm/Constants.h" 23167514Skmacy#include "llvm/DerivedTypes.h" 24167514Skmacy#include "llvm/Module.h" 25167514Skmacy#include "llvm/Assembly/Writer.h" 26167514Skmacy#include "llvm/CodeGen/AsmPrinter.h" 27167514Skmacy#include "llvm/CodeGen/MachineModuleInfo.h" 28167514Skmacy#include "llvm/CodeGen/MachineFunctionPass.h" 29167514Skmacy#include "llvm/CodeGen/MachineConstantPool.h" 30167514Skmacy#include "llvm/CodeGen/MachineInstr.h" 31167514Skmacy#include "llvm/MC/MCInst.h" 32167514Skmacy#include "llvm/MC/MCStreamer.h" 33167514Skmacy#include "llvm/MC/MCSymbol.h" 34167514Skmacy#include "llvm/Target/Mangler.h" 35167514Skmacy#include "llvm/Target/TargetData.h" 36167514Skmacy#include "llvm/Target/TargetLoweringObjectFile.h" 37167514Skmacy#include "llvm/Target/TargetRegistry.h" 38167514Skmacy#include "llvm/Support/raw_ostream.h" 39167514Skmacyusing namespace llvm; 40167514Skmacy 41167514Skmacynamespace { 42167514Skmacy class MSP430AsmPrinter : public AsmPrinter { 43167514Skmacy public: 44167514Skmacy MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 45167514Skmacy : AsmPrinter(TM, Streamer) {} 46167514Skmacy 47167514Skmacy virtual const char *getPassName() const { 48167514Skmacy return "MSP430 Assembly Printer"; 49167514Skmacy } 50167514Skmacy 51167514Skmacy void printOperand(const MachineInstr *MI, int OpNum, 52167514Skmacy raw_ostream &O, const char* Modifier = 0); 53167514Skmacy void printSrcMemOperand(const MachineInstr *MI, int OpNum, 54167514Skmacy raw_ostream &O); 55167514Skmacy bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 56167514Skmacy unsigned AsmVariant, const char *ExtraCode, 57167514Skmacy raw_ostream &O); 58167514Skmacy bool PrintAsmMemoryOperand(const MachineInstr *MI, 59167514Skmacy unsigned OpNo, unsigned AsmVariant, 60167514Skmacy const char *ExtraCode, raw_ostream &O); 61167514Skmacy void EmitInstruction(const MachineInstr *MI); 62167514Skmacy }; 63167514Skmacy} // end of anonymous namespace 64167514Skmacy 65167514Skmacy 66167514Skmacyvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 67167514Skmacy raw_ostream &O, const char *Modifier) { 68167514Skmacy const MachineOperand &MO = MI->getOperand(OpNum); 69167514Skmacy switch (MO.getType()) { 70167514Skmacy default: assert(0 && "Not implemented yet!"); 71167514Skmacy case MachineOperand::MO_Register: 72167514Skmacy O << MSP430InstPrinter::getRegisterName(MO.getReg()); 73167514Skmacy return; 74167514Skmacy case MachineOperand::MO_Immediate: 75167514Skmacy if (!Modifier || strcmp(Modifier, "nohash")) 76167514Skmacy O << '#'; 77167514Skmacy O << MO.getImm(); 78167514Skmacy return; 79167514Skmacy case MachineOperand::MO_MachineBasicBlock: 80167514Skmacy O << *MO.getMBB()->getSymbol(); 81167514Skmacy return; 82167514Skmacy case MachineOperand::MO_GlobalAddress: { 83167514Skmacy bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 84167514Skmacy uint64_t Offset = MO.getOffset(); 85167514Skmacy 86167514Skmacy // If the global address expression is a part of displacement field with a 87167514Skmacy // register base, we should not emit any prefix symbol here, e.g. 88167514Skmacy // mov.w &foo, r1 89167514Skmacy // vs 90167514Skmacy // mov.w glb(r1), r2 91167514Skmacy // Otherwise (!) msp430-as will silently miscompile the output :( 92167514Skmacy if (!Modifier || strcmp(Modifier, "nohash")) 93167514Skmacy O << (isMemOp ? '&' : '#'); 94167514Skmacy if (Offset) 95167514Skmacy O << '(' << Offset << '+'; 96167514Skmacy 97167514Skmacy O << *Mang->getSymbol(MO.getGlobal()); 98167514Skmacy 99167514Skmacy if (Offset) 100167514Skmacy O << ')'; 101167514Skmacy 102167514Skmacy return; 103167514Skmacy } 104167514Skmacy case MachineOperand::MO_ExternalSymbol: { 105167514Skmacy bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 106167514Skmacy O << (isMemOp ? '&' : '#'); 107167514Skmacy O << MAI->getGlobalPrefix() << MO.getSymbolName(); 108167514Skmacy return; 109167514Skmacy } 110167514Skmacy } 111167514Skmacy} 112167514Skmacy 113167514Skmacyvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 114167514Skmacy raw_ostream &O) { 115167514Skmacy const MachineOperand &Base = MI->getOperand(OpNum); 116167514Skmacy const MachineOperand &Disp = MI->getOperand(OpNum+1); 117167514Skmacy 118167514Skmacy // Print displacement first 119167514Skmacy 120167514Skmacy // Imm here is in fact global address - print extra modifier. 121167514Skmacy if (Disp.isImm() && !Base.getReg()) 122167514Skmacy O << '&'; 123167514Skmacy printOperand(MI, OpNum+1, O, "nohash"); 124167514Skmacy 125167514Skmacy // Print register base field 126167514Skmacy if (Base.getReg()) { 127167514Skmacy O << '('; 128167514Skmacy printOperand(MI, OpNum, O); 129167514Skmacy O << ')'; 130167514Skmacy } 131167514Skmacy} 132167514Skmacy 133167514Skmacy/// PrintAsmOperand - Print out an operand for an inline asm expression. 134167514Skmacy/// 135167514Skmacybool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 136167514Skmacy unsigned AsmVariant, 137167514Skmacy const char *ExtraCode, raw_ostream &O) { 138167514Skmacy // Does this asm operand have a single letter operand modifier? 139167514Skmacy if (ExtraCode && ExtraCode[0]) 140167514Skmacy return true; // Unknown modifier. 141167514Skmacy 142167514Skmacy printOperand(MI, OpNo, O); 143167514Skmacy return false; 144167514Skmacy} 145167514Skmacy 146167514Skmacybool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 147167514Skmacy unsigned OpNo, unsigned AsmVariant, 148167514Skmacy const char *ExtraCode, 149167514Skmacy raw_ostream &O) { 150167514Skmacy if (ExtraCode && ExtraCode[0]) { 151167514Skmacy return true; // Unknown modifier. 152167514Skmacy } 153167514Skmacy printSrcMemOperand(MI, OpNo, O); 154167514Skmacy return false; 155167514Skmacy} 156167514Skmacy 157167514Skmacy//===----------------------------------------------------------------------===// 158167514Skmacyvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 159167514Skmacy MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this); 160167514Skmacy 161167514Skmacy MCInst TmpInst; 162167514Skmacy MCInstLowering.Lower(MI, TmpInst); 163167514Skmacy OutStreamer.EmitInstruction(TmpInst); 164167514Skmacy} 165167514Skmacy 166167514Skmacystatic MCInstPrinter *createMSP430MCInstPrinter(const Target &T, 167167514Skmacy unsigned SyntaxVariant, 168167514Skmacy const MCAsmInfo &MAI) { 169167514Skmacy if (SyntaxVariant == 0) 170167514Skmacy return new MSP430InstPrinter(MAI); 171167514Skmacy return 0; 172167514Skmacy} 173167514Skmacy 174167514Skmacy// Force static initialization. 175167514Skmacyextern "C" void LLVMInitializeMSP430AsmPrinter() { 176167514Skmacy RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 177167514Skmacy TargetRegistry::RegisterMCInstPrinter(TheMSP430Target, 178167514Skmacy createMSP430MCInstPrinter); 179167514Skmacy} 180167514Skmacy