Skip to content
51 changes: 32 additions & 19 deletions llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ using namespace llvm;
struct XtensaOperand;

class XtensaAsmParser : public MCTargetAsmParser {
const MCRegisterInfo &MRI;

enum XtensaRegisterType { Xtensa_Generic, Xtensa_SR, Xtensa_UR };
SMLoc getLoc() const { return getParser().getTok().getLoc(); }

XtensaTargetStreamer &getTargetStreamer() {
Expand Down Expand Up @@ -64,11 +66,12 @@ class XtensaAsmParser : public MCTargetAsmParser {
ParseStatus parseImmediate(OperandVector &Operands);
ParseStatus
parseRegister(OperandVector &Operands, bool AllowParens = false,
bool SR = false,
XtensaRegisterType SR = Xtensa_Generic,
Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
ParseStatus parseOperandWithModifier(OperandVector &Operands);
bool
parseOperand(OperandVector &Operands, StringRef Mnemonic, bool SR = false,
parseOperand(OperandVector &Operands, StringRef Mnemonic,
XtensaRegisterType SR = Xtensa_Generic,
Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands);
Expand All @@ -90,7 +93,8 @@ class XtensaAsmParser : public MCTargetAsmParser {

XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
: MCTargetAsmParser(Options, STI, MII) {
: MCTargetAsmParser(Options, STI, MII),
MRI(*Parser.getContext().getRegisterInfo()) {
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}

Expand Down Expand Up @@ -583,7 +587,8 @@ bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
}

ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
bool AllowParens, bool SR,
bool AllowParens,
XtensaRegisterType RegType,
Xtensa::RegisterAccessType RAType) {
SMLoc FirstS = getLoc();
bool HadParens = false;
Expand All @@ -594,25 +599,32 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
if (AllowParens && getLexer().is(AsmToken::LParen)) {
size_t ReadCount = getLexer().peekTokens(Buf);
if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))
if (Buf[0].getKind() == AsmToken::Integer && RegType == Xtensa_Generic)
return ParseStatus::NoMatch;
HadParens = true;
getParser().Lex(); // Eat '('
}
}

unsigned RegNo = 0;
MCRegister RegNo = 0;

switch (getLexer().getKind()) {
default:
return ParseStatus::NoMatch;
case AsmToken::Integer:
if (!SR)
if (RegType == Xtensa_Generic)
return ParseStatus::NoMatch;
RegName = getLexer().getTok().getString();
RegNo = MatchRegisterName(RegName);
if (RegNo == 0)

// Parse case when we expect UR register code as special case,
// because SR and UR registers may have the same number
// and such situation may lead to confilct
if (RegType == Xtensa_UR) {
int64_t RegCode = getLexer().getTok().getIntVal();
RegNo = Xtensa::getUserRegister(RegCode, MRI);
} else {
RegName = getLexer().getTok().getString();
RegNo = MatchRegisterAltName(RegName);
}
break;
case AsmToken::Identifier:
RegName = getLexer().getTok().getIdentifier();
Expand Down Expand Up @@ -689,7 +701,8 @@ ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
/// from this information, adding to Operands.
/// If operand was parsed, returns false, else true.
bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
bool SR, Xtensa::RegisterAccessType RAType) {
XtensaRegisterType RegType,
Xtensa::RegisterAccessType RAType) {
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
Expand All @@ -703,7 +716,7 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
return true;

// Attempt to parse token as register
if (parseRegister(Operands, true, SR, RAType).isSuccess())
if (parseRegister(Operands, true, RegType, RAType).isSuccess())
return false;

// Attempt to parse token as an immediate
Expand All @@ -722,11 +735,9 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
: (Name[0] == 'r' ? Xtensa::REGISTER_READ
: Xtensa::REGISTER_EXCHANGE);

if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||
Name.starts_with("xsr.")) &&
(Name.size() > 4)) {
// Parse case when instruction name is concatenated with SR register
// name, like "wsr.sar a1"
if ((Name.size() > 4) && Name[3] == '.') {
// Parse case when instruction name is concatenated with SR/UR register
// name, like "wsr.sar a1" or "wur.fcr a1"

// First operand is token for instruction
Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
Expand Down Expand Up @@ -762,7 +773,8 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
}

// Parse second operand
if (parseOperand(Operands, Name, true, RAType))
if (parseOperand(Operands, Name, Name[1] == 's' ? Xtensa_SR : Xtensa_UR,
RAType))
return true;
}

Expand All @@ -780,7 +792,8 @@ bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
Name.starts_with("xsr")) {
Name.starts_with("xsr") || Name.starts_with("rur") ||
Name.starts_with("wur")) {
return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
}

Expand Down
61 changes: 41 additions & 20 deletions llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,42 +73,68 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}

