[llvm] 3347f77 - [LoongArch] Add basic support to AsmParser

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 9 00:26:26 PST 2022


Author: Weining Lu
Date: 2022-03-09T16:20:36+08:00
New Revision: 3347f77b80758a04a942dd672d35d9fc15b8f41e

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

LOG: [LoongArch] Add basic support to AsmParser

This patch adds basic support to AsmParser which can handle basic
instructions with register or immediate operands. With the addition of
the parser, now it's possible to test instructions encoding with `llvm-mc`.

Disassembler will be added later and then we can do `round-trip` test.

Reviewed By: xen0n, MaskRay, myhsu

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

Added: 
    llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/test/MC/LoongArch/Basic/Integer/arith.s
    llvm/test/MC/LoongArch/Basic/Integer/atomic.s
    llvm/test/MC/LoongArch/Basic/Integer/barrier.s
    llvm/test/MC/LoongArch/Basic/Integer/bit-manipu.s
    llvm/test/MC/LoongArch/Basic/Integer/bit-shift.s
    llvm/test/MC/LoongArch/Basic/Integer/bound-check.s
    llvm/test/MC/LoongArch/Basic/Integer/branch.s
    llvm/test/MC/LoongArch/Basic/Integer/crc.s
    llvm/test/MC/LoongArch/Basic/Integer/invalid.s
    llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
    llvm/test/MC/LoongArch/Basic/Integer/memory.s
    llvm/test/MC/LoongArch/Basic/Integer/misc.s
    llvm/test/MC/LoongArch/Basic/Integer/pseudos.s
    llvm/test/MC/LoongArch/Directives/cfi.s
    llvm/test/MC/LoongArch/Directives/data.s
    llvm/test/MC/LoongArch/lit.local.cfg

Modified: 
    llvm/lib/Target/LoongArch/CMakeLists.txt
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt b/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt
new file mode 100644
index 0000000000000..29616053118f2
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_llvm_component_library(LLVMLoongArchAsmParser
+  LoongArchAsmParser.cpp
+
+  LINK_COMPONENTS
+  LoongArchDesc
+  LoongArchInfo
+  MC
+  MCParser
+  Support
+
+  ADD_TO_COMPONENT
+  LoongArch
+  )

diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
new file mode 100644
index 0000000000000..5f9eae2ff589e
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -0,0 +1,477 @@
+// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/LoongArchInstPrinter.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "TargetInfo/LoongArchTargetInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Casting.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-asm-parser"
+
+namespace {
+struct LoongArchOperand;
+
+class LoongArchAsmParser : public MCTargetAsmParser {
+  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+
+  /// Parse a register as used in CFI directives.
+  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
+
+  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+                        SMLoc NameLoc, OperandVector &Operands) override;
+
+  bool ParseDirective(AsmToken DirectiveID) override { return true; }
+
+  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+                               OperandVector &Operands, MCStreamer &Out,
+                               uint64_t &ErrorInfo,
+                               bool MatchingInlineAsm) override;
+
+  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
+                                  int64_t Lower, int64_t Upper, Twine Msg);
+
+  /// Helper for processing MC instructions that have been successfully matched
+  /// by MatchAndEmitInstruction.
+  bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
+                          MCStreamer &Out);
+
+// Auto-generated instruction matching functions.
+#define GET_ASSEMBLER_HEADER
+#include "LoongArchGenAsmMatcher.inc"
+
+  OperandMatchResultTy parseRegister(OperandVector &Operands);
+  OperandMatchResultTy parseImmediate(OperandVector &Operands);
+
+  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
+
+public:
+  enum LoongArchMatchResultTy {
+    Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
+#define GET_OPERAND_DIAGNOSTIC_TYPES
+#include "LoongArchGenAsmMatcher.inc"
+#undef GET_OPERAND_DIAGNOSTIC_TYPES
+  };
+
+  LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
+                     const MCInstrInfo &MII, const MCTargetOptions &Options)
+      : MCTargetAsmParser(Options, STI, MII) {
+    Parser.addAliasForDirective(".half", ".2byte");
+    Parser.addAliasForDirective(".hword", ".2byte");
+    Parser.addAliasForDirective(".word", ".4byte");
+    Parser.addAliasForDirective(".dword", ".8byte");
+
+    // Initialize the set of available features.
+    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+  }
+};
+
+/// LoongArchOperand - Instances of this class represent a parsed LoongArch
+/// machine instruction.
+class LoongArchOperand : public MCParsedAsmOperand {
+  enum class KindTy {
+    Token,
+    Register,
+    Immediate,
+  } Kind;
+
+  struct RegOp {
+    MCRegister RegNum;
+  };
+
+  struct ImmOp {
+    const MCExpr *Val;
+  };
+
+  SMLoc StartLoc, EndLoc;
+  union {
+    StringRef Tok;
+    struct RegOp Reg;
+    struct ImmOp Imm;
+  };
+
+public:
+  LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+
+  bool isToken() const override { return Kind == KindTy::Token; }
+  bool isReg() const override { return Kind == KindTy::Register; }
+  bool isImm() const override { return Kind == KindTy::Immediate; }
+  bool isMem() const override { return false; }
+
+  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
+    if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
+      Imm = CE->getValue();
+      return true;
+    }
+
+    return false;
+  }
+
+  template <unsigned N, int P = 0> bool isUImm() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    return IsConstantImm && isUInt<N>(Imm - P);
+  }
+
+  template <unsigned N, unsigned S = 0> bool isSImm() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    return IsConstantImm && isShiftedInt<N, S>(Imm);
+  }
+
+  bool isUImm2() const { return isUImm<2>(); }
+  bool isUImm2plus1() const { return isUImm<2, 1>(); }
+  bool isUImm3() const { return isUImm<3>(); }
+  bool isUImm5() const { return isUImm<5>(); }
+  bool isUImm6() const { return isUImm<6>(); }
+  bool isUImm12() const { return isUImm<12>(); }
+  bool isUImm15() const { return isUImm<15>(); }
+  bool isSImm12() const { return isSImm<12>(); }
+  bool isSImm14lsl2() const { return isSImm<14, 2>(); }
+  bool isSImm16() const { return isSImm<16>(); }
+  bool isSImm16lsl2() const { return isSImm<16, 2>(); }
+  bool isSImm20() const { return isSImm<20>(); }
+  bool isSImm21lsl2() const { return isSImm<21, 2>(); }
+  bool isSImm26lsl2() const { return isSImm<26, 2>(); }
+
+  /// Gets location of the first token of this operand.
+  SMLoc getStartLoc() const override { return StartLoc; }
+  /// Gets location of the last token of this operand.
+  SMLoc getEndLoc() const override { return EndLoc; }
+
+  unsigned getReg() const override {
+    assert(Kind == KindTy::Register && "Invalid type access!");
+    return Reg.RegNum.id();
+  }
+
+  const MCExpr *getImm() const {
+    assert(Kind == KindTy::Immediate && "Invalid type access!");
+    return Imm.Val;
+  }
+
+  StringRef getToken() const {
+    assert(Kind == KindTy::Token && "Invalid type access!");
+    return Tok;
+  }
+
+  void print(raw_ostream &OS) const override {
+    auto RegName = [](unsigned Reg) {
+      if (Reg)
+        return LoongArchInstPrinter::getRegisterName(Reg);
+      else
+        return "noreg";
+    };
+
+    switch (Kind) {
+    case KindTy::Immediate:
+      OS << *getImm();
+      break;
+    case KindTy::Register:
+      OS << "<register " << RegName(getReg()) << ">";
+      break;
+    case KindTy::Token:
+      OS << "'" << getToken() << "'";
+      break;
+    }
+  }
+
+  static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
+    auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
+    Op->Tok = Str;
+    Op->StartLoc = S;
+    Op->EndLoc = S;
+    return Op;
+  }
+
+  static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S,
+                                                     SMLoc E) {
+    auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
+    Op->Reg.RegNum = RegNo;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
+  static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
+                                                     SMLoc E) {
+    auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
+    Op->Imm.Val = Val;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
+  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
+    if (auto CE = dyn_cast<MCConstantExpr>(Expr))
+      Inst.addOperand(MCOperand::createImm(CE->getValue()));
+    else
+      Inst.addOperand(MCOperand::createExpr(Expr));
+  }
+
+  // Used by the TableGen Code.
+  void addRegOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+  void addImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    addExpr(Inst, getImm());
+  }
+};
+} // end anonymous namespace
+
+#define GET_REGISTER_MATCHER
+#define GET_SUBTARGET_FEATURE_NAME
+#define GET_MATCHER_IMPLEMENTATION
+#define GET_MNEMONIC_SPELL_CHECKER
+#include "LoongArchGenAsmMatcher.inc"
+
+static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
+  RegNo = MatchRegisterName(Name);
+
+  if (RegNo == LoongArch::NoRegister)
+    RegNo = MatchRegisterAltName(Name);
+
+  return RegNo == LoongArch::NoRegister;
+}
+
+bool LoongArchAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                       SMLoc &EndLoc) {
+  return Error(getParser().getTok().getLoc(), "invalid register number");
+}
+
+OperandMatchResultTy LoongArchAsmParser::tryParseRegister(unsigned &RegNo,
+                                                          SMLoc &StartLoc,
+                                                          SMLoc &EndLoc) {
+  llvm_unreachable("Unimplemented function.");
+}
+
+OperandMatchResultTy
+LoongArchAsmParser::parseRegister(OperandVector &Operands) {
+  if (getLexer().getTok().isNot(AsmToken::Dollar))
+    return MatchOperand_NoMatch;
+
+  // Eat the $ prefix.
+  getLexer().Lex();
+  if (getLexer().getKind() != AsmToken::Identifier)
+    return MatchOperand_NoMatch;
+
+  StringRef Name = getLexer().getTok().getIdentifier();
+  MCRegister RegNo;
+  matchRegisterNameHelper(RegNo, Name);
+  if (RegNo == LoongArch::NoRegister)
+    return MatchOperand_NoMatch;
+
+  SMLoc S = getLoc();
+  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
+  getLexer().Lex();
+  Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
+
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
+  SMLoc S = getLoc();
+  SMLoc E;
+  const MCExpr *Res;
+
+  if (getParser().parseExpression(Res, E))
+    return MatchOperand_ParseFail;
+
+  Operands.push_back(LoongArchOperand::createImm(Res, S, E));
+  return MatchOperand_Success;
+}
+
+/// Looks at a token type and creates the relevant operand from this
+/// information, adding to Operands. Return true upon an error.
+bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
+                                      StringRef Mnemonic) {
+  if (parseRegister(Operands) == MatchOperand_Success ||
+      parseImmediate(Operands) == MatchOperand_Success)
+    return false;
+
+  // Finally we have exhausted all options and must declare defeat.
+  Error(getLoc(), "unknown operand");
+  return true;
+}
+
+bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,
+                                          StringRef Name, SMLoc NameLoc,
+                                          OperandVector &Operands) {
+  // First operand in MCInst is instruction mnemonic.
+  Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
+
+  // If there are no more operands, then finish.
+  if (parseOptionalToken(AsmToken::EndOfStatement))
+    return false;
+
+  // Parse first operand.
+  if (parseOperand(Operands, Name))
+    return true;
+
+  // Parse until end of statement, consuming commas between operands.
+  while (parseOptionalToken(AsmToken::Comma))
+    if (parseOperand(Operands, Name))
+      return true;
+
+  // Parse end of statement and return successfully.
+  if (parseOptionalToken(AsmToken::EndOfStatement))
+    return false;
+
+  SMLoc Loc = getLexer().getLoc();
+  getParser().eatToEndOfStatement();
+  return Error(Loc, "unexpected token");
+}
+
+bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
+                                            OperandVector &Operands,
+                                            MCStreamer &Out) {
+  Inst.setLoc(IDLoc);
+  Out.emitInstruction(Inst, getSTI());
+  return false;
+}
+
+bool LoongArchAsmParser::generateImmOutOfRangeError(
+    OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
+    Twine Msg = "immediate must be an integer in the range") {
+  SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
+  return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
+}
+
+bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+                                                 OperandVector &Operands,
+                                                 MCStreamer &Out,
+                                                 uint64_t &ErrorInfo,
+                                                 bool MatchingInlineAsm) {
+  MCInst Inst;
+  FeatureBitset MissingFeatures;
+
+  auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
+                                     MatchingInlineAsm);
+  switch (Result) {
+  default:
+    break;
+  case Match_Success:
+    return processInstruction(Inst, IDLoc, Operands, Out);
+  case Match_MissingFeature: {
+    assert(MissingFeatures.any() && "Unknown missing features!");
+    bool FirstFeature = true;
+    std::string Msg = "instruction requires the following:";
+    for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
+      if (MissingFeatures[i]) {
+        Msg += FirstFeature ? " " : ", ";
+        Msg += getSubtargetFeatureName(i);
+        FirstFeature = false;
+      }
+    }
+    return Error(IDLoc, Msg);
+  }
+  case Match_MnemonicFail: {
+    FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
+    std::string Suggestion = LoongArchMnemonicSpellCheck(
+        ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
+    return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
+  }
+  case Match_InvalidOperand: {
+    SMLoc ErrorLoc = IDLoc;
+    if (ErrorInfo != ~0ULL) {
+      if (ErrorInfo >= Operands.size())
+        return Error(ErrorLoc, "too few operands for instruction");
+
+      ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
+      if (ErrorLoc == SMLoc())
+        ErrorLoc = IDLoc;
+    }
+    return Error(ErrorLoc, "invalid operand for instruction");
+  }
+  }
+
+  // Handle the case when the error message is of specific type
+  // other than the generic Match_InvalidOperand, and the
+  // corresponding operand is missing.
+  if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
+    SMLoc ErrorLoc = IDLoc;
+    if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
+      return Error(ErrorLoc, "too few operands for instruction");
+  }
+
+  switch (Result) {
+  default:
+    break;
+  case Match_InvalidUImm2:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 2) - 1);
+  case Match_InvalidUImm2plus1:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
+                                      /*Upper=*/(1 << 2));
+  case Match_InvalidUImm3:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 3) - 1);
+  case Match_InvalidUImm5:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 5) - 1);
+  case Match_InvalidUImm6:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 6) - 1);
+  case Match_InvalidUImm12:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 12) - 1);
+  case Match_InvalidUImm15:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
+                                      /*Upper=*/(1 << 15) - 1);
+  case Match_InvalidSImm12:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
+                                      (1 << 11) - 1);
+  case Match_InvalidSImm14lsl2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
+        "immediate must be a multiple of 4 in the range");
+  case Match_InvalidSImm16:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 15),
+                                      (1 << 15) - 1);
+  case Match_InvalidSImm16lsl2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
+        "immediate must be a multiple of 4 in the range");
+  case Match_InvalidSImm20:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 19),
+                                      (1 << 19) - 1);
+  case Match_InvalidSImm21lsl2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
+        "immediate must be a multiple of 4 in the range");
+  case Match_InvalidSImm26lsl2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
+        "immediate must be a multiple of 4 in the range");
+  }
+  llvm_unreachable("Unknown match type detected!");
+}
+
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
+  RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
+  RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
+}

