[llvm] de10a02 - [CSKY] Complete to add basic integer instruction set

Zi Xuan Wu via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 20 00:51:10 PDT 2021


Author: Zi Xuan Wu
Date: 2021-10-20T15:50:44+08:00
New Revision: de10a02fc067339224196735aa3ecec66e2d4845

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

LOG: [CSKY] Complete to add basic integer instruction set

Complete the basic integer instruction set and add related predictor in CSKY.td.
And it includes the instruction definition and asm parser support.

Differential Revision: https://reviews.llvm.org/D111701

Added: 
    llvm/lib/Target/CSKY/CSKYSubtarget.cpp
    llvm/lib/Target/CSKY/CSKYSubtarget.h

Modified: 
    llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
    llvm/lib/Target/CSKY/CMakeLists.txt
    llvm/lib/Target/CSKY/CSKY.td
    llvm/lib/Target/CSKY/CSKYInstrFormats.td
    llvm/lib/Target/CSKY/CSKYInstrInfo.td
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h
    llvm/test/MC/CSKY/basic.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
index 8c82ba0bca65..137f48caf60f 100644
--- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -1,4 +1,4 @@
-//===-- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
+//===---- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/CSKYInstPrinter.h"
 #include "MCTargetDesc/CSKYMCExpr.h"
 #include "MCTargetDesc/CSKYMCTargetDesc.h"
 #include "TargetInfo/CSKYTargetInfo.h"
@@ -19,10 +20,14 @@
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
 #include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "csky-asm-parser"
 
 using namespace llvm;
 
@@ -31,6 +36,8 @@ struct CSKYOperand;
 
 class CSKYAsmParser : public MCTargetAsmParser {
 
+  const MCRegisterInfo *MRI;
+
   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
                                   int64_t Lower, int64_t Upper, Twine Msg);
 
@@ -51,6 +58,9 @@ class CSKYAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                         SMLoc &EndLoc) override;
 
+  bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
+                          MCStreamer &Out);
+
 // Auto-generated instruction matching functions
 #define GET_ASSEMBLER_HEADER
 #include "CSKYGenAsmMatcher.inc"
@@ -60,12 +70,18 @@ class CSKYAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
   OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
   OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
+  OperandMatchResultTy parseDataSymbol(OperandVector &Operands);
+  OperandMatchResultTy parsePSRFlag(OperandVector &Operands);
+  OperandMatchResultTy parseRegSeq(OperandVector &Operands);
+  OperandMatchResultTy parseRegList(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
 public:
   enum CSKYMatchResultTy {
     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
+    Match_RequiresSameSrcAndDst,
+    Match_InvalidRegOutOfRange,
 #define GET_OPERAND_DIAGNOSTIC_TYPES
 #include "CSKYGenAsmMatcher.inc"
 #undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -80,10 +96,14 @@ class CSKYAsmParser : public MCTargetAsmParser {
 
 /// Instances of this class represent a parsed machine instruction.
 struct CSKYOperand : public MCParsedAsmOperand {
+
   enum KindTy {
     Token,
     Register,
     Immediate,
+    RegisterSeq,
+    CPOP,
+    RegisterList
   } Kind;
 
   struct RegOp {
@@ -94,11 +114,34 @@ struct CSKYOperand : public MCParsedAsmOperand {
     const MCExpr *Val;
   };
 
+  struct ConstpoolOp {
+    const MCExpr *Val;
+  };
+
+  struct RegSeqOp {
+    unsigned RegNumFrom;
+    unsigned RegNumTo;
+  };
+
+  struct RegListOp {
+    unsigned List1From = 0;
+    unsigned List1To = 0;
+    unsigned List2From = 0;
+    unsigned List2To = 0;
+    unsigned List3From = 0;
+    unsigned List3To = 0;
+    unsigned List4From = 0;
+    unsigned List4To = 0;
+  };
+
   SMLoc StartLoc, EndLoc;
   union {
     StringRef Tok;
     RegOp Reg;
     ImmOp Imm;
+    ConstpoolOp CPool;
+    RegSeqOp RegSeq;
+    RegListOp RegList;
   };
 
   CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -112,18 +155,31 @@ struct CSKYOperand : public MCParsedAsmOperand {
     case Register:
       Reg = o.Reg;
       break;
+    case RegisterSeq:
+      RegSeq = o.RegSeq;
+      break;
+    case CPOP:
+      CPool = o.CPool;
+      break;
     case Immediate:
       Imm = o.Imm;
       break;
     case Token:
       Tok = o.Tok;
       break;
+    case RegisterList:
+      RegList = o.RegList;
+      break;
     }
   }
 
   bool isToken() const override { return Kind == Token; }
   bool isReg() const override { return Kind == Register; }
   bool isImm() const override { return Kind == Immediate; }
+  bool isRegisterSeq() const { return Kind == RegisterSeq; }
+  bool isRegisterList() const { return Kind == RegisterList; }
+  bool isConstPoolOp() const { return Kind == CPOP; }
+
   bool isMem() const override { return false; }
 
   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
@@ -162,29 +218,132 @@ struct CSKYOperand : public MCParsedAsmOperand {
     return IsConstantImm && isShiftedInt<num, shift>(Imm);
   }
 
+  bool isUImm1() const { return isUImm<1>(); }
   bool isUImm2() const { return isUImm<2>(); }
+  bool isUImm3() const { return isUImm<3>(); }
+  bool isUImm4() const { return isUImm<4>(); }
   bool isUImm5() const { return isUImm<5>(); }
+  bool isUImm6() const { return isUImm<6>(); }
+  bool isUImm7() const { return isUImm<7>(); }
+  bool isUImm8() const { return isUImm<8>(); }
   bool isUImm12() const { return isUImm<12>(); }
   bool isUImm16() const { return isUImm<16>(); }
-
+  bool isUImm20() const { return isUImm<20>(); }
+  bool isUImm24() const { return isUImm<24>(); }
+
+  bool isOImm3() const { return isOImm<3>(); }
+  bool isOImm4() const { return isOImm<4>(); }
+  bool isOImm5() const { return isOImm<5>(); }
+  bool isOImm6() const { return isOImm<6>(); }
+  bool isOImm8() const { return isOImm<8>(); }
   bool isOImm12() const { return isOImm<12>(); }
   bool isOImm16() const { return isOImm<16>(); }
 
+  bool isSImm8() const { return isSImm<8>(); }
+
+  bool isUImm5Shift1() { return isUImm<5, 1>(); }
+  bool isUImm5Shift2() { return isUImm<5, 2>(); }
+  bool isUImm7Shift1() { return isUImm<7, 1>(); }
+  bool isUImm7Shift2() { return isUImm<7, 2>(); }
+  bool isUImm7Shift3() { return isUImm<7, 3>(); }
+  bool isUImm8Shift2() { return isUImm<8, 2>(); }
+  bool isUImm8Shift3() { return isUImm<8, 3>(); }
+  bool isUImm8Shift8() { return isUImm<8, 8>(); }
+  bool isUImm8Shift16() { return isUImm<8, 16>(); }
+  bool isUImm8Shift24() { return isUImm<8, 24>(); }
   bool isUImm12Shift1() { return isUImm<12, 1>(); }
   bool isUImm12Shift2() { return isUImm<12, 2>(); }
+  bool isUImm16Shift8() { return isUImm<16, 8>(); }
+  bool isUImm16Shift16() { return isUImm<16, 16>(); }
+  bool isUImm24Shift8() { return isUImm<24, 8>(); }
 
   bool isSImm16Shift1() { return isSImm<16, 1>(); }
 
-  bool isCSKYSymbol() const {
+  bool isCSKYSymbol() const { return isImm(); }
+
+  bool isConstpool() const { return isConstPoolOp(); }
+  bool isDataSymbol() const { return isConstPoolOp(); }
+
+  bool isSPOperand() const {
+    if (!isReg())
+      return false;
+    return getReg() == CSKY::R14;
+  }
+
+  bool isPSRFlag() const {
     int64_t Imm;
-    // Must be of 'immediate' type but not a constant.
-    return isImm() && !evaluateConstantImm(getImm(), Imm);
+    // Must be of 'immediate' type and a constant.
+    if (!isImm() || !evaluateConstantImm(getImm(), Imm))
+      return false;
+
+    return isUInt<5>(Imm);
   }
 
-  bool isConstpoolSymbol() const {
+  template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
+    if (!isRegisterSeq())
+      return false;
+
+    std::pair<unsigned, unsigned> regSeq = getRegSeq();
+
+    return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
+           regSeq.second <= MAX;
+  }
+
+  bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
+
+  static bool isLegalRegList(unsigned from, unsigned to) {
+    if (from == 0 && to == 0)
+      return true;
+
+    if (from == to) {
+      if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
+          from != CSKY::R28)
+        return false;
+
+      return true;
+    } else {
+      if (from != CSKY::R4 && from != CSKY::R16)
+        return false;
+
+      if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
+        return true;
+      else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
+        return true;
+      else
+        return false;
+    }
+  }
+
+  bool isRegList() const {
+    if (!isRegisterList())
+      return false;
+
+    auto regList = getRegList();
+
+    if (!isLegalRegList(regList.List1From, regList.List1To))
+      return false;
+    if (!isLegalRegList(regList.List2From, regList.List2To))
+      return false;
+    if (!isLegalRegList(regList.List3From, regList.List3To))
+      return false;
+    if (!isLegalRegList(regList.List4From, regList.List4To))
+      return false;
+
+    return true;
+  }
+
+  bool isExtImm6() {
+    if (!isImm())
+      return false;
+
     int64_t Imm;
-    // Must be of 'immediate' type but not a constant.
-    return isImm() && !evaluateConstantImm(getImm(), Imm);
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    if (!IsConstantImm)
+      return false;
+
+    int uimm4 = Imm & 0xf;
+
+    return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
   }
 
   /// Gets location of the first token of this operand.
@@ -197,23 +356,64 @@ struct CSKYOperand : public MCParsedAsmOperand {
     return Reg.RegNum;
   }
 
+  std::pair<unsigned, unsigned> getRegSeq() const {
+    assert(Kind == RegisterSeq && "Invalid type access!");
+    return std::pair<unsigned, unsigned>(RegSeq.RegNumFrom, RegSeq.RegNumTo);
+  }
+
+  RegListOp getRegList() const {
+    assert(Kind == RegisterList && "Invalid type access!");
+    return RegList;
+  }
+
   const MCExpr *getImm() const {
     assert(Kind == Immediate && "Invalid type access!");
     return Imm.Val;
   }
 
+  const MCExpr *getConstpoolOp() const {
+    assert(Kind == CPOP && "Invalid type access!");
+    return CPool.Val;
+  }
+
   StringRef getToken() const {
     assert(Kind == Token && "Invalid type access!");
     return Tok;
   }
 
   void print(raw_ostream &OS) const override {
+    auto RegName = [](unsigned Reg) {
+      if (Reg)
+        return CSKYInstPrinter::getRegisterName(Reg);
+      else
+        return "noreg";
+    };
+
     switch (Kind) {
+    case CPOP:
+      OS << *getConstpoolOp();
+      break;
     case Immediate:
       OS << *getImm();
       break;
-    case Register:
-      OS << "<register x" << getReg() << ">";
+    case KindTy::Register:
+      OS << "<register " << RegName(getReg()) << ">";
+      break;
+    case RegisterSeq:
+      OS << "<register-seq ";
+      OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
+         << ">";
+      break;
+    case RegisterList:
+      OS << "<register-list ";
+      OS << RegName(getRegList().List1From) << "-"
+         << RegName(getRegList().List1To) << ",";
+      OS << RegName(getRegList().List2From) << "-"
+         << RegName(getRegList().List2To) << ",";
+      OS << RegName(getRegList().List3From) << "-"
+         << RegName(getRegList().List3To) << ",";
+      OS << RegName(getRegList().List4From) << "-"
+         << RegName(getRegList().List4To);
       break;
     case Token:
       OS << "'" << getToken() << "'";
@@ -238,6 +438,51 @@ struct CSKYOperand : public MCParsedAsmOperand {
     return Op;
   }
 
+  static std::unique_ptr<CSKYOperand> createRegSeq(unsigned RegNoFrom,
+                                                   unsigned RegNoTo, SMLoc S) {
+    auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
+    Op->RegSeq.RegNumFrom = RegNoFrom;
+    Op->RegSeq.RegNumTo = RegNoTo;
+    Op->StartLoc = S;
+    Op->EndLoc = S;
+    return Op;
+  }
+
+  static std::unique_ptr<CSKYOperand>
+  createRegList(SmallVector<unsigned, 4> reglist, SMLoc S) {
+    auto Op = std::make_unique<CSKYOperand>(RegisterList);
+    Op->RegList.List1From = 0;
+    Op->RegList.List1To = 0;
+    Op->RegList.List2From = 0;
+    Op->RegList.List2To = 0;
+    Op->RegList.List3From = 0;
+    Op->RegList.List3To = 0;
+    Op->RegList.List4From = 0;
+    Op->RegList.List4To = 0;
+
+    for (unsigned i = 0; i < reglist.size(); i += 2) {
+      if (Op->RegList.List1From == 0) {
+        Op->RegList.List1From = reglist[i];
+        Op->RegList.List1To = reglist[i + 1];
+      } else if (Op->RegList.List2From == 0) {
+        Op->RegList.List2From = reglist[i];
+        Op->RegList.List2To = reglist[i + 1];
+      } else if (Op->RegList.List3From == 0) {
+        Op->RegList.List3From = reglist[i];
+        Op->RegList.List3To = reglist[i + 1];
+      } else if (Op->RegList.List4From == 0) {
+        Op->RegList.List4From = reglist[i];
+        Op->RegList.List4To = reglist[i + 1];
+      } else {
+        assert(0);
+      }
+    }
+
+    Op->StartLoc = S;
+    Op->EndLoc = S;
+    return Op;
+  }
+
   static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
                                                 SMLoc E) {
     auto Op = std::make_unique<CSKYOperand>(Immediate);
@@ -247,6 +492,15 @@ struct CSKYOperand : public MCParsedAsmOperand {
     return Op;
   }
 
+  static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
+                                                        SMLoc S, SMLoc E) {
+    auto Op = std::make_unique<CSKYOperand>(CPOP);
+    Op->CPool.Val = Val;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     assert(Expr && "Expr shouldn't be null!");
     if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
@@ -265,6 +519,70 @@ struct CSKYOperand : public MCParsedAsmOperand {
     assert(N == 1 && "Invalid number of operands!");
     addExpr(Inst, getImm());
   }
+
+  void addConstpoolOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
+  }
+
+  void addRegSeqOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 2 && "Invalid number of operands!");
+    auto regSeq = getRegSeq();
+
+    Inst.addOperand(MCOperand::createReg(regSeq.first));
+    Inst.addOperand(MCOperand::createReg(regSeq.second));
+  }
+
+  static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
+    if (ListFrom == ListTo && ListFrom == CSKY::R15)
+      return (1 << 4);
+    else if (ListFrom == ListTo && ListFrom == CSKY::R28)
+      return (1 << 8);
+    else if (ListFrom == CSKY::R4)
+      return ListTo - ListFrom + 1;
+    else if (ListFrom == CSKY::R16)
+      return ((ListTo - ListFrom + 1) << 5);
+    else
+      return 0;
+  }
+
+  void addRegListOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    auto regList = getRegList();
+
+    unsigned V = 0;
+
+    unsigned T = getListValue(regList.List1From, regList.List1To);
+    if (T != 0)
+      V = V | T;
+
+    T = getListValue(regList.List2From, regList.List2To);
+    if (T != 0)
+      V = V | T;
+
+    T = getListValue(regList.List3From, regList.List3To);
+    if (T != 0)
+      V = V | T;
+
+    T = getListValue(regList.List4From, regList.List4To);
+    if (T != 0)
+      V = V | T;
+
+    Inst.addOperand(MCOperand::createImm(V));
+  }
+
+  bool isValidForTie(const CSKYOperand &Other) const {
+    if (Kind != Other.Kind)
+      return false;
+
+    switch (Kind) {
+    default:
+      llvm_unreachable("Unexpected kind");
+      return false;
+    case Register:
+      return Reg.RegNum == Other.Reg.RegNum;
+    }
+  }
 };
 } // end anonymous namespace.
 
@@ -298,9 +616,7 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   default:
     break;
   case Match_Success:
-    Inst.setLoc(IDLoc);
-    Out.emitInstruction(Inst, getSTI());
-    return false;
+    return processInstruction(Inst, IDLoc, Operands, Out);
   case Match_MissingFeature: {
     assert(MissingFeatures.any() && "Unknown missing features!");
     ListSeparator LS;
@@ -346,26 +662,79 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   switch (Result) {
   default:
     break;
+  case Match_InvalidSImm8:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
+                                      (1 << 7) - 1);
+  case Match_InvalidOImm3:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
+  case Match_InvalidOImm4:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
+  case Match_InvalidOImm5:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
+  case Match_InvalidOImm6:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
+  case Match_InvalidOImm8:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
   case Match_InvalidOImm12:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
   case Match_InvalidOImm16:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
+  case Match_InvalidUImm1:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
   case Match_InvalidUImm2:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
+  case Match_InvalidUImm3:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
+  case Match_InvalidUImm4:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
   case Match_InvalidUImm5:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
+  case Match_InvalidUImm6:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
+  case Match_InvalidUImm7:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
+  case Match_InvalidUImm8:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
   case Match_InvalidUImm12:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
+  case Match_InvalidUImm16:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
+  case Match_InvalidUImm5Shift1:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 5) - 2,
+        "immediate must be a multiple of 2 bytes in the range");
   case Match_InvalidUImm12Shift1:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, 0, (1 << 12) - 2,
         "immediate must be a multiple of 2 bytes in the range");