static const MCPhysReg MRDecoderTable[] = {Xtensa::M0, Xtensa::M1, Xtensa::M2,
Xtensa::M3};

static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= std::size(MRDecoderTable))
if (RegNo > 3)
return MCDisassembler::Fail;

MCPhysReg Reg = MRDecoderTable[RegNo];
MCPhysReg Reg = Xtensa::M0 + RegNo;
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

static const MCPhysReg MR01DecoderTable[] = {Xtensa::M0, Xtensa::M1};

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

MCPhysReg Reg = MR01DecoderTable[RegNo];
MCPhysReg Reg = Xtensa::M0 + RegNo;
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

static const MCPhysReg MR23DecoderTable[] = {Xtensa::M2, Xtensa::M3};

static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo != 0 && RegNo != 1)
if (RegNo > 1)
return MCDisassembler::Fail;

MCPhysReg Reg = Xtensa::M2 + RegNo;
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

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

MCPhysReg Reg = Xtensa::F0 + RegNo;
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

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

Xtensa::RegisterAccessType RAType = Inst.getOpcode() == Xtensa::WUR
? Xtensa::REGISTER_WRITE
: Xtensa::REGISTER_READ;

const XtensaDisassembler *Dis =
static_cast<const XtensaDisassembler *>(Decoder);
const MCRegisterInfo *MRI = Dis->getContext().getRegisterInfo();
MCPhysReg Reg = Xtensa::getUserRegister(RegNo, *MRI);
if (!Xtensa::checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits(),
RAType))
return MCDisassembler::Fail;

MCPhysReg Reg = MR23DecoderTable[RegNo];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
Expand Down Expand Up @@ -187,18 +213,13 @@ static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Fail;
}

const MCPhysReg BRDecoderTable[] = {
Xtensa::B0, Xtensa::B1, Xtensa::B2, Xtensa::B3, Xtensa::B4, Xtensa::B5,
Xtensa::B6, Xtensa::B7, Xtensa::B8, Xtensa::B9, Xtensa::B10, Xtensa::B11,
Xtensa::B12, Xtensa::B13, Xtensa::B14, Xtensa::B15};

static DecodeStatus DecodeBRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= std::size(BRDecoderTable))
if (RegNo > 15)
return MCDisassembler::Fail;

MCPhysReg Reg = BRDecoderTable[RegNo];
MCPhysReg Reg = Xtensa::B0 + RegNo;
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
case Xtensa::L32I:
case Xtensa::S32I_N:
case Xtensa::L32I_N:
case Xtensa::SSI:
case Xtensa::SSIP:
case Xtensa::LSI:
case Xtensa::LSIP:

if (Res & 0x3) {
report_fatal_error("Unexpected operand value!");
}
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID];
case Xtensa::VECBASE:
return FeatureBits[Xtensa::FeatureRelocatableVector];
case Xtensa::FCR:
case Xtensa::FSR:
return FeatureBits[FeatureSingleFloat];
case Xtensa::WINDOWBASE:
case Xtensa::WINDOWSTART:
return FeatureBits[Xtensa::FeatureWindowed];
Expand All @@ -198,6 +201,16 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
return true;
}

// Get Xtensa User Register by encoding value.
MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
if (MRI.getEncodingValue(Xtensa::FCR) == Code) {
return Xtensa::FCR;
} else if (MRI.getEncodingValue(Xtensa::FSR) == Code) {
return Xtensa::FSR;
}
return Xtensa::NoRegister;
}

