NaplesPUInstPrinter.cpp
From NaplesPU Documentation
Revision as of 15:49, 21 June 2019 by Francesco (talk | contribs) (Francesco moved page NuPlusInstPrinter.cpp to NaplesPUInstPrinter.cpp)
NuPlusInstPrinter contains method to print assembly instructions from MCInst objects.
//===-- NuPlusInstPrinter.cpp - Convert NuPlus 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 NuPlus MCInst to a .s file.
//
//===----------------------------------------------------------------------===//
#include "NuPlusInstPrinter.h"
#include "MCTargetDesc/NuPlusMCTargetDesc.h"
#include "NuPlusInstrInfo.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 "NuPlusGenAsmWriter.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 NuPlusInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
{
// TODO: (Catello) magic errs()
//errs()<< "";
OS << StringRef(getRegisterName(RegNo)).lower();
}
void NuPlusInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot, const MCSubtargetInfo &STI)
{
// NOP is or s0, s0, 0
if (MI->getOpcode() == NuPlus::ORSSI && MI->getOperand(0).isReg() &&
MI->getOperand(0).getReg() == NuPlus::S0 && MI->getOperand(1).isReg() &&
MI->getOperand(1).getReg() == NuPlus::S0 && MI->getOperand(2).isImm() &&
MI->getOperand(2).getImm() == 0)
{
O << "\tnop";
return;
}
printInstruction(MI, O);
printAnnotation(O, Annot);
}
void NuPlusInstPrinter::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 NuPlusInstPrinter::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 << ")";
}
}