1 //===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to the MSP430 assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "MSP430.h" 16 #include "InstPrinter/MSP430InstPrinter.h" 17 #include "MSP430InstrInfo.h" 18 #include "MSP430MCInstLower.h" 19 #include "MSP430TargetMachine.h" 20 #include "llvm/CodeGen/AsmPrinter.h" 21 #include "llvm/CodeGen/MachineConstantPool.h" 22 #include "llvm/CodeGen/MachineFunctionPass.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineModuleInfo.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/DerivedTypes.h" 27 #include "llvm/IR/Mangler.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/MC/MCAsmInfo.h" 30 #include "llvm/MC/MCInst.h" 31 #include "llvm/MC/MCStreamer.h" 32 #include "llvm/MC/MCSymbol.h" 33 #include "llvm/Support/TargetRegistry.h" 34 #include "llvm/Support/raw_ostream.h" 35 using namespace llvm; 36 37 #define DEBUG_TYPE "asm-printer" 38 39 namespace { 40 class MSP430AsmPrinter : public AsmPrinter { 41 public: 42 MSP430AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) 43 : AsmPrinter(TM, std::move(Streamer)) {} 44 45 StringRef getPassName() const override { return "MSP430 Assembly Printer"; } 46 47 void printOperand(const MachineInstr *MI, int OpNum, 48 raw_ostream &O, const char* Modifier = nullptr); 49 void printSrcMemOperand(const MachineInstr *MI, int OpNum, 50 raw_ostream &O); 51 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 52 unsigned AsmVariant, const char *ExtraCode, 53 raw_ostream &O) override; 54 bool PrintAsmMemoryOperand(const MachineInstr *MI, 55 unsigned OpNo, unsigned AsmVariant, 56 const char *ExtraCode, raw_ostream &O) override; 57 void EmitInstruction(const MachineInstr *MI) override; 58 }; 59 } // end of anonymous namespace 60 61 62 void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 63 raw_ostream &O, const char *Modifier) { 64 const MachineOperand &MO = MI->getOperand(OpNum); 65 switch (MO.getType()) { 66 default: llvm_unreachable("Not implemented yet!"); 67 case MachineOperand::MO_Register: 68 O << MSP430InstPrinter::getRegisterName(MO.getReg()); 69 return; 70 case MachineOperand::MO_Immediate: 71 if (!Modifier || strcmp(Modifier, "nohash")) 72 O << '#'; 73 O << MO.getImm(); 74 return; 75 case MachineOperand::MO_MachineBasicBlock: 76 MO.getMBB()->getSymbol()->print(O, MAI); 77 return; 78 case MachineOperand::MO_GlobalAddress: { 79 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 80 uint64_t Offset = MO.getOffset(); 81 82 // If the global address expression is a part of displacement field with a 83 // register base, we should not emit any prefix symbol here, e.g. 84 // mov.w &foo, r1 85 // vs 86 // mov.w glb(r1), r2 87 // Otherwise (!) msp430-as will silently miscompile the output :( 88 if (!Modifier || strcmp(Modifier, "nohash")) 89 O << (isMemOp ? '&' : '#'); 90 if (Offset) 91 O << '(' << Offset << '+'; 92 93 getSymbol(MO.getGlobal())->print(O, MAI); 94 95 if (Offset) 96 O << ')'; 97 98 return; 99 } 100 } 101 } 102 103 void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, 104 raw_ostream &O) { 105 const MachineOperand &Base = MI->getOperand(OpNum); 106 const MachineOperand &Disp = MI->getOperand(OpNum+1); 107 108 // Print displacement first 109 110 // Imm here is in fact global address - print extra modifier. 111 if (Disp.isImm() && !Base.getReg()) 112 O << '&'; 113 printOperand(MI, OpNum+1, O, "nohash"); 114 115 // Print register base field 116 if (Base.getReg()) { 117 O << '('; 118 printOperand(MI, OpNum, O); 119 O << ')'; 120 } 121 } 122 123 /// PrintAsmOperand - Print out an operand for an inline asm expression. 124 /// 125 bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 126 unsigned AsmVariant, 127 const char *ExtraCode, raw_ostream &O) { 128 // Does this asm operand have a single letter operand modifier? 129 if (ExtraCode && ExtraCode[0]) 130 return true; // Unknown modifier. 131 132 printOperand(MI, OpNo, O); 133 return false; 134 } 135 136 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 137 unsigned OpNo, unsigned AsmVariant, 138 const char *ExtraCode, 139 raw_ostream &O) { 140 if (ExtraCode && ExtraCode[0]) { 141 return true; // Unknown modifier. 142 } 143 printSrcMemOperand(MI, OpNo, O); 144 return false; 145 } 146 147 //===----------------------------------------------------------------------===// 148 void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { 149 MSP430MCInstLower MCInstLowering(OutContext, *this); 150 151 MCInst TmpInst; 152 MCInstLowering.Lower(MI, TmpInst); 153 EmitToStreamer(*OutStreamer, TmpInst); 154 } 155 156 // Force static initialization. 157 extern "C" void LLVMInitializeMSP430AsmPrinter() { 158 RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target()); 159 } 160