[llvm-branch-commits] [llvm] c6dce21 - [Xtensa] Add descriptions of the Xtensa

Andrei Safronov via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 11 15:40:17 PDT 2020


Author: Andrei Safronov
Date: 2020-07-21T13:25:50+03:00
New Revision: c6dce21897ec70408f4dc6f6e40a49550835308f

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

LOG: [Xtensa] Add descriptions of the Xtensa

 shift/load/store instructions.

Added: 
    

Modified: 
    llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.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/XtensaInstrInfo.td
    llvm/lib/Target/Xtensa/XtensaOperands.td
    llvm/test/MC/Xtensa/xtensa-invalid.s
    llvm/test/MC/Xtensa/xtensa-valid.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index 555ff46c8a83..2bc7178b865c 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -53,7 +53,10 @@ class XtensaAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy parseRegister(OperandVector &Operands,
                                      bool AllowParens = false, bool SR = false);
   OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
-  bool parseOperand(OperandVector &Operands);
+  bool parseOperand(OperandVector &Operands, StringRef Mnemonic,
+                    bool SR = false);
+  bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
+                              SMLoc NameLoc, OperandVector &Operands);
 
 public:
   enum XtensaMatchResultTy {
@@ -138,6 +141,39 @@ struct XtensaOperand : public MCParsedAsmOperand {
            ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
   }
 
+  bool isImm12() const { return isImm(-2048, 2047); }
+
+  bool isImm12m() const { return isImm(-2048, 2047); }
+
+  bool isOffset4m32() const {
+    return isImm(0, 60) &&
+           ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
+  }
+
+  bool isOffset8m8() const { return isImm(0, 255); }
+
+  bool isOffset8m16() const {
+    return isImm(0, 510) &&
+           ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
+  }
+
+  bool isOffset8m32() const {
+    return isImm(0, 1020) &&
+           ((dyn_cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
+  }
+
+  bool isUimm4() const { return isImm(0, 15); }
+
+  bool isUimm5() const { return isImm(0, 31); }
+
+  bool isImm8n_7() const { return isImm(-8, 7); }
+
+  bool isShimm1_31() const { return isImm(1, 31); }
+
+  bool isImm16_31() const { return isImm(16, 31); }
+
+  bool isImm1_16() const { return isImm(1, 16); }
+
   /// getStartLoc - Gets location of the first token of this operand
   SMLoc getStartLoc() const override { return StartLoc; }
   /// getEndLoc - Gets location of the last token of this operand
@@ -286,6 +322,39 @@ bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
                  "expected immediate in range [-32768, 32512], first 8 bits "
                  "should be zero");
+  case Match_InvalidImm12:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [-2048, 2047]");
+  case Match_InvalidImm12m:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [-2048, 2047]");
+  case Match_InvalidImm1_16:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [1, 16]");
+  case Match_InvalidShimm1_31:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [1, 31]");
+  case Match_InvalidUimm4:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 15]");
+  case Match_InvalidUimm5:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 31]");
+  case Match_InvalidOffset8m8:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 255]");
+  case Match_InvalidOffset8m16:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 510], first bit "
+                 "should be zero");
+  case Match_InvalidOffset8m32:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 1020], first 2 bits "
+                 "should be zero");
+  case Match_InvalidOffset4m32:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected immediate in range [0, 60], first 2 bits "
+                 "should be zero");
   }
 
   llvm_unreachable("Unknown match type detected!");
