MSP430AsmPrinter.cpp revision 224145
1218885Sdim//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file contains a printer that converts from our internal representation 11218885Sdim// of machine-dependent LLVM code to the MSP430 assembly language. 12218885Sdim// 13218885Sdim//===----------------------------------------------------------------------===// 14218885Sdim 15218885Sdim#define DEBUG_TYPE "asm-printer" 16218885Sdim#include "MSP430.h" 17218885Sdim#include "MSP430InstrInfo.h" 18218885Sdim#include "MSP430MCInstLower.h" 19218885Sdim#include "MSP430TargetMachine.h" 20218885Sdim#include "InstPrinter/MSP430InstPrinter.h" 21218885Sdim#include "llvm/Constants.h" 22218885Sdim#include "llvm/DerivedTypes.h" 23218885Sdim#include "llvm/Module.h" 24218885Sdim#include "llvm/Assembly/Writer.h" 25218885Sdim#include "llvm/CodeGen/AsmPrinter.h" 26218885Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 27218885Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 28218885Sdim#include "llvm/CodeGen/MachineConstantPool.h" 29218885Sdim#include "llvm/CodeGen/MachineInstr.h" 30224145Sdim#include "llvm/MC/MCAsmInfo.h" 31218885Sdim#include "llvm/MC/MCInst.h" 32218885Sdim#include "llvm/MC/MCStreamer.h" 33218885Sdim#include "llvm/MC/MCSymbol.h" 34218885Sdim#include "llvm/Target/Mangler.h" 35218885Sdim#include "llvm/Target/TargetData.h" 36218885Sdim#include "llvm/Target/TargetLoweringObjectFile.h" 37218885Sdim#include "llvm/Target/TargetRegistry.h" 38218885Sdim#include "llvm/Support/raw_ostream.h" 39218885Sdimusing namespace llvm; 40218885Sdim 41218885Sdimnamespace { 42218885Sdim class MSP430AsmPrinter : public AsmPrinter { 43218885Sdim public: 44218885Sdim MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 45218885Sdim : AsmPrinter(TM, Streamer) {} 46218885Sdim 47218885Sdim virtual const char *getPassName() const { 48218885Sdim return "MSP430 Assembly Printer"; 49218885Sdim } 50218885Sdim 51218885Sdim void printOperand(const MachineInstr *MI, int OpNum, 52218885Sdim raw_ostream &O, const char* Modifier = 0); 53218885Sdim void printSrcMemOperand(const MachineInstr *MI, int OpNum, 54218885Sdim raw_ostream &O); 55218885Sdim bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 56218885Sdim unsigned AsmVariant, const char *ExtraCode, 57218885Sdim raw_ostream &O); 58218885Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, 59218885Sdim unsigned OpNo, unsigned AsmVariant, 60218885Sdim const char *ExtraCode, raw_ostream &O); 61218885Sdim void EmitInstruction(const MachineInstr *MI); 62218885Sdim }; 63218885Sdim} // end of anonymous namespace 64218885Sdim 65218885Sdim 66218885Sdimvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 67218885Sdim raw_ostream &O, const char *Modifier) { 68218885Sdim const MachineOperand &MO = MI->getOperand(OpNum); 69218885Sdim switch (MO.getType()) { 70218885Sdim default: assert(0 && "Not implemented yet!"); 71218885Sdim case MachineOperand::MO_Register: 72218885Sdim O << MSP430InstPrinter::getRegisterName(MO.getReg()); 73218885Sdim return; 74218885Sdim case MachineOperand::MO_Immediate: 75218885Sdim if (!Modifier || strcmp(Modifier, "nohash")) 76218885Sdim O << '#'; 77218885Sdim O << MO.getImm(); 78218885Sdim return; 79218885Sdim case MachineOperand::MO_MachineBasicBlock: 80218885Sdim O << *MO.getMBB()->getSymbol(); 81218885Sdim return; 82218885Sdim case MachineOperand::MO_GlobalAddress: { 83218885Sdim bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 84218885Sdim uint64_t Offset = MO.getOffset(); 85218885Sdim 86218885Sdim // If the global address expression is a part of displacement field with a 87218885Sdim // register base, we should not emit any prefix symbol here, e.g. 88218885Sdim // mov.w &foo, r1 89218885Sdim // vs 90218885Sdim // mov.w glb(r1), r2 91218885Sdim // Otherwise (!) msp430-as will silently miscompile the output :( 92218885Sdim if (!Modifier || strcmp(Modifier, "nohash")) 93218885Sdim O << (isMemOp ? '&' : '#'); 94218885Sdim if (Offset) 95218885Sdim O << '(' << Offset << '+'; 96218885Sdim 97218885Sdim O << *Mang->getSymbol(MO.getGlobal()); 98218885Sdim 99218885Sdim if (Offset) 100218885Sdim O << ')'; 101218885Sdim 102218885Sdim return; 103218885Sdim } 104218885Sdim case MachineOperand::MO_ExternalSymbol: { 105218885Sdim bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 106218885Sdim O << (isMemOp ? '&' : '#'); 107218885Sdim O << MAI->getGlobalPrefix() << MO.getSymbolName(); 108218885Sdim return; 109218885Sdim } 110218885Sdim } 111218885Sdim} 112218885Sdim 113218885Sdimvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 114218885Sdim raw_ostream &O) { 115218885Sdim const MachineOperand &Base = MI->getOperand(OpNum); 116218885Sdim const MachineOperand &Disp = MI->getOperand(OpNum+1); 117218885Sdim 118218885Sdim // Print displacement first 119218885Sdim 120218885Sdim // Imm here is in fact global address - print extra modifier. 121218885Sdim if (Disp.isImm() && !Base.getReg()) 122218885Sdim O << '&'; 123218885Sdim printOperand(MI, OpNum+1, O, "nohash"); 124218885Sdim 125218885Sdim // Print register base field 126218885Sdim if (Base.getReg()) { 127218885Sdim O << '('; 128218885Sdim printOperand(MI, OpNum, O); 129218885Sdim O << ')'; 130218885Sdim } 131218885Sdim} 132218885Sdim 133218885Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression. 134218885Sdim/// 135218885Sdimbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 136218885Sdim unsigned AsmVariant, 137218885Sdim const char *ExtraCode, raw_ostream &O) { 138218885Sdim // Does this asm operand have a single letter operand modifier? 139218885Sdim if (ExtraCode && ExtraCode[0]) 140218885Sdim return true; // Unknown modifier. 141218885Sdim 142218885Sdim printOperand(MI, OpNo, O); 143218885Sdim return false; 144218885Sdim} 145218885Sdim 146218885Sdimbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 147218885Sdim unsigned OpNo, unsigned AsmVariant, 148218885Sdim const char *ExtraCode, 149218885Sdim raw_ostream &O) { 150218885Sdim if (ExtraCode && ExtraCode[0]) { 151218885Sdim return true; // Unknown modifier. 152218885Sdim } 153218885Sdim printSrcMemOperand(MI, OpNo, O); 154218885Sdim return false; 155218885Sdim} 156218885Sdim 157218885Sdim//===----------------------------------------------------------------------===// 158218885Sdimvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 159218885Sdim MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this); 160218885Sdim 161218885Sdim MCInst TmpInst; 162218885Sdim MCInstLowering.Lower(MI, TmpInst); 163218885Sdim OutStreamer.EmitInstruction(TmpInst); 164218885Sdim} 165218885Sdim 166218885Sdimstatic MCInstPrinter *createMSP430MCInstPrinter(const Target &T, 167218885Sdim unsigned SyntaxVariant, 168218885Sdim const MCAsmInfo &MAI) { 169218885Sdim if (SyntaxVariant == 0) 170224145Sdim return new MSP430InstPrinter(MAI); 171218885Sdim return 0; 172218885Sdim} 173218885Sdim 174218885Sdim// Force static initialization. 175218885Sdimextern "C" void LLVMInitializeMSP430AsmPrinter() { 176218885Sdim RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 177218885Sdim TargetRegistry::RegisterMCInstPrinter(TheMSP430Target, 178218885Sdim createMSP430MCInstPrinter); 179218885Sdim} 180