NaplesPUInstPrinter.cpp

From NaplesPU Documentation
Revision as of 16:05, 21 June 2019 by Francesco (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

NaplesPUInstPrinter contains method to print assembly instructions from MCInst objects.

//===-- NaplesPUInstPrinter.cpp - Convert NaplesPU MCInst to assembly syntax -----==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an NaplesPU MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#include "NaplesPUInstPrinter.h"
#include "MCTargetDesc/NaplesPUMCTargetDesc.h"
#include "NaplesPUInstrInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

using namespace llvm;

#include "NaplesPUGenAsmWriter.inc"

namespace
{
void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
               raw_ostream &OS)
{
  int Offset = 0;
  const MCSymbolRefExpr *SRE;

  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr))
  {
    SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
    assert(SRE && CE && "Binary expression must be sym+const.");
    Offset = CE->getValue();
  }
  else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr)))
  {
    Expr->print(OS, MAI);
    return;
  }

  MCSymbolRefExpr::VariantKind Kind = SRE->getKind();

  OS << SRE->getSymbol();

  if (Offset)
  {
    if (Offset > 0)
      OS << '+';
    OS << Offset;
  }

  if (Kind != MCSymbolRefExpr::VK_None)
    OS << ')';
}
}

void NaplesPUInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
{
  // TODO: (Catello) magic errs()
  //errs()<< "";
  OS << StringRef(getRegisterName(RegNo)).lower();
}

void NaplesPUInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
                                  StringRef Annot, const MCSubtargetInfo &STI)
{
  // NOP is or s0, s0, 0
  if (MI->getOpcode() == NaplesPU::ORSSI && MI->getOperand(0).isReg() &&
      MI->getOperand(0).getReg() == NaplesPU::S0 && MI->getOperand(1).isReg() &&
      MI->getOperand(1).getReg() == NaplesPU::S0 && MI->getOperand(2).isImm() &&
      MI->getOperand(2).getImm() == 0)
  {
    O << "\tnop";
    return;
  }

  printInstruction(MI, O);
  printAnnotation(O, Annot);
}

void NaplesPUInstPrinter::printOperand(const MCInst *MI, int opNum,
                                     raw_ostream &O)
{
  const MCOperand &MO = MI->getOperand(opNum);

  if (MO.isReg())
  {
    printRegName(O, MO.getReg());
    return;
  }

  if (MO.isImm())
  {
    O << (int)MO.getImm();
    return;
  }

  assert(MO.isExpr() && "Unknown operand kind in printOperand");
  if (MO.isExpr())
  {
    printExpr(MO.getExpr(), &MAI, O);
  }
  return;
}

void NaplesPUInstPrinter::printMemOperand(const MCInst *MI, int opNum,
                                        raw_ostream &O)
{
   if (MI->getOperand(opNum).isExpr())
  {
    // Abs instructions
    printOperand(MI, opNum, O);
  }
  else if (MI->getOperand(opNum + 1).isExpr())
  {
    // PC relative memory access to a local label
    printOperand(MI, opNum + 1, O);
  }
  else
  {
    // Register/offset
    assert(MI->getOperand(opNum).isReg());
    assert(MI->getOperand(opNum + 1).isImm());

    if (MI->getOperand(opNum + 1).getImm())
      printOperand(MI, opNum + 1, O);

    O << "(";
    printOperand(MI, opNum, O);
    O << ")";
  }
}