[llvm] 4bb60c2 - [CSKY 6/n] Add support branch and symbol series instruction

Zi Xuan Wu via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 20 00:38:49 PDT 2021


Author: Zi Xuan Wu
Date: 2021-04-20T15:36:49+08:00
New Revision: 4bb60c285cb3090e5fa91f585714a63618e08b4f

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

LOG: [CSKY 6/n] Add support branch and symbol series instruction

This patch adds basic CSKY branch instructions and symbol address series instructions.
Those two kinds of instruction have relationship between each other, and it involves much work about Fixups.

For now, basic instructions are enabled except for disassembler support.
We would support to generate basic codegen asm firstly and delay disassembler work later.

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

Added: 
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
    llvm/test/MC/CSKY/csky-error.s

Modified: 
    llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
    llvm/lib/Target/CSKY/CSKYInstrFormats.td
    llvm/lib/Target/CSKY/CSKYInstrInfo.td
    llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
    llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.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 c971638e449c..f2a381190fe7 100644
--- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/CSKYMCExpr.h"
 #include "MCTargetDesc/CSKYMCTargetDesc.h"
 #include "TargetInfo/CSKYTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
@@ -58,6 +59,8 @@ class CSKYAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy parseImmediate(OperandVector &Operands);
   OperandMatchResultTy parseRegister(OperandVector &Operands);
   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
+  OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
+  OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -171,6 +174,20 @@ struct CSKYOperand : public MCParsedAsmOperand {
   bool isUImm12Shift1() { return isUImm<12, 1>(); }
   bool isUImm12Shift2() { return isUImm<12, 2>(); }
 
+  bool isSImm16Shift1() { return isSImm<16, 1>(); }
+
+  bool isCSKYSymbol() const {
+    int64_t Imm;
+    // Must be of 'immediate' type but not a constant.
+    return isImm() && !evaluateConstantImm(getImm(), Imm);
+  }
+
+  bool isConstpoolSymbol() const {
+    int64_t Imm;
+    // Must be of 'immediate' type but not a constant.
+    return isImm() && !evaluateConstantImm(getImm(), Imm);
+  }
+
   /// Gets location of the first token of this operand.
   SMLoc getStartLoc() const override { return StartLoc; }
   /// Gets location of the last token of this operand.
@@ -350,6 +367,14 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
         "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");
+  }
+  case Match_InvalidConstpool: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "operand must be a constpool symbol name");
+  }
   }
 
   llvm_unreachable("Unknown match type detected!");
@@ -482,6 +507,15 @@ OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
 /// information, adding to Operands. If operand was parsed, returns false, else
 /// true.
 bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
+  // Check if the current operand has a custom associated parser, if so, try to
+  // custom parse the operand, or fallback to the general approach.
+  OperandMatchResultTy Result =
+      MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
+  if (Result == MatchOperand_Success)
+    return false;
+  if (Result == MatchOperand_ParseFail)
+    return true;
+
   // Attempt to parse token as register
   if (parseRegister(Operands) == MatchOperand_Success)
     return false;
@@ -500,6 +534,68 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
   return true;
 }
 
+OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+  if (getLexer().getKind() != AsmToken::Identifier)
+    return MatchOperand_NoMatch;
+
+  StringRef Identifier;
+  if (getParser().parseIdentifier(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"))
+    Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
+  else if (Identifier.consume_back("@PLT"))
+    Kind = CSKYMCExpr::VK_CSKY_PLT;
+  else if (Identifier.consume_back("@GOTPC"))
+    Kind = CSKYMCExpr::VK_CSKY_GOTPC;
+
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
+  const MCExpr *Res =
+      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+
+  if (Kind != CSKYMCExpr::VK_CSKY_None)
+    Res = CSKYMCExpr::create(Res, Kind, getContext());
+
+  Operands.push_back(CSKYOperand::createImm(Res, S, E));
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+  if (getLexer().getKind() != AsmToken::LBrac)
+    return MatchOperand_NoMatch;
+
+  getLexer().Lex(); // Eat '['.
+
+  if (getLexer().getKind() != AsmToken::Identifier)
+    return MatchOperand_NoMatch;
+
+  StringRef Identifier;
+  if (getParser().parseIdentifier(Identifier))
+    return MatchOperand_ParseFail;
+
+  if (getLexer().getKind() != AsmToken::RBrac)
+    return MatchOperand_NoMatch;
+
+  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));
+  return MatchOperand_Success;
+}
+
 bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                                      SMLoc NameLoc, OperandVector &Operands) {
   // First operand is token for instruction.

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrFormats.td b/llvm/lib/Target/CSKY/CSKYInstrFormats.td
index bc247eecfd70..dd71b693bbbb 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrFormats.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrFormats.td
@@ -54,13 +54,14 @@ class J<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern>
                  pattern> {
   bits<26> offset;
   let Inst{25 - 0} = offset;
+  let isCall = 1;
+  let Defs = [ R15 ];
 }
 
 // Format< OP[6] | RZ[5] | SOP[3] | OFFSET[18] >
 // Instructions(7): grs, lrs32.b, lrs32.h, lrs32.w, srs32.b, srs32.h, srs32.w
-class I_18_Z_L<bits<3> sop, string op, dag outs, dag ins, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x33, outs, ins,
-                 !strconcat(op, "\t$rz, $offset"), pattern> {
+class I_18_Z_L<bits<3> sop, string asm, dag outs, dag ins, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x33, outs, ins, asm, pattern> {
   bits<5> rz;
   bits<18> offset;
   let Inst{25 - 21} = rz;
@@ -102,7 +103,7 @@ class I_16_MOV<bits<5> sop, string op, ImmLeaf ImmType>
 // Instructions(1): lrw32
 class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>
   : CSKY32Inst<AddrModeNone, 0x3a, (outs GPR:$rz), ins,
-  !strconcat(op, "\t$rz, [$imm16]"), pattern> {
+  !strconcat(op, "\t$rz, $imm16"), pattern> {
   bits<5> rz;
   bits<16> imm16;
   let Inst{25 - 21} = sop;
@@ -112,9 +113,8 @@ class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>
 
 // Format< OP[6] | SOP[5] | 00000[5] | OFFSET[16] >
 // Instructions(5): bt32, bf32, br32, jmpi32, jsri32
-class I_16_L<bits<5> sop, dag outs, dag ins, string op, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x3a, outs, ins, !strconcat(op, "\t$imm16"),
-                 pattern> {
+class I_16_L<bits<5> sop, dag outs, dag ins, string asm, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x3a, outs, ins, asm, pattern> {
   bits<16> imm16;
   let Inst{25 - 21} = sop;
   let Inst{20 - 16} = 0;
@@ -159,6 +159,19 @@ class I_16_RET<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
   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;
+}
+
 // Format< OP[6] | SOP[5] | RX[5] | IMM16[16] >
 // Instructions(3): cmpnei32, cmphsi32, cmplti32
 class I_16_X<bits<5> sop, string op, Operand operand>

diff  --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index a3e5c9c81012..720ce86aa6d9 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -15,7 +15,9 @@
 // CSKY specific DAG Nodes.
 //===----------------------------------------------------------------------===//
 
-// TODO: Add CSKY specific DAG Nodes.
+// Target-dependent nodes.
+def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone,
+    [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
 
 //===----------------------------------------------------------------------===//
 // Operand and SDNode transformation definitions.
@@ -81,6 +83,41 @@ def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
   let ParserMatchClass = UImmAsmOperand<2>;
 }
 
+def CSKYSymbol : AsmOperandClass {
+  let Name = "CSKYSymbol";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = "InvalidCSKYSymbol";
+  let ParserMethod = "parseCSKYSymbol";
+}
+
+def br_symbol : Operand<iPTR> {
+  let EncoderMethod =
+    "getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm16_scale2>";
+  let ParserMatchClass = CSKYSymbol;
+}
+
+def call_symbol : Operand<iPTR> {
+  let ParserMatchClass = CSKYSymbol;
+  let EncoderMethod = "getCallSymbolOpValue";
+}
+
+def Constpool : AsmOperandClass {
+  let Name = "ConstpoolSymbol";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = "InvalidConstpool";
+  let ParserMethod = "parseConstpoolSymbol";
+}
+
+def constpool_symbol : Operand<iPTR> {
+  let ParserMatchClass = Constpool;
+  let EncoderMethod =
+    "getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm16_scale4>";
+}
+
+def bare_symbol : Operand<iPTR> {
+  let ParserMatchClass = CSKYSymbol;
+  let EncoderMethod = "getBareSymbolOpValue";
+}
 
 def oimm12 : oimm<12>;
 def oimm16 : oimm<16>;
@@ -229,3 +266,69 @@ def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>;
 
 def MVC32 : R_Z_1<0x1, 0x8, "mvc32">;
 def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">;
+
+//===----------------------------------------------------------------------===//
+// Branch and call instructions.
+//===----------------------------------------------------------------------===//
+
+let isBranch = 1, isTerminator = 1 in {
+  let isBarrier = 1, isPredicable = 1 in
+    def BR32 : I_16_L<0x0, (outs), (ins br_symbol:$imm16), "br32\t$imm16",
+                     [(br bb:$imm16)]>;
+
+  def BT32 : I_16_L<0x3, (outs), (ins CARRY:$ca, br_symbol:$imm16),
+    "bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>;
+  def BF32 : I_16_L<0x2, (outs), (ins CARRY:$ca, br_symbol:$imm16),
+    "bf32\t$imm16", []>;
+}
+
+
+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>;
+def BLSZ32 : I_16_X_L<0xB, "blsz32", br_symbol>;
+def BLZ32 : I_16_X_L<0xC, "blz32", br_symbol>;
+def BHSZ32 : I_16_X_L<0xD, "bhsz32", br_symbol>;
+
+let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
+  def JMP32 : I_16_JX<0x6, "jmp32", [(brind GPR:$rx)]>; // jmp to register
+  def JMPI32 : I_16_L<0x16, (outs), (ins constpool_symbol:$imm16),
+                   "jmpi32\t$imm16", []>;
+}
+
+let isCall = 1, Defs = [ R15 ] in
+  def JSR32 : I_16_JX<0x7, "jsr32", []>;
+
+let isCall = 1, Defs = [ R15 ] , mayLoad = 1 in
+  def JSRI32: I_16_L<0x17, (outs),
+    (ins constpool_symbol:$imm16), "jsri32\t$imm16", []>;
+
+
+def BSR32 : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>;
+
+def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
+  let isCodeGenOnly = 1;
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isBarrier = 1;
+  let isPredicable = 1;
+  let Defs = [ R15 ];
+}
+
+def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;
+
+
+def RTE32 : I_16_RET_I<0, 0, "rte32", []>;
+
+//===----------------------------------------------------------------------===//
+// Symbol address instructions.
+//===----------------------------------------------------------------------===//
+
+def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset",
+                    (outs GPR:$rz), (ins bare_symbol:$offset), []>;
+
+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), []>;
+}
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
index d084266dd0b2..df59a9955a71 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMCSKYDesc
   CSKYELFObjectWriter.cpp
   CSKYInstPrinter.cpp
   CSKYMCAsmInfo.cpp
+  CSKYMCExpr.cpp
   CSKYMCTargetDesc.cpp
   CSKYMCCodeEmitter.cpp
 

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
index e30123d64755..7fb5f35548b4 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
@@ -8,6 +8,7 @@
 
 #include "CSKYAsmBackend.h"
 #include "MCTargetDesc/CSKYMCTargetDesc.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
@@ -24,14 +25,113 @@ CSKYAsmBackend::createObjectTargetWriter() const {
   return createCSKYELFObjectWriter();
 }
 
-unsigned int CSKYAsmBackend::getNumFixupKinds() const { return 1; }
+const MCFixupKindInfo &
+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_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}},
+      {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}}};
+  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)
+    return Infos[Kind];
+  else if (Kind < FirstTargetFixupKind)
+    return MCAsmBackend::getFixupKindInfo(Kind);
+  else
+    return MCAsmBackend::getFixupKindInfo(FK_NONE);
+}
+
+static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+                                 MCContext &Ctx) {
+  switch (Fixup.getTargetKind()) {
+  default:
+    llvm_unreachable("Unknown fixup kind!");
+  case FK_Data_1:
+  case FK_Data_2:
+  case FK_Data_4:
+  case FK_Data_8:
+    return Value;
+  case CSKY::fixup_csky_addr32:
+    return Value & 0xffffffff;
+  case CSKY::fixup_csky_pcrel_imm16_scale2:
+    if (!isIntN(17, 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) & 0xffff;
+  case CSKY::fixup_csky_pcrel_uimm16_scale4:
+    if (!isUIntN(18, 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.");
+
+    return (Value >> 2) & 0xffff;
+  case CSKY::fixup_csky_pcrel_imm26_scale2:
+    if (!isIntN(27, 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) & 0x3ffffff;
+  case CSKY::fixup_csky_pcrel_imm18_scale2:
+    if (!isIntN(19, 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) & 0x3ffff;
+  }
+}
 
 void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                                 const MCValue &Target,
                                 MutableArrayRef<char> Data, uint64_t Value,
                                 bool IsResolved,
                                 const MCSubtargetInfo *STI) const {
-  return;
+  MCFixupKind Kind = Fixup.getKind();
+  if (Kind >= FirstLiteralRelocationKind)
+    return;
+  MCContext &Ctx = Asm.getContext();
+  MCFixupKindInfo Info = getFixupKindInfo(Kind);
+  if (!Value)
+    return; // Doesn't change encoding.
+  // Apply any target-specific value adjustments.
+  Value = adjustFixupValue(Fixup, Value, Ctx);
+
+  // Shift the value into position.
+  Value <<= Info.TargetOffset;
+
+  unsigned Offset = Fixup.getOffset();
+  unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
+
+  assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+
+  // For each byte of the fragment that the fixup touches, mask in the
+  // bits from the fixup value.
+  bool IsLittleEndian = (Endian == support::little);
+
+  if (IsLittleEndian && (NumBytes == 4)) {
+    Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
+    Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
+    Data[Offset + 2] |= uint8_t(Value & 0xff);
+    Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
+  } else {
+    for (unsigned I = 0; I != NumBytes; I++) {
+      unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
+      Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
+    }
+  }
 }
 
 bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
index b4cba4264e03..cdf688e9032a 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYASMBACKEND_H
 #define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYASMBACKEND_H
 
+#include "MCTargetDesc/CSKYFixupKinds.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCTargetOptions.h"
 
@@ -20,17 +21,26 @@ class CSKYAsmBackend : public MCAsmBackend {
   CSKYAsmBackend(const MCSubtargetInfo &STI, const MCTargetOptions &OP)
       : MCAsmBackend(support::little) {}
 
-  unsigned int getNumFixupKinds() const override;
+  unsigned int getNumFixupKinds() const override {
+    return CSKY::NumTargetFixupKinds;
+  }
+
   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                   const MCValue &Target, MutableArrayRef<char> Data,
                   uint64_t Value, bool IsResolved,
                   const MCSubtargetInfo *STI) const override;
+
+  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
+
   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                             const MCRelaxableFragment *DF,
                             const MCAsmLayout &Layout) const override;
+
   void relaxInstruction(MCInst &Inst,
                         const MCSubtargetInfo &STI) const override;
+
   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
+
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override;
 };

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
new file mode 100644
index 000000000000..917f940fcad4
--- /dev/null
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
@@ -0,0 +1,34 @@
+//===-- CSKYFixupKinds.h - CSKY Specific Fixup Entries ----------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
+#define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+namespace llvm {
+namespace CSKY {
+enum Fixups {
+  fixup_csky_addr32 = FirstTargetFixupKind,
+
+  fixup_csky_pcrel_imm16_scale2,
+
+  fixup_csky_pcrel_uimm16_scale4,
+
+  fixup_csky_pcrel_imm26_scale2,
+
+  fixup_csky_pcrel_imm18_scale2,
+
+  // Marker
+  fixup_csky_invalid,
+  NumTargetFixupKinds = fixup_csky_invalid - FirstTargetFixupKind
+};
+} // end namespace CSKY
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
index ed2b0e77b81a..1a5b0225e0b9 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp
@@ -62,6 +62,17 @@ CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   return 0;
 }
 
+MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
+  const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
+
+  switch (CSKYExpr->getKind()) {
+  default:
+    llvm_unreachable("Unhandled fixup kind!");
+  case CSKYMCExpr::VK_CSKY_ADDR:
+    return MCFixupKind(CSKY::fixup_csky_addr32);
+  }
+}
+
 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
                                              const MCRegisterInfo &MRI,
                                              MCContext &Ctx) {

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
index 99a6763e521e..a4c50d992a07 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
@@ -13,6 +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 "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
 
@@ -62,6 +64,70 @@ class CSKYMCCodeEmitter : public MCCodeEmitter {
     assert(MO.isImm() && "Unexpected MO type.");
     return 1 << MO.getImm();
   }
+
+  MCFixupKind getTargetFixup(const MCExpr *Expr) const;
+
+  template <llvm::CSKY::Fixups FIXUP>
+  unsigned getBranchSymbolOpValue(const MCInst &MI, unsigned Idx,
+                                  SmallVectorImpl<MCFixup> &Fixups,
+                                  const MCSubtargetInfo &STI) const {
+    const MCOperand &MO = MI.getOperand(Idx);
+
+    if (MO.isImm())
+      return MO.getImm() >> 1;
+
+    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;
+  }
+
+  template <llvm::CSKY::Fixups FIXUP>
+  unsigned getConstpoolSymbolOpValue(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 {
+    const MCOperand &MO = MI.getOperand(Idx);
+    assert(MO.isExpr() && "Unexpected MO type.");
+
+    MCFixupKind Kind = MCFixupKind(CSKY::fixup_csky_pcrel_imm26_scale2);
+    if (MO.getExpr()->getKind() == MCExpr::Target)
+      Kind = getTargetFixup(MO.getExpr());
+
+    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
+    return 0;
+  }
+
+  unsigned getBareSymbolOpValue(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(CSKY::fixup_csky_pcrel_imm18_scale2);
+    if (MO.getExpr()->getKind() == MCExpr::Target)
+      Kind = getTargetFixup(MO.getExpr());
+
+    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
+    return 0;
+  }
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
new file mode 100644
index 000000000000..59e630f43a42
--- /dev/null
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
@@ -0,0 +1,122 @@
+//===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYMCExpr.h"
+#include "CSKYFixupKinds.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolELF.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "csky-mc-expr"
+
+const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
+                                     MCContext &Ctx) {
+  return new (Ctx) CSKYMCExpr(Kind, Expr);
+}
+
+StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Invalid ELF symbol kind");
+  case VK_CSKY_ADDR:
+    return "";
+  case VK_CSKY_PCREL:
+    return "";
+  case VK_CSKY_GOT:
+    return "@GOT";
+  case VK_CSKY_GOTPC:
+    return "@GOTPC";
+  case VK_CSKY_GOTOFF:
+    return "@GOTOFF";
+  case VK_CSKY_PLT:
+    return "@PLT";
+  case VK_CSKY_TPOFF:
+    return "@TPOFF";
+  case VK_CSKY_TLSGD:
+    return "@TLSGD";
+  }
+}
+
+void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
+  Streamer.visitUsedExpr(*getSubExpr());
+}
+
+void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+  Expr->print(OS, MAI);
+  OS << getVariantKindName(getKind());
+}
+
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+  switch (Expr->getKind()) {
+  case MCExpr::Target:
+    llvm_unreachable("Can't handle nested target expression");
+    break;
+  case MCExpr::Constant:
+    break;
+
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+    fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+    fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+    break;
+  }
+
+  case MCExpr::SymbolRef: {
+    // We're known to be under a TLS fixup, so any symbol should be
+    // modified. There should be only one.
+    const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+    cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
+    break;
+  }
+
+  case MCExpr::Unary:
+    fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+    break;
+  }
+}
+
+void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+  switch (getKind()) {
+  default:
+    return;
+  case VK_CSKY_TPOFF:
+  case VK_CSKY_TLSGD:
+    break;
+  }
+
+  fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
+}
+
+bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
+                                           const MCAsmLayout *Layout,
+                                           const MCFixup *Fixup) const {
+  if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
+    return false;
+
+  // Some custom fixup types are not valid with symbol 
diff erence expressions
+  if (Res.getSymA() && Res.getSymB()) {
+    switch (getKind()) {
+    default:
+      return true;
+
+    case VK_CSKY_ADDR:
+    case VK_CSKY_PCREL:
+    case VK_CSKY_GOT:
+    case VK_CSKY_GOTPC:
+    case VK_CSKY_GOTOFF:
+    case VK_CSKY_TPOFF:
+    case VK_CSKY_TLSGD:
+      return false;
+    }
+  }
+
+  return true;
+}
\ No newline at end of file

