10e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
20e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//
30e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//                     The LLVM Compiler Infrastructure
40e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//
50e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// This file is distributed under the University of Illinois Open Source
60e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// License. See LICENSE.TXT for details.
70e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//
80e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===//
90e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//
100e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// This file contains a printer that converts from our internal representation
110e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// of machine-dependent LLVM code to the MSP430 assembly language.
120e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//
130e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===//
140e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
150e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#define DEBUG_TYPE "asm-printer"
160e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430.h"
170e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430InstrInfo.h"
180e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430MCInstLower.h"
190e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "MSP430TargetMachine.h"
2033caa07cc57a6311292f7e89c008c5479bde50caJim Grosbach#include "InstPrinter/MSP430InstPrinter.h"
210e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Constants.h"
220e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/DerivedTypes.h"
230e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Module.h"
240e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Assembly/Writer.h"
250e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/AsmPrinter.h"
260e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineModuleInfo.h"
270e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineFunctionPass.h"
280e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineConstantPool.h"
290e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/CodeGen/MachineInstr.h"
301abf2cb59b8d63415780a03329307c0997b2670cEvan Cheng#include "llvm/MC/MCAsmInfo.h"
310e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCInst.h"
320e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCStreamer.h"
330e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/MC/MCSymbol.h"
340e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Target/Mangler.h"
353e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
360e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky#include "llvm/Support/raw_ostream.h"
370e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyusing namespace llvm;
380e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
390e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckynamespace {
400e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  class MSP430AsmPrinter : public AsmPrinter {
410e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  public:
420e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
430e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      : AsmPrinter(TM, Streamer) {}
440e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
450e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    virtual const char *getPassName() const {
460e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      return "MSP430 Assembly Printer";
470e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    }
480e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
490e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    void printOperand(const MachineInstr *MI, int OpNum,
500e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                      raw_ostream &O, const char* Modifier = 0);
510e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
520e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                            raw_ostream &O);
530e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
540e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                         unsigned AsmVariant, const char *ExtraCode,
550e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                         raw_ostream &O);
560e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    bool PrintAsmMemoryOperand(const MachineInstr *MI,
570e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                               unsigned OpNo, unsigned AsmVariant,
580e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                               const char *ExtraCode, raw_ostream &O);
590e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    void EmitInstruction(const MachineInstr *MI);
600e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  };
610e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky} // end of anonymous namespace
620e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
630e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
640e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
650e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                    raw_ostream &O, const char *Modifier) {
660e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  const MachineOperand &MO = MI->getOperand(OpNum);
670e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  switch (MO.getType()) {
68bc2198133a1836598b54b943420748e75d5dea94Craig Topper  default: llvm_unreachable("Not implemented yet!");
690e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  case MachineOperand::MO_Register:
700e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << MSP430InstPrinter::getRegisterName(MO.getReg());
710e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return;
720e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  case MachineOperand::MO_Immediate:
730e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    if (!Modifier || strcmp(Modifier, "nohash"))
740e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      O << '#';
750e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << MO.getImm();
760e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return;
770e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  case MachineOperand::MO_MachineBasicBlock:
780e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << *MO.getMBB()->getSymbol();
790e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return;
800e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  case MachineOperand::MO_GlobalAddress: {
810e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
820e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    uint64_t Offset = MO.getOffset();
830e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
840e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    // If the global address expression is a part of displacement field with a
850e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    // register base, we should not emit any prefix symbol here, e.g.
860e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    //   mov.w &foo, r1
870e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    // vs
880e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    //   mov.w glb(r1), r2
890e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    // Otherwise (!) msp430-as will silently miscompile the output :(
900e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    if (!Modifier || strcmp(Modifier, "nohash"))
910e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      O << (isMemOp ? '&' : '#');
920e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    if (Offset)
930e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      O << '(' << Offset << '+';
940e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
950e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << *Mang->getSymbol(MO.getGlobal());
960e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
970e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    if (Offset)
980e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky      O << ')';
990e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1000e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return;
1010e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  }
1020e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  case MachineOperand::MO_ExternalSymbol: {
1030e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
1040e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << (isMemOp ? '&' : '#');
1050e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << MAI->getGlobalPrefix() << MO.getSymbolName();
1060e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return;
1070e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  }
1080e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  }
1090e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
1100e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1110e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
1120e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                          raw_ostream &O) {
1130e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  const MachineOperand &Base = MI->getOperand(OpNum);
1140e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  const MachineOperand &Disp = MI->getOperand(OpNum+1);
1150e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1160e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  // Print displacement first
1170e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1180e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  // Imm here is in fact global address - print extra modifier.
1190e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  if (Disp.isImm() && !Base.getReg())
1200e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << '&';
1210e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  printOperand(MI, OpNum+1, O, "nohash");
1220e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1230e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  // Print register base field
1240e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  if (Base.getReg()) {
1250e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << '(';
1260e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    printOperand(MI, OpNum, O);
1270e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    O << ')';
1280e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  }
1290e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
1300e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1310e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky/// PrintAsmOperand - Print out an operand for an inline asm expression.
1320e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky///
1330e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckybool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
1340e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                       unsigned AsmVariant,
1350e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                       const char *ExtraCode, raw_ostream &O) {
1360e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  // Does this asm operand have a single letter operand modifier?
1370e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  if (ExtraCode && ExtraCode[0])
1380e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return true; // Unknown modifier.
1390e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1400e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  printOperand(MI, OpNo, O);
1410e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  return false;
1420e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
1430e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1440e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckybool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
1450e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                             unsigned OpNo, unsigned AsmVariant,
1460e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                             const char *ExtraCode,
1470e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky                                             raw_ostream &O) {
1480e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  if (ExtraCode && ExtraCode[0]) {
1490e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky    return true; // Unknown modifier.
1500e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  }
1510e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  printSrcMemOperand(MI, OpNo, O);
1520e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  return false;
1530e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
1540e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1550e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky//===----------------------------------------------------------------------===//
1560e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
157a7542d5f870c5d98960d1676e23ac1d1d975d7e5Benjamin Kramer  MSP430MCInstLower MCInstLowering(OutContext, *this);
1580e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1590e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  MCInst TmpInst;
1600e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  MCInstLowering.Lower(MI, TmpInst);
1610e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  OutStreamer.EmitInstruction(TmpInst);
1620e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
1630e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky
1640e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky// Force static initialization.
1650e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewyckyextern "C" void LLVMInitializeMSP430AsmPrinter() {
1660e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
1670e7fdf5f09cf047223aa1756ca113ccd3c383a8eNick Lewycky}
168