// 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/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchInstPrinter.h"
#include "MCTargetDesc/LoongArchMCExpr.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "MCTargetDesc/LoongArchMatInt.h"
#include "MCTargetDesc/LoongArchTargetStreamer.h"
#include "TargetInfo/LoongArchTargetInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstBuilder.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/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"

using namespace llvm;

#define DEBUG_TYPE "loongarch-asm-parser"

namespace {
class LoongArchAsmParser : public MCTargetAsmParser {
  SmallVector<FeatureBitset, 4> FeatureBitStack;

  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
  bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
  LoongArchTargetStreamer &getTargetStreamer() {
    assert(getParser().getStreamer().getTargetStreamer() &&
           "do not have a target streamer");
    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
    return static_cast<LoongArchTargetStreamer &>(TS);
  }

  struct Inst {
    unsigned Opc;
    LoongArchMCExpr::VariantKind VK;
    Inst(unsigned Opc,
         LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None)
        : Opc(Opc), VK(VK) {}
  };
  using InstSeq = SmallVector<Inst>;

  /// Parse a register as used in CFI directives.
  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
                               SMLoc &EndLoc) override;

  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
                        SMLoc NameLoc, OperandVector &Operands) override;

  bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                               OperandVector &Operands, MCStreamer &Out,
                               uint64_t &ErrorInfo,
                               bool MatchingInlineAsm) override;

  unsigned checkTargetMatchPredicate(MCInst &Inst) override;

  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                      unsigned Kind) override;

  ParseStatus parseDirective(AsmToken DirectiveID) override;

  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
                                  int64_t Lower, int64_t Upper,
                                  const 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"

  ParseStatus parseRegister(OperandVector &Operands);
  ParseStatus parseImmediate(OperandVector &Operands);
  ParseStatus parseOperandWithModifier(OperandVector &Operands);
  ParseStatus parseSImm26Operand(OperandVector &Operands);
  ParseStatus parseAtomicMemOp(OperandVector &Operands);

  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);

  bool parseDirectiveOption();

  void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
    if (!(getSTI().hasFeature(Feature))) {
      MCSubtargetInfo &STI = copySTI();
      setAvailableFeatures(
          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
    }
  }

  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
    if (getSTI().hasFeature(Feature)) {
      MCSubtargetInfo &STI = copySTI();
      setAvailableFeatures(
          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
    }
  }

  void pushFeatureBits() {
    FeatureBitStack.push_back(getSTI().getFeatureBits());
  }

  bool popFeatureBits() {
    if (FeatureBitStack.empty())
      return true;

    FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
    copySTI().setFeatureBits(FeatureBits);
    setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));

    return false;
  }

  // Helper to emit the sequence of instructions generated by the
  // "emitLoadAddress*" functions.
  void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                     const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
                     SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);

  // Helper to emit pseudo instruction "la.abs $rd, sym".
  void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.pcrel $rd, sym".
  void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
  void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.got $rd, sym".
  void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
  void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.tls.le $rd, sym".
  void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
  void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
  void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
  void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
  void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
  void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
  void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
  void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
  // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
  void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "li.w/d $rd, $imm".
  void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

  // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
  void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
                      bool IsTailCall);

public:
  enum LoongArchMatchResultTy {
    Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
    Match_RequiresMsbNotLessThanLsb,
    Match_RequiresOpnd2NotR0R1,
    Match_RequiresAMORdDifferRkRj,
    Match_RequiresLAORdDifferRj,
    Match_RequiresLAORdR4,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "LoongArchGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
  };

  static bool classifySymbolRef(const MCExpr *Expr,
                                LoongArchMCExpr::VariantKind &Kind);

  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()));
  }
};

