[llvm] f6578c3 - [Xtensa] Implement Windowed Register Option. (#124656)

via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 2 16:13:28 PST 2025


Author: Andrei Safronov
Date: 2025-02-03T03:13:24+03:00
New Revision: f6578c3d809b22d08524c3ae017c843f478d67e6

URL: https://github.com/llvm/llvm-project/commit/f6578c3d809b22d08524c3ae017c843f478d67e6
DIFF: https://github.com/llvm/llvm-project/commit/f6578c3d809b22d08524c3ae017c843f478d67e6.diff

LOG: [Xtensa] Implement Windowed Register Option. (#124656)

 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.

Added: 
    llvm/lib/Target/Xtensa/XtensaFeatures.td
    llvm/test/MC/Disassembler/Xtensa/windowed.txt
    llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
    llvm/test/MC/Xtensa/windowed.s
    llvm/test/MC/Xtensa/windowed_code_density.s
    llvm/test/MC/Xtensa/windowed_invalid.s

Modified: 
    llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
    llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
    llvm/lib/Target/Xtensa/Xtensa.td
    llvm/lib/Target/Xtensa/XtensaInstrInfo.td
    llvm/lib/Target/Xtensa/XtensaOperands.td
    llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
    llvm/lib/Target/Xtensa/XtensaSubtarget.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index 731f9535ca251f2..0c9258ecd65ecb4 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;
   }
+
   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,6 +186,11 @@ struct XtensaOperand : public MCParsedAsmOperand {
            ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
   }
 
+  bool isentry_imm12() const {
+    return isImm(0, 32760) &&
+           ((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
+  }
+
   bool isUimm4() const { return isImm(0, 15); }
 
   bool isUimm5() const { return isImm(0, 31); }
@@ -198,6 +208,11 @@ struct XtensaOperand : public MCParsedAsmOperand {
 
   bool isImm32n_95() const { return isImm(-32, 95); }
 
+  bool isImm64n_4n() const {
+    return isImm(-64, -4) &&
+           ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
+  }
+
   bool isB4const() const {
     if (Kind != Immediate)
       return false;
@@ -491,6 +506,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 +536,10 @@ 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], first 3 bits "
+                 "should be zero");
   }
 
   report_fatal_error("Unknown match type detected!");
@@ -601,6 +626,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
       getLexer().UnLex(Buf[0]);
     return ParseStatus::NoMatch;
   }
+
+  if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
+    return ParseStatus::NoMatch;
+
   if (HadParens)
     Operands.push_back(XtensaOperand::createToken("(", FirstS));
   SMLoc S = getLoc();
@@ -702,7 +731,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
     if (RegNo == 0)
       RegNo = MatchRegisterAltName(RegName);
 
-    if (RegNo == 0)
+    if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits()))
       return Error(NameLoc, "invalid register name");
 
     // Parse operand

diff  --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index c11c4b7038bdb7f..7ad8a87ed599ae1 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -57,7 +57,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {
                                          createXtensaDisassembler);
 }
 
-static const unsigned ARDecoderTable[] = {
+const unsigned ARDecoderTable[] = {
     Xtensa::A0,  Xtensa::SP,  Xtensa::A2,  Xtensa::A3, Xtensa::A4,  Xtensa::A5,
     Xtensa::A6,  Xtensa::A7,  Xtensa::A8,  Xtensa::A9, Xtensa::A10, Xtensa::A11,
     Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
@@ -73,17 +73,23 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Success;
 }
 
-static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
+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 MCDisassembler *Decoder) {
   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 (!Xtensa::checkRegister(Reg,
+                                 Decoder->getSubtargetInfo().getFeatureBits()))
+        return MCDisassembler::Fail;
+
       Inst.addOperand(MCOperand::createReg(Reg));
       return MCDisassembler::Success;
     }
@@ -210,6 +216,29 @@ 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");
+  Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : 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 df8a0854f06f41b..868c7f6c0b9c3c0 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 e5bc67869e103de..630b4dd60108ffe 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 51d4b8a9cc5fc5d..e6cdd3d0020fc0d 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/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index fc23c2356825f3c..37dee072e5b3dd2 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -74,6 +74,19 @@ bool Xtensa::isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset) {
   return isValidAddrOffset(Scale, Offset);
 }
 
+// Verify Special Register
+bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) {
+  switch (RegNo) {
+  case Xtensa::WINDOWBASE:
+  case Xtensa::WINDOWSTART:
+    return FeatureBits[Xtensa::FeatureWindowed];
+  case Xtensa::NoRegister:
+    return false;
+  }
+
+  return true;
+}
+
 static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
                                         const Triple &TT,
                                         const MCTargetOptions &Options) {

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
index 6be54867d84a739..649073b01f5c10d 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
@@ -19,12 +19,14 @@
 
 namespace llvm {
 
+class FeatureBitset;
 class MCAsmBackend;
 class MCCodeEmitter;
 class MCContext;
 class MCInstrInfo;
 class MCObjectTargetWriter;
 class MCObjectWriter;
+class MCRegister;
 class MCRegisterInfo;
 class MCSubtargetInfo;
 class MCTargetOptions;
@@ -52,6 +54,9 @@ bool isValidAddrOffset(int Scale, int64_t OffsetVal);
 
 // Check address offset for load/store instructions.
 bool isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset);
+
+// Verify if it's correct to use a special register.
+bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits);
 } // namespace Xtensa
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td
index 460a15e808b3a40..2c4bacbe8282b04 100644
--- a/llvm/lib/Target/Xtensa/Xtensa.td
+++ b/llvm/lib/Target/Xtensa/Xtensa.td
@@ -17,10 +17,9 @@ 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)>;
+
+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 000000000000000..6f24a674ae0ce20
--- /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 699d0d6cf804458..5ef795a0e5287a3 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -678,3 +678,104 @@ 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 {
+  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;
+    }
+  }
+}
+
+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 aa72fa0a56a6f5b..402e05a5c3dd1d9 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 % 8 == 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 5c07386b060cd97..09087edc86712d9 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 948dcbc5278eaa4..dddc0f7ef605d78 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -36,9 +36,12 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
   SelectionDAGTargetInfo TSInfo;
   XtensaFrameLowering FrameLowering;
 
-  // Enabled Xtensa Density extension
+  // Enabled Xtensa Density Option
   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 000000000000000..34c51dd32b6be79
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt
@@ -0,0 +1,71 @@
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# 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
+## windowed register option enabled. Also verify that dissasembling without
+## windowed register 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
+
+[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
new file mode 100644
index 000000000000000..69d7d424d968260
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt
@@ -0,0 +1,11 @@
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# 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 windowed register
+## and code density options enabled. Also verify that
+## dissasembling without these options 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 000000000000000..3376469e3085b8f
--- /dev/null
+++ b/llvm/test/MC/Xtensa/windowed.s
@@ -0,0 +1,105 @@
+# 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
+
+# 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_code_density.s b/llvm/test/MC/Xtensa/windowed_code_density.s
new file mode 100644
index 000000000000000..e532657466fba54
--- /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 000000000000000..958363093dd8e15
--- /dev/null
+++ b/llvm/test/MC/Xtensa/windowed_invalid.s
@@ -0,0 +1,35 @@
+// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# 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], 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
+// 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]


        


More information about the llvm-commits mailing list