[llvm] [Xtensa] Implement Windowed Register Option. (PR #121118)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 29 07:03:07 PST 2024
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/121118
>From bb3de6f2aebb098189232c62c6b5619d75058f63 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 26 Dec 2024 02:19:15 +0300
Subject: [PATCH 1/2] [Xtensa] Implement Windowed Register Option.
---
.../Xtensa/AsmParser/XtensaAsmParser.cpp | 16 +++
.../Disassembler/XtensaDisassembler.cpp | 29 ++++-
.../Xtensa/MCTargetDesc/XtensaInstPrinter.cpp | 34 +++++
.../Xtensa/MCTargetDesc/XtensaInstPrinter.h | 3 +
.../MCTargetDesc/XtensaMCCodeEmitter.cpp | 52 ++++++++
llvm/lib/Target/Xtensa/Xtensa.td | 10 +-
llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 121 ++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaOperands.td | 21 +++
llvm/lib/Target/Xtensa/XtensaRegisterInfo.td | 6 +-
llvm/lib/Target/Xtensa/XtensaSubtarget.h | 5 +
llvm/test/MC/Disassembler/Xtensa/windowed.txt | 64 +++++++++
.../Xtensa/windowed_code_density.txt | 12 ++
llvm/test/MC/Xtensa/windowed.s | 80 ++++++++++++
llvm/test/MC/Xtensa/windowed_code_density.s | 14 ++
llvm/test/MC/Xtensa/windowed_invalid.s | 15 +++
15 files changed, 478 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/MC/Disassembler/Xtensa/windowed.txt
create mode 100644 llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
create mode 100644 llvm/test/MC/Xtensa/windowed.s
create mode 100644 llvm/test/MC/Xtensa/windowed_code_density.s
create mode 100644 llvm/test/MC/Xtensa/windowed_invalid.s
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: warning: invalid instruction encoding
+
+[0xd0,0x03,0x00]
+# CHECK-WINDOWED: callx4 a3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xe0,0x03,0x00]
+# CHECK-WINDOWED: callx8 a3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xf0,0x03,0x00]
+# CHECK-WINDOWED: callx12 a3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x90,0x00,0x00]
+# CHECK-WINDOWED: retw
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x20,0x80,0x40]
+# CHECK-WINDOWED: rotw 2
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0xd4,0x09]
+# CHECK-WINDOWED: l32e a3, a4, -12
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0xd4,0x49]
+# CHECK-WINDOWED: s32e a3, a4, -12
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x00,0x34,0x00]
+# CHECK-WINDOWED: rfwo
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x00,0x35,0x00]
+# CHECK-WINDOWED: rfwu
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
new file mode 100644
index 00000000000000..376677595ac3d1
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
@@ -0,0 +1,12 @@
+# RUN: llvm-mc -triple=xtensa -mattr=+windowed,+density -disassemble %s | FileCheck -check-prefixes=CHECK-WINDOWED-DENSITY %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.
+#------------------------------------------------------------------------------
+
+[0x1d,0xf0]
+# CHECK-WINDOWED-DENSITY: retw.n
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
diff --git a/llvm/test/MC/Xtensa/windowed.s b/llvm/test/MC/Xtensa/windowed.s
new file mode 100644
index 00000000000000..38e36b225723a6
--- /dev/null
+++ b/llvm/test/MC/Xtensa/windowed.s
@@ -0,0 +1,80 @@
+# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+windowed \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align 4
+LBL0:
+
+# Instruction format BRI12
+# CHECK-INST: entry a3, 128
+# CHECK: encoding: [0x36,0x03,0x01]
+entry a3, 128
+
+# Instruction format RRR
+# CHECK-INST: movsp a3, a4
+# CHECK: encoding: [0x30,0x14,0x00]
+movsp a3, a4
+
+# Instruction format CALL
+# CHECK-INST: call4 LBL0
+# CHECK: encoding: [0bAA010101,A,A]
+call4 LBL0
+
+# Instruction format CALL
+# CHECK-INST: call8 LBL0
+# CHECK: encoding: [0bAA100101,A,A]
+call8 LBL0
+
+# Instruction format CALL
+# CHECK-INST: call12 LBL0
+# CHECK: encoding: [0bAA110101,A,A]
+call12 LBL0
+
+# Instruction format CALLX
+# CHECK-INST: callx4 a3
+# CHECK: encoding: [0xd0,0x03,0x00]
+callx4 a3
+
+# Instruction format CALLX
+# CHECK-INST: callx8 a3
+# CHECK: encoding: [0xe0,0x03,0x00]
+callx8 a3
+
+# Instruction format CALLX
+# CHECK-INST: callx12 a3
+# CHECK: encoding: [0xf0,0x03,0x00]
+callx12 a3
+
+# Instruction format CALLX
+# CHECK-INST: retw
+# CHECK: encoding: [0x90,0x00,0x00]
+retw
+
+# Instruction format CALLX
+# CHECK-INST: retw
+# CHECK: encoding: [0x90,0x00,0x00]
+_retw
+
+# Instruction format RRR
+# CHECK-INST: rotw 2
+# CHECK: encoding: [0x20,0x80,0x40]
+rotw 2
+
+# Instruction format RRI4
+# CHECK-INST: l32e a3, a4, -12
+# CHECK: encoding: [0x30,0xd4,0x09]
+l32e a3, a4, -12
+
+# Instruction format RRI4
+# CHECK-INST: s32e a3, a4, -12
+# CHECK: encoding: [0x30,0xd4,0x49]
+s32e a3, a4, -12
+
+# Instruction format RRR
+# CHECK-INST: rfwo
+# CHECK: encoding: [0x00,0x34,0x00]
+rfwo
+
+# Instruction format RRR
+# CHECK-INST: rfwu
+# CHECK: encoding: [0x00,0x35,0x00]
+rfwu
diff --git a/llvm/test/MC/Xtensa/windowed_code_density.s b/llvm/test/MC/Xtensa/windowed_code_density.s
new file mode 100644
index 00000000000000..e532657466fba5
--- /dev/null
+++ b/llvm/test/MC/Xtensa/windowed_code_density.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+windowed,+density \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align 4
+
+# Instruction format RRRN
+# CHECK-INST: retw.n
+# CHECK: encoding: [0x1d,0xf0]
+retw.n
+
+# Instruction format RRRN
+# CHECK-INST: retw.n
+# CHECK: encoding: [0x1d,0xf0]
+_retw.n
diff --git a/llvm/test/MC/Xtensa/windowed_invalid.s b/llvm/test/MC/Xtensa/windowed_invalid.s
new file mode 100644
index 00000000000000..169096b09caba9
--- /dev/null
+++ b/llvm/test/MC/Xtensa/windowed_invalid.s
@@ -0,0 +1,15 @@
+# RUN: not llvm-mc -triple xtensa --mattr=+windowed %s 2>&1 | FileCheck %s
+
+# Out of range immediates
+
+# entry_imm12
+entry a3, -1
+# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760]
+
+# imm8n_7
+rotw 100
+# CHECK: :[[#@LINE-1]]:6: error: expected immediate in range [-8, 7]
+
+# imm64n_4n
+l32e a3, a4, -100
+# CHECK: :[[#@LINE-1]]:14: error: expected immediate in range [-64, -4]
>From d36e6d20dc30e0d6fff5ea689525da5b2acea111 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Sun, 29 Dec 2024 17:54:50 +0300
Subject: [PATCH 2/2] [Xtensa] Fix Windowed Option tests and AsmParser.
---
.../Xtensa/AsmParser/XtensaAsmParser.cpp | 37 ++++++++++++--
.../Disassembler/XtensaDisassembler.cpp | 29 +++++++++--
llvm/lib/Target/Xtensa/Xtensa.td | 11 +----
llvm/lib/Target/Xtensa/XtensaFeatures.td | 14 ++++++
llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 48 ++++++-------------
llvm/lib/Target/Xtensa/XtensaOperands.td | 2 +-
llvm/test/MC/Disassembler/Xtensa/windowed.txt | 12 ++++-
.../Xtensa/windowed_code_density.txt | 6 +--
llvm/test/MC/Xtensa/windowed.s | 25 ++++++++++
llvm/test/MC/Xtensa/windowed_invalid.s | 10 +++-
10 files changed, 136 insertions(+), 58 deletions(-)
create mode 100644 llvm/lib/Target/Xtensa/XtensaFeatures.td
diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index fc1f214efe6673..fc8140aeb7ead8 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -73,6 +73,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
SMLoc &EndLoc) override {
return ParseStatus::NoMatch;
}
+ bool checkRegister(MCRegister RegNo);
ParseStatus parsePCRelTarget(OperandVector &Operands);
bool parseLiteralDirective(SMLoc L);
@@ -89,6 +90,10 @@ class XtensaAsmParser : public MCTargetAsmParser {
: MCTargetAsmParser(Options, STI, MII) {
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
+
+ bool hasWindowed() const {
+ return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];
+ };
};
// Return true if Expr is in the range [MinValue, MaxValue].
@@ -181,7 +186,10 @@ struct XtensaOperand : public MCParsedAsmOperand {
((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
}
- bool isentry_imm12() const { return isImm(0, 32760); }
+ bool isentry_imm12() const {
+ return isImm(0, 32760) &&
+ ((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
+ }
bool isUimm4() const { return isImm(0, 15); }
@@ -202,7 +210,7 @@ struct XtensaOperand : public MCParsedAsmOperand {
bool isImm64n_4n() const {
return isImm(-64, -4) &&
- ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
+ ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
}
bool isB4const() const {
@@ -530,7 +538,8 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
"should be zero");
case Match_Invalidentry_imm12:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected immediate in range [0, 32760]");
+ "expected immediate in range [0, 32760], first 3 bits "
+ "should be zero");
}
report_fatal_error("Unknown match type detected!");
@@ -617,6 +626,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
getLexer().UnLex(Buf[0]);
return ParseStatus::NoMatch;
}
+
+ if (!checkRegister(RegNo))
+ return ParseStatus::NoMatch;
+
if (HadParens)
Operands.push_back(XtensaOperand::createToken("(", FirstS));
SMLoc S = getLoc();
@@ -718,7 +731,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
if (RegNo == 0)
RegNo = MatchRegisterAltName(RegName);
- if (RegNo == 0)
+ if (!checkRegister(RegNo))
return Error(NameLoc, "invalid register name");
// Parse operand
@@ -842,6 +855,22 @@ ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {
return ParseStatus::NoMatch;
}
+// Verify Special Register
+bool XtensaAsmParser::checkRegister(MCRegister RegNo) {
+ bool Res = true;
+
+ switch (RegNo) {
+ case Xtensa::WINDOWBASE:
+ case Xtensa::WINDOWSTART:
+ Res = hasWindowed();
+ break;
+ case Xtensa::NoRegister:
+ Res = false;
+ }
+
+ return Res;
+}
+
// Force static initialization.
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index 1f4197f573ce6a..0cab74e104f6d5 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -73,18 +73,42 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}
+// Verify SR
+bool CheckRegister(unsigned RegNo, MCSubtargetInfo STI) {
+ bool Res = true;
+
+ switch (RegNo) {
+ case Xtensa::WINDOWBASE:
+ case Xtensa::WINDOWSTART:
+ Res = STI.getFeatureBits()[Xtensa::FeatureWindowed];
+ break;
+ default:
+ Res = false;
+ break;
+ }
+
+ return Res;
+}
+
static const unsigned SRDecoderTable[] = {
Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
+ const llvm::MCSubtargetInfo STI =
+ ((const MCDisassembler *)Decoder)->getSubtargetInfo();
+
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, STI))
+ return MCDisassembler::Fail;
+
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
@@ -214,10 +238,7 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
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));
+ Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
return MCDisassembler::Success;
}
diff --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td
index d6dedb6c760ab5..2c4bacbe8282b0 100644
--- a/llvm/lib/Target/Xtensa/Xtensa.td
+++ b/llvm/lib/Target/Xtensa/Xtensa.td
@@ -17,15 +17,8 @@ include "llvm/Target/Target.td"
//===----------------------------------------------------------------------===//
// Subtarget Features.
//===----------------------------------------------------------------------===//
-def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
- "Enable Density instructions">;
-def HasDensity : Predicate<"Subtarget->hasDensity()">,
- AssemblerPredicate<(all_of FeatureDensity)>;
-
-def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
- "Enable Xtensa Windowed Register option">;
-def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
- AssemblerPredicate<(all_of FeatureWindowed)>;
+
+include "XtensaFeatures.td"
//===----------------------------------------------------------------------===//
// Xtensa supported processors.
diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
new file mode 100644
index 00000000000000..6f24a674ae0ce2
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -0,0 +1,14 @@
+//===----------------------------------------------------------------------===//
+// Xtensa subtarget features.
+//===----------------------------------------------------------------------===//
+
+// Xtensa ISA extensions (Xtensa Options).
+def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
+ "Enable Density instructions">;
+def HasDensity : Predicate<"Subtarget->hasDensity()">,
+ AssemblerPredicate<(all_of FeatureDensity)>;
+
+def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
+ "Enable Xtensa Windowed Register option">;
+def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
+ AssemblerPredicate<(all_of FeatureWindowed)>;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index d09c4264dd166b..5ef795a0e5287a 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -692,40 +692,20 @@ def ENTRY : BRI12_Inst<0x06, 0x3, 0x0, (outs), (ins AR:$s, entry_imm12:$imm),
}
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;
+ foreach i = {1,2,3} in {
+ defvar I = !mul(4, i);
+
+ def CALL#I# : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset),
+ "call"#I#"\t$offset", []>, Requires<[HasWindowed]> {
+ let n = i;
+ }
+
+ def CALLX#I# : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
+ "callx"#I#"\t$s", []>, Requires<[HasWindowed]> {
+ let m = 0x3;
+ let n = i;
+ let r = 0;
+ }
}
}
diff --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td
index dd12bd23904992..402e05a5c3dd1d 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperands.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperands.td
@@ -133,7 +133,7 @@ def offset4m32 : Immediate<i32,
// 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"> {
+def entry_imm12: Immediate<i32, [{ return Imm >= 0 && Imm <= 32760 && (Imm % 8 == 0); }], "Entry_Imm12_AsmOperand"> {
let EncoderMethod = "getEntry_Imm12OpValue";
let DecoderMethod = "decodeEntry_Imm12OpValue";
}
diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed.txt b/llvm/test/MC/Disassembler/Xtensa/windowed.txt
index 880a691af9ddf0..69f588efd73de6 100644
--- a/llvm/test/MC/Disassembler/Xtensa/windowed.txt
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt
@@ -3,8 +3,8 @@
#------------------------------------------------------------------------------
# Verify that binary code is correctly disassembled with
-# 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.
#------------------------------------------------------------------------------
[0x36,0x03,0x01]
@@ -62,3 +62,11 @@
[0x00,0x35,0x00]
# CHECK-WINDOWED: rfwu
# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x48,0x61]
+# CHECK-WINDOWED: xsr a3, windowbase
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x49,0x61]
+# CHECK-WINDOWED: xsr a3, windowstart
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
index 376677595ac3d1..1b8c87e643f5d3 100644
--- a/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
@@ -2,9 +2,9 @@
# 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.
+# Verify that binary code is correctly disassembled with windowed register
+# and code density options enabled. Also verify that
+# dissasembling without these options generates warnings.
#------------------------------------------------------------------------------
[0x1d,0xf0]
diff --git a/llvm/test/MC/Xtensa/windowed.s b/llvm/test/MC/Xtensa/windowed.s
index 38e36b225723a6..3376469e3085b8 100644
--- a/llvm/test/MC/Xtensa/windowed.s
+++ b/llvm/test/MC/Xtensa/windowed.s
@@ -78,3 +78,28 @@ rfwo
# CHECK-INST: rfwu
# CHECK: encoding: [0x00,0x35,0x00]
rfwu
+
+# Instruction format RSR
+# CHECK-INST: xsr a3, windowbase
+# CHECK: # encoding: [0x30,0x48,0x61]
+xsr a3, windowbase
+
+# CHECK-INST: xsr a3, windowbase
+# CHECK: # encoding: [0x30,0x48,0x61]
+xsr.windowbase a3
+
+# CHECK-INST: xsr a3, windowbase
+# CHECK: # encoding: [0x30,0x48,0x61]
+xsr a3, 72
+
+# CHECK-INST: xsr a3, windowstart
+# CHECK: # encoding: [0x30,0x49,0x61]
+xsr a3, windowstart
+
+# CHECK-INST: xsr a3, windowstart
+# CHECK: # encoding: [0x30,0x49,0x61]
+xsr.windowstart a3
+
+# CHECK-INST: xsr a3, windowstart
+# CHECK: # encoding: [0x30,0x49,0x61]
+xsr a3, 73
diff --git a/llvm/test/MC/Xtensa/windowed_invalid.s b/llvm/test/MC/Xtensa/windowed_invalid.s
index 169096b09caba9..d2d59e11576052 100644
--- a/llvm/test/MC/Xtensa/windowed_invalid.s
+++ b/llvm/test/MC/Xtensa/windowed_invalid.s
@@ -4,7 +4,15 @@
# entry_imm12
entry a3, -1
-# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760]
+# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero
+
+# entry_imm12
+entry a3, 32764
+# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero
+
+# entry_imm12
+entry a3, 4
+# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero
# imm8n_7
rotw 100
More information about the llvm-commits
mailing list