diff  --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
new file mode 100644
index 000000000000..06fccada53ce
--- /dev/null
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
@@ -0,0 +1,69 @@
+//===-- CSKYMCExpr.h - CSKY specific MC expression classes -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCEXPR_H
+#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCEXPR_H
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCValue.h"
+
+namespace llvm {
+
+class CSKYMCExpr : public MCTargetExpr {
+public:
+  enum VariantKind {
+    VK_CSKY_None,
+    VK_CSKY_ADDR,
+    VK_CSKY_PCREL,
+    VK_CSKY_GOT,
+    VK_CSKY_GOTPC,
+    VK_CSKY_GOTOFF,
+    VK_CSKY_PLT,
+    VK_CSKY_TPOFF,
+    VK_CSKY_TLSGD,
+    VK_CSKY_Invalid
+  };
+
+private:
+  const VariantKind Kind;
+  const MCExpr *Expr;
+
+  explicit CSKYMCExpr(VariantKind Kind, const MCExpr *Expr)
+      : Kind(Kind), Expr(Expr) {}
+
+public:
+  static const CSKYMCExpr *create(const MCExpr *Expr, VariantKind Kind,
+                                  MCContext &Ctx);
+
+  // Returns the kind of this expression.
+  VariantKind getKind() const { return Kind; }
+
+  // Returns the child of this expression.
+  const MCExpr *getSubExpr() const { return Expr; }
+
+  void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
+
+  bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
+                                 const MCFixup *Fixup) const override;
+  void visitUsedExpr(MCStreamer &Streamer) const override;
+
+  MCFragment *findAssociatedFragment() const override {
+    return getSubExpr()->findAssociatedFragment();
+  }
+
+  void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
+
+  static bool classof(const MCExpr *E) {
+    return E->getKind() == MCExpr::Target;
+  }
+
+  static StringRef getVariantKindName(VariantKind Kind);
+};
+} // end namespace llvm
+
+#endif