@@ -326,6 +395,11 @@ OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands,
   switch (getLexer().getKind()) {
   default:
     return MatchOperand_NoMatch;
+  case AsmToken::Integer:
+    if (!SR)
+      return MatchOperand_NoMatch;
+    RegName = StringRef(std::to_string(getLexer().getTok().getIntVal()));
+    break;
   case AsmToken::Identifier:
     RegName = getLexer().getTok().getIdentifier();
     break;
@@ -397,9 +471,10 @@ XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
 /// Looks at a token type and creates the relevant operand
 /// from this information, adding to Operands.
 /// If operand was parsed, returns false, else true.
-bool XtensaAsmParser::parseOperand(OperandVector &Operands) {
+bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
+                                   bool SR) {
   // Attempt to parse token as register
-  if (parseRegister(Operands, true) == MatchOperand_Success)
+  if (parseRegister(Operands, true, SR) == MatchOperand_Success)
     return false;
 
   // Attempt to parse token as an immediate
@@ -412,9 +487,75 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands) {
   return true;
 }
 
+bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
+                                             StringRef Name, SMLoc NameLoc,
+                                             OperandVector &Operands) {
+  if ((Name.startswith("wsr.") || Name.startswith("rsr.") ||
+       Name.startswith("xsr.")) &&
+      (Name.size() > 4)) {
+    // Parse case when instruction name is concatenated with SR register
+    // name, like "wsr.sar a1"
+
+    // First operand is token for instruction
+    Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
+
+    StringRef RegName = Name.drop_front(4);
+    unsigned RegNo = MatchRegisterName(RegName);
+
+    if (RegNo == 0)
+      RegNo = MatchRegisterAltName(RegName);
+
+    if (RegNo == 0) {
+      Error(NameLoc, "invalid register name");
+      return true;
+    }
+
+    // Parse operand
+    if (parseOperand(Operands, Name))
+      return true;
+
+    SMLoc S = getLoc();
+    SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+    Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
+  } else {
+    // First operand is token for instruction
+    Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
+
+    // Parse first operand
+    if (parseOperand(Operands, Name))
+      return true;
+
+    if (!getLexer().is(AsmToken::Comma)) {
+      SMLoc Loc = getLexer().getLoc();
+      getParser().eatToEndOfStatement();
+      return Error(Loc, "unexpected token");
+    }
+
+    getLexer().Lex();
+
+    // Parse second operand
+    if (parseOperand(Operands, Name, true))
+      return true;
+  }
+
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    SMLoc Loc = getLexer().getLoc();
+    getParser().eatToEndOfStatement();
+    return Error(Loc, "unexpected token");
+  }
+
+  getParser().Lex(); // Consume the EndOfStatement.
+  return false;
+}
+
 bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
                                        StringRef Name, SMLoc NameLoc,
                                        OperandVector &Operands) {
+  if (Name.startswith("wsr") || Name.startswith("rsr") ||
+      Name.startswith("xsr")) {
+    return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
+  }
+
   // First operand is token for instruction
   Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
 
@@ -423,7 +564,7 @@ bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
     return false;
 
   // Parse first operand
-  if (parseOperand(Operands))
+  if (parseOperand(Operands, Name))
     return true;
 
   // Parse until end of statement, consuming commas between operands
@@ -432,7 +573,7 @@ bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
     getLexer().Lex();
 
     // Parse next operand
-    if (parseOperand(Operands))
+    if (parseOperand(Operands, Name))
       return true;
   }
 

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index 7cd363ac4314..865d98f1e6cf 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -81,6 +81,13 @@ void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
   printOperand(MI->getOperand(OpNum), O);
 }
 
+void XtensaInstPrinter::printMemOperand(const MCInst *MI, int opNum,
+                                        raw_ostream &OS) {
+  OS << getRegisterName(MI->getOperand(opNum).getReg());
+  OS << ", ";
+  printOperand(MI, opNum + 1, OS);
+}
+
 void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
                                              raw_ostream &O) {
   if (MI->getOperand(OpNum).isImm()) {
@@ -103,3 +110,112 @@ void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum,
   } else
     printOperand(MI, OpNum, O);
 }
