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