Skip to content

[Xtensa] Implement Windowed Register Option. #121118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "MCTargetDesc/XtensaTargetStreamer.h"
#include "TargetInfo/XtensaTargetInfo.h"
#include "XtensaUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCContext.h"
Expand Down Expand Up @@ -73,6 +74,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
SMLoc &EndLoc) override {
return ParseStatus::NoMatch;
}

ParseStatus parsePCRelTarget(OperandVector &Operands);
bool parseLiteralDirective(SMLoc L);

Expand All @@ -89,6 +91,10 @@ class XtensaAsmParser : public MCTargetAsmParser {
: MCTargetAsmParser(Options, STI, MII) {
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}

bool hasWindowed() const {
return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];
};
};

// Return true if Expr is in the range [MinValue, MaxValue].
Expand Down Expand Up @@ -181,6 +187,11 @@ struct XtensaOperand : public MCParsedAsmOperand {
((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
}

bool isentry_imm12() const {
return isImm(0, 32760) &&
((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
}

bool isUimm4() const { return isImm(0, 15); }

bool isUimm5() const { return isImm(0, 31); }
Expand All @@ -198,6 +209,11 @@ struct XtensaOperand : public MCParsedAsmOperand {

bool isImm32n_95() const { return isImm(-32, 95); }

bool isImm64n_4n() const {
return isImm(-64, -4) &&
((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
}

bool isB4const() const {
if (Kind != Immediate)
return false;
Expand Down Expand Up @@ -491,6 +507,12 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm32n_95:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [-32, 95]");
case Match_InvalidImm64n_4n:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [-64, -4]");
case Match_InvalidImm8n_7:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [-8, 7]");
case Match_InvalidShimm1_31:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [1, 31]");
Expand All @@ -515,6 +537,10 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [0, 60], first 2 bits "
"should be zero");
case Match_Invalidentry_imm12:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [0, 32760], first 3 bits "
"should be zero");
}

report_fatal_error("Unknown match type detected!");
Expand Down Expand Up @@ -601,6 +627,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
getLexer().UnLex(Buf[0]);
return ParseStatus::NoMatch;
}

if (!checkRegister(RegNo, getSTI().getFeatureBits()))
return ParseStatus::NoMatch;

if (HadParens)
Operands.push_back(XtensaOperand::createToken("(", FirstS));
SMLoc S = getLoc();
Expand Down Expand Up @@ -702,7 +732,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
if (RegNo == 0)
RegNo = MatchRegisterAltName(RegName);

if (RegNo == 0)
if (!checkRegister(RegNo, getSTI().getFeatureBits()))
return Error(NameLoc, "invalid register name");

// Parse operand
Expand Down
33 changes: 31 additions & 2 deletions llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "TargetInfo/XtensaTargetInfo.h"
#include "XtensaUtils.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDecoderOps.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
Expand Down Expand Up @@ -73,17 +74,22 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}

static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
static const unsigned SRDecoderTable[] = {
Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};

static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
const MCDisassembler *Decoder) {
if (RegNo > 255)
return MCDisassembler::Fail;

for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
if (SRDecoderTable[i + 1] == RegNo) {
unsigned Reg = SRDecoderTable[i];

if (!checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits()))
Copy link
Member

@MaskRay MaskRay Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XtensaDisassembler cannot use functions defined in XtensaCodeGen (Xtensa/CMakeFiles.txt).

After #123969 , you can place checkRegister in MCTargetDesc/

For CMake changes, best to check both BUILD_SHARED_LIBS=on and off builds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much!

return MCDisassembler::Fail;

Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
Expand Down Expand Up @@ -210,6 +216,29 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
return MCDisassembler::Success;
}

static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm,
int64_t Address, const void *Decoder) {
assert(isUInt<4>(Imm) && "Invalid immediate");
Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
return MCDisassembler::Success;
}

static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm,
int64_t Address,
const void *Decoder) {
assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
return MCDisassembler::Success;
}

static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm,
int64_t Address,
const void *Decoder) {
assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
Inst.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}

static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
int64_t Address,
const void *Decoder) {
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,28 @@ void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
printOperand(MI, OpNum, O);
}

void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= -8 && Value <= 7) &&
"Invalid argument, value must be in ranges <-8,7>");
O << Value;
} else
printOperand(MI, OpNum, O);
}

void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) &&
"Invalid argument, value must be in ranges <-64,-4>");
O << Value;
} else
printOperand(MI, OpNum, O);
}

void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
Expand Down Expand Up @@ -309,6 +331,18 @@ void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
printOperand(MI, OpNum, O);
}

void XtensaInstPrinter::printEntry_Imm12_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 <= 32760) &&
"Invalid argument, value must be multiples of eight in range "
"<0,32760>");
O << Value;
} else
printOperand(MI, OpNum, O);
}

void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ class XtensaInstPrinter : public MCInstPrinter {
void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
};
Expand Down
52 changes: 52 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint32_t getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint32_t getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint32_t getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
Expand Down Expand Up @@ -405,6 +417,46 @@ XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
return Res;
}

uint32_t
XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
int32_t Res = static_cast<int32_t>(MO.getImm());

assert(((Res >= -8) && (Res <= 7)) && "Unexpected operand value!");

if (Res < 0)
return Res + 16;

return Res;
}

uint32_t
XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
int32_t Res = static_cast<int32_t>(MO.getImm());

assert(((Res >= -64) && (Res <= -4) && ((Res & 0x3) == 0)) &&
"Unexpected operand value!");

return Res & 0x3f;
}

uint32_t
XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
uint32_t res = static_cast<uint32_t>(MO.getImm());

assert(((res & 0x7) == 0) && "Unexpected operand value!");

return res;
}

uint32_t
XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down
7 changes: 3 additions & 4 deletions llvm/lib/Target/Xtensa/Xtensa.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ include "llvm/Target/Target.td"
//===----------------------------------------------------------------------===//
// Subtarget Features.
//===----------------------------------------------------------------------===//
def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
"Enable Density instructions">;
def HasDensity : Predicate<"Subtarget->hasDensity()">,
AssemblerPredicate<(all_of FeatureDensity)>;

include "XtensaFeatures.td"

//===----------------------------------------------------------------------===//
// Xtensa supported processors.
//===----------------------------------------------------------------------===//
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaFeatures.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//===----------------------------------------------------------------------===//
// Xtensa subtarget features.
//===----------------------------------------------------------------------===//

// Xtensa ISA extensions (Xtensa Options).
def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
"Enable Density instructions">;
def HasDensity : Predicate<"Subtarget->hasDensity()">,
AssemblerPredicate<(all_of FeatureDensity)>;

def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
"Enable Xtensa Windowed Register option">;
def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
AssemblerPredicate<(all_of FeatureWindowed)>;
Loading
Loading