+  case Match_InvalidUImm5Shift2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 5) - 4,
+        "immediate must be a multiple of 4 bytes in the range");
+  case Match_InvalidUImm7Shift1:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 7) - 2,
+        "immediate must be a multiple of 2 bytes in the range");
+  case Match_InvalidUImm7Shift2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 7) - 4,
+        "immediate must be a multiple of 4 bytes in the range");
+  case Match_InvalidUImm8Shift2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 8) - 4,
+        "immediate must be a multiple of 4 bytes in the range");
+  case Match_InvalidUImm8Shift3:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 8) - 8,
+        "immediate must be a multiple of 8 bytes in the range");
+  case Match_InvalidUImm8Shift8:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 8) - 256,
+        "immediate must be a multiple of 256 bytes in the range");
   case Match_InvalidUImm12Shift2:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, 0, (1 << 12) - 4,
         "immediate must be a multiple of 4 bytes in the range");
-  case Match_InvalidUImm16:
-    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
   case Match_InvalidCSKYSymbol: {
     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(ErrorLoc, "operand must be a symbol name");
@@ -374,15 +743,64 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(ErrorLoc, "operand must be a constpool symbol name");
   }
+  case Match_InvalidPSRFlag: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "psrset operand is not valid");
+  }
+  case Match_InvalidRegSeq: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "Register sequence is not valid");
   }
-
+  case Match_InvalidRegOutOfRange: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "register is out of range");
+  }
+  case Match_RequiresSameSrcAndDst: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "src and dst operand must be same");
+  }
+  case Match_InvalidRegList: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "invalid register list");
+  }
+  }
+  LLVM_DEBUG(dbgs() << "Result = " << Result);
   llvm_unreachable("Unknown match type detected!");
 }
 
+bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
+                                       OperandVector &Operands,
+                                       MCStreamer &Out) {
+
+  if (Inst.getOpcode() == CSKY::LDQ32 || Inst.getOpcode() == CSKY::STQ32) {
+    if (Inst.getOperand(1).getReg() != CSKY::R4 ||
+        Inst.getOperand(2).getReg() != CSKY::R7) {
+      return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
+    }
+    Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
+    Out.emitInstruction(Inst, getSTI());
+    return false;
+  } else if (Inst.getOpcode() == CSKY::SEXT32 ||
+             Inst.getOpcode() == CSKY::ZEXT32) {
+    if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
+      return Error(IDLoc, "msb must be greater or equal to lsb");
+  } else if (Inst.getOpcode() == CSKY::INS32) {
+    if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
+      return Error(IDLoc, "msb must be greater or equal to lsb");
+  } else if (Inst.getOpcode() == CSKY::IDLY32) {
+    if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
+      return Error(IDLoc, "n must be in range [0,32]");
+  }
+
+  Out.emitInstruction(Inst, getSTI());
+  return false;
+}
+
 // Attempts to match Name as a register (either using the default name or
 // alternative ABI names), setting RegNo to the matching register. Upon
 // failure, returns true and sets RegNo to 0.
-static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
+static bool matchRegisterNameHelper(const MCSubtargetInfo &STI,
+                                    MCRegister &RegNo, StringRef Name) {
   RegNo = MatchRegisterName(Name);
 
   if (RegNo == CSKY::NoRegister)
@@ -398,12 +816,12 @@ bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
   EndLoc = Tok.getEndLoc();
   StringRef Name = getLexer().getTok().getIdentifier();
 
-  if (!matchRegisterNameHelper((MCRegister &)RegNo, Name)) {
+  if (!matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name)) {
     getParser().Lex(); // Eat identifier token.
     return false;
   }
 
-  return Error(StartLoc, "invalid register name");
+  return MatchOperand_NoMatch;
 }
 
 OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
@@ -417,7 +835,7 @@ OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
     StringRef Name = getLexer().getTok().getIdentifier();
     MCRegister RegNo;
 
-    if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
+    if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
       return MatchOperand_NoMatch;
 
     getLexer().Lex();
@@ -438,7 +856,13 @@ OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
   if (parseRegister(Operands) != MatchOperand_Success) {
     getLexer().UnLex(Tok);
     Operands.pop_back();
-    return MatchOperand_ParseFail;
+    return MatchOperand_NoMatch;
+  }
+
+  if (getLexer().is(AsmToken::RParen)) {
+    Operands.push_back(CSKYOperand::createToken(")", getLoc()));
+    getParser().Lex(); // Eat ')'
+    return MatchOperand_Success;
   }
 
   if (getLexer().isNot(AsmToken::Comma)) {
@@ -494,8 +918,10 @@ OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
 
   const MCExpr *IdVal;
   SMLoc S = getLoc();
-  if (getParser().parseExpression(IdVal))
+  if (getParser().parseExpression(IdVal)) {
+    Error(getLoc(), "unknown expression");
     return MatchOperand_ParseFail;
+  }
 
   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
   Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
@@ -516,17 +942,26 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
     return true;
 
   // Attempt to parse token as register
-  if (parseRegister(Operands) == MatchOperand_Success)
+  auto Res = parseRegister(Operands);
+  if (Res == MatchOperand_Success)
     return false;
+  else if (Res == MatchOperand_ParseFail)
+    return true;
 
   // Attempt to parse token as (register, imm)
-  if (getLexer().is(AsmToken::LParen))
-    if (parseBaseRegImm(Operands) == MatchOperand_Success)
+  if (getLexer().is(AsmToken::LParen)) {
+    Res = parseBaseRegImm(Operands);
+    if (Res == MatchOperand_Success)
       return false;
+    else if (Res == MatchOperand_ParseFail)
+      return true;
+  }
 
-  // Attempt to parse token as a imm.
-  if (parseImmediate(Operands) == MatchOperand_Success)
+  Res = parseImmediate(Operands);
+  if (Res == MatchOperand_Success)
     return false;
+  else if (Res == MatchOperand_ParseFail)
+    return true;
 
   // Finally we have exhausted all options and must declare defeat.
   Error(getLoc(), "unknown operand");
@@ -536,16 +971,20 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
 OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
   SMLoc S = getLoc();
   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+  const MCExpr *Res;
 
   if (getLexer().getKind() != AsmToken::Identifier)
     return MatchOperand_NoMatch;
 
   StringRef Identifier;
-  if (getParser().parseIdentifier(Identifier))
+  AsmToken Tok = getLexer().getTok();
+
+  if (getParser().parseIdentifier(Identifier)) {
+    Error(getLoc(), "unknown identifier");
     return MatchOperand_ParseFail;
+  }
 
   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
-
   if (Identifier.consume_back("@GOT"))
     Kind = CSKYMCExpr::VK_CSKY_GOT;
   else if (Identifier.consume_back("@GOTOFF"))
@@ -554,44 +993,377 @@ OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
     Kind = CSKYMCExpr::VK_CSKY_PLT;
   else if (Identifier.consume_back("@GOTPC"))
     Kind = CSKYMCExpr::VK_CSKY_GOTPC;
+  else if (Identifier.consume_back("@TLSGD32"))
+    Kind = CSKYMCExpr::VK_CSKY_TLSGD;
+  else if (Identifier.consume_back("@GOTTPOFF"))
+    Kind = CSKYMCExpr::VK_CSKY_TLSIE;
+  else if (Identifier.consume_back("@TPOFF"))
+    Kind = CSKYMCExpr::VK_CSKY_TLSLE;
+  else if (Identifier.consume_back("@TLSLDM32"))
+    Kind = CSKYMCExpr::VK_CSKY_TLSLDM;
+  else if (Identifier.consume_back("@TLSLDO32"))
+    Kind = CSKYMCExpr::VK_CSKY_TLSLDO;
+
+  MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
+
+  if (!Sym)
+    Sym = getContext().getOrCreateSymbol(Identifier);
+
+  if (Sym->isVariable()) {
+    const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
+    if (!isa<MCSymbolRefExpr>(V)) {
+      getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
+      Error(getLoc(), "unknown symbol");
+      return MatchOperand_ParseFail;
+    }
+    Res = V;
+  } else
+    Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
 
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
-  const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+  MCBinaryExpr::Opcode Opcode;
+  switch (getLexer().getKind()) {
+  default:
+    if (Kind != CSKYMCExpr::VK_CSKY_None)
+      Res = CSKYMCExpr::create(Res, Kind, getContext());
 
-  if (Kind != CSKYMCExpr::VK_CSKY_None)
-    Res = CSKYMCExpr::create(Res, Kind, getContext());
+    Operands.push_back(CSKYOperand::createImm(Res, S, E));
+    return MatchOperand_Success;
+  case AsmToken::Plus:
+    Opcode = MCBinaryExpr::Add;
+    break;
+  case AsmToken::Minus:
+    Opcode = MCBinaryExpr::Sub;
+    break;
+  }
+
+  getLexer().Lex(); // eat + or -
 
+  const MCExpr *Expr;
+  if (getParser().parseExpression(Expr)) {
+    Error(getLoc(), "unknown expression");
+    return MatchOperand_ParseFail;
+  }
+  Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
   Operands.push_back(CSKYOperand::createImm(Res, S, E));
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+  const MCExpr *Res;
+
+  if (getLexer().getKind() != AsmToken::LBrac)
+    return MatchOperand_NoMatch;
+
+  getLexer().Lex(); // Eat '['.
+
+  if (getLexer().getKind() != AsmToken::Identifier) {
+    const MCExpr *Expr;
+    if (getParser().parseExpression(Expr)) {
+      Error(getLoc(), "unknown expression");
+      return MatchOperand_ParseFail;
+    }
+
+    if (getLexer().getKind() != AsmToken::RBrac) {
+      Error(getLoc(), "expected ]");
+      return MatchOperand_ParseFail;
+    }
+
+    getLexer().Lex(); // Eat ']'.
+
+    Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
+    return MatchOperand_Success;
+  }
+
+  AsmToken Tok = getLexer().getTok();
+  StringRef Identifier;
+
+  if (getParser().parseIdentifier(Identifier)) {
+    Error(getLoc(), "unknown identifier " + Identifier);
+    return MatchOperand_ParseFail;
+  }
+
+  CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
+  if (Identifier.consume_back("@GOT"))
+    Kind = CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4;
+  else if (Identifier.consume_back("@PLT"))
+    Kind = CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4;
+
+  MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
+
+  if (!Sym)
+    Sym = getContext().getOrCreateSymbol(Identifier);
+
+  if (Sym->isVariable()) {
+    const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
+    if (!isa<MCSymbolRefExpr>(V)) {
+      getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
+      Error(getLoc(), "unknown symbol");
+      return MatchOperand_ParseFail;
+    }
+    Res = V;
+  } else {
+    Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+  }
+
+  MCBinaryExpr::Opcode Opcode;
+  switch (getLexer().getKind()) {
+  default:
+    Error(getLoc(), "unknown symbol");
+    return MatchOperand_ParseFail;
+  case AsmToken::RBrac:
+
+    getLexer().Lex(); // Eat ']'.
+
+    if (Kind != CSKYMCExpr::VK_CSKY_None)
+      Res = CSKYMCExpr::create(Res, Kind, getContext());
+
+    Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
+    return MatchOperand_Success;
+  case AsmToken::Plus:
+    Opcode = MCBinaryExpr::Add;
+    break;
+  case AsmToken::Minus:
+    Opcode = MCBinaryExpr::Sub;
+    break;
+  }
+
+  getLexer().Lex(); // eat + or -
+
+  const MCExpr *Expr;
+  if (getParser().parseExpression(Expr)) {
+    Error(getLoc(), "unknown expression");
+    return MatchOperand_ParseFail;
+  }
+
+  if (getLexer().getKind() != AsmToken::RBrac) {
+    Error(getLoc(), "expected ']'");
+    return MatchOperand_ParseFail;
+  }
+
+  getLexer().Lex(); // Eat ']'.
+
+  Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
+  Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy
 CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
   SMLoc S = getLoc();
   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+  const MCExpr *Res;
 
   if (getLexer().getKind() != AsmToken::LBrac)
     return MatchOperand_NoMatch;
 
   getLexer().Lex(); // Eat '['.
 
-  if (getLexer().getKind() != AsmToken::Identifier)
-    return MatchOperand_NoMatch;
+  if (getLexer().getKind() != AsmToken::Identifier) {
+    const MCExpr *Expr;
+    if (getParser().parseExpression(Expr)) {
+      Error(getLoc(), "unknown expression");
+      return MatchOperand_ParseFail;
+    }
+
+    if (getLexer().getKind() != AsmToken::RBrac) {
+      Error(getLoc(), "expected ']'");
+      return MatchOperand_ParseFail;
+    }
+
+    getLexer().Lex(); // Eat ']'.
 
+    Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
+    return MatchOperand_Success;
+  }
+
+  AsmToken Tok = getLexer().getTok();
   StringRef Identifier;
-  if (getParser().parseIdentifier(Identifier))
+
+  if (getParser().parseIdentifier(Identifier)) {
+    Error(getLoc(), "unknown identifier");
     return MatchOperand_ParseFail;
+  }
 
-  if (getLexer().getKind() != AsmToken::RBrac)
-    return MatchOperand_NoMatch;
+  MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
+
+  if (!Sym)
+    Sym = getContext().getOrCreateSymbol(Identifier);
+
+  if (Sym->isVariable()) {
+    const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
+    if (!isa<MCSymbolRefExpr>(V)) {
+      getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
+      Error(getLoc(), "unknown symbol");
+      return MatchOperand_ParseFail;
+    }
+    Res = V;
+  } else {
+    Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+  }
+
+  MCBinaryExpr::Opcode Opcode;
+  switch (getLexer().getKind()) {
+  default:
+    Error(getLoc(), "unknown symbol");
+    return MatchOperand_ParseFail;
+  case AsmToken::RBrac:
+
+    getLexer().Lex(); // Eat ']'.
+
+    Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
+    return MatchOperand_Success;
+  case AsmToken::Plus:
+    Opcode = MCBinaryExpr::Add;
+    break;
+  case AsmToken::Minus:
+    Opcode = MCBinaryExpr::Sub;
+    break;
+  }
+
+  getLexer().Lex(); // eat + or -
+
+  const MCExpr *Expr;
+  if (getParser().parseExpression(Expr)) {
+    Error(getLoc(), "unknown expression");
+    return MatchOperand_ParseFail;
+  }
+
+  if (getLexer().getKind() != AsmToken::RBrac) {
+    Error(getLoc(), "expected ']'");
+    return MatchOperand_ParseFail;
+  }
 
   getLexer().Lex(); // Eat ']'.
 
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
-  const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
-  Operands.push_back(CSKYOperand::createImm(Res, S, E));
+  Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
+  Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+  unsigned Flag = 0;
+
+  while (getLexer().isNot(AsmToken::EndOfStatement)) {
+    StringRef Identifier;
+    if (getParser().parseIdentifier(Identifier)) {
+      Error(getLoc(), "unknown identifier " + Identifier);
+      return MatchOperand_ParseFail;
+    }
+
+    if (Identifier == "sie")
+      Flag = (1 << 4) | Flag;
+    else if (Identifier == "ee")
+      Flag = (1 << 3) | Flag;
+    else if (Identifier == "ie")
+      Flag = (1 << 2) | Flag;
+    else if (Identifier == "fe")
+      Flag = (1 << 1) | Flag;
+    else if (Identifier == "af")
+      Flag = (1 << 0) | Flag;
+    else {
+      Error(getLoc(), "expected " + Identifier);
+      return MatchOperand_ParseFail;
+    }
+
+    if (getLexer().is(AsmToken::EndOfStatement))
+      break;
+
+    if (getLexer().is(AsmToken::Comma)) {
+      getLexer().Lex(); // eat ','
+    } else {
+      Error(getLoc(), "expected ,");
+      return MatchOperand_ParseFail;
+    }
+  }
+
+  Operands.push_back(
+      CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  if (parseRegister(Operands) != MatchOperand_Success)
+    return MatchOperand_NoMatch;
+
+  auto Ry = Operands.back()->getReg();
+  Operands.pop_back();
+
+  if (getLexer().isNot(AsmToken::Minus)) {
+    Error(getLoc(), "expected '-'");
+    return MatchOperand_ParseFail;
+  }
+
+  getLexer().Lex(); // eat '-'
+
+  if (parseRegister(Operands) != MatchOperand_Success) {
+    Error(getLoc(), "invalid register");
+    return MatchOperand_ParseFail;
+  }
+
+  auto Rz = Operands.back()->getReg();
+  Operands.pop_back();
+
+  Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy CSKYAsmParser::parseRegList(OperandVector &Operands) {
+  SMLoc S = getLoc();
+
+  SmallVector<unsigned, 4> reglist;
+
+  while (true) {
+
+    if (parseRegister(Operands) != MatchOperand_Success) {
+      Error(getLoc(), "invalid register");
+      return MatchOperand_ParseFail;
+    }
+
+    auto Ry = Operands.back()->getReg();
+    Operands.pop_back();
+
+    if (getLexer().is(AsmToken::Minus)) {
+      getLexer().Lex(); // eat '-'
+
+      if (parseRegister(Operands) != MatchOperand_Success) {
+        Error(getLoc(), "invalid register");
+        return MatchOperand_ParseFail;
+      }
+
+      auto Rz = Operands.back()->getReg();
+      Operands.pop_back();
+
+      reglist.push_back(Ry);
+      reglist.push_back(Rz);
+
+      if (getLexer().is(AsmToken::Comma))
+        getLexer().Lex(); // eat ','
+      else if (getLexer().is(AsmToken::EndOfStatement))
+        break;
+
+    } else if (getLexer().is(AsmToken::Comma)) {
+      reglist.push_back(Ry);
+      reglist.push_back(Ry);
+
+      getLexer().Lex(); // eat ','
+    } else if (getLexer().is(AsmToken::EndOfStatement)) {
+      reglist.push_back(Ry);
+      reglist.push_back(Ry);
+      break;
+    } else {
+      Error(getLoc(), "invalid register list");
+      return MatchOperand_ParseFail;
+    }
+  }
+
+  Operands.push_back(CSKYOperand::createRegList(reglist, S));
   return MatchOperand_Success;
 }
 
@@ -637,7 +1409,7 @@ OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
 
   StringRef Name = getLexer().getTok().getIdentifier();
 
-  if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
+  if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
     return MatchOperand_NoMatch;
 
   getParser().Lex(); // Eat identifier token.
@@ -648,4 +1420,4 @@ bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
 
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
   RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
-}
+}
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/CMakeLists.txt b/llvm/lib/Target/CSKY/CMakeLists.txt
index c49c2a02e7f0..9b42413b4346 100644
--- a/llvm/lib/Target/CSKY/CMakeLists.txt
+++ b/llvm/lib/Target/CSKY/CMakeLists.txt
@@ -12,6 +12,7 @@ tablegen(LLVM CSKYGenSubtargetInfo.inc -gen-subtarget)
 add_public_tablegen_target(CSKYCommonTableGen)
 
 add_llvm_target(CSKYCodeGen
+  CSKYSubtarget.cpp
   CSKYTargetMachine.cpp
 
   LINK_COMPONENTS

diff  --git a/llvm/lib/Target/CSKY/CSKY.td b/llvm/lib/Target/CSKY/CSKY.td
index 854a8b5f22a2..31e34d78bbde 100644
--- a/llvm/lib/Target/CSKY/CSKY.td
+++ b/llvm/lib/Target/CSKY/CSKY.td
@@ -8,6 +8,80 @@
 
 include "llvm/Target/Target.td"
 
+//===----------------------------------------------------------------------===//
+// CSKY subtarget features and instruction predicates.
+//===----------------------------------------------------------------------===//
+
+// Atomic Support
+def FeatureExtendLrw : SubtargetFeature<"elrw", "HasExtendLrw", "true",
+                                        "Use the extend LRW instruction">;
+def HasExtendLrw : Predicate<"Subtarget->hasExtendLrw()">,
+                   AssemblerPredicate<(all_of FeatureExtendLrw),
+                   "Use the extend LRW instruction">;
+
+def FeatureDoloop : SubtargetFeature<"doloop", "HasDoloop", "true",
+                                     "Enable doloop instructions">;
+def HasDoloop : Predicate<"Subtarget->hasDoloop()">,
+                AssemblerPredicate<(all_of FeatureDoloop),
+                "Enable doloop instructions">;
+
+def HasE1
+    : SubtargetFeature<"e1", "HasE1", "true", "Support CSKY e1 instructions",
+                       [FeatureExtendLrw]>;
+def iHasE1 : Predicate<"Subtarget->hasE1()">,
+             AssemblerPredicate<(all_of HasE1),
+             "Support CSKY e1 instructions">;
+
+def HasE2
+    : SubtargetFeature<"e2", "HasE2", "true", "Support CSKY e2 instructions",
+                       [HasE1]>;
+def iHasE2 : Predicate<"Subtarget->hasE2()">,
+             AssemblerPredicate<(all_of HasE2),
+             "Support CSKY e2 instructions">;
+
+def Has2E3 : SubtargetFeature<"2e3", "Has2E3", "true",
+                              "Support CSKY 2e3 instructions", [HasE2]>;
+def iHas2E3 : Predicate<"Subtarget->has2E3()">,
+              AssemblerPredicate<(all_of Has2E3),
+              "Support CSKY 2e3 instructions">;
+
+def Has3E3r1 : SubtargetFeature<"3e3r1", "Has3E3r1", "true",
+                                "Support CSKY 3e3r1 instructions">;
+def iHas3E3r1 : Predicate<"Subtarget->has3E3r1()">,
+                AssemblerPredicate<(all_of Has3E3r1),
+                "Support CSKY 3e3r1 instructions">;
+
+def Has3r2E3r3
+    : SubtargetFeature<"3e3r3", "Has3r2E3r3", "true",
+                       "Support CSKY 3e3r3 instructions", [FeatureDoloop]>;
+def iHas3r2E3r3 : Predicate<"Subtarget->has3r2E3r3()">,
+                  AssemblerPredicate<(all_of Has3r2E3r3),
+                  "Support CSKY 3e3r3 instructions">;
+
+def Has3E7 : SubtargetFeature<"3e7", "Has3E7", "true",
+                              "Support CSKY 3e7 instructions", [Has2E3]>;
+def iHas3E7 : Predicate<"Subtarget->has3E7()">,
+              AssemblerPredicate<(all_of Has3E7),
+              "Support CSKY 3e7 instructions">;
+
+def HasMP1E2 : SubtargetFeature<"mp1e2", "HasMP1E2", "true",
+                                "Support CSKY mp1e2 instructions", [Has3E7]>;
+def iHasMP1E2 : Predicate<"Subtarget->hasMP1E2()">,
+                AssemblerPredicate<(all_of HasMP1E2),
+                "Support CSKY mp1e2 instructions">;
+
+def Has7E10 : SubtargetFeature<"7e10", "Has7E10", "true",
+                               "Support CSKY 7e10 instructions", [Has3E7]>;
+def iHas7E10 : Predicate<"Subtarget->has7E10()">,
+               AssemblerPredicate<(all_of Has7E10),
+               "Support CSKY 7e10 instructions">;
+
+def Has10E60 : SubtargetFeature<"10e60", "Has10E60", "true",
+                               "Support CSKY 10e60 instructions", [Has7E10]>;
+def iHas10E60 : Predicate<"Subtarget->has10E60()">,
+               AssemblerPredicate<(all_of Has10E60),
+               "Support CSKY 10e60 instructions">;
+
 //===----------------------------------------------------------------------===//
 // Registers, calling conventions, instruction descriptions.
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrFormats.td b/llvm/lib/Target/CSKY/CSKYInstrFormats.td
index dd71b693bbbb..101fd40d643e 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrFormats.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrFormats.td
@@ -24,7 +24,7 @@ class CSKYInst<AddrMode am, int sz, dag outs, dag ins, string asmstr,
   let Namespace = "CSKY";
   int Size = sz;
   AddrMode AM = am;
-
+  field bits<32> SoftFail = 0;
   let OutOperandList = outs;
   let InOperandList = ins;
   let AsmString = asmstr;
@@ -46,6 +46,11 @@ class CSKY32Inst<AddrMode am, bits<6> opcode, dag outs, dag ins, string asmstr,
   let Inst{31 - 26} = opcode;
 }
 
