Skip to content

Commit f6578c3

Browse files
authored
[Xtensa] Implement Windowed Register Option. (#124656)
This patch implements Xtensa ISA option "Windowed Register Option". It implements subtarget feature, instructions descriptions and support of these instructions in asm parser and disassembler. This is the second version of the Windowed Register Option implementation ( previous implementation #121118). In this variant "checkRegister" function is placed in XtensaMCTargetDesc.
1 parent 115bb87 commit f6578c3

18 files changed

+555
-10
lines changed

llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
7373
SMLoc &EndLoc) override {
7474
return ParseStatus::NoMatch;
7575
}
76+
7677
ParseStatus parsePCRelTarget(OperandVector &Operands);
7778
bool parseLiteralDirective(SMLoc L);
7879

@@ -89,6 +90,10 @@ class XtensaAsmParser : public MCTargetAsmParser {
8990
: MCTargetAsmParser(Options, STI, MII) {
9091
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
9192
}
93+
94+
bool hasWindowed() const {
95+
return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];
96+
};
9297
};
9398

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

189+
bool isentry_imm12() const {
190+
return isImm(0, 32760) &&
191+
((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
192+
}
193+
184194
bool isUimm4() const { return isImm(0, 15); }
185195

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

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

211+
bool isImm64n_4n() const {
212+
return isImm(-64, -4) &&
213+
((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
214+
}
215+
201216
bool isB4const() const {
202217
if (Kind != Immediate)
203218
return false;
@@ -491,6 +506,12 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
491506
case Match_InvalidImm32n_95:
492507
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
493508
"expected immediate in range [-32, 95]");
509+
case Match_InvalidImm64n_4n:
510+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
511+
"expected immediate in range [-64, -4]");
512+
case Match_InvalidImm8n_7:
513+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
514+
"expected immediate in range [-8, 7]");
494515
case Match_InvalidShimm1_31:
495516
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
496517
"expected immediate in range [1, 31]");
@@ -515,6 +536,10 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
515536
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
516537
"expected immediate in range [0, 60], first 2 bits "
517538
"should be zero");
539+
case Match_Invalidentry_imm12:
540+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
541+
"expected immediate in range [0, 32760], first 3 bits "
542+
"should be zero");
518543
}
519544

520545
report_fatal_error("Unknown match type detected!");
@@ -601,6 +626,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
601626
getLexer().UnLex(Buf[0]);
602627
return ParseStatus::NoMatch;
603628
}
629+
630+
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
631+
return ParseStatus::NoMatch;
632+
604633
if (HadParens)
605634
Operands.push_back(XtensaOperand::createToken("(", FirstS));
606635
SMLoc S = getLoc();
@@ -702,7 +731,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
702731
if (RegNo == 0)
703732
RegNo = MatchRegisterAltName(RegName);
704733

705-
if (RegNo == 0)
734+
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
706735
return Error(NameLoc, "invalid register name");
707736

708737
// Parse operand

llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {
5757
createXtensaDisassembler);
5858
}
5959

