[llvm] 582836f - [CSKY] Enhance asm parser and relocation fixup for some special symbol address instruction

Zi Xuan Wu via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 23 23:14:54 PDT 2022


Author: Zi Xuan Wu
Date: 2022-03-24T14:14:04+08:00
New Revision: 582836faafcb458161947a72df27752fe5f76171

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

LOG: [CSKY] Enhance asm parser and relocation fixup for some special symbol address instruction

Add processing of parsing and emiting lrw/jsri/jmpi instruction, including related fixup and relocation.
Add relax support about pseudo instructions such as jbr/jbsr.
Add objdump format support like arm in llvm-objdump.

Added: 
    llvm/lib/Target/CSKY/CSKYInstrAlias.td
    llvm/test/MC/CSKY/3e3r1.s
    llvm/test/MC/CSKY/801.s
    llvm/test/MC/CSKY/branch-relax-801.s
    llvm/test/MC/CSKY/branch-relax-803.s
    llvm/test/MC/CSKY/bsr.s
    llvm/test/MC/CSKY/jmpi.s
    llvm/test/MC/CSKY/jsri.s
    llvm/test/MC/CSKY/lrs.s
    llvm/test/MC/CSKY/lrw.s
    llvm/test/MC/CSKY/tls_gd.s
    llvm/test/MC/CSKY/tls_ie.s
    llvm/test/MC/CSKY/tls_ld.s
    llvm/test/MC/CSKY/tls_le.s

Modified: 
    llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
    llvm/lib/Target/CSKY/CSKYInstrInfo.td
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
    llvm/tools/llvm-objdump/llvm-objdump.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
index aca05ee8fcfa5..f67147a60c61e 100644
--- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -86,6 +86,9 @@ class CSKYAsmParser : public MCTargetAsmParser {
 
   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
                           MCStreamer &Out);
+  bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+  bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+  bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
 
   CSKYTargetStreamer &getTargetStreamer() {
     assert(getParser().getStreamer().getTargetStreamer() &&
@@ -128,7 +131,11 @@ class CSKYAsmParser : public MCTargetAsmParser {
 
     MCAsmParserExtension::Initialize(Parser);
 
+    // Cache the MCRegisterInfo.
+    MRI = getContext().getRegisterInfo();
+
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+    getTargetStreamer().emitTargetAttributes(STI);
   }
 };
 
@@ -813,6 +820,96 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   llvm_unreachable("Unknown match type detected!");
 }
 
+bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
+  Inst.setLoc(IDLoc);
+
+  unsigned Opcode;
+  MCOperand Op;
+  if (Inst.getOpcode() == CSKY::PseudoLRW16)
+    Opcode = CSKY::LRW16;
+  else
+    Opcode = CSKY::LRW32;
+
+  if (Inst.getOperand(1).isImm()) {
+    if (isUInt<8>(Inst.getOperand(1).getImm()) &&
+        Inst.getOperand(0).getReg() <= CSKY::R7) {
+      Opcode = CSKY::MOVI16;
+    } else if (getSTI().getFeatureBits()[CSKY::HasE2] &&
+               isUInt<16>(Inst.getOperand(1).getImm())) {
+      Opcode = CSKY::MOVI32;
+    } else {
+      auto *Expr = getTargetStreamer().addConstantPoolEntry(
+          MCConstantExpr::create(Inst.getOperand(1).getImm(), getContext()),
+          Inst.getLoc());
+      Inst.erase(std::prev(Inst.end()));
+      Inst.addOperand(MCOperand::createExpr(Expr));
+    }
+  } else {
+    const MCExpr *AdjustExpr = nullptr;
+    if (const CSKYMCExpr *CSKYExpr =
+            dyn_cast<CSKYMCExpr>(Inst.getOperand(1).getExpr())) {
+      if (CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSGD ||
+          CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSIE ||
+          CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSLDM) {
+        MCSymbol *Dot = getContext().createNamedTempSymbol();
+        Out.emitLabel(Dot);
+        AdjustExpr = MCSymbolRefExpr::create(Dot, getContext());
+      }
+    }
+    auto *Expr = getTargetStreamer().addConstantPoolEntry(
+        Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr);
+    Inst.erase(std::prev(Inst.end()));
+    Inst.addOperand(MCOperand::createExpr(Expr));
+  }
+
+  Inst.setOpcode(Opcode);
+
+  Out.emitInstruction(Inst, getSTI());
+  return false;
+}
+
+bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
+  Inst.setLoc(IDLoc);
+
+  if (Inst.getOperand(0).isImm()) {
+    const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
+        MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()),
+        Inst.getLoc());
+    Inst.setOpcode(CSKY::JSRI32);
+    Inst.erase(std::prev(Inst.end()));
+    Inst.addOperand(MCOperand::createExpr(Expr));
+  } else {
+    const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
+        Inst.getOperand(0).getExpr(), Inst.getLoc());
+    Inst.setOpcode(CSKY::JBSR32);
+    Inst.addOperand(MCOperand::createExpr(Expr));
+  }
+
+  Out.emitInstruction(Inst, getSTI());
+  return false;
+}
+
+bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
+  Inst.setLoc(IDLoc);
+
+  if (Inst.getOperand(0).isImm()) {
+    const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
+        MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()),
+        Inst.getLoc());
+    Inst.setOpcode(CSKY::JMPI32);
+    Inst.erase(std::prev(Inst.end()));
+    Inst.addOperand(MCOperand::createExpr(Expr));
+  } else {
+    const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
+        Inst.getOperand(0).getExpr(), Inst.getLoc());
+    Inst.setOpcode(CSKY::JBR32);
+    Inst.addOperand(MCOperand::createExpr(Expr));
+  }
+
+  Out.emitInstruction(Inst, getSTI());
+  return false;
+}
+
 bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
                                        OperandVector &Operands,
                                        MCStreamer &Out) {
@@ -870,6 +967,28 @@ bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
     Inst.erase(std::next(Inst.begin()));
     Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
     break;
+  case CSKY::PseudoLRW16:
+  case CSKY::PseudoLRW32:
+    return processLRW(Inst, IDLoc, Out);
+  case CSKY::PseudoJSRI32:
+    return processJSRI(Inst, IDLoc, Out);
+  case CSKY::PseudoJMPI32:
+    return processJMPI(Inst, IDLoc, Out);
+  case CSKY::JBSR32:
+  case CSKY::JBR16:
+  case CSKY::JBT16:
+  case CSKY::JBF16:
+  case CSKY::JBR32:
+  case CSKY::JBT32:
+  case CSKY::JBF32:
+    unsigned Num = Inst.getNumOperands() - 1;
+    assert(Inst.getOperand(Num).isExpr());
+
+    const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
+        Inst.getOperand(Num).getExpr(), Inst.getLoc());
+
+    Inst.addOperand(MCOperand::createExpr(Expr));
+    break;
   }
 
   emitToStreamer(Out, Inst);

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrAlias.td b/llvm/lib/Target/CSKY/CSKYInstrAlias.td
new file mode 100644
index 0000000000000..e3c0538e752e6
--- /dev/null
+++ b/llvm/lib/Target/CSKY/CSKYInstrAlias.td
@@ -0,0 +1,38 @@
+//===-- CSKYInstrAlias.td - Target Description for CSKY ----*- tablegen -*-===//
+//
+// 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 describes the CSKY instructions alias.
+//
+//===----------------------------------------------------------------------===//
+
+def : InstAlias<"nop", (MOV16 R0, R0)>;
+def : InstAlias<"nop", (MOV32 R0, R0)>, Requires<[iHasE2]>;
+
+def : InstAlias<"bgeni16 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>;
+def : InstAlias<"bgeni32 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>;
+
+def : InstAlias<"bsr $dst", (BSR32 call_symbol:$dst)>;
+
+def : InstAlias<"grs\t$rz, $offset", (GRS32 GPR:$rz, bare_symbol:$offset)>;
+
+def : InstAlias<"jbsr\t$src1", (JBSR32 call_symbol:$src1)>;
+
+def : InstAlias<"jbr $dst", (JBR16 br_symbol_16bit:$dst)>;
+def : InstAlias<"jbt $dst", (JBT16 C, br_symbol_16bit:$dst)>;
+def : InstAlias<"jbf $dst", (JBF16 C, br_symbol_16bit:$dst)>;
+
+def : InstAlias<"lrw $rz, $src", (PseudoLRW16 mGPR:$rz, bare_symbol:$src)>;
+def : InstAlias<"lrw $rz, $src", (LRW16 mGPR:$rz, constpool_symbol_16bit:$src)>;
+def : InstAlias<"lrw $rz, $src", (PseudoLRW32 GPR:$rz, bare_symbol:$src)>;
+def : InstAlias<"lrw $rz, $src", (LRW32 GPR:$rz, constpool_symbol:$src)>;
+
+def : InstAlias<"jsri $dst", (PseudoJSRI32 call_symbol:$dst)>;
+def : InstAlias<"jsri $dst", (JSRI32 constpool_symbol:$dst)>;
+
+def : InstAlias<"jmpi $dst", (PseudoJMPI32 br_symbol:$dst)>;
+def : InstAlias<"jmpi $dst", (JMPI32 constpool_symbol:$dst)>;
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index a782efe7f4f42..e3edf8280c75c 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -709,8 +709,6 @@ let Predicates= [iHasE2] in {
   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
@@ -779,8 +777,6 @@ def BNEZAD32 : CSKY32Inst<AddrModeNone, 0x3a,
 
 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;
@@ -804,7 +800,6 @@ 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",
@@ -1291,8 +1286,6 @@ let Predicates = [iHasE2] in {
 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;
@@ -1338,18 +1331,13 @@ 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),
@@ -1362,3 +1350,4 @@ def CONSTPOOL_ENTRY : CSKYPseudo<(outs),
 include "CSKYInstrInfo16Instr.td"
 include "CSKYInstrInfoF1.td"
 include "CSKYInstrInfoF2.td"
+include "CSKYInstrAlias.td"
\ 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 daa655416c476..215b453739a3e 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
@@ -88,6 +88,13 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
   switch (Fixup.getTargetKind()) {
   default:
     llvm_unreachable("Unknown fixup kind!");
+  case CSKY::fixup_csky_got32:
+  case CSKY::fixup_csky_got_imm18_scale4:
+  case CSKY::fixup_csky_gotoff:
+  case CSKY::fixup_csky_gotpc:
+  case CSKY::fixup_csky_plt32:
+  case CSKY::fixup_csky_plt_imm18_scale4:
+    llvm_unreachable("Relocation should be unconditionally forced\n");
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_4:
@@ -123,6 +130,71 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
 
     return (Value >> 1) & 0x3ffff;
+  case CSKY::fixup_csky_pcrel_uimm8_scale4: {
+    if (!isUIntN(10, Value))
+      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+    if (Value & 0x3)
+      Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
+
+    unsigned IMM4L = (Value >> 2) & 0xf;
+    unsigned IMM4H = (Value >> 6) & 0xf;
+
+    Value = (IMM4H << 21) | (IMM4L << 4);
+    return Value;
+  }
+  case CSKY::fixup_csky_pcrel_imm10_scale2:
+    if (!isIntN(11, Value))
+      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+    if (Value & 0x1)
+      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
+
+    return (Value >> 1) & 0x3ff;
+  case CSKY::fixup_csky_pcrel_uimm7_scale4:
+    if (!isUIntN(9, Value))
+      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+    if (Value & 0x3)
+      Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
+
+    if ((Value & 0xff) <= 0b111111100) {
+      unsigned IMM5L = (Value >> 2) & 0x1f;
+      unsigned IMM2H = (Value >> 7) & 0x3;
+
+      Value = (1 << 12) | (IMM2H << 8) | IMM5L;
+    } else {
+      unsigned IMM5L = (!Value >> 2) & 0x1f;
+      unsigned IMM2H = (!Value >> 7) & 0x3;
+
+      Value = (IMM2H << 8) | IMM5L;
+    }
+
+    return Value & 0xffff;
+  }
+}
+
+bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup,
+                                                  bool Resolved, uint64_t Value,
+                                                  const MCRelaxableFragment *DF,
+                                                  const MCAsmLayout &Layout,
+                                                  const bool WasForced) const {
+  // Return true if the symbol is actually unresolved.
+  // Resolved could be always false when shouldForceRelocation return true.
+  // We use !WasForced to indicate that the symbol is unresolved and not forced
+  // by shouldForceRelocation.
+  if (!Resolved && !WasForced)
+    return true;
+
+  int64_t Offset = int64_t(Value);
+  switch (Fixup.getTargetKind()) {
+  default:
+    return false;
+  case CSKY::fixup_csky_pcrel_imm10_scale2:
+    return !isShiftedInt<10, 1>(Offset);
+  case CSKY::fixup_csky_pcrel_imm16_scale2:
+    return !isShiftedInt<16, 1>(Offset);
+  case CSKY::fixup_csky_pcrel_imm26_scale2:
+    return !isShiftedInt<26, 1>(Offset);
+  case CSKY::fixup_csky_pcrel_uimm7_scale4:
+    return !isShiftedUInt<8, 2>(Offset);
   }
 }
 
@@ -166,6 +238,50 @@ void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
   }
 }
 
