MSP430AsmPrinter.cpp revision 234353
1160416Smarcel//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 2160416Smarcel// 3160416Smarcel// The LLVM Compiler Infrastructure 4160416Smarcel// 5160416Smarcel// This file is distributed under the University of Illinois Open Source 6160416Smarcel// License. See LICENSE.TXT for details. 7160416Smarcel// 8160416Smarcel//===----------------------------------------------------------------------===// 9160416Smarcel// 10160416Smarcel// This file contains a printer that converts from our internal representation 11160416Smarcel// of machine-dependent LLVM code to the MSP430 assembly language. 12160416Smarcel// 13160416Smarcel//===----------------------------------------------------------------------===// 14160416Smarcel 15160416Smarcel#define DEBUG_TYPE "asm-printer" 16160416Smarcel#include "MSP430.h" 17160416Smarcel#include "MSP430InstrInfo.h" 18160416Smarcel#include "MSP430MCInstLower.h" 19160416Smarcel#include "MSP430TargetMachine.h" 20160416Smarcel#include "InstPrinter/MSP430InstPrinter.h" 21160416Smarcel#include "llvm/Constants.h" 22160416Smarcel#include "llvm/DerivedTypes.h" 23160416Smarcel#include "llvm/Module.h" 24160416Smarcel#include "llvm/Assembly/Writer.h" 25160416Smarcel#include "llvm/CodeGen/AsmPrinter.h" 26160416Smarcel#include "llvm/CodeGen/MachineModuleInfo.h" 27160416Smarcel#include "llvm/CodeGen/MachineFunctionPass.h" 28160416Smarcel#include "llvm/CodeGen/MachineConstantPool.h" 29160416Smarcel#include "llvm/CodeGen/MachineInstr.h" 30160416Smarcel#include "llvm/MC/MCAsmInfo.h" 31160416Smarcel#include "llvm/MC/MCInst.h" 32160416Smarcel#include "llvm/MC/MCStreamer.h" 33160416Smarcel#include "llvm/MC/MCSymbol.h" 34160416Smarcel#include "llvm/Target/Mangler.h" 35160416Smarcel#include "llvm/Support/TargetRegistry.h" 36160416Smarcel#include "llvm/Support/raw_ostream.h" 37160416Smarcelusing namespace llvm; 38160416Smarcel 39160416Smarcelnamespace { 40160416Smarcel class MSP430AsmPrinter : public AsmPrinter { 41160416Smarcel public: 42160416Smarcel MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 43160416Smarcel : AsmPrinter(TM, Streamer) {} 44160416Smarcel 45160416Smarcel virtual const char *getPassName() const { 46160416Smarcel return "MSP430 Assembly Printer"; 47160416Smarcel } 48160416Smarcel 49160416Smarcel void printOperand(const MachineInstr *MI, int OpNum, 50160416Smarcel raw_ostream &O, const char* Modifier = 0); 51160416Smarcel void printSrcMemOperand(const MachineInstr *MI, int OpNum, 52160416Smarcel raw_ostream &O); 53160416Smarcel bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 54160416Smarcel unsigned AsmVariant, const char *ExtraCode, 55160416Smarcel raw_ostream &O); 56160416Smarcel bool PrintAsmMemoryOperand(const MachineInstr *MI, 57160416Smarcel unsigned OpNo, unsigned AsmVariant, 58160416Smarcel const char *ExtraCode, raw_ostream &O); 59160416Smarcel void EmitInstruction(const MachineInstr *MI); 60160416Smarcel }; 61160416Smarcel} // end of anonymous namespace 62160416Smarcel 63160416Smarcel 64160416Smarcelvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 65160416Smarcel raw_ostream &O, const char *Modifier) { 66160416Smarcel const MachineOperand &MO = MI->getOperand(OpNum); 67160416Smarcel switch (MO.getType()) { 68160416Smarcel default: llvm_unreachable("Not implemented yet!"); 69160416Smarcel case MachineOperand::MO_Register: 70160416Smarcel O << MSP430InstPrinter::getRegisterName(MO.getReg()); 71160416Smarcel return; 72160416Smarcel case MachineOperand::MO_Immediate: 73160416Smarcel if (!Modifier || strcmp(Modifier, "nohash")) 74160416Smarcel O << '#'; 75160416Smarcel O << MO.getImm(); 76160416Smarcel return; 77160416Smarcel case MachineOperand::MO_MachineBasicBlock: 78160416Smarcel O << *MO.getMBB()->getSymbol(); 79160416Smarcel return; 80160416Smarcel case MachineOperand::MO_GlobalAddress: { 81160416Smarcel bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 82160416Smarcel uint64_t Offset = MO.getOffset(); 83160416Smarcel 84160416Smarcel // If the global address expression is a part of displacement field with a 85160416Smarcel // register base, we should not emit any prefix symbol here, e.g. 86160416Smarcel // mov.w &foo, r1 87160416Smarcel // vs 88160416Smarcel // mov.w glb(r1), r2 89160416Smarcel // Otherwise (!) msp430-as will silently miscompile the output :( 90160416Smarcel if (!Modifier || strcmp(Modifier, "nohash")) 91160416Smarcel O << (isMemOp ? '&' : '#'); 92160416Smarcel if (Offset) 93160416Smarcel O << '(' << Offset << '+'; 94160416Smarcel 95160416Smarcel O << *Mang->getSymbol(MO.getGlobal()); 96160416Smarcel 97160416Smarcel if (Offset) 98160416Smarcel O << ')'; 99160416Smarcel 100 return; 101 } 102 case MachineOperand::MO_ExternalSymbol: { 103 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 104 O << (isMemOp ? '&' : '#'); 105 O << MAI->getGlobalPrefix() << MO.getSymbolName(); 106 return; 107 } 108 } 109} 110 111void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 112 raw_ostream &O) { 113 const MachineOperand &Base = MI->getOperand(OpNum); 114 const MachineOperand &Disp = MI->getOperand(OpNum+1); 115 116 // Print displacement first 117 118 // Imm here is in fact global address - print extra modifier. 119 if (Disp.isImm() && !Base.getReg()) 120 O << '&'; 121 printOperand(MI, OpNum+1, O, "nohash"); 122 123 // Print register base field 124 if (Base.getReg()) { 125 O << '('; 126 printOperand(MI, OpNum, O); 127 O << ')'; 128 } 129} 130 131/// PrintAsmOperand - Print out an operand for an inline asm expression. 132/// 133bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 134 unsigned AsmVariant, 135 const char *ExtraCode, raw_ostream &O) { 136 // Does this asm operand have a single letter operand modifier? 137 if (ExtraCode && ExtraCode[0]) 138 return true; // Unknown modifier. 139 140 printOperand(MI, OpNo, O); 141 return false; 142} 143 144bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 145 unsigned OpNo, unsigned AsmVariant, 146 const char *ExtraCode, 147 raw_ostream &O) { 148 if (ExtraCode && ExtraCode[0]) { 149 return true; // Unknown modifier. 150 } 151 printSrcMemOperand(MI, OpNo, O); 152 return false; 153} 154 155//===----------------------------------------------------------------------===// 156void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 157 MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this); 158 159 MCInst TmpInst; 160 MCInstLowering.Lower(MI, TmpInst); 161 OutStreamer.EmitInstruction(TmpInst); 162} 163 164// Force static initialization. 165extern "C" void LLVMInitializeMSP430AsmPrinter() { 166 RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 167} 168