10e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 20e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// 30e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// The LLVM Compiler Infrastructure 40e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// 50e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// This file is distributed under the University of Illinois Open Source 60e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// License. See LICENSE.TXT for details. 70e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// 80e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===// 90e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// 100e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// This file contains a printer that converts from our internal representation 110e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// of machine-dependent LLVM code to the MSP430 assembly language. 120e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// 130e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===// 140e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 150e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#define DEBUG_TYPE "asm-printer" 160e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430.h" 170e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430InstrInfo.h" 180e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430MCInstLower.h" 190e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430TargetMachine.h" 2033caa07cc57a6311292f7e89c008c5479bde50caJim Grosbach#include "InstPrinter/MSP430InstPrinter.h" 210e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Constants.h" 220e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/DerivedTypes.h" 230e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Module.h" 240e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Assembly/Writer.h" 250e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/AsmPrinter.h" 260e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineModuleInfo.h" 270e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineFunctionPass.h" 280e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineConstantPool.h" 290e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineInstr.h" 301abf2cb59b8d63415780a03329307c0997b2670cEvan Cheng#include "llvm/MC/MCAsmInfo.h" 310e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCInst.h" 320e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCStreamer.h" 330e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCSymbol.h" 340e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Target/Mangler.h" 353e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h" 360e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Support/raw_ostream.h" 370e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyusing namespace llvm; 380e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 390e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckynamespace { 400e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky class MSP430AsmPrinter : public AsmPrinter { 410e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky public: 420e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 430e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky : AsmPrinter(TM, Streamer) {} 440e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 450e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky virtual const char *getPassName() const { 460e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return "MSP430 Assembly Printer"; 470e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 480e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 490e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky void printOperand(const MachineInstr *MI, int OpNum, 500e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O, const char* Modifier = 0); 510e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky void printSrcMemOperand(const MachineInstr *MI, int OpNum, 520e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O); 530e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 540e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky unsigned AsmVariant, const char *ExtraCode, 550e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O); 560e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky bool PrintAsmMemoryOperand(const MachineInstr *MI, 570e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky unsigned OpNo, unsigned AsmVariant, 580e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const char *ExtraCode, raw_ostream &O); 590e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky void EmitInstruction(const MachineInstr *MI); 600e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky }; 610e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} // end of anonymous namespace 620e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 630e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 640e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 650e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O, const char *Modifier) { 660e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const MachineOperand &MO = MI->getOperand(OpNum); 670e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky switch (MO.getType()) { 68bc2198133a1836598b54b943420748e75d5dea94Craig Topper default: llvm_unreachable("Not implemented yet!"); 690e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky case MachineOperand::MO_Register: 700e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << MSP430InstPrinter::getRegisterName(MO.getReg()); 710e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return; 720e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky case MachineOperand::MO_Immediate: 730e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (!Modifier || strcmp(Modifier, "nohash")) 740e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << '#'; 750e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << MO.getImm(); 760e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return; 770e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky case MachineOperand::MO_MachineBasicBlock: 780e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << *MO.getMBB()->getSymbol(); 790e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return; 800e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky case MachineOperand::MO_GlobalAddress: { 810e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 820e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky uint64_t Offset = MO.getOffset(); 830e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 840e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // If the global address expression is a part of displacement field with a 850e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // register base, we should not emit any prefix symbol here, e.g. 860e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // mov.w &foo, r1 870e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // vs 880e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // mov.w glb(r1), r2 890e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // Otherwise (!) msp430-as will silently miscompile the output :( 900e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (!Modifier || strcmp(Modifier, "nohash")) 910e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << (isMemOp ? '&' : '#'); 920e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (Offset) 930e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << '(' << Offset << '+'; 940e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 950e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << *Mang->getSymbol(MO.getGlobal()); 960e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 970e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (Offset) 980e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << ')'; 990e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1000e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return; 1010e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 1020e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky case MachineOperand::MO_ExternalSymbol: { 1030e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 1040e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << (isMemOp ? '&' : '#'); 1050e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << MAI->getGlobalPrefix() << MO.getSymbolName(); 1060e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return; 1070e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 1080e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 1090e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 1100e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1110e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 1120e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O) { 1130e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const MachineOperand &Base = MI->getOperand(OpNum); 1140e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const MachineOperand &Disp = MI->getOperand(OpNum+1); 1150e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1160e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // Print displacement first 1170e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1180e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // Imm here is in fact global address - print extra modifier. 1190e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (Disp.isImm() && !Base.getReg()) 1200e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << '&'; 1210e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky printOperand(MI, OpNum+1, O, "nohash"); 1220e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1230e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // Print register base field 1240e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (Base.getReg()) { 1250e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << '('; 1260e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky printOperand(MI, OpNum, O); 1270e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky O << ')'; 1280e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 1290e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 1300e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1310e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky/// PrintAsmOperand - Print out an operand for an inline asm expression. 1320e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky/// 1330e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckybool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 1340e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky unsigned AsmVariant, 1350e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const char *ExtraCode, raw_ostream &O) { 1360e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky // Does this asm operand have a single letter operand modifier? 1370e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (ExtraCode && ExtraCode[0]) 1380e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return true; // Unknown modifier. 1390e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1400e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky printOperand(MI, OpNo, O); 1410e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return false; 1420e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 1430e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1440e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckybool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 1450e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky unsigned OpNo, unsigned AsmVariant, 1460e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky const char *ExtraCode, 1470e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky raw_ostream &O) { 1480e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky if (ExtraCode && ExtraCode[0]) { 1490e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return true; // Unknown modifier. 1500e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky } 1510e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky printSrcMemOperand(MI, OpNo, O); 1520e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky return false; 1530e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 1540e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1550e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===// 1560e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 157a7542d5f870c5d98960d1676e23ac1d1d975d7e5Benjamin Kramer MSP430MCInstLower MCInstLowering(OutContext, *this); 1580e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1590e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky MCInst TmpInst; 1600e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky MCInstLowering.Lower(MI, TmpInst); 1610e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky OutStreamer.EmitInstruction(TmpInst); 1620e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 1630e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky 1640e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// Force static initialization. 1650e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyextern "C" void LLVMInitializeMSP430AsmPrinter() { 1660e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target); 1670e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} 168