MSP430AsmPrinter.cpp revision 249423
1204431Sraj//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
2204431Sraj//
3204431Sraj//                     The LLVM Compiler Infrastructure
4204431Sraj//
5204431Sraj// This file is distributed under the University of Illinois Open Source
6204431Sraj// License. See LICENSE.TXT for details.
7204431Sraj//
8204431Sraj//===----------------------------------------------------------------------===//
9204431Sraj//
10204431Sraj// This file contains a printer that converts from our internal representation
11204431Sraj// of machine-dependent LLVM code to the MSP430 assembly language.
12204431Sraj//
13204431Sraj//===----------------------------------------------------------------------===//
14204431Sraj
15204431Sraj#define DEBUG_TYPE "asm-printer"
16204431Sraj#include "MSP430.h"
17204431Sraj#include "InstPrinter/MSP430InstPrinter.h"
18204431Sraj#include "MSP430InstrInfo.h"
19204431Sraj#include "MSP430MCInstLower.h"
20204431Sraj#include "MSP430TargetMachine.h"
21204431Sraj#include "llvm/Assembly/Writer.h"
22204431Sraj#include "llvm/CodeGen/AsmPrinter.h"
23204431Sraj#include "llvm/CodeGen/MachineConstantPool.h"
24204431Sraj#include "llvm/CodeGen/MachineFunctionPass.h"
25204431Sraj#include "llvm/CodeGen/MachineInstr.h"
26204431Sraj#include "llvm/CodeGen/MachineModuleInfo.h"
27204431Sraj#include "llvm/IR/Constants.h"
28204431Sraj#include "llvm/IR/DerivedTypes.h"
29204431Sraj#include "llvm/IR/Module.h"
30204431Sraj#include "llvm/MC/MCAsmInfo.h"
31204431Sraj#include "llvm/MC/MCInst.h"
32204431Sraj#include "llvm/MC/MCStreamer.h"
33204431Sraj#include "llvm/MC/MCSymbol.h"
34204431Sraj#include "llvm/Support/TargetRegistry.h"
35204431Sraj#include "llvm/Support/raw_ostream.h"
36204431Sraj#include "llvm/Target/Mangler.h"
37204431Srajusing namespace llvm;
38204431Sraj
39204431Srajnamespace {
40204431Sraj  class MSP430AsmPrinter : public AsmPrinter {
41204431Sraj  public:
42204431Sraj    MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
43204431Sraj      : AsmPrinter(TM, Streamer) {}
44204431Sraj
45204431Sraj    virtual const char *getPassName() const {
46204431Sraj      return "MSP430 Assembly Printer";
47204431Sraj    }
48204431Sraj
49204431Sraj    void printOperand(const MachineInstr *MI, int OpNum,
50204431Sraj                      raw_ostream &O, const char* Modifier = 0);
51204431Sraj    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
52204431Sraj                            raw_ostream &O);
53204431Sraj    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
54204431Sraj                         unsigned AsmVariant, const char *ExtraCode,
55204431Sraj                         raw_ostream &O);
56204431Sraj    bool PrintAsmMemoryOperand(const MachineInstr *MI,
57204431Sraj                               unsigned OpNo, unsigned AsmVariant,
58204431Sraj                               const char *ExtraCode, raw_ostream &O);
59204431Sraj    void EmitInstruction(const MachineInstr *MI);
60204431Sraj  };
61204431Sraj} // end of anonymous namespace
62204431Sraj
63204431Sraj
64204431Srajvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
65204431Sraj                                    raw_ostream &O, const char *Modifier) {
66204431Sraj  const MachineOperand &MO = MI->getOperand(OpNum);
67204431Sraj  switch (MO.getType()) {
68204431Sraj  default: llvm_unreachable("Not implemented yet!");
69204431Sraj  case MachineOperand::MO_Register:
70204431Sraj    O << MSP430InstPrinter::getRegisterName(MO.getReg());
71204431Sraj    return;
72204431Sraj  case MachineOperand::MO_Immediate:
73204431Sraj    if (!Modifier || strcmp(Modifier, "nohash"))
74204431Sraj      O << '#';
75204431Sraj    O << MO.getImm();
76204431Sraj    return;
77204431Sraj  case MachineOperand::MO_MachineBasicBlock:
78204431Sraj    O << *MO.getMBB()->getSymbol();
79204431Sraj    return;
80204431Sraj  case MachineOperand::MO_GlobalAddress: {
81204431Sraj    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
82204431Sraj    uint64_t Offset = MO.getOffset();
83204433Sraj
84204433Sraj    // If the global address expression is a part of displacement field with a
85204433Sraj    // register base, we should not emit any prefix symbol here, e.g.
86204433Sraj    //   mov.w &foo, r1
87204433Sraj    // vs
88204433Sraj    //   mov.w glb(r1), r2
89204433Sraj    // Otherwise (!) msp430-as will silently miscompile the output :(
90204433Sraj    if (!Modifier || strcmp(Modifier, "nohash"))
91204431Sraj      O << (isMemOp ? '&' : '#');
92204431Sraj    if (Offset)
93204431Sraj      O << '(' << Offset << '+';
94204431Sraj
95204431Sraj    O << *Mang->getSymbol(MO.getGlobal());
96204431Sraj
97204431Sraj    if (Offset)
98204431Sraj      O << ')';
99204431Sraj
100204431Sraj    return;
101204431Sraj  }
102204431Sraj  case MachineOperand::MO_ExternalSymbol: {
103204431Sraj    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
104204431Sraj    O << (isMemOp ? '&' : '#');
105204431Sraj    O << MAI->getGlobalPrefix() << MO.getSymbolName();
106204431Sraj    return;
107204431Sraj  }
108238742Simp  }
109238742Simp}
110238742Simp
111238742Simpvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
112238742Simp                                          raw_ostream &O) {
113238742Simp  const MachineOperand &Base = MI->getOperand(OpNum);
114238742Simp  const MachineOperand &Disp = MI->getOperand(OpNum+1);
115238742Simp
116238742Simp  // Print displacement first
117238742Simp
118238742Simp  // Imm here is in fact global address - print extra modifier.
119238742Simp  if (Disp.isImm() && !Base.getReg())
120238742Simp    O << '&';
121238742Simp  printOperand(MI, OpNum+1, O, "nohash");
122238742Simp
123238742Simp  // Print register base field
124238742Simp  if (Base.getReg()) {
125238742Simp    O << '(';
126238742Simp    printOperand(MI, OpNum, O);
127238742Simp    O << ')';
128238742Simp  }
129238742Simp}
130238742Simp
131238742Simp/// PrintAsmOperand - Print out an operand for an inline asm expression.
132204431Sraj///
133204431Srajbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
134204431Sraj                                       unsigned AsmVariant,
135204431Sraj                                       const char *ExtraCode, raw_ostream &O) {
136204431Sraj  // Does this asm operand have a single letter operand modifier?
137204431Sraj  if (ExtraCode && ExtraCode[0])
138204431Sraj    return true; // Unknown modifier.
139204431Sraj
140204433Sraj  printOperand(MI, OpNo, O);
141204433Sraj  return false;
142204433Sraj}
143204433Sraj
144204431Srajbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
145204431Sraj                                             unsigned OpNo, unsigned AsmVariant,
146204433Sraj                                             const char *ExtraCode,
147204433Sraj                                             raw_ostream &O) {
148204431Sraj  if (ExtraCode && ExtraCode[0]) {
149204431Sraj    return true; // Unknown modifier.
150204431Sraj  }
151204431Sraj  printSrcMemOperand(MI, OpNo, O);
152204431Sraj  return false;
153204431Sraj}
154204431Sraj
155204431Sraj//===----------------------------------------------------------------------===//
156204431Srajvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
157204431Sraj  MSP430MCInstLower MCInstLowering(OutContext, *this);
158204431Sraj
159204431Sraj  MCInst TmpInst;
160204431Sraj  MCInstLowering.Lower(MI, TmpInst);
161204431Sraj  OutStreamer.EmitInstruction(TmpInst);
162204431Sraj}
163204431Sraj
164204431Sraj// Force static initialization.
165204433Srajextern "C" void LLVMInitializeMSP430AsmPrinter() {
166204433Sraj  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
167204433Sraj}
168204431Sraj