// 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; }
  void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
  bool isGPR() const {
    return Kind == KindTy::Register &&
           LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
               Reg.RegNum);
  }

  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
                                  LoongArchMCExpr::VariantKind &VK) {
    if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
      VK = LE->getKind();
      return false;
    }

    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;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    return IsConstantImm && isUInt<N>(Imm - P) &&
           VK == LoongArchMCExpr::VK_LoongArch_None;
  }

  template <unsigned N, unsigned S = 0> bool isSImm() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    return IsConstantImm && isShiftedInt<N, S>(Imm) &&
           VK == LoongArchMCExpr::VK_LoongArch_None;
  }

  bool isBareSymbol() const {
    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    // Must be of 'immediate' type but not a constant.
    if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
      return false;
    return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
           VK == LoongArchMCExpr::VK_LoongArch_None;
  }

  bool isTPRelAddSymbol() const {
    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    // Must be of 'immediate' type but not a constant.
    if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
      return false;
    return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
           VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
  }

  bool isUImm1() const { return isUImm<1>(); }
  bool isUImm2() const { return isUImm<2>(); }
  bool isUImm2plus1() const { return isUImm<2, 1>(); }
  bool isUImm3() const { return isUImm<3>(); }
  bool isUImm4() const { return isUImm<4>(); }
  bool isSImm5() const { return isSImm<5>(); }
  bool isUImm5() const { return isUImm<5>(); }
  bool isUImm6() const { return isUImm<6>(); }
  bool isUImm7() const { return isUImm<7>(); }
  bool isSImm8() const { return isSImm<8>(); }
  bool isSImm8lsl1() const { return isSImm<8, 1>(); }
  bool isSImm8lsl2() const { return isSImm<8, 2>(); }
  bool isSImm8lsl3() const { return isSImm<8, 3>(); }
  bool isUImm8() const { return isUImm<8>(); }
  bool isSImm9lsl3() const { return isSImm<9, 3>(); }
  bool isSImm10() const { return isSImm<10>(); }
  bool isSImm10lsl2() const { return isSImm<10, 2>(); }
  bool isSImm11lsl1() const { return isSImm<11, 1>(); }
  bool isSImm12() const { return isSImm<12>(); }

  bool isSImm12addlike() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
    return IsConstantImm
               ? isInt<12>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm12lu52id() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
    return IsConstantImm
               ? isInt<12>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isUImm12() const { return isUImm<12>(); }

  bool isUImm12ori() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12;
    return IsConstantImm
               ? isUInt<12>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm13() const { return isSImm<13>(); }
  bool isUImm14() const { return isUImm<14>(); }
  bool isUImm15() const { return isUImm<15>(); }

  bool isSImm14lsl2() const { return isSImm<14, 2>(); }
  bool isSImm16() const { return isSImm<16>(); }

  bool isSImm16lsl2() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_B16 ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
    return IsConstantImm
               ? isShiftedInt<16, 2>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm20() const { return isSImm<20>(); }

  bool isSImm20pcalau12i() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
    return IsConstantImm
               ? isInt<20>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm20lu12iw() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
    return IsConstantImm
               ? isInt<20>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm20lu32id() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20;

    return IsConstantImm
               ? isInt<20>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm20pcaddu18i() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_CALL36;

    return IsConstantImm
               ? isInt<20>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm20pcaddi() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_PCREL20_S2 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 ||
                       VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2;
    return IsConstantImm
               ? isInt<20>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm21lsl2() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_B21;
    return IsConstantImm
               ? isShiftedInt<21, 2>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isSImm26Operand() const {
    if (!isImm())
      return false;

    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
                       VK == LoongArchMCExpr::VK_LoongArch_CALL ||
                       VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
                       VK == LoongArchMCExpr::VK_LoongArch_B26;
    return IsConstantImm
               ? isShiftedInt<26, 2>(Imm) && IsValidKind
               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
                     IsValidKind;
  }

  bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
  bool isImm64() const {
    if (!isImm())
      return false;
    int64_t Imm;
    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
    return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
  }

  /// 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; }

  MCRegister getReg() const override {
    assert(Kind == KindTy::Register && "Invalid type access!");
    return Reg.RegNum;
  }

  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 = [](MCRegister 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(MCRegister Reg, SMLoc S,
                                                     SMLoc E) {
    auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
    Op->Reg.RegNum = Reg;
    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 namespace

#define GET_REGISTER_MATCHER
#define GET_SUBTARGET_FEATURE_NAME
#define GET_MATCHER_IMPLEMENTATION
#define GET_MNEMONIC_SPELL_CHECKER
#include "LoongArchGenAsmMatcher.inc"

static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
  assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
  return Reg - LoongArch::F0 + LoongArch::F0_64;
}

// Attempts to match Name as a register (either using the default name or
// alternative ABI names), setting RegNo to the matching register. Upon
// failure, returns true and sets RegNo to 0.
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
  RegNo = MatchRegisterName(Name);
  // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
  // match always matches the 32-bit variant, and not the 64-bit one.
  assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
  // The default FPR register class is based on the tablegen enum ordering.
  static_assert(LoongArch::F0 < LoongArch::F0_64,
                "FPR matching must be updated");
  if (RegNo == LoongArch::NoRegister)
    RegNo = MatchRegisterAltName(Name);

  return RegNo == LoongArch::NoRegister;
}

bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
                                       SMLoc &EndLoc) {
  if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
    return Error(getLoc(), "invalid register name");

  if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
      !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
    return Error(getLoc(), "invalid register name");

  return false;
}

ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
                                                 SMLoc &StartLoc,
                                                 SMLoc &EndLoc) {
  const AsmToken &Tok = getParser().getTok();
  StartLoc = Tok.getLoc();
  EndLoc = Tok.getEndLoc();

  parseOptionalToken(AsmToken::Dollar);
  if (getLexer().getKind() != AsmToken::Identifier)
    return ParseStatus::NoMatch;

  StringRef Name = Tok.getIdentifier();
  if (matchRegisterNameHelper(Reg, Name))
    return ParseStatus::NoMatch;

  getParser().Lex(); // Eat identifier token.
  return ParseStatus::Success;
}

bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
                                           LoongArchMCExpr::VariantKind &Kind) {
  Kind = LoongArchMCExpr::VK_LoongArch_None;

  if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
    Kind = RE->getKind();
    Expr = RE->getSubExpr();
  }

  MCValue Res;
  if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
    return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;
  return false;
}

ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
  if (!parseOptionalToken(AsmToken::Dollar))
    return ParseStatus::NoMatch;
  if (getLexer().getKind() != AsmToken::Identifier)
    return ParseStatus::NoMatch;

  StringRef Name = getLexer().getTok().getIdentifier();
  MCRegister RegNo;
  matchRegisterNameHelper(RegNo, Name);
  if (RegNo == LoongArch::NoRegister)
    return ParseStatus::NoMatch;

  SMLoc S = getLoc();
  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
  getLexer().Lex();
  Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));

  return ParseStatus::Success;
}

ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
  SMLoc S = getLoc();
  SMLoc E;
  const MCExpr *Res;

  switch (getLexer().getKind()) {
  default:
    return ParseStatus::NoMatch;
  case AsmToken::LParen:
  case AsmToken::Dot:
  case AsmToken::Minus:
  case AsmToken::Plus:
  case AsmToken::Exclaim:
  case AsmToken::Tilde:
  case AsmToken::Integer:
  case AsmToken::String:
  case AsmToken::Identifier:
    if (getParser().parseExpression(Res, E))
      return ParseStatus::Failure;
    break;
  case AsmToken::Percent:
    return parseOperandWithModifier(Operands);
  }

  Operands.push_back(LoongArchOperand::createImm(Res, S, E));
  return ParseStatus::Success;
}

ParseStatus
LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
  SMLoc S = getLoc();
  SMLoc E;

  if (getLexer().getKind() != AsmToken::Percent)
    return Error(getLoc(), "expected '%' for operand modifier");

  getParser().Lex(); // Eat '%'

  if (getLexer().getKind() != AsmToken::Identifier)
    return Error(getLoc(), "expected valid identifier for operand modifier");
  StringRef Identifier = getParser().getTok().getIdentifier();
  LoongArchMCExpr::VariantKind VK =
      LoongArchMCExpr::getVariantKindForName(Identifier);
  if (VK == LoongArchMCExpr::VK_LoongArch_Invalid)
    return Error(getLoc(), "unrecognized operand modifier");

  getParser().Lex(); // Eat the identifier
  if (getLexer().getKind() != AsmToken::LParen)
    return Error(getLoc(), "expected '('");
  getParser().Lex(); // Eat '('

  const MCExpr *SubExpr;
  if (getParser().parseParenExpression(SubExpr, E))
    return ParseStatus::Failure;

  const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
  Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
  return ParseStatus::Success;
}

ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
  SMLoc S = getLoc();
  const MCExpr *Res;

  if (getLexer().getKind() == AsmToken::Percent)
    return parseOperandWithModifier(Operands);

  if (getLexer().getKind() != AsmToken::Identifier)
    return ParseStatus::NoMatch;

  StringRef Identifier;
  if (getParser().parseIdentifier(Identifier))
    return ParseStatus::Failure;

  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());

  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
  Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL,
                                getContext());
  Operands.push_back(LoongArchOperand::createImm(Res, S, E));
  return ParseStatus::Success;
}

ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
  // Parse "$r*".
  if (!parseRegister(Operands).isSuccess())
    return ParseStatus::NoMatch;

  // If there is a next operand and it is 0, ignore it. Otherwise print a
  // diagnostic message.
  if (parseOptionalToken(AsmToken::Comma)) {
    int64_t ImmVal;
    SMLoc ImmStart = getLoc();
    if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
      return ParseStatus::Failure;
    if (ImmVal)
      return Error(ImmStart, "optional integer offset must be 0");
  }

  return ParseStatus::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) {
  // Check if the current operand has a custom associated parser, if so, try to
  // custom parse the operand, or fallback to the general approach.
  ParseStatus Result =
      MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
  if (Result.isSuccess())
    return false;
  if (Result.isFailure())
    return true;

  if (parseRegister(Operands).isSuccess() ||
      parseImmediate(Operands).isSuccess())
    return false;

  // Finally we have exhausted all options and must declare defeat.
  return Error(getLoc(), "unknown operand");
}

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");
}

