Skip to content

Commit c21a4c6

Browse files
authored
[Xtensa] Implement Xtensa Interrupt/Exception/Debug Options. (#143820)
Implement Xtensa Interrupt. HighInterrupts, Exception, Debug Options. Also implement small Xtensa Options like PRID, Coprocessor and Timers.
1 parent f2d2c99 commit c21a4c6

24 files changed

+1438
-23
lines changed

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,14 @@ class XtensaAsmParser : public MCTargetAsmParser {
6262
#include "XtensaGenAsmMatcher.inc"
6363

6464
ParseStatus parseImmediate(OperandVector &Operands);
65-
ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false,
66-
bool SR = false);
65+
ParseStatus
66+
parseRegister(OperandVector &Operands, bool AllowParens = false,
67+
bool SR = false,
68+
Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
6769
ParseStatus parseOperandWithModifier(OperandVector &Operands);
68-
bool parseOperand(OperandVector &Operands, StringRef Mnemonic,
69-
bool SR = false);
70+
bool
71+
parseOperand(OperandVector &Operands, StringRef Mnemonic, bool SR = false,
72+
Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
7073
bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
7174
SMLoc NameLoc, OperandVector &Operands);
7275
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
@@ -580,7 +583,8 @@ bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
580583
}
581584

582585
ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
583-
bool AllowParens, bool SR) {
586+
bool AllowParens, bool SR,
587+
Xtensa::RegisterAccessType RAType) {
584588
SMLoc FirstS = getLoc();
585589
bool HadParens = false;
586590
AsmToken Buf[2];
@@ -624,7 +628,7 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
624628
return ParseStatus::NoMatch;
625629
}
626630

627-
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
631+
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
628632
return ParseStatus::NoMatch;
629633

630634
if (HadParens)
@@ -685,7 +689,7 @@ ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
685689
/// from this information, adding to Operands.
686690
/// If operand was parsed, returns false, else true.
687691
bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
688-
bool SR) {
692+
bool SR, Xtensa::RegisterAccessType RAType) {
689693
// Check if the current operand has a custom associated parser, if so, try to
690694
// custom parse the operand, or fallback to the general approach.
691695
ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
@@ -699,7 +703,7 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
699703
return true;
700704

701705
// Attempt to parse token as register
702-
if (parseRegister(Operands, true, SR).isSuccess())
706+
if (parseRegister(Operands, true, SR, RAType).isSuccess())
703707
return false;
704708

705709
// Attempt to parse token as an immediate
@@ -713,6 +717,11 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
713717
bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
714718
StringRef Name, SMLoc NameLoc,
715719
OperandVector &Operands) {
720+
Xtensa::RegisterAccessType RAType =
721+
Name[0] == 'w' ? Xtensa::REGISTER_WRITE
722+
: (Name[0] == 'r' ? Xtensa::REGISTER_READ
723+
: Xtensa::REGISTER_EXCHANGE);
724+
716725
if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||
717726
Name.starts_with("xsr.")) &&
718727
(Name.size() > 4)) {
@@ -728,7 +737,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
728737
if (RegNo == 0)
729738
RegNo = MatchRegisterAltName(RegName);
730739

731-
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
740+
if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
732741
return Error(NameLoc, "invalid register name");
733742

734743
// Parse operand
@@ -753,7 +762,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
753762
}
754763

755764
// Parse second operand
756-
if (parseOperand(Operands, Name, true))
765+
if (parseOperand(Operands, Name, true, RAType))
757766
return true;
758767
}
759768

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

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,64 @@ struct DecodeRegister {
119119
};
120120