+bool CSKYAsmBackend::mayNeedRelaxation(const MCInst &Inst,
+                                       const MCSubtargetInfo &STI) const {
+  switch (Inst.getOpcode()) {
+  default:
+    return false;
+  case CSKY::JBR32:
+  case CSKY::JBT32:
+  case CSKY::JBF32:
+  case CSKY::JBSR32:
+    if (!STI.getFeatureBits()[CSKY::Has2E3])
+      return false;
+    return true;
+  case CSKY::JBR16:
+  case CSKY::JBT16:
+  case CSKY::JBF16:
+  case CSKY::LRW16:
+  case CSKY::BR16:
+    return true;
+  }
+}
+
+bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
+                                           const MCFixup &Fixup,
+                                           const MCValue &Target) {
+  if (Fixup.getKind() >= FirstLiteralRelocationKind)
+    return true;
+  switch (Fixup.getTargetKind()) {
+  default:
+    break;
+  case CSKY::fixup_csky_got32:
+  case CSKY::fixup_csky_got_imm18_scale4:
+  case CSKY::fixup_csky_gotoff:
+  case CSKY::fixup_csky_gotpc:
+  case CSKY::fixup_csky_plt32:
+  case CSKY::fixup_csky_plt_imm18_scale4:
+  case CSKY::fixup_csky_doffset_imm18:
+  case CSKY::fixup_csky_doffset_imm18_scale2:
+  case CSKY::fixup_csky_doffset_imm18_scale4:
+    return true;
+  }
+
+  return false;
+}
+
 bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                                           const MCRelaxableFragment *DF,
                                           const MCAsmLayout &Layout) const {
@@ -174,23 +290,62 @@ bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
 
 void CSKYAsmBackend::relaxInstruction(MCInst &Inst,
                                       const MCSubtargetInfo &STI) const {
-  llvm_unreachable("CSKYAsmBackend::relaxInstruction() unimplemented");
-}
+  MCInst Res;
 
-bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
-                                  const MCSubtargetInfo *STI) const {
-  if (Count % 2)
-    return false;
+  switch (Inst.getOpcode()) {
+  default:
+    Inst.dump();
+    llvm_unreachable("Opcode not expected!");
+  case CSKY::LRW16:
+    Res.setOpcode(CSKY::LRW32);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case CSKY::BR16:
+    Res.setOpcode(CSKY::BR32);
+    Res.addOperand(Inst.getOperand(0));
+    break;
+  case CSKY::JBSR32:
+    Res.setOpcode(CSKY::JSRI32);
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case CSKY::JBR32:
+    Res.setOpcode(CSKY::JMPI32);
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case CSKY::JBT32:
+  case CSKY::JBF32:
+    Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(Inst.getOperand(1));
+    Res.addOperand(Inst.getOperand(2));
+    break;
+  case CSKY::JBR16:
+    Res.setOpcode(CSKY::JBR32);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case CSKY::JBT16:
+  case CSKY::JBF16:
+    // ck801
+    unsigned opcode;
+    if (STI.getFeatureBits()[CSKY::HasE2])
+      opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;
+    else
+      opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;
 
-  // MOV32 r0, r0
-  while (Count >= 4) {
-    OS.write("\xc4\x00\x48\x20", 4);
-    Count -= 4;
+    Res.setOpcode(opcode);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(Inst.getOperand(1));
+    Res.addOperand(Inst.getOperand(2));
+    break;
   }
-  // MOV16 r0, r0
-  if (Count)
-    OS.write("\x6c\x03", 2);
+  Inst = std::move(Res);
+}
 
+bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
+                                  const MCSubtargetInfo *STI) const {
+  OS.write_zeros(Count);
   return true;
 }
 

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
index 87503439fe1a0..09b3ce6cc82be 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
@@ -40,9 +40,21 @@ class CSKYAsmBackend : public MCAsmBackend {
   void relaxInstruction(MCInst &Inst,
                         const MCSubtargetInfo &STI) const override;
 
+  bool mayNeedRelaxation(const MCInst &Inst,
+                         const MCSubtargetInfo &STI) const override;
+
+  bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
+                                    uint64_t Value,
+                                    const MCRelaxableFragment *DF,
+                                    const MCAsmLayout &Layout,
+                                    const bool WasForced) const override;
+
   bool writeNopData(raw_ostream &OS, uint64_t Count,
                     const MCSubtargetInfo *STI) const override;
 
+  bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
+                             const MCValue &Target) override;
+
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override;
 };

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp
index 1636326322908..321a4145b207b 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CSKYFixupKinds.h"
 #include "CSKYMCTargetDesc.h"
+#include "CSKYMCExpr.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCELFObjectWriter.h"
 #include "llvm/MC/MCObjectWriter.h"
@@ -33,10 +35,111 @@ unsigned CSKYELFObjectWriter::getRelocType(MCContext &Ctx,
                                            const MCValue &Target,
                                            const MCFixup &Fixup,
                                            bool IsPCRel) const {
-  // Determine the type of the relocation.
-  switch ((unsigned)Fixup.getKind()) {
+  const MCExpr *Expr = Fixup.getValue();
+  // Determine the type of the relocation
+  unsigned Kind = Fixup.getTargetKind();
+  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
+
+  if (IsPCRel) {
+    switch (Kind) {
+    default:
+      LLVM_DEBUG(dbgs() << "Unknown Kind1  = " << Kind);
+      Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
+      return ELF::R_CKCORE_NONE;
+    case FK_Data_4:
+    case FK_PCRel_4:
+      return ELF::R_CKCORE_PCREL32;
+    case CSKY::fixup_csky_pcrel_uimm16_scale4:
+      return ELF::R_CKCORE_PCREL_IMM16_4;
+    case CSKY::fixup_csky_pcrel_uimm8_scale4:
+      return ELF::R_CKCORE_PCREL_IMM8_4;
+    case CSKY::fixup_csky_pcrel_imm26_scale2:
+      return ELF::R_CKCORE_PCREL_IMM26_2;
+    case CSKY::fixup_csky_pcrel_imm18_scale2:
+      return ELF::R_CKCORE_PCREL_IMM18_2;
+    case CSKY::fixup_csky_pcrel_imm16_scale2:
+      return ELF::R_CKCORE_PCREL_IMM16_2;
+    case CSKY::fixup_csky_pcrel_imm10_scale2:
+      return ELF::R_CKCORE_PCREL_IMM10_2;
+    case CSKY::fixup_csky_pcrel_uimm7_scale4:
+      return ELF::R_CKCORE_PCREL_IMM7_4;
+    }
+  }
+
+  switch (Kind) {
   default:
-    llvm_unreachable("invalid fixup kind!");
+    LLVM_DEBUG(dbgs() << "Unknown Kind2  = " << Kind);
+    Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
+    return ELF::R_CKCORE_NONE;
+  case FK_Data_1:
+    Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
+    return ELF::R_CKCORE_NONE;
+  case FK_Data_2:
+    Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
+    return ELF::R_CKCORE_NONE;
+  case FK_Data_4:
+    if (Expr->getKind() == MCExpr::Target) {
+      auto TK = cast<CSKYMCExpr>(Expr)->getKind();
+      if (TK == CSKYMCExpr::VK_CSKY_ADDR)
+        return ELF::R_CKCORE_ADDR32;
+      if (TK == CSKYMCExpr::VK_CSKY_GOT)
+        return ELF::R_CKCORE_GOT32;
+      if (TK == CSKYMCExpr::VK_CSKY_GOTOFF)
+        return ELF::R_CKCORE_GOTOFF;
+      if (TK == CSKYMCExpr::VK_CSKY_PLT)
+        return ELF::R_CKCORE_PLT32;
+      if (TK == CSKYMCExpr::VK_CSKY_TLSIE)
+        return ELF::R_CKCORE_TLS_IE32;
+      if (TK == CSKYMCExpr::VK_CSKY_TLSLE)
+        return ELF::R_CKCORE_TLS_LE32;
+      if (TK == CSKYMCExpr::VK_CSKY_TLSGD)
+        return ELF::R_CKCORE_TLS_GD32;
+      if (TK == CSKYMCExpr::VK_CSKY_TLSLDM)
+        return ELF::R_CKCORE_TLS_LDM32;
+      if (TK == CSKYMCExpr::VK_CSKY_TLSLDO)
+        return ELF::R_CKCORE_TLS_LDO32;
+      if (TK == CSKYMCExpr::VK_CSKY_GOTPC)
+        return ELF::R_CKCORE_GOTPC;
+      if (TK == CSKYMCExpr::VK_CSKY_None)
+        return ELF::R_CKCORE_ADDR32;
+
+      LLVM_DEBUG(dbgs() << "Unknown FK_Data_4 TK  = " << TK);
+      Ctx.reportError(Fixup.getLoc(), "unknown target FK_Data_4");
+    } else {
+      switch (Modifier) {
+      default:
+        Ctx.reportError(Fixup.getLoc(),
+                        "invalid fixup for 4-byte data relocation");
+        return ELF::R_CKCORE_NONE;
+      case MCSymbolRefExpr::VK_GOT:
+        return ELF::R_CKCORE_GOT32;
+      case MCSymbolRefExpr::VK_GOTOFF:
+        return ELF::R_CKCORE_GOTOFF;
+      case MCSymbolRefExpr::VK_PLT:
+        return ELF::R_CKCORE_PLT32;
+      case MCSymbolRefExpr::VK_None:
+        return ELF::R_CKCORE_ADDR32;
+      }
+    }
+  case FK_Data_8:
+    Ctx.reportError(Fixup.getLoc(), "8-byte data relocations not supported");
+    return ELF::R_CKCORE_NONE;
+  case CSKY::fixup_csky_addr32:
+    return ELF::R_CKCORE_ADDR32;
+  case CSKY::fixup_csky_addr_hi16:
+    return ELF::R_CKCORE_ADDR_HI16;
+  case CSKY::fixup_csky_addr_lo16:
+    return ELF::R_CKCORE_ADDR_LO16;
+  case CSKY::fixup_csky_doffset_imm18:
+    return ELF::R_CKCORE_DOFFSET_IMM18;
+  case CSKY::fixup_csky_doffset_imm18_scale2:
+    return ELF::R_CKCORE_DOFFSET_IMM18_2;
+  case CSKY::fixup_csky_doffset_imm18_scale4:
+    return ELF::R_CKCORE_DOFFSET_IMM18_4;
+  case CSKY::fixup_csky_got_imm18_scale4:
+    return ELF::R_CKCORE_GOT_IMM18_4;
+  case CSKY::fixup_csky_plt_imm18_scale4:
+    return ELF::R_CKCORE_PLT_IMM18_4;
   }
 }
 

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
index 29b91173bc117..540f901fd479d 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
@@ -67,15 +67,170 @@ static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) {
   support::endian::write<uint16_t>(OS, LO16, support::little);
 }
 