+class CSKY16Inst<AddrMode am, dag outs, dag ins, string asmstr, list<dag> pattern>
+  : CSKYInst<am, 2, outs, ins, asmstr, pattern> {
+  field bits<16> Inst;
+}
+
 // CSKY 32-bit instruction
 // Format< OP[6] | Offset[26] >
 // Instruction(1): bsr32
@@ -157,19 +162,7 @@ class I_16_RET<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
   let isTerminator = 1;
   let isReturn = 1;
   let isBarrier = 1;
-}
-
-// Instructions(1): rte32
-class I_16_RET_I<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), op, pattern> {
-  let Inst{25 - 21} = sop;
-  let Inst{20 - 16} = pcode;
-  let Inst{15 - 10} = 0x10;
-  let Inst{9 - 5} = 1;
-  let Inst{4 - 0} = 0;
-  let isTerminator = 1;
-  let isReturn = 1;
-  let isBarrier = 1;
+  let Uses = [ R15 ];
 }
 
 // Format< OP[6] | SOP[5] | RX[5] | IMM16[16] >
@@ -227,14 +220,27 @@ class I_LDST<AddrMode am, bits<6> opcode, bits<4> sop, dag outs, dag ins,
   let Inst{11 - 0} = imm12;
 }
 
+class I_PLDR<AddrMode am, bits<6> opcode, bits<4> sop, dag outs, dag ins,
+             string op, list<dag> pattern>
+    : CSKY32Inst<am, opcode, outs, ins, !strconcat(op, "\t($rx, ${imm12})"),
+                 pattern> {
+  bits<5> rx;
+  bits<12> imm12;
+  let Inst{25 - 21} = 0;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 12} = sop;
+  let Inst{11 - 0} = imm12;
+}
+
+
 // Format< OP[6] | RZ[5] | RX[5] | SOP[4] | OFFSET[12] >
-// Instructions(6): ld32.b, ld32.bs, ld32.h, ld32.hs, ld32.w, ld32.d
+// Instructions(6): ld32.b, ld32.bs, ld32.h, ld32.hs, ld32.w
 class I_LD<AddrMode am, bits<4> sop, string op, Operand operand>
     : I_LDST<am, 0x36, sop,
     (outs GPR:$rz), (ins GPR:$rx, operand:$imm12), op, []>;
 
 // Format< OP[6] | RZ[5] | RX[5] | SOP[4] | OFFSET[12] >
-// Instructions(4): st32.b, st32.h, st32.w, st32.d
+// Instructions(4): st32.b, st32.h, st32.w
 class I_ST<AddrMode am, bits<4> sop, string op, Operand operand>
     : I_LDST<am, 0x37, sop, (outs),
     (ins GPR:$rz, GPR:$rx, operand:$imm12), op, []>;
@@ -249,6 +255,8 @@ class I_12_PP<bits<5> sop, bits<5> pcode, dag outs, dag ins, string op>
   let Inst{20 - 16} = pcode;
   let Inst{15 - 12} = 0;
   let Inst{11 - 0} = regs;
+  let Uses = [R14];
+  let Defs = [R14];
 }
 
 // Format< OP[6] | RZ[5] | RX[5] | SOP[6] | PCODE[5] | IMM[5]>
@@ -256,7 +264,7 @@ class I_12_PP<bits<5> sop, bits<5> pcode, dag outs, dag ins, string op>
 class I_5_ZX<bits<6> sop, bits<5> pcode, string op, ImmLeaf ImmType,
              list<dag> pattern>
     : CSKY32Inst<AddrModeNone, 0x31, (outs GPR:$rz),
-    (ins GPR:$false, GPR:$rx, ImmType:$imm5),
+    (ins CARRY:$cond, GPR:$false, GPR:$rx, ImmType:$imm5),
     !strconcat(op, "\t$rz, $rx, $imm5"), pattern> {
   bits<5> rz;
   bits<5> rx;
@@ -272,9 +280,9 @@ class I_5_ZX<bits<6> sop, bits<5> pcode, string op, ImmLeaf ImmType,
 // Format< OP[6] | IMM[5] | RX[5] | SOP[6] | PCODE[5] | RZ[5]>
 // Instructions(13): decgt32, declt32, decne32, lsli32, lslc32, lsri32
 //                   lsrc32, asri32, asrc32, rotli32, xsr32, bclri32, bseti32
-class I_5_XZ<bits<6> sop, bits<5> pcode, string op, dag ins, dag outs,
+class I_5_XZ<bits<6> sop, bits<5> pcode, string op, dag outs, dag ins,
              list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x31, ins, outs,
+    : CSKY32Inst<AddrModeNone, 0x31, outs, ins,
                  !strconcat(op, "\t$rz, $rx, $imm5"), pattern> {
   bits<5> imm5;
   bits<5> rx;
@@ -286,19 +294,107 @@ class I_5_XZ<bits<6> sop, bits<5> pcode, string op, dag ins, dag outs,
   let Inst{4 - 0} = rz;
 }
 
+// mtcr32, mfcr32
+class I_5_XZ_CR<bits<6> sop, bits<5> pcode, string opStr, dag outs, dag ins,
+             list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x30, outs, ins, opStr, pattern> {
+  bits<5> sel;
+  bits<5> rx;
+  bits<5> cr;
+  let Inst{25 - 21} = sel;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = pcode;
+  let Inst{4 - 0} = cr;
+}
+
+// sync
+class I_5_XZ_SYNC<bits<6> sop, bits<5> pcode, string opStr, bits<1> S, bits<1> I>
+    : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), opStr, []> {
+  let Inst{25 - 21} = 0;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = pcode;
+  let Inst{4 - 0} = 0;
+  let Inst{25} = S;
+  let Inst{21} = I;
+
+}
+
+// Priviledged Instructions
+class I_5_XZ_PRIVI<bits<6> sop, bits<5> pcode, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), opStr, []> {
+  let Inst{25 - 21} = 0;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = pcode;
+  let Inst{4 - 0} = 0;
+}
+
+class I_CP<bits<4> sop, dag outs, dag ins, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x3f, outs, ins, opStr, []> {
+  bits<5> cpid;
+  bits<12> usdef;
+  let Inst{25 - 21} = cpid;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 12} = sop;
+  let Inst{11 - 0} = usdef;
+}
+
+class I_CPOP<dag outs, dag ins, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x3f, outs, ins, opStr, []> {
+  bits<5> cpid;
+  bits<20> usdef;
+  let Inst{25 - 21} = cpid;
+  let Inst{20 - 16} = usdef{19-15};
+  let Inst{15} = 1;
+  let Inst{14 - 0} = usdef{14-0};
+}
+
+class I_CP_Z<bits<4> sop, dag outs, dag ins, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x3f, outs, ins, opStr, []> {
+  bits<5> cpid;
+  bits<12> usdef;
+  bits<5> rz;
+
+  let Inst{25 - 21} = cpid;
+  let Inst{20 - 16} = rz;
+  let Inst{15 - 12} = sop;
+  let Inst{11 - 0} = usdef;
+}
+
+class I_5_CACHE<bits<6> sop, bits<5> pcode, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), opStr, []> {
+  let Inst{25 - 21} = pcode;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
+class I_5_X_CACHE<bits<6> sop, bits<5> pcode, string opStr>
+    : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins GPR:$rx), opStr #"\t$rx", []> {
+  bits<5> rx;
+
+  let Inst{25 - 21} = pcode;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
 // Format< OP[6] | RY[5] | RX[5] | SOP[6] | PCODE[5] | IMM[5]>
 // Instructions(2): ldm32, (ldq32), stm32, (stq32)
-class I_5_YX<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern,
-             bits<5> imm5>
-    : CSKY32Inst<AddrModeNone, opcode, outs, ins,
-                 op #"\t${ry}, (${rx}), " #!cast<int>(imm5), pattern> {
+class I_5_YX<bits<6> opcode, bits<6> sop, dag outs, dag ins, string opStr, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, opcode, outs, ins, opStr, pattern> {
+  bits<10> regs;
   bits<5> rx;
-  bits<5> ry;
-  let Inst{25 - 21} = ry; // ry
+
+  let Inst{25 - 21} = regs{9 - 5}; // ry
   let Inst{20 - 16} = rx;
-  let Inst{15 - 10} = 0b000111;
+  let Inst{15 - 10} = sop;
   let Inst{9 - 5} = 0b00001;
-  let Inst{4 - 0} = imm5{4 - 0}; // imm5
+  let Inst{4 - 0} = regs{4 - 0}; // imm5
 }
 
 // Format< OP[6] | LSB[5] | RX[5] | SOP[6] | MSB[5] | RZ[5]>
@@ -317,14 +413,33 @@ class I_5_XZ_U<bits<6> sop, dag outs, dag ins, string op, list<dag> pattern>
   let Inst{4 - 0} = rz;
 }
 
-// sextb, sexth
-class I_5_XZ_US<bits<6> sop, string op, SDNode opnode,
-  ValueType type> : I_5_XZ_U<sop, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), op,
-    [(set GPR:$rz, (opnode GPR:$rx, type))]>;
+class I_5_XZ_INS<bits<6> sop, dag outs, dag ins, string op, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x31, outs, ins, op #"\t$rz, $rx, $msb, $lsb",
+                 pattern> {
+  bits<5> rx;
+  bits<5> rz;
+  bits<5> msb;
+  bits<5> lsb;
+  let Inst{25 - 21} = rz;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = msb;
+  let Inst{4 - 0} = lsb;
+}
 
-class I_5_XZ_UZ<bits<6> sop, string op, int v>
-    : I_5_XZ_U<sop, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), op,
-    [(set GPR:$rz, (and GPR:$rx, (i32 v)))]>;
+// Format< OP[6] | LSB[5] | RX[5] | SOP[6] | MSB[5] | RZ[5]>
+// Instructions(6): zext32, zextb32, zexth32, sext32, sextb32, sexth32
+class I_5_XZ_U2<bits<6> sop, bits<5> lsb, bits<5> msb, dag outs, dag ins,
+  string op, list<dag> pattern>
+  : CSKY32Inst<AddrModeNone, 0x31, outs, ins, !strconcat(op, "\t$rz, $rx"), pattern> {
+  bits<5> rx;
+  bits<5> rz;
+  let Inst{25 - 21} = lsb;     // lsb
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = msb;       // msb
+  let Inst{4 - 0} = rz;
+}
 
 // Format< OP[6] | RZ[5] | RX[5] | SOP[6] | SIZE[5] | LSB[5]>
 // Instructions(1): ins32
