brintos

brintos / llvm-project-archived public Read only

0
0
Text · 71.8 KiB · 9b11201 Raw
1963 lines · cpp
1// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/LoongArchBaseInfo.h"10#include "MCTargetDesc/LoongArchInstPrinter.h"11#include "MCTargetDesc/LoongArchMCAsmInfo.h"12#include "MCTargetDesc/LoongArchMCTargetDesc.h"13#include "MCTargetDesc/LoongArchMatInt.h"14#include "MCTargetDesc/LoongArchTargetStreamer.h"15#include "TargetInfo/LoongArchTargetInfo.h"16#include "llvm/BinaryFormat/ELF.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCInstBuilder.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCParser/AsmLexer.h"21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"22#include "llvm/MC/MCParser/MCTargetAsmParser.h"23#include "llvm/MC/MCRegisterInfo.h"24#include "llvm/MC/MCStreamer.h"25#include "llvm/MC/MCSubtargetInfo.h"26#include "llvm/MC/MCValue.h"27#include "llvm/MC/TargetRegistry.h"28#include "llvm/Support/Casting.h"29#include "llvm/Support/Compiler.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "loongarch-asm-parser"34 35namespace {36class LoongArchAsmParser : public MCTargetAsmParser {37  SmallVector<FeatureBitset, 4> FeatureBitStack;38 39  SMLoc getLoc() const { return getParser().getTok().getLoc(); }40  bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }41  LoongArchTargetStreamer &getTargetStreamer() {42    assert(getParser().getStreamer().getTargetStreamer() &&43           "do not have a target streamer");44    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();45    return static_cast<LoongArchTargetStreamer &>(TS);46  }47 48  struct Inst {49    unsigned Opc;50    uint16_t Specifier;51    Inst(unsigned Opc, uint16_t VK = 0) : Opc(Opc), Specifier(VK) {}52  };53  using InstSeq = SmallVector<Inst>;54 55  /// Parse a register as used in CFI directives.56  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;57  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,58                               SMLoc &EndLoc) override;59 60  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,61                        SMLoc NameLoc, OperandVector &Operands) override;62 63  bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,64                               OperandVector &Operands, MCStreamer &Out,65                               uint64_t &ErrorInfo,66                               bool MatchingInlineAsm) override;67 68  unsigned checkTargetMatchPredicate(MCInst &Inst) override;69 70  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,71                                      unsigned Kind) override;72 73  ParseStatus parseDirective(AsmToken DirectiveID) override;74 75  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,76                                  int64_t Lower, int64_t Upper,77                                  const Twine &Msg);78 79  /// Helper for processing MC instructions that have been successfully matched80  /// by matchAndEmitInstruction.81  bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,82                          MCStreamer &Out);83 84// Auto-generated instruction matching functions.85#define GET_ASSEMBLER_HEADER86#include "LoongArchGenAsmMatcher.inc"87 88  ParseStatus parseRegister(OperandVector &Operands);89  ParseStatus parseImmediate(OperandVector &Operands);90  ParseStatus parseOperandWithModifier(OperandVector &Operands);91  ParseStatus parseSImm26Operand(OperandVector &Operands);92  ParseStatus parseAtomicMemOp(OperandVector &Operands);93 94  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);95 96  bool parseDirectiveOption();97 98  void setFeatureBits(uint64_t Feature, StringRef FeatureString) {99    if (!(getSTI().hasFeature(Feature))) {100      MCSubtargetInfo &STI = copySTI();101      setAvailableFeatures(102          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));103    }104  }105 106  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {107    if (getSTI().hasFeature(Feature)) {108      MCSubtargetInfo &STI = copySTI();109      setAvailableFeatures(110          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));111    }112  }113 114  void pushFeatureBits() {115    FeatureBitStack.push_back(getSTI().getFeatureBits());116  }117 118  bool popFeatureBits() {119    if (FeatureBitStack.empty())120      return true;121 122    FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();123    copySTI().setFeatureBits(FeatureBits);124    setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));125 126    return false;127  }128 129  // Helper to emit the sequence of instructions generated by the130  // "emitLoadAddress*" functions.131  void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,132                     const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,133                     SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);134 135  // Helper to emit pseudo instruction "la.abs $rd, sym".136  void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);137 138  // Helper to emit pseudo instruction "la.pcrel $rd, sym".139  void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);140  // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".141  void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);142 143  // Helper to emit pseudo instruction "la.got $rd, sym".144  void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);145  // Helper to emit pseudo instruction "la.got $rd, $rj, sym".146  void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);147 148  // Helper to emit pseudo instruction "la.tls.le $rd, sym".149  void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);150 151  // Helper to emit pseudo instruction "la.tls.ie $rd, sym".152  void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);153  // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".154  void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);155 156  // Helper to emit pseudo instruction "la.tls.ld $rd, sym".157  void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);158  // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".159  void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);160 161  // Helper to emit pseudo instruction "la.tls.gd $rd, sym".162  void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);163  // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".164  void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);165 166  // Helper to emit pseudo instruction "la.tls.desc $rd, sym".167  void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);168  // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".169  void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);170 171  // Helper to emit pseudo instruction "li.w/d $rd, $imm".172  void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);173 174  // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".175  void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,176                      bool IsTailCall);177 178public:179  enum LoongArchMatchResultTy {180    Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,181    Match_RequiresMsbNotLessThanLsb,182    Match_RequiresOpnd2NotR0R1,183    Match_RequiresAMORdDifferRkRj,184    Match_RequiresLAORdDifferRj,185    Match_RequiresLAORdR4,186#define GET_OPERAND_DIAGNOSTIC_TYPES187#include "LoongArchGenAsmMatcher.inc"188#undef GET_OPERAND_DIAGNOSTIC_TYPES189  };190 191  static bool classifySymbolRef(const MCExpr *Expr,192                                LoongArchMCExpr::Specifier &Kind);193 194  LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,195                     const MCInstrInfo &MII, const MCTargetOptions &Options)196      : MCTargetAsmParser(Options, STI, MII) {197    Parser.addAliasForDirective(".half", ".2byte");198    Parser.addAliasForDirective(".hword", ".2byte");199    Parser.addAliasForDirective(".word", ".4byte");200    Parser.addAliasForDirective(".dword", ".8byte");201 202    // Initialize the set of available features.203    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));204  }205};206 207// Instances of this class represent a parsed LoongArch machine instruction.208class LoongArchOperand : public MCParsedAsmOperand {209  enum class KindTy {210    Token,211    Register,212    Immediate,213  } Kind;214 215  struct RegOp {216    MCRegister RegNum;217  };218 219  struct ImmOp {220    const MCExpr *Val;221  };222 223  SMLoc StartLoc, EndLoc;224  union {225    StringRef Tok;226    struct RegOp Reg;227    struct ImmOp Imm;228  };229 230public:231  LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}232 233  bool isToken() const override { return Kind == KindTy::Token; }234  bool isReg() const override { return Kind == KindTy::Register; }235  bool isImm() const override { return Kind == KindTy::Immediate; }236  bool isMem() const override { return false; }237  void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }238  bool isGPR() const {239    return Kind == KindTy::Register &&240           LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(241               Reg.RegNum);242  }243 244  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,245                                  LoongArchMCExpr::Specifier &VK) {246    if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {247      VK = LE->getSpecifier();248      return false;249    }250 251    if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {252      Imm = CE->getValue();253      return true;254    }255 256    return false;257  }258 259  template <unsigned N, int P = 0> bool isUImm() const {260    if (!isImm())261      return false;262 263    int64_t Imm;264    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;265    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);266    return IsConstantImm && isUInt<N>(Imm - P) &&267           VK == LoongArchMCExpr::VK_None;268  }269 270  template <unsigned N, unsigned S = 0> bool isSImm() const {271    if (!isImm())272      return false;273 274    int64_t Imm;275    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;276    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);277    return IsConstantImm && isShiftedInt<N, S>(Imm) &&278           VK == LoongArchMCExpr::VK_None;279  }280 281  bool isBareSymbol() const {282    int64_t Imm;283    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;284    // Must be of 'immediate' type but not a constant.285    if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))286      return false;287    return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&288           VK == LoongArchMCExpr::VK_None;289  }290 291  bool isTPRelAddSymbol() const {292    int64_t Imm;293    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;294    // Must be of 'immediate' type but not a constant.295    if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))296      return false;297    return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&298           VK == ELF::R_LARCH_TLS_LE_ADD_R;299  }300 301  bool isUImm1() const { return isUImm<1>(); }302  bool isUImm2() const { return isUImm<2>(); }303  bool isUImm2plus1() const { return isUImm<2, 1>(); }304  bool isUImm3() const { return isUImm<3>(); }305  bool isUImm4() const { return isUImm<4>(); }306  bool isSImm5() const { return isSImm<5>(); }307  bool isUImm5() const { return isUImm<5>(); }308  bool isUImm6() const { return isUImm<6>(); }309  bool isUImm7() const { return isUImm<7>(); }310  bool isSImm8() const { return isSImm<8>(); }311  bool isSImm8lsl1() const { return isSImm<8, 1>(); }312  bool isSImm8lsl2() const { return isSImm<8, 2>(); }313  bool isSImm8lsl3() const { return isSImm<8, 3>(); }314  bool isUImm8() const { return isUImm<8>(); }315  bool isSImm9lsl3() const { return isSImm<9, 3>(); }316  bool isSImm10() const { return isSImm<10>(); }317  bool isSImm10lsl2() const { return isSImm<10, 2>(); }318  bool isSImm11lsl1() const { return isSImm<11, 1>(); }319  bool isSImm12() const { return isSImm<12>(); }320 321  bool isSImm12addlike() const {322    if (!isImm())323      return false;324 325    int64_t Imm;326    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;327    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);328    bool IsValidKind =329        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_PCALA_LO12 ||330        VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||331        VK == ELF::R_LARCH_TLS_LE_LO12_R ||332        VK == ELF::R_LARCH_TLS_DESC_PC_LO12 || VK == ELF::R_LARCH_TLS_DESC_LD;333    return IsConstantImm334               ? isInt<12>(Imm) && IsValidKind335               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&336                     IsValidKind;337  }338 339  bool isSImm12lu52id() const {340    if (!isImm())341      return false;342 343    int64_t Imm;344    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;345    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);346    bool IsValidKind =347        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS64_HI12 ||348        VK == ELF::R_LARCH_PCALA64_HI12 || VK == ELF::R_LARCH_GOT64_HI12 ||349        VK == ELF::R_LARCH_GOT64_PC_HI12 || VK == ELF::R_LARCH_TLS_LE64_HI12 ||350        VK == ELF::R_LARCH_TLS_IE64_HI12 ||351        VK == ELF::R_LARCH_TLS_IE64_PC_HI12 ||352        VK == ELF::R_LARCH_TLS_DESC64_HI12 ||353        VK == ELF::R_LARCH_TLS_DESC64_PC_HI12;354    return IsConstantImm355               ? isInt<12>(Imm) && IsValidKind356               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&357                     IsValidKind;358  }359 360  bool isUImm12() const { return isUImm<12>(); }361 362  bool isUImm12ori() const {363    if (!isImm())364      return false;365 366    int64_t Imm;367    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;368    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);369    bool IsValidKind =370        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS_LO12 ||371        VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_GOT_LO12 ||372        VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_LE_LO12 ||373        VK == ELF::R_LARCH_TLS_IE_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||374        VK == ELF::R_LARCH_TLS_DESC_LO12;375    return IsConstantImm376               ? isUInt<12>(Imm) && IsValidKind377               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&378                     IsValidKind;379  }380 381  bool isSImm13() const { return isSImm<13>(); }382  bool isUImm14() const { return isUImm<14>(); }383  bool isUImm15() const { return isUImm<15>(); }384 385  bool isSImm14lsl2() const { return isSImm<14, 2>(); }386  bool isSImm16() const { return isSImm<16>(); }387 388  bool isSImm16lsl2() const {389    if (!isImm())390      return false;391 392    int64_t Imm;393    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;394    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);395    bool IsValidKind =396        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B16 ||397        VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_TLS_DESC_CALL;398    return IsConstantImm399               ? isShiftedInt<16, 2>(Imm) && IsValidKind400               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&401                     IsValidKind;402  }403 404  bool isSImm20() const { return isSImm<20>(); }405 406  bool isSImm20pcalau12i() const {407    if (!isImm())408      return false;409 410    int64_t Imm;411    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;412    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);413    bool IsValidKind =414        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_PCALA_HI20 ||415        VK == ELF::R_LARCH_GOT_PC_HI20 || VK == ELF::R_LARCH_TLS_IE_PC_HI20 ||416        VK == ELF::R_LARCH_TLS_LD_PC_HI20 ||417        VK == ELF::R_LARCH_TLS_GD_PC_HI20 ||418        VK == ELF::R_LARCH_TLS_DESC_PC_HI20;419    return IsConstantImm420               ? isInt<20>(Imm) && IsValidKind421               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&422                     IsValidKind;423  }424 425  bool isSImm20lu12iw() const {426    if (!isImm())427      return false;428 429    int64_t Imm;430    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;431    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);432    bool IsValidKind =433        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS_HI20 ||434        VK == ELF::R_LARCH_GOT_HI20 || VK == ELF::R_LARCH_TLS_GD_HI20 ||435        VK == ELF::R_LARCH_TLS_LD_HI20 || VK == ELF::R_LARCH_TLS_IE_HI20 ||436        VK == ELF::R_LARCH_TLS_LE_HI20 || VK == ELF::R_LARCH_TLS_LE_HI20_R ||437        VK == ELF::R_LARCH_TLS_DESC_HI20;438    return IsConstantImm439               ? isInt<20>(Imm) && IsValidKind440               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&441                     IsValidKind;442  }443 444  bool isSImm20lu32id() const {445    if (!isImm())446      return false;447 448    int64_t Imm;449    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;450    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);451    bool IsValidKind =452        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS64_LO20 ||453        VK == ELF::R_LARCH_PCALA64_LO20 || VK == ELF::R_LARCH_GOT64_LO20 ||454        VK == ELF::R_LARCH_GOT64_PC_LO20 || VK == ELF::R_LARCH_TLS_IE64_LO20 ||455        VK == ELF::R_LARCH_TLS_IE64_PC_LO20 ||456        VK == ELF::R_LARCH_TLS_LE64_LO20 ||457        VK == ELF::R_LARCH_TLS_DESC64_PC_LO20 ||458        VK == ELF::R_LARCH_TLS_DESC64_LO20;459 460    return IsConstantImm461               ? isInt<20>(Imm) && IsValidKind462               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&463                     IsValidKind;464  }465 466  bool isSImm20pcaddu18i() const {467    if (!isImm())468      return false;469 470    int64_t Imm;471    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;472    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);473    bool IsValidKind =474        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL36;475 476    return IsConstantImm477               ? isInt<20>(Imm) && IsValidKind478               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&479                     IsValidKind;480  }481 482  bool isSImm20pcaddi() const {483    if (!isImm())484      return false;485 486    int64_t Imm;487    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;488    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);489    bool IsValidKind = VK == LoongArchMCExpr::VK_None ||490                       VK == ELF::R_LARCH_PCREL20_S2 ||491                       VK == ELF::R_LARCH_TLS_LD_PCREL20_S2 ||492                       VK == ELF::R_LARCH_TLS_GD_PCREL20_S2 ||493                       VK == ELF::R_LARCH_TLS_DESC_PCREL20_S2;494    return IsConstantImm495               ? isInt<20>(Imm) && IsValidKind496               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&497                     IsValidKind;498  }499 500  bool isSImm21lsl2() const {501    if (!isImm())502      return false;503 504    int64_t Imm;505    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;506    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);507    bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B21;508    return IsConstantImm509               ? isShiftedInt<21, 2>(Imm) && IsValidKind510               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&511                     IsValidKind;512  }513 514  bool isSImm26Operand() const {515    if (!isImm())516      return false;517 518    int64_t Imm;519    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;520    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);521    bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B26;522    return IsConstantImm523               ? isShiftedInt<26, 2>(Imm) && IsValidKind524               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&525                     IsValidKind;526  }527 528  bool isImm32() const { return isSImm<32>() || isUImm<32>(); }529  bool isImm64() const {530    if (!isImm())531      return false;532    int64_t Imm;533    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;534    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);535    return IsConstantImm && VK == LoongArchMCExpr::VK_None;536  }537 538  /// Gets location of the first token of this operand.539  SMLoc getStartLoc() const override { return StartLoc; }540  /// Gets location of the last token of this operand.541  SMLoc getEndLoc() const override { return EndLoc; }542 543  MCRegister getReg() const override {544    assert(Kind == KindTy::Register && "Invalid type access!");545    return Reg.RegNum;546  }547 548  const MCExpr *getImm() const {549    assert(Kind == KindTy::Immediate && "Invalid type access!");550    return Imm.Val;551  }552 553  StringRef getToken() const {554    assert(Kind == KindTy::Token && "Invalid type access!");555    return Tok;556  }557 558  void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {559    auto RegName = [](MCRegister Reg) {560      if (Reg)561        return LoongArchInstPrinter::getRegisterName(Reg);562      else563        return "noreg";564    };565 566    switch (Kind) {567    case KindTy::Immediate:568      MAI.printExpr(OS, *getImm());569      break;570    case KindTy::Register:571      OS << "<register " << RegName(getReg()) << ">";572      break;573    case KindTy::Token:574      OS << "'" << getToken() << "'";575      break;576    }577  }578 579  static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {580    auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);581    Op->Tok = Str;582    Op->StartLoc = S;583    Op->EndLoc = S;584    return Op;585  }586 587  static std::unique_ptr<LoongArchOperand> createReg(MCRegister Reg, SMLoc S,588                                                     SMLoc E) {589    auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);590    Op->Reg.RegNum = Reg;591    Op->StartLoc = S;592    Op->EndLoc = E;593    return Op;594  }595 596  static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,597                                                     SMLoc E) {598    auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);599    Op->Imm.Val = Val;600    Op->StartLoc = S;601    Op->EndLoc = E;602    return Op;603  }604 605  void addExpr(MCInst &Inst, const MCExpr *Expr) const {606    if (auto CE = dyn_cast<MCConstantExpr>(Expr))607      Inst.addOperand(MCOperand::createImm(CE->getValue()));608    else609      Inst.addOperand(MCOperand::createExpr(Expr));610  }611 612  // Used by the TableGen Code.613  void addRegOperands(MCInst &Inst, unsigned N) const {614    assert(N == 1 && "Invalid number of operands!");615    Inst.addOperand(MCOperand::createReg(getReg()));616  }617  void addImmOperands(MCInst &Inst, unsigned N) const {618    assert(N == 1 && "Invalid number of operands!");619    addExpr(Inst, getImm());620  }621};622} // end namespace623 624#define GET_REGISTER_MATCHER625#define GET_SUBTARGET_FEATURE_NAME626#define GET_MATCHER_IMPLEMENTATION627#define GET_MNEMONIC_SPELL_CHECKER628#include "LoongArchGenAsmMatcher.inc"629 630static MCRegister convertFPR32ToFPR64(MCRegister Reg) {631  assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");632  return Reg - LoongArch::F0 + LoongArch::F0_64;633}634 635// Attempts to match Name as a register (either using the default name or636// alternative ABI names), setting RegNo to the matching register. Upon637// failure, returns true and sets RegNo to 0.638static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {639  RegNo = MatchRegisterName(Name);640  // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial641  // match always matches the 32-bit variant, and not the 64-bit one.642  assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));643  // The default FPR register class is based on the tablegen enum ordering.644  static_assert(LoongArch::F0 < LoongArch::F0_64,645                "FPR matching must be updated");646  if (RegNo == LoongArch::NoRegister)647    RegNo = MatchRegisterAltName(Name);648 649  return RegNo == LoongArch::NoRegister;650}651 652bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,653                                       SMLoc &EndLoc) {654  if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())655    return Error(getLoc(), "invalid register name");656 657  if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&658      !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))659    return Error(getLoc(), "invalid register name");660 661  return false;662}663 664ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,665                                                 SMLoc &StartLoc,666                                                 SMLoc &EndLoc) {667  const AsmToken &Tok = getParser().getTok();668  StartLoc = Tok.getLoc();669  EndLoc = Tok.getEndLoc();670 671  parseOptionalToken(AsmToken::Dollar);672  if (getLexer().getKind() != AsmToken::Identifier)673    return ParseStatus::NoMatch;674 675  StringRef Name = Tok.getIdentifier();676  if (matchRegisterNameHelper(Reg, Name))677    return ParseStatus::NoMatch;678 679  getParser().Lex(); // Eat identifier token.680  return ParseStatus::Success;681}682 683bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,684                                           LoongArchMCExpr::Specifier &Kind) {685  Kind = LoongArchMCExpr::VK_None;686 687  if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {688    Kind = RE->getSpecifier();689    Expr = RE->getSubExpr();690  }691 692  MCValue Res;693  if (Expr->evaluateAsRelocatable(Res, nullptr))694    return Res.getSpecifier() == LoongArchMCExpr::VK_None;695  return false;696}697 698ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {699  if (!parseOptionalToken(AsmToken::Dollar))700    return ParseStatus::NoMatch;701  if (getLexer().getKind() != AsmToken::Identifier)702    return ParseStatus::NoMatch;703 704  StringRef Name = getLexer().getTok().getIdentifier();705  MCRegister RegNo;706  matchRegisterNameHelper(RegNo, Name);707  if (RegNo == LoongArch::NoRegister)708    return ParseStatus::NoMatch;709 710  SMLoc S = getLoc();711  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());712  getLexer().Lex();713  Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));714 715  return ParseStatus::Success;716}717 718ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {719  SMLoc S = getLoc();720  SMLoc E;721  const MCExpr *Res;722 723  switch (getLexer().getKind()) {724  default:725    return ParseStatus::NoMatch;726  case AsmToken::LParen:727  case AsmToken::Dot:728  case AsmToken::Minus:729  case AsmToken::Plus:730  case AsmToken::Exclaim:731  case AsmToken::Tilde:732  case AsmToken::Integer:733  case AsmToken::String:734  case AsmToken::Identifier:735    if (getParser().parseExpression(Res, E))736      return ParseStatus::Failure;737    break;738  case AsmToken::Percent:739    return parseOperandWithModifier(Operands);740  }741 742  Operands.push_back(LoongArchOperand::createImm(Res, S, E));743  return ParseStatus::Success;744}745 746ParseStatus747LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {748  SMLoc S = getLoc();749  SMLoc E;750 751  if (getLexer().getKind() != AsmToken::Percent)752    return Error(getLoc(), "expected '%' for operand modifier");753 754  getParser().Lex(); // Eat '%'755 756  if (getLexer().getKind() != AsmToken::Identifier)757    return Error(getLoc(), "expected valid identifier for operand modifier");758  StringRef Identifier = getParser().getTok().getIdentifier();759  auto VK = LoongArch::parseSpecifier(Identifier);760  if (VK == LoongArchMCExpr::VK_None)761    return Error(getLoc(), "invalid relocation specifier");762 763  getParser().Lex(); // Eat the identifier764  if (getLexer().getKind() != AsmToken::LParen)765    return Error(getLoc(), "expected '('");766  getParser().Lex(); // Eat '('767 768  const MCExpr *SubExpr;769  if (getParser().parseParenExpression(SubExpr, E))770    return ParseStatus::Failure;771 772  const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());773  Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));774  return ParseStatus::Success;775}776 777ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {778  SMLoc S = getLoc();779  const MCExpr *Res;780 781  if (getLexer().getKind() == AsmToken::Percent)782    return parseOperandWithModifier(Operands);783 784  if (getLexer().getKind() != AsmToken::Identifier)785    return ParseStatus::NoMatch;786 787  StringRef Identifier;788  if (getParser().parseIdentifier(Identifier))789    return ParseStatus::Failure;790 791  SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());792 793  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);794  Res = MCSymbolRefExpr::create(Sym, getContext());795  Operands.push_back(LoongArchOperand::createImm(Res, S, E));796  return ParseStatus::Success;797}798 799ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {800  // Parse "$r*".801  if (!parseRegister(Operands).isSuccess())802    return ParseStatus::NoMatch;803 804  // If there is a next operand and it is 0, ignore it. Otherwise print a805  // diagnostic message.806  if (parseOptionalToken(AsmToken::Comma)) {807    int64_t ImmVal;808    SMLoc ImmStart = getLoc();809    if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))810      return ParseStatus::Failure;811    if (ImmVal)812      return Error(ImmStart, "optional integer offset must be 0");813  }814 815  return ParseStatus::Success;816}817/// Looks at a token type and creates the relevant operand from this818/// information, adding to Operands. Return true upon an error.819bool LoongArchAsmParser::parseOperand(OperandVector &Operands,820                                      StringRef Mnemonic) {821  // Check if the current operand has a custom associated parser, if so, try to822  // custom parse the operand, or fallback to the general approach.823  ParseStatus Result =824      MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);825  if (Result.isSuccess())826    return false;827  if (Result.isFailure())828    return true;829 830  if (parseRegister(Operands).isSuccess() ||831      parseImmediate(Operands).isSuccess())832    return false;833 834  // Finally we have exhausted all options and must declare defeat.835  return Error(getLoc(), "unknown operand");836}837 838bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo &Info,839                                          StringRef Name, SMLoc NameLoc,840                                          OperandVector &Operands) {841  // First operand in MCInst is instruction mnemonic.842  Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));843 844  // If there are no more operands, then finish.845  if (parseOptionalToken(AsmToken::EndOfStatement))846    return false;847 848  // Parse first operand.849  if (parseOperand(Operands, Name))850    return true;851 852  // Parse until end of statement, consuming commas between operands.853  while (parseOptionalToken(AsmToken::Comma))854    if (parseOperand(Operands, Name))855      return true;856 857  // Parse end of statement and return successfully.858  if (parseOptionalToken(AsmToken::EndOfStatement))859    return false;860 861  SMLoc Loc = getLexer().getLoc();862  getParser().eatToEndOfStatement();863  return Error(Loc, "unexpected token");864}865 866void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,867                                       const MCExpr *Symbol,868                                       SmallVectorImpl<Inst> &Insts,869                                       SMLoc IDLoc, MCStreamer &Out,870                                       bool RelaxHint) {871  MCContext &Ctx = getContext();872  for (LoongArchAsmParser::Inst &Inst : Insts) {873    unsigned Opc = Inst.Opc;874    auto VK = LoongArchMCExpr::Specifier(Inst.Specifier);875    const LoongArchMCExpr *LE =876        LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);877    switch (Opc) {878    default:879      llvm_unreachable("unexpected opcode");880    case LoongArch::PCALAU12I:881    case LoongArch::LU12I_W:882      Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),883                          getSTI());884      break;885    case LoongArch::ORI:886    case LoongArch::ADDI_W:887    case LoongArch::LD_W:888    case LoongArch::LD_D: {889      if (VK == LoongArchMCExpr::VK_None) {890        Out.emitInstruction(891            MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),892            getSTI());893        continue;894      } else if (VK == ELF::R_LARCH_TLS_DESC_LD) {895        Out.emitInstruction(MCInstBuilder(Opc)896                                .addReg(LoongArch::R1)897                                .addReg(DestReg)898                                .addExpr(LE),899                            getSTI());900        continue;901      }902      Out.emitInstruction(903          MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),904          getSTI());905      break;906    }907    case LoongArch::LU32I_D:908      Out.emitInstruction(MCInstBuilder(Opc)909                              .addReg(DestReg == TmpReg ? DestReg : TmpReg)910                              .addReg(DestReg == TmpReg ? DestReg : TmpReg)911                              .addExpr(LE),912                          getSTI());913      break;914    case LoongArch::LU52I_D:915      Out.emitInstruction(916          MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),917          getSTI());918      break;919    case LoongArch::ADDI_D:920      Out.emitInstruction(921          MCInstBuilder(Opc)922              .addReg(TmpReg)923              .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)924              .addExpr(LE),925          getSTI());926      break;927    case LoongArch::ADD_D:928    case LoongArch::LDX_D:929      Out.emitInstruction(930          MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),931          getSTI());932      break;933    case LoongArch::JIRL:934      Out.emitInstruction(MCInstBuilder(Opc)935                              .addReg(LoongArch::R1)936                              .addReg(LoongArch::R1)937                              .addExpr(LE),938                          getSTI());939      break;940    }941  }942}943 944void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,945                                            MCStreamer &Out) {946  // la.abs $rd, sym947  // expands to:948  //   lu12i.w $rd, %abs_hi20(sym)949  //   ori     $rd, $rd, %abs_lo12(sym)950  //951  // for 64bit appends:952  //   lu32i.d $rd, %abs64_lo20(sym)953  //   lu52i.d $rd, $rd, %abs64_hi12(sym)954  MCRegister DestReg = Inst.getOperand(0).getReg();955  const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS956                             ? Inst.getOperand(1).getExpr()957                             : Inst.getOperand(2).getExpr();958  InstSeq Insts;959 960  // To distinguish between la.abs and %abs_hi20, la.abs will generate961  // R_LARCH_MARK_LA and R_LARCH_ABS_HI20 relocations.962  Insts.push_back(963      LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_MARK_LA));964  Insts.push_back(965      LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_ABS_LO12));966 967  if (is64Bit()) {968    Insts.push_back(969        LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_ABS64_LO20));970    Insts.push_back(971        LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_ABS64_HI12));972  }973 974  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);975}976 977void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,978                                              MCStreamer &Out) {979  // la.pcrel $rd, sym980  // expands to:981  //   pcalau12i $rd, %pc_hi20(sym)982  //   addi.w/d  $rd, rd, %pc_lo12(sym)983  MCRegister DestReg = Inst.getOperand(0).getReg();984  const MCExpr *Symbol = Inst.getOperand(1).getExpr();985  InstSeq Insts;986  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;987 988  Insts.push_back(989      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));990  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_PCALA_LO12));991 992  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,993                /*RelaxHint=*/true);994}995 996void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,997                                                   MCStreamer &Out) {998  // la.pcrel $rd, $rj, sym999  // expands to:1000  //   pcalau12i $rd, %pc_hi20(sym)1001  //   addi.d    $rj, $r0, %pc_lo12(sym)1002  //   lu32i.d   $rj, %pc64_lo20(sym)1003  //   lu52i.d   $rj, $rj, %pc64_hi12(sym)1004  //   add.d     $rd, $rd, $rj1005  MCRegister DestReg = Inst.getOperand(0).getReg();1006  MCRegister TmpReg = Inst.getOperand(1).getReg();1007  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1008  InstSeq Insts;1009 1010  Insts.push_back(1011      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));1012  Insts.push_back(1013      LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_PCALA_LO12));1014  Insts.push_back(1015      LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_PCALA64_LO20));1016  Insts.push_back(1017      LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_PCALA64_HI12));1018  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));1019 1020  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1021}1022 1023void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,1024                                            MCStreamer &Out) {1025  // la.got $rd, sym1026  MCRegister DestReg = Inst.getOperand(0).getReg();1027  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1028  InstSeq Insts;1029  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;1030 1031  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {1032    // with feature: +la-glabal-with-abs1033    // for 32bit:1034    //   lu12i.w $rd, %got_hi20(sym)1035    //   ori     $rd, $rd, %got_lo12(sym)1036    //   ld.w    $rd, $rd, 01037    //1038    // for 64bit:1039    //   lu12i.w $rd, %got_hi20(sym)1040    //   ori     $rd, $rd, %got_lo12(sym)1041    //   lu32i.d $rd, %got64_lo20(sym)1042    //   lu52i.d $rd, $rd, %got64_hi12(sym)1043    //   ld.d    $rd, $rd, 01044    Insts.push_back(1045        LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_GOT_HI20));1046    Insts.push_back(1047        LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));1048 1049    if (is64Bit()) {1050      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1051                                               ELF::R_LARCH_GOT64_LO20));1052      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1053                                               ELF::R_LARCH_GOT64_HI12));1054    }1055    Insts.push_back(LoongArchAsmParser::Inst(LD));1056    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1057    return;1058  }1059  // expands to:1060  //   pcalau12i $rd, %got_pc_hi20(sym)1061  //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)1062  Insts.push_back(1063      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));1064  Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_GOT_PC_LO12));1065 1066  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,1067                /*RelaxHint=*/true);1068}1069 1070void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,1071                                                 MCStreamer &Out) {1072  // la.got $rd, $rj, sym1073  // expands to:1074  //   pcalau12i $rd, %got_pc_hi20(sym)1075  //   addi.d    $rj, $r0, %got_pc_lo12(sym)1076  //   lu32i.d   $rj, %got64_pc_lo20(sym)1077  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)1078  //   ldx.d     $rd, $rd, $rj1079  MCRegister DestReg = Inst.getOperand(0).getReg();1080  MCRegister TmpReg = Inst.getOperand(1).getReg();1081  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1082  InstSeq Insts;1083 1084  Insts.push_back(1085      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));1086  Insts.push_back(1087      LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));1088  Insts.push_back(1089      LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));1090  Insts.push_back(1091      LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));1092  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));1093 1094  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1095}1096 1097void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,1098                                              MCStreamer &Out) {1099  // la.tls.le $rd, sym1100  // expands to:1101  //   lu12i.w $rd, %le_hi20(sym)1102  //   ori     $rd, $rd, %le_lo12(sym)1103  MCRegister DestReg = Inst.getOperand(0).getReg();1104  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1105  InstSeq Insts;1106 1107  Insts.push_back(1108      LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LE_HI20));1109  Insts.push_back(1110      LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_LE_LO12));1111 1112  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1113}1114 1115void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,1116                                              MCStreamer &Out) {1117  // la.tls.ie $rd, sym1118  MCRegister DestReg = Inst.getOperand(0).getReg();1119  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1120  InstSeq Insts;1121  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;1122 1123  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {1124    // with feature: +la-glabal-with-abs1125    // for 32bit:1126    //   lu12i.w $rd, %ie_hi20(sym)1127    //   ori     $rd, $rd, %ie_lo12(sym)1128    //   ld.w    $rd, $rd, 01129    //1130    // for 64bit:1131    //   lu12i.w $rd, %ie_hi20(sym)1132    //   ori     $rd, $rd, %ie_lo12(sym)1133    //   lu32i.d $rd, %ie64_lo20(sym)1134    //   lu52i.d $rd, $rd, %ie64_hi12(sym)1135    //   ld.d    $rd, $rd, 01136    Insts.push_back(1137        LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_IE_HI20));1138    Insts.push_back(1139        LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_IE_LO12));1140 1141    if (is64Bit()) {1142      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1143                                               ELF::R_LARCH_TLS_IE64_LO20));1144      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1145                                               ELF::R_LARCH_TLS_IE64_HI12));1146    }1147    Insts.push_back(LoongArchAsmParser::Inst(LD));1148    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1149    return;1150  }1151 1152  // expands to:1153  //   pcalau12i $rd, %ie_pc_hi20(sym)1154  //   ld.w/d    $rd, $rd, %ie_pc_lo12(sym)1155  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1156                                           ELF::R_LARCH_TLS_IE_PC_HI20));1157  Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_IE_PC_LO12));1158 1159  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,1160                /*RelaxHint=*/true);1161}1162 1163void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,1164                                                   MCStreamer &Out) {1165  // la.tls.ie $rd, $rj, sym1166  // expands to:1167  //   pcalau12i $rd, %ie_pc_hi20(sym)1168  //   addi.d    $rj, $r0, %ie_pc_lo12(sym)1169  //   lu32i.d   $rj, %ie64_pc_lo20(sym)1170  //   lu52i.d   $rj, $rj, %ie64_pc_hi12(sym)1171  //   ldx.d     $rd, $rd, $rj1172  MCRegister DestReg = Inst.getOperand(0).getReg();1173  MCRegister TmpReg = Inst.getOperand(1).getReg();1174  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1175  InstSeq Insts;1176 1177  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1178                                           ELF::R_LARCH_TLS_IE_PC_HI20));1179  Insts.push_back(1180      LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_TLS_IE_PC_LO12));1181  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1182                                           ELF::R_LARCH_TLS_IE64_PC_LO20));1183  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1184                                           ELF::R_LARCH_TLS_IE64_PC_HI12));1185  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));1186 1187  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1188}1189 1190void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,1191                                              MCStreamer &Out) {1192  // la.tls.ld $rd, sym1193  MCRegister DestReg = Inst.getOperand(0).getReg();1194  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1195  InstSeq Insts;1196  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;1197 1198  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {1199    // with feature: +la-glabal-with-abs1200    // for 32bit:1201    //   lu12i.w $rd, %ld_hi20(sym)1202    //   ori     $rd, $rd, %got_lo12(sym)1203    //1204    // for 64bit:1205    //   lu12i.w $rd, %ld_hi20(sym)1206    //   ori     $rd, $rd, %got_lo12(sym)1207    //   lu32i.d $rd, %got64_lo20(sym)1208    //   lu52i.d $rd, $rd, %got64_hi12(sym)1209    Insts.push_back(1210        LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LD_HI20));1211    Insts.push_back(1212        LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));1213 1214    if (is64Bit()) {1215      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1216                                               ELF::R_LARCH_GOT64_LO20));1217      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1218                                               ELF::R_LARCH_GOT64_HI12));1219    }1220    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1221    return;1222  }1223 1224  // expands to:1225  //   pcalau12i $rd, %ld_pc_hi20(sym)1226  //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)1227  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1228                                           ELF::R_LARCH_TLS_LD_PC_HI20));1229  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));1230 1231  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,1232                /*RelaxHint=*/true);1233}1234 1235void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,1236                                                   MCStreamer &Out) {1237  // la.tls.ld $rd, $rj, sym1238  // expands to:1239  //   pcalau12i $rd, %ld_pc_hi20(sym)1240  //   addi.d    $rj, $r0, %got_pc_lo12(sym)1241  //   lu32i.d   $rj, %got64_pc_lo20(sym)1242  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)1243  //   add.d     $rd, $rd, $rj1244  MCRegister DestReg = Inst.getOperand(0).getReg();1245  MCRegister TmpReg = Inst.getOperand(1).getReg();1246  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1247  InstSeq Insts;1248 1249  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1250                                           ELF::R_LARCH_TLS_LD_PC_HI20));1251  Insts.push_back(1252      LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));1253  Insts.push_back(1254      LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));1255  Insts.push_back(1256      LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));1257  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));1258 1259  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1260}1261 1262void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,1263                                              MCStreamer &Out) {1264  // la.tls.gd $rd, sym1265  MCRegister DestReg = Inst.getOperand(0).getReg();1266  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1267  InstSeq Insts;1268  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;1269 1270  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {1271    // with feature: +la-glabal-with-abs1272    // for 32bit:1273    //   lu12i.w $rd, %gd_hi20(sym)1274    //   ori     $rd, $rd, %got_lo12(sym)1275    //1276    // for 64bit:1277    //   lu12i.w $rd, %gd_hi20(sym)1278    //   ori     $rd, $rd, %got_lo12(sym)1279    //   lu32i.d $rd, %got64_lo20(sym)1280    //   lu52i.d $rd, $rd, %got64_hi12(sym)1281    Insts.push_back(1282        LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_GD_HI20));1283    Insts.push_back(1284        LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));1285 1286    if (is64Bit()) {1287      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1288                                               ELF::R_LARCH_GOT64_LO20));1289      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1290                                               ELF::R_LARCH_GOT64_HI12));1291    }1292    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1293    return;1294  }1295 1296  // expands to:1297  //   pcalau12i $rd, %gd_pc_hi20(sym)1298  //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)1299  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1300                                           ELF::R_LARCH_TLS_GD_PC_HI20));1301  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));1302 1303  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,1304                /*RelaxHint=*/true);1305}1306 1307void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,1308                                                   MCStreamer &Out) {1309  // la.tls.gd $rd, $rj, sym1310  // expands to:1311  //   pcalau12i $rd, %gd_pc_hi20(sym)1312  //   addi.d    $rj, $r0, %got_pc_lo12(sym)1313  //   lu32i.d   $rj, %got64_pc_lo20(sym)1314  //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)1315  //   add.d     $rd, $rd, $rj1316  MCRegister DestReg = Inst.getOperand(0).getReg();1317  MCRegister TmpReg = Inst.getOperand(1).getReg();1318  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1319  InstSeq Insts;1320 1321  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1322                                           ELF::R_LARCH_TLS_GD_PC_HI20));1323  Insts.push_back(1324      LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));1325  Insts.push_back(1326      LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));1327  Insts.push_back(1328      LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));1329  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));1330 1331  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1332}1333 1334void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,1335                                                MCStreamer &Out) {1336  // la.tls.desc $rd, sym1337  MCRegister DestReg = Inst.getOperand(0).getReg();1338  const MCExpr *Symbol = Inst.getOperand(1).getExpr();1339  unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;1340  unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;1341  InstSeq Insts;1342 1343  if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {1344    // with feature: +la-glabal-with-abs1345    // for la32 expands to:1346    //   lu12i.w $rd, %desc_hi20(sym)1347    //   ori     $rd, $rd, %desc_lo12(sym)1348    //   ld.w    $ra, $rd, %desc_ld(sym)1349    //   jirl    $ra, $ra, %desc_call(sym)1350    //1351    // for la64 expands to:1352    //   lu12i.w $rd, %desc_hi20(sym)1353    //   ori     $rd, $rd, %desc_lo12(sym)1354    //   lu32i.d $rd, %desc64_lo20(sym)1355    //   lu52i.d $rd, $rd, %desc64_hi12(sym)1356    //   ld.d    $ra, $rd, %desc_ld(sym)1357    //   jirl    $ra, $ra, %desc_call(sym)1358    Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU12I_W,1359                                             ELF::R_LARCH_TLS_DESC_HI20));1360    Insts.push_back(1361        LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_DESC_LO12));1362 1363    if (is64Bit()) {1364      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1365                                               ELF::R_LARCH_TLS_DESC64_LO20));1366      Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1367                                               ELF::R_LARCH_TLS_DESC64_HI12));1368    }1369 1370    Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));1371    Insts.push_back(1372        LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));1373 1374    emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1375    return;1376  }1377 1378  // expands to:1379  //   pcalau12i $rd, %desc_pc_hi20(sym)1380  //   addi.w/d  $rd, $rd, %desc_pc_lo12(sym)1381  //   ld.w/d    $ra, $rd, %desc_ld(sym)1382  //   jirl      $ra, $ra, %desc_call(sym)1383  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1384                                           ELF::R_LARCH_TLS_DESC_PC_HI20));1385  Insts.push_back(1386      LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_TLS_DESC_PC_LO12));1387  Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));1388  Insts.push_back(1389      LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));1390 1391  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,1392                /*RelaxHint=*/true);1393}1394 1395void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,1396                                                     MCStreamer &Out) {1397  // la.tls.desc $rd, $rj, sym1398  // expands to:1399  //   pcalau12i $rd, %desc_pc_hi20(sym)1400  //   addi.d    $rj, $r0, %desc_pc_lo12(sym)1401  //   lu32i.d   $rj, %desc64_pc_lo20(sym)1402  //   lu52i.d   $rj, $rj, %desc64_pc_hi12(sym)1403  //   add.d     $rd, $rd, $rj1404  //   ld.w/d    $ra, $rd, %desc_ld(sym)1405  //   jirl      $ra, $ra, %desc_call(sym)1406  MCRegister DestReg = Inst.getOperand(0).getReg();1407  MCRegister TmpReg = Inst.getOperand(1).getReg();1408  const MCExpr *Symbol = Inst.getOperand(2).getExpr();1409  InstSeq Insts;1410 1411  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,1412                                           ELF::R_LARCH_TLS_DESC_PC_HI20));1413  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADDI_D,1414                                           ELF::R_LARCH_TLS_DESC_PC_LO12));1415  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,1416                                           ELF::R_LARCH_TLS_DESC64_PC_LO20));1417  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,1418                                           ELF::R_LARCH_TLS_DESC64_PC_HI12));1419  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));1420  Insts.push_back(1421      LoongArchAsmParser::Inst(LoongArch::LD_D, ELF::R_LARCH_TLS_DESC_LD));1422  Insts.push_back(1423      LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));1424 1425  emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1426}1427 1428void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,1429                                     MCStreamer &Out) {1430  MCRegister DestReg = Inst.getOperand(0).getReg();1431  int64_t Imm = Inst.getOperand(1).getImm();1432  MCRegister SrcReg = LoongArch::R0;1433 1434  if (Inst.getOpcode() == LoongArch::PseudoLI_W)1435    Imm = SignExtend64<32>(Imm);1436 1437  for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {1438    switch (Inst.Opc) {1439    case LoongArch::LU12I_W:1440      Out.emitInstruction(1441          MCInstBuilder(Inst.Opc).addReg(DestReg).addImm(Inst.Imm), getSTI());1442      break;1443    case LoongArch::ADDI_W:1444    case LoongArch::ORI:1445    case LoongArch::LU32I_D:1446    case LoongArch::LU52I_D:1447      Out.emitInstruction(1448          MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(1449              Inst.Imm),1450          getSTI());1451      break;1452    case LoongArch::BSTRINS_D:1453      Out.emitInstruction(MCInstBuilder(Inst.Opc)1454                              .addReg(DestReg)1455                              .addReg(SrcReg)1456                              .addReg(SrcReg)1457                              .addImm(Inst.Imm >> 32)1458                              .addImm(Inst.Imm & 0xFF),1459                          getSTI());1460      break;1461    default:1462      llvm_unreachable("unexpected opcode generated by LoongArchMatInt");1463    }1464    SrcReg = DestReg;1465  }1466}1467 1468void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,1469                                        MCStreamer &Out, bool IsTailCall) {1470  // call36 sym1471  // expands to:1472  //   pcaddu18i $ra, %call36(sym)1473  //   jirl      $ra, $ra, 01474  //1475  // tail36 $rj, sym1476  // expands to:1477  //   pcaddu18i $rj, %call36(sym)1478  //   jirl      $r0, $rj, 01479  MCRegister ScratchReg =1480      IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);1481  const MCExpr *Sym =1482      IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();1483  const LoongArchMCExpr *LE = LoongArchMCExpr::create(1484      Sym, ELF::R_LARCH_CALL36, getContext(), /*RelaxHint=*/true);1485 1486  Out.emitInstruction(1487      MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),1488      getSTI());1489  Out.emitInstruction(1490      MCInstBuilder(LoongArch::JIRL)1491          .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)1492          .addReg(ScratchReg)1493          .addImm(0),1494      getSTI());1495}1496 1497bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,1498                                            OperandVector &Operands,1499                                            MCStreamer &Out) {1500  Inst.setLoc(IDLoc);1501  switch (Inst.getOpcode()) {1502  default:1503    break;1504  case LoongArch::PseudoLA_ABS:1505  case LoongArch::PseudoLA_ABS_LARGE:1506    emitLoadAddressAbs(Inst, IDLoc, Out);1507    return false;1508  case LoongArch::PseudoLA_PCREL:1509    emitLoadAddressPcrel(Inst, IDLoc, Out);1510    return false;1511  case LoongArch::PseudoLA_PCREL_LARGE:1512    emitLoadAddressPcrelLarge(Inst, IDLoc, Out);1513    return false;1514  case LoongArch::PseudoLA_GOT:1515    emitLoadAddressGot(Inst, IDLoc, Out);1516    return false;1517  case LoongArch::PseudoLA_GOT_LARGE:1518    emitLoadAddressGotLarge(Inst, IDLoc, Out);1519    return false;1520  case LoongArch::PseudoLA_TLS_LE:1521    emitLoadAddressTLSLE(Inst, IDLoc, Out);1522    return false;1523  case LoongArch::PseudoLA_TLS_IE:1524    emitLoadAddressTLSIE(Inst, IDLoc, Out);1525    return false;1526  case LoongArch::PseudoLA_TLS_IE_LARGE:1527    emitLoadAddressTLSIELarge(Inst, IDLoc, Out);1528    return false;1529  case LoongArch::PseudoLA_TLS_LD:1530    emitLoadAddressTLSLD(Inst, IDLoc, Out);1531    return false;1532  case LoongArch::PseudoLA_TLS_LD_LARGE:1533    emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);1534    return false;1535  case LoongArch::PseudoLA_TLS_GD:1536    emitLoadAddressTLSGD(Inst, IDLoc, Out);1537    return false;1538  case LoongArch::PseudoLA_TLS_GD_LARGE:1539    emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);1540    return false;1541  case LoongArch::PseudoLA_TLS_DESC:1542    emitLoadAddressTLSDesc(Inst, IDLoc, Out);1543    return false;1544  case LoongArch::PseudoLA_TLS_DESC_LARGE:1545    emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);1546    return false;1547  case LoongArch::PseudoLI_W:1548  case LoongArch::PseudoLI_D:1549    emitLoadImm(Inst, IDLoc, Out);1550    return false;1551  case LoongArch::PseudoCALL36:1552    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);1553    return false;1554  case LoongArch::PseudoTAIL36:1555    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);1556    return false;1557  }1558  Out.emitInstruction(Inst, getSTI());1559  return false;1560}1561 1562unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {1563  unsigned Opc = Inst.getOpcode();1564  const MCInstrDesc &MCID = MII.get(Opc);1565  switch (Opc) {1566  default:1567    if (LoongArchII::isSubjectToAMORdConstraint(MCID.TSFlags)) {1568      const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);1569      MCRegister Rd = Inst.getOperand(0).getReg();1570      MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();1571      MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();1572      if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)1573        return Match_RequiresAMORdDifferRkRj;1574    }1575    break;1576  case LoongArch::PseudoLA_TLS_DESC:1577  case LoongArch::PseudoLA_TLS_DESC_LARGE: {1578    MCRegister Rd = Inst.getOperand(0).getReg();1579    if (Rd != LoongArch::R4)1580      return Match_RequiresLAORdR4;1581    break;1582  }1583  case LoongArch::PseudoLA_PCREL_LARGE:1584  case LoongArch::PseudoLA_GOT_LARGE:1585  case LoongArch::PseudoLA_TLS_IE_LARGE:1586  case LoongArch::PseudoLA_TLS_LD_LARGE:1587  case LoongArch::PseudoLA_TLS_GD_LARGE: {1588    MCRegister Rd = Inst.getOperand(0).getReg();1589    MCRegister Rj = Inst.getOperand(1).getReg();1590    if (Rd == Rj)1591      return Match_RequiresLAORdDifferRj;1592    break;1593  }1594  case LoongArch::CSRXCHG:1595  case LoongArch::GCSRXCHG: {1596    MCRegister Rj = Inst.getOperand(2).getReg();1597    if (Rj == LoongArch::R0 || Rj == LoongArch::R1)1598      return Match_RequiresOpnd2NotR0R1;1599    return Match_Success;1600  }1601  case LoongArch::BSTRINS_W:1602  case LoongArch::BSTRINS_D:1603  case LoongArch::BSTRPICK_W:1604  case LoongArch::BSTRPICK_D: {1605    unsigned Opc = Inst.getOpcode();1606    const signed Msb =1607        (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)1608            ? Inst.getOperand(3).getImm()1609            : Inst.getOperand(2).getImm();1610    const signed Lsb =1611        (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)1612            ? Inst.getOperand(4).getImm()1613            : Inst.getOperand(3).getImm();1614    if (Msb < Lsb)1615      return Match_RequiresMsbNotLessThanLsb;1616    return Match_Success;1617  }1618  }1619 1620  return Match_Success;1621}1622 1623unsigned1624LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,1625                                               unsigned Kind) {1626  LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);1627  if (!Op.isReg())1628    return Match_InvalidOperand;1629 1630  MCRegister Reg = Op.getReg();1631  // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the1632  // register from FPR32 to FPR64 if necessary.1633  if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&1634      Kind == MCK_FPR64) {1635    Op.setReg(convertFPR32ToFPR64(Reg));1636    return Match_Success;1637  }1638 1639  if (Kind == MCK_GPRNoR0R1 && (Reg == LoongArch::R0 || Reg == LoongArch::R1))1640    return Match_RequiresOpnd2NotR0R1;1641 1642  return Match_InvalidOperand;1643}1644 1645bool LoongArchAsmParser::generateImmOutOfRangeError(1646    OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,1647    const Twine &Msg = "immediate must be an integer in the range") {1648  SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1649  return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");1650}1651 1652bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1653                                                 OperandVector &Operands,1654                                                 MCStreamer &Out,1655                                                 uint64_t &ErrorInfo,1656                                                 bool MatchingInlineAsm) {1657  MCInst Inst;1658  FeatureBitset MissingFeatures;1659 1660  auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,1661                                     MatchingInlineAsm);1662  switch (Result) {1663  default:1664    break;1665  case Match_Success:1666    return processInstruction(Inst, IDLoc, Operands, Out);1667  case Match_MissingFeature: {1668    assert(MissingFeatures.any() && "Unknown missing features!");1669    bool FirstFeature = true;1670    std::string Msg = "instruction requires the following:";1671    for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {1672      if (MissingFeatures[i]) {1673        Msg += FirstFeature ? " " : ", ";1674        Msg += getSubtargetFeatureName(i);1675        FirstFeature = false;1676      }1677    }1678    return Error(IDLoc, Msg);1679  }1680  case Match_MnemonicFail: {1681    FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());1682    std::string Suggestion = LoongArchMnemonicSpellCheck(1683        ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);1684    return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);1685  }1686  case Match_InvalidOperand: {1687    SMLoc ErrorLoc = IDLoc;1688    if (ErrorInfo != ~0ULL) {1689      if (ErrorInfo >= Operands.size())1690        return Error(ErrorLoc, "too few operands for instruction");1691 1692      ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1693      if (ErrorLoc == SMLoc())1694        ErrorLoc = IDLoc;1695    }1696    return Error(ErrorLoc, "invalid operand for instruction");1697  }1698  }1699 1700  // Handle the case when the error message is of specific type1701  // other than the generic Match_InvalidOperand, and the1702  // corresponding operand is missing.1703  if (Result > FIRST_TARGET_MATCH_RESULT_TY) {1704    SMLoc ErrorLoc = IDLoc;1705    if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())1706      return Error(ErrorLoc, "too few operands for instruction");1707  }1708 1709  switch (Result) {1710  default:1711    break;1712  case Match_RequiresMsbNotLessThanLsb: {1713    SMLoc ErrorStart = Operands[3]->getStartLoc();1714    return Error(ErrorStart, "msb is less than lsb",1715                 SMRange(ErrorStart, Operands[4]->getEndLoc()));1716  }1717  case Match_RequiresOpnd2NotR0R1:1718    return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");1719  case Match_RequiresAMORdDifferRkRj:1720    return Error(Operands[1]->getStartLoc(),1721                 "$rd must be different from both $rk and $rj");1722  case Match_RequiresLAORdDifferRj:1723    return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");1724  case Match_RequiresLAORdR4:1725    return Error(Operands[1]->getStartLoc(), "$rd must be $r4");1726  case Match_InvalidUImm1:1727    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1728                                      /*Upper=*/(1 << 1) - 1);1729  case Match_InvalidUImm2:1730    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1731                                      /*Upper=*/(1 << 2) - 1);1732  case Match_InvalidUImm2plus1:1733    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,1734                                      /*Upper=*/(1 << 2));1735  case Match_InvalidUImm3:1736    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1737                                      /*Upper=*/(1 << 3) - 1);1738  case Match_InvalidUImm4:1739    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1740                                      /*Upper=*/(1 << 4) - 1);1741  case Match_InvalidUImm5:1742    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1743                                      /*Upper=*/(1 << 5) - 1);1744  case Match_InvalidUImm6:1745    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1746                                      /*Upper=*/(1 << 6) - 1);1747  case Match_InvalidUImm7:1748    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1749                                      /*Upper=*/(1 << 7) - 1);1750  case Match_InvalidUImm8:1751    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1752                                      /*Upper=*/(1 << 8) - 1);1753  case Match_InvalidUImm12:1754    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1755                                      /*Upper=*/(1 << 12) - 1);1756  case Match_InvalidUImm12ori:1757    return generateImmOutOfRangeError(1758        Operands, ErrorInfo, /*Lower=*/0,1759        /*Upper=*/(1 << 12) - 1,1760        "operand must be a symbol with modifier (e.g. %abs_lo12) or an "1761        "integer in the range");1762  case Match_InvalidUImm14:1763    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1764                                      /*Upper=*/(1 << 14) - 1);1765  case Match_InvalidUImm15:1766    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1767                                      /*Upper=*/(1 << 15) - 1);1768  case Match_InvalidSImm5:1769    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),1770                                      /*Upper=*/(1 << 4) - 1);1771  case Match_InvalidSImm8:1772    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),1773                                      /*Upper=*/(1 << 7) - 1);1774  case Match_InvalidSImm8lsl1:1775    return generateImmOutOfRangeError(1776        Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,1777        "immediate must be a multiple of 2 in the range");1778  case Match_InvalidSImm8lsl2:1779    return generateImmOutOfRangeError(1780        Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,1781        "immediate must be a multiple of 4 in the range");1782  case Match_InvalidSImm10:1783    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),1784                                      /*Upper=*/(1 << 9) - 1);1785  case Match_InvalidSImm8lsl3:1786    return generateImmOutOfRangeError(1787        Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,1788        "immediate must be a multiple of 8 in the range");1789  case Match_InvalidSImm9lsl3:1790    return generateImmOutOfRangeError(1791        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,1792        "immediate must be a multiple of 8 in the range");1793  case Match_InvalidSImm10lsl2:1794    return generateImmOutOfRangeError(1795        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,1796        "immediate must be a multiple of 4 in the range");1797  case Match_InvalidSImm11lsl1:1798    return generateImmOutOfRangeError(1799        Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,1800        "immediate must be a multiple of 2 in the range");1801  case Match_InvalidSImm12:1802    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),1803                                      /*Upper=*/(1 << 11) - 1);1804  case Match_InvalidSImm12addlike:1805    return generateImmOutOfRangeError(1806        Operands, ErrorInfo, /*Lower=*/-(1 << 11),1807        /*Upper=*/(1 << 11) - 1,1808        "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "1809        "in the range");1810  case Match_InvalidSImm12lu52id:1811    return generateImmOutOfRangeError(1812        Operands, ErrorInfo, /*Lower=*/-(1 << 11),1813        /*Upper=*/(1 << 11) - 1,1814        "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "1815        "integer in the range");1816  case Match_InvalidSImm13:1817    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),1818                                      /*Upper=*/(1 << 12) - 1);1819  case Match_InvalidSImm14lsl2:1820    return generateImmOutOfRangeError(1821        Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,1822        "immediate must be a multiple of 4 in the range");1823  case Match_InvalidSImm16:1824    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),1825                                      /*Upper=*/(1 << 15) - 1);1826  case Match_InvalidSImm16lsl2:1827    return generateImmOutOfRangeError(1828        Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,1829        "operand must be a symbol with modifier (e.g. %b16) or an integer "1830        "in the range");1831  case Match_InvalidSImm20:1832    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),1833                                      /*Upper=*/(1 << 19) - 1);1834  case Match_InvalidSImm20lu12iw:1835    return generateImmOutOfRangeError(1836        Operands, ErrorInfo, /*Lower=*/-(1 << 19),1837        /*Upper=*/(1 << 19) - 1,1838        "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "1839        "in the range");1840  case Match_InvalidSImm20lu32id:1841    return generateImmOutOfRangeError(1842        Operands, ErrorInfo, /*Lower=*/-(1 << 19),1843        /*Upper=*/(1 << 19) - 1,1844        "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "1845        "integer in the range");1846  case Match_InvalidSImm20pcalau12i:1847    return generateImmOutOfRangeError(1848        Operands, ErrorInfo, /*Lower=*/-(1 << 19),1849        /*Upper=*/(1 << 19) - 1,1850        "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "1851        "in the range");1852  case Match_InvalidSImm20pcaddu18i:1853    return generateImmOutOfRangeError(1854        Operands, ErrorInfo, /*Lower=*/-(1 << 19),1855        /*Upper=*/(1 << 19) - 1,1856        "operand must be a symbol with modifier (e.g. %call36) or an integer "1857        "in the range");1858  case Match_InvalidSImm20pcaddi:1859    return generateImmOutOfRangeError(1860        Operands, ErrorInfo, /*Lower=*/-(1 << 19),1861        /*Upper=*/(1 << 19) - 1,1862        "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "1863        "in the range");1864  case Match_InvalidSImm21lsl2:1865    return generateImmOutOfRangeError(1866        Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,1867        "operand must be a symbol with modifier (e.g. %b21) or an integer "1868        "in the range");1869  case Match_InvalidSImm26Operand:1870    return generateImmOutOfRangeError(1871        Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,1872        "operand must be a bare symbol name or an immediate must be a multiple "1873        "of 4 in the range");1874  case Match_InvalidImm32: {1875    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1876    return Error(ErrorLoc, "operand must be a 32 bit immediate");1877  }1878  case Match_InvalidImm64: {1879    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1880    return Error(ErrorLoc, "operand must be a 64 bit immediate");1881  }1882  case Match_InvalidBareSymbol: {1883    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1884    return Error(ErrorLoc, "operand must be a bare symbol name");1885  }1886  case Match_InvalidTPRelAddSymbol: {1887    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1888    return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");1889  }1890  }1891  llvm_unreachable("Unknown match type detected!");1892}1893 1894bool LoongArchAsmParser::parseDirectiveOption() {1895  MCAsmParser &Parser = getParser();1896  // Get the option token.1897  AsmToken Tok = Parser.getTok();1898 1899  // At the moment only identifiers are supported.1900  if (parseToken(AsmToken::Identifier, "expected identifier"))1901    return true;1902 1903  StringRef Option = Tok.getIdentifier();1904 1905  if (Option == "push") {1906    if (Parser.parseEOL())1907      return true;1908 1909    getTargetStreamer().emitDirectiveOptionPush();1910    pushFeatureBits();1911    return false;1912  }1913 1914  if (Option == "pop") {1915    SMLoc StartLoc = Parser.getTok().getLoc();1916    if (Parser.parseEOL())1917      return true;1918 1919    getTargetStreamer().emitDirectiveOptionPop();1920    if (popFeatureBits())1921      return Error(StartLoc, ".option pop with no .option push");1922 1923    return false;1924  }1925 1926  if (Option == "relax") {1927    if (Parser.parseEOL())1928      return true;1929 1930    getTargetStreamer().emitDirectiveOptionRelax();1931    setFeatureBits(LoongArch::FeatureRelax, "relax");1932    return false;1933  }1934 1935  if (Option == "norelax") {1936    if (Parser.parseEOL())1937      return true;1938 1939    getTargetStreamer().emitDirectiveOptionNoRelax();1940    clearFeatureBits(LoongArch::FeatureRelax, "relax");1941    return false;1942  }1943 1944  // Unknown option.1945  Warning(Parser.getTok().getLoc(),1946          "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");1947  Parser.eatToEndOfStatement();1948  return false;1949}1950 1951ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {1952  if (DirectiveID.getString() == ".option")1953    return parseDirectiveOption();1954 1955  return ParseStatus::NoMatch;1956}1957 1958extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void1959LLVMInitializeLoongArchAsmParser() {1960  RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());1961  RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());1962}1963