static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options) {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ enum RegisterAccessType {
// Verify if it's correct to use a special register.
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
RegisterAccessType RA);

// Get Xtensa User Register by register encoding value.
MCRegister getUserRegister(unsigned Code, const MCRegisterInfo &MRI);
} // namespace Xtensa
} // end namespace llvm

Expand Down
33 changes: 18 additions & 15 deletions llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,25 @@ void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {

void XtensaAsmPrinter::emitMachineConstantPoolValue(
MachineConstantPoolValue *MCPV) {
XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
XtensaConstantPoolValue *XtensaCPV =
static_cast<XtensaConstantPoolValue *>(MCPV);
MCSymbol *MCSym;

if (ACPV->isBlockAddress()) {
if (XtensaCPV->isBlockAddress()) {
const BlockAddress *BA =
cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
cast<XtensaConstantPoolConstant>(XtensaCPV)->getBlockAddress();
MCSym = GetBlockAddressSymbol(BA);
} else if (ACPV->isMachineBasicBlock()) {
const MachineBasicBlock *MBB = cast<XtensaConstantPoolMBB>(ACPV)->getMBB();
} else if (XtensaCPV->isMachineBasicBlock()) {
const MachineBasicBlock *MBB =
cast<XtensaConstantPoolMBB>(XtensaCPV)->getMBB();
MCSym = MBB->getSymbol();
} else if (ACPV->isJumpTable()) {
unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
} else if (XtensaCPV->isJumpTable()) {
unsigned Idx = cast<XtensaConstantPoolJumpTable>(XtensaCPV)->getIndex();
MCSym = this->GetJTISymbol(Idx, false);
} else {
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
assert(XtensaCPV->isExtSymbol() && "unrecognized constant pool value");
XtensaConstantPoolSymbol *XtensaSym =
cast<XtensaConstantPoolSymbol>(XtensaCPV);
const char *SymName = XtensaSym->getSymbol();

if (XtensaSym->isPrivateLinkage()) {
Expand All @@ -89,14 +92,14 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
}
}

MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
MCSymbol *LblSym = GetCPISymbol(XtensaCPV->getLabelId());
auto *TS =
static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
auto Spec = getModifierSpecifier(ACPV->getModifier());
auto Spec = getModifierSpecifier(XtensaCPV->getModifier());

if (ACPV->getModifier() != XtensaCP::no_modifier) {
if (XtensaCPV->getModifier() != XtensaCP::no_modifier) {
std::string SymName(MCSym->getName());
StringRef Modifier = ACPV->getModifierText();
StringRef Modifier = XtensaCPV->getModifierText();
SymName += Modifier;
MCSym = OutContext.getOrCreateSymbol(SymName);
}
Expand All @@ -108,9 +111,9 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
void XtensaAsmPrinter::emitMachineConstantPoolEntry(
const MachineConstantPoolEntry &CPE, int i) {
if (CPE.isMachineConstantPoolEntry()) {
XtensaConstantPoolValue *ACPV =
XtensaConstantPoolValue *XtensaCPV =
static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal);
ACPV->setLabelId(i);
XtensaCPV->setLabelId(i);
emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
} else {
MCSymbol *LblSym = GetCPISymbol(i);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/Xtensa/XtensaCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
def RetCC_Xtensa : CallingConv<[
// First two return values go in a2, a3, a4, a5
CCIfType<[i32], CCAssignToReg<[A2, A3, A4, A5]>>,
CCIfType<[f32], CCAssignToReg<[A2, A3, A4, A5]>>,
CCIfType<[i64], CCAssignToRegWithShadow<[A2, A4], [A3, A5]>>
]>;

Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
def HasDensity : Predicate<"Subtarget->hasDensity()">,
AssemblerPredicate<(all_of FeatureDensity)>;

def FeatureSingleFloat : SubtargetFeature<"fp", "HasSingleFloat", "true",
"Enable Xtensa Single FP instructions">;
def HasSingleFloat : Predicate<"Subtarget->hasSingleFloat()">,
AssemblerPredicate<(all_of FeatureSingleFloat)>;

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