+void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, raw_ostream &OS,
+                                   SmallVectorImpl<MCFixup> &Fixups,
+                                   const MCSubtargetInfo &STI) const {
+
+  MCInst TmpInst;
+
+  uint32_t Binary;
+
+  TmpInst =
+      MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16)
+          .addOperand(MI.getOperand(0))
+          .addImm(6);
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  writeData(Binary, 2, OS);
+
+  if (!STI.getFeatureBits()[CSKY::Has2E3])
+    TmpInst = MCInstBuilder(CSKY::BR32)
+                  .addOperand(MI.getOperand(1))
+                  .addOperand(MI.getOperand(2));
+  else
+    TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2));
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  Fixups[Fixups.size() - 1].setOffset(2);
+  writeData(Binary, 4, OS);
+}
+
+void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, raw_ostream &OS,
+                                  SmallVectorImpl<MCFixup> &Fixups,
+                                  const MCSubtargetInfo &STI) const {
+
+  MCInst TmpInst;
+  uint32_t Binary;
+  unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2;
+
+  TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
+                .addOperand(MI.getOperand(0))
+                .addOperand(MI.getOperand(1));
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  writeData(Binary, Size, OS);
+
+  TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
+                .addOperand(MI.getOperand(0))
+                .addOperand(MI.getOperand(0))
+                .addImm(1);
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  writeData(Binary, Size, OS);
+}
+
+void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, raw_ostream &OS,
+                                    SmallVectorImpl<MCFixup> &Fixups,
+                                    const MCSubtargetInfo &STI) const {
+
+  MCInst TmpInst;
+  uint32_t Binary;
+  unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2;
+
+  TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)
+                .addOperand(MI.getOperand(0))
+                .addOperand(MI.getOperand(1));
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  writeData(Binary, Size, OS);
+
+  TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)
+                .addOperand(MI.getOperand(0))
+                .addOperand(MI.getOperand(0))
+                .addImm(MI.getOperand(2).getImm() + 1);
+  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  writeData(Binary, Size, OS);
+}
+
 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();
 
+  MCInst TmpInst;
+
+  switch (MI.getOpcode()) {
+  default:
+    TmpInst = MI;
+    break;
+  case CSKY::JBT_E:
+  case CSKY::JBF_E:
+    expandJBTF(MI, OS, Fixups, STI);
+    MCNumEmitted += 2;
+    return;
+  case CSKY::NEG32:
+  case CSKY::NEG16:
+    expandNEG(MI, OS, Fixups, STI);
+    MCNumEmitted += 2;
+    return;
+  case CSKY::RSUBI32:
+  case CSKY::RSUBI16:
+    expandRSUBI(MI, OS, Fixups, STI);
+    MCNumEmitted += 2;
+    return;
+  case CSKY::JBSR32:
+    TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0));
+    break;
+  case CSKY::JBR16:
+    TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0));
+    break;
+  case CSKY::JBR32:
+    TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0));
+    break;
+  case CSKY::JBT16:
+    TmpInst = MCInstBuilder(CSKY::BT16)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1));
+    break;
+  case CSKY::JBT32:
+    TmpInst = MCInstBuilder(CSKY::BT32)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1));
+    break;
+  case CSKY::JBF16:
+    TmpInst = MCInstBuilder(CSKY::BF16)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1));
+    break;
+  case CSKY::JBF32:
+    TmpInst = MCInstBuilder(CSKY::BF32)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1));
+    break;
+  case CSKY::LRW32_Gen:
+    TmpInst = MCInstBuilder(CSKY::LRW32)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(2));
+    break;
+  case CSKY::LRW16_Gen:
+    TmpInst = MCInstBuilder(CSKY::LRW16)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(2));
+    break;
+  case CSKY::CMPLEI32:
+    TmpInst = MCInstBuilder(CSKY::CMPLTI32)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1))
+                  .addImm(MI.getOperand(2).getImm() + 1);
+    break;
+  case CSKY::CMPLEI16:
+    TmpInst = MCInstBuilder(CSKY::CMPLTI16)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1))
+                  .addImm(MI.getOperand(2).getImm() + 1);
+    break;
+  case CSKY::ROTRI32:
+    TmpInst = MCInstBuilder(CSKY::ROTLI32)
+                  .addOperand(MI.getOperand(0))
+                  .addOperand(MI.getOperand(1))
+                  .addImm(32 - MI.getOperand(2).getImm());
+    break;
+  case CSKY::BGENI:
+    auto V = 1 << MI.getOperand(1).getImm();
+    TmpInst =
+        MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V);
+    break;
+  }
+
   ++MCNumEmitted;
 