diff  --git a/llvm/test/MC/CSKY/basic.s b/llvm/test/MC/CSKY/basic.s
index 71920e7324e1..23fddd8e544b 100644
--- a/llvm/test/MC/CSKY/basic.s
+++ b/llvm/test/MC/CSKY/basic.s
@@ -240,6 +240,102 @@ zext32 a3, l0, 7, 0
 # CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58]
 sext32 a3, l0, 7, 0
 
+# 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
+.L.test:
+br32 .L.test
+
+# CHECK-ASM: bt32 .L.test2
+# CHECK-ASM: encoding: [0x60'A',0xe8'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test2, kind: fixup_csky_pcrel_imm16_scale2
+.L.test2:
+bt32 .L.test2
+
+# CHECK-ASM: bf32 .L.test3
+# CHECK-ASM: encoding: [0x40'A',0xe8'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test3, kind: fixup_csky_pcrel_imm16_scale2
+.L.test3:
+bf32 .L.test3
+
+# CHECK-ASM: bez32 a0, .L.test4
+# CHECK-ASM: encoding: [A,0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test4, kind: fixup_csky_pcrel_imm16_scale2
+.L.test4:
+bez32 a0, .L.test4
+
+# CHECK-ASM: bnez32 a0, .L.test5
+# CHECK-ASM: encoding: [0x20'A',0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test5, kind: fixup_csky_pcrel_imm16_scale2
+.L.test5:
+bnez32 a0, .L.test5
+
+# CHECK-ASM: bhz32 a0, .L.test6
+# CHECK-ASM: encoding: [0x40'A',0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test6, kind: fixup_csky_pcrel_imm16_scale2
+.L.test6:
+bhz32 a0, .L.test6
+
+# CHECK-ASM: blsz32 a0, .L.test7
+# CHECK-ASM: encoding: [0x60'A',0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test7, kind: fixup_csky_pcrel_imm16_scale2
+.L.test7:
+blsz32 a0, .L.test7
+
+# CHECK-ASM: blz32 a0, .L.test8
+# CHECK-ASM: encoding: [0x80'A',0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test8, kind: fixup_csky_pcrel_imm16_scale2
+.L.test8:
+blz32 a0, .L.test8
+
+# CHECK-ASM: bhsz32 a0, .L.test9
+# CHECK-ASM: encoding: [0xa0'A',0xe9'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test9, kind: fixup_csky_pcrel_imm16_scale2
+.L.test9:
+bhsz32 a0, .L.test9
+
+# CHECK-ASM: jmp32 a3
+# CHECK-ASM: encoding: [0xc3,0xe8,0x00,0x00]
+jmp32 a3
+
+# 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:
+jmpi32 [.L.test10]
+
+# CHECK-ASM: bsr32 .L.test11
+# CHECK-ASM: encoding: [A,0xe0'A',A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test11, kind: fixup_csky_pcrel_imm26_scale2
+.L.test11:
+bsr32 .L.test11
+
+# CHECK-ASM: jsr32 a3
+# CHECK-ASM: encoding: [0xe3,0xe8,0x00,0x00]
+jsr32 a3
+
+# 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: 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
 
 .ifdef ERR