121121
const DecodeRegister SRDecoderTable[] = {
122-
{Xtensa::LBEG, 0}, {Xtensa::LEND, 1}, {Xtensa::LCOUNT, 2},
123-
{Xtensa::SAR, 3}, {Xtensa::BREG, 4}, {Xtensa::SAR, 3},
124-
{Xtensa::LITBASE, 5}, {Xtensa::ACCLO, 16}, {Xtensa::ACCHI, 17},
125-
{Xtensa::M0, 32}, {Xtensa::M1, 33}, {Xtensa::M2, 34},
126-
{Xtensa::M3, 35}, {Xtensa::WINDOWBASE, 72}, {Xtensa::WINDOWSTART, 73},
127-
{Xtensa::MEMCTL, 97}, {Xtensa::VECBASE, 231}, {Xtensa::MISC0, 244},
128-
{Xtensa::MISC1, 245}, {Xtensa::MISC2, 246}, {Xtensa::MISC3, 247}};
122+
{Xtensa::LBEG, 0}, {Xtensa::LEND, 1},
123+
{Xtensa::LCOUNT, 2}, {Xtensa::SAR, 3},
124+
{Xtensa::BREG, 4}, {Xtensa::LITBASE, 5},
125+
{Xtensa::ACCLO, 16}, {Xtensa::ACCHI, 17},
126+
{Xtensa::M0, 32}, {Xtensa::M1, 33},
127+
{Xtensa::M2, 34}, {Xtensa::M3, 35},
128+
{Xtensa::WINDOWBASE, 72}, {Xtensa::WINDOWSTART, 73},
129+
{Xtensa::IBREAKENABLE, 96}, {Xtensa::MEMCTL, 97},
130+
{Xtensa::DDR, 104}, {Xtensa::IBREAKA0, 128},
131+
{Xtensa::IBREAKA1, 129}, {Xtensa::DBREAKA0, 144},
132+
{Xtensa::DBREAKA1, 145}, {Xtensa::DBREAKC0, 160},
133+
{Xtensa::DBREAKC1, 161}, {Xtensa::CONFIGID0, 176},
134+
{Xtensa::EPC1, 177}, {Xtensa::EPC2, 178},
135+
{Xtensa::EPC3, 179}, {Xtensa::EPC4, 180},
136+
{Xtensa::EPC5, 181}, {Xtensa::EPC6, 182},
137+
{Xtensa::EPC7, 183}, {Xtensa::DEPC, 192},
138+
{Xtensa::EPS2, 194}, {Xtensa::EPS3, 195},
139+
{Xtensa::EPS4, 196}, {Xtensa::EPS5, 197},
140+
{Xtensa::EPS6, 198}, {Xtensa::EPS7, 199},
141+
{Xtensa::CONFIGID1, 208}, {Xtensa::EXCSAVE1, 209},
142+
{Xtensa::EXCSAVE2, 210}, {Xtensa::EXCSAVE3, 211},
143+
{Xtensa::EXCSAVE4, 212}, {Xtensa::EXCSAVE5, 213},
144+
{Xtensa::EXCSAVE6, 214}, {Xtensa::EXCSAVE7, 215},
145+
{Xtensa::CPENABLE, 224}, {Xtensa::INTERRUPT, 226},
146+
{Xtensa::INTCLEAR, 227}, {Xtensa::INTENABLE, 228},
147+
{Xtensa::PS, 230}, {Xtensa::VECBASE, 231},
148+
{Xtensa::EXCCAUSE, 232}, {Xtensa::DEBUGCAUSE, 233},
149+
{Xtensa::CCOUNT, 234}, {Xtensa::PRID, 235},
150+
{Xtensa::ICOUNT, 236}, {Xtensa::ICOUNTLEVEL, 237},
151+
{Xtensa::EXCVADDR, 238}, {Xtensa::CCOMPARE0, 240},
152+
{Xtensa::CCOMPARE1, 241}, {Xtensa::CCOMPARE2, 242},
153+
{Xtensa::MISC0, 244}, {Xtensa::MISC1, 245},
154+
{Xtensa::MISC2, 246}, {Xtensa::MISC3, 247}};
129155