void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                                       const MCExpr *Symbol,
                                       SmallVectorImpl<Inst> &Insts,
                                       SMLoc IDLoc, MCStreamer &Out,
                                       bool RelaxHint) {
  MCContext &Ctx = getContext();
  for (LoongArchAsmParser::Inst &Inst : Insts) {
    unsigned Opc = Inst.Opc;
    LoongArchMCExpr::VariantKind VK = Inst.VK;
    const LoongArchMCExpr *LE =
        LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
    switch (Opc) {
    default:
      llvm_unreachable("unexpected opcode");
    case LoongArch::PCALAU12I:
    case LoongArch::LU12I_W:
      Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
                          getSTI());
      break;
    case LoongArch::ORI:
    case LoongArch::ADDI_W:
    case LoongArch::LD_W:
    case LoongArch::LD_D: {
      if (VK == LoongArchMCExpr::VK_LoongArch_None) {
        Out.emitInstruction(
            MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
            getSTI());
        continue;
      } else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) {
        Out.emitInstruction(MCInstBuilder(Opc)
                                .addReg(LoongArch::R1)
                                .addReg(DestReg)
                                .addExpr(LE),
                            getSTI());
        continue;
      }
      Out.emitInstruction(
          MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
          getSTI());
      break;
    }
    case LoongArch::LU32I_D:
      Out.emitInstruction(MCInstBuilder(Opc)
                              .addReg(DestReg == TmpReg ? DestReg : TmpReg)
                              .addReg(DestReg == TmpReg ? DestReg : TmpReg)
                              .addExpr(LE),
                          getSTI());
      break;
    case LoongArch::LU52I_D:
      Out.emitInstruction(
          MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
          getSTI());
      break;
    case LoongArch::ADDI_D:
      Out.emitInstruction(
          MCInstBuilder(Opc)
              .addReg(TmpReg)
              .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
              .addExpr(LE),
          getSTI());
      break;
    case LoongArch::ADD_D:
    case LoongArch::LDX_D:
      Out.emitInstruction(
          MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
          getSTI());
      break;
    case LoongArch::JIRL:
      Out.emitInstruction(MCInstBuilder(Opc)
                              .addReg(LoongArch::R1)
                              .addReg(LoongArch::R1)
                              .addExpr(LE),
                          getSTI());
      break;
    }
  }
}

