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" 17249423Sdim#include "InstPrinter/MSP430InstPrinter.h" 18218885Sdim#include "MSP430InstrInfo.h" 19218885Sdim#include "MSP430MCInstLower.h" 20218885Sdim#include "MSP430TargetMachine.h" 21218885Sdim#include "llvm/Assembly/Writer.h" 22218885Sdim#include "llvm/CodeGen/AsmPrinter.h" 23249423Sdim#include "llvm/CodeGen/MachineConstantPool.h" 24218885Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 25218885Sdim#include "llvm/CodeGen/MachineInstr.h" 26249423Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 27249423Sdim#include "llvm/IR/Constants.h" 28249423Sdim#include "llvm/IR/DerivedTypes.h" 29249423Sdim#include "llvm/IR/Module.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" 34226633Sdim#include "llvm/Support/TargetRegistry.h" 35218885Sdim#include "llvm/Support/raw_ostream.h" 36249423Sdim#include "llvm/Target/Mangler.h" 37218885Sdimusing namespace llvm; 38218885Sdim 39218885Sdimnamespace { 40218885Sdim class MSP430AsmPrinter : public AsmPrinter { 41218885Sdim public: 42218885Sdim MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 43218885Sdim : AsmPrinter(TM, Streamer) {} 44218885Sdim 45218885Sdim virtual const char *getPassName() const { 46218885Sdim return "MSP430 Assembly Printer"; 47218885Sdim } 48218885Sdim 49218885Sdim void printOperand(const MachineInstr *MI, int OpNum, 50218885Sdim raw_ostream &O, const char* Modifier = 0); 51218885Sdim void printSrcMemOperand(const MachineInstr *MI, int OpNum, 52218885Sdim raw_ostream &O); 53218885Sdim bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 54218885Sdim unsigned AsmVariant, const char *ExtraCode, 55218885Sdim raw_ostream &O); 56218885Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, 57218885Sdim unsigned OpNo, unsigned AsmVariant, 58218885Sdim const char *ExtraCode, raw_ostream &O); 59218885Sdim void EmitInstruction(const MachineInstr *MI); 60218885Sdim }; 61218885Sdim} // end of anonymous namespace 62218885Sdim 63218885Sdim 64218885Sdimvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 65218885Sdim raw_ostream &O, const char *Modifier) { 66218885Sdim const MachineOperand &MO = MI->getOperand(OpNum); 67218885Sdim switch (MO.getType()) { 68234353Sdim default: llvm_unreachable("Not implemented yet!"); 69218885Sdim case MachineOperand::MO_Register: 70218885Sdim O << MSP430InstPrinter::getRegisterName(MO.getReg()); 71218885Sdim return; 72218885Sdim case MachineOperand::MO_Immediate: 73218885Sdim if (!Modifier || strcmp(Modifier, "nohash")) 74218885Sdim O << '#'; 75218885Sdim O << MO.getImm(); 76218885Sdim return; 77218885Sdim case MachineOperand::MO_MachineBasicBlock: 78218885Sdim O << *MO.getMBB()->getSymbol(); 79218885Sdim return; 80218885Sdim case MachineOperand::MO_GlobalAddress: { 81218885Sdim bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 82218885Sdim uint64_t Offset = MO.getOffset(); 83218885Sdim 84218885Sdim // If the global address expression is a part of displacement field with a 85218885Sdim // register base, we should not emit any prefix symbol here, e.g. 86218885Sdim // mov.w &foo, r1 87218885Sdim // vs 88218885Sdim // mov.w glb(r1), r2 89218885Sdim // Otherwise (!) msp430-as will silently miscompile the output :( 90218885Sdim if (!Modifier || strcmp(Modifier, "nohash")) 91218885Sdim O << (isMemOp ? '&' : '#'); 92218885Sdim if (Offset) 93218885Sdim O << '(' << Offset << '+'; 94218885Sdim 95263508Sdim O << *getSymbol(MO.getGlobal()); 96218885Sdim 97218885Sdim if (Offset) 98218885Sdim O << ')'; 99218885Sdim 100218885Sdim return; 101218885Sdim } 102218885Sdim case MachineOperand::MO_ExternalSymbol: { 103218885Sdim bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 104218885Sdim O << (isMemOp ? '&' : '#'); 105218885Sdim O << MAI->getGlobalPrefix() << MO.getSymbolName(); 106218885Sdim return; 107218885Sdim } 108218885Sdim } 109218885Sdim} 110218885Sdim 111218885Sdimvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 112218885Sdim raw_ostream &O) { 113218885Sdim const MachineOperand &Base = MI->getOperand(OpNum); 114218885Sdim const MachineOperand &Disp = MI->getOperand(OpNum+1); 115218885Sdim 116218885Sdim // Print displacement first 117218885Sdim 118218885Sdim // Imm here is in fact global address - print extra modifier. 119218885Sdim if (Disp.isImm() && !Base.getReg()) 120218885Sdim O << '&'; 121218885Sdim printOperand(MI, OpNum+1, O, "nohash"); 122218885Sdim 123218885Sdim // Print register base field 124218885Sdim if (Base.getReg()) { 125218885Sdim O << '('; 126218885Sdim printOperand(MI, OpNum, O); 127218885Sdim O << ')'; 128218885Sdim } 129218885Sdim} 130218885Sdim 131218885Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression. 132218885Sdim/// 133218885Sdimbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 134218885Sdim unsigned AsmVariant, 135218885Sdim const char *ExtraCode, raw_ostream &O) { 136218885Sdim // Does this asm operand have a single letter operand modifier? 137218885Sdim if (ExtraCode && ExtraCode[0]) 138218885Sdim return true; // Unknown modifier. 139218885Sdim 140218885Sdim printOperand(MI, OpNo, O); 141218885Sdim return false; 142218885Sdim} 143218885Sdim 144218885Sdimbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 145218885Sdim unsigned OpNo, unsigned AsmVariant, 146218885Sdim const char *ExtraCode, 147218885Sdim raw_ostream &O) { 148218885Sdim if (ExtraCode && ExtraCode[0]) { 149218885Sdim return true; // Unknown modifier. 150218885Sdim } 151218885Sdim printSrcMemOperand(MI, OpNo, O); 152218885Sdim return false; 153218885Sdim} 154218885Sdim 155218885Sdim//===----------------------------------------------------------------------===// 156218885Sdimvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 157239462Sdim MSP430MCInstLower MCInstLowering(OutContext, *this); 158218885Sdim 159218885Sdim MCInst TmpInst; 160218885Sdim MCInstLowering.Lower(MI, TmpInst); 161218885Sdim OutStreamer.EmitInstruction(TmpInst); 162218885Sdim} 163218885Sdim 164218885Sdim// Force static initialization. 165218885Sdimextern "C" void LLVMInitializeMSP430AsmPrinter() { 166218885Sdim RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 167218885Sdim} 168