@@ -308,4 +404,9 @@ 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
+
 .endif

diff  --git a/llvm/test/MC/CSKY/csky-error.s b/llvm/test/MC/CSKY/csky-error.s
new file mode 100644
index 000000000000..6580692133f5
--- /dev/null
+++ b/llvm/test/MC/CSKY/csky-error.s
@@ -0,0 +1,80 @@
+# RUN: not llvm-mc -triple=csky %s -filetype=obj -o %t.o 2>&1 | FileCheck %s
+
+# Out of PC range
+
+# br/bt/bf
+
+.L.test1:
+.space 0x10001
+br32 .L.test1 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+              # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+
+br32 .L.test2 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+              # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+.space 0x10001
+.L.test2:
+
+.L.test3:
+.space 0xFFFF
+br32 .L.test3 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
+
+.L.test4:
+.space 0x10002
+br32 .L.test4 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+
+# bsr
+.L.test5:
+.space 0x4000001
+bsr32 .L.test5 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+               # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+
+bsr32 .L.test6 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+               # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+.space 0x4000001
+.L.test6:
+
+.L.test7:
+.space 0x3FFFFFF
+bsr32 .L.test7 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
+
+.L.test8:
+.space 0x4000002
+bsr32 .L.test8 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+
+# grs
+.L.test9:
+.space 0x40001
+grs32 a0, .L.test9 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+                   # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+
+grs32 a0, .L.test10 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+                    # CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
+.space 0x40001
+.L.test10:
+
+.L.test11:
+.space 0x3FFFF
+grs32 a0, .L.test11 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
+
+.L.test12:
+.space 0x40002
+grs32 a0, .L.test12 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+
+
+# TODO: Fixup
+lrw32 a0, [.L.test15] # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+                    # CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
+.space 0x40001
+.L.test15:
+
+# TODO: Fixup
+jsri32 [.L.test16]     # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+                     # CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
+.space 0x40001
+.L.test16:
+
+# TODO: Fixup
+jmpi32 [.L.test17]     # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
+                     # CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
+.space 0x40001
+.L.test17:


        


More information about the llvm-commits mailing list