@@ -341,6 +456,16 @@ class I_5_ZX_U<bits<6> sop, string op, Operand operand, list<dag> pattern>
   let Inst{4 - 0} = size_lsb{4 - 0}; // lsb
 }
 
+// sextb, sexth
+class I_5_XZ_US<bits<6> sop, bits<5> lsb, bits<5> msb, string op,
+  SDNode opnode, ValueType type>
+  : I_5_XZ_U2<sop, lsb, msb, (outs GPR:$rz), (ins GPR:$rx), op,
+  [(set GPR:$rz, (opnode GPR:$rx, type))]>;
+
+class I_5_XZ_UZ<bits<6> sop, bits<5> lsb, bits<5> msb, string op, int v>
+  : I_5_XZ_U2<sop, lsb, msb, (outs GPR:$rz), (ins GPR:$rx), op,
+  [(set GPR:$rz, (and GPR:$rx, (i32 v)))]>;
+
 // Format< OP[6] | IMM[5] | RX[5] | SOP[6] | PCODE[5] | 00000 >
 // Instructions(1): btsti32
 class I_5_X<bits<6> sop, bits<5> pcode, string op, ImmLeaf ImmType,
@@ -373,6 +498,18 @@ class I_5_Z<bits<6> sop, bits<5> pcode, string op, ImmLeaf ImmType,
   let Inst{4 - 0} = rz;
 }
 
+class I_5_IMM5<bits<6> opcode, bits<6> sop, bits<5> pcode, string op, ImmLeaf ImmType,
+            list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, opcode, (outs), (ins ImmType:$imm5),
+                 !strconcat(op, "\t$imm5"), pattern> {
+  bits<5> imm5;
+  let Inst{25 - 21} = imm5;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = sop;
+  let Inst{9 - 5} = pcode;
+  let Inst{4 - 0} = 0;
+}
+
 // Format< OP[6] | RY[5] | RX[5] | SOP[6] | PCODE[5] | RZ[5] >
 // Instructions(24): addu32, addc32, subu32, subc32, (rsub32), ixh32, ixw32,
 // ixd32, and32, andn32, or32, xor32, nor32, lsl32, lsr32, asr32, rotl32
@@ -493,9 +630,8 @@ class R_ZX<bits<6> sop, bits<5> pcode, string op, list<dag> pattern>
 
 // Format< OP[6] | 00000[5] | RX[5] | SOP[6] | PCODE[5] | 00000[5] >
 // Instructions:(1) tstnbz32
-class R_X<bits<6> sop, bits<5> pcode, string op, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x31, (outs CARRY:$ca),(ins GPR:$rx),
-                 !strconcat(op, "\t$rx"), pattern> {
+class R_X<bits<6> sop, bits<5> pcode, dag outs, dag ins, string op, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x31, outs, ins, !strconcat(op, "\t$rx"), pattern> {
   bits<5> rx;
   let Inst{25 - 21} = 0;
   let Inst{20 - 16} = rx;
@@ -530,3 +666,14 @@ class R_Z_2<bits<6> sop, bits<5> pcode, string op, list<dag> pattern>
   let Inst{4 - 0} = 0;
   let Constraints = "$rz = $false";
 }
+
+class BAR<bits<5> sop, string op, bits<1> signed>
+  : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), op, []> {
+  let Inst{25} = signed;
+  let Inst{24 - 16} = 0;
+  let Inst{15 - 5} = 0x421;
+  let Inst{4 - 0} = sop;
+  let hasSideEffects = 1;
+  let mayLoad = 0;
+  let mayStore = 0;
+}
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index 20adda4f9ca2..0db7cbc333e7 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -15,6 +15,18 @@
 // CSKY specific DAG Nodes.
 //===----------------------------------------------------------------------===//
 
+def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
+                                       SDTCisVT<1, i32>]>;
+
+def SDT_CallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, i32>,
+                                     SDTCisVT<1, i32>]>;
+
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
+                           [SDNPHasChain, SDNPOutGlue]>;
+
+def callseq_end   : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
+                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
 // Target-dependent nodes.
 def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone,
     [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
@@ -44,6 +56,7 @@ class oimm<int num> : Operand<i32>,
   ImmLeaf<i32, "return isUInt<"#num#">(Imm - 1);"> {
   let EncoderMethod = "getOImmOpValue";
   let ParserMatchClass = OImmAsmOperand<num>;
+  let DecoderMethod = "decodeOImmOperand<"#num#">";
 }
 
 class uimm<int num, int shift = 0> : Operand<i32>,
@@ -53,12 +66,14 @@ class uimm<int num, int shift = 0> : Operand<i32>,
     !if(!ne(shift, 0),
         UImmAsmOperand<num, "Shift"#shift>,
         UImmAsmOperand<num>);
+  let DecoderMethod = "decodeUImmOperand<"#num#", "#shift#">";
 }
 
 class simm<int num, int shift = 0> : Operand<i32>,
   ImmLeaf<i32, "return isShiftedInt<"#num#", "#shift#">(Imm);"> {
   let EncoderMethod = "getImmOpValue<"#shift#">";
   let ParserMatchClass = SImmAsmOperand<num>;
+  let DecoderMethod = "decodeSImmOperand<"#num#", "#shift#">";
 }
 
 def nimm_XFORM : SDNodeXForm<imm, [{
@@ -73,14 +88,19 @@ def uimm32_hi16 : SDNodeXForm<imm, [{
   return CurDAG->getTargetConstant((N->getZExtValue() >> 16) & 0xFFFF,
     SDLoc(N), MVT::i32);
 }]>;
+def uimm32_lo16 : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant(N->getZExtValue()& 0xFFFF, SDLoc(N), MVT::i32);
+}]>;
 def uimm16_16_xform : Operand<i32>,
   ImmLeaf<i32, "return isShiftedUInt<16, 16>(Imm);", uimm32_hi16> {
   let ParserMatchClass = UImmAsmOperand<16>;
+  let EncoderMethod = "getImmOpValue";
 }
 
 def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
   let EncoderMethod = "getImmShiftOpValue";
   let ParserMatchClass = UImmAsmOperand<2>;
+  let DecoderMethod = "decodeImmShiftOpValue";
 }
 
 def CSKYSymbol : AsmOperandClass {
@@ -94,16 +114,22 @@ def br_symbol : Operand<iPTR> {
   let EncoderMethod =
     "getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm16_scale2>";
   let ParserMatchClass = CSKYSymbol;
+  let DecoderMethod = "decodeSImmOperand<16, 1>";
+  let PrintMethod = "printCSKYSymbolOperand";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def call_symbol : Operand<iPTR> {
   let ParserMatchClass = CSKYSymbol;
   let EncoderMethod = "getCallSymbolOpValue";
+  let DecoderMethod = "decodeSImmOperand<26, 1>";
+  let PrintMethod = "printCSKYSymbolOperand";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def Constpool : AsmOperandClass {
-  let Name = "ConstpoolSymbol";
-  let RenderMethod = "addImmOperands";
+  let Name = "Constpool";
+  let RenderMethod = "addConstpoolOperands";
   let DiagnosticType = "InvalidConstpool";
   let ParserMethod = "parseConstpoolSymbol";
 }
@@ -112,24 +138,132 @@ def constpool_symbol : Operand<iPTR> {
   let ParserMatchClass = Constpool;
   let EncoderMethod =
     "getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm16_scale4>";
+  let DecoderMethod = "decodeUImmOperand<16, 2>";
+  let PrintMethod = "printConstpool";
+  let OperandType = "OPERAND_PCREL";
+}
+
+def DataAsmClass : AsmOperandClass {
+  let Name = "DataSymbol";
+  let RenderMethod = "addConstpoolOperands";
+  let DiagnosticType = "InvalidConstpool";
+  let ParserMethod = "parseDataSymbol";
+}
+
+class data_symbol<string reloc, int shift> : Operand<iPTR> {
+  let ParserMatchClass = Constpool;
+  let EncoderMethod =
+    "getDataSymbolOpValue<"#reloc#">";
+  let DecoderMethod = "decodeUImmOperand<18, "#shift#">";
+  let PrintMethod = "printDataSymbol";
 }
 
 def bare_symbol : Operand<iPTR> {
   let ParserMatchClass = CSKYSymbol;
   let EncoderMethod = "getBareSymbolOpValue";
+  let PrintMethod = "printCSKYSymbolOperand";
+  let DecoderMethod = "decodeSImmOperand<18, 1>";
+  let OperandType = "OPERAND_PCREL";
+}
+
+def oimm3 : oimm<3>;
+def oimm4 : oimm<4>;
+def oimm5 : oimm<5>;
+def oimm6 : oimm<6>;
+
+def imm5_idly : Operand<i32>, ImmLeaf<i32,
+  "return Imm <= 32 && Imm >= 0;"> {
+  let EncoderMethod = "getImmOpValueIDLY";
+  let DecoderMethod = "decodeOImmOperand<5>";
 }
 
+def oimm8 : oimm<8>;
 def oimm12 : oimm<12>;
 def oimm16 : oimm<16>;
 
 def nimm12 : nimm<12>;
 
+def uimm1 : uimm<1>;
+def uimm2 : uimm<2>;
+
+
+def uimm2_jmpix : Operand<i32>,
+  ImmLeaf<i32, "return Imm == 16 || Imm == 24 || Imm == 32 || Imm == 40;"> {
+  let EncoderMethod = "getImmJMPIX";
+  let DecoderMethod = "decodeJMPIXImmOperand";
+}
+
+def uimm3 : uimm<3>;
+def uimm4 : uimm<4>;
 def uimm5 : uimm<5>;
+def uimm5_msb_size : uimm<5> {
+  let EncoderMethod = "getImmOpValueMSBSize";
+}
+
+def uimm5_1 : uimm<5, 1>;
+def uimm5_2 : uimm<5, 2>;
+def uimm6 : uimm<6>;
+def uimm7 : uimm<7>;
+def uimm7_1 : uimm<7, 1>;
+def uimm7_2 : uimm<7, 2>;
+def uimm7_3 : uimm<7, 3>;
+def uimm8 : uimm<8>;
+def uimm8_2 : uimm<8, 2>;
+def uimm8_3 : uimm<8, 3>;
+def uimm8_8 : uimm<8, 8>;
+def uimm8_16 : uimm<8, 16>;
+def uimm8_24 : uimm<8, 24>;
 def uimm12 : uimm<12>;
 def uimm12_1 : uimm<12, 1>;
 def uimm12_2 : uimm<12, 2>;
 def uimm16 : uimm<16>;
+def uimm16_8 : uimm<16, 8>;
+def uimm16_16 : uimm<16, 16>;
+def uimm20 : uimm<20>;
+def uimm24 : uimm<24>;
+def uimm24_8 : uimm<24, 8>;
+
+def simm8_2 : simm<8, 2>;
+
+class RegSeqAsmOperand<string Suffix = ""> : AsmOperandClass {
+  let Name = "RegSeq"#Suffix;
+  let RenderMethod = "addRegSeqOperands";
+  let DiagnosticType = "InvalidRegSeq";
+  let ParserMethod = "parseRegSeq";
+}
+
+def regseq : Operand<iPTR> {
+  let EncoderMethod = "getRegisterSeqOpValue";
+  let ParserMatchClass = RegSeqAsmOperand<"">;
+  let PrintMethod = "printRegisterSeq";
+  let DecoderMethod = "DecodeRegSeqOperand";
+  let MIOperandInfo = (ops GPR, uimm5);
+}
 
+def RegListAsmOperand : AsmOperandClass {
+  let Name = "RegList";
+  let RenderMethod = "addRegListOperands";
+  let DiagnosticType = "InvalidRegList";
+  let ParserMethod = "parseRegList";
+}
+
+def reglist : Operand<iPTR> {
+  let ParserMatchClass = RegListAsmOperand;
+  let PrintMethod = "printRegisterList";
+}
+
+def PSRFlag : AsmOperandClass {
+  let Name = "PSRFlag";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = "InvalidPSRFlag";
+  let ParserMethod = "parsePSRFlag";
+}
+
+def psrflag : Operand<i32>, ImmLeaf<i32, "return isShiftedUInt<5, 0>(Imm);"> {
+  let EncoderMethod = "getImmOpValue";
+  let ParserMatchClass = PSRFlag;
+  let PrintMethod = "printPSRFlag";
+}
 
 //===----------------------------------------------------------------------===//
 // Instruction Formats
@@ -145,12 +279,33 @@ class TriOpFrag<dag res> : PatFrag<(ops node: $LHS, node:$MHS, node:$RHS), res>;
 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
 class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
 
+def eqToAdd : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs), [{
+  return isOrEquivalentToAdd(N);
+}]>;
+
+def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
+
+
+//===----------------------------------------------------------------------===//
+// CSKYPseudo
+//===----------------------------------------------------------------------===//
+
+// Pessimistically assume the stack pointer will be clobbered
+let Defs = [R14], Uses = [R14] in {
+def ADJCALLSTACKDOWN : CSKYPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+  "!ADJCALLSTACKDOWN $amt1, $amt2", [(callseq_start timm:$amt1, timm:$amt2)]>;
+def ADJCALLSTACKUP   : CSKYPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+  "!ADJCALLSTACKUP $amt1, $amt2", [(callseq_end timm:$amt1, timm:$amt2)]>;
+} // Defs = [R14], Uses = [R14]
 
 
 //===----------------------------------------------------------------------===//
 // Basic ALU instructions.
 //===----------------------------------------------------------------------===//
 
+let Predicates = [iHasE2] in {
+  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+  let isAdd = 1 in
   def ADDI32 : I_12<0x0, "addi32", add, oimm12>;
   def SUBI32 : I_12<0x1, "subi32", sub, oimm12>;
   def ORI32 : I_16_ZX<"ori32", uimm16,
@@ -171,11 +326,15 @@ class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
     (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
     [(set GPR:$rz, (rotl GPR:$rx, uimm5:$imm5))]>;
 
-
+  def ROTRI32 : CSKYPseudo<(outs GPR:$rz), (ins GPR:$rx, oimm5:$imm5),
+                            "rotri32 $rz, $rx, $imm5", []>;
+  }
+  let isAdd = 1 in
   def ADDU32 : R_YXZ_SP_F1<0x0, 0x1,
     BinOpFrag<(add node:$LHS, node:$RHS)>, "addu32", 1>;
   def SUBU32 : R_YXZ_SP_F1<0x0, 0x4,
     BinOpFrag<(sub node:$LHS, node:$RHS)>, "subu32">;
+
   def MULT32 : R_YXZ_SP_F1<0x21, 0x1,
     BinOpFrag<(mul node:$LHS, node:$RHS)>, "mult32", 1>;
   def AND32 : R_YXZ_SP_F1<0x8, 0x1,
@@ -188,8 +347,16 @@ class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
     BinOpFrag<(xor node:$LHS, node:$RHS)>, "xor32", 1>;
   def NOR32 : R_YXZ_SP_F1<0x9, 0x4,
     BinOpFrag<(not (or node:$LHS, node:$RHS))>, "nor32", 1>;
+  let isCodeGenOnly = 1 in
   def NOT32 : R_XXZ<0b001001, 0b00100, (outs GPR:$rz), (ins GPR:$rx),
     "not32", [(set GPR:$rz, (not GPR:$rx))]>;
+
+  let Size = 8 in
+  def NEG32 : CSKYPseudo<(outs GPR:$rd), (ins GPR:$rx), "neg32 $rd, $rx", []>;
+
+  let Size = 8 in
+  def RSUBI32 : CSKYPseudo<(outs GPR:$rd), (ins GPR:$rx, uimm12:$imm12), "rsubi32 $rd, $rx, $imm12", []>;
+
   def LSL32 : R_YXZ_SP_F1<0x10, 0x1,
     BinOpFrag<(shl node:$LHS, node:$RHS)>, "lsl32">;
   def LSR32 : R_YXZ_SP_F1<0x10, 0x2,
@@ -199,23 +366,37 @@ class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
   def ROTL32 : R_YXZ_SP_F1<0x10, 0x8,
     BinOpFrag<(rotl node:$LHS, (and node:$RHS, 0x1f))>, "rotl32">;
 
-  // TODO: Shift series instr. with carry.
+  def BMASKI32 : I_5_Z<0b010100, 0x1, "bmaski32", oimm5, []>;
+  def LSLC32 : I_5_XZ<0x13, 0x1, "lslc32",
+    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>;
+  def LSRC32 : I_5_XZ<0x13, 0x2, "lsrc32",
+    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>;
+  def ASRC32 : I_5_XZ<0x13, 0x4, "asrc32",
+    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>;
+  def XSR32 : I_5_XZ<0x13, 0x8, "xsr32",
+    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5, CARRY:$cin), []>;
 
   def IXH32 : R_YXZ_SP_F1<0x2, 0x1,
     BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 1)))>, "ixh32">;
   def IXW32 : R_YXZ_SP_F1<0x2, 0x2,
     BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 2)))>, "ixw32">;
