119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//                     The LLVM Compiler Infrastructure
419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source
619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details.
719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file contains a printer that converts from our internal representation
1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// of machine-dependent LLVM code to the MSP430 assembly language.
1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#define DEBUG_TYPE "asm-printer"
1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430.h"
1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430InstrInfo.h"
1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430MCInstLower.h"
1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "MSP430TargetMachine.h"
2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "InstPrinter/MSP430InstPrinter.h"
2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Constants.h"
2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/DerivedTypes.h"
2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Module.h"
2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Assembly/Writer.h"
2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/AsmPrinter.h"
2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineModuleInfo.h"
2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineFunctionPass.h"
2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineConstantPool.h"
2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/CodeGen/MachineInstr.h"
3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCAsmInfo.h"
3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCInst.h"
3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCStreamer.h"
3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCSymbol.h"
3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Target/Mangler.h"
3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/TargetRegistry.h"
3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/raw_ostream.h"
3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanusing namespace llvm;
3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace {
4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  class MSP430AsmPrinter : public AsmPrinter {
4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  public:
4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      : AsmPrinter(TM, Streamer) {}
4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    virtual const char *getPassName() const {
4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return "MSP430 Assembly Printer";
4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    void printOperand(const MachineInstr *MI, int OpNum,
5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                      raw_ostream &O, const char* Modifier = 0);
5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            raw_ostream &O);
5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         unsigned AsmVariant, const char *ExtraCode,
5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         raw_ostream &O);
5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool PrintAsmMemoryOperand(const MachineInstr *MI,
5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               unsigned OpNo, unsigned AsmVariant,
5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               const char *ExtraCode, raw_ostream &O);
5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    void EmitInstruction(const MachineInstr *MI);
6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  };
6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end of anonymous namespace
6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                    raw_ostream &O, const char *Modifier) {
6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const MachineOperand &MO = MI->getOperand(OpNum);
6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  switch (MO.getType()) {
6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  default: assert(0 && "Not implemented yet!");
6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case MachineOperand::MO_Register:
7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << MSP430InstPrinter::getRegisterName(MO.getReg());
7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case MachineOperand::MO_Immediate:
7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!Modifier || strcmp(Modifier, "nohash"))
7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      O << '#';
7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << MO.getImm();
7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case MachineOperand::MO_MachineBasicBlock:
7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << *MO.getMBB()->getSymbol();
7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case MachineOperand::MO_GlobalAddress: {
8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint64_t Offset = MO.getOffset();
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // If the global address expression is a part of displacement field with a
8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // register base, we should not emit any prefix symbol here, e.g.
8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    //   mov.w &foo, r1
8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // vs
8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    //   mov.w glb(r1), r2
8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Otherwise (!) msp430-as will silently miscompile the output :(
9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!Modifier || strcmp(Modifier, "nohash"))
9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      O << (isMemOp ? '&' : '#');
9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Offset)
9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      O << '(' << Offset << '+';
9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << *Mang->getSymbol(MO.getGlobal());
9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Offset)
9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      O << ')';
9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case MachineOperand::MO_ExternalSymbol: {
10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << (isMemOp ? '&' : '#');
10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << MAI->getGlobalPrefix() << MO.getSymbolName();
10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                          raw_ostream &O) {
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const MachineOperand &Base = MI->getOperand(OpNum);
11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const MachineOperand &Disp = MI->getOperand(OpNum+1);
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Print displacement first
11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Imm here is in fact global address - print extra modifier.
11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Disp.isImm() && !Base.getReg())
12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << '&';
12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  printOperand(MI, OpNum+1, O, "nohash");
12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Print register base field
12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Base.getReg()) {
12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << '(';
12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    printOperand(MI, OpNum, O);
12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    O << ')';
12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// PrintAsmOperand - Print out an operand for an inline asm expression.
13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman///
13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                       unsigned AsmVariant,
13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                       const char *ExtraCode, raw_ostream &O) {
13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Does this asm operand have a single letter operand modifier?
13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (ExtraCode && ExtraCode[0])
13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true; // Unknown modifier.
13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  printOperand(MI, OpNo, O);
14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return false;
14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                             unsigned OpNo, unsigned AsmVariant,
14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                             const char *ExtraCode,
14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                             raw_ostream &O) {
14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (ExtraCode && ExtraCode[0]) {
14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true; // Unknown modifier.
15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  printSrcMemOperand(MI, OpNo, O);
15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return false;
15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);
15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MCInst TmpInst;
16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MCInstLowering.Lower(MI, TmpInst);
16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  OutStreamer.EmitInstruction(TmpInst);
16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// Force static initialization.
16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanextern "C" void LLVMInitializeMSP430AsmPrinter() {
16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
168