//===- XtensaInstPrinter.cpp - Convert Xtensa MCInst to asm syntax --------===//
//
// The LLVM Compiler Infrastructure
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This class prints an Xtensa MCInst to a .s file.
//
//===----------------------------------------------------------------------===//
#include "XtensaInstPrinter.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
#include "XtensaGenAsmWriter.inc"
static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
int Offset = 0;
const MCSymbolRefExpr *SRE;
if (!(SRE = cast<MCSymbolRefExpr>(Expr)))
assert(false && "Unexpected MCExpr type.");
MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
switch (Kind) {
case MCSymbolRefExpr::VK_None:
break;
// TODO
default:
report_fatal_error("Invalid kind!");
}
OS << SRE->getSymbol();
if (Offset) {
if (Offset > 0)
OS << '+';
OS << Offset;
}
if (Kind != MCSymbolRefExpr::VK_None)
OS << ')';
}
void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) {
if (MC.isReg())
O << getRegisterName(MC.getReg());
else if (MC.isImm())
O << MC.getImm();
else if (MC.isExpr())
printExpr(MC.getExpr(), O);
else
report_fatal_error("Invalid operand");
}
void XtensaInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
}
void XtensaInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
O << getRegisterName(Reg);
}
void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printOperand(MI->getOperand(OpNum), O);
}
void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
raw_ostream &OS) {
OS << getRegisterName(MI->getOperand(OpNum).getReg());
OS << ", ";
printOperand(MI, OpNum + 1, OS);
}
void XtensaInstPrinter::printBranchTarget(const MCInst *MI, int OpNum,
raw_ostream &OS) {
const MCOperand &MC = MI->getOperand(OpNum);
if (MI->getOperand(OpNum).isImm()) {
int64_t Val = MC.getImm() + 4;
OS << ". ";
if (Val > 0)
OS << '+';
OS << Val;
} else if (MC.isExpr())
MC.getExpr()->print(OS, &MAI, true);
else
llvm_unreachable("Invalid operand");
}
void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum,
raw_ostream &OS) {
const MCOperand &MC = MI->getOperand(OpNum);
if (MC.isImm()) {
int64_t Val = MC.getImm() + 4;
OS << ". ";
if (Val > 0)
OS << '+';
OS << Val;
} else if (MC.isExpr())
MC.getExpr()->print(OS, &MAI, true);
else
llvm_unreachable("Invalid operand");
;
}
void XtensaInstPrinter::printCallOperand(const MCInst *MI, int OpNum,
raw_ostream &OS) {
const MCOperand &MC = MI->getOperand(OpNum);
if (MC.isImm()) {
int64_t Val = MC.getImm() + 4;
OS << ". ";
if (Val > 0)
OS << '+';
OS << Val;
} else if (MC.isExpr())
MC.getExpr()->print(OS, &MAI, true);
else
llvm_unreachable("Invalid operand");
}
void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum,
raw_ostream &O) {
const MCOperand &MC = MI->getOperand(OpNum);
if (MC.isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
int64_t InstrOff = Value & 0x3;
Value -= InstrOff;
assert((Value >= -262144 && Value <= -4) &&
"Invalid argument, value must be in ranges [-262144,-4]");
Value += ((InstrOff + 0x3) & 0x4) - InstrOff;
O << ". ";
O << Value;
} else if (MC.isExpr())
MC.getExpr()->print(O, &MAI, true);
else
llvm_unreachable("Invalid operand");
}
void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<8>(Value) &&
"Invalid argument, value must be in ranges [-128,127]");
O << Value;
} else {
printOperand(MI, OpNum, O);
}
}
void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((isInt<16>(Value) && ((Value & 0xFF) == 0)) &&
"Invalid argument, value must be multiples of 256 in range "
"[-32768,32512]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printImm12_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= -2048 && Value <= 2047) &&
"Invalid argument, value must be in ranges [-2048,2047]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= -2048 && Value <= 2047) &&
"Invalid argument, value must be in ranges [-2048,2047]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printUimm4_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 0 && Value <= 15) && "Invalid argument");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printUimm5_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 0 && Value <= 31) && "Invalid argument");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 1 && Value <= 31) &&
"Invalid argument, value must be in range [1,31]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 1 && Value <= 16) &&
"Invalid argument, value must be in range [1,16]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 0 && Value <= 255) &&
"Invalid argument, value must be in range [0,255]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printOffset8m16_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 0 && Value <= 510 && ((Value & 0x1) == 0)) &&
"Invalid argument, value must be multiples of two in range [0,510]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printOffset8m32_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(
(Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) &&
"Invalid argument, value must be multiples of four in range [0,1020]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) &&
"Invalid argument, value must be multiples of four in range [0,60]");
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
switch (Value) {
case -1:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 10:
case 12:
case 16:
case 32:
case 64:
case 128:
case 256:
break;
default:
assert((0) && "Invalid B4const argument");
}
O << Value;
} else
printOperand(MI, OpNum, O);
}
void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
switch (Value) {
case 32768:
case 65536:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 10:
case 12:
case 16:
case 32:
case 64:
case 128:
case 256:
break;
default:
assert((0) && "Invalid B4constu argument");
}
O << Value;
} else
printOperand(MI, OpNum, O);
}