diff  --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt
index ecd6af701316a..4eebfb713b61c 100644
--- a/llvm/lib/Target/LoongArch/CMakeLists.txt
+++ b/llvm/lib/Target/LoongArch/CMakeLists.txt
@@ -4,11 +4,11 @@ set(LLVM_TARGET_DEFINITIONS LoongArch.td)
 
 tablegen(LLVM LoongArchGenAsmMatcher.inc -gen-asm-matcher)
 tablegen(LLVM LoongArchGenAsmWriter.inc -gen-asm-writer)
-tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info)
-tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM LoongArchGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering)
 tablegen(LLVM LoongArchGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info)
 tablegen(LLVM LoongArchGenSubtargetInfo.inc -gen-subtarget)
 
 add_public_tablegen_target(LoongArchCommonTableGen)
@@ -41,5 +41,6 @@ add_llvm_target(LoongArchCodeGen
   LoongArch
   )
 
+add_subdirectory(AsmParser)
 add_subdirectory(MCTargetDesc)
 add_subdirectory(TargetInfo)

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 4b452b28314c2..48a68b5bd3a70 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -22,6 +22,7 @@
 class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
   let Name = prefix # "Imm" # width # suffix;
   let DiagnosticType = !strconcat("Invalid", Name);
+  let RenderMethod = "addImmOperands";
 }
 
 class SImmAsmOperand<int width, string suffix = "">
@@ -32,29 +33,64 @@ class UImmAsmOperand<int width, string suffix = "">
     : ImmAsmOperand<"U", width, suffix> {
 }
 
-def uimm2 : Operand<GRLenVT>;
+def uimm2 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<2>;
+}
+
 def uimm2_plus1 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<2, "plus1">;
   let EncoderMethod = "getImmOpValueSub1";
 }
-def uimm3 : Operand<GRLenVT>;
-def uimm5 : Operand<GRLenVT>;
-def uimm6 : Operand<GRLenVT>;
-def uimm12 : Operand<GRLenVT>;
-def uimm15 : Operand<GRLenVT>;
-def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]>;
-def simm14 : Operand<GRLenVT>;
+
+def uimm3 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<3>;
+}
+
+def uimm5 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<5>;
+}
+
+def uimm6 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<6>;
+}
+
+def uimm12 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<12>;
+}
+
+def uimm15 : Operand<GRLenVT> {
+  let ParserMatchClass = UImmAsmOperand<15>;
+}
+
+def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]> {
+  let ParserMatchClass = SImmAsmOperand<12>;
+}
+
 def simm14_lsl2 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
   let EncoderMethod = "getImmOpValueAsr2";
 }
-def simm16 : Operand<GRLenVT>;
+
+def simm16 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<16>;
+}
+
 def simm16_lsl2 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
   let EncoderMethod = "getImmOpValueAsr2";
 }
-def simm20 : Operand<GRLenVT>;
+
+def simm20 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<20>;
+}
+
 def simm21_lsl2 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
   let EncoderMethod = "getImmOpValueAsr2";
 }
+
 def simm26_lsl2 : Operand<GRLenVT> {
+  let ParserMatchClass = SImmAsmOperand<26, "lsl2">;
   let EncoderMethod = "getImmOpValueAsr2";
 }
 

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
index 01993f93e7507..bc946db2f4495 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
@@ -29,5 +29,6 @@ LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) {
   ZeroDirective = "\t.space\t";
   CommentString = "#";
   SupportsDebugInformation = true;
+  DwarfRegNumForCFI = true;
   ExceptionsType = ExceptionHandling::DwarfCFI;
 }

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
index 6b78b31c9b33c..aa576abff9757 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
@@ -17,6 +17,7 @@
 #include "TargetInfo/LoongArchTargetInfo.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -73,6 +74,31 @@ static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T,
   return new LoongArchInstPrinter(MAI, MII, MRI);
 }
 
+namespace {
+
+class LoongArchMCInstrAnalysis : public MCInstrAnalysis {
+public:
+  explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info)
+      : MCInstrAnalysis(Info) {}
+
+  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
+                      uint64_t &Target) const override {
+    unsigned NumOps = Inst.getNumOperands();
+    if (isBranch(Inst) || Inst.getOpcode() == LoongArch::BL) {
+      Target = Addr + Inst.getOperand(NumOps - 1).getImm();
+      return true;
+    }
+
+    return false;
+  }
+};
+
+} // end anonymous namespace
+
+static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) {
+  return new LoongArchMCInstrAnalysis(Info);
+}
+
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() {
   for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) {
     TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo);