void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
                                            MCStreamer &Out) {
  // la.abs $rd, sym
  // expands to:
  //   lu12i.w $rd, %abs_hi20(sym)
  //   ori     $rd, $rd, %abs_lo12(sym)
  //
  // for 64bit appends:
  //   lu32i.d $rd, %abs64_lo20(sym)
  //   lu52i.d $rd, $rd, %abs64_hi12(sym)
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
                             ? Inst.getOperand(1).getExpr()
                             : Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12));

  if (is64Bit()) {
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
  }

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
                                              MCStreamer &Out) {
  // la.pcrel $rd, sym
  // expands to:
  //   pcalau12i $rd, %pc_hi20(sym)
  //   addi.w/d  $rd, rd, %pc_lo12(sym)
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;
  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
  Insts.push_back(
      LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
                                                   MCStreamer &Out) {
  // la.pcrel $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %pc_hi20(sym)
  //   addi.d    $rj, $r0, %pc_lo12(sym)
  //   lu32i.d   $rj, %pc64_lo20(sym)
  //   lu52i.d   $rj, $rj, %pc64_hi12(sym)
  //   add.d     $rd, $rd, $rj
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
                                            MCStreamer &Out) {
  // la.got $rd, sym
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;
  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
    // with feature: +la-glabal-with-abs
    // for 32bit:
    //   lu12i.w $rd, %got_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //   ld.w    $rd, $rd, 0
    //
    // for 64bit:
    //   lu12i.w $rd, %got_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //   lu32i.d $rd, %got64_lo20(sym)
    //   lu52i.d $rd, $rd, %got64_hi12(sym)
    //   ld.d    $rd, $rd, 0
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_GOT_HI20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

    if (is64Bit()) {
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
    }
    Insts.push_back(LoongArchAsmParser::Inst(LD));
    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
    return;
  }
  // expands to:
  //   pcalau12i $rd, %got_pc_hi20(sym)
  //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
  Insts.push_back(
      LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
                                                 MCStreamer &Out) {
  // la.got $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %got_pc_hi20(sym)
  //   addi.d    $rj, $r0, %got_pc_lo12(sym)
  //   lu32i.d   $rj, %got64_pc_lo20(sym)
  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
  //   ldx.d     $rd, $rd, $rj
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
                                              MCStreamer &Out) {
  // la.tls.le $rd, sym
  // expands to:
  //   lu12i.w $rd, %le_hi20(sym)
  //   ori     $rd, $rd, %le_lo12(sym)
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
                                              MCStreamer &Out) {
  // la.tls.ie $rd, sym
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;
  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;

  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
    // with feature: +la-glabal-with-abs
    // for 32bit:
    //   lu12i.w $rd, %ie_hi20(sym)
    //   ori     $rd, $rd, %ie_lo12(sym)
    //   ld.w    $rd, $rd, 0
    //
    // for 64bit:
    //   lu12i.w $rd, %ie_hi20(sym)
    //   ori     $rd, $rd, %ie_lo12(sym)
    //   lu32i.d $rd, %ie64_lo20(sym)
    //   lu52i.d $rd, $rd, %ie64_hi12(sym)
    //   ld.d    $rd, $rd, 0
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12));

    if (is64Bit()) {
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20));
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12));
    }
    Insts.push_back(LoongArchAsmParser::Inst(LD));
    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
    return;
  }

  // expands to:
  //   pcalau12i $rd, %ie_pc_hi20(sym)
  //   ld.w/d    $rd, $rd, %ie_pc_lo12(sym)
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
                                                   MCStreamer &Out) {
  // la.tls.ie $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %ie_pc_hi20(sym)
  //   addi.d    $rj, $r0, %ie_pc_lo12(sym)
  //   lu32i.d   $rj, %ie64_pc_lo20(sym)
  //   lu52i.d   $rj, $rj, %ie64_pc_hi12(sym)
  //   ldx.d     $rd, $rd, $rj
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
                                              MCStreamer &Out) {
  // la.tls.ld $rd, sym
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;
  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
    // with feature: +la-glabal-with-abs
    // for 32bit:
    //   lu12i.w $rd, %ld_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //
    // for 64bit:
    //   lu12i.w $rd, %ld_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //   lu32i.d $rd, %got64_lo20(sym)
    //   lu52i.d $rd, $rd, %got64_hi12(sym)
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

    if (is64Bit()) {
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
    }
    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
    return;
  }

  // expands to:
  //   pcalau12i $rd, %ld_pc_hi20(sym)
  //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
                                                   MCStreamer &Out) {
  // la.tls.ld $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %ld_pc_hi20(sym)
  //   addi.d    $rj, $r0, %got_pc_lo12(sym)
  //   lu32i.d   $rj, %got64_pc_lo20(sym)
  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
  //   add.d     $rd, $rd, $rj
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
                                              MCStreamer &Out) {
  // la.tls.gd $rd, sym
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  InstSeq Insts;
  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
    // with feature: +la-glabal-with-abs
    // for 32bit:
    //   lu12i.w $rd, %gd_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //
    // for 64bit:
    //   lu12i.w $rd, %gd_hi20(sym)
    //   ori     $rd, $rd, %got_lo12(sym)
    //   lu32i.d $rd, %got64_lo20(sym)
    //   lu52i.d $rd, $rd, %got64_hi12(sym)
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));

    if (is64Bit()) {
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
    }
    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
    return;
  }

  // expands to:
  //   pcalau12i $rd, %gd_pc_hi20(sym)
  //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
                                                   MCStreamer &Out) {
  // la.tls.gd $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %gd_pc_hi20(sym)
  //   addi.d    $rj, $r0, %got_pc_lo12(sym)
  //   lu32i.d   $rj, %got64_pc_lo20(sym)
  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
  //   add.d     $rd, $rd, $rj
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
                                                MCStreamer &Out) {
  // la.tls.desc $rd, sym
  MCRegister DestReg = Inst.getOperand(0).getReg();
  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
  InstSeq Insts;

  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
    // with feature: +la-glabal-with-abs
    // for la32 expands to:
    //   lu12i.w $rd, %desc_hi20(sym)
    //   ori     $rd, $rd, %desc_lo12(sym)
    //   ld.w    $ra, $rd, %desc_ld(sym)
    //   jirl    $ra, $ra, %desc_call(sym)
    //
    // for la64 expands to:
    //   lu12i.w $rd, %desc_hi20(sym)
    //   ori     $rd, $rd, %desc_lo12(sym)
    //   lu32i.d $rd, %desc64_lo20(sym)
    //   lu52i.d $rd, $rd, %desc64_hi12(sym)
    //   ld.d    $ra, $rd, %desc_ld(sym)
    //   jirl    $ra, $ra, %desc_call(sym)
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));

    if (is64Bit()) {
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
      Insts.push_back(LoongArchAsmParser::Inst(
          LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
    }

    Insts.push_back(LoongArchAsmParser::Inst(
        LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
    Insts.push_back(LoongArchAsmParser::Inst(
        LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));

    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
    return;
  }

  // expands to:
  //   pcalau12i $rd, %desc_pc_hi20(sym)
  //   addi.w/d  $rd, $rd, %desc_pc_lo12(sym)
  //   ld.w/d    $ra, $rd, %desc_ld(sym)
  //   jirl      $ra, $ra, %desc_call(sym)
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
  Insts.push_back(
      LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));

  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                /*RelaxHint=*/true);
}