60-
static const unsigned ARDecoderTable[] = {
60+
const unsigned ARDecoderTable[] = {
6161
Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5,
6262
Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11,
6363
Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
@@ -73,17 +73,23 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
7373
return MCDisassembler::Success;
7474
}
7575

76-
static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
76+
const unsigned SRDecoderTable[] = {
77+
Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
7778

7879
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
7980
uint64_t Address,
80-
const void *Decoder) {
81+
const MCDisassembler *Decoder) {
8182
if (RegNo > 255)
8283
return MCDisassembler::Fail;
8384

8485
for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
8586
if (SRDecoderTable[i + 1] == RegNo) {
8687
unsigned Reg = SRDecoderTable[i];
88+
89+
if (!Xtensa::checkRegister(Reg,
90+
Decoder->getSubtargetInfo().getFeatureBits()))
91+
return MCDisassembler::Fail;
92+
8793
Inst.addOperand(MCOperand::createReg(Reg));
8894
return MCDisassembler::Success;
8995
}
@@ -210,6 +216,29 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
210216
return MCDisassembler::Success;
211217
}
212218

219+
static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm,
220+
int64_t Address, const void *Decoder) {
221+
assert(isUInt<4>(Imm) && "Invalid immediate");
222+
Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
223+
return MCDisassembler::Success;
224+
}
225+
226+
static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm,
227+
int64_t Address,
228+
const void *Decoder) {
229+
assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
230+
Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
231+
return MCDisassembler::Success;
232+
}
233+
234+
static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm,
235+
int64_t Address,
236+
const void *Decoder) {
237+
assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
238+
Inst.addOperand(MCOperand::createImm(Imm));
239+
return MCDisassembler::Success;
240+
}
241+
213242
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
214243
int64_t Address,
215244
const void *Decoder) {

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,28 @@ void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
264264
printOperand(MI, OpNum, O);
265265
}
266266

267+
void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum,
268+
raw_ostream &O) {
269+
if (MI->getOperand(OpNum).isImm()) {
270+
int64_t Value = MI->getOperand(OpNum).getImm();
271+
assert((Value >= -8 && Value <= 7) &&
272+
"Invalid argument, value must be in ranges <-8,7>");
273+
O << Value;
274+
} else
275+
printOperand(MI, OpNum, O);
276+
}
277+
278+
void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum,
279+
raw_ostream &O) {
280+
if (MI->getOperand(OpNum).isImm()) {
281+
int64_t Value = MI->getOperand(OpNum).getImm();
282+
assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) &&
283+
"Invalid argument, value must be in ranges <-64,-4>");
284+
O << Value;
285+
} else
286+
printOperand(MI, OpNum, O);
287+
}
288+
267289
void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
268290
raw_ostream &O) {
269291
if (MI->getOperand(OpNum).isImm()) {
@@ -309,6 +331,18 @@ void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
309331
printOperand(MI, OpNum, O);
310332
}
311333

334+
void XtensaInstPrinter::printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum,
335+
raw_ostream &O) {
336+
if (MI->getOperand(OpNum).isImm()) {
337+
int64_t Value = MI->getOperand(OpNum).getImm();
338+
assert((Value >= 0 && Value <= 32760) &&
339+
"Invalid argument, value must be multiples of eight in range "
340+
"<0,32760>");
341+
O << Value;
342+
} else
343+
printOperand(MI, OpNum, O);
344+
}
345+
312346
void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
313347
raw_ostream &O) {
314348
if (MI->getOperand(OpNum).isImm()) {

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ class XtensaInstPrinter : public MCInstPrinter {
6060
void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6161
void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6262
void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
63+
void printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
64+
void printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6365
void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6466
void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6567
void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6668
void printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
69+
void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6770
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6871
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6972
};

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
111111
SmallVectorImpl<MCFixup> &Fixups,
112112
const MCSubtargetInfo &STI) const;
113113

114+
uint32_t getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
115+
SmallVectorImpl<MCFixup> &Fixups,
116+
const MCSubtargetInfo &STI) const;
117+
118+
uint32_t getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
119+
SmallVectorImpl<MCFixup> &Fixups,
120+
const MCSubtargetInfo &STI) const;
121+
122+
uint32_t getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
123+
SmallVectorImpl<MCFixup> &Fixups,
124+
const MCSubtargetInfo &STI) const;
125+
114126
uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
115127
SmallVectorImpl<MCFixup> &Fixups,
116128
const MCSubtargetInfo &STI) const;
@@ -405,6 +417,46 @@ XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
405417
return Res;
406418
}
407419