@@ -82,5 +108,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() {
     TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter);
     TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend);
     TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter);
+    TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis);
   }
 }

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/arith.s b/llvm/test/MC/LoongArch/Basic/Integer/arith.s
new file mode 100644
index 0000000000000..104b01fba19a0
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/arith.s
@@ -0,0 +1,208 @@
+## Test valid arithmetic operation instructions
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: add.w $a5, $ra, $s8
+# CHECK-ASM: encoding: [0x29,0x7c,0x10,0x00]
+add.w $a5, $ra, $s8
+
+# CHECK-ASM: sub.w $r21, $s2, $t7
+# CHECK-ASM: encoding: [0x35,0x4f,0x11,0x00]
+sub.w $r21, $s2, $t7
+
+# CHECK-ASM: addi.w $a1, $a3, 246
+# CHECK-ASM: encoding: [0xe5,0xd8,0x83,0x02]
+addi.w $a1, $a3, 246
+
+# CHECK-ASM: alsl.w $tp, $t5, $tp, 4
+# CHECK-ASM: encoding: [0x22,0x8a,0x05,0x00]
+alsl.w $tp, $t5, $tp, 4
+
+# CHECK-ASM: lu12i.w $t4, 49
+# CHECK-ASM: encoding: [0x30,0x06,0x00,0x14]
+lu12i.w $t4, 49
+
+# CHECK-ASM: lu12i.w $a0, -1
+# CHECK-ASM: encoding: [0xe4,0xff,0xff,0x15]
+lu12i.w $a0, -1
+
+# CHECK-ASM: slt $s6, $s3, $tp
+# CHECK-ASM: encoding: [0x5d,0x0b,0x12,0x00]
+slt $s6, $s3, $tp
+
+# CHECK-ASM: sltu $a7, $r21, $s6
+# CHECK-ASM: encoding: [0xab,0xf6,0x12,0x00]
+sltu $a7, $r21, $s6
+
+# CHECK-ASM: slti $s4, $ra, 235
+# CHECK-ASM: encoding: [0x3b,0xac,0x03,0x02]
+slti $s4, $ra, 235
+
+# CHECK-ASM: sltui $zero, $a4, 162
+# CHECK-ASM: encoding: [0x00,0x89,0x42,0x02]
+sltui $zero, $a4, 162
+
+# CHECK-ASM: pcaddi $a5, 187
+# CHECK-ASM: encoding: [0x69,0x17,0x00,0x18]
+pcaddi $a5, 187
+
+# CHECK-ASM: pcaddu12i $zero, 37
+# CHECK-ASM: encoding: [0xa0,0x04,0x00,0x1c]
+pcaddu12i $zero, 37
+
+# CHECK-ASM: pcalau12i $a6, 89
+# CHECK-ASM: encoding: [0x2a,0x0b,0x00,0x1a]
+pcalau12i $a6, 89
+
+# CHECK-ASM: and $t7, $s8, $ra
+# CHECK-ASM: encoding: [0xf3,0x87,0x14,0x00]
+and $t7, $s8, $ra
+
+# CHECK-ASM: or $t5, $t4, $s7
+# CHECK-ASM: encoding: [0x11,0x7a,0x15,0x00]
+or $t5, $t4, $s7
+
+# CHECK-ASM: nor $a1, $t6, $a1
+# CHECK-ASM: encoding: [0x45,0x16,0x14,0x00]
+nor $a1, $t6, $a1
+
+# CHECK-ASM: xor $t3, $t7, $a4
+# CHECK-ASM: encoding: [0x6f,0xa2,0x15,0x00]
+xor $t3, $t7, $a4
+
+# CHECK-ASM: andn $s5, $s2, $a1
+# CHECK-ASM: encoding: [0x3c,0x97,0x16,0x00]
+andn $s5, $s2, $a1
+
+# CHECK-ASM: orn $tp, $sp, $s2
+# CHECK-ASM: encoding: [0x62,0x64,0x16,0x00]
+orn $tp, $sp, $s2
+
+# CHECK-ASM: andi $s2, $zero, 106
+# CHECK-ASM: encoding: [0x19,0xa8,0x41,0x03]
+andi $s2, $zero, 106
+
+# CHECK-ASM: ori $t5, $a1, 47
+# CHECK-ASM: encoding: [0xb1,0xbc,0x80,0x03]
+ori $t5, $a1, 47
+
+# CHECK-ASM: xori $t6, $s0, 99
+# CHECK-ASM: encoding: [0xf2,0x8e,0xc1,0x03]
+xori $t6, $s0, 99
+
+# CHECK-ASM: mul.w $a0, $t6, $sp
+# CHECK-ASM: encoding: [0x44,0x0e,0x1c,0x00]
+mul.w $a0, $t6, $sp
+
+# CHECK-ASM: mulh.w $s4, $s0, $zero
+# CHECK-ASM: encoding: [0xfb,0x82,0x1c,0x00]
+mulh.w $s4, $s0, $zero
+
+# CHECK-ASM: mulh.wu $a6, $t5, $s1
+# CHECK-ASM: encoding: [0x2a,0x62,0x1d,0x00]
+mulh.wu $a6, $t5, $s1
+
+# CHECK-ASM: div.w $s7, $t1, $s2
+# CHECK-ASM: encoding: [0xbe,0x65,0x20,0x00]
+div.w $s7, $t1, $s2
+
+# CHECK-ASM: mod.w $ra, $s3, $a6
+# CHECK-ASM: encoding: [0x41,0xab,0x20,0x00]
+mod.w $ra, $s3, $a6
+
+# CHECK-ASM: div.wu $t7, $s0, $zero
+# CHECK-ASM: encoding: [0xf3,0x02,0x21,0x00]
+div.wu $t7, $s0, $zero
+
+# CHECK-ASM: mod.wu $s4, $a5, $t5
+# CHECK-ASM: encoding: [0x3b,0xc5,0x21,0x00]
+mod.wu $s4, $a5, $t5
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: add.d $tp, $t6, $s4
+# CHECK64-ASM: encoding: [0x42,0xee,0x10,0x00]
+add.d $tp, $t6, $s4
+
+# CHECK64-ASM: sub.d $a3, $t0, $a3
+# CHECK64-ASM: encoding: [0x87,0x9d,0x11,0x00]
+sub.d $a3, $t0, $a3
+
+# CHECK64-ASM: addi.d $s5, $a2, 75
+# CHECK64-ASM: encoding: [0xdc,0x2c,0xc1,0x02]
+addi.d $s5, $a2, 75
+
+# CHECK64-ASM: addu16i.d $a5, $s0, 23
+# CHECK64-ASM: encoding: [0xe9,0x5e,0x00,0x10]
+addu16i.d $a5, $s0, 23
+
+# CHECK64-ASM: alsl.wu $t7, $a4, $s2, 1
+# CHECK64-ASM: encoding: [0x13,0x65,0x06,0x00]
+alsl.wu $t7, $a4, $s2, 1
+
+# CHECK64-ASM: alsl.d $t5, $a7, $a1, 3
+# CHECK64-ASM: encoding: [0x71,0x15,0x2d,0x00]
+alsl.d $t5, $a7, $a1, 3
+
+# CHECK64-ASM: lu32i.d $sp, 196
+# CHECK64-ASM: encoding: [0x83,0x18,0x00,0x16]
+lu32i.d $sp, 196
+
+# CHECK64-ASM: lu52i.d $t1, $a0, 195
+# CHECK64-ASM: encoding: [0x8d,0x0c,0x03,0x03]
+lu52i.d $t1, $a0, 195
+
+# CHECK64-ASM: pcaddu18i $t0, 26
+# CHECK64-ASM: encoding: [0x4c,0x03,0x00,0x1e]
+pcaddu18i $t0, 26
+
+# CHECK64-ASM: mul.d $ra, $t2, $s1
+# CHECK64-ASM: encoding: [0xc1,0xe1,0x1d,0x00]
+mul.d $ra, $t2, $s1
+
+# CHECK64-ASM: mulh.d $s5, $ra, $s4
+# CHECK64-ASM: encoding: [0x3c,0x6c,0x1e,0x00]
+mulh.d $s5, $ra, $s4
+
+# CHECK64-ASM: mulh.du $t1, $s4, $s6
+# CHECK64-ASM: encoding: [0x6d,0xf7,0x1e,0x00]
+mulh.du $t1, $s4, $s6
+
+# CHECK64-ASM: mulw.d.w $s4, $a2, $t5
+# CHECK64-ASM: encoding: [0xdb,0x44,0x1f,0x00]
+mulw.d.w $s4, $a2, $t5
+
+# CHECK64-ASM: mulw.d.wu $t5, $fp, $s7
+# CHECK64-ASM: encoding: [0xd1,0xfa,0x1f,0x00]
+mulw.d.wu $t5, $fp, $s7
+
+# CHECK64-ASM: div.d $s0, $a2, $r21
+# CHECK64-ASM: encoding: [0xd7,0x54,0x22,0x00]
+div.d $s0, $a2, $r21
+
+# CHECK64-ASM: mod.d $t4, $sp, $t3
+# CHECK64-ASM: encoding: [0x70,0xbc,0x22,0x00]
+mod.d $t4, $sp, $t3
+
+# CHECK64-ASM: div.du $s8, $s1, $t2
+# CHECK64-ASM: encoding: [0x1f,0x3b,0x23,0x00]
+div.du $s8, $s1, $t2
+
+# CHECK64-ASM: mod.du $s2, $s0, $s1
+# CHECK64-ASM: encoding: [0xf9,0xe2,0x23,0x00]
+mod.du $s2, $s0, $s1
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/atomic.s b/llvm/test/MC/LoongArch/Basic/Integer/atomic.s
new file mode 100644
index 0000000000000..5a3671ec9cd31
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/atomic.s
@@ -0,0 +1,181 @@
+## Test valid atomic memory access instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: ll.w $tp, $s4, 220
+# CHECK-ASM: encoding: [0x62,0xdf,0x00,0x20]
+ll.w $tp, $s4, 220
+
+# CHECK-ASM: sc.w $t7, $t2, 56
+# CHECK-ASM: encoding: [0xd3,0x39,0x00,0x21]
+sc.w $t7, $t2, 56
+
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: amswap.w $a2, $t0, $s1
+# CHECK64-ASM: encoding: [0x06,0x33,0x60,0x38]
+amswap.w $a2, $t0, $s1
+
+# CHECK64-ASM: amswap.d $tp, $t2, $fp
+# CHECK64-ASM: encoding: [0xc2,0xba,0x60,0x38]
+amswap.d $tp, $t2, $fp
+
+# CHECK64-ASM: amadd.w $a4, $t0, $r21
+# CHECK64-ASM: encoding: [0xa8,0x32,0x61,0x38]
+amadd.w $a4, $t0, $r21
+
+# CHECK64-ASM: amadd.d $a1, $t5, $s6
+# CHECK64-ASM: encoding: [0xa5,0xc7,0x61,0x38]
+amadd.d $a1, $t5, $s6
+
+# CHECK64-ASM: amand.w $a0, $t7, $fp
+# CHECK64-ASM: encoding: [0xc4,0x4e,0x62,0x38]
+amand.w $a0, $t7, $fp
+
+# CHECK64-ASM: amand.d $a6, $t6, $s6
+# CHECK64-ASM: encoding: [0xaa,0xcb,0x62,0x38]
+amand.d $a6, $t6, $s6
+
+# CHECK64-ASM: amor.w $a2, $t4, $s0
+# CHECK64-ASM: encoding: [0xe6,0x42,0x63,0x38]
+amor.w $a2, $t4, $s0
+
+# CHECK64-ASM: amor.d $sp, $t4, $s1
+# CHECK64-ASM: encoding: [0x03,0xc3,0x63,0x38]
+amor.d $sp, $t4, $s1
+
+# CHECK64-ASM: amxor.w $tp, $t3, $s0
+# CHECK64-ASM: encoding: [0xe2,0x3e,0x64,0x38]
+amxor.w $tp, $t3, $s0
+
+# CHECK64-ASM: amxor.d $a4, $t8, $s5
+# CHECK64-ASM: encoding: [0x88,0xd3,0x64,0x38]
+amxor.d $a4, $t8, $s5
+
+# CHECK64-ASM: ammax.w $ra, $a7, $s0
+# CHECK64-ASM: encoding: [0xe1,0x2e,0x65,0x38]
+ammax.w $ra, $a7, $s0
+
+# CHECK64-ASM: ammax.d $a5, $t8, $s4
+# CHECK64-ASM: encoding: [0x69,0xd3,0x65,0x38]
+ammax.d $a5, $t8, $s4
+
+# CHECK64-ASM: ammin.w $a5, $t2, $s0
+# CHECK64-ASM: encoding: [0xe9,0x3a,0x66,0x38]
+ammin.w $a5, $t2, $s0
+
+# CHECK64-ASM: ammin.d $a5, $t1, $fp
+# CHECK64-ASM: encoding: [0xc9,0xb6,0x66,0x38]
+ammin.d $a5, $t1, $fp
+
+# CHECK64-ASM: ammax.wu $a5, $a7, $fp
+# CHECK64-ASM: encoding: [0xc9,0x2e,0x67,0x38]
+ammax.wu $a5, $a7, $fp
+
+# CHECK64-ASM: ammax.du $a2, $t4, $s2
+# CHECK64-ASM: encoding: [0x26,0xc3,0x67,0x38]
+ammax.du $a2, $t4, $s2
+
+# CHECK64-ASM: ammin.wu $a4, $t6, $s7
+# CHECK64-ASM: encoding: [0xc8,0x4b,0x68,0x38]
+ammin.wu $a4, $t6, $s7
+
+# CHECK64-ASM: ammin.du $a3, $t4, $s2
+# CHECK64-ASM: encoding: [0x27,0xc3,0x68,0x38]
+ammin.du $a3, $t4, $s2
+
+# CHECK64-ASM: amswap_db.w $a2, $t0, $s1
+# CHECK64-ASM: encoding: [0x06,0x33,0x69,0x38]
+amswap_db.w $a2, $t0, $s1
+
+# CHECK64-ASM: amswap_db.d $tp, $t2, $fp
+# CHECK64-ASM: encoding: [0xc2,0xba,0x69,0x38]
+amswap_db.d $tp, $t2, $fp
+
+# CHECK64-ASM: amadd_db.w $a4, $t0, $r21
+# CHECK64-ASM: encoding: [0xa8,0x32,0x6a,0x38]
+amadd_db.w $a4, $t0, $r21
+
+# CHECK64-ASM: amadd_db.d $a1, $t5, $s6
+# CHECK64-ASM: encoding: [0xa5,0xc7,0x6a,0x38]
+amadd_db.d $a1, $t5, $s6
+
+# CHECK64-ASM: amand_db.w $a0, $t7, $fp
+# CHECK64-ASM: encoding: [0xc4,0x4e,0x6b,0x38]
+amand_db.w $a0, $t7, $fp
+
+# CHECK64-ASM: amand_db.d $a6, $t6, $s6
+# CHECK64-ASM: encoding: [0xaa,0xcb,0x6b,0x38]
+amand_db.d $a6, $t6, $s6
+
+# CHECK64-ASM: amor_db.w $a2, $t4, $s0
+# CHECK64-ASM: encoding: [0xe6,0x42,0x6c,0x38]
+amor_db.w $a2, $t4, $s0
+
+# CHECK64-ASM: amor_db.d $sp, $t4, $s1
+# CHECK64-ASM: encoding: [0x03,0xc3,0x6c,0x38]
+amor_db.d $sp, $t4, $s1
+
+# CHECK64-ASM: amxor_db.w $tp, $t3, $s0
+# CHECK64-ASM: encoding: [0xe2,0x3e,0x6d,0x38]
+amxor_db.w $tp, $t3, $s0
+
+# CHECK64-ASM: amxor_db.d $a4, $t8, $s5
+# CHECK64-ASM: encoding: [0x88,0xd3,0x6d,0x38]
+amxor_db.d $a4, $t8, $s5
+
+# CHECK64-ASM: ammax_db.w $ra, $a7, $s0
+# CHECK64-ASM: encoding: [0xe1,0x2e,0x6e,0x38]
+ammax_db.w $ra, $a7, $s0
+
+# CHECK64-ASM: ammax_db.d $a5, $t8, $s4
+# CHECK64-ASM: encoding: [0x69,0xd3,0x6e,0x38]
+ammax_db.d $a5, $t8, $s4
+
+# CHECK64-ASM: ammin_db.w $a5, $t2, $s0
+# CHECK64-ASM: encoding: [0xe9,0x3a,0x6f,0x38]
+ammin_db.w $a5, $t2, $s0
+
+# CHECK64-ASM: ammin_db.d $a5, $t1, $fp
+# CHECK64-ASM: encoding: [0xc9,0xb6,0x6f,0x38]
+ammin_db.d $a5, $t1, $fp
+
+# CHECK64-ASM: ammax_db.wu $a5, $a7, $fp
+# CHECK64-ASM: encoding: [0xc9,0x2e,0x70,0x38]
+ammax_db.wu $a5, $a7, $fp
+
+# CHECK64-ASM: ammax_db.du $a2, $t4, $s2
+# CHECK64-ASM: encoding: [0x26,0xc3,0x70,0x38]
+ammax_db.du $a2, $t4, $s2
+
+# CHECK64-ASM: ammin_db.wu $a4, $t6, $s7
+# CHECK64-ASM: encoding: [0xc8,0x4b,0x71,0x38]
+ammin_db.wu $a4, $t6, $s7
+
+# CHECK64-ASM: ammin_db.du $a3, $t4, $s2
+# CHECK64-ASM: encoding: [0x27,0xc3,0x71,0x38]
+ammin_db.du $a3, $t4, $s2
+
+# CHECK64-ASM: ll.d $s2, $s4, 16
+# CHECK64-ASM: encoding: [0x79,0x13,0x00,0x22]
+ll.d $s2, $s4, 16
+
+# CHECK64-ASM: sc.d $t5, $t5, 244
+# CHECK64-ASM: encoding: [0x31,0xf6,0x00,0x23]
+sc.d $t5, $t5, 244
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/barrier.s b/llvm/test/MC/LoongArch/Basic/Integer/barrier.s
new file mode 100644
index 0000000000000..077ada583b70f
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/barrier.s
@@ -0,0 +1,15 @@
+## Test valid barrier instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+
+# CHECK-ASM: dbar 0
+# CHECK-ASM: encoding: [0x00,0x00,0x72,0x38]
+dbar 0
+
+# CHECK-ASM: ibar 0
+# CHECK-ASM: encoding: [0x00,0x80,0x72,0x38]
+ibar 0
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/bit-manipu.s b/llvm/test/MC/LoongArch/Basic/Integer/bit-manipu.s
new file mode 100644
index 0000000000000..d3604b4d8676e
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/bit-manipu.s
@@ -0,0 +1,132 @@
+## Test valid bit manipulation instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: ext.w.b $t8, $t6
+# CHECK-ASM: encoding: [0x54,0x5e,0x00,0x00]
+ext.w.b $t8, $t6
+
+# CHECK-ASM: ext.w.h $s0, $s0
+# CHECK-ASM: encoding: [0xf7,0x5a,0x00,0x00]
+ext.w.h $s0, $s0
+
+# CHECK-ASM: clo.w $ra, $sp
+# CHECK-ASM: encoding: [0x61,0x10,0x00,0x00]
+clo.w $ra, $sp
+
+# CHECK-ASM: clz.w $a3, $a6
+# CHECK-ASM: encoding: [0x47,0x15,0x00,0x00]
+clz.w $a3, $a6
+
+# CHECK-ASM: cto.w $tp, $a2
+# CHECK-ASM: encoding: [0xc2,0x18,0x00,0x00]
+cto.w $tp, $a2
+
+# CHECK-ASM: ctz.w $a1, $fp
+# CHECK-ASM: encoding: [0xc5,0x1e,0x00,0x00]
+ctz.w $a1, $fp
+
+# CHECK-ASM: bytepick.w $s6, $zero, $t4, 0
+# CHECK-ASM: encoding: [0x1d,0x40,0x08,0x00]
+bytepick.w $s6, $zero, $t4, 0
+
+# CHECK-ASM: revb.2h $t8, $a7
+# CHECK-ASM: encoding: [0x74,0x31,0x00,0x00]
+revb.2h $t8, $a7
+
+# CHECK-ASM: bitrev.4b $r21, $s4
+# CHECK-ASM: encoding: [0x75,0x4b,0x00,0x00]
+bitrev.4b $r21, $s4
+
+# CHECK-ASM: bitrev.w $s2, $a1
+# CHECK-ASM: encoding: [0xb9,0x50,0x00,0x00]
+bitrev.w $s2, $a1
+
+# CHECK-ASM: bstrins.w $a4, $a7, 7, 2
+# CHECK-ASM: encoding: [0x68,0x09,0x67,0x00]
+bstrins.w $a4, $a7, 7, 2
+
+# CHECK-ASM: bstrpick.w $ra, $a5, 10, 4
+# CHECK-ASM: encoding: [0x21,0x91,0x6a,0x00]
+bstrpick.w $ra, $a5, 10, 4
+
+# CHECK-ASM: maskeqz $t8, $a7, $t6
+# CHECK-ASM: encoding: [0x74,0x49,0x13,0x00]
+maskeqz $t8, $a7, $t6
+
+# CHECK-ASM: masknez $t8, $t1, $s3
+# CHECK-ASM: encoding: [0xb4,0xe9,0x13,0x00]
+masknez $t8, $t1, $s3
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: clo.d $s6, $ra
+# CHECK64-ASM: encoding: [0x3d,0x20,0x00,0x00]
+clo.d $s6, $ra
+
+# CHECK64-ASM: clz.d $s3, $s3
+# CHECK64-ASM: encoding: [0x5a,0x27,0x00,0x00]
+clz.d $s3, $s3
+
+# CHECK64-ASM: cto.d $t6, $t8
+# CHECK64-ASM: encoding: [0x92,0x2a,0x00,0x00]
+cto.d $t6, $t8
+
+# CHECK64-ASM: ctz.d $t5, $a6
+# CHECK64-ASM: encoding: [0x51,0x2d,0x00,0x00]
+ctz.d $t5, $a6
+
+# CHECK64-ASM: bytepick.d $t3, $t5, $t8, 4
+# CHECK64-ASM: encoding: [0x2f,0x52,0x0e,0x00]
+bytepick.d $t3, $t5, $t8, 4
+
+# CHECK64-ASM: revb.4h $t1, $t7
+# CHECK64-ASM: encoding: [0x6d,0x36,0x00,0x00]
+revb.4h $t1, $t7
+
+# CHECK64-ASM: revb.2w $s5, $s4
+# CHECK64-ASM: encoding: [0x7c,0x3b,0x00,0x00]
+revb.2w $s5, $s4
+
+# CHECK64-ASM: revb.d $zero, $s0
+# CHECK64-ASM: encoding: [0xe0,0x3e,0x00,0x00]
+revb.d $zero, $s0
+
+# CHECK64-ASM: revh.2w $s5, $a6
+# CHECK64-ASM: encoding: [0x5c,0x41,0x00,0x00]
+revh.2w $s5, $a6
+
+# CHECK64-ASM: revh.d $a5, $a3
+# CHECK64-ASM: encoding: [0xe9,0x44,0x00,0x00]
+revh.d $a5, $a3
+
+# CHECK64-ASM: bitrev.8b $t1, $s2
+# CHECK64-ASM: encoding: [0x2d,0x4f,0x00,0x00]
+bitrev.8b $t1, $s2
+
+# CHECK64-ASM: bitrev.d $t7, $s0
+# CHECK64-ASM: encoding: [0xf3,0x56,0x00,0x00]
+bitrev.d $t7, $s0
+
+# CHECK64-ASM: bstrins.d $a4, $a7, 7, 2
+# CHECK64-ASM: encoding: [0x68,0x09,0x87,0x00]
+bstrins.d $a4, $a7, 7, 2
+
+# CHECK64-ASM: bstrpick.d $s8, $s4, 39, 22
+# CHECK64-ASM: encoding: [0x7f,0x5b,0xe7,0x00]
+bstrpick.d $s8, $s4, 39, 22
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/bit-shift.s b/llvm/test/MC/LoongArch/Basic/Integer/bit-shift.s
new file mode 100644
index 0000000000000..2646245bcd740
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/bit-shift.s
@@ -0,0 +1,84 @@
+## Test valid bit shift instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: sll.w $s1, $s4, $s0
+# CHECK-ASM: encoding: [0x78,0x5f,0x17,0x00]
+sll.w $s1, $s4, $s0
+
+# CHECK-ASM: srl.w $s8, $t5, $a3
+# CHECK-ASM: encoding: [0x3f,0x9e,0x17,0x00]
+srl.w $s8, $t5, $a3
+
+# CHECK-ASM: sra.w $t0, $s5, $a6
+# CHECK-ASM: encoding: [0x8c,0x2b,0x18,0x00]
+sra.w $t0, $s5, $a6
+
+# CHECK-ASM: rotr.w $ra, $s3, $t6
+# CHECK-ASM: encoding: [0x41,0x4b,0x1b,0x00]
+rotr.w $ra, $s3, $t6
+
+# CHECK-ASM: slli.w $s3, $t6, 0
+# CHECK-ASM: encoding: [0x5a,0x82,0x40,0x00]
+slli.w $s3, $t6, 0
+
+# CHECK-ASM: srli.w $a6, $t2, 30
+# CHECK-ASM: encoding: [0xca,0xf9,0x44,0x00]
+srli.w $a6, $t2, 30
+
+# CHECK-ASM: srai.w $a4, $t5, 24
+# CHECK-ASM: encoding: [0x28,0xe2,0x48,0x00]
+srai.w $a4, $t5, 24
+
+# CHECK-ASM: rotri.w $s0, $t8, 23
+# CHECK-ASM: encoding: [0x97,0xde,0x4c,0x00]
+rotri.w $s0, $t8, 23
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: sll.d $t8, $t3, $sp
+# CHECK64-ASM: encoding: [0xf4,0x8d,0x18,0x00]
+sll.d $t8, $t3, $sp
+
+# CHECK64-ASM: srl.d $t2, $s2, $zero
+# CHECK64-ASM: encoding: [0x2e,0x03,0x19,0x00]
+srl.d $t2, $s2, $zero
+
+# CHECK64-ASM: sra.d $a3, $fp, $s8
+# CHECK64-ASM: encoding: [0xc7,0xfe,0x19,0x00]
+sra.d $a3, $fp, $s8
+
+# CHECK64-ASM: rotr.d $s8, $sp, $ra
+# CHECK64-ASM: encoding: [0x7f,0x84,0x1b,0x00]
+rotr.d $s8, $sp, $ra
+
+# CHECK64-ASM: slli.d $a6, $s8, 39
+# CHECK64-ASM: encoding: [0xea,0x9f,0x41,0x00]
+slli.d $a6, $s8, 39
+
+# CHECK64-ASM: srli.d $s8, $fp, 38
+# CHECK64-ASM: encoding: [0xdf,0x9a,0x45,0x00]
+srli.d $s8, $fp, 38
+
+# CHECK64-ASM: srai.d $a5, $r21, 27
+# CHECK64-ASM: encoding: [0xa9,0x6e,0x49,0x00]
+srai.d $a5, $r21, 27
+
+# CHECK64-ASM: rotri.d $s6, $zero, 7
+# CHECK64-ASM: encoding: [0x1d,0x1c,0x4d,0x00]
+rotri.d $s6, $zero, 7
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/bound-check.s b/llvm/test/MC/LoongArch/Basic/Integer/bound-check.s
new file mode 100644
index 0000000000000..0d914dd737e7e
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/bound-check.s
@@ -0,0 +1,69 @@
+## Test valid boundary check memory access instructions.
+
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+
+# CHECK-ASM: ldgt.b $a2, $a2, $s6
+# CHECK-ASM: encoding: [0xc6,0x74,0x78,0x38]
+ldgt.b $a2, $a2, $s6
+
+# CHECK-ASM: ldgt.h $a1, $s8, $ra
+# CHECK-ASM: encoding: [0xe5,0x87,0x78,0x38]
+ldgt.h $a1, $s8, $ra
+
+# CHECK-ASM: ldgt.w $t3, $s3, $a4
+# CHECK-ASM: encoding: [0x4f,0x23,0x79,0x38]
+ldgt.w $t3, $s3, $a4
+
+# CHECK-ASM: ldgt.d $s0, $s2, $s8
+# CHECK-ASM: encoding: [0x37,0xff,0x79,0x38]
+ldgt.d $s0, $s2, $s8
+
+# CHECK-ASM: ldle.b $a5, $t0, $t3
+# CHECK-ASM: encoding: [0x89,0x3d,0x7a,0x38]
+ldle.b $a5, $t0, $t3
+
+# CHECK-ASM: ldle.h $a7, $a7, $s0
+# CHECK-ASM: encoding: [0x6b,0xdd,0x7a,0x38]
+ldle.h $a7, $a7, $s0
+
+# CHECK-ASM: ldle.w $s1, $tp, $tp
+# CHECK-ASM: encoding: [0x58,0x08,0x7b,0x38]
+ldle.w $s1, $tp, $tp
+
+# CHECK-ASM: ldle.d $t8, $t3, $t4
+# CHECK-ASM: encoding: [0xf4,0xc1,0x7b,0x38]
+ldle.d $t8, $t3, $t4
+
+# CHECK-ASM: stgt.b $s4, $t7, $t8
+# CHECK-ASM: encoding: [0x7b,0x52,0x7c,0x38]
+stgt.b $s4, $t7, $t8
+
+# CHECK-ASM: stgt.h $t4, $a0, $a2
+# CHECK-ASM: encoding: [0x90,0x98,0x7c,0x38]
+stgt.h $t4, $a0, $a2
+
+# CHECK-ASM: stgt.w $s8, $s5, $t2
+# CHECK-ASM: encoding: [0x9f,0x3b,0x7d,0x38]
+stgt.w $s8, $s5, $t2
+
+# CHECK-ASM: stgt.d $s7, $r21, $s1
+# CHECK-ASM: encoding: [0xbe,0xe2,0x7d,0x38]
+stgt.d $s7, $r21, $s1
+
+# CHECK-ASM: stle.b $a6, $a0, $t4
+# CHECK-ASM: encoding: [0x8a,0x40,0x7e,0x38]
+stle.b $a6, $a0, $t4
+
+# CHECK-ASM: stle.h $t5, $t5, $r21
+# CHECK-ASM: encoding: [0x31,0xd6,0x7e,0x38]
+stle.h $t5, $t5, $r21
+
+# CHECK-ASM: stle.w $s0, $s5, $s6
+# CHECK-ASM: encoding: [0x97,0x77,0x7f,0x38]
+stle.w $s0, $s5, $s6
+
+# CHECK-ASM: stle.d $s2, $s1, $s6
+# CHECK-ASM: encoding: [0x19,0xf7,0x7f,0x38]
+stle.d $s2, $s1, $s6
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/branch.s b/llvm/test/MC/LoongArch/Basic/Integer/branch.s
new file mode 100644
index 0000000000000..8e4fb3d11fe79
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/branch.s
@@ -0,0 +1,51 @@
+## Test valid branch instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+
+# CHECK-ASM: beq $a6, $a3, 176
+# CHECK-ASM: encoding: [0x47,0xb1,0x00,0x58]
+beq $a6, $a3, 176
+
+# CHECK-ASM: bne $s2, $ra, 136
+# CHECK-ASM: encoding: [0x21,0x8b,0x00,0x5c]
+bne $s2, $ra, 136
+
+# CHECK-ASM: blt $t3, $s7, 168
+# CHECK-ASM: encoding: [0xfe,0xa9,0x00,0x60]
+blt $t3, $s7, 168
+
+# CHECK-ASM: bge $t0, $t3, 148
+# CHECK-ASM: encoding: [0x8f,0x95,0x00,0x64]
+bge $t0, $t3, 148
+
+# CHECK-ASM: bltu $t5, $a1, 4
+# CHECK-ASM: encoding: [0x25,0x06,0x00,0x68]
+bltu $t5, $a1, 4
+
+# CHECK-ASM: bgeu $a2, $s0, 140
+# CHECK-ASM: encoding: [0xd7,0x8c,0x00,0x6c]
+bgeu $a2, $s0, 140
+
+# CHECK-ASM: beqz $a5, 96
+# CHECK-ASM: encoding: [0x20,0x61,0x00,0x40]
+beqz $a5, 96
+
+# CHECK-ASM: bnez $sp, 212
+# CHECK-ASM: encoding: [0x60,0xd4,0x00,0x44]
+bnez $sp, 212
+
+# CHECK-ASM: b 248
+# CHECK-ASM: encoding: [0x00,0xf8,0x00,0x50]
+b 248
+
+# CHECK-ASM: bl 236
+# CHECK-ASM: encoding: [0x00,0xec,0x00,0x54]
+bl 236
+
+# CHECK-ASM: jirl $ra, $a0, 4
+# CHECK-ASM: encoding: [0x81,0x04,0x00,0x4c]
+jirl $ra, $a0, 4
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/crc.s b/llvm/test/MC/LoongArch/Basic/Integer/crc.s
new file mode 100644
index 0000000000000..06ccdd93ee31c
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/crc.s
@@ -0,0 +1,37 @@
+## Test valid CRC check instructions.
+
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+
+# CHECK-ASM: crc.w.b.w $s1, $a3, $tp
+# CHECK-ASM: encoding: [0xf8,0x08,0x24,0x00]
+crc.w.b.w $s1, $a3, $tp
+
+# CHECK-ASM: crc.w.h.w $s8, $a6, $t6
+# CHECK-ASM: encoding: [0x5f,0xc9,0x24,0x00]
+crc.w.h.w $s8, $a6, $t6
+
+# CHECK-ASM: crc.w.w.w $s5, $a2, $a6
+# CHECK-ASM: encoding: [0xdc,0x28,0x25,0x00]
+crc.w.w.w $s5, $a2, $a6
+
+# CHECK-ASM: crc.w.d.w $s5, $a7, $s8
+# CHECK-ASM: encoding: [0x7c,0xfd,0x25,0x00]
+crc.w.d.w $s5, $a7, $s8
+
+# CHECK-ASM: crcc.w.b.w $t3, $t6, $sp
+# CHECK-ASM: encoding: [0x4f,0x0e,0x26,0x00]
+crcc.w.b.w $t3, $t6, $sp
+
+# CHECK-ASM: crcc.w.h.w $r21, $s6, $t6
+# CHECK-ASM: encoding: [0xb5,0xcb,0x26,0x00]
+crcc.w.h.w $r21, $s6, $t6
+
+# CHECK-ASM: crcc.w.w.w $t5, $t2, $t1
+# CHECK-ASM: encoding: [0xd1,0x35,0x27,0x00]
+crcc.w.w.w $t5, $t2, $t1
+
+# CHECK-ASM: crcc.w.d.w $s7, $r21, $s4
+# CHECK-ASM: encoding: [0xbe,0xee,0x27,0x00]
+crcc.w.d.w $s7, $r21, $s4
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
new file mode 100644
index 0000000000000..cb6b2ba1beddf
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
@@ -0,0 +1,176 @@
+## Test invalid instructions on both loongarch32 and loongarch64 target.
+
+# RUN: not llvm-mc --triple=loongarch32 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK64
+# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 --defsym=LA64=1 | FileCheck %s
+
+## Out of range immediates
+## uimm2
+bytepick.w $a0, $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:27: error: immediate must be an integer in the range [0, 3]
+bytepick.w $a0, $a0, $a0, 4
+# CHECK: :[[#@LINE-1]]:27: error: immediate must be an integer in the range [0, 3]
+
+## uimm2_plus1
+alsl.w $a0, $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:23: error: immediate must be an integer in the range [1, 4]
+alsl.w $a0, $a0, $a0, 5
+# CHECK: :[[#@LINE-1]]:23: error: immediate must be an integer in the range [1, 4]
+
+## uimm5
+slli.w $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 31]
+srli.w $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 31]
+srai.w $a0, $a0, 32
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 31]
+rotri.w $a0, $a0, 32
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be an integer in the range [0, 31]
+bstrins.w $a0, $a0, 31, -1
+# CHECK: :[[#@LINE-1]]:25: error: immediate must be an integer in the range [0, 31]
+bstrpick.w $a0, $a0, 32, 0
+# CHECK: :[[#@LINE-1]]:22: error: immediate must be an integer in the range [0, 31]
+preld -1, $a0, 0
+# CHECK: :[[#@LINE-1]]:7: error: immediate must be an integer in the range [0, 31]
+preld 32, $a0, 0
+# CHECK: :[[#@LINE-1]]:7: error: immediate must be an integer in the range [0, 31]
+
+## uimm12
+andi $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
+ori $a0, $a0, 4096
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [0, 4095]
+xori $a0, $a0, 4096
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
+
+## simm12
+addi.w $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [-2048, 2047]
+slti $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+sltui $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
+preld 0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [-2048, 2047]
+ld.b $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+ld.h $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+ld.w $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+ld.bu $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
+ld.hu $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
+st.b $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+st.h $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+st.w $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+
+## simm14_lsl2
+ll.w $a0, $a0, -32772
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+ll.w $a0, $a0, -32769
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+sc.w $a0, $a0, 32767
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+sc.w $a0, $a0, 32768
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+
+## simm16_lsl2
+beq $a0, $a0, -0x20004
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+bne $a0, $a0, -0x20004
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+blt $a0, $a0, -0x1FFFF
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+bge $a0, $a0, -0x1FFFF
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+bltu $a0, $a0, 0x1FFFF
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+bgeu $a0, $a0, 0x1FFFF
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+jirl $a0, $a0, 0x20000
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+
+## simm20
+lu12i.w $a0, -0x80001
+# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
+pcaddi $a0, -0x80001
+# CHECK: :[[#@LINE-1]]:13: error: immediate must be an integer in the range [-524288, 524287]
+pcaddu12i $a0, 0x80000
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
+pcalau12i $a0, 0x80000
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
+
+## simm21_lsl2
+beqz $a0, -0x400001
+# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+bnez $a0, -0x3FFFFF
+# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+beqz $a0, 0x3FFFFF
+# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+bnez $a0, 0x400000
+# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+
+## simm26_lsl2
+b -0x8000001
+# CHECK: :[[#@LINE-1]]:3: error: immediate must be a multiple of 4 in the range [-134217728, 134217724]
+b 0x1
+# CHECK: :[[#@LINE-1]]:3: error: immediate must be a multiple of 4 in the range [-134217728, 134217724]
+bl 0x7FFFFFF
+# CHECK: :[[#@LINE-1]]:4: error: immediate must be a multiple of 4 in the range [-134217728, 134217724]
+bl 0x8000000
+# CHECK: :[[#@LINE-1]]:4: error: immediate must be a multiple of 4 in the range [-134217728, 134217724]
+
+## Invalid mnemonics
+nori $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:1: error: unrecognized instruction mnemonic
+andni $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:1: error: unrecognized instruction mnemonic
+orni $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:1: error: unrecognized instruction mnemonic
+
+## Invalid register names
+add.w $foo, $a0, $a0
+# CHECK: :[[#@LINE-1]]:8: error: invalid operand for instruction
+sub.w $a8, $a0, $a0
+# CHECK: :[[#@LINE-1]]:8: error: invalid operand for instruction
+addi.w $x0, $a0, 0
+# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction
+alsl.w $t9, $a0, $a0, 1
+# CHECK: :[[#@LINE-1]]:9: error: invalid operand for instruction
+lu12i.w $s10, 0
+# CHECK: :[[#@LINE-1]]:10: error: invalid operand for instruction
+
+.ifndef LA64
+## LoongArch64 mnemonics
+add.d $a0, $a0, $a0
+# CHECK64: :[[#@LINE-1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set
+addi.d $a0, $a0, 0
+# CHECK64: :[[#@LINE-1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set
+.endif
+
+## Invalid operand types
+slt $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:15: error: invalid operand for instruction
+slti $a0, 0, 0
+# CHECK: :[[#@LINE-1]]:11: error: invalid operand for instruction
+
+## Too many operands
+andi $a0, $a0, 0, 0
+# CHECK: :[[#@LINE-1]]:19: error: invalid operand for instruction
+
+## Too few operands
+and $a0, $a0
+# CHECK: :[[#@LINE-1]]:1: error: too few operands for instruction
+andi $a0, $a0
+# CHECK: :[[#@LINE-1]]:1: error: too few operands for instruction
+
+## Instructions outside the base ISA
+## TODO: Test instructions in LSX/LASX/LBT/LVZ after their introduction.
+
+## Using floating point registers when integer registers are expected
+sll.w $a0, $a0, $fa0
+# CHECK: :[[#@LINE-1]]:18: error: invalid operand for instruction

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
new file mode 100644
index 0000000000000..e5249f04f4920
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
@@ -0,0 +1,66 @@
+## Test invalid instructions on loongarch64 target.
+
+# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 | FileCheck %s
+
+## Out of range immediates
+## uimm2_plus1
+alsl.wu $a0, $a0, $a0, 0
+# CHECK: :[[#@LINE-1]]:24: error: immediate must be an integer in the range [1, 4]
+alsl.d $a0, $a0, $a0, 5
+# CHECK: :[[#@LINE-1]]:23: error: immediate must be an integer in the range [1, 4]
+
+## uimm3
+bytepick.d $a0, $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:27: error: immediate must be an integer in the range [0, 7]
+bytepick.d $a0, $a0, $a0, 8
+# CHECK: :[[#@LINE-1]]:27: error: immediate must be an integer in the range [0, 7]
+
+## uimm6
+slli.d $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 63]
+srli.d $a0, $a0, -1
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 63]
+srai.d $a0, $a0, 64
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [0, 63]
+rotri.d $a0, $a0, 64
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be an integer in the range [0, 63]
+bstrins.d $a0, $a0, 63, -1
+# CHECK: :[[#@LINE-1]]:25: error: immediate must be an integer in the range [0, 63]
+bstrpick.d $a0, $a0, 64, 0
+# CHECK: :[[#@LINE-1]]:22: error: immediate must be an integer in the range [0, 63]
+
+## simm12
+addi.d $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:18: error: immediate must be an integer in the range [-2048, 2047]
+lu52i.d $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be an integer in the range [-2048, 2047]
+ld.wu $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
+st.d $a0, $a0, 2048
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
+
+## simm14_lsl2
+ldptr.w $a0, $a0, -32772
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+ldptr.d $a0, $a0, -32772
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+stptr.w $a0, $a0, -32769
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+stptr.d $a0, $a0, -32769
+# CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+ll.w $a0, $a0, 32767
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+sc.w $a0, $a0, 32768
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-32768, 32764]
+
+## simm16
+addu16i.d $a0, $a0, -32769
+# CHECK: :[[#@LINE-1]]:21: error: immediate must be an integer in the range [-32768, 32767]
+addu16i.d $a0, $a0, 32768
+# CHECK: :[[#@LINE-1]]:21: error: immediate must be an integer in the range [-32768, 32767]
+
+## simm20
+lu32i.d $a0, -0x80001
+# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
+pcaddu18i $a0, 0x80000
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/memory.s b/llvm/test/MC/LoongArch/Basic/Integer/memory.s
new file mode 100644
index 0000000000000..75225f7ac9a2d
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/memory.s
@@ -0,0 +1,124 @@
+## Test valid memory access instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: ld.b $s1, $a4, 21
+# CHECK-ASM: encoding: [0x18,0x55,0x00,0x28]
+ld.b $s1, $a4, 21
+
+# CHECK-ASM: ld.h $a3, $t6, 80
+# CHECK-ASM: encoding: [0x47,0x42,0x41,0x28]
+ld.h $a3, $t6, 80
+
+# CHECK-ASM: ld.w $t6, $s3, 92
+# CHECK-ASM: encoding: [0x52,0x73,0x81,0x28]
+ld.w $t6, $s3, 92
+
+# CHECK-ASM: ld.bu $t1, $t1, 150
+# CHECK-ASM: encoding: [0xad,0x59,0x02,0x2a]
+ld.bu $t1, $t1, 150
+
+# CHECK-ASM: ld.hu $t6, $s6, 198
+# CHECK-ASM: encoding: [0xb2,0x1b,0x43,0x2a]
+ld.hu $t6, $s6, 198
+
+# CHECK-ASM: st.b $sp, $a3, 95
+# CHECK-ASM: encoding: [0xe3,0x7c,0x01,0x29]
+st.b $sp, $a3, 95
+
+# CHECK-ASM: st.h $s2, $t4, 122
+# CHECK-ASM: encoding: [0x19,0xea,0x41,0x29]
+st.h $s2, $t4, 122
+
+# CHECK-ASM: st.w $t1, $t1, 175
+# CHECK-ASM: encoding: [0xad,0xbd,0x82,0x29]
+st.w $t1, $t1, 175
+
+# CHECK-ASM: preld 10, $zero, 23
+# CHECK-ASM: encoding: [0x0a,0x5c,0xc0,0x2a]
+preld 10, $zero, 23
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: ld.wu $t2, $t7, 31
+# CHECK64-ASM: encoding: [0x6e,0x7e,0x80,0x2a]
+ld.wu $t2, $t7, 31
+
+# CHECK64-ASM: st.d $s7, $s7, 60
+# CHECK64-ASM: encoding: [0xde,0xf3,0xc0,0x29]
+st.d $s7, $s7, 60
+
+# CHECK64-ASM: ldx.b $s1, $ra, $tp
+# CHECK64-ASM: encoding: [0x38,0x08,0x00,0x38]
+ldx.b $s1, $ra, $tp
+
+# CHECK64-ASM: ldx.h $fp, $fp, $t5
+# CHECK64-ASM: encoding: [0xd6,0x46,0x04,0x38]
+ldx.h $fp, $fp, $t5
+
+# CHECK64-ASM: ldx.w $s2, $a7, $s0
+# CHECK64-ASM: encoding: [0x79,0x5d,0x08,0x38]
+ldx.w $s2, $a7, $s0
+
+# CHECK64-ASM: ldx.d $t6, $s0, $t8
+# CHECK64-ASM: encoding: [0xf2,0x52,0x0c,0x38]
+ldx.d $t6, $s0, $t8
+
+# CHECK64-ASM: ldx.bu $a7, $a5, $a5
+# CHECK64-ASM: encoding: [0x2b,0x25,0x20,0x38]
+ldx.bu $a7, $a5, $a5
+
+# CHECK64-ASM: ldx.hu $fp, $s0, $s4
+# CHECK64-ASM: encoding: [0xf6,0x6e,0x24,0x38]
+ldx.hu $fp, $s0, $s4
+
+# CHECK64-ASM: ldx.wu $a4, $s1, $s5
+# CHECK64-ASM: encoding: [0x08,0x73,0x28,0x38]
+ldx.wu $a4, $s1, $s5
+
+# CHECK64-ASM: stx.b $t7, $ra, $sp
+# CHECK64-ASM: encoding: [0x33,0x0c,0x10,0x38]
+stx.b $t7, $ra, $sp
+
+# CHECK64-ASM: stx.h $zero, $s5, $s3
+# CHECK64-ASM: encoding: [0x80,0x6b,0x14,0x38]
+stx.h $zero, $s5, $s3
+
+# CHECK64-ASM: stx.w $a3, $a0, $s8
+# CHECK64-ASM: encoding: [0x87,0x7c,0x18,0x38]
+stx.w $a3, $a0, $s8
+
+# CHECK64-ASM: stx.d $a3, $s8, $a6
+# CHECK64-ASM: encoding: [0xe7,0x2b,0x1c,0x38]
+stx.d $a3, $s8, $a6
+
+# CHECK64-ASM: ldptr.w $s3, $a2, 60
+# CHECK64-ASM: encoding: [0xda,0x3c,0x00,0x24]
+ldptr.w $s3, $a2, 60
+
+# CHECK64-ASM: ldptr.d $a1, $s6, 244
+# CHECK64-ASM: encoding: [0xa5,0xf7,0x00,0x26]
+ldptr.d $a1, $s6, 244
+
+# CHECK64-ASM: stptr.w $s5, $a1, 216
+# CHECK64-ASM: encoding: [0xbc,0xd8,0x00,0x25]
+stptr.w $s5, $a1, 216
+
+# CHECK64-ASM: stptr.d $t2, $s1, 196
+# CHECK64-ASM: encoding: [0x0e,0xc7,0x00,0x27]
+stptr.d $t2, $s1, 196
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/misc.s b/llvm/test/MC/LoongArch/Basic/Integer/misc.s
new file mode 100644
index 0000000000000..7ed934bd04d66
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/misc.s
@@ -0,0 +1,52 @@
+## Test valid misc instructions.
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM,CHECK64-ASM %s
+
+#############################################################
+## Instructions for both loongarch32 and loongarch64
+#############################################################
+
+# CHECK-ASM: syscall 100
+# CHECK-ASM: encoding: [0x64,0x00,0x2b,0x00]
+syscall 100
+
+# CHECK-ASM: break 199
+# CHECK-ASM: encoding: [0xc7,0x00,0x2a,0x00]
+break 199
+
+# CHECK-ASM: rdtimel.w $s1, $a0
+# CHECK-ASM: encoding: [0x98,0x60,0x00,0x00]
+rdtimel.w $s1, $a0
+
+# CHECK-ASM: rdtimeh.w $a7, $a1
+# CHECK-ASM: encoding: [0xab,0x64,0x00,0x00]
+rdtimeh.w $a7, $a1
+
+# CHECK-ASM: cpucfg $sp, $a4
+# CHECK-ASM: encoding: [0x03,0x6d,0x00,0x00]
+cpucfg $sp, $a4
+
+
+#############################################################
+## Instructions only for loongarch64
+#############################################################
+
+.ifdef LA64
+
+# CHECK64-ASM: asrtle.d $t0, $t5
+# CHECK64-ASM: encoding: [0x80,0x45,0x01,0x00]
+asrtle.d $t0, $t5
+
+# CHECK64-ASM: asrtgt.d $t8, $t8
+# CHECK64-ASM: encoding: [0x80,0xd2,0x01,0x00]
+asrtgt.d $t8, $t8
+
+# CHECK64-ASM: rdtime.d $tp, $t3
+# CHECK64-ASM: encoding: [0xe2,0x69,0x00,0x00]
+rdtime.d $tp, $t3
+
+.endif
+

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/pseudos.s b/llvm/test/MC/LoongArch/Basic/Integer/pseudos.s
new file mode 100644
index 0000000000000..1ace33f7131ae
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Integer/pseudos.s
@@ -0,0 +1,14 @@
+## Test valid pseudo instructions
+
+# RUN: llvm-mc %s --triple=loongarch32 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 -show-encoding \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+
+# CHECK-ASM: nop
+# CHECK-ASM: encoding: [0x00,0x00,0x40,0x03]
+nop
+
+# CHECK-ASM: move $a4, $a5
+# CHECK-ASM: encoding: [0x28,0x01,0x15,0x00]
+move $a4, $a5