130156
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
131157
uint64_t Address,
132158
const MCDisassembler *Decoder) {
133159
if (RegNo > 255)
134160
return MCDisassembler::Fail;
135161

162+
Xtensa::RegisterAccessType RAType =
163+
Inst.getOpcode() == Xtensa::WSR
164+
? Xtensa::REGISTER_WRITE
165+
: (Inst.getOpcode() == Xtensa::RSR ? Xtensa::REGISTER_READ
166+
: Xtensa::REGISTER_EXCHANGE);
167+
136168
for (unsigned i = 0; i < std::size(SRDecoderTable); i++) {
137169
if (SRDecoderTable[i].RegNo == RegNo) {
138170
MCPhysReg Reg = SRDecoderTable[i].Reg;
139171

140-
if (!Xtensa::checkRegister(Reg,
141-
Decoder->getSubtargetInfo().getFeatureBits()))
172+
// Handle special case. The INTERRUPT/INTSET registers use the same
173+
// encoding, but INTERRUPT used for read and INTSET for write.
174+
if (Reg == Xtensa::INTERRUPT && RAType == Xtensa::REGISTER_WRITE) {
175+
Reg = Xtensa::INTSET;
176+
}
177+
178+
if (!Xtensa::checkRegister(
179+
Reg, Decoder->getSubtargetInfo().getFeatureBits(), RAType))
142180
return MCDisassembler::Fail;
143181

144182
Inst.addOperand(MCOperand::createReg(Reg));

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

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,95 @@ bool Xtensa::isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset) {
7575
}
7676

7777
// Verify Special Register
78-
bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) {
78+
bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
79+
RegisterAccessType RAType) {
7980
switch (RegNo) {
8081
case Xtensa::BREG:
8182
return FeatureBits[Xtensa::FeatureBoolean];
83+
case Xtensa::CCOUNT:
84+
case Xtensa::CCOMPARE0:
85+
if (FeatureBits[Xtensa::FeatureTimers1])
86+
return true;
87+
LLVM_FALLTHROUGH;
88+
case Xtensa::CCOMPARE1:
89+
if (FeatureBits[Xtensa::FeatureTimers2])
90+
return true;
91+
LLVM_FALLTHROUGH;
92+
case Xtensa::CCOMPARE2:
93+
if (FeatureBits[Xtensa::FeatureTimers3])
94+
return true;
95+
return false;
96+
case Xtensa::CONFIGID0:
97+
return RAType != Xtensa::REGISTER_EXCHANGE;
98+
case Xtensa::CONFIGID1:
99+
return RAType == Xtensa::REGISTER_READ;
100+
case Xtensa::CPENABLE:
101+
return FeatureBits[Xtensa::FeatureCoprocessor];
102+
case Xtensa::DEBUGCAUSE:
103+
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeatureDebug];
104+
case Xtensa::DEPC:
105+
case Xtensa::EPC1:
106+
case Xtensa::EXCCAUSE:
107+
case Xtensa::EXCSAVE1:
108+
case Xtensa::EXCVADDR:
109+
return FeatureBits[Xtensa::FeatureException];
110+
LLVM_FALLTHROUGH;
111+
case Xtensa::EPC2:
112+
case Xtensa::EPS2:
113+
case Xtensa::EXCSAVE2:
114+
if (FeatureBits[Xtensa::FeatureHighPriInterrupts])
115+
return true;
116+
LLVM_FALLTHROUGH;
117+
case Xtensa::EPC3:
118+
case Xtensa::EPS3:
119+
case Xtensa::EXCSAVE3:
120+
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel3])
121+
return true;
122+
LLVM_FALLTHROUGH;
123+
case Xtensa::EPC4:
124+
case Xtensa::EPS4:
125+
case Xtensa::EXCSAVE4:
126+
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel4])
127+
return true;
128+
LLVM_FALLTHROUGH;
129+
case Xtensa::EPC5:
130+
case Xtensa::EPS5:
131+
case Xtensa::EXCSAVE5:
132+
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel5])
133+
return true;
134+
LLVM_FALLTHROUGH;
135+
case Xtensa::EPC6:
136+
case Xtensa::EPS6:
137+
case Xtensa::EXCSAVE6:
138+
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel6])
139+
return true;
140+
LLVM_FALLTHROUGH;
141+
case Xtensa::EPC7:
142+
case Xtensa::EPS7:
143+
case Xtensa::EXCSAVE7:
144+
if (FeatureBits[Xtensa::FeatureHighPriInterruptsLevel7])
145+
return true;
146+
return false;
147+
case Xtensa::INTENABLE:
148+
return FeatureBits[Xtensa::FeatureInterrupt];
149+
case Xtensa::INTERRUPT:
150+
return RAType == Xtensa::REGISTER_READ &&
151+
FeatureBits[Xtensa::FeatureInterrupt];
152+
case Xtensa::INTSET:
153+
case Xtensa::INTCLEAR:
154+
return RAType == Xtensa::REGISTER_WRITE &&
155+
FeatureBits[Xtensa::FeatureInterrupt];
156+
case Xtensa::ICOUNT:
157+
case Xtensa::ICOUNTLEVEL:
158+
case Xtensa::IBREAKENABLE:
159+
case Xtensa::DDR:
160+
case Xtensa::IBREAKA0:
161+
case Xtensa::IBREAKA1:
162+
case Xtensa::DBREAKA0:
163+
case Xtensa::DBREAKA1:
164+
case Xtensa::DBREAKC0:
165+
case Xtensa::DBREAKC1:
166+
return FeatureBits[Xtensa::FeatureDebug];
82167
case Xtensa::LBEG:
83168
case Xtensa::LEND:
84169
case Xtensa::LCOUNT:
@@ -99,6 +184,8 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) {
99184
case Xtensa::MISC2:
100185
case Xtensa::MISC3:
101186
return FeatureBits[Xtensa::FeatureMiscSR];
187+
case Xtensa::PRID:
188+
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID];
102189
case Xtensa::VECBASE:
103190
return FeatureBits[Xtensa::FeatureRelocatableVector];
104191
case Xtensa::WINDOWBASE:

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,15 @@ bool isValidAddrOffset(int Scale, int64_t OffsetVal);
5555
// Check address offset for load/store instructions.
5656
bool isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset);
5757