+
+void XtensaInstPrinter::printImm12_AsmOperand(const MCInst *MI, int OpNum,
+                                              raw_ostream &O) {
+  if (MI->getOperand(OpNum).isImm()) {
+    int64_t Value = MI->getOperand(OpNum).getImm();
+    assert((Value >= -2048 && Value <= 2047) &&
+           "Invalid argument, value must be in ranges [-2048,2047]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum,
+                                               raw_ostream &O) {
+  if (MI->getOperand(OpNum).isImm()) {
+    int64_t Value = MI->getOperand(OpNum).getImm();
+    assert((Value >= -2048 && Value <= 2047) &&
+           "Invalid argument, value must be in ranges [-2048,2047]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printUimm4_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 <= 15) && "Invalid argument");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printUimm5_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 <= 31) && "Invalid argument");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum,
+                                                  raw_ostream &O) {
+  if (MI->getOperand(OpNum).isImm()) {
+    int64_t Value = MI->getOperand(OpNum).getImm();
+    assert((Value >= 1 && Value <= 31) &&
+           "Invalid argument, value must be in range [1,31]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,
+                                                raw_ostream &O) {
+  if (MI->getOperand(OpNum).isImm()) {
+    int64_t Value = MI->getOperand(OpNum).getImm();
+    assert((Value >= 1 && Value <= 16) &&
+           "Invalid argument, value must be in range [1,16]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printOffset8m8_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 <= 255) &&
+           "Invalid argument, value must be in range [0,255]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printOffset8m16_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 <= 510 && ((Value & 0x1) == 0)) &&
+           "Invalid argument, value must be multiples of two in range [0,510]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printOffset8m32_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 <= 1020 && ((Value & 0x3) == 0)) &&
+        "Invalid argument, value must be multiples of four in range [0,1020]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}
+
+void XtensaInstPrinter::printOffset4m32_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 <= 60 && ((Value & 0x3) == 0)) &&
+           "Invalid argument, value must be multiples of four in range [0,60]");
+    O << Value;
+  } else
+    printOperand(MI, OpNum, O);
+}

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
index 8c6cb677734c..e83a4c6196ed 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
@@ -42,9 +42,20 @@ class XtensaInstPrinter : public MCInstPrinter {
 private:
   // Print various types of operand.
   void printOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printMemOperand(const MCInst *MI, int OpNUm, raw_ostream &O);
 
   void printImm8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
   void printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printImm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printImm12m_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printUimm4_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printUimm5_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printShimm1_31_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+  void printImm1_16_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);
 };
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 4bb298e4ed62..d0d3f7077cdf 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -52,6 +52,10 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
 
+  uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,
+                             SmallVectorImpl<MCFixup> &Fixups,
+                             const MCSubtargetInfo &STI) const;
+
   uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
@@ -59,6 +63,26 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
   uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
                               SmallVectorImpl<MCFixup> &Fixups,
                               const MCSubtargetInfo &STI) const;
+
+  uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
+
+  uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
+
+  uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
+
+  uint32_t getImm1_16OpValue(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;
 };
 } // namespace
 
@@ -94,14 +118,48 @@ XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   if (MO.isReg())
     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
   if (MO.isImm()) {
-    uint32_t res = static_cast<uint32_t>(MO.getImm());
-    return res;
+    uint32_t Res = static_cast<uint32_t>(MO.getImm());
+    return Res;
   }
 
   llvm_unreachable("Unhandled expression!");
   return 0;
 }
 
+uint32_t
+XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  assert(MI.getOperand(OpNo + 1).isImm());
+
+  uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
+
+  switch (MI.getOpcode()) {
+  case Xtensa::S16I:
+  case Xtensa::L16SI:
+  case Xtensa::L16UI:
+    if (Res & 0x1) {
+      llvm_unreachable("Unexpected operand value!");
+    }
+    Res >>= 1;
+    break;
+  case Xtensa::S32I:
+  case Xtensa::L32I:
+    if (Res & 0x3) {
+      llvm_unreachable("Unexpected operand value!");
+    }
+    Res >>= 2;
+    break;
+  }
+  
+  assert((isUInt<8>(Res)) && "Unexpected operand value!");
+
+  uint32_t OffBits = Res << 4;
+  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
+
+  return ((OffBits & 0xFF0) | RegBits);
+}
+
 uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
                                              SmallVectorImpl<MCFixup> &Fixups,
                                              const MCSubtargetInfo &STI) const {
@@ -126,4 +184,63 @@ XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
   return (Res & 0xffff);
 }
 
+uint32_t
+XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
+                                     SmallVectorImpl<MCFixup> &Fixups,
+                                     const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  int32_t Res = MO.getImm();
+
+  assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
+
+  return (Res & 0xfff);
+}
+
+uint32_t
+XtensaMCCodeEmitter::getUimm4OpValue(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 <= 15) && "Unexpected operand value!");
+
+  return Res & 0xf;
+}
+
+uint32_t
+XtensaMCCodeEmitter::getUimm5OpValue(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 <= 31) && "Unexpected operand value!");
+
+  return (Res & 0x1f);
+}
+
+uint32_t
+XtensaMCCodeEmitter::getShimm1_31OpValue(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 >= 1) && (Res <= 31)) && "Unexpected operand value!");
+
+  return ((32 - Res) & 0x1f);
+}
+
+uint32_t
+XtensaMCCodeEmitter::getImm1_16OpValue(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 >= 1) && (Res <= 16)) && "Unexpected operand value!");
+
+  return (Res - 1);
+}
 #include "XtensaGenMCCodeEmitter.inc"