diff  --git a/llvm/test/MC/LoongArch/Directives/cfi.s b/llvm/test/MC/LoongArch/Directives/cfi.s
new file mode 100644
index 0000000000000..7101fc9072906
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Directives/cfi.s
@@ -0,0 +1,34 @@
+## Test cfi directives.
+
+# RUN: llvm-mc %s --triple=loongarch32 | FileCheck %s
+# RUN: llvm-mc %s --triple=loongarch64 | FileCheck %s
+# RUN: not llvm-mc --triple=loongarch32 --defsym=ERR=1 < %s 2>&1 \
+# RUN:     | FileCheck %s --check-prefix=CHECK-ERR
+# RUN: not llvm-mc --triple=loongarch64 --defsym=ERR=1 < %s 2>&1 \
+# RUN:     | FileCheck %s --check-prefix=CHECK-ERR
+
+# CHECK: .cfi_startproc
+.cfi_startproc
+# CHECK-NEXT: .cfi_offset 0, 0
+.cfi_offset 0, 0
+# CHECK-NEXT: .cfi_offset 9, 8
+.cfi_offset 9, 8
+# CHECK-NEXT: .cfi_offset 31, 16
+.cfi_offset 31, 16
+# CHECK-NEXT: .cfi_endproc
+.cfi_endproc
+
+.ifdef ERR
+.cfi_startproc
+# CHECK-ERR: :[[#@LINE+1]]:13: error: invalid register number
+.cfi_offset -22, -8
+# CHECK-ERR: :[[#@LINE+1]]:13: error: invalid register number
+.cfi_offset fp, -8
+# CHECK-ERR: :[[#@LINE+1]]:13: error: invalid register number
+.cfi_offset $22, -8
+# CHECK-ERR: :[[#@LINE+1]]:13: error: invalid register number
+.cfi_offset $r22, -8
+# CHECK-ERR: :[[#@LINE+1]]:13: error: invalid register number
+.cfi_offset $fp, -8
+.cfi_endproc
+.endif

