Skip to content

Commit

Permalink
[Xtensa] Fix asm parsing of special registers.
Browse files Browse the repository at this point in the history
Fix parsing of the interrupt feature registers.
The "interrupt" register mnemonic is used only with rsr instruction, "intset" and "intclear"
register mnemonics are used only with wsr instruction. Also fixed "debugcause" and "prid"
registers parsing. Fix tryParseRegister function.
  • Loading branch information
andreisfr committed Jul 14, 2023
1 parent 2aba83d commit 5073a51
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 34 deletions.
87 changes: 61 additions & 26 deletions llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class XtensaAsmParser : public MCTargetAsmParser {

OperandMatchResultTy parseImmediate(OperandVector &Operands);
OperandMatchResultTy parseRegister(OperandVector &Operands,
StringRef Mnemonic,
bool AllowParens = false, bool SR = false,
bool UR = false);
OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
Expand All @@ -88,11 +89,9 @@ class XtensaAsmParser : public MCTargetAsmParser {
bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands);
OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) override {
return MatchOperand_NoMatch;
}
SMLoc &EndLoc) override;
OperandMatchResultTy parsePCRelTarget(OperandVector &Operands);
bool checkRegister(unsigned RegNo);
bool checkRegister(StringRef Mnemonic, StringRef RegName, MCRegister RegNo);
bool parseLiteralDirective(SMLoc L);
bool parseBeginDirective(SMLoc L);
bool parseEndDirective(SMLoc L);
Expand Down Expand Up @@ -737,6 +736,29 @@ XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
return MatchOperand_Success;
}

// Attempts to match Name as a register (either using the default name or
// alternative ABI names), setting RegNo to the matching register. Upon
// failure, returns true and sets RegNo to 0
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
RegNo = MatchRegisterName(Name);

if (RegNo == Xtensa::NoRegister)
RegNo = MatchRegisterAltName(Name.lower());

if (RegNo == Xtensa::NoRegister)
RegNo = MatchRegisterAltName(Name.upper());

return RegNo == Xtensa::NoRegister;
}

OperandMatchResultTy XtensaAsmParser::tryParseRegister(MCRegister &RegNo,
SMLoc &StartLoc,
SMLoc &EndLoc) {
if (parseRegister(RegNo, StartLoc, EndLoc))
return MatchOperand_NoMatch;
return MatchOperand_Success;
}

bool XtensaAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
const AsmToken &Tok = getParser().getTok();
Expand All @@ -754,12 +776,14 @@ bool XtensaAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
}

OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands,
StringRef Mnemonic,
bool AllowParens, bool SR,
bool UR) {
SMLoc FirstS = getLoc();
bool HadParens = false;
AsmToken Buf[2];
std::string RegName = "";
MCRegister RegNo = 0;
int64_t Num;
bool IsIdentifier = false;

Expand All @@ -774,8 +798,6 @@ OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands,
}
}

unsigned RegNo = 0;

switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
Expand Down Expand Up @@ -813,16 +835,13 @@ OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands,
RegName = "F64S";
} else
RegName = std::to_string(Num);
RegNo = MatchRegisterName(RegName);
if (RegNo == 0)
RegNo = MatchRegisterAltName(RegName);

matchRegisterNameHelper(RegNo, RegName);
break;
case AsmToken::Identifier:
IsIdentifier = true;
RegName = getLexer().getTok().getIdentifier().str();
RegNo = MatchRegisterName(RegName);
if (RegNo == 0)
RegNo = MatchRegisterAltName(RegName);
matchRegisterNameHelper(RegNo, RegName);
break;
}

Expand All @@ -832,7 +851,7 @@ OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands,
return MatchOperand_NoMatch;
}

if (!checkRegister(RegNo)) {
if (!checkRegister(Mnemonic.lower(), RegName, RegNo)) {
return MatchOperand_NoMatch;
}

Expand Down Expand Up @@ -908,7 +927,7 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
return true;

// Attempt to parse token as register
if (parseRegister(Operands, true, SR, UR) == MatchOperand_Success)
if (parseRegister(Operands, Mnemonic, true, SR, UR) == MatchOperand_Success)
return false;

// Attempt to parse token as an immediate
Expand Down Expand Up @@ -939,17 +958,11 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));

StringRef RegName = Name.drop_front(4);
unsigned RegNo = MatchRegisterName(RegName);
MCRegister RegNo = 0;

