MSP430AsmPrinter.cpp revision 218885
1167514Skmacy//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
2167514Skmacy//
3167514Skmacy//                     The LLVM Compiler Infrastructure
4167514Skmacy//
5167514Skmacy// This file is distributed under the University of Illinois Open Source
6167514Skmacy// License. See LICENSE.TXT for details.
7167514Skmacy//
8167514Skmacy//===----------------------------------------------------------------------===//
9167514Skmacy//
10167514Skmacy// This file contains a printer that converts from our internal representation
11167514Skmacy// of machine-dependent LLVM code to the MSP430 assembly language.
12167514Skmacy//
13167514Skmacy//===----------------------------------------------------------------------===//
14167514Skmacy
15167514Skmacy#define DEBUG_TYPE "asm-printer"
16167514Skmacy#include "MSP430.h"
17167514Skmacy#include "MSP430InstrInfo.h"
18167514Skmacy#include "MSP430MCAsmInfo.h"
19167514Skmacy#include "MSP430MCInstLower.h"
20167514Skmacy#include "MSP430TargetMachine.h"
21167514Skmacy#include "InstPrinter/MSP430InstPrinter.h"
22167514Skmacy#include "llvm/Constants.h"
23167514Skmacy#include "llvm/DerivedTypes.h"
24167514Skmacy#include "llvm/Module.h"
25167514Skmacy#include "llvm/Assembly/Writer.h"
26167514Skmacy#include "llvm/CodeGen/AsmPrinter.h"
27167514Skmacy#include "llvm/CodeGen/MachineModuleInfo.h"
28167514Skmacy#include "llvm/CodeGen/MachineFunctionPass.h"
29167514Skmacy#include "llvm/CodeGen/MachineConstantPool.h"
30167514Skmacy#include "llvm/CodeGen/MachineInstr.h"
31167514Skmacy#include "llvm/MC/MCInst.h"
32167514Skmacy#include "llvm/MC/MCStreamer.h"
33167514Skmacy#include "llvm/MC/MCSymbol.h"
34167514Skmacy#include "llvm/Target/Mangler.h"
35167514Skmacy#include "llvm/Target/TargetData.h"
36167514Skmacy#include "llvm/Target/TargetLoweringObjectFile.h"
37167514Skmacy#include "llvm/Target/TargetRegistry.h"
38167514Skmacy#include "llvm/Support/raw_ostream.h"
39167514Skmacyusing namespace llvm;
40167514Skmacy
41167514Skmacynamespace {
42167514Skmacy  class MSP430AsmPrinter : public AsmPrinter {
43167514Skmacy  public:
44167514Skmacy    MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
45167514Skmacy      : AsmPrinter(TM, Streamer) {}
46167514Skmacy
47167514Skmacy    virtual const char *getPassName() const {
48167514Skmacy      return "MSP430 Assembly Printer";
49167514Skmacy    }
50167514Skmacy
51167514Skmacy    void printOperand(const MachineInstr *MI, int OpNum,
52167514Skmacy                      raw_ostream &O, const char* Modifier = 0);
53167514Skmacy    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
54167514Skmacy                            raw_ostream &O);
55167514Skmacy    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
56167514Skmacy                         unsigned AsmVariant, const char *ExtraCode,
57167514Skmacy                         raw_ostream &O);
58167514Skmacy    bool PrintAsmMemoryOperand(const MachineInstr *MI,
59167514Skmacy                               unsigned OpNo, unsigned AsmVariant,
60167514Skmacy                               const char *ExtraCode, raw_ostream &O);
61167514Skmacy    void EmitInstruction(const MachineInstr *MI);
62167514Skmacy  };
63167514Skmacy} // end of anonymous namespace
64167514Skmacy
65167514Skmacy
66167514Skmacyvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
67167514Skmacy                                    raw_ostream &O, const char *Modifier) {
68167514Skmacy  const MachineOperand &MO = MI->getOperand(OpNum);
69167514Skmacy  switch (MO.getType()) {
70167514Skmacy  default: assert(0 && "Not implemented yet!");
71167514Skmacy  case MachineOperand::MO_Register:
72167514Skmacy    O << MSP430InstPrinter::getRegisterName(MO.getReg());
73167514Skmacy    return;
74167514Skmacy  case MachineOperand::MO_Immediate:
75167514Skmacy    if (!Modifier || strcmp(Modifier, "nohash"))
76167514Skmacy      O << '#';
77167514Skmacy    O << MO.getImm();
78167514Skmacy    return;
79167514Skmacy  case MachineOperand::MO_MachineBasicBlock:
80167514Skmacy    O << *MO.getMBB()->getSymbol();
81167514Skmacy    return;
82167514Skmacy  case MachineOperand::MO_GlobalAddress: {
83167514Skmacy    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
84167514Skmacy    uint64_t Offset = MO.getOffset();
85167514Skmacy
86167514Skmacy    // If the global address expression is a part of displacement field with a
87167514Skmacy    // register base, we should not emit any prefix symbol here, e.g.
88167514Skmacy    //   mov.w &foo, r1
89167514Skmacy    // vs
90167514Skmacy    //   mov.w glb(r1), r2
91167514Skmacy    // Otherwise (!) msp430-as will silently miscompile the output :(
92167514Skmacy    if (!Modifier || strcmp(Modifier, "nohash"))
93167514Skmacy      O << (isMemOp ? '&' : '#');
94167514Skmacy    if (Offset)
95167514Skmacy      O << '(' << Offset << '+';
96167514Skmacy
97167514Skmacy    O << *Mang->getSymbol(MO.getGlobal());
98167514Skmacy
99167514Skmacy    if (Offset)
100167514Skmacy      O << ')';
101167514Skmacy
102167514Skmacy    return;
103167514Skmacy  }
104167514Skmacy  case MachineOperand::MO_ExternalSymbol: {
105167514Skmacy    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
106167514Skmacy    O << (isMemOp ? '&' : '#');
107167514Skmacy    O << MAI->getGlobalPrefix() << MO.getSymbolName();
108167514Skmacy    return;
109167514Skmacy  }
110167514Skmacy  }
111167514Skmacy}
112167514Skmacy
113167514Skmacyvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
114167514Skmacy                                          raw_ostream &O) {
115167514Skmacy  const MachineOperand &Base = MI->getOperand(OpNum);
116167514Skmacy  const MachineOperand &Disp = MI->getOperand(OpNum+1);
117167514Skmacy
118167514Skmacy  // Print displacement first
119167514Skmacy
120167514Skmacy  // Imm here is in fact global address - print extra modifier.
121167514Skmacy  if (Disp.isImm() && !Base.getReg())
122167514Skmacy    O << '&';
123167514Skmacy  printOperand(MI, OpNum+1, O, "nohash");
124167514Skmacy
125167514Skmacy  // Print register base field
126167514Skmacy  if (Base.getReg()) {
127167514Skmacy    O << '(';
128167514Skmacy    printOperand(MI, OpNum, O);
129167514Skmacy    O << ')';
130167514Skmacy  }
131167514Skmacy}
132167514Skmacy
133167514Skmacy/// PrintAsmOperand - Print out an operand for an inline asm expression.
134167514Skmacy///
135167514Skmacybool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
136167514Skmacy                                       unsigned AsmVariant,
137167514Skmacy                                       const char *ExtraCode, raw_ostream &O) {
138167514Skmacy  // Does this asm operand have a single letter operand modifier?
139167514Skmacy  if (ExtraCode && ExtraCode[0])
140167514Skmacy    return true; // Unknown modifier.
141167514Skmacy
142167514Skmacy  printOperand(MI, OpNo, O);
143167514Skmacy  return false;
144167514Skmacy}
145167514Skmacy
146167514Skmacybool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
147167514Skmacy                                             unsigned OpNo, unsigned AsmVariant,
148167514Skmacy                                             const char *ExtraCode,
149167514Skmacy                                             raw_ostream &O) {
150167514Skmacy  if (ExtraCode && ExtraCode[0]) {
151167514Skmacy    return true; // Unknown modifier.
152167514Skmacy  }
153167514Skmacy  printSrcMemOperand(MI, OpNo, O);
154167514Skmacy  return false;
155167514Skmacy}
156167514Skmacy
157167514Skmacy//===----------------------------------------------------------------------===//
158167514Skmacyvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
159167514Skmacy  MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);
160167514Skmacy
161167514Skmacy  MCInst TmpInst;
162167514Skmacy  MCInstLowering.Lower(MI, TmpInst);
163167514Skmacy  OutStreamer.EmitInstruction(TmpInst);
164167514Skmacy}
165167514Skmacy
166167514Skmacystatic MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
167167514Skmacy                                                unsigned SyntaxVariant,
168167514Skmacy                                                const MCAsmInfo &MAI) {
169167514Skmacy  if (SyntaxVariant == 0)
170167514Skmacy    return new MSP430InstPrinter(MAI);
171167514Skmacy  return 0;
172167514Skmacy}
173167514Skmacy
174167514Skmacy// Force static initialization.
175167514Skmacyextern "C" void LLVMInitializeMSP430AsmPrinter() {
176167514Skmacy  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
177167514Skmacy  TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
178167514Skmacy                                        createMSP430MCInstPrinter);
179167514Skmacy}
180167514Skmacy