MSP430AsmPrinter.cpp revision 263508
1283514Sarybchik//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
2300607Sarybchik//
3283514Sarybchik//                     The LLVM Compiler Infrastructure
4283514Sarybchik//
5283514Sarybchik// This file is distributed under the University of Illinois Open Source
6283514Sarybchik// License. See LICENSE.TXT for details.
7283514Sarybchik//
8283514Sarybchik//===----------------------------------------------------------------------===//
9283514Sarybchik//
10283514Sarybchik// This file contains a printer that converts from our internal representation
11283514Sarybchik// of machine-dependent LLVM code to the MSP430 assembly language.
12283514Sarybchik//
13283514Sarybchik//===----------------------------------------------------------------------===//
14283514Sarybchik
15283514Sarybchik#define DEBUG_TYPE "asm-printer"
16283514Sarybchik#include "MSP430.h"
17283514Sarybchik#include "InstPrinter/MSP430InstPrinter.h"
18283514Sarybchik#include "MSP430InstrInfo.h"
19283514Sarybchik#include "MSP430MCInstLower.h"
20283514Sarybchik#include "MSP430TargetMachine.h"
21283514Sarybchik#include "llvm/Assembly/Writer.h"
22283514Sarybchik#include "llvm/CodeGen/AsmPrinter.h"
23283514Sarybchik#include "llvm/CodeGen/MachineConstantPool.h"
24283514Sarybchik#include "llvm/CodeGen/MachineFunctionPass.h"
25283514Sarybchik#include "llvm/CodeGen/MachineInstr.h"
26283514Sarybchik#include "llvm/CodeGen/MachineModuleInfo.h"
27283514Sarybchik#include "llvm/IR/Constants.h"
28283514Sarybchik#include "llvm/IR/DerivedTypes.h"
29283514Sarybchik#include "llvm/IR/Module.h"
30283514Sarybchik#include "llvm/MC/MCAsmInfo.h"
31283514Sarybchik#include "llvm/MC/MCInst.h"
32283514Sarybchik#include "llvm/MC/MCStreamer.h"
33283514Sarybchik#include "llvm/MC/MCSymbol.h"
34283514Sarybchik#include "llvm/Support/TargetRegistry.h"
35283514Sarybchik#include "llvm/Support/raw_ostream.h"
36283514Sarybchik#include "llvm/Target/Mangler.h"
37283514Sarybchikusing namespace llvm;
38283514Sarybchik
39283514Sarybchiknamespace {
40299606Sarybchik  class MSP430AsmPrinter : public AsmPrinter {
41283514Sarybchik  public:
42283514Sarybchik    MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
43283514Sarybchik      : AsmPrinter(TM, Streamer) {}
44291436Sarybchik
45293755Sarybchik    virtual const char *getPassName() const {
46283514Sarybchik      return "MSP430 Assembly Printer";
47283514Sarybchik    }
48283514Sarybchik
49283514Sarybchik    void printOperand(const MachineInstr *MI, int OpNum,
50283514Sarybchik                      raw_ostream &O, const char* Modifier = 0);
51294078Sarybchik    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
52291436Sarybchik                            raw_ostream &O);
53283514Sarybchik    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
54283514Sarybchik                         unsigned AsmVariant, const char *ExtraCode,
55293755Sarybchik                         raw_ostream &O);
56293755Sarybchik    bool PrintAsmMemoryOperand(const MachineInstr *MI,
57283514Sarybchik                               unsigned OpNo, unsigned AsmVariant,
58294078Sarybchik                               const char *ExtraCode, raw_ostream &O);
59294078Sarybchik    void EmitInstruction(const MachineInstr *MI);
60294078Sarybchik  };
61294078Sarybchik} // end of anonymous namespace
62294078Sarybchik
63294078Sarybchik
64294078Sarybchikvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
65283514Sarybchik                                    raw_ostream &O, const char *Modifier) {
66283514Sarybchik  const MachineOperand &MO = MI->getOperand(OpNum);
67283514Sarybchik  switch (MO.getType()) {
68283514Sarybchik  default: llvm_unreachable("Not implemented yet!");
69283514Sarybchik  case MachineOperand::MO_Register:
70283514Sarybchik    O << MSP430InstPrinter::getRegisterName(MO.getReg());
71283514Sarybchik    return;
72293756Sarybchik  case MachineOperand::MO_Immediate:
73283514Sarybchik    if (!Modifier || strcmp(Modifier, "nohash"))
74294078Sarybchik      O << '#';
75283514Sarybchik    O << MO.getImm();
76283514Sarybchik    return;
77299345Sarybchik  case MachineOperand::MO_MachineBasicBlock:
78283514Sarybchik    O << *MO.getMBB()->getSymbol();
79283514Sarybchik    return;
80283514Sarybchik  case MachineOperand::MO_GlobalAddress: {
81283514Sarybchik    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
82283514Sarybchik    uint64_t Offset = MO.getOffset();
83283514Sarybchik
84283514Sarybchik    // If the global address expression is a part of displacement field with a
85283514Sarybchik    // register base, we should not emit any prefix symbol here, e.g.
86283514Sarybchik    //   mov.w &foo, r1
87283514Sarybchik    // vs
88293748Sarybchik    //   mov.w glb(r1), r2
89293748Sarybchik    // Otherwise (!) msp430-as will silently miscompile the output :(
90283514Sarybchik    if (!Modifier || strcmp(Modifier, "nohash"))
91283514Sarybchik      O << (isMemOp ? '&' : '#');
92283514Sarybchik    if (Offset)
93283514Sarybchik      O << '(' << Offset << '+';
94283514Sarybchik
95283514Sarybchik    O << *getSymbol(MO.getGlobal());
96283514Sarybchik
97283514Sarybchik    if (Offset)
98283514Sarybchik      O << ')';
99291436Sarybchik
100283514Sarybchik    return;
101283514Sarybchik  }
102283514Sarybchik  case MachineOperand::MO_ExternalSymbol: {
103283514Sarybchik    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
104291436Sarybchik    O << (isMemOp ? '&' : '#');
105293755Sarybchik    O << MAI->getGlobalPrefix() << MO.getSymbolName();
106283514Sarybchik    return;
107283514Sarybchik  }
108283514Sarybchik  }
109291436Sarybchik}
110283514Sarybchik
111293755Sarybchikvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
112293755Sarybchik                                          raw_ostream &O) {
113283514Sarybchik  const MachineOperand &Base = MI->getOperand(OpNum);
114283514Sarybchik  const MachineOperand &Disp = MI->getOperand(OpNum+1);
115283514Sarybchik
116283514Sarybchik  // Print displacement first
117283514Sarybchik
118283514Sarybchik  // Imm here is in fact global address - print extra modifier.
119283514Sarybchik  if (Disp.isImm() && !Base.getReg())
120283514Sarybchik    O << '&';
121291746Sarybchik  printOperand(MI, OpNum+1, O, "nohash");
122283514Sarybchik
123283514Sarybchik  // Print register base field
124283514Sarybchik  if (Base.getReg()) {
125283514Sarybchik    O << '(';
126283514Sarybchik    printOperand(MI, OpNum, O);
127291436Sarybchik    O << ')';
128283514Sarybchik  }
129283514Sarybchik}
130283514Sarybchik
131283514Sarybchik/// PrintAsmOperand - Print out an operand for an inline asm expression.
132291436Sarybchik///
133293755Sarybchikbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
134283514Sarybchik                                       unsigned AsmVariant,
135283514Sarybchik                                       const char *ExtraCode, raw_ostream &O) {
136283514Sarybchik  // Does this asm operand have a single letter operand modifier?
137283514Sarybchik  if (ExtraCode && ExtraCode[0])
138283514Sarybchik    return true; // Unknown modifier.
139283514Sarybchik
140283514Sarybchik  printOperand(MI, OpNo, O);
141294078Sarybchik  return false;
142291436Sarybchik}
143283514Sarybchik
144293755Sarybchikbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
145293755Sarybchik                                             unsigned OpNo, unsigned AsmVariant,
146283514Sarybchik                                             const char *ExtraCode,
147294078Sarybchik                                             raw_ostream &O) {
148294078Sarybchik  if (ExtraCode && ExtraCode[0]) {
149294078Sarybchik    return true; // Unknown modifier.
150294078Sarybchik  }
151294078Sarybchik  printSrcMemOperand(MI, OpNo, O);
152294078Sarybchik  return false;
153283514Sarybchik}
154293756Sarybchik
155283514Sarybchik//===----------------------------------------------------------------------===//
156294078Sarybchikvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
157283514Sarybchik  MSP430MCInstLower MCInstLowering(OutContext, *this);
158283514Sarybchik
159283514Sarybchik  MCInst TmpInst;
160283514Sarybchik  MCInstLowering.Lower(MI, TmpInst);
161283514Sarybchik  OutStreamer.EmitInstruction(TmpInst);
162283514Sarybchik}
163283514Sarybchik
164283514Sarybchik// Force static initialization.
165283514Sarybchikextern "C" void LLVMInitializeMSP430AsmPrinter() {
166283514Sarybchik  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
167283514Sarybchik}
168283514Sarybchik