-
+  let Predicates = [iHas2E3] in
   def IXD32 : R_YXZ_SP_F1<0x2, 0x4,
     BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 3)))>, "ixd32">;
 
-  let isCommutable = 1 in
+  let isCommutable = 1, isAdd = 1 in
   def ADDC32 : R_YXZ<0x31, 0x0, 0x2, (outs GPR:$rz, CARRY:$cout),
     (ins GPR:$rx, GPR:$ry, CARRY:$cin), "addc32", []>;
   def SUBC32 : R_YXZ<0x31, 0x0, 0x8, (outs GPR:$rz, CARRY:$cout),
     (ins GPR:$rx, GPR:$ry, CARRY:$cin), "subc32", []>;
 
-  // TODO: incf32.
+  def INCF32 : I_5_ZX<0x3, 0x1, "incf32", uimm5, []>;
+  def INCT32 : I_5_ZX<0x3, 0x2, "inct32", uimm5, []>;
+  def DECF32 : I_5_ZX<0x3, 0x4, "decf32", uimm5, []>;
+  def DECT32 : I_5_ZX<0x3, 0x8, "dect32", uimm5, []>;
+}
+
+let Predicates = [iHas2E3] in {
   def DIVS32 : R_YXZ_SP_F1<0x20, 0x2,
     BinOpFrag<(sdiv node:$LHS, node:$RHS)>, "divs32">;
   def DIVU32 : R_YXZ_SP_F1<0x20, 0x1,
@@ -228,11 +409,35 @@ class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
   def DECNE32 : I_5_XZ<0x4, 0x4, "decne32",
     (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, uimm5:$imm5), []>;
 
-  // TODO: s/zext.
-  def ZEXT32 : I_5_XZ_U<0x15, (outs GPR:$rz),
-    (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",[]>;
-  def SEXT32 : I_5_XZ_U<0x16, (outs GPR:$rz),
-    (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32", []>;
+  def SEXT32 : I_5_XZ_U<0x16, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32", []>;
+  let isCodeGenOnly = 1 in {
+  def SEXTB32 : I_5_XZ_US<0x16, 0, 7, "sextb32", sext_inreg, i8>;
+  def SEXTH32 : I_5_XZ_US<0x16, 0, 15, "sexth32", sext_inreg, i16>;
+  def ZEXTB32 : I_5_XZ_UZ<0x15, 0, 7, "zextb32", 255>;
+  def ZEXTH32 : I_5_XZ_UZ<0x15, 0, 15, "zexth32", 65535>;
+  }
+  def ZEXT32 : I_5_XZ_U<0x15, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",[]>;
+
+  let Constraints = "$rZ = $rz" in
+  def INS32 : I_5_XZ_INS<0b010111, (outs GPR:$rz), (ins GPR:$rZ, GPR:$rx, uimm5_msb_size:$msb, uimm5:$lsb), "ins32", []>;
+}
+
+let Predicates = [iHas3E3r1] in {
+def MULTS32 : R_YXZ<0x3e, 0x20, 0x10, (outs GPRPair:$rz),
+    (ins GPR:$rx, GPR:$ry), "mul.s32", []>;
+def MULTU32 : R_YXZ<0x3e, 0x20, 0x00, (outs GPRPair:$rz),
+    (ins GPR:$rx, GPR:$ry), "mul.u32", []>;
+
+let Constraints = "$rZ = $rz" in {
+def MULATS32 : R_YXZ<0x3e, 0x20, 0x14, (outs GPRPair:$rZ),
+    (ins GPRPair:$rz, GPR:$rx, GPR:$ry), "mula.s32", []>;
+def MULATU32 : R_YXZ<0x3e, 0x20, 0x04, (outs GPRPair:$rZ),
+    (ins GPRPair:$rz, GPR:$rx, GPR:$ry), "mula.u32", []>;
+}
+}
+
+def MULSH32 : R_YXZ<0x31, 0b100100, 0b00001, (outs GPR:$rz),
+    (ins GPR:$rx, GPR:$ry), "mulsh32", []>;
 
 //===----------------------------------------------------------------------===//
 // Load & Store instructions.
@@ -242,18 +447,35 @@ def LD32B : I_LD<AddrMode32B, 0x0, "ld32.b", uimm12>;
 def LD32H : I_LD<AddrMode32H, 0x1, "ld32.h", uimm12_1>;
 def LD32W : I_LD<AddrMode32WD, 0x2, "ld32.w", uimm12_2>;
 
+let OutOperandList = (outs GPRPair:$rz) in
+def LD32D : I_LD<AddrMode32WD, 0x3, "ld32.d", uimm12_2>;
 
+let Predicates = [iHasE2] in {
   def LD32BS : I_LD<AddrMode32B, 0x4, "ld32.bs", uimm12>;
   def LD32HS : I_LD<AddrMode32H, 0x5, "ld32.hs", uimm12_1>;
 
-  // TODO: LDM and STM.
+  def LDM32 : I_5_YX<0b110100, 0b000111,
+    (outs), (ins GPR:$rx, regseq:$regs, variable_ops), "ldm32\t$regs, (${rx})", []>;
+  def STM32 : I_5_YX<0b110101, 0b000111,
+    (outs), (ins GPR:$rx, regseq:$regs, variable_ops), "stm32\t$regs, (${rx})", []>;
+
+  let Size = 4, isCodeGenOnly = 0 in {
+  def LDQ32 : CSKYPseudo<(outs), (ins GPR:$rx, regseq:$regs, variable_ops),
+                             "ldq32\t$regs, (${rx})", []>;
+  def STQ32 : CSKYPseudo<(outs), (ins GPR:$rx, regseq:$regs, variable_ops),
+                             "stq32\t$regs, (${rx})", []>;
+  }
 
+}
 
 def ST32B : I_ST<AddrMode32B, 0x0, "st32.b", uimm12>;
 def ST32H : I_ST<AddrMode32H, 0x1, "st32.h", uimm12_1>;
 def ST32W : I_ST<AddrMode32WD, 0x2, "st32.w", uimm12_2>;
 
+let InOperandList = (ins GPRPair:$rz, GPR:$rx, uimm12_2:$imm12 ) in
+def ST32D : I_ST<AddrMode32WD, 0x3, "st32.d", uimm12_2>;
 
+let Predicates = [iHas2E3] in {
   def LDR32B :  I_LDR<0x0, "ldr32.b">;
   def LDR32BS :  I_LDR<0x4, "ldr32.bs">;
   def LDR32H :  I_LDR<0x1, "ldr32.h">;
@@ -262,42 +484,100 @@ def ST32W : I_ST<AddrMode32WD, 0x2, "st32.w", uimm12_2>;
   def STR32B :  I_STR<0x0, "str32.b">;
   def STR32H :  I_STR<0x1, "str32.h">;
   def STR32W :  I_STR<0x2, "str32.w">;
+}
+
+// Indicate that we're dumping the CR register, so we'll need to
+// scavenge a register for it.
+let mayStore = 1 in {
+def SPILL_CARRY : CSKYPseudo<(outs), (ins CARRY:$cond, GPR:$rx, uimm12_2:$imm),
+                             "!SPILL_CARRY $cond, $rx, $imm", []>;
+}
+
+// Indicate that we're restoring the CR register (previously
+// spilled), so we'll need to scavenge a register for it.
+let mayLoad = 1 in {
+def RESTORE_CARRY : CSKYPseudo<(outs CARRY:$cond), (ins GPR:$rx, uimm12_2:$imm),
+                                "!RESTORE_CARRY $cond, $rx, $imm", []>;
+}
+
+let mayLoad = 1 in {
+def STORE_PAIR : CSKYPseudo<(outs), (ins GPRPair:$rz, GPR:$rx, uimm12_2:$imm),
+                            "!STORE_PAIR $rz, $rx, $imm", []>;
+}
 
-  //TODO: SPILL_CARRY and RESTORE_CARRY.
+let mayLoad = 1 in {
+def LOAD_PAIR : CSKYPseudo<(outs GPRPair:$rz), (ins GPR:$rx, uimm12_2:$imm),
+                            "!LOAD_PAIR $rz, $rx, $imm", []>;
+}
 
 //===----------------------------------------------------------------------===//
 // Compare instructions.
 //===----------------------------------------------------------------------===//
-
+let Predicates = [iHasE2] in {
   def CMPNEI32 : I_16_X<0x1A, "cmpnei32", uimm16>;
   def CMPHSI32 : I_16_X<0x18, "cmphsi32", oimm16>;
   def CMPLTI32 : I_16_X<0x19, "cmplti32", oimm16>;
-
-
+  def CMPLEI32 : CSKYPseudo<(outs CARRY:$ca), (ins GPR:$rx, uimm16:$imm16),
+    "cmplei32\t$rx, $imm16", []>;
+}
+let Predicates = [iHas2E3] in {
   def CMPNE32 : R_YX<0x1, 0x4, "cmpne32">;
   def CMPHS32 : R_YX<0x1, 0x1, "cmphs32">;
   def CMPLT32 : R_YX<0x1, 0x2, "cmplt32">;
 
-  // TODO: setc and clrc.
-  // TODO: test32 and tstnbz.
+  def SETC32 : CSKY32Inst<AddrModeNone, 0x31,
+    (outs CARRY:$ca), (ins), "setc32", []> {
+    let Inst{25 - 21} = 0; //rx
+    let Inst{20 - 16} = 0; //ry
+    let Inst{15 - 10} = 0x1;
+    let Inst{9 - 5} = 0x1;
+    let Inst{4 - 0} = 0;
+    let isCompare = 1;
+  }
+  def CLRC32 : CSKY32Inst<AddrModeNone, 0x31,
+    (outs CARRY:$ca), (ins), "clrc32", []> {
+    let Inst{25 - 21} = 0; //rx
+    let Inst{20 - 16} = 0; //ry
+    let Inst{15 - 10} = 0x1;
+    let Inst{9 - 5} = 0x4;
+    let Inst{4 - 0} = 0;
+    let isCompare = 1;
+  }
+
+  def TST32 : R_YX<0x8, 0x4, "tst32">;
+  def TSTNBZ32 : R_X<0x8, 0x8,
+    (outs CARRY:$ca), (ins GPR:$rx), "tstnbz32", []>;
+}
 
 //===----------------------------------------------------------------------===//
 // Data move instructions.
 //===----------------------------------------------------------------------===//
 
+let Predicates= [iHasE2] in {
+  let isCodeGenOnly = 1 in {
   def MOVT32 : R_ZX<0x3, 0x2, "movt32", []>;
   def MOVF32 : R_ZX<0x3, 0x1, "movf32", []>;
+  }
   def MOVI32 : I_16_MOV<0x10, "movi32", uimm16>;
+  let Size = 4, isCodeGenOnly = 0 in
+  def BGENI : CSKYPseudo<(outs GPR:$dst), (ins uimm5:$imm), "bgeni\t$dst, $imm", []>;
+  def : InstAlias<"bgeni16 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>;
+  def : InstAlias<"bgeni32 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>;
   def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>;
   def MVC32 : R_Z_1<0x1, 0x8, "mvc32">;
+  let isCodeGenOnly = 1 in
   def MOV32 : R_XZ<0x12, 0x1, "mov32">;
 
-  // TODO: ISEL Pseudo.
+  let usesCustomInserter = 1 in
+  def ISEL32 : CSKYPseudo<(outs GPR:$dst), (ins CARRY:$cond, GPR:$src1, GPR:$src2),
+    "!isel32\t$dst, $src1, src2", [(set GPR:$dst, (select CARRY:$cond, GPR:$src1, GPR:$src2))]>;
+}
 
+let Predicates = [iHas2E3] in {
   def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">;
-  // TODO: clrf and clrt.
   def CLRF32 : R_Z_2<0xB, 0x1, "clrf32", []>;
   def CLRT32 : R_Z_2<0xB, 0x2, "clrt32", []>;
+}
 
 //===----------------------------------------------------------------------===//
 // Branch and call instructions.
@@ -309,12 +589,12 @@ let isBranch = 1, isTerminator = 1 in {
                      [(br bb:$imm16)]>;
 
   def BT32 : I_16_L<0x3, (outs), (ins CARRY:$ca, br_symbol:$imm16),
-    "bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>;
+    "bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>, Requires<[iHasE2]>;
   def BF32 : I_16_L<0x2, (outs), (ins CARRY:$ca, br_symbol:$imm16),
-    "bf32\t$imm16", []>;
+    "bf32\t$imm16", []>, Requires<[iHasE2]>;
 }
 
-
+let Predicates = [iHas2E3] in {
   def BEZ32 : I_16_X_L<0x8, "bez32", br_symbol>;
   def BNEZ32 : I_16_X_L<0x9, "bnez32", br_symbol>;
   def BHZ32 : I_16_X_L<0xA, "bhz32", br_symbol>;
@@ -334,10 +614,25 @@ let isBranch = 1, isTerminator = 1 in {
   let isCall = 1, Defs = [ R15 ] , mayLoad = 1 in
     def JSRI32: I_16_L<0x17, (outs),
       (ins constpool_symbol:$imm16), "jsri32\t$imm16", []>;
+}
 
+def BNEZAD32 : CSKY32Inst<AddrModeNone, 0x3a,
+  (outs GPR:$rx_u), (ins GPR:$rx, br_symbol:$imm16), "bnezad32\t$rx, $imm16", []> {
+  bits<5> rx;
+  bits<16> imm16;
+  let Inst{25 - 21} = 0x1;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 0} = imm16;
+  let isBranch = 1;
+  let isTerminator = 1;
+  let Constraints = "$rx_u = $rx";
+  let Predicates = [iHas2E3, iHas10E60];
+}
 
 def BSR32 : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>;
 
+def : InstAlias<"bsr $dst", (BSR32 call_symbol:$dst)>;
+
 def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
   let isCodeGenOnly = 1;
   let isBranch = 1;
@@ -347,27 +642,308 @@ def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
   let Defs = [ R15 ];
 }
 
-
+let Predicates = [iHasE2], isCodeGenOnly = 1 in {
   def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;
+}
 
 
-def RTE32 : I_16_RET_I<0, 0, "rte32", []>;
-
 //===----------------------------------------------------------------------===//
 // Symbol address instructions.
 //===----------------------------------------------------------------------===//
 
+def data_symbol_b : data_symbol<"CSKY::fixup_csky_doffset_imm18", 0>;
+def data_symbol_h : data_symbol<"CSKY::fixup_csky_doffset_imm18_scale2", 1>;
+def data_symbol_w : data_symbol<"CSKY::fixup_csky_doffset_imm18_scale4", 2> {
+  let ParserMatchClass = DataAsmClass;
+}
+
+let Predicates = [iHas2E3] in {
+
 def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset",
                     (outs GPR:$rz), (ins bare_symbol:$offset), []>;
+def : InstAlias<"grs\t$rz, $offset", (GRS32 GPR:$rz, bare_symbol:$offset)>;
+
+let Uses = [R28] in {
+def LRS32B : I_18_Z_L<0x0, "lrs32.b\t$rz, $offset",
+                    (outs GPR:$rz), (ins data_symbol_b:$offset), []>;
+def LRS32H : I_18_Z_L<0x1, "lrs32.h\t$rz, $offset",
+                    (outs GPR:$rz), (ins data_symbol_h:$offset), []>;
+def LRS32W : I_18_Z_L<0x2, "lrs32.w\t$rz, $offset",
+                    (outs GPR:$rz), (ins data_symbol_w:$offset), []>;
+def SRS32B : I_18_Z_L<0x4, "srs32.b\t$rz, $offset",
+                    (outs), (ins GPR:$rz, data_symbol_b:$offset), []>;
+def SRS32H : I_18_Z_L<0x5, "srs32.h\t$rz, $offset",
+                    (outs), (ins GPR:$rz, data_symbol_h:$offset), []>;
+def SRS32W : I_18_Z_L<0x6, "srs32.w\t$rz, $offset",
+                    (outs), (ins GPR:$rz, data_symbol_w:$offset), []>;
+}
+
+def PUSH32 : I_12_PP<0b11111, 0b00000, (outs), (ins reglist:$regs, variable_ops), "push32 $regs">;
+
+let Uses = [R14, R15], isReturn = 1, isTerminator = 1, isBarrier = 1 in
+def POP32 : I_12_PP<0b11110, 0b00000, (outs), (ins reglist:$regs, variable_ops), "pop32 $regs">;
+
+}
 
 let mayLoad = 1, mayStore = 0 in {
 def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>;
 let isCodeGenOnly = 1 in
-def LRW32_Gen : I_16_Z_L<0x14, "lrw32",
-  (ins bare_symbol:$src1, constpool_symbol:$imm16), []>;
+def LRW32_Gen : I_16_Z_L<0x14, "lrw32", (ins bare_symbol:$src1, constpool_symbol:$imm16), []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Atomic and fence instructions.
+//===----------------------------------------------------------------------===//
+
+let Predicates = [iHasMP1E2] in {
+  def BRWARW : BAR<0b01111, "bar.brwarw", 0>;
+  def BRWARWS : BAR<0b01111, "bar.brwarws", 1>;
+  def BRARW : BAR<0b00111, "bar.brarw", 0>;
+  def BRARWS : BAR<0b00111, "bar.brarws", 1>;
+  def BRWAW : BAR<0b01110, "bar.brwaw", 0>;
+  def BRWAWS : BAR<0b01110, "bar.brwaws", 1>;
+  def BRAR : BAR<0b00101, "bar.brar", 0>;
+  def BRARS : BAR<0b00101, "bar.brars", 1>;
+  def BWAW : BAR<0b01010, "bar.bwaw", 0>;
+  def BWAWS : BAR<0b01010, "bar.bwaws", 1>;
+
+  def LDEX32W : I_LD<AddrMode32WD, 0x7, "ldex32.w", uimm12_2>;
+  let Constraints = "$rd = $rz" in
+    def STEX32W : I_LDST<AddrMode32WD, 0x37, 7,
+      (outs GPR:$rd), (ins GPR:$rz, GPR:$rx, uimm12_2:$imm12), "stex32.w", []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Other operation instructions.
+//===----------------------------------------------------------------------===//
+
+let Predicates = [iHas2E3] in {
+  def BREV32 : R_XZ<0x18, 0x10, "brev32">;
+  def ABS32 : R_XZ<0x0, 0x10, "abs32">;
+  def BGENR32 : R_XZ<0x14, 0x2, "bgenr32">;
+}
+
+let Predicates = [iHasE2] in {
+  def REVB32 : R_XZ<0x18, 0x4, "revb32">;
+  def REVH32 : R_XZ<0x18, 0x8, "revh32">;
+  def FF0 : R_XZ<0x1F, 0x1, "ff0.32">;
+  def FF1 : R_XZ<0x1F, 0x2, "ff1.32">;
+  def XTRB0 : R_XZ<0x1C, 0x1, "xtrb0.32">;
+  def XTRB1 : R_XZ<0x1C, 0x2, "xtrb1.32">;
+  def XTRB2 : R_XZ<0x1C, 0x4, "xtrb2.32">;
+  def XTRB3 : R_XZ<0x1C, 0x8, "xtrb3.32">;
+  def BTSTI32 : I_5_X<0x0A, 0x4, "btsti32", uimm5, []>;
+  def BCLRI32 : I_5_XZ<0xA, 0x1, "bclri32",
+  (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5), []>;
+  def BSETI32 : I_5_XZ<0xA, 0x2, "bseti32",
+  (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5), []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Special instructions.
+//===----------------------------------------------------------------------===//
+
+def MFFCR : CSKY32Inst<AddrModeNone, 0x30,
+  (outs GPR:$rx), (ins), "mfcr\t$rx, fcr", []> {
+  bits<5> rx;
+
+  let Inst{25 - 21} = 0b00010;
+  let Inst{20 - 16} = 0b00001;
+  let Inst{15 - 10} = 0b011000;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = rx;
+  let hasSideEffects = 1;
+  let isCodeGenOnly = 1;
+}
+
+def MTFCR : CSKY32Inst<AddrModeNone, 0x30,
+  (outs), (ins GPR:$rx), "mtcr\t$rx, fcr", []> {
+  bits<5> rx;
+
+  let Inst{25 - 21} = 0b00010;
+  let Inst{20 - 16} = rx;
+  let Inst{15 - 10} = 0b011001;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0b00001;
+  let hasSideEffects = 1;
+  let isCodeGenOnly = 1;
+}
+
+def SYNC32 : I_5_IMM5<0x30, 0b000001, 0b00001, "sync32", uimm5, []>;
+
+def SYNC0_32 : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins),
+                 "sync32", []> {
+  let Inst{25 - 21} = 0;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = 0b000001;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
+def SYNC_32_I : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins),
+                 "sync32.i", []> {
+  let Inst{25 - 21} = 1;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = 0b000001;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
+def SYNC_32_S : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins),
+                 "sync32.s", []> {
+  let Inst{25 - 21} = 0b10000;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = 0b000001;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
+def SYNC_32_IS : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins),
+                 "sync32.is", []> {
+  let Inst{25 - 21} = 0b10001;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 10} = 0b000001;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+}
+
+let Predicates = [iHas2E3] in {
+  def RFI32 : I_5_XZ_PRIVI<0x11, 0x1, "rfi32">;
+  def SCE32 : I_5_IMM5<0x30, 0b000110, 0b00001, "sce32", uimm4, []>;
+}
+let Predicates = [HasExtendLrw] in
+def IDLY32 : I_5_IMM5<0x30, 0b000111, 0b00001, "idly32", imm5_idly, []>;
+def STOP32 : I_5_XZ_PRIVI<0x12, 0x1, "stop32">;
+def WAIT32 : I_5_XZ_PRIVI<0x13, 0x1, "wait32">;
+def DOZE32 : I_5_XZ_PRIVI<0x14, 0x1, "doze32">;
+def WE32 : I_5_XZ_PRIVI<0b010101, 0x1, "we32">;
+def SE32 : I_5_XZ_PRIVI<0b010110, 0x1, "se32">;
+def WSC32 : I_5_XZ_PRIVI<0b001111, 0x1, "wsc32">;
+
+def CPOP32 : I_CPOP<(outs), (ins uimm5:$cpid, uimm20:$usdef), "cpop32 <$cpid, ${usdef}>">;
+def CPRC32 : I_CP<0b0100, (outs CARRY:$ca), (ins uimm5:$cpid, uimm12:$usdef), "cprc32 <$cpid, ${usdef}>">;
+def CPRCR32 : I_CP_Z<0b0010, (outs GPR:$rz), (ins uimm5:$cpid, uimm12:$usdef), "cprcr32 $rz, <$cpid, ${usdef}>">;
+def CPRGR32 : I_CP_Z<0b0000, (outs GPR:$rz), (ins uimm5:$cpid, uimm12:$usdef), "cprgr32 $rz, <$cpid, ${usdef}>">;
+def CPWCR32 : I_CP_Z<0b0011, (outs), (ins GPR:$rz, uimm5:$cpid, uimm12:$usdef), "cpwcr32 $rz, <$cpid, ${usdef}>">;
+def CPWGR32 : I_CP_Z<0b0001, (outs), (ins GPR:$rz, uimm5:$cpid, uimm12:$usdef), "cpwgr32 $rz, <$cpid, ${usdef}>">;
+
+let Predicates = [iHas3r2E3r3] in {
+def DCACHE_IALL32 : I_5_CACHE<0b100101, 0b01000, "dcache32.iall">;
+def DCACHE_CALL32 : I_5_CACHE<0b100101, 0b00100, "dcache32.call">;
+def DCACHE_CIALL32 : I_5_CACHE<0b100101, 0b01100, "dcache32.ciall">;
+def DCACHE_IVA32 : I_5_X_CACHE<0b100101, 0b01011, "dcache32.iva">;
+def DCACHE_ISW32: I_5_X_CACHE<0b100101, 0b01010, "dcache32.isw">;
+def DCACHE_CVA32 : I_5_X_CACHE<0b100101, 0b00111, "dcache32.cva">;
+def DCACHE_CVAL32 : I_5_X_CACHE<0b100101, 0b10111, "dcache32.cval1">;
+def DCACHE_CSW32 : I_5_X_CACHE<0b100101, 0b00110, "dcache32.csw">;
+def DCACHE_CIVA32 : I_5_X_CACHE<0b100101, 0b01111, "dcache32.civa">;
+def DCACHE_CISW32 : I_5_X_CACHE<0b100101, 0b01110, "dcache32.cisw">;
+
+def ICACHE_IALL32 : I_5_CACHE<0b100100, 0b01000, "icache32.iall">;
+def ICACHE_IALLS32 : I_5_CACHE<0b100100, 0b11000, "icache32.ialls">;
+def ICACHE_IVA32 : I_5_X_CACHE<0b100100, 0b01011, "icache32.iva">;
+
+def TLBI_VAA32 : I_5_X_CACHE<0b100010, 0b00010, "tlbi32.vaa">;
+def TLBI_VAAS32 : I_5_X_CACHE<0b100010, 0b10010, "tlbi32.vaas">;
+def TLBI_ASID32 : I_5_X_CACHE<0b100010, 0b00001, "tlbi32.asid">;
+def TLBI_ASIDS32 : I_5_X_CACHE<0b100010, 0b10001, "tlbi32.asids">;
+def TLBI_VA32 : I_5_X_CACHE<0b100010, 0b00011, "tlbi32.va">;
+def TLBI_VAS32 : I_5_X_CACHE<0b100010, 0b10011, "tlbi32.vas">;
+def TLBI_ALL32 : I_5_CACHE<0b100010, 0b00000, "tlbi32.all">;
+def TLBI_ALLS32 : I_5_CACHE<0b100010, 0b10000, "tlbi32.alls">;
+
+def L2CACHE_IALL : I_5_CACHE<0b100110, 0b01000, "l2cache.iall">;
+def L2CACHE_CALL : I_5_CACHE<0b100110, 0b00100, "l2cache.call">;
+def L2CACHE_CIALL : I_5_CACHE<0b100110, 0b01100, "l2cache.ciall">;
+}
+
+def PLDR32 :I_PLDR<AddrMode32WD, 0x36, 0b0110, (outs), (ins GPR:$rx, uimm12_2:$imm12), "pldr32", []>;
+def PLDW32 :I_PLDR<AddrMode32WD, 0x37, 0b0110, (outs), (ins GPR:$rx, uimm12_2:$imm12), "pldw32", []>;
+
+def TRAP32 : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins uimm2:$imm2), "trap32 ${imm2}", []> {
+  bits<2> imm2;
+
+  let Inst{25 - 21} = 0;
+  let Inst{20 - 16} = 0;
+  let Inst{15 - 12} = 0b0010;
+  let Inst{11 - 10} = imm2;
+  let Inst{9 - 5} = 0b00001;
+  let Inst{4 - 0} = 0;
+
+}
+
+
+//===----------------------------------------------------------------------===//
+// Pseudo for assembly
+//===----------------------------------------------------------------------===//
+
+let isCall = 1, Defs = [ R15 ], mayLoad = 1, Size = 4, isCodeGenOnly = 0 in
+def JBSR32 : CSKYPseudo<(outs), (ins call_symbol:$src1), "jbsr32\t$src1", []>;
+
+def : InstAlias<"jbsr\t$src1", (JBSR32 call_symbol:$src1)>;
+
+def JBR32 : CSKYPseudo<(outs), (ins br_symbol:$src1), "jbr32\t$src1", []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isBarrier = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 4;
+}
+
+def JBT32 : CSKYPseudo<(outs), (ins CARRY:$ca, br_symbol:$src1), "jbt32\t$src1", []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 4;
+}
+
+def JBF32 : CSKYPseudo<(outs), (ins CARRY:$ca, br_symbol:$src1), "jbf32\t$src1", []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 4;
+}
+
+def JBT_E : CSKYPseudo<(outs), (ins CARRY:$ca, br_symbol:$src1), "!jbt_e\t$src1", []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 6;
 }
 