58+
enum RegisterAccessType {
59+
REGISTER_WRITE = 1,
60+
REGISTER_READ = 2,
61+
REGISTER_EXCHANGE = 3
62+
};
63+
5864
// Verify if it's correct to use a special register.
59-
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits);
65+
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
66+
RegisterAccessType RA);
6067
} // namespace Xtensa
6168
} // end namespace llvm
6269

llvm/lib/Target/Xtensa/XtensaFeatures.td

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,43 @@ def FeatureDataCache : SubtargetFeature<"dcache", "HasDataCache", "true",
9292
"Enable Xtensa Data Cache option">;
9393
def HasDataCache : Predicate<"Subtarget->hasDataCache()">,
9494
AssemblerPredicate<(all_of FeatureDataCache)>;
95+
96+
// Xtensa Interrupts Options.
97+
def FeatureHighPriInterrupts : SubtargetFeature<"highpriinterrupts",
98+
"HasHighPriInterrupts", "true",
99+
"Enable Xtensa HighPriInterrupts option">;
100+
def HasHighPriInterrupts : Predicate<"Subtarget->hasHighPriInterrupts()">,
101+
AssemblerPredicate<(all_of FeatureHighPriInterrupts)>;
102+
103+
foreach i = {3-7} in
104+
def FeatureHighPriInterruptsLevel#i : SubtargetFeature<"highpriinterrupts-level"#i,
105+
"HasHighPriInterruptsLevel"#i#"", "true", "Enable Xtensa HighPriInterrupts Level"#i, [FeatureHighPriInterrupts]>;
106+
107+
def FeatureInterrupt : SubtargetFeature<"interrupt", "HasInterrupt", "true",
108+
"Enable Xtensa Interrupt option">;
109+
def HasInterrupt : Predicate<"Subtarget->hasInterrupt()">,
110+
AssemblerPredicate<(all_of FeatureInterrupt)>;
111+
112+
def FeatureException : SubtargetFeature<"exception", "HasException", "true",
113+
"Enable Xtensa Exception option">;
114+
def HasException : Predicate<"Subtarget->hasException()">,
115+
AssemblerPredicate<(all_of FeatureException)>;
116+
117+
def FeatureDebug : SubtargetFeature<"debug", "HasDebug", "true",
118+
"Enable Xtensa Debug option">;
119+
def HasDebug : Predicate<"Subtarget->hasDebug()">,
120+
AssemblerPredicate<(all_of FeatureDebug)>;
121+
122+
foreach i = {1-3} in
123+
def FeatureTimers#i : SubtargetFeature<"timers"#i,
124+
"HasTimers"#i#"", "true", "Enable Xtensa Timers "#i>;
125+
126+
def FeaturePRID : SubtargetFeature<"prid", "HasPRID", "true",
127+
"Enable Xtensa Processor ID option">;
128+
def HasPRID : Predicate<"Subtarget->hasPRID()">,
129+
AssemblerPredicate<(all_of FeaturePRID)>;
130+
131+
def FeatureCoprocessor : SubtargetFeature<"coprocessor", "HasCoprocessor", "true",
132+
"Enable Xtensa Coprocessor option">;
133+
def HasCoprocessor : Predicate<"Subtarget->hasCoprocessor()">,
134+
AssemblerPredicate<(all_of FeatureCoprocessor)>;

0 commit comments

Comments
 (0)