-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Xtensa] Implement Windowed Register Option. #121118
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
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-xtensa Author: Andrei Safronov (andreisfr) ChangesPatch is 25.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121118.diff 15 Files Affected:
diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index 731f9535ca251f..fc1f214efe6673 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -181,6 +181,8 @@ struct XtensaOperand : public MCParsedAsmOperand {
((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
}
+ bool isentry_imm12() const { return isImm(0, 32760); }
+
bool isUimm4() const { return isImm(0, 15); }
bool isUimm5() const { return isImm(0, 31); }
@@ -198,6 +200,11 @@ struct XtensaOperand : public MCParsedAsmOperand {
bool isImm32n_95() const { return isImm(-32, 95); }
+ bool isImm64n_4n() const {
+ return isImm(-64, -4) &&
+ ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
+ }
+
bool isB4const() const {
if (Kind != Immediate)
return false;
@@ -491,6 +498,12 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm32n_95:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [-32, 95]");
+ case Match_InvalidImm64n_4n:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range [-64, -4]");
+ case Match_InvalidImm8n_7:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range [-8, 7]");
case Match_InvalidShimm1_31:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [1, 31]");
@@ -515,6 +528,9 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [0, 60], first 2 bits "
"should be zero");
+ case Match_Invalidentry_imm12:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range [0, 32760]");
}
report_fatal_error("Unknown match type detected!");
diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index c11c4b7038bdb7..1f4197f573ce6a 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -73,7 +73,8 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}
-static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
+static const unsigned SRDecoderTable[] = {
+ Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
@@ -210,6 +211,32 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
return MCDisassembler::Success;
}
+static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm,
+ int64_t Address, const void *Decoder) {
+ assert(isUInt<4>(Imm) && "Invalid immediate");
+ if (Imm > 7)
+ Inst.addOperand(MCOperand::createImm(Imm - 16));
+ else
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
int64_t Address,
const void *Decoder) {
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index df8a0854f06f41..868c7f6c0b9c3c 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -264,6 +264,28 @@ void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
printOperand(MI, OpNum, O);
}
+void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum,
+ raw_ostream &O) {
+ if (MI->getOperand(OpNum).isImm()) {
+ int64_t Value = MI->getOperand(OpNum).getImm();
+ assert((Value >= -8 && Value <= 7) &&
+ "Invalid argument, value must be in ranges <-8,7>");
+ O << Value;
+ } else
+ printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum,
+ raw_ostream &O) {
+ if (MI->getOperand(OpNum).isImm()) {
+ int64_t Value = MI->getOperand(OpNum).getImm();
+ assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) &&
+ "Invalid argument, value must be in ranges <-64,-4>");
+ O << Value;
+ } else
+ printOperand(MI, OpNum, O);
+}
+
void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
@@ -309,6 +331,18 @@ void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,
printOperand(MI, OpNum, O);
}
+void XtensaInstPrinter::printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum,
+ raw_ostream &O) {
+ if (MI->getOperand(OpNum).isImm()) {
+ int64_t Value = MI->getOperand(OpNum).getImm();
+ assert((Value >= 0 && Value <= 32760) &&
+ "Invalid argument, value must be multiples of eight in range "
+ "<0,32760>");
+ O << Value;
+ } else
+ printOperand(MI, OpNum, O);
+}
+
void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
if (MI->getOperand(OpNum).isImm()) {
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
index e5bc67869e103d..630b4dd60108ff 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
@@ -60,10 +60,13 @@ class XtensaInstPrinter : public MCInstPrinter {
void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+ void printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+ void printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+ void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
};
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 51d4b8a9cc5fc5..e6cdd3d0020fc0 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -111,6 +111,18 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint32_t getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ uint32_t getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ uint32_t getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -405,6 +417,46 @@ XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
return Res;
}
+uint32_t
+XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ int32_t Res = static_cast<int32_t>(MO.getImm());
+
+ assert(((Res >= -8) && (Res <= 7)) && "Unexpected operand value!");
+
+ if (Res < 0)
+ return Res + 16;
+
+ return Res;
+}
+
+uint32_t
+XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ int32_t Res = static_cast<int32_t>(MO.getImm());
+
+ assert(((Res >= -64) && (Res <= -4) && ((Res & 0x3) == 0)) &&
+ "Unexpected operand value!");
+
+ return Res & 0x3f;
+}
+
+uint32_t
+XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ uint32_t res = static_cast<uint32_t>(MO.getImm());
+
+ assert(((res & 0x7) == 0) && "Unexpected operand value!");
+
+ return res;
+}
+
uint32_t
XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td
index 460a15e808b3a4..d6dedb6c760ab5 100644
--- a/llvm/lib/Target/Xtensa/Xtensa.td
+++ b/llvm/lib/Target/Xtensa/Xtensa.td
@@ -18,9 +18,15 @@ include "llvm/Target/Target.td"
// Subtarget Features.
//===----------------------------------------------------------------------===//
def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
- "Enable Density instructions">;
+ "Enable Density instructions">;
def HasDensity : Predicate<"Subtarget->hasDensity()">,
- AssemblerPredicate<(all_of FeatureDensity)>;
+ AssemblerPredicate<(all_of FeatureDensity)>;
+
+def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
+ "Enable Xtensa Windowed Register option">;
+def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
+ AssemblerPredicate<(all_of FeatureWindowed)>;
+
//===----------------------------------------------------------------------===//
// Xtensa supported processors.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 699d0d6cf80445..d09c4264dd166b 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -678,3 +678,124 @@ let isReturn = 1, isTerminator = 1,
let t = 0;
}
}
+
+//===----------------------------------------------------------------------===//
+// Windowed instructions
+//===----------------------------------------------------------------------===//
+
+def ENTRY : BRI12_Inst<0x06, 0x3, 0x0, (outs), (ins AR:$s, entry_imm12:$imm),
+ "entry\t$s, $imm", []>, Requires<[HasWindowed]> {
+ bits<15> imm;
+
+ let imm12{11-0} = imm{14-3};
+ let Defs = [SP];
+}
+
+let isCall = 1, Defs = [A0] in {
+ def CALL4 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset),
+ "call4\t$offset", []>, Requires<[HasWindowed]> {
+ let n = 1;
+ }
+
+ def CALL8 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset),
+ "call8\t$offset", []>, Requires<[HasWindowed]> {
+ let n = 2;
+ }
+
+ def CALL12 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset),
+ "call12\t$offset", []>, Requires<[HasWindowed]> {
+ let n = 3;
+ }
+
+ def CALLX4 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
+ "callx4\t$s", []>, Requires<[HasWindowed]> {
+ let m = 0x3;
+ let n = 0x1;
+ let r = 0;
+ }
+
+ def CALLX8 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
+ "callx8\t$s", []>, Requires<[HasWindowed]> {
+ let m = 0x3;
+ let n = 0x2;
+ let r = 0;
+ }
+
+ def CALLX12 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
+ "callx12\t$s", []>, Requires<[HasWindowed]> {
+ let m = 0x3;
+ let n = 0x3;
+ let r = 0;
+ }
+}
+
+def MOVSP : RRR_Inst<0x00, 0x00, 0x00, (outs AR:$t), (ins AR:$s),
+ "movsp\t$t, $s", []>, Requires<[HasWindowed]> {
+ let r = 0x01;
+}
+
+let isReturn = 1, isTerminator = 1,
+ isBarrier = 1, Uses = [A0] in {
+ def RETW_N : RRRN_Inst<0x0D, (outs), (ins),
+ "retw.n", []>, Requires<[HasWindowed, HasDensity]> {
+ let r = 0x0F;
+ let s = 0;
+ let t = 1;
+ }
+
+ def RETW : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins),
+ "retw", []>, Requires<[HasWindowed]> {
+ let m = 0x2;
+ let n = 0x1;
+ let s = 0;
+ let r = 0;
+ }
+}
+
+def : InstAlias<"_retw", (RETW)>;
+def : InstAlias<"_retw.n", (RETW_N)>;
+
+def S32E : RRI4_Inst<0x00, 0x09, (outs), (ins AR:$t, AR:$s, imm64n_4n:$imm),
+ "s32e\t$t, $s, $imm", []>, Requires<[HasWindowed]> {
+ bits<6> imm;
+
+ let r = imm{5-2};
+ let imm4 = 0x4;
+ let mayStore = 1;
+}
+
+def L32E : RRI4_Inst<0x00, 0x09, (outs), (ins AR:$t, AR:$s, imm64n_4n:$imm),
+ "l32e\t$t, $s, $imm", []>, Requires<[HasWindowed]> {
+ bits<6> imm;
+
+ let r = imm{5-2};
+ let imm4 = 0x0;
+ let mayLoad = 1;
+}
+
+def RFWU : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
+ "rfwu", []>, Requires<[HasWindowed]> {
+ bits<4> imm;
+
+ let r = 0x3;
+ let s = 0x5;
+ let t = 0x0;
+}
+
+def RFWO : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
+ "rfwo", []>, Requires<[HasWindowed]> {
+ bits<4> imm;
+
+ let r = 0x3;
+ let s = 0x4;
+ let t = 0x0;
+}
+
+def ROTW : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins imm8n_7:$imm),
+ "rotw\t$imm", []>, Requires<[HasWindowed]> {
+ bits<4> imm;
+
+ let r = 0x8;
+ let s = 0x0;
+ let t = imm{3-0};
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td
index aa72fa0a56a6f5..dd12bd23904992 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperands.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperands.td
@@ -37,6 +37,20 @@ def imm8_sh8 : Immediate<i32, [{ return Imm >= -32768 && Imm <= 32512 && ((Imm &
let DecoderMethod = "decodeImm8_sh8Operand";
}
+// imm8n_7 predicate - Immediate in the range [-8,7]
+def Imm8n_7_AsmOperand: ImmAsmOperand<"Imm8n_7">;
+def imm8n_7: Immediate<i32, [{ return Imm >= -8 && Imm <= 7; }], "Imm8n_7_AsmOperand"> {
+ let EncoderMethod = "getImm8n_7OpValue";
+ let DecoderMethod = "decodeImm8n_7Operand";
+}
+
+// imm64n_4n predicate - Immediate in the range [-64,-4]
+def Imm64n_4n_AsmOperand: ImmAsmOperand<"Imm64n_4n">;
+def imm64n_4n: Immediate<i32, [{ return Imm >= -64 && Imm <= -4; }], "Imm64n_4n_AsmOperand"> {
+ let EncoderMethod = "getImm64n_4nOpValue";
+ let DecoderMethod = "decodeImm64n_4nOperand";
+}
+
// imm12 predicate - Immediate in the range [-2048,2047]
def Imm12_AsmOperand : ImmAsmOperand<"Imm12">;
def imm12 : Immediate<i32, [{ return Imm >= -2048 && Imm <= 2047; }], "Imm12_AsmOperand"> {
@@ -117,6 +131,13 @@ def offset4m32 : Immediate<i32,
[{ return Imm >= 0 && Imm <= 60 && (Imm & 0x3 == 0); }],
"Offset4m32_AsmOperand">;
+// entry_imm12 predicate - Immediate in the range [0,32760], ENTRY parameter
+def Entry_Imm12_AsmOperand: ImmAsmOperand<"entry_imm12">;
+def entry_imm12: Immediate<i32, [{ return Imm >= 0 && Imm <= 32760 && (Imm & 0x3 == 0); }], "Entry_Imm12_AsmOperand"> {
+ let EncoderMethod = "getEntry_Imm12OpValue";
+ let DecoderMethod = "decodeEntry_Imm12OpValue";
+}
+
// b4const predicate - Branch Immediate 4-bit signed operand
def B4const_AsmOperand: ImmAsmOperand<"B4const">;
def b4const: Immediate<i32,
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index 5c07386b060cd9..09087edc86712d 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -75,4 +75,8 @@ class SRReg<bits<8> num, string n, list<string> alt = []> : XtensaReg<n> {
// Shift Amount Register
def SAR : SRReg<3, "sar", ["SAR","3"]>;
-def SR : RegisterClass<"Xtensa", [i32], 32, (add SAR)>;
+// Windowed Register Option registers
+def WINDOWBASE : SRReg<72, "windowbase", ["WINDOWBASE", "72"]>;
+def WINDOWSTART : SRReg<73, "windowstart", ["WINDOWSTART", "73"]>;
+
+def SR : RegisterClass<"Xtensa", [i32], 32, (add SAR, WINDOWBASE, WINDOWSTART)>;
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index 948dcbc5278eaa..1cdd0f9f5baf7e 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -39,6 +39,9 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
// Enabled Xtensa Density extension
bool HasDensity;
+ // Enabled Xtensa Windowed Register Option
+ bool HasWindowed;
+
XtensaSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
public:
@@ -64,6 +67,8 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
bool hasDensity() const { return HasDensity; }
+ bool hasWindowed() const { return HasWindowed; }
+
// Automatically generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
};
diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed.txt b/llvm/test/MC/Disassembler/Xtensa/windowed.txt
new file mode 100644
index 00000000000000..880a691af9ddf0
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt
@@ -0,0 +1,64 @@
+# RUN: llvm-mc -triple=xtensa -mattr=+windowed -disassemble %s | FileCheck -check-prefixes=CHECK-WINDOWED %s
+# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s
+
+#------------------------------------------------------------------------------
+# Verify that binary code is correctly disassembled with
+# code density option enabled. Also verify that dissasembling without
+# density option generates warnings.
+#------------------------------------------------------------------------------
+
+[0x36,0x03,0x01]
+# CHECK-WINDOWED: entry a3, 128
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x14,0x00]
+# CHECK-WINDOWED: movsp a3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x15,0x10,0x00]
+# CHECK-WINDOWED: call4 . +260
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x25,0x10,0x00]
+# CHECK-WINDOWED: call8 . +260
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x35,0x10,0x00]
+# CHECK-WINDOWED: call12 . +260
+# CHECK-CORE: [[#@LINE-2]]:2: w...
[truncated]
|
@@ -198,6 +200,11 @@ struct XtensaOperand : public MCParsedAsmOperand { | |||
|
|||
bool isImm32n_95() const { return isImm(-32, 95); } | |||
|
|||
bool isImm64n_4n() const { | |||
return isImm(-64, -4) && | |||
((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unchecked dyn_cast. Should be cast? But I don't understand the usage. How can "getImm" return an MCConstantExpr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for comments. I corrected code and use cast instead of dyn_cast. About "getImm", you mean that getImm should return integer value instead of MCExpr or we should rename getImm() function? Actually I used the same approach (by analogy) with "getImm" function like it is done in ARM backend(
const MCExpr *getImm() const { |
if (Imm > 7) | ||
Inst.addOperand(MCOperand::createImm(Imm - 16)); | ||
else | ||
Inst.addOperand(MCOperand::createImm(Imm)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (Imm > 7) | |
Inst.addOperand(MCOperand::createImm(Imm - 16)); | |
else | |
Inst.addOperand(MCOperand::createImm(Imm)); | |
Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
llvm/lib/Target/Xtensa/Xtensa.td
Outdated
AssemblerPredicate<(all_of FeatureDensity)>; | ||
|
||
def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true", | ||
"Enable Xtensa Windowed Register option">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this an "option". Is this terminology used in the ISA manual? This is a subtarget featur e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ISA summary refers to these extensions as options, calling this particular one "Windowed Register Option".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created special file XtensaFeatures.td for Xtensa ISA extensions/features.
@@ -39,6 +39,9 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { | |||
// Enabled Xtensa Density extension | |||
bool HasDensity; | |||
|
|||
// Enabled Xtensa Windowed Register Option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Option/Feature/?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arsenm , may I ask you for advice, what naming scheme should be used for Xtensa extensions( or options)?
Like @bugadani noted ,the Xtensa architecture have some ISA Options (in other words standard extensions) in documentation. It is differs a bit from for example RISCV terminology and other architectures, the documentation for RISCV architecture usually use "ISA extension" phrase is such cases. The Xtensa architecture allows to define user specific ISA and such case it is named TIE extensions (TIE language).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LLVM concept you are using is a "subtarget feature".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed "Xtensa Density extension" to "Xtensa Density Option".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like you only implement the MC support (and no codegen support) for windowed registers, could you put that in either your title and/or description?
# code density option enabled. Also verify that dissasembling without | ||
# density option generates warnings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# code density option enabled. Also verify that dissasembling without | |
# density option generates warnings. | |
# windowed register option enabled. Also verify that dissasembling without | |
# windowed register option generates warnings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for comment. Fixed.
# code density option enabled. Also verify that dissasembling without | ||
# density option generates warnings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# code density option enabled. Also verify that dissasembling without | |
# density option generates warnings. | |
# code density and windowed register options enabled. Also verify that dissasembling without | |
# these options generates warnings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxied.
@@ -117,6 +131,13 @@ def offset4m32 : Immediate<i32, | |||
[{ return Imm >= 0 && Imm <= 60 && (Imm & 0x3 == 0); }], | |||
"Offset4m32_AsmOperand">; | |||
|
|||
// entry_imm12 predicate - Immediate in the range [0,32760], ENTRY parameter | |||
def Entry_Imm12_AsmOperand: ImmAsmOperand<"entry_imm12">; | |||
def entry_imm12: Immediate<i32, [{ return Imm >= 0 && Imm <= 32760 && (Imm & 0x3 == 0); }], "Entry_Imm12_AsmOperand"> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def entry_imm12: Immediate<i32, [{ return Imm >= 0 && Imm <= 32760 && (Imm & 0x3 == 0); }], "Entry_Imm12_AsmOperand"> { | |
def entry_imm12: Immediate<i32, [{ return Imm >= 0 && Imm <= 32760 && (Imm & 0x7 == 0); }], "Entry_Imm12_AsmOperand"> { |
I believe the mask should be 7 instead of 3 (but even better would be % 8 == 0
if that is supported).
The stack frame size is specified as the 12-bit unsigned imm12 field in units of eight bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
# Out of range immediates | ||
|
||
# entry_imm12 | ||
entry a3, -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please test a positive parameter that is not divisible by 8 - may be 4 to catch the issue in my other comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added more tests for "entry" instruction.
@@ -826,6 +855,22 @@ ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { | |||
return ParseStatus::NoMatch; | |||
} | |||
|
|||
// Verify Special Register | |||
bool XtensaAsmParser::checkRegister(MCRegister RegNo) { | |||
bool Res = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be rewritten with a simpler expression without any conditional assign and break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote the function code.
@@ -73,17 +73,42 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, | |||
return MCDisassembler::Success; | |||
} | |||
|
|||
static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3}; | |||
// Verify SR | |||
bool CheckRegister(unsigned RegNo, MCSubtargetInfo STI) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, also this is the same function? Also should start with lowercase, and not pass MCSubtargetInfo by value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote the function code and name. This function is almost the same as "checkRegister" in asm parser. I plan to make version asm parser more complex (then disassembler version) in future commits (probably it will require additional arguments). Am I understand correctly that your suggestion is to create single variant of this function in XtensaUtils.*?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arsenm , I placed "checkRegister" function to the "XtensaUtils.cpp" in new commit. Could you please take a look?
This reverts commit 0dcb16e.
…3913) Reverts llvm/llvm-project#121118 for causing #123817
if (RegNo > 255) | ||
return MCDisassembler::Fail; | ||
|
||
for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) { | ||
if (SRDecoderTable[i + 1] == RegNo) { | ||
unsigned Reg = SRDecoderTable[i]; | ||
|
||
if (!checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XtensaDisassembler cannot use functions defined in XtensaCodeGen (Xtensa/CMakeFiles.txt).
After #123969 , you can place checkRegister in MCTargetDesc/
For CMake changes, best to check both BUILD_SHARED_LIBS=on and off builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much!
This patch implements Xtensa ISA option "Windowed Register Option". It implements subtarget feature, instructions descriptions and support of these instruction in asm parser and disassembler. This is the second version of the Windowed Register Option implementation. Previous implementation llvm#121118. In this variant "checkRegister" function placed in XtensaMCTargetDesc.
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.
No description provided.