-  uint32_t Bin = getBinaryCodeForInstr(MI, Fixups, STI);
+  uint32_t Bin = getBinaryCodeForInstr(TmpInst, Fixups, STI);
 
   uint16_t LO16 = static_cast<uint16_t>(Bin);
   uint16_t HI16 = static_cast<uint16_t>(Bin >> 16);

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
index 0720d33920200..128430197cc53 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
@@ -171,6 +171,16 @@ class CSKYMCCodeEmitter : public MCCodeEmitter {
     Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
     return 0;
   }
+
+  void expandJBTF(const MCInst &MI, raw_ostream &OS,
+                  SmallVectorImpl<MCFixup> &Fixups,
+                  const MCSubtargetInfo &STI) const;
+  void expandNEG(const MCInst &MI, raw_ostream &OS,
+                 SmallVectorImpl<MCFixup> &Fixups,
+                 const MCSubtargetInfo &STI) const;
+  void expandRSUBI(const MCInst &MI, raw_ostream &OS,
+                   SmallVectorImpl<MCFixup> &Fixups,
+                   const MCSubtargetInfo &STI) const;
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
index c41a20060e484..1a69dc8acde05 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
@@ -19,6 +19,7 @@
 #include "CSKYTargetStreamer.h"
 #include "TargetInfo/CSKYTargetInfo.h"
 #include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -107,6 +108,49 @@ static MCTargetStreamer *createCSKYNullTargetStreamer(MCStreamer &S) {
   return new CSKYTargetStreamer(S);
 }
 
