119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// The LLVM Compiler Infrastructure 419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source 619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details. 719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file contains a printer that converts from our internal representation 1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// of machine-dependent LLVM code to the MSP430 assembly language. 1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#define DEBUG_TYPE "asm-printer" 1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430.h" 1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430InstrInfo.h" 1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430MCInstLower.h" 1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430TargetMachine.h" 2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "InstPrinter/MSP430InstPrinter.h" 2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Constants.h" 2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/DerivedTypes.h" 2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Module.h" 2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Assembly/Writer.h" 2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/AsmPrinter.h" 2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineModuleInfo.h" 2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineFunctionPass.h" 2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineConstantPool.h" 2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineInstr.h" 3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCAsmInfo.h" 3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCInst.h" 3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCStreamer.h" 3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCSymbol.h" 3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Target/Mangler.h" 3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/TargetRegistry.h" 3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/raw_ostream.h" 3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanusing namespace llvm; 3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace { 4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class MSP430AsmPrinter : public AsmPrinter { 4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public: 4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman : AsmPrinter(TM, Streamer) {} 4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman virtual const char *getPassName() const { 4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return "MSP430 Assembly Printer"; 4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void printOperand(const MachineInstr *MI, int OpNum, 5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O, const char* Modifier = 0); 5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void printSrcMemOperand(const MachineInstr *MI, int OpNum, 5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O); 5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned AsmVariant, const char *ExtraCode, 5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O); 5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool PrintAsmMemoryOperand(const MachineInstr *MI, 5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned OpNo, unsigned AsmVariant, 5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *ExtraCode, raw_ostream &O); 5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void EmitInstruction(const MachineInstr *MI); 6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end of anonymous namespace 6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O, const char *Modifier) { 6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MachineOperand &MO = MI->getOperand(OpNum); 6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman switch (MO.getType()) { 6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman default: assert(0 && "Not implemented yet!"); 6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case MachineOperand::MO_Register: 7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << MSP430InstPrinter::getRegisterName(MO.getReg()); 7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return; 7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case MachineOperand::MO_Immediate: 7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Modifier || strcmp(Modifier, "nohash")) 7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << '#'; 7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << MO.getImm(); 7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return; 7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case MachineOperand::MO_MachineBasicBlock: 7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << *MO.getMBB()->getSymbol(); 7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return; 8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case MachineOperand::MO_GlobalAddress: { 8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint64_t Offset = MO.getOffset(); 8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // If the global address expression is a part of displacement field with a 8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // register base, we should not emit any prefix symbol here, e.g. 8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // mov.w &foo, r1 8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // vs 8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // mov.w glb(r1), r2 8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Otherwise (!) msp430-as will silently miscompile the output :( 9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Modifier || strcmp(Modifier, "nohash")) 9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << (isMemOp ? '&' : '#'); 9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Offset) 9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << '(' << Offset << '+'; 9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << *Mang->getSymbol(MO.getGlobal()); 9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Offset) 9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << ')'; 9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return; 10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case MachineOperand::MO_ExternalSymbol: { 10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << (isMemOp ? '&' : '#'); 10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << MAI->getGlobalPrefix() << MO.getSymbolName(); 10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return; 10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O) { 11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MachineOperand &Base = MI->getOperand(OpNum); 11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MachineOperand &Disp = MI->getOperand(OpNum+1); 11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Print displacement first 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Imm here is in fact global address - print extra modifier. 11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Disp.isImm() && !Base.getReg()) 12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << '&'; 12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman printOperand(MI, OpNum+1, O, "nohash"); 12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Print register base field 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Base.getReg()) { 12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << '('; 12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman printOperand(MI, OpNum, O); 12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman O << ')'; 12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// PrintAsmOperand - Print out an operand for an inline asm expression. 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// 13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned AsmVariant, 13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *ExtraCode, raw_ostream &O) { 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Does this asm operand have a single letter operand modifier? 13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (ExtraCode && ExtraCode[0]) 13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return true; // Unknown modifier. 13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman printOperand(MI, OpNo, O); 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return false; 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned OpNo, unsigned AsmVariant, 14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *ExtraCode, 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream &O) { 14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (ExtraCode && ExtraCode[0]) { 14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return true; // Unknown modifier. 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman printSrcMemOperand(MI, OpNo, O); 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return false; 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this); 15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCInst TmpInst; 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCInstLowering.Lower(MI, TmpInst); 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OutStreamer.EmitInstruction(TmpInst); 16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// Force static initialization. 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanextern "C" void LLVMInitializeMSP430AsmPrinter() { 16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 168