void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
                                                     MCStreamer &Out) {
  // la.tls.desc $rd, $rj, sym
  // expands to:
  //   pcalau12i $rd, %desc_pc_hi20(sym)
  //   addi.d    $rj, $r0, %desc_pc_lo12(sym)
  //   lu32i.d   $rj, %desc64_pc_lo20(sym)
  //   lu52i.d   $rj, $rj, %desc64_pc_hi12(sym)
  //   add.d     $rd, $rd, $rj
  //   ld.w/d    $ra, $rd, %desc_ld(sym)
  //   jirl      $ra, $ra, %desc_call(sym)
  MCRegister DestReg = Inst.getOperand(0).getReg();
  MCRegister TmpReg = Inst.getOperand(1).getReg();
  const MCExpr *Symbol = Inst.getOperand(2).getExpr();
  InstSeq Insts;

  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12));
  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
  Insts.push_back(LoongArchAsmParser::Inst(
      LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));

  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}

void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
                                     MCStreamer &Out) {
  MCRegister DestReg = Inst.getOperand(0).getReg();
  int64_t Imm = Inst.getOperand(1).getImm();
  MCRegister SrcReg = LoongArch::R0;

  if (Inst.getOpcode() == LoongArch::PseudoLI_W)
    Imm = SignExtend64<32>(Imm);

  for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
    switch (Inst.Opc) {
    case LoongArch::LU12I_W:
      Out.emitInstruction(
          MCInstBuilder(Inst.Opc).addReg(DestReg).addImm(Inst.Imm), getSTI());
      break;
    case LoongArch::ADDI_W:
    case LoongArch::ORI:
    case LoongArch::LU32I_D:
    case LoongArch::LU52I_D:
      Out.emitInstruction(
          MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
              Inst.Imm),
          getSTI());
      break;
    case LoongArch::BSTRINS_D:
      Out.emitInstruction(MCInstBuilder(Inst.Opc)
                              .addReg(DestReg)
                              .addReg(SrcReg)
                              .addReg(SrcReg)
                              .addImm(Inst.Imm >> 32)
                              .addImm(Inst.Imm & 0xFF),
                          getSTI());
      break;
    default:
      llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
    }
    SrcReg = DestReg;
  }
}

void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
                                        MCStreamer &Out, bool IsTailCall) {
  // call36 sym
  // expands to:
  //   pcaddu18i $ra, %call36(sym)
  //   jirl      $ra, $ra, 0
  //
  // tail36 $rj, sym
  // expands to:
  //   pcaddu18i $rj, %call36(sym)
  //   jirl      $r0, $rj, 0
  MCRegister ScratchReg =
      IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
  const MCExpr *Sym =
      IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
  const LoongArchMCExpr *LE =
      LoongArchMCExpr::create(Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36,
                              getContext(), /*RelaxHint=*/true);

  Out.emitInstruction(
      MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
      getSTI());
  Out.emitInstruction(
      MCInstBuilder(LoongArch::JIRL)
          .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
          .addReg(ScratchReg)
          .addImm(0),
      getSTI());
}

bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
                                            OperandVector &Operands,
                                            MCStreamer &Out) {
  Inst.setLoc(IDLoc);
  switch (Inst.getOpcode()) {
  default:
    break;
  case LoongArch::PseudoLA_ABS:
  case LoongArch::PseudoLA_ABS_LARGE:
    emitLoadAddressAbs(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_PCREL:
    emitLoadAddressPcrel(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_PCREL_LARGE:
    emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_GOT:
    emitLoadAddressGot(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_GOT_LARGE:
    emitLoadAddressGotLarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_LE:
    emitLoadAddressTLSLE(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_IE:
    emitLoadAddressTLSIE(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_IE_LARGE:
    emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_LD:
    emitLoadAddressTLSLD(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_LD_LARGE:
    emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_GD:
    emitLoadAddressTLSGD(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_GD_LARGE:
    emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_DESC:
    emitLoadAddressTLSDesc(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLA_TLS_DESC_LARGE:
    emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoLI_W:
  case LoongArch::PseudoLI_D:
    emitLoadImm(Inst, IDLoc, Out);
    return false;
  case LoongArch::PseudoCALL36:
    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
    return false;
  case LoongArch::PseudoTAIL36:
    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
    return false;
  }
  Out.emitInstruction(Inst, getSTI());
  return false;
}

unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
  unsigned Opc = Inst.getOpcode();
  const MCInstrDesc &MCID = MII.get(Opc);
  switch (Opc) {
  default:
    if (LoongArchII::isSubjectToAMORdConstraint(MCID.TSFlags)) {
      const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);
      MCRegister Rd = Inst.getOperand(0).getReg();
      MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();
      MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();
      if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
        return Match_RequiresAMORdDifferRkRj;
    }
    break;
  case LoongArch::PseudoLA_TLS_DESC:
  case LoongArch::PseudoLA_TLS_DESC_LARGE: {
    MCRegister Rd = Inst.getOperand(0).getReg();
    if (Rd != LoongArch::R4)
      return Match_RequiresLAORdR4;
    break;
  }
  case LoongArch::PseudoLA_PCREL_LARGE:
  case LoongArch::PseudoLA_GOT_LARGE:
  case LoongArch::PseudoLA_TLS_IE_LARGE:
  case LoongArch::PseudoLA_TLS_LD_LARGE:
  case LoongArch::PseudoLA_TLS_GD_LARGE: {
    MCRegister Rd = Inst.getOperand(0).getReg();
    MCRegister Rj = Inst.getOperand(1).getReg();
    if (Rd == Rj)
      return Match_RequiresLAORdDifferRj;
    break;
  }
  case LoongArch::CSRXCHG:
  case LoongArch::GCSRXCHG: {
    MCRegister Rj = Inst.getOperand(2).getReg();
    if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
      return Match_RequiresOpnd2NotR0R1;
    return Match_Success;
  }
  case LoongArch::BSTRINS_W:
  case LoongArch::BSTRINS_D:
  case LoongArch::BSTRPICK_W:
  case LoongArch::BSTRPICK_D: {
    unsigned Opc = Inst.getOpcode();
    const signed Msb =
        (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
            ? Inst.getOperand(3).getImm()
            : Inst.getOperand(2).getImm();
    const signed Lsb =
        (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
            ? Inst.getOperand(4).getImm()
            : Inst.getOperand(3).getImm();
    if (Msb < Lsb)
      return Match_RequiresMsbNotLessThanLsb;
    return Match_Success;
  }
  }

  return Match_Success;
}

unsigned
LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
                                               unsigned Kind) {
  LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
  if (!Op.isReg())
    return Match_InvalidOperand;

  MCRegister Reg = Op.getReg();
  // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
  // register from FPR32 to FPR64 if necessary.
  if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
      Kind == MCK_FPR64) {
    Op.setReg(convertFPR32ToFPR64(Reg));
    return Match_Success;
  }

  if (Kind == MCK_GPRNoR0R1 && (Reg == LoongArch::R0 || Reg == LoongArch::R1))
    return Match_RequiresOpnd2NotR0R1;

  return Match_InvalidOperand;
}

bool LoongArchAsmParser::generateImmOutOfRangeError(
    OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
    const 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_RequiresMsbNotLessThanLsb: {
    SMLoc ErrorStart = Operands[3]->getStartLoc();
    return Error(ErrorStart, "msb is less than lsb",
                 SMRange(ErrorStart, Operands[4]->getEndLoc()));
  }
  case Match_RequiresOpnd2NotR0R1:
    return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
  case Match_RequiresAMORdDifferRkRj:
    return Error(Operands[1]->getStartLoc(),
                 "$rd must be different from both $rk and $rj");
  case Match_RequiresLAORdDifferRj:
    return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
  case Match_RequiresLAORdR4:
    return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
  case Match_InvalidUImm1:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 1) - 1);
  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_InvalidUImm4:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 4) - 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_InvalidUImm7:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 7) - 1);
  case Match_InvalidUImm8:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 8) - 1);
  case Match_InvalidUImm12:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 12) - 1);
  case Match_InvalidUImm12ori:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/0,
        /*Upper=*/(1 << 12) - 1,
        "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
        "integer in the range");
  case Match_InvalidUImm14:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 14) - 1);
  case Match_InvalidUImm15:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                      /*Upper=*/(1 << 15) - 1);
  case Match_InvalidSImm5:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
                                      /*Upper=*/(1 << 4) - 1);
  case Match_InvalidSImm8:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
                                      /*Upper=*/(1 << 7) - 1);
  case Match_InvalidSImm8lsl1:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
        "immediate must be a multiple of 2 in the range");
  case Match_InvalidSImm8lsl2:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
        "immediate must be a multiple of 4 in the range");
  case Match_InvalidSImm10:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
                                      /*Upper=*/(1 << 9) - 1);
  case Match_InvalidSImm8lsl3:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
        "immediate must be a multiple of 8 in the range");
  case Match_InvalidSImm9lsl3:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
        "immediate must be a multiple of 8 in the range");
  case Match_InvalidSImm10lsl2:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
        "immediate must be a multiple of 4 in the range");
  case Match_InvalidSImm11lsl1:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
        "immediate must be a multiple of 2 in the range");
  case Match_InvalidSImm12:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
                                      /*Upper=*/(1 << 11) - 1);
  case Match_InvalidSImm12addlike:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 11),
        /*Upper=*/(1 << 11) - 1,
        "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
        "in the range");
  case Match_InvalidSImm12lu52id:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 11),
        /*Upper=*/(1 << 11) - 1,
        "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
        "integer in the range");
  case Match_InvalidSImm13:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
                                      /*Upper=*/(1 << 12) - 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, /*Lower=*/-(1 << 15),
                                      /*Upper=*/(1 << 15) - 1);
  case Match_InvalidSImm16lsl2:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
        "operand must be a symbol with modifier (e.g. %b16) or an integer "
        "in the range");
  case Match_InvalidSImm20:
    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
                                      /*Upper=*/(1 << 19) - 1);
  case Match_InvalidSImm20lu12iw:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
        /*Upper=*/(1 << 19) - 1,
        "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
        "in the range");
  case Match_InvalidSImm20lu32id:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
        /*Upper=*/(1 << 19) - 1,
        "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
        "integer in the range");
  case Match_InvalidSImm20pcalau12i:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
        /*Upper=*/(1 << 19) - 1,
        "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
        "in the range");
  case Match_InvalidSImm20pcaddu18i:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
        /*Upper=*/(1 << 19) - 1,
        "operand must be a symbol with modifier (e.g. %call36) or an integer "
        "in the range");
  case Match_InvalidSImm20pcaddi:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
        /*Upper=*/(1 << 19) - 1,
        "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
        "in the range");
  case Match_InvalidSImm21lsl2:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
        "operand must be a symbol with modifier (e.g. %b21) or an integer "
        "in the range");
  case Match_InvalidSImm26Operand:
    return generateImmOutOfRangeError(
        Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
        "operand must be a bare symbol name or an immediate must be a multiple "
        "of 4 in the range");
  case Match_InvalidImm32: {
    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
    return Error(ErrorLoc, "operand must be a 32 bit immediate");
  }
  case Match_InvalidImm64: {
    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
    return Error(ErrorLoc, "operand must be a 64 bit immediate");
  }
  case Match_InvalidBareSymbol: {
    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
    return Error(ErrorLoc, "operand must be a bare symbol name");
  }
  case Match_InvalidTPRelAddSymbol: {
    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
    return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
  }
  }
  llvm_unreachable("Unknown match type detected!");
}

