MSP430AsmPrinter.cpp revision 263508
1283514Sarybchik//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 2300607Sarybchik// 3283514Sarybchik// The LLVM Compiler Infrastructure 4283514Sarybchik// 5283514Sarybchik// This file is distributed under the University of Illinois Open Source 6283514Sarybchik// License. See LICENSE.TXT for details. 7283514Sarybchik// 8283514Sarybchik//===----------------------------------------------------------------------===// 9283514Sarybchik// 10283514Sarybchik// This file contains a printer that converts from our internal representation 11283514Sarybchik// of machine-dependent LLVM code to the MSP430 assembly language. 12283514Sarybchik// 13283514Sarybchik//===----------------------------------------------------------------------===// 14283514Sarybchik 15283514Sarybchik#define DEBUG_TYPE "asm-printer" 16283514Sarybchik#include "MSP430.h" 17283514Sarybchik#include "InstPrinter/MSP430InstPrinter.h" 18283514Sarybchik#include "MSP430InstrInfo.h" 19283514Sarybchik#include "MSP430MCInstLower.h" 20283514Sarybchik#include "MSP430TargetMachine.h" 21283514Sarybchik#include "llvm/Assembly/Writer.h" 22283514Sarybchik#include "llvm/CodeGen/AsmPrinter.h" 23283514Sarybchik#include "llvm/CodeGen/MachineConstantPool.h" 24283514Sarybchik#include "llvm/CodeGen/MachineFunctionPass.h" 25283514Sarybchik#include "llvm/CodeGen/MachineInstr.h" 26283514Sarybchik#include "llvm/CodeGen/MachineModuleInfo.h" 27283514Sarybchik#include "llvm/IR/Constants.h" 28283514Sarybchik#include "llvm/IR/DerivedTypes.h" 29283514Sarybchik#include "llvm/IR/Module.h" 30283514Sarybchik#include "llvm/MC/MCAsmInfo.h" 31283514Sarybchik#include "llvm/MC/MCInst.h" 32283514Sarybchik#include "llvm/MC/MCStreamer.h" 33283514Sarybchik#include "llvm/MC/MCSymbol.h" 34283514Sarybchik#include "llvm/Support/TargetRegistry.h" 35283514Sarybchik#include "llvm/Support/raw_ostream.h" 36283514Sarybchik#include "llvm/Target/Mangler.h" 37283514Sarybchikusing namespace llvm; 38283514Sarybchik 39283514Sarybchiknamespace { 40299606Sarybchik class MSP430AsmPrinter : public AsmPrinter { 41283514Sarybchik public: 42283514Sarybchik MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 43283514Sarybchik : AsmPrinter(TM, Streamer) {} 44291436Sarybchik 45293755Sarybchik virtual const char *getPassName() const { 46283514Sarybchik return "MSP430 Assembly Printer"; 47283514Sarybchik } 48283514Sarybchik 49283514Sarybchik void printOperand(const MachineInstr *MI, int OpNum, 50283514Sarybchik raw_ostream &O, const char* Modifier = 0); 51294078Sarybchik void printSrcMemOperand(const MachineInstr *MI, int OpNum, 52291436Sarybchik raw_ostream &O); 53283514Sarybchik bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 54283514Sarybchik unsigned AsmVariant, const char *ExtraCode, 55293755Sarybchik raw_ostream &O); 56293755Sarybchik bool PrintAsmMemoryOperand(const MachineInstr *MI, 57283514Sarybchik unsigned OpNo, unsigned AsmVariant, 58294078Sarybchik const char *ExtraCode, raw_ostream &O); 59294078Sarybchik void EmitInstruction(const MachineInstr *MI); 60294078Sarybchik }; 61294078Sarybchik} // end of anonymous namespace 62294078Sarybchik 63294078Sarybchik 64294078Sarybchikvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 65283514Sarybchik raw_ostream &O, const char *Modifier) { 66283514Sarybchik const MachineOperand &MO = MI->getOperand(OpNum); 67283514Sarybchik switch (MO.getType()) { 68283514Sarybchik default: llvm_unreachable("Not implemented yet!"); 69283514Sarybchik case MachineOperand::MO_Register: 70283514Sarybchik O << MSP430InstPrinter::getRegisterName(MO.getReg()); 71283514Sarybchik return; 72293756Sarybchik case MachineOperand::MO_Immediate: 73283514Sarybchik if (!Modifier || strcmp(Modifier, "nohash")) 74294078Sarybchik O << '#'; 75283514Sarybchik O << MO.getImm(); 76283514Sarybchik return; 77299345Sarybchik case MachineOperand::MO_MachineBasicBlock: 78283514Sarybchik O << *MO.getMBB()->getSymbol(); 79283514Sarybchik return; 80283514Sarybchik case MachineOperand::MO_GlobalAddress: { 81283514Sarybchik bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 82283514Sarybchik uint64_t Offset = MO.getOffset(); 83283514Sarybchik 84283514Sarybchik // If the global address expression is a part of displacement field with a 85283514Sarybchik // register base, we should not emit any prefix symbol here, e.g. 86283514Sarybchik // mov.w &foo, r1 87283514Sarybchik // vs 88293748Sarybchik // mov.w glb(r1), r2 89293748Sarybchik // Otherwise (!) msp430-as will silently miscompile the output :( 90283514Sarybchik if (!Modifier || strcmp(Modifier, "nohash")) 91283514Sarybchik O << (isMemOp ? '&' : '#'); 92283514Sarybchik if (Offset) 93283514Sarybchik O << '(' << Offset << '+'; 94283514Sarybchik 95283514Sarybchik O << *getSymbol(MO.getGlobal()); 96283514Sarybchik 97283514Sarybchik if (Offset) 98283514Sarybchik O << ')'; 99291436Sarybchik 100283514Sarybchik return; 101283514Sarybchik } 102283514Sarybchik case MachineOperand::MO_ExternalSymbol: { 103283514Sarybchik bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 104291436Sarybchik O << (isMemOp ? '&' : '#'); 105293755Sarybchik O << MAI->getGlobalPrefix() << MO.getSymbolName(); 106283514Sarybchik return; 107283514Sarybchik } 108283514Sarybchik } 109291436Sarybchik} 110283514Sarybchik 111293755Sarybchikvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 112293755Sarybchik raw_ostream &O) { 113283514Sarybchik const MachineOperand &Base = MI->getOperand(OpNum); 114283514Sarybchik const MachineOperand &Disp = MI->getOperand(OpNum+1); 115283514Sarybchik 116283514Sarybchik // Print displacement first 117283514Sarybchik 118283514Sarybchik // Imm here is in fact global address - print extra modifier. 119283514Sarybchik if (Disp.isImm() && !Base.getReg()) 120283514Sarybchik O << '&'; 121291746Sarybchik printOperand(MI, OpNum+1, O, "nohash"); 122283514Sarybchik 123283514Sarybchik // Print register base field 124283514Sarybchik if (Base.getReg()) { 125283514Sarybchik O << '('; 126283514Sarybchik printOperand(MI, OpNum, O); 127291436Sarybchik O << ')'; 128283514Sarybchik } 129283514Sarybchik} 130283514Sarybchik 131283514Sarybchik/// PrintAsmOperand - Print out an operand for an inline asm expression. 132291436Sarybchik/// 133293755Sarybchikbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 134283514Sarybchik unsigned AsmVariant, 135283514Sarybchik const char *ExtraCode, raw_ostream &O) { 136283514Sarybchik // Does this asm operand have a single letter operand modifier? 137283514Sarybchik if (ExtraCode && ExtraCode[0]) 138283514Sarybchik return true; // Unknown modifier. 139283514Sarybchik 140283514Sarybchik printOperand(MI, OpNo, O); 141294078Sarybchik return false; 142291436Sarybchik} 143283514Sarybchik 144293755Sarybchikbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 145293755Sarybchik unsigned OpNo, unsigned AsmVariant, 146283514Sarybchik const char *ExtraCode, 147294078Sarybchik raw_ostream &O) { 148294078Sarybchik if (ExtraCode && ExtraCode[0]) { 149294078Sarybchik return true; // Unknown modifier. 150294078Sarybchik } 151294078Sarybchik printSrcMemOperand(MI, OpNo, O); 152294078Sarybchik return false; 153283514Sarybchik} 154293756Sarybchik 155283514Sarybchik//===----------------------------------------------------------------------===// 156294078Sarybchikvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 157283514Sarybchik MSP430MCInstLower MCInstLowering(OutContext, *this); 158283514Sarybchik 159283514Sarybchik MCInst TmpInst; 160283514Sarybchik MCInstLowering.Lower(MI, TmpInst); 161283514Sarybchik OutStreamer.EmitInstruction(TmpInst); 162283514Sarybchik} 163283514Sarybchik 164283514Sarybchik// Force static initialization. 165283514Sarybchikextern "C" void LLVMInitializeMSP430AsmPrinter() { 166283514Sarybchik RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 167283514Sarybchik} 168283514Sarybchik