diff  --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 360cc88b2b5b..cd7764672427 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -84,8 +84,17 @@ def NEG: RRR_Inst<0x00, 0x00, 0x06, (outs AR:$r), (ins AR:$t),
 //===----------------------------------------------------------------------===//
 // Move instructions
 //===----------------------------------------------------------------------===//
+def MOVI: RRI8_Inst<0x02, (outs AR:$t), (ins imm12m:$imm),
+                   "movi\t$t, $imm",
+                   [(set AR:$t, imm12m:$imm)]>
+{
+  bits<12> imm;
+
+  let imm8{7-0} = imm{7-0};
+  let s{3-0} = imm{11-8};
+  let r = 0xa;
+}
 
-// Conditional move
 def MOVEQZ : RRR_Inst<0x00, 0x03, 0x08, (outs AR:$r), (ins AR:$s, AR:$t),
                      "moveqz\t$r, $s, $t", []>;
 def MOVNEZ : RRR_Inst<0x00, 0x03, 0x09, (outs AR:$r), (ins AR:$s, AR:$t),
@@ -95,9 +104,162 @@ def MOVLTZ : RRR_Inst<0x00, 0x03, 0x0A, (outs AR:$r), (ins AR:$s, AR:$t),
 def MOVGEZ : RRR_Inst<0x00, 0x03, 0x0B, (outs AR:$r), (ins AR:$s, AR:$t),
                      "movgez\t$r, $s, $t", []>;
 