420+
uint32_t
421+
XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
422+
SmallVectorImpl<MCFixup> &Fixups,
423+
const MCSubtargetInfo &STI) const {
424+
const MCOperand &MO = MI.getOperand(OpNo);
425+
int32_t Res = static_cast<int32_t>(MO.getImm());
426+
427+
assert(((Res >= -8) && (Res <= 7)) && "Unexpected operand value!");
428+
429+
if (Res < 0)
430+
return Res + 16;
431+
432+
return Res;
433+
}
434+
435+
uint32_t
436+
XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
437+
SmallVectorImpl<MCFixup> &Fixups,
438+
const MCSubtargetInfo &STI) const {
439+
const MCOperand &MO = MI.getOperand(OpNo);
440+
int32_t Res = static_cast<int32_t>(MO.getImm());
441+
442+
assert(((Res >= -64) && (Res <= -4) && ((Res & 0x3) == 0)) &&
443+
"Unexpected operand value!");
444+
445+
return Res & 0x3f;
446+
}
447+
448+
uint32_t
449+
XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
450+
SmallVectorImpl<MCFixup> &Fixups,
451+
const MCSubtargetInfo &STI) const {
452+
const MCOperand &MO = MI.getOperand(OpNo);
453+
uint32_t res = static_cast<uint32_t>(MO.getImm());
454+
455+
assert(((res & 0x7) == 0) && "Unexpected operand value!");
456+
457+
return res;
458+
}
459+
408460
uint32_t
409461
XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
410462
SmallVectorImpl<MCFixup> &Fixups,

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ bool Xtensa::isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset) {
7474
return isValidAddrOffset(Scale, Offset);
7575
}
7676

77+
// Verify Special Register
78+
bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) {
79+
switch (RegNo) {
80+
case Xtensa::WINDOWBASE:
81+
case Xtensa::WINDOWSTART:
82+
return FeatureBits[Xtensa::FeatureWindowed];
83+
case Xtensa::NoRegister:
84+
return false;
85+
}
86+
87+
return true;
88+
}
89+
7790
static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
7891
const Triple &TT,
7992
const MCTargetOptions &Options) {

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
namespace llvm {
2121

22+
class FeatureBitset;
2223
class MCAsmBackend;
2324
class MCCodeEmitter;
2425
class MCContext;
2526
class MCInstrInfo;
2627
class MCObjectTargetWriter;
2728
class MCObjectWriter;
29+
class MCRegister;
2830
class MCRegisterInfo;
2931
class MCSubtargetInfo;
3032
class MCTargetOptions;
@@ -52,6 +54,9 @@ bool isValidAddrOffset(int Scale, int64_t OffsetVal);
5254

5355
// Check address offset for load/store instructions.
5456
bool isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset);
57+
58+
// Verify if it's correct to use a special register.
59+
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits);
5560
} // namespace Xtensa
5661
} // end namespace llvm
5762

llvm/lib/Target/Xtensa/Xtensa.td

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ include "llvm/Target/Target.td"
1717
//===----------------------------------------------------------------------===//
1818
// Subtarget Features.
1919
//===----------------------------------------------------------------------===//
20-
def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
21-
"Enable Density instructions">;
22-
def HasDensity : Predicate<"Subtarget->hasDensity()">,
23-
AssemblerPredicate<(all_of FeatureDensity)>;
20+
21+
include "XtensaFeatures.td"
22+
2423
//===----------------------------------------------------------------------===//
2524
// Xtensa supported processors.
2625
//===----------------------------------------------------------------------===//
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===----------------------------------------------------------------------===//
2+
// Xtensa subtarget features.
3+
//===----------------------------------------------------------------------===//
4+
5+
// Xtensa ISA extensions (Xtensa Options).
6+
def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
7+
"Enable Density instructions">;
8+
def HasDensity : Predicate<"Subtarget->hasDensity()">,
9+
AssemblerPredicate<(all_of FeatureDensity)>;
10+
11+
def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
12+
"Enable Xtensa Windowed Register option">;
13+
def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
14+
AssemblerPredicate<(all_of FeatureWindowed)>;

0 commit comments

Comments
 (0)