Skip to content

[Xtensa] Implement Xtensa Floating Point Option. #136086

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
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
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