+//===----------------------------------------------------------------------===//
+// Shift instructions
+//===----------------------------------------------------------------------===//
+
+let Uses = [SAR] in
+{
+  def SLL: RRR_Inst<0x00, 0x01, 0x0A, (outs AR:$r), (ins AR:$s),
+                   "sll\t$r, $s", []>
+  {
+    let t = 0x00;
+  }
+
+  def SRA: RRR_Inst<0x00, 0x01, 0x0B, (outs AR:$r), (ins AR:$t),
+                   "sra\t$r, $t", []>
+  {
+    let s = 0x00;
+  }
+
+  def SRC: RRR_Inst<0x00, 0x01, 0x08, (outs AR:$r), (ins AR:$s, AR:$t),
+                   "src\t$r, $s, $t", []>;
+
+  def SRL: RRR_Inst<0x00, 0x01, 0x09, (outs AR:$r), (ins AR:$t),
+                   "srl\t$r, $t", []>
+  {
+    let s = 0x00;
+  }
+}
+
+let Defs = [SAR] in
+{
+  def SSL: RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
+                   "ssl\t$s", []>
+  {
+    let r = 0x01;
+    let t = 0x00;
+  }
+
+  def SSR: RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
+                   "ssr\t$s", []>
+  {
+    let r = 0x00;
+    let t = 0x00;
+  }
+}
+
+def EXTUI: RRR_Inst<0x00, 0x04, 0x00, (outs AR:$r), (ins AR:$t, uimm5:$imm1, imm1_16:$imm2),
+                   "extui\t$r, $t, $imm1, $imm2",
+                   []>
+{
+  bits<5> imm1;
+  bits<4> imm2;
+
+  let s = imm1{3-0};
+  let Inst{16} = imm1{4};
+  let Inst{23-20} = imm2;
+}
+
+def SRAI: RRR_Inst<0x00, 0x01, 0x02, (outs AR:$r), (ins AR:$t, uimm5:$sa),
+                  "srai\t$r, $t, $sa",
+                  [(set AR:$r, (sra AR:$t, uimm5:$sa))]>
+{
+  bits<5> sa;
+
+  let Inst{20} = sa{4};
+  let s = sa{3-0};
+}
+
+def SRLI: RRR_Inst<0x00, 0x01, 0x04, (outs AR:$r), (ins AR:$t, uimm4:$sa),
+                  "srli\t$r, $t, $sa",
+                  [(set AR:$r, (srl AR:$t, uimm4:$sa))]>
+{
+  bits<4> sa;
+
+  let s = sa;
+}
+
+def SLLI: RRR_Inst<0x00, 0x01, 0x00, (outs AR:$r), (ins AR:$s, shimm1_31:$sa),
+                  "slli\t$r, $s, $sa",
+                  [(set AR:$r, (shl AR:$s, shimm1_31:$sa))]>
+{
+  bits<5> sa;
+
+  let Inst{20} = sa{4};
+  let t = sa{3-0};
+}
+
+def SSA8L : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
+     "ssa8l\t$s", []>
+{
+  let r = 0x2;
+  let t = 0x0;
+}
+
+def SSAI: RRR_Inst<0x00, 0x00, 0x04, (outs), (ins uimm5:$imm),
+                  "ssai\t$imm", []>
+{
+  bits<5> imm;
+
+  let r = 0x04;
+  let s = imm{3-0};
+  let t{3-1} = 0;
+  let t{0} = imm{4};
+}
+
+//===----------------------------------------------------------------------===//
+// Load and store instructions
+//===----------------------------------------------------------------------===//
+
+// Load instructions
+let mayLoad = 1 in
+{
+
+  class Load_RRI8<bits<4> oper, string instrAsm, SDPatternOperator opNode,
+        ComplexPattern addrOp, Operand memOp>
+	  : RRI8_Inst<0x02, (outs AR:$t), (ins memOp:$addr),
+                  instrAsm#"\t$t, $addr",
+                 [(set AR:$t, (opNode addrOp:$addr))]>
+  {
+    bits<12> addr;
+
+    let r = oper;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+}
+
+def L8UI: Load_RRI8<0x00, "l8ui", zextloadi8, addr_ish1, mem8>;
+def L16SI: Load_RRI8<0x09, "l16si", sextloadi16, addr_ish2, mem16>;
+def L16UI: Load_RRI8<0x01, "l16ui", zextloadi16, addr_ish2, mem16>;
+def L32I: Load_RRI8<0x02, "l32i", load, addr_ish4, mem32>;
+
+// Store instructions
+let mayStore = 1 in
+{
+  class Store_II8<bits<4> oper, string instrAsm, SDPatternOperator opNode,
+        ComplexPattern addrOp, Operand memOp>
+	  : RRI8_Inst<0x02, (outs), (ins AR:$t, memOp:$addr),
+                  instrAsm#"\t$t, $addr",
+                 [(opNode AR:$t, addrOp:$addr)]>
+  {
+    bits<12> addr;
+
+    let r = oper;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+}
+
+def S8I: Store_II8<0x04, "s8i", truncstorei8, addr_ish1, mem8>;
+def S16I: Store_II8<0x05, "s16i", truncstorei16, addr_ish2, mem16>;
+def S32I: Store_II8<0x06, "s32i", store, addr_ish4, mem32>;
+
 //===----------------------------------------------------------------------===//
 // Mem barrier instructions
 //===----------------------------------------------------------------------===//
+
 def MEMW:  RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
                    "memw", []>
 {
@@ -159,3 +321,15 @@ def NOP: RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
   let s = 0x00;
   let t = 0x0f;
 }
+
+def WSR: RSR_Inst<0x00, 0x03, 0x01, (outs SR:$sr), (ins AR:$t),
+                 "wsr\t$t, $sr", []>;
+
+def RSR: RSR_Inst<0x00, 0x03, 0x00, (outs AR:$t), (ins SR:$sr),
+                 "rsr\t$t, $sr", []>;
+
+def XSR: RSR_Inst<0x00, 0x01, 0x06, (outs AR:$ard, SR:$srd), (ins AR:$t, SR:$sr),
+                 "xsr\t$t, $sr", []>
+{
+  let Constraints = "$ard = $t, $srd = $sr";
+}

diff  --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td
index dcf818437c08..817bbeeb1313 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperands.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperands.td
@@ -35,3 +35,87 @@ def Imm8_sh8_AsmOperand: ImmAsmOperand<"Imm8_sh8">;
 def imm8_sh8: Immediate<i32, [{ return Imm >= -32768 && Imm <= 32512 && ((Imm & 0xFF) == 0); }], "Imm8_sh8_AsmOperand"> {
   let EncoderMethod = "getImm8_sh8OpValue";
 }
+
+// imm12 predicate - Immediate in the range [-2048,2047]
+def Imm12_AsmOperand: ImmAsmOperand<"Imm12">;
+def imm12: Immediate<i32, [{ return Imm >= -2048 && Imm <= 2047; }], "Imm12_AsmOperand"> {
+  let EncoderMethod = "getImm12OpValue";
+}
+
+// imm12m predicate - Immediate for MOV operation
+def Imm12m_AsmOperand: ImmAsmOperand<"Imm12m">;
+def imm12m: Immediate<i32, [{ return Imm >= -2048 && Imm <= 2047; }], "Imm12m_AsmOperand"> {
+  let EncoderMethod = "getImm12OpValue";
+}
+
+// uimm4 predicate - Immediate in the range [0,15]
+def Uimm4_AsmOperand: ImmAsmOperand<"Uimm4">;
+def uimm4: Immediate<i32, [{ return Imm >= 0 && Imm <= 15; }], "Uimm4_AsmOperand"> {
+  let EncoderMethod = "getUimm4OpValue";
+}
+
+// uimm5 predicate - Immediate in the range [0,31]
+def Uimm5_AsmOperand: ImmAsmOperand<"Uimm5">;
+def uimm5: Immediate<i32, [{ return Imm >= 0 && Imm <= 31; }], "Uimm5_AsmOperand"> {
+  let EncoderMethod = "getUimm5OpValue";
+}
+
+// imm1_16 predicate - Immediate in the range [1,16]
+def Imm1_16_AsmOperand: ImmAsmOperand<"Imm1_16">;
+def imm1_16: Immediate<i32, [{ return Imm >= 1 && Imm <= 16; }], "Imm1_16_AsmOperand"> {
+  let EncoderMethod = "getImm1_16OpValue";
+}
+
+// shimm1_31 predicate - Immediate in the range [1,31]
+def Shimm1_31_AsmOperand: ImmAsmOperand<"Shimm1_31">;
+def shimm1_31: Immediate<i32, [{ return Imm >= 1 && Imm <= 31; }], "Shimm1_31_AsmOperand"> {
+  let EncoderMethod = "getShimm1_31OpValue";
+}
+
+// Memory offset 0..255 for 8-bit memory accesses
+def Offset8m8_AsmOperand: ImmAsmOperand<"Offset8m8">;
+def offset8m8: Immediate<i32,
+    [{ return Imm >= 0 && Imm <= 255; }],
+    "Offset8m8_AsmOperand">;
+
+// Memory offset 0..510 for 16-bit memory accesses
+def Offset8m16_AsmOperand: ImmAsmOperand<"Offset8m16">;
+def offset8m16: Immediate<i32,
+    [{ return Imm >= 0 && Imm <= 510 && (Imm & 0x1 == 0); }],
+    "Offset8m16_AsmOperand">;
+
+// Memory offset 0..1020 for 32-bit memory accesses
+def Offset8m32_AsmOperand: ImmAsmOperand<"Offset8m32">;
+def offset8m32: Immediate<i32,
+    [{ return Imm >= 0 && Imm <= 1020 && (Imm & 0x3 == 0); }],
+    "Offset8m32_AsmOperand">;
+
+// Memory offset 0..60 for 32-bit memory accesses
+def Offset4m32_AsmOperand: ImmAsmOperand<"Offset4m32">;
+def offset4m32: Immediate<i32,
+    [{ return Imm >= 0 && Imm <= 60 && (Imm & 0x3 == 0); }],
+    "Offset4m32_AsmOperand">;
+//===----------------------------------------------------------------------===//
+// Memory address operands
+//===----------------------------------------------------------------------===//
+
+class mem<Operand offset> : Operand<i32>
+{
+  let MIOperandInfo = (ops AR, offset);
+  let EncoderMethod = "getMemRegEncoding";
+  let OperandType = "OPERAND_MEMORY";
+  let PrintMethod = "printMemOperand";
+}
+
+def mem8: mem<offset8m8>;
+
+def mem16: mem<offset8m16>;
+
+def mem32: mem<offset8m32>;
+
+def mem32n: mem<offset4m32>;
+
+//Add patterns for future use in stack addressing mode
+def addr_ish1: ComplexPattern<iPTR, 2, "selectMemRegAddrISH1", [frameindex]>;
+def addr_ish2: ComplexPattern<iPTR, 2, "selectMemRegAddrISH2", [frameindex]>;
+def addr_ish4: ComplexPattern<iPTR, 2, "selectMemRegAddrISH4", [frameindex]>;

diff  --git a/llvm/test/MC/Xtensa/xtensa-invalid.s b/llvm/test/MC/Xtensa/xtensa-invalid.s
index 86f4ff2e4c4b..555263f9c187 100644
--- a/llvm/test/MC/Xtensa/xtensa-invalid.s
+++ b/llvm/test/MC/Xtensa/xtensa-invalid.s
@@ -4,10 +4,15 @@
 
 LBL0:
 
+# imm12m
+movi a1, 3000
+# CHECK:      error: expected immediate in range [-2048, 2047]
+
 # imm8
 addi a1, a2, 300
 # CHECK:      error: expected immediate in range [-128, 127]
 
+# imm8
 addi a1, a2, -129
 # CHECK:      error: expected immediate in range [-128, 127]
 
@@ -15,6 +20,34 @@ addi a1, a2, -129
 addmi a1, a2, 33
 # CHECK:      error: expected immediate in range [-32768, 32512], first 8 bits should be zero
 
+# shimm1_31
+slli a1, a2, 0
+# CHECK:      error: expected immediate in range [1, 31]
+
+# uimm4
+srli a1, a2, 16
+# CHECK:      error: expected immediate in range [0, 15]
+
+# uimm5
+ssai 32
+# CHECK:      error: expected immediate in range [0, 31]
+
+# imm64n_4n
+ssai 32
+# CHECK:      error: expected immediate in range [0, 31]
+
+# offset8m8
+s8i a1, a2, 300
+# CHECK:      error: expected immediate in range [0, 255]
+
+# offset16m8
+l16si a1, a2, 512
+# CHECK:      error: expected immediate in range [0, 510], first bit should be zero
+
+# offset32m8
+l32i a1, a2, 1024
+# CHECK:      error: expected immediate in range [0, 1020], first 2 bits should be zero
+
 # Invalid number of operands
 addi a1, a2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
 addi a1, a2, 4, 4 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction
@@ -24,6 +57,7 @@ aaa a10, a12 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
 
 # Invalid register names
 addi a101, sp, 10 # CHECK: :[[@LINE]]:6: error: invalid operand for instruction
+wsr.uregister a2 # CHECK: :[[@LINE]]:1: error: invalid register name
 or r2, sp, a3 # CHECK: :[[@LINE]]:4: error: invalid operand for instruction
 
 # Invalid operand types

diff  --git a/llvm/test/MC/Xtensa/xtensa-valid.s b/llvm/test/MC/Xtensa/xtensa-valid.s
index e50ad17babd0..209afc635ce1 100644
--- a/llvm/test/MC/Xtensa/xtensa-valid.s
+++ b/llvm/test/MC/Xtensa/xtensa-valid.s
@@ -44,6 +44,10 @@ LBL0:
 # CHECK: encoding: [0x20,0x20,0x00]
  esync
 
+# CHECK-INST:  extui    a1, a2, 7, 8
+# CHECK: encoding: [0x20,0x17,0x74]
+ extui a1, a2, 7, 8
+
 # CHECK-INST:  extw
 # CHECK: encoding: [0xd0,0x20,0x00]
  extw
@@ -52,6 +56,19 @@ LBL0:
 # CHECK: encoding: [0x00,0x20,0x00]
  isync
 
+# CHECK-INST:  l8ui    a2, a1, 3
+# CHECK: encoding: [0x22,0x01,0x03]
+ l8ui a2, sp, 3
+# CHECK-INST:  l16si   a3, a1, 4
+# CHECK: encoding: [0x32,0x91,0x02]
+ l16si a3, sp, 4
+# CHECK-INST: l16ui   a4, a1, 6
+# CHECK: encoding: [0x42,0x11,0x03]
+ l16ui a4, sp, 6
+# CHECK-INST: l32i    a5, a1, 8
+# CHECK: encoding: [0x52,0x21,0x02]
+ l32i a5, sp, 8
+
 # CHECK-INST: memw
 # CHECK: encoding: [0xc0,0x20,0x00]
  memw
@@ -63,6 +80,10 @@ LBL0:
 # CHECK: encoding: [0xc0,0x3b,0xb3]
  movgez  a3,a11,a12
 
+# CHECK-INST: movi    a1, -2048
+# CHECK: encoding: [0x12,0xa8,0x00]
+ movi  a1, -2048
+
 # CHECK-INST: movltz  a7, a8, a9
 # CHECK: encoding: [0x90,0x78,0xa3]
  movltz a7, a8, a9
@@ -82,10 +103,74 @@ LBL0:
 # CHECK: encoding: [0x60,0x45,0x20]
  or a4, a5, a6
 
+# CHECK-INST: rsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x03]
+ rsr a8, sar
+# CHECK-INST: rsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x03]
+ rsr.sar a8
+ # CHECK-INST: rsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x03]
+ rsr a8, 3
+
 # CHECK-INST: rsync
 # CHECK: encoding: [0x10,0x20,0x00]
  rsync
 
+# CHECK-INST: s8i     a2, a1, 3
+# CHECK: encoding: [0x22,0x41,0x03]
+ s8i a2, sp, 3
+# CHECK-INST: s16i    a3, a1, 4
+# CHECK: encoding: [0x32,0x51,0x02]
+ s16i a3, sp, 4
+# CHECK-INST: s32i    a5, a1, 8
+# CHECK: encoding: [0x52,0x61,0x02]
+ s32i a5, sp, 8
+
+# CHECK-INST: sll     a10, a11
+# CHECK: encoding: [0x00,0xab,0xa1]
+ sll a10, a11
+
+# CHECK-INST: slli    a5, a1, 15
+# CHECK: encoding: [0x10,0x51,0x11]
+ slli a5, a1, 15
+
+# CHECK-INST: sra     a12, a3
+# CHECK: encoding: [0x30,0xc0,0xb1]
+ sra a12, a3
+
+# CHECK-INST: srai    a8, a5, 0
+# CHECK: encoding: [0x50,0x80,0x21]
+ srai a8, a5, 0
+
+# CHECK-INST: src     a3, a4, a5
+# CHECK: encoding: [0x50,0x34,0x81]
+ src a3, a4, a5
+
+# CHECK-INST: srl     a6, a7
+# CHECK: encoding: [0x70,0x60,0x91]
+ srl a6, a7
+
+# CHECK-INST: srli    a3, a4, 8
+# CHECK: encoding: [0x40,0x38,0x41]
+ srli a3, a4, 8
+
+# CHECK-INST: ssa8l   a14
+# CHECK: encoding: [0x00,0x2e,0x40]
+ ssa8l a14
+
+# CHECK-INST: ssai    31
+# CHECK: encoding: [0x10,0x4f,0x40]
+ ssai 31
+
+# CHECK-INST: ssl     a0
+# CHECK: encoding: [0x00,0x10,0x40]
+ ssl a0
+
+# CHECK-INST: ssr     a2
+# CHECK: encoding: [0x00,0x02,0x40]
+ ssr a2
+
 # CHECK-INST: sub     a8, a2, a1
 # CHECK: encoding: [0x10,0x82,0xc0]
  sub  a8, a2, a1
@@ -99,6 +184,26 @@ LBL0:
 # CHECK: encoding: [0x70,0x41,0xf0]
  subx8 a4, sp, a7
 
+# CHECK-INST: wsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x13]
+ wsr a8, sar
+# CHECK-INST: wsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x13]
+ wsr.sar a8
+# CHECK-INST: wsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x13]
+ wsr a8, 3
+
 # CHECK-INST: xor     a6, a4, a5
 # CHECK: encoding: [0x50,0x64,0x30]
  xor a6, a4, a5
+
+# CHECK-INST: xsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x61]
+ xsr a8, sar
+# CHECK-INST: xsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x61
+ xsr.sar a8
+# CHECK-INST: xsr     a8, sar
+# CHECK: encoding: [0x80,0x03,0x61
+ xsr a8, 3


        


More information about the llvm-branch-commits mailing list