diff  --git a/llvm/test/MC/LoongArch/Directives/data.s b/llvm/test/MC/LoongArch/Directives/data.s
new file mode 100644
index 0000000000000..e3c66d10b18a0
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Directives/data.s
@@ -0,0 +1,102 @@
+## Test data directives.
+# RUN: llvm-mc --triple=loongarch32 < %s \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc --triple=loongarch64 < %s \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM %s
+# RUN: llvm-mc --triple=loongarch32 --filetype=obj < %s | llvm-objdump -s - \
+# RUN:     | FileCheck --check-prefix=CHECK-DATA %s
+# RUN: llvm-mc --triple=loongarch64 --filetype=obj < %s | llvm-objdump -s - \
+# RUN:     | FileCheck --check-prefix=CHECK-DATA %s
+# RUN: not llvm-mc --triple=loongarch32 --defsym=ERR=1 < %s 2>&1 \
+# RUN:     | FileCheck %s --check-prefix=CHECK-ERR
+# RUN: not llvm-mc --triple=loongarch64 --defsym=ERR=1 < %s 2>&1 \
+# RUN:     | FileCheck %s --check-prefix=CHECK-ERR
+
+.data
+
+# CHECK-ASM:      .byte 0
+# CHECK-ASM-NEXT: .byte 1
+# CHECK-ASM-NEXT: .byte 171
+# CHECK-ASM-NEXT: .byte 255
+# CHECK-DATA: Contents of section .data:
+# CHECK-DATA-NEXT: 0000 0001abff 0100ffff 0100ffff 0100ffff
+.byte 0
+.byte 1
+.byte 0xab
+.byte 0xff
+
+# CHECK-ASM:      .half 1
+# CHECK-ASM-NEXT: .half 65535
+.half 0x1
+.half 0xffff
+
+# CHECK-ASM:      .half 1
+# CHECK-ASM-NEXT: .half 65535
+.2byte 0x1
+.2byte 0xffff
+
+# CHECK-ASM:      .half 1
+# CHECK-ASM-NEXT: .half 65535
+.short 0x1
+.short 0xffff
+
+# CHECK-ASM:      .half 0
+# CHECK-ASM-NEXT: .half 1
+# CHECK-ASM-NEXT: .half 4660
+# CHECK-ASM-NEXT: .half 65535
+# CHECK-DATA-NEXT: 0010 00000100 3412ffff 01000000 ffffffff
+.hword 0
+.hword 0x1
+.hword 0x1234
+.hword 0xffff
+
+# CHECK-ASM:      .word 1
+# CHECK-ASM-NEXT: .word 4294967295
+.word 0x1
+.word 0xffffffff
+
+# CHECK-ASM:      .word 1
+# CHECK-ASM-NEXT: .word 4294967295
+# CHECK-DATA-NEXT: 0020 01000000 ffffffff 01000000 ffffffff
+.long 0x1
+.long 0xffffffff
+
+# CHECK-ASM:      .word 1
+# CHECK-ASM-NEXT: .word 4294967295
+.4byte 0x1
+.4byte 0xffffffff
+
+# CHECK-ASM:      .dword 1
+# CHECK-ASM-NEXT: .dword 1234605616436508552
+# CHECK-DATA-NEXT: 0030 01000000 00000000 88776655 44332211
+.dword 0x1
+.dword 0x1122334455667788
+
+# CHECK-ASM:      .dword 1
+# CHECK-ASM-NEXT: .dword 1234605616436508552
+# CHECK-DATA-NEXT: 0040 01000000 00000000 88776655 44332211
+.8byte 0x1
+.8byte 0x1122334455667788
+
+.ifdef ERR
+# CHECK-ERR: :[[#@LINE+1]]:7: error: out of range literal value
+.byte 0xffa
+# CHECK-ERR: :[[#@LINE+1]]:7: error: out of range literal value
+.half 0xffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: out of range literal value
+.short 0xffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: out of range literal value
+.hword 0xffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: out of range literal value
+.2byte 0xffffa
+# CHECK-ERR: :[[#@LINE+1]]:7: error: out of range literal value
+.word 0xffffffffa
+# CHECK-ERR: :[[#@LINE+1]]:7: error: out of range literal value
+.long 0xffffffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: out of range literal value
+.4byte 0xffffffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: literal value out of range for directive
+.dword 0xffffffffffffffffa
+# CHECK-ERR: :[[#@LINE+1]]:8: error: literal value out of range for directive
+.8byte 0xffffffffffffffffa
+.endif

diff  --git a/llvm/test/MC/LoongArch/lit.local.cfg b/llvm/test/MC/LoongArch/lit.local.cfg
new file mode 100644
index 0000000000000..2b5a4893e686f
--- /dev/null
+++ b/llvm/test/MC/LoongArch/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'LoongArch' in config.root.targets:
+    config.unsupported = True


        


More information about the llvm-commits mailing list