+namespace {
+
+class CSKYMCInstrAnalysis : public MCInstrAnalysis {
+public:
+  explicit CSKYMCInstrAnalysis(const MCInstrInfo *Info)
+      : MCInstrAnalysis(Info) {}
+
+  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
+                      uint64_t &Target) const override {
+    if (isConditionalBranch(Inst) || isUnconditionalBranch(Inst)) {
+      int64_t Imm;
+      Imm = Inst.getOperand(Inst.getNumOperands() - 1).getImm();
+      Target = Addr + Imm;
+      return true;
+    }
+
+    if (Inst.getOpcode() == CSKY::BSR32) {
+      Target = Addr + Inst.getOperand(0).getImm();
+      return true;
+    }
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case CSKY::LRW16:
+    case CSKY::LRW32:
+    case CSKY::JSRI32:
+    case CSKY::JMPI32:
+      int64_t Imm = Inst.getOperand(Inst.getNumOperands() - 1).getImm();
+      Target = ((Addr + Imm) & 0xFFFFFFFC);
+      return true;
+    }
+
+    return false;
+  }
+};
+
+} // end anonymous namespace
+
+static MCInstrAnalysis *createCSKYInstrAnalysis(const MCInstrInfo *Info) {
+  return new CSKYMCInstrAnalysis(Info);
+}
+
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() {
   auto &CSKYTarget = getTheCSKYTarget();
   TargetRegistry::RegisterMCAsmBackend(CSKYTarget, createCSKYAsmBackend);
@@ -125,4 +169,5 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() {
   // Register the null target streamer.
   TargetRegistry::RegisterNullTargetStreamer(CSKYTarget,
                                              createCSKYNullTargetStreamer);
+  TargetRegistry::RegisterMCInstrAnalysis(CSKYTarget, createCSKYInstrAnalysis);
 }

diff  --git a/llvm/test/MC/CSKY/3e3r1.s b/llvm/test/MC/CSKY/3e3r1.s
new file mode 100644
index 0000000000000..2aebc90083c05
--- /dev/null
+++ b/llvm/test/MC/CSKY/3e3r1.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+3e3r1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+3e3r1 < %s \
+# RUN:     | llvm-objdump --mattr=+3e3r1 -M no-aliases -M abi-names -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+
+
+# CHECK-ASM-AND-OBJ: mul.s32 a3, l0, a1
+# CHECK-ASM: encoding: [0x24,0xf8,0x03,0x82]
+mul.s32 a3, l0, a1
+
+# CHECK-ASM-AND-OBJ: mul.u32 a3, l0, a1
+# CHECK-ASM: encoding: [0x24,0xf8,0x03,0x80]
+mul.u32 a3, l0, a1
+
+# CHECK-ASM-AND-OBJ: mula.s32 a3, l0, a1
+# CHECK-ASM: encoding: [0x24,0xf8,0x83,0x82]
+mula.s32 a3, l0, a1
+
+# CHECK-ASM-AND-OBJ: mula.u32 a3, l0, a1
+# CHECK-ASM: encoding: [0x24,0xf8,0x83,0x80]
+mula.u32 a3, l0, a1
\ No newline at end of file

diff  --git a/llvm/test/MC/CSKY/801.s b/llvm/test/MC/CSKY/801.s
new file mode 100644
index 0000000000000..9b3d5ce394fc4
--- /dev/null
+++ b/llvm/test/MC/CSKY/801.s
@@ -0,0 +1,19 @@
+# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+e1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+e1 < %s \
+# RUN:     | llvm-objdump --mattr=+e1 -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: ipush
+# CHECK-ASM: encoding: [0x62,0x14]
+ipush16
+
+# CHECK-ASM-AND-OBJ: ipop
+# CHECK-ASM: encoding: [0x63,0x14]
+ipop16
+
+# RUN: not llvm-mc -triple csky -mattr=+e1 --defsym=ERR=1 < %s 2>&1 | FileCheck %s
+
+.ifdef ERR
+ipush16 1 # CHECK: :[[#@LINE]]:9: error: invalid operand for instruction
+.endif

diff  --git a/llvm/test/MC/CSKY/branch-relax-801.s b/llvm/test/MC/CSKY/branch-relax-801.s
new file mode 100644
index 0000000000000..87a51cd947402
--- /dev/null
+++ b/llvm/test/MC/CSKY/branch-relax-801.s
@@ -0,0 +1,44 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck801 < %s \
+# RUN:     | llvm-objdump --mattr=+e1 --no-show-raw-insn -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ-CK801 %s
+# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck802 < %s \
+# RUN:     | llvm-objdump --mattr=+e2 --no-show-raw-insn -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ-CK802 %s
+
+# CHECK-OBJ-CK801:            0:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK801-NEXT:       2:      	bt16	0x8
+# CHECK-OBJ-CK801-NEXT:       4:      	br32	0x4bc
+# CHECK-OBJ-CK801-NEXT:       8:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK801:          4ba:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK801-NEXT:     4bc:      	bf16	0x4c2
+# CHECK-OBJ-CK801-NEXT:     4be:      	br32	0x2
+# CHECK-OBJ-CK801-NEXT:     4c2:      	br32	0x2
+# CHECK-OBJ-CK801-NEXT:     4c6:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK801-NEXT:     4c8:      	br16	0x4ca
+
+# CHECK-OBJ-CK802:            0:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK802-NEXT:       2:      	bf32	0x96a
+# CHECK-OBJ-CK802-NEXT:       6:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK802:          968:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK802-NEXT:     96a:      	bt32	0x2
+# CHECK-OBJ-CK802-NEXT:     96e:      	br32	0x2
+# CHECK-OBJ-CK802-NEXT:     972:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK802-NEXT:     974:      	br16	0x976
+
+	addu16 r1, r2, r3
+.L1:
+	jbf .L2
+	addu16 r3, r2, r1
+
+	.rept 600
+	nop
+	.endr
+
+
+	addu16 r1, r2, r3
+.L2:
+	jbt .L1
+	jbr .L1
+	addu16 r3, r2, r1
+	jbr .L3
+.L3:

diff  --git a/llvm/test/MC/CSKY/branch-relax-803.s b/llvm/test/MC/CSKY/branch-relax-803.s
new file mode 100644
index 0000000000000..6aacbe20ad143
--- /dev/null
+++ b/llvm/test/MC/CSKY/branch-relax-803.s
@@ -0,0 +1,35 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck803 < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ-CK803 %s
+
+# CHECK-OBJ-CK803:            0:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK803-NEXT:       2:      	bt16	0x8
+# CHECK-OBJ-CK803-NEXT:       4:      	jmpi32  0x3a9a0 <$d.0>
+# CHECK-OBJ-CK803-NEXT:       8:        bsr32   0x3a990 <.text+0x3a990>
+# CHECK-OBJ-CK803-NEXT:       c:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK803:        3a98e:      	addu16	r1, r2, r3
+# CHECK-OBJ-CK803-NEXT:   3a990:      	bf16	0x3a996 <.text+0x3a996>
+# CHECK-OBJ-CK803-NEXT:   3a992:      	jmpi32  0x3a9a4 <$d.0+0x4>
+# CHECK-OBJ-CK803-NEXT:   3a996:      	jmpi32	0x3a9a4 <$d.0+0x4>
+# CHECK-OBJ-CK803-NEXT:   3a99a:      	addu16	r3, r2, r1
+# CHECK-OBJ-CK803-NEXT:   3a99c:      	br16	0x3a99e <.text+0x3a99e>
+
+
+        addu16 r1, r2, r3
+.L1:
+	jbf .L2
+	jbsr .L2
+	addu16 r3, r2, r1
+
+	.rept 60000
+	nop
+	.endr
+
+
+	addu16 r1, r2, r3
+.L2:
+	jbt .L1
+	jbr .L1
+	addu16 r3, r2, r1
+	jbr .L3
+.L3:

diff  --git a/llvm/test/MC/CSKY/bsr.s b/llvm/test/MC/CSKY/bsr.s
new file mode 100644
index 0000000000000..f4c79ec6d316a
--- /dev/null
+++ b/llvm/test/MC/CSKY/bsr.s
@@ -0,0 +1,54 @@
+# RUN: llvm-mc -filetype=obj -triple=csky  < %s \
+# RUN:     | llvm-objdump  --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+.data
+sec:
+    .long 0x77
+.text
+tstart:
+    bsr lnk
+    bsr lnk - 4
+    bsr lnk + 4
+    .short 0x1C00
+    bsr sec
+    bsr sec - 4
+    bsr sec + 4
+
+.L1:
+    bsr .L1
+.L2:
+    bsr .L2 - 1024
+.L3:
+    bsr .L3 + 1022
+
+.L4:
+    bsr .L4 - 1026
+.L5:
+    bsr .L5 + 1024
+
+.L6:
+    bsr .L6 - 64*1024*1024
+.L7:
+    bsr .L7 + 64*1024*1024 - 2
+
+
+# CHECK:       0:      	bsr32	0x0
+# CHECK:       			        00000000:  R_CKCORE_PCREL_IMM26_2	lnk
+# CHECK:       4:      	bsr32	0x4
+# CHECK:       			        00000004:  R_CKCORE_PCREL_IMM26_2	lnk-0x4
+# CHECK:       8:      	bsr32	0x8
+# CHECK:       			        00000008:  R_CKCORE_PCREL_IMM26_2	lnk+0x4
+
+# CHECK:       e:      	bsr32	0xe
+# CHECK:       			        0000000e:  R_CKCORE_PCREL_IMM26_2	.data
+# CHECK:       12:      bsr32	0x12
+# CHECK:       			        00000012:  R_CKCORE_PCREL_IMM26_2	.data-0x4
+# CHECK:       16:      bsr32	0x16
+# CHECK:       			        00000016:  R_CKCORE_PCREL_IMM26_2	.data+0x4
+# CHECK:       1a:      bsr32	0x1a
+# CHECK:       1e:      bsr32	0xfffffc1e
+# CHECK:       22:      bsr32	0x420
+# CHECK:       26:      bsr32	0xfffffc24
+# CHECK:       2a:      bsr32	0x42a
+# CHECK:       2e:      bsr32	0xfc00002e
+# CHECK:       32:      bsr32	0x4000030
\ No newline at end of file

diff  --git a/llvm/test/MC/CSKY/jmpi.s b/llvm/test/MC/CSKY/jmpi.s
new file mode 100644
index 0000000000000..a02aaac7b5c8a
--- /dev/null
+++ b/llvm/test/MC/CSKY/jmpi.s
@@ -0,0 +1,20 @@
+# RUN: llvm-mc -filetype=obj -triple=csky  < %s \
+# RUN:     | llvm-objdump  --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL
+  bkpt
+
+
+# CHECK:        0:      	bkpt
+# CHECK-NEXT:   2:      	br32	0x0
+# CHECK-NEXT:   6:      	bkpt
+
+
+# CHECK:        8:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:   			    00000008:  R_CKCORE_ADDR32	.text
+

diff  --git a/llvm/test/MC/CSKY/jsri.s b/llvm/test/MC/CSKY/jsri.s
new file mode 100644
index 0000000000000..8342f89f61d9c
--- /dev/null
+++ b/llvm/test/MC/CSKY/jsri.s
@@ -0,0 +1,73 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3  < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+
+.data
+sec:
+    .long 0x77
+.text
+tstart:
+    jsri lnk
+    jsri lnk - 4
+    jsri lnk + 4
+    .short 0x1C00
+    jsri sec
+    jsri sec - 4
+    jsri sec + 4
+
+.J1:
+    jsri .J1
+.J2:
+    jsri .J2 - 0x1000
+.J3:
+    jsri .J3 + 0x1000
+
+    jsri 0x01020304
+    jsri 0xFFFFFFFE
+
+
+# CHECK:         0:      	jsri32  0x30 <$d.4>
+# CHECK-NEXT:    4:      	jsri32	0x34 <$d.4+0x4>
+# CHECK-NEXT:    8:      	jsri32	0x38 <$d.4+0x8>
+
+# CHECK:         c:	        00 1c	.short	0x1c00
+
+# CHECK:         e:      	jsri32	0x3c <$d.4+0xc>
+# CHECK-NEXT:   12:         jsri32	0x40 <$d.4+0x10>
+# CHECK-NEXT:   16:         jsri32	0x44 <$d.4+0x14>
+
+
+
+# CHECK:    <.J1>:
+# CHECK-NEXT:   1a:         bsr32	0x1a
+
+# CHECK:    <.J2>:
+# CHECK-NEXT:   1e:         bsr32	0xfffff01e <$d.4+0xffffffffffffefee>
+
+# CHECK:    <.J3>:
+# CHECK-NEXT:   22:         bsr32	0x1022 <$d.4+0xff2>
+# CHECK-NEXT:   26:         jsri32	0x54 <$d.4+0x24>
+# CHECK-NEXT:   2a:         jsri32	0x58 <$d.4+0x28>
+# CHECK-NEXT:   2e:         bkpt
+
+
+# CHECK:        30:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000030:  R_CKCORE_ADDR32	lnk
+# CHECK-NEXT:   34:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000034:  R_CKCORE_ADDR32	lnk-0x4
+# CHECK-NEXT:   38:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000038:  R_CKCORE_ADDR32	lnk+0x4
+# CHECK-NEXT:   3c:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        0000003c:  R_CKCORE_ADDR32	.data
+# CHECK-NEXT:   40:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000040:  R_CKCORE_ADDR32	.data-0x4
+# CHECK-NEXT:   44:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000044:  R_CKCORE_ADDR32	.data+0x4
+# CHECK-NEXT:   48:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000048:  R_CKCORE_ADDR32	.text+0x1a
+# CHECK-NEXT:   4c:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        0000004c:  R_CKCORE_ADDR32	.text-0xfe2
+# CHECK-NEXT:   50:      00 00 00 00     .word	0x0
+# CHECK-NEXT:   			        00000050:  R_CKCORE_ADDR32	.text+0x1022
+# CHECK-NEXT:   54:      04 03 02 01	 .word	0x01020304
+# CHECK-NEXT:   58:      fe ff ff ff     .word	0xfffffffe

diff  --git a/llvm/test/MC/CSKY/lrs.s b/llvm/test/MC/CSKY/lrs.s
new file mode 100644
index 0000000000000..f0eb66bd388f5
--- /dev/null
+++ b/llvm/test/MC/CSKY/lrs.s
@@ -0,0 +1,57 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3  < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+
+.data
+sec:
+    .long 0x77
+.text
+tstart:
+    lrs32.b r0,[lnk]
+    lrs32.b r0,[lnk - 4]
+    lrs32.b r0,[lnk + 4]
+    .short 0x1C00
+    lrs32.h r0,[sec]
+    lrs32.h r0,[sec - 4]
+    lrs32.h r0,[sec + 4]
+    lrs32.b r0,[0]
+    lrs32.b r0,[0xFFFF]
+    lrs32.b r31,[0]
+.L1:
+    lrs32.w r31,[.L1]
+.L2:
+    lrs32.w r0, [.L2]
+.L3:
+    lrs32.w r0, [.L3 - 64*1024]
+.L4:
+    lrs32.w r0, [.L4 + 64*1024 - 2]
+
+# CHECK:        0:      	lrs32.b	r0, [0]
+# CHECK-NEXT:   			        00000000:  R_CKCORE_DOFFSET_IMM18	lnk
+# CHECK-NEXT:   4:      	lrs32.b	r0, [0]
+# CHECK-NEXT:   			        00000004:  R_CKCORE_DOFFSET_IMM18	lnk-0x4
+# CHECK-NEXT:   8:      	lrs32.b	r0, [0]
+# CHECK-NEXT:   			        00000008:  R_CKCORE_DOFFSET_IMM18	lnk+0x4
+
+# CHECK:        c:	        00 1c		.short	0x1c00
+
+# CHECK:        e:       lrs32.h	r0, [0]
+# CHECK-NEXT:   			        0000000e:  R_CKCORE_DOFFSET_IMM18_2	.data
+# CHECK-NEXT:   12:      lrs32.h	r0, [0]
+# CHECK-NEXT:   			        00000012:  R_CKCORE_DOFFSET_IMM18_2	.data-0x4
+# CHECK-NEXT:   16:      lrs32.h	r0, [0]
+# CHECK-NEXT:   			        00000016:  R_CKCORE_DOFFSET_IMM18_2	.data+0x4
+# CHECK-NEXT:   1a:      lrs32.b	r0, [0]
+# CHECK-NEXT:   			        0000001a:  R_CKCORE_DOFFSET_IMM18	*ABS*
+# CHECK-NEXT:   1e:      lrs32.b	r0, [0]
+# CHECK-NEXT:   			        0000001e:  R_CKCORE_DOFFSET_IMM18	*ABS*+0xffff
+# CHECK-NEXT:   22:      lrs32.b	r31, [0]
+# CHECK-NEXT:   			        00000022:  R_CKCORE_DOFFSET_IMM18	*ABS*
+# CHECK-NEXT:   26:      lrs32.w	r31, [0]
+# CHECK-NEXT:   			        00000026:  R_CKCORE_DOFFSET_IMM18_4	.text+0x26
+# CHECK-NEXT:   2a:      lrs32.w	r0, [0]
+# CHECK-NEXT:   			        0000002a:  R_CKCORE_DOFFSET_IMM18_4	.text+0x2a
+# CHECK-NEXT:   2e:      lrs32.w	r0, [0]
+# CHECK-NEXT:   			        0000002e:  R_CKCORE_DOFFSET_IMM18_4	.text-0xffd2
+# CHECK-NEXT:   32:      lrs32.w	r0, [0]
+# CHECK-NEXT:   			        00000032:  R_CKCORE_DOFFSET_IMM18_4	.text+0x10030

diff  --git a/llvm/test/MC/CSKY/lrw.s b/llvm/test/MC/CSKY/lrw.s
new file mode 100644
index 0000000000000..69eea7e128c3d
--- /dev/null
+++ b/llvm/test/MC/CSKY/lrw.s
@@ -0,0 +1,73 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+e2 < %s \
+# RUN:     | llvm-objdump --mattr=+e2  --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+
+.data
+sec:
+    .long 0x77
+.text
+tstart:
+    lrw r0,lnk
+    lrw r0,lnk - 4
+    lrw r0,lnk + 4
+    .short 0x1C00
+    lrw r0,sec
+    lrw r0,sec - 4
+    lrw r0,sec + 4
+    lrw r0,0
+    lrw r0,0xFFFF
+    lrw r31,0
+.L1:
+    lrw r31,.L1
+.L2:
+    lrw r0, .L2
+.L3:
+    lrw r0, .L3 - 64*1024
+.L4:
+    lrw r0, .L4 + 64*1024 - 2
+
+    lrw r0,0x01020304
+    lrw r0,0xFFFFFFFE
+
+# CHECK:        0:      	lrw16	r0, 0x28 <$d.4>
+# CHECK-NEXT:   2:      	lrw16	r0, 0x2c  <$d.4+0x4>
+# CHECK-NEXT:   4:      	lrw16	r0, 0x30  <$d.4+0x8>
+
+# CHECK:        6:	        00 1c	.short	0x1c00
+
+# CHECK:        8:      	lrw16	r0, 0x34 <$d.4+0xc>
+# CHECK-NEXT:   a:      	lrw16	r0, 0x38  <$d.4+0x10>
+# CHECK-NEXT:   c:      	lrw16	r0, 0x3c <$d.4+0x14>
+# CHECK-NEXT:   e:      	movi16	r0, 0
+# CHECK-NEXT:  10:      	movi32	r0, 65535
+# CHECK-NEXT:  14:      	movi32	r31, 0
+# CHECK-NEXT:  18:              lrw32	r31, 0x40 <$d.4+0x18>
+# CHECK-NEXT:  1c:              lrw16	r0,  0x44 <$d.4+0x1c>
+# CHECK-NEXT:  1e:              lrw16	r0,  0x48 <$d.4+0x20>
+# CHECK-NEXT:  20:              lrw16	r0,  0x4c <$d.4+0x24>
+# CHECK-NEXT:  22:              lrw16	r0,  0x50 <$d.4+0x28>
+# CHECK-NEXT:  24:              lrw16	r0,  0x54 <$d.4+0x2c>
+
+# CHECK:       28:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      00000028:  R_CKCORE_ADDR32	lnk
+# CHECK-NEXT:  2c:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      0000002c:  R_CKCORE_ADDR32	lnk-0x4
+# CHECK-NEXT:  30:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      00000030:  R_CKCORE_ADDR32	lnk+0x4
+# CHECK-NEXT:  34:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      00000034:  R_CKCORE_ADDR32	.data
+# CHECK-NEXT:  38:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      00000038:  R_CKCORE_ADDR32	.data-0x4
+# CHECK-NEXT:  3c:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	      0000003c:  R_CKCORE_ADDR32	.data+0x4
+# CHECK-NEXT:  40:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	     00000040:  R_CKCORE_ADDR32	.text+0x18
+# CHECK-NEXT:  44:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	     00000044:  R_CKCORE_ADDR32	.text+0x1c
+# CHECK-NEXT:  48:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	     00000048:  R_CKCORE_ADDR32	.text-0xffe2
+# CHECK-NEXT:  4c:	    00 00 00 00	.word	0x00000000
+# CHECK-NEXT:       	     0000004c:  R_CKCORE_ADDR32	.text+0x1001e
+# CHECK-NEXT:  50:	    04 03 02 01	.word	0x01020304
+# CHECK-NEXT:  54:	    fe ff ff ff	.word	0xfffffffe
+

diff  --git a/llvm/test/MC/CSKY/tls_gd.s b/llvm/test/MC/CSKY/tls_gd.s
new file mode 100644
index 0000000000000..3e1cc06238391
--- /dev/null
+++ b/llvm/test/MC/CSKY/tls_gd.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3  < %s \
+# RUN:     | llvm-objdump  --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+.LTLS0:
+	lrw16 r0, xxx at TLSGD32
+	grs32 r2, .LTLS0
+	addu16 r0, r0, r2
+	lrw16 r3, __tls_get_addr at PLT
+	ldr32.w r3, (rgb, r3 << 0)
+	jsr16 r3
+
+# CHECK:            0:      	lrw16	r0, 0x10 <$d.0>
+# CHECK-NEXT:       2:      	grs32	r2, 0x0
+# CHECK-NEXT:       6:      	addu16	r0, r0, r2
+# CHECK-NEXT:       8:      	lrw16	r3, 0x14  <$d.0+0x4>
+# CHECK-NEXT:       a:      	ldr32.w	r3, (r28, r3 << 0)
+# CHECK-NEXT:       e:      	jsr16	r3
+
+# CHECK:           10:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           00000010:  R_CKCORE_TLS_GD32	xxx+0x10
+# CHECK-NEXT:      14:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           00000014:  R_CKCORE_PLT32	__tls_get_addr

diff  --git a/llvm/test/MC/CSKY/tls_ie.s b/llvm/test/MC/CSKY/tls_ie.s
new file mode 100644
index 0000000000000..1752dfc9b7f90
--- /dev/null
+++ b/llvm/test/MC/CSKY/tls_ie.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+.LTLS0:
+	lrw16 r3, xxx at GOTTPOFF
+	grs32 r2, .LTLS0
+	addu16 r3, r3, r2
+	ld16.w r3, (r3, 0)
+        lsli32  r2, r31, 0
+	str32.w r0, (r2, r3 << 0)
+
+
+# CHECK:            0:      	lrw16	r3, 0x14 <$d.0>
+# CHECK-NEXT:       2:      	grs32	r2, 0x0
+# CHECK-NEXT:       6:      	addu16	r3, r3, r2
+# CHECK-NEXT:       8:      	ld16.w	r3, (r3, 0x0)
+# CHECK-NEXT:       a:      	lsli32	r2, r31, 0
+# CHECK-NEXT:       e:      	str32.w	r0, (r2, r3 << 0)
+# CHECK-NEXT:       12:      	bkpt
+
+# CHECK:           14:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           00000014:  R_CKCORE_TLS_IE32	xxx+0x14

diff  --git a/llvm/test/MC/CSKY/tls_ld.s b/llvm/test/MC/CSKY/tls_ld.s
new file mode 100644
index 0000000000000..c4cbf15dfd81f
--- /dev/null
+++ b/llvm/test/MC/CSKY/tls_ld.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3  < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+.LTLS0:
+	lrw16 r0, xxx at TLSLDM32
+	grs32 r2, .LTLS0
+	addu16 r0, r0, r2
+	lrw16 r3, __tls_get_addr at PLT
+	ldr32.w r3, (rgb, r3 << 0)
+	jsr16 r3
+	lrw16 r3, xxx at TLSLDO32
+	str32.w r4, (r0, r3 << 0)
+
+# CHECK:            0:      	lrw16	r0, 0x18 <$d.0>
+# CHECK-NEXT:       2:      	grs32	r2, 0x0
+# CHECK-NEXT:       6:      	addu16	r0, r0, r2
+# CHECK-NEXT:       8:      	lrw16	r3, 0x1c <$d.0+0x4>
+# CHECK-NEXT:       a:      	ldr32.w	r3, (r28, r3 << 0)
+# CHECK-NEXT:       e:      	jsr16	r3
+# CHECK-NEXT:       10:      	lrw16	r3, 0x20 <$d.0+0x8>
+# CHECK-NEXT:       12:      	str32.w	r4, (r0, r3 << 0)
+# CHECK-NEXT:       16:      	bkpt
+
+# CHECK:            18:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           00000018:  R_CKCORE_TLS_LDM32	xxx+0x18
+# CHECK-NEXT:       1c:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           0000001c:  R_CKCORE_PLT32	__tls_get_addr
+# CHECK-NEXT:       20:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           00000020:  R_CKCORE_TLS_LDO32	xxx

diff  --git a/llvm/test/MC/CSKY/tls_le.s b/llvm/test/MC/CSKY/tls_le.s
new file mode 100644
index 0000000000000..3206643ef255f
--- /dev/null
+++ b/llvm/test/MC/CSKY/tls_le.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3  < %s \
+# RUN:     | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s
+
+	lrw16 r3, xxx at TPOFF
+        lsli32    r2, r31, 0
+	str32.w r0, (r2, r3 << 0)
+
+# CHECK:            0:      	lrw16	r3, 0xc <$d.0>
+# CHECK-NEXT:       2:      	lsli32    r2, r31, 0
+# CHECK-NEXT:       6:      	str32.w	r0, (r2, r3 << 0)
+# CHECK-NEXT:       a:      	bkpt
+
+# CHECK:            c:	00 00 00 00	.word	0x00000000
+# CHECK-NEXT:           0000000c:  R_CKCORE_TLS_LE32	xxx

diff  --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index c8c512659f4b0..a9ce463c22bb1 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -441,8 +441,13 @@ static bool isArmElf(const ObjectFile *Obj) {
   return Elf && Elf->getEMachine() == ELF::EM_ARM;
 }
 
+static bool isCSKYElf(const ObjectFile *Obj) {
+  const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
+  return Elf && Elf->getEMachine() == ELF::EM_CSKY;
+}
+
 static bool hasMappingSymbols(const ObjectFile *Obj) {
-  return isArmElf(Obj) || isAArch64Elf(Obj);
+  return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ;
 }
 
 static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,


        


More information about the llvm-commits mailing list