bool LoongArchAsmParser::parseDirectiveOption() {
  MCAsmParser &Parser = getParser();
  // Get the option token.
  AsmToken Tok = Parser.getTok();

  // At the moment only identifiers are supported.
  if (parseToken(AsmToken::Identifier, "expected identifier"))
    return true;

  StringRef Option = Tok.getIdentifier();

  if (Option == "push") {
    if (Parser.parseEOL())
      return true;

    getTargetStreamer().emitDirectiveOptionPush();
    pushFeatureBits();
    return false;
  }

  if (Option == "pop") {
    SMLoc StartLoc = Parser.getTok().getLoc();
    if (Parser.parseEOL())
      return true;

    getTargetStreamer().emitDirectiveOptionPop();
    if (popFeatureBits())
      return Error(StartLoc, ".option pop with no .option push");

    return false;
  }

  if (Option == "relax") {
    if (Parser.parseEOL())
      return true;

    getTargetStreamer().emitDirectiveOptionRelax();
    setFeatureBits(LoongArch::FeatureRelax, "relax");
    return false;
  }

  if (Option == "norelax") {
    if (Parser.parseEOL())
      return true;

    getTargetStreamer().emitDirectiveOptionNoRelax();
    clearFeatureBits(LoongArch::FeatureRelax, "relax");
    return false;
  }

  // Unknown option.
  Warning(Parser.getTok().getLoc(),
          "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
  Parser.eatToEndOfStatement();
  return false;
}

ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
  if (DirectiveID.getString() == ".option")
    return parseDirectiveOption();

  return ParseStatus::NoMatch;
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
  RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
  RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
}