if (RegNo == 0)
RegNo = MatchRegisterAltName(RegName);
matchRegisterNameHelper(RegNo, RegName);

if (RegNo == 0) {
Error(NameLoc, "invalid register name");
return true;
}

if (!checkRegister(RegNo)) {
if (!checkRegister(Name.lower(), RegName, RegNo)) {
Error(NameLoc, "invalid register name");
return true;
}
Expand Down Expand Up @@ -1168,7 +1181,8 @@ bool XtensaAsmParser::ParseDirective(AsmToken DirectiveID) {
}

// Verify SR and UR
bool XtensaAsmParser::checkRegister(unsigned RegNo) {
bool XtensaAsmParser::checkRegister(StringRef Mnemonic, StringRef RegName,
MCRegister RegNo) {
StringRef CPU = getSTI().getCPU();
unsigned NumIntLevels = 0;
unsigned NumTimers = 0;
Expand All @@ -1177,6 +1191,8 @@ bool XtensaAsmParser::checkRegister(unsigned RegNo) {
bool IsESP32S2 = false;
bool IsESP32S3 = false;
bool Res = true;
bool IsWSR = Mnemonic.startswith("wsr");
bool IsRSR = Mnemonic.startswith("rsr");

// Assume that CPU is esp32 by default
if ((CPU == "esp32") || (CPU == "")) {
Expand Down Expand Up @@ -1233,11 +1249,14 @@ bool XtensaAsmParser::checkRegister(unsigned RegNo) {
case Xtensa::DBREAKA1:
case Xtensa::DBREAKC0:
case Xtensa::DBREAKC1:
case Xtensa::DEBUGCAUSE:
case Xtensa::ICOUNT:
case Xtensa::ICOUNTLEVEL:
Res = hasDebug();
break;
case Xtensa::DEBUGCAUSE:
Res = hasDebug();
Res = Res & IsRSR;
break;
case Xtensa::ATOMCTL:
Res = hasATOMCTL();
break;
Expand Down Expand Up @@ -1300,9 +1319,23 @@ bool XtensaAsmParser::checkRegister(unsigned RegNo) {
break;
case Xtensa::PRID:
Res = hasPRID();
Res = Res & IsRSR;
break;
case Xtensa::INTERRUPT:
// INTSET mnemonic is wrtite-only
// INTERRUPT mnemonic is read-only
if (RegName.startswith("intset")) {
if (!IsWSR)
Res = false;
} else if (!IsRSR) {
Res = false;
}
Res = Res & hasInterrupt();
break;
case Xtensa::INTSET:
case Xtensa::INTCLEAR:
Res = hasInterrupt();
Res = Res & IsWSR;
break;
case Xtensa::INTENABLE:
Res = hasInterrupt();
break;
Expand Down Expand Up @@ -1331,6 +1364,8 @@ bool XtensaAsmParser::checkRegister(unsigned RegNo) {
case Xtensa::F64S:
Res = hasDFPAccel();
break;
case Xtensa::NoRegister:
Res = false;
}

return Res;
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ bool CheckRegister(unsigned RegNo, MCSubtargetInfo STI) {
case Xtensa::PRID:
Res = STI.getFeatureBits()[Xtensa::FeaturePRID];
break;
case Xtensa::INTSET:
case Xtensa::INTERRUPT:
case Xtensa::INTCLEAR:
case Xtensa::INTENABLE:
Res = STI.getFeatureBits()[Xtensa::FeatureInterrupt];
Expand Down Expand Up @@ -335,7 +335,7 @@ static const unsigned SRDecoderTable[] = {
Xtensa::EXCSAVE2, 210, Xtensa::EXCSAVE3, 211,
Xtensa::EXCSAVE4, 212, Xtensa::EXCSAVE5, 213,
Xtensa::EXCSAVE6, 214, Xtensa::EXCSAVE7, 215,
Xtensa::CPENABLE, 224, Xtensa::INTSET, 226,
Xtensa::CPENABLE, 224, Xtensa::INTERRUPT, 226,
Xtensa::INTCLEAR, 227, Xtensa::INTENABLE, 228,
Xtensa::PS, 230, Xtensa::VECBASE, 231,
Xtensa::EXCCAUSE, 232, Xtensa::DEBUGCAUSE, 233,
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

#include "XtensaInstrInfo.h"
#include "XtensaInstPrinter.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/MC/MCExpr.h"
Expand Down Expand Up @@ -70,6 +71,23 @@ void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) {
void XtensaInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
unsigned Opcode = MI->getOpcode();

switch (Opcode) {
case Xtensa::WSR: {
// INTERRUPT mnemonic is read-only, so use INTSET mnemonic instead
Register SR = MI->getOperand(0).getReg();
if (SR == Xtensa::INTERRUPT) {
Register Reg = MI->getOperand(1).getReg();
O << '\t' << "wsr" << '\t';
printRegName(O, Reg);
O << ", "
<< "intset";
printAnnotation(O, Annot);
return;
}
}
}
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
}
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def EXCSAVE7 : SRReg<215, "excsave7", ["EXCSAVE7", "215"]>;
def CPENABLE : SRReg<224, "cpenable", ["CPENABLE", "224"]>;

// Interrupt enable mask register
def INTSET : SRReg<226, "interrupt", ["INTERRUPT", "226"]>;
def INTERRUPT : SRReg<226, "interrupt", ["INTERRUPT", "INTSET", "226"]>;

def INTCLEAR : SRReg<227, "intclear", ["INTCLEAR", "227"]>;

Expand Down Expand Up @@ -213,8 +213,8 @@ def SR : RegisterClass<"Xtensa", [i32], 32, (add
WINDOWBASE, WINDOWSTART, IBREAKENABLE, MEMCTL, ATOMCTL, DDR, IBREAKA0, IBREAKA1,
DBREAKA0, DBREAKA1, DBREAKC0, DBREAKC1, CONFIGID0, EPC1, EPC2, EPC3, EPC4, EPC5,
EPC6, EPC7, DEPC, EPS2, EPS3, EPS4, EPS5, EPS6, EPS7, CONFIGID1, EXCSAVE1, EXCSAVE2,
EXCSAVE3, EXCSAVE4, EXCSAVE5, EXCSAVE6, EXCSAVE7, CPENABLE, INTSET, INTCLEAR, INTENABLE, PS,
VECBASE, EXCCAUSE, DEBUGCAUSE, CCOUNT, PRID, ICOUNT, ICOUNTLEVEL, EXCVADDR, CCOMPARE0,
EXCSAVE3, EXCSAVE4, EXCSAVE5, EXCSAVE6, EXCSAVE7, CPENABLE, INTERRUPT, INTCLEAR, INTENABLE,
PS, VECBASE, EXCCAUSE, DEBUGCAUSE, CCOUNT, PRID, ICOUNT, ICOUNTLEVEL, EXCVADDR, CCOMPARE0,
CCOMPARE1, CCOMPARE2, MISC0, MISC1, MISC2, MISC3)>;

//===----------------------------------------------------------------------===//
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/MC/Xtensa/xtensa-invalid-int.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: not llvm-mc -triple xtensa %s 2>&1 | FileCheck %s

.align 4
LBL0:

rsr a0, intclear
# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction

rsr a0, intset
# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction

wsr a1, interrupt
# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction

xsr a1, intset
# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction

xsr a1, interrupt
# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction
29 changes: 26 additions & 3 deletions llvm/test/MC/Xtensa/xtensa-valid-int.s
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# RUN: llvm-mc %s -triple=xtensa -mattr=+interrupt -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s


.align 4
LBL0:

Expand All @@ -12,7 +11,31 @@ LBL0:
# CHECK-INST: rsil a3, 1
# CHECK: encoding: [0x30,0x61,0x00]
rsil a3, 1


# CHECK-INST: rsr a8, interrupt
# CHECK: encoding: [0x80,0xe2,0x03]
rsr a8, interrupt

# CHECK-INST: waiti 1
# CHECK: encoding: [0x00,0x71,0x00]
waiti 1
waiti 1

# CHECK-INST: wsr a0, intclear
# CHECK: encoding: [0x00,0xe3,0x13]
wsr a0, intclear

# CHECK-INST: wsr a0, intclear
# CHECK: encoding: [0x00,0xe3,0x13]
wsr.intclear a0

# CHECK-INST: wsr a0, intset
# CHECK: encoding: [0x00,0xe2,0x13]
wsr a0, intset

# CHECK-INST: wsr a0, intset
# CHECK: encoding: [0x00,0xe2,0x13]
wsr.intset a0

# CHECK-INST: wsr a0, intset
# CHECK: encoding: [0x00,0xe2,0x13]
wsr.INTSET a0

0 comments on commit 5073a51

Please sign in to comment.