-// TODO: Atomic and fence instructions.
-// TODO: Other operations.
-// TODO: Special instructions.
-// TODO: Pseudo for assembly.
+def JBF_E : CSKYPseudo<(outs), (ins CARRY:$ca, br_symbol:$src1), "!jbf_e\t$src1", []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 6;
+}
+
+let mayLoad = 1, Size = 2, isCodeGenOnly = 0 in
+def PseudoLRW32 : CSKYPseudo<(outs GPR:$rz), (ins bare_symbol:$src), "lrw32 $rz, $src", []>;
+
+
+def : InstAlias<"lrw $rz, $src", (PseudoLRW32 GPR:$rz, bare_symbol:$src)>;
+def : InstAlias<"lrw $rz, $src", (LRW32 GPR:$rz, constpool_symbol:$src)>;
+
+let mayLoad = 1, Size = 4, isCodeGenOnly = 0 in
+def PseudoJSRI32 : CSKYPseudo<(outs), (ins call_symbol:$src), "jsri32 $src", []>;
+def : InstAlias<"jsri $dst", (PseudoJSRI32 call_symbol:$dst)>;
+def : InstAlias<"jsri $dst", (JSRI32 constpool_symbol:$dst)>;
+
+let mayLoad = 1, Size = 4, isCodeGenOnly = 0 in
+def PseudoJMPI32 : CSKYPseudo<(outs), (ins br_symbol:$src), "jmpi32 $src", []>;
+def : InstAlias<"jmpi $dst", (PseudoJMPI32 br_symbol:$dst)>;
+def : InstAlias<"jmpi $dst", (JMPI32 constpool_symbol:$dst)>;
+
+let isNotDuplicable = 1, mayLoad = 1, mayStore = 0, Size = 8 in
+def PseudoTLSLA32 : CSKYPseudo<(outs GPR:$dst1, GPR:$dst2),
+  (ins constpool_symbol:$src, i32imm:$label), "!tlslrw32\t$dst1, $dst2, $src, $label", []>;
+
+let hasSideEffects = 0, isNotDuplicable = 1 in
+def CONSTPOOL_ENTRY : CSKYPseudo<(outs),
+  (ins i32imm:$instid, i32imm:$cpidx, i32imm:$size), "", []>;
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/CSKYSubtarget.cpp b/llvm/lib/Target/CSKY/CSKYSubtarget.cpp
new file mode 100644
index 000000000000..a401b0289b2a
--- /dev/null
+++ b/llvm/lib/Target/CSKY/CSKYSubtarget.cpp
@@ -0,0 +1,52 @@
+//===-- CSKYSubtarget.h - Define Subtarget for the CSKY----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the CSKY specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYSubtarget.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "csky-subtarget"
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "CSKYGenSubtargetInfo.inc"
+
+void CSKYSubtarget::anchor() {}
+
+CSKYSubtarget &CSKYSubtarget::initializeSubtargetDependencies(
+    const Triple &TT, StringRef CPUName, StringRef TuneCPUName, StringRef FS) {
+
+  if (CPUName.empty())
+    CPUName = "generic";
+  if (TuneCPUName.empty())
+    TuneCPUName = CPUName;
+
+  HasE1 = false;
+  HasE2 = false;
+  Has2E3 = false;
+  HasMP = false;
+  Has3E3r1 = false;
+  Has3r1E3r2 = false;
+  Has3r2E3r3 = false;
+  Has3E7 = false;
+  HasMP1E2 = false;
+  Has7E10 = false;
+  Has10E60 = false;
+
+  ParseSubtargetFeatures(CPUName, TuneCPUName, FS);
+  return *this;
+}
+
+CSKYSubtarget::CSKYSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
+                             StringRef FS, const TargetMachine &TM)
+    : CSKYGenSubtargetInfo(TT, CPU, TuneCPU, FS),
+      FrameLowering(initializeSubtargetDependencies(TT, CPU, TuneCPU, FS)),
+      InstrInfo(*this), RegInfo(), TLInfo(TM, *this) {}
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/CSKYSubtarget.h b/llvm/lib/Target/CSKY/CSKYSubtarget.h
new file mode 100644
index 000000000000..ae70d74abd86
--- /dev/null
+++ b/llvm/lib/Target/CSKY/CSKYSubtarget.h
@@ -0,0 +1,87 @@
+//===-- CSKYSubtarget.h - Define Subtarget for the CSKY----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the CSKY specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H
+#define LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H
+
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define GET_SUBTARGETINFO_HEADER
+#include "CSKYGenSubtargetInfo.inc"
+
+namespace llvm {
+class StringRef;
+
+class CSKYSubtarget : public CSKYGenSubtargetInfo {
+  virtual void anchor();
+
+  CSKYFrameLowering FrameLowering;
+  CSKYInstrInfo InstrInfo;
+  CSKYRegisterInfo RegInfo;
+  CSKYTargetLowering TLInfo;
+  SelectionDAGTargetInfo TSInfo;
+
+  bool HasE1;
+  bool HasE2;
+  bool Has2E3;
+  bool HasMP;
+  bool Has3E3r1;
+  bool Has3r1E3r2;
+  bool Has3r2E3r3;
+  bool Has3E7;
+  bool HasMP1E2;
+  bool Has7E10;
+  bool Has10E60;
+
+public:
+  CSKYSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
+                StringRef FS, const TargetMachine &TM);
+
+  const CSKYFrameLowering *getFrameLowering() const override {
+    return &FrameLowering;
+  }
+  const CSKYInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+  const CSKYRegisterInfo *getRegisterInfo() const override { return &RegInfo; }
+  const CSKYTargetLowering *getTargetLowering() const override {
+    return &TLInfo;
+  }
+  const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
+    return &TSInfo;
+  }
+
+  /// Initializes using the passed in CPU and feature strings so that we can
+  /// use initializer lists for subtarget initialization.
+  CSKYSubtarget &initializeSubtargetDependencies(const Triple &TT,
+                                                 StringRef CPU,
+                                                 StringRef TuneCPU,
+                                                 StringRef FS);
+
+  // Generated by inc file
+  void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
+
+  bool hasE1() const { return HasE1; }
+  bool hasE2() const { return HasE2; }
+  bool has2E3() const { return Has2E3; }
+  bool has3r1E3r2() const { return Has3r1E3r2; }
+  bool has3r2E3r3() const { return Has3r2E3r3; }
+  bool has3E3r1() const { return Has3E3r1; }
+  bool has3E7() const { return Has3E7; }
+  bool hasMP() const { return HasMP; }
+  bool hasMP1E2() const { return HasMP1E2; }
+  bool has7E10() const { return Has7E10; }
+  bool has10E60() const { return Has10E60; }
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
index c995b063330a..daa655416c47 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
@@ -30,25 +30,57 @@ CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
 
   static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {
       {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},
       {CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,
        {"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
       {CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,
-       {"fixup_csky_pcrel_uimm16_scale4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+       {"fixup_csky_pcrel_uimm16_scale4", 0, 32,
+        MCFixupKindInfo::FKF_IsPCRel |
+            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
+      {CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4,
+       {"fixup_csky_pcrel_uimm8_scale4", 0, 32,
+        MCFixupKindInfo::FKF_IsPCRel |
+            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
       {CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,
        {"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
       {CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,
-       {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}};
+       {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+      {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_got_imm18_scale4,
+       {"fixup_csky_got_imm18_scale4", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_gotpc,
+       {"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+      {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_plt_imm18_scale4,
+       {"fixup_csky_plt_imm18_scale4", 0, 32, 0}},
+      {CSKY::Fixups::fixup_csky_pcrel_imm10_scale2,
+       {"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}},
+      {CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4,
+       {"fixup_csky_pcrel_uimm7_scale4", 0, 16,
+        MCFixupKindInfo::FKF_IsPCRel |
+            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
+      {CSKY::Fixups::fixup_csky_doffset_imm18,
+       {"fixup_csky_doffset_imm18", 0, 18, 0}},
+      {CSKY::Fixups::fixup_csky_doffset_imm18_scale2,
+       {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},
+      {CSKY::Fixups::fixup_csky_doffset_imm18_scale4,
+       {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};
+
   assert(Infos.size() == CSKY::NumTargetFixupKinds &&
          "Not all fixup kinds added to Infos array");
 
-  assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
-         "Invalid kind!");
-  if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind)
+  if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind) {
+    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+           "Invalid kind!");
+
     return Infos[Kind];
-  else if (Kind < FirstTargetFixupKind)
+  } else if (Kind < FirstTargetFixupKind) {
     return MCAsmBackend::getFixupKindInfo(Kind);
-  else
+  } else {
     return MCAsmBackend::getFixupKindInfo(FK_NONE);
+  }
 }
 
 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
index 917f940fcad4..aae77c2ac6ac 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
@@ -16,6 +16,10 @@ namespace CSKY {
 enum Fixups {
   fixup_csky_addr32 = FirstTargetFixupKind,
 
+  fixup_csky_addr_hi16,
+
+  fixup_csky_addr_lo16,
+
   fixup_csky_pcrel_imm16_scale2,
 
   fixup_csky_pcrel_uimm16_scale4,
@@ -24,6 +28,29 @@ enum Fixups {
 
   fixup_csky_pcrel_imm18_scale2,
 
+  fixup_csky_gotpc,
+
+  fixup_csky_gotoff,
+
+  fixup_csky_got32,
+
+  fixup_csky_got_imm18_scale4,
+
+  fixup_csky_plt32,
+
+  fixup_csky_plt_imm18_scale4,
+
+  fixup_csky_pcrel_imm10_scale2,
+
+  fixup_csky_pcrel_uimm7_scale4,
+
+  fixup_csky_pcrel_uimm8_scale4,
+
+  fixup_csky_doffset_imm18,
+
+  fixup_csky_doffset_imm18_scale2,
+
+  fixup_csky_doffset_imm18_scale4,
   // Marker
   fixup_csky_invalid,
   NumTargetFixupKinds = fixup_csky_invalid - FirstTargetFixupKind
@@ -31,4 +58,4 @@ enum Fixups {
 } // end namespace CSKY
 } // end namespace llvm
 
-#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
index c8920fbb4b4c..7001de999a51 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CSKYInstPrinter.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -95,6 +96,107 @@ void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
   MO.getExpr()->print(O, &MAI);
 }
 
+void CSKYInstPrinter::printDataSymbol(const MCInst *MI, unsigned OpNo,
+                                      const MCSubtargetInfo &STI,
+                                      raw_ostream &O) {
+  const MCOperand &MO = MI->getOperand(OpNo);
+
+  O << "[";
+  if (MO.isImm())
+    O << MO.getImm();
+  else
+    MO.getExpr()->print(O, &MAI);
+  O << "]";
+}
+
+void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address,
+                                     unsigned OpNo, const MCSubtargetInfo &STI,
+                                     raw_ostream &O) {
+  const MCOperand &MO = MI->getOperand(OpNo);
+
+  if (MO.isImm()) {
+    if (PrintBranchImmAsAddress) {
+      uint64_t Target = Address + MO.getImm();
+      Target &= 0xfffffffc;
+      O << formatHex(Target);
+    } else {
+      O << MO.getImm();
+    }
+    return;
+  }
+
+  assert(MO.isExpr() && "Unknown operand kind in printConstpool");
+
+  O << "[";
+  MO.getExpr()->print(O, &MAI);
+  O << "]";
+}
+
+void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address,
+                                             unsigned OpNo,
+                                             const MCSubtargetInfo &STI,
+                                             raw_ostream &O) {
+  const MCOperand &MO = MI->getOperand(OpNo);
+  if (!MO.isImm()) {
+    return printOperand(MI, OpNo, STI, O);
+  }
+
+  if (PrintBranchImmAsAddress) {
+    uint64_t Target = Address + MO.getImm();
+    Target &= 0xffffffff;
+    O << formatHex(Target);
+  } else {
+    O << MO.getImm();
+  }
+}
+
+void CSKYInstPrinter::printRegisterSeq(const MCInst *MI, unsigned OpNum,
+                                       const MCSubtargetInfo &STI,
+                                       raw_ostream &O) {
+  printRegName(O, MI->getOperand(OpNum).getReg());
+  O << "-";
+  printRegName(O, MI->getOperand(OpNum + 1).getReg());
+}
+
+void CSKYInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
+                                        const MCSubtargetInfo &STI,
+                                        raw_ostream &O) {
+  auto V = MI->getOperand(OpNum).getImm();
+  ListSeparator LS;
+
+  if (V & 0xf) {
+    O << LS;
+    printRegName(O, CSKY::R4);
+    auto Offset = (V & 0xf) - 1;
+    if (Offset) {
+      O << "-";
+      printRegName(O, CSKY::R4 + Offset);
+    }
+  }
+
+  if ((V >> 4) & 0x1) {
+    O << LS;
+    printRegName(O, CSKY::R15);
+  }
+
+  if ((V >> 5) & 0x7) {
+    O << LS;
+    printRegName(O, CSKY::R16);
+
+    auto Offset = ((V >> 5) & 0x7) - 1;
+
+    if (Offset) {
+      O << "-";
+      printRegName(O, CSKY::R16 + Offset);
+    }
+  }
+
+  if ((V >> 8) & 0x1) {
+    O << LS;
+    printRegName(O, CSKY::R28);
+  }
+}
+
 const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) {
   return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName
                                              : CSKY::ABIRegAltName);

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
index a28791a6d8e9..a3855a8ef094 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h
@@ -19,6 +19,9 @@
 namespace llvm {
 
 class CSKYInstPrinter : public MCInstPrinter {
+private:
+  bool ABIRegNames = false;
+
 public:
   CSKYInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
                   const MCRegisterInfo &MRI)
@@ -43,10 +46,24 @@ class CSKYInstPrinter : public MCInstPrinter {
                                unsigned OpIdx, unsigned PrintMethodIdx,
                                const MCSubtargetInfo &STI, raw_ostream &O);
 
+  void printDataSymbol(const MCInst *MI, unsigned OpNo,
+                       const MCSubtargetInfo &STI, raw_ostream &O);
+  void printConstpool(const MCInst *MI, uint64_t Address, unsigned OpNo,
+                      const MCSubtargetInfo &STI, raw_ostream &O);
+  void printPSRFlag(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+                    raw_ostream &O);
+  void printRegisterSeq(const MCInst *MI, unsigned OpNo,
+                        const MCSubtargetInfo &STI, raw_ostream &O);
+  void printRegisterList(const MCInst *MI, unsigned OpNo,
+                         const MCSubtargetInfo &STI, raw_ostream &O);
+  void printCSKYSymbolOperand(const MCInst *MI, uint64_t Address, unsigned OpNo,
+                              const MCSubtargetInfo &STI, raw_ostream &O);
+  void printSPAddr(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+                   raw_ostream &O);
   static const char *getRegisterName(unsigned RegNo);
   static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
 };
 
 } // namespace llvm
 
-#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYINSTPRINTER_H
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYINSTPRINTER_H
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
index 1a5b0225e0b9..53945ff849c8 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CSKYMCCodeEmitter.h"
+#include "CSKYMCExpr.h"
 #include "MCTargetDesc/CSKYMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/MC/MCInstBuilder.h"
@@ -31,11 +32,46 @@ unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,
   return MO.getImm() - 1;
 }
 
+unsigned
+CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
+                                     SmallVectorImpl<MCFixup> &Fixups,
+                                     const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(Idx);
+  assert(MO.isImm() && "Unexpected MO type.");
+
+  auto V = (MO.getImm() <= 3) ? 4 : MO.getImm();
+  return V - 1;
+}
+
+unsigned
+CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
+                                        SmallVectorImpl<MCFixup> &Fixups,
+                                        const MCSubtargetInfo &STI) const {
+  const MCOperand &MSB = MI.getOperand(Idx);
+  const MCOperand &LSB = MI.getOperand(Idx + 1);
+  assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type.");
+
+  return MSB.getImm() - LSB.getImm();
+}
+
+static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) {
+  uint16_t LO16 = static_cast<uint16_t>(Bin);
+  uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);
+
+  if (Size == 4)
+    support::endian::write<uint16_t>(OS, HI16, support::little);
+
+  support::endian::write<uint16_t>(OS, LO16, support::little);
+}
+
 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
                                           SmallVectorImpl<MCFixup> &Fixups,
                                           const MCSubtargetInfo &STI) const {
   const MCInstrDesc &Desc = MII.get(MI.getOpcode());
   unsigned Size = Desc.getSize();
+
+  ++MCNumEmitted;
+
   uint32_t Bin = getBinaryCodeForInstr(MI, Fixups, STI);
 
   uint16_t LO16 = static_cast<uint16_t>(Bin);
@@ -45,7 +81,6 @@ void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     support::endian::write<uint16_t>(OS, HI16, support::little);
 
   support::endian::write<uint16_t>(OS, LO16, support::little);
-  ++MCNumEmitted; // Keep track of the # of mi's emitted.
 }
 
 unsigned
@@ -62,6 +97,51 @@ CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   return 0;
 }
 
+unsigned
+CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");
+  assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");
+
+  unsigned Ry = MI.getOperand(Idx).getReg();
+  unsigned Rz = MI.getOperand(Idx + 1).getImm();
+
+  unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -
+                 Ctx.getRegisterInfo()->getEncodingValue(Ry);
+
+  return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);
+}
+
+unsigned
+CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
+                                         SmallVectorImpl<MCFixup> &Fixups,
+                                         const MCSubtargetInfo &STI) const {
+  unsigned Reg1 =
+      Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());
+  unsigned Reg2 =
+      Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());
+
+  unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);
+
+  return Binary;
+}
+
+unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,
+                                        SmallVectorImpl<MCFixup> &Fixups,
+                                        const MCSubtargetInfo &STI) const {
+  if (MI.getOperand(Idx).getImm() == 16)
+    return 0;
+  else if (MI.getOperand(Idx).getImm() == 24)
+    return 1;
+  else if (MI.getOperand(Idx).getImm() == 32)
+    return 2;
+  else if (MI.getOperand(Idx).getImm() == 40)
+    return 3;
+  else
+    assert(0);
+}
+
 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
   const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
 
@@ -70,6 +150,22 @@ MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
     llvm_unreachable("Unhandled fixup kind!");
   case CSKYMCExpr::VK_CSKY_ADDR:
     return MCFixupKind(CSKY::fixup_csky_addr32);
+  case CSKYMCExpr::VK_CSKY_ADDR_HI16:
+    return MCFixupKind(CSKY::fixup_csky_addr_hi16);
+  case CSKYMCExpr::VK_CSKY_ADDR_LO16:
+    return MCFixupKind(CSKY::fixup_csky_addr_lo16);
+  case CSKYMCExpr::VK_CSKY_GOT:
+    return MCFixupKind(CSKY::fixup_csky_got32);
+  case CSKYMCExpr::VK_CSKY_GOTPC:
+    return MCFixupKind(CSKY::fixup_csky_gotpc);
+  case CSKYMCExpr::VK_CSKY_GOTOFF:
+    return MCFixupKind(CSKY::fixup_csky_gotoff);
+  case CSKYMCExpr::VK_CSKY_PLT:
+    return MCFixupKind(CSKY::fixup_csky_plt32);
+  case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4:
+    return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4);
+  case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4:
+    return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4);
   }
 }
 
@@ -79,4 +175,4 @@ MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
   return new CSKYMCCodeEmitter(Ctx, MCII);
 }
 
-#include "CSKYGenMCCodeEmitter.inc"
+#include "CSKYGenMCCodeEmitter.inc"
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
index a4c50d992a07..5224f1785948 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
@@ -13,8 +13,8 @@
 #ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
 #define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
 
-#include "CSKYMCExpr.h"
 #include "MCTargetDesc/CSKYFixupKinds.h"
+#include "MCTargetDesc/CSKYMCExpr.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
 
@@ -49,14 +49,40 @@ class CSKYMCCodeEmitter : public MCCodeEmitter {
                          SmallVectorImpl<MCFixup> &Fixups,
                          const MCSubtargetInfo &STI) const {
     const MCOperand &MO = MI.getOperand(Idx);
-    assert(MO.isImm() && "Unexpected MO type.");
-    return (MO.getImm() >> shift);
+    if (MO.isImm())
+      return (MO.getImm() >> shift);
+
+    assert(MO.isExpr() && "Unexpected MO type.");
+
+    MCFixupKind Kind = getTargetFixup(MO.getExpr());
+    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
+    return 0;
   }
 
+  unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,
+                               SmallVectorImpl<MCFixup> &Fixups,
+                               const MCSubtargetInfo &STI) const;
+
+  unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op,
+                                 SmallVectorImpl<MCFixup> &Fixups,
+                                 const MCSubtargetInfo &STI) const;
+
   unsigned getOImmOpValue(const MCInst &MI, unsigned Idx,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
 
+  unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx,
+                             SmallVectorImpl<MCFixup> &Fixups,
+                             const MCSubtargetInfo &STI) const;
+
+  unsigned getImmJMPIX(const MCInst &MI, unsigned Idx,
+                       SmallVectorImpl<MCFixup> &Fixups,
+                       const MCSubtargetInfo &STI) const;
+
+  unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,
+                                SmallVectorImpl<MCFixup> &Fixups,
+                                const MCSubtargetInfo &STI) const;
+
   unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx,
                               SmallVectorImpl<MCFixup> &Fixups,
                               const MCSubtargetInfo &STI) const {
@@ -101,6 +127,21 @@ class CSKYMCCodeEmitter : public MCCodeEmitter {
     return 0;
   }
 
+  template <llvm::CSKY::Fixups FIXUP>
+  unsigned getDataSymbolOpValue(const MCInst &MI, unsigned Idx,
+                                SmallVectorImpl<MCFixup> &Fixups,
+                                const MCSubtargetInfo &STI) const {
+    const MCOperand &MO = MI.getOperand(Idx);
+    assert(MO.isExpr() && "Unexpected MO type.");
+
+    MCFixupKind Kind = MCFixupKind(FIXUP);
+    if (MO.getExpr()->getKind() == MCExpr::Target)
+      Kind = getTargetFixup(MO.getExpr());
+
+    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
+    return 0;
+  }
+
   unsigned getCallSymbolOpValue(const MCInst &MI, unsigned Idx,
                                 SmallVectorImpl<MCFixup> &Fixups,
                                 const MCSubtargetInfo &STI) const {
@@ -132,4 +173,4 @@ class CSKYMCCodeEmitter : public MCCodeEmitter {
 
 } // namespace llvm
 
-#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
index 59e630f43a42..c06a9598b6a1 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
@@ -26,22 +26,33 @@ StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
   switch (Kind) {
   default:
     llvm_unreachable("Invalid ELF symbol kind");
+  case VK_CSKY_None:
   case VK_CSKY_ADDR:
     return "";
-  case VK_CSKY_PCREL:
-    return "";
+  case VK_CSKY_ADDR_HI16:
+    return "@HI16";
+  case VK_CSKY_ADDR_LO16:
+    return "@LO16";
+  case VK_CSKY_GOT_IMM18_BY4:
   case VK_CSKY_GOT:
     return "@GOT";
   case VK_CSKY_GOTPC:
     return "@GOTPC";
   case VK_CSKY_GOTOFF:
     return "@GOTOFF";
+  case VK_CSKY_PLT_IMM18_BY4:
   case VK_CSKY_PLT:
     return "@PLT";
-  case VK_CSKY_TPOFF:
+  case VK_CSKY_TLSLE:
     return "@TPOFF";
+  case VK_CSKY_TLSIE:
+    return "@GOTTPOFF";
   case VK_CSKY_TLSGD:
-    return "@TLSGD";
+    return "@TLSGD32";
+  case VK_CSKY_TLSLDO:
+    return "@TLSLDO32";
+  case VK_CSKY_TLSLDM:
+    return "@TLSLDM32";
   }
 }
 
@@ -87,7 +98,8 @@ void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
   switch (getKind()) {
   default:
     return;
-  case VK_CSKY_TPOFF:
+  case VK_CSKY_TLSLE:
+  case VK_CSKY_TLSIE:
   case VK_CSKY_TLSGD:
     break;
   }
@@ -106,14 +118,17 @@ bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
     switch (getKind()) {
     default:
       return true;
-
-    case VK_CSKY_ADDR:
-    case VK_CSKY_PCREL:
     case VK_CSKY_GOT:
+    case VK_CSKY_GOT_IMM18_BY4:
     case VK_CSKY_GOTPC:
     case VK_CSKY_GOTOFF:
-    case VK_CSKY_TPOFF:
+    case VK_CSKY_PLT:
+    case VK_CSKY_PLT_IMM18_BY4:
+    case VK_CSKY_TLSIE:
+    case VK_CSKY_TLSLE:
     case VK_CSKY_TLSGD:
+    case VK_CSKY_TLSLDO:
+    case VK_CSKY_TLSLDM:
       return false;
     }
   }

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
index 06fccada53ce..e0e713d6630b 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
@@ -19,13 +19,20 @@ class CSKYMCExpr : public MCTargetExpr {
   enum VariantKind {
     VK_CSKY_None,
     VK_CSKY_ADDR,
+    VK_CSKY_ADDR_HI16,
+    VK_CSKY_ADDR_LO16,
     VK_CSKY_PCREL,
     VK_CSKY_GOT,
+    VK_CSKY_GOT_IMM18_BY4,
     VK_CSKY_GOTPC,
     VK_CSKY_GOTOFF,
     VK_CSKY_PLT,
-    VK_CSKY_TPOFF,
+    VK_CSKY_PLT_IMM18_BY4,
+    VK_CSKY_TLSIE,
+    VK_CSKY_TLSLE,
     VK_CSKY_TLSGD,
+    VK_CSKY_TLSLDO,
+    VK_CSKY_TLSLDM,
     VK_CSKY_Invalid
   };
 
@@ -66,4 +73,4 @@ class CSKYMCExpr : public MCTargetExpr {
 };
 } // end namespace llvm
 
-#endif
+#endif
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h
index da8a3b63a2f9..43223ce66563 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.h
@@ -45,4 +45,7 @@ MCCodeEmitter *createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
 #define GET_INSTRINFO_ENUM
 #include "CSKYGenInstrInfo.inc"
 
-#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCTARGETDESC_H
+#define GET_SUBTARGETINFO_ENUM
+#include "CSKYGenSubtargetInfo.inc"
+
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCTARGETDESC_H
\ No newline at end of file

diff  --git a/llvm/test/MC/CSKY/basic.s b/llvm/test/MC/CSKY/basic.s
index 23fddd8e544b..69f41bb09030 100644
--- a/llvm/test/MC/CSKY/basic.s
+++ b/llvm/test/MC/CSKY/basic.s
@@ -1,4 +1,5 @@
-# RUN: llvm-mc %s -triple=csky -show-encoding | FileCheck -check-prefixes=CHECK-ASM %s
+# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+e2 -mattr=+2e3 \
+# RUN: -mattr=+mp1e2 | FileCheck -check-prefixes=CHECK-ASM %s
 
 # CHECK-ASM: addi32 a0, sp, 2
 # CHECK-ASM: encoding: [0x0e,0xe4,0x01,0x00]
@@ -40,6 +41,46 @@ ori32 a0, sp, 2
 # CHECK-ASM: encoding: [0x4e,0xc4,0x00,0x49]
 rotli32 a0, sp, 2
 
+# CHECK-ASM: incf32 a0, sp, 2
+# CHECK-ASM: encoding: [0x0e,0xc4,0x22,0x0c]
+incf32 a0, sp, 2
+
+# CHECK-ASM: inct32 a0, sp, 2
+# CHECK-ASM: encoding: [0x0e,0xc4,0x42,0x0c]
+inct32 a0, sp, 2
+
+# CHECK-ASM: decf32 a0, sp, 2
+# CHECK-ASM: encoding: [0x0e,0xc4,0x82,0x0c]
+decf32 a0, sp, 2
+
+# CHECK-ASM: dect32 a0, sp, 2
+# CHECK-ASM: encoding: [0x0e,0xc4,0x02,0x0d]
+dect32 a0, sp, 2
+
+# CHECK-ASM: decgt32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x20,0x10]
+decgt32 a0, sp, 2
+
+# CHECK-ASM: declt32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x40,0x10]
+declt32 a0, sp, 2
+
+# CHECK-ASM: decne32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x80,0x10]
+decne32 a0, sp, 2
+
+# CHECK-ASM: btsti32 a0, 2
+# CHECK-ASM: encoding: [0x40,0xc4,0x80,0x28]
+btsti32 a0, 2
+
+# CHECK-ASM: bclri32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x20,0x28]
+bclri32 a0, sp, 2
+
+# CHECK-ASM: bseti32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x40,0x28]
+bseti32 a0, sp, 2
+
 # CHECK-ASM: cmpnei32 a0, 2
 # CHECK-ASM: encoding: [0x40,0xeb,0x02,0x00]
 cmpnei32 a0, 2
@@ -92,6 +133,10 @@ nor32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x40]
 lsl32 a3, l0, l1
 
+# CHECK-ASM: rotl32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x03,0x41]
+rotl32 a3, l0, l1
+
 # CHECK-ASM: lsr32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x43,0x40]
 lsr32 a3, l0, l1
@@ -100,6 +145,26 @@ lsr32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x83,0x40]
 asr32 a3, l0, l1
 
+# CHECK-ASM: lslc32 a0, sp, 2
+# CHECK-ASM: encoding: [0x2e,0xc4,0x20,0x4c]
+lslc32 a0, sp, 2
+
+# CHECK-ASM: lsrc32 a0, sp, 2
+# CHECK-ASM: encoding: [0x2e,0xc4,0x40,0x4c]
+lsrc32 a0, sp, 2
+
+# CHECK-ASM: asrc32 a0, sp, 2
+# CHECK-ASM: encoding: [0x2e,0xc4,0x80,0x4c]
+asrc32 a0, sp, 2
+
+# CHECK-ASM: xsr32 a0, sp, 2
+# CHECK-ASM: encoding: [0x2e,0xc4,0x00,0x4d]
+xsr32 a0, sp, 2
+
+# CHECK-ASM: bmaski32 a3, 17
+# CHECK-ASM: encoding: [0x00,0xc6,0x23,0x50]
+bmaski32 a3, 17
+
 # CHECK-ASM: mult32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x84]
 mult32 a3, l0, l1
@@ -156,6 +221,10 @@ ld32.w a0, (sp, 4)
 # CHECK-ASM: encoding: [0xae,0xd0,0x80,0x00]
 ldr32.b a0, (sp, l1 << 2)
 
+# CHECK-ASM: ldex32.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x70]
+ldex32.w a0, (sp, 4)
+
 # CHECK-ASM: ldr32.bs a0, (sp, l1 << 2)
 # CHECK-ASM: encoding: [0xae,0xd0,0x80,0x10]
 ldr32.bs a0, (sp, l1 << 2)
@@ -184,6 +253,10 @@ st32.h a0, (sp, 2)
 # CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x20]
 st32.w a0, (sp, 4)
 
+# CHECK-ASM: stex32.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x70]
+stex32.w a0, (sp, 4)
+
 # CHECK-ASM: str32.b a0, (sp, l1 << 2)
 # CHECK-ASM: encoding: [0xae,0xd4,0x80,0x00]
 str32.b a0, (sp, l1 << 2)
@@ -196,21 +269,65 @@ str32.h a0, (sp, l1 << 3)
 # CHECK-ASM: encoding: [0xae,0xd4,0x00,0x09]
 str32.w a0, (sp, l1 << 3)
 
-# CHECK-ASM: not32 a3, l0
-# CHECK-ASM: encoding: [0x84,0xc4,0x83,0x24]
-not32 a3, l0
+# CHECK-ASM: ldm32  a1-a2, (a0)
+# CHECK-ASM: encoding: [0x20,0xd0,0x21,0x1c]
+ldm32  a1-a2, (a0)
+
+# CHECK-ASM: stm32  a1-a2, (a0)
+# CHECK-ASM: encoding: [0x20,0xd4,0x21,0x1c]
+stm32  a1-a2, (a0)
+
+# CHECK-ASM: ldm32  l0-l3, (a0)
+# CHECK-ASM: encoding: [0x80,0xd0,0x23,0x1c]
+ldq32  r4-r7, (a0)
+
+# CHECK-ASM: stm32  l0-l3, (a0)
+# CHECK-ASM: encoding: [0x80,0xd4,0x23,0x1c]
+stq32  r4-r7, (a0)
+
+# CHECK-ASM: brev32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x62]
+brev32 a3, l0
+
+# CHECK-ASM: abs32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x02]
+abs32 a3, l0
+
+# CHECK-ASM: bgenr32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x50]
+bgenr32 a3, l0
+
+# CHECK-ASM: revb32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x83,0x60]
+revb32 a3, l0
+
+# CHECK-ASM: revh32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x61]
+revh32 a3, l0
+
+# CHECK-ASM: ff0.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x7c]
+ff0.32 a3, l0
+
+# CHECK-ASM: ff1.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x7c]
+ff1.32 a3, l0
+
+# CHECK-ASM: xtrb0.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x70]
+xtrb0.32 a3, l0
 
-# CHECK-ASM: mov32 a3, l0
-# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x48]
-mov32 a3, l0
+# CHECK-ASM: xtrb1.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x70]
+xtrb1.32 a3, l0
 
-# CHECK-ASM: movt32 a3, l0
-# CHECK-ASM: encoding: [0x64,0xc4,0x40,0x0c]
-movt32 a3, l0
+# CHECK-ASM: xtrb2.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x83,0x70]
+xtrb2.32 a3, l0
 
-# CHECK-ASM: movf32 a3, l0
-# CHECK-ASM: encoding: [0x64,0xc4,0x20,0x0c]
-movf32 a3, l0
+# CHECK-ASM: xtrb3.32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x71]
+xtrb3.32 a3, l0
 
 # CHECK-ASM: mvc32 a3
 # CHECK-ASM: encoding: [0x00,0xc4,0x03,0x05]
@@ -240,6 +357,110 @@ zext32 a3, l0, 7, 0
 # CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58]
 sext32 a3, l0, 7, 0
 
+# CHECK-ASM: ldm32 l1-l3, (a0)
+# CHECK-ASM: encoding: [0xa0,0xd0,0x22,0x1c]
+ldm32 r5-r7, (a0)
+
+# CHECK-ASM: stm32 l1-l3, (a0)
+# CHECK-ASM: encoding: [0xa0,0xd4,0x22,0x1c]
+stm32 r5-r7, (a0)
+
+# CHECK-ASM: setc32
+# CHECK-ASM: encoding: [0x00,0xc4,0x20,0x04]
+setc32
+
+# CHECK-ASM: clrc32
+# CHECK-ASM: encoding: [0x00,0xc4,0x80,0x04]
+clrc32
+
+# CHECK-ASM: tst32 a3, l0
+# CHECK-ASM: encoding: [0x83,0xc4,0x80,0x20]
+tst32 a3, l0
+
+# CHECK-ASM: tstnbz32 a3
+# CHECK-ASM: encoding: [0x03,0xc4,0x00,0x21]
+tstnbz32 a3
+
+# CHECK-ASM: clrf32 a3
+# CHECK-ASM: encoding: [0x60,0xc4,0x20,0x2c]
+clrf32 a3
+
+# CHECK-ASM: clrt32 a3
+# CHECK-ASM: encoding: [0x60,0xc4,0x40,0x2c]
+clrt32 a3
+
+# CHECK-ASM: bar.brwarw
+# CHECK-ASM: encoding: [0x00,0xc0,0x2f,0x84]
+bar.brwarw
+
+# CHECK-ASM: bar.brwarws
+# CHECK-ASM: encoding: [0x00,0xc2,0x2f,0x84]
+bar.brwarws
+
+# CHECK-ASM: bar.brarw
+# CHECK-ASM: encoding: [0x00,0xc0,0x27,0x84]
+bar.brarw
+
+# CHECK-ASM: bar.brarws
+# CHECK-ASM: encoding: [0x00,0xc2,0x27,0x84]
+bar.brarws
+
+# CHECK-ASM: bar.brwaw
+# CHECK-ASM: encoding: [0x00,0xc0,0x2e,0x84]
+bar.brwaw
+
+# CHECK-ASM: bar.brwaws
+# CHECK-ASM: encoding: [0x00,0xc2,0x2e,0x84]
+bar.brwaws
+
+# CHECK-ASM: bar.brar
+# CHECK-ASM: encoding: [0x00,0xc0,0x25,0x84]
+bar.brar
+
+# CHECK-ASM: bar.brars
+# CHECK-ASM: encoding: [0x00,0xc2,0x25,0x84]
+bar.brars
+
+# CHECK-ASM: bar.bwaw
+# CHECK-ASM: encoding: [0x00,0xc0,0x2a,0x84]
+bar.bwaw
+
+# CHECK-ASM: bar.bwaws
+# CHECK-ASM: encoding: [0x00,0xc2,0x2a,0x84]
+bar.bwaws
+
+# CHECK-ASM: sync32
+# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x04]
+sync32
+
+# CHECK-ASM: sync32.s
+# CHECK-ASM: encoding: [0x00,0xc2,0x20,0x04]
+sync32.s
+
+# CHECK-ASM: sync32.i
+# CHECK-ASM: encoding: [0x20,0xc0,0x20,0x04]
+sync32.i
+
+# CHECK-ASM: sync32.is
+# CHECK-ASM: encoding: [0x20,0xc2,0x20,0x04]
+sync32.is
+
+# CHECK-ASM: rfi32
+# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x44]
+rfi32
+
+# CHECK-ASM: stop32
+# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x48]
+stop32
+
+# CHECK-ASM: wait32
+# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x4c]
+wait32
+
+# CHECK-ASM: doze32
+# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x50]
+doze32
+
 # CHECK-ASM: br32 .L.test
 # CHECK-ASM: encoding: [A,0xe8'A',A,A]
 # CHECK-ASM: fixup A - offset: 0, value: .L.test, kind: fixup_csky_pcrel_imm16_scale2
@@ -298,7 +519,7 @@ bhsz32 a0, .L.test9
 # CHECK-ASM: encoding: [0xc3,0xe8,0x00,0x00]
 jmp32 a3
 
-# CHECK-ASM: jmpi32 .L.test10
+# CHECK-ASM: jmpi32 [.L.test10]
 # CHECK-ASM: encoding: [0xc0'A',0xea'A',A,A]
 # CHECK-ASM: fixup A - offset: 0, value: .L.test10, kind: fixup_csky_pcrel_uimm16_scale4
 .L.test10:
@@ -314,29 +535,25 @@ bsr32 .L.test11
 # CHECK-ASM: encoding: [0xe3,0xe8,0x00,0x00]
 jsr32 a3
 
-# CHECK-ASM: jsri32 .L.test12
+# CHECK-ASM: jsri32 [.L.test12]
 # CHECK-ASM: encoding: [0xe0'A',0xea'A',A,A]
 # CHECK-ASM: fixup A - offset: 0, value: .L.test12, kind: fixup_csky_pcrel_uimm16_scale4
 .L.test12:
 jsri32 [.L.test12]
 
-# CHECK-ASM: rts32
-# CHECK-ASM: encoding: [0xcf,0xe8,0x00,0x00]
-rts32
-
 # CHECK-ASM: grs32 a0, .L.test13
 # CHECK-ASM: encoding: [0x0c'A',0xcc'A',A,A]
 # CHECK-ASM: fixup A - offset: 0, value: .L.test13, kind: fixup_csky_pcrel_imm18_scale2
 .L.test13:
 grs32 a0, .L.test13
 
-# CHECK-ASM: lrw32 a0, .L.test14
+# CHECK-ASM: lrw32 a0, [.L.test14]
 # CHECK-ASM: encoding: [0x80'A',0xea'A',A,A]
 # CHECK-ASM: fixup A - offset: 0, value: .L.test14, kind: fixup_csky_pcrel_uimm16_scale4
 .L.test14:
 lrw32 a0, [.L.test14]
 
-# RUN: not llvm-mc -triple csky --defsym=ERR=1 < %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple csky -mattr=+e2 -mattr=+2e3 --defsym=ERR=1 < %s 2>&1 | FileCheck %s
 
 .ifdef ERR
 
@@ -404,9 +621,10 @@ subi32 t2, t3, 0x50, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for ins
 xori32 a0, a1 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
 xor32 a0, a2 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
 
-# Need label
-br32 0x100 # CHECK: :[[@LINE]]:6: error: operand must be a symbol name
-jmpi32 0x100 # CHECK: :[[@LINE]]:8: error: operand must be a constpool symbol name
-bsr32 0x100 # CHECK: :[[@LINE]]:7: error: operand must be a symbol name
+ldm32 a1-a33, (a1) # CHECK: :[[#@LINE]]:10: error: invalid register
+stm32 a1-a33, (a1) # CHECK: :[[#@LINE]]:10: error: invalid register
+
+ldq32 a1-a2, (a1) # CHECK: :[[#@LINE]]:1: error: Register sequence is not valid. 'r4-r7' expected
+stq32 a1-a3, (a1) # CHECK: :[[#@LINE]]:1: error: Register sequence is not valid. 'r4-r7' expected
 
-.endif
+.endif
\ No newline at end of file


        


More information about the llvm-commits mailing list