xref: /llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (revision 89e3a649f207021c0884ed5f8e56321c51854ac3)
13347f77bSWeining Lu // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//
23347f77bSWeining Lu //
33347f77bSWeining Lu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43347f77bSWeining Lu // See https://llvm.org/LICENSE.txt for license information.
53347f77bSWeining Lu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63347f77bSWeining Lu //
73347f77bSWeining Lu //===----------------------------------------------------------------------===//
83347f77bSWeining Lu 
98234c612SWÁNG Xuěruì #include "MCTargetDesc/LoongArchBaseInfo.h"
103347f77bSWeining Lu #include "MCTargetDesc/LoongArchInstPrinter.h"
11c2ee21cfSwanglei #include "MCTargetDesc/LoongArchMCExpr.h"
123347f77bSWeining Lu #include "MCTargetDesc/LoongArchMCTargetDesc.h"
13f873c50cSwanglei #include "MCTargetDesc/LoongArchMatInt.h"
141a787b3cSwanglei #include "MCTargetDesc/LoongArchTargetStreamer.h"
153347f77bSWeining Lu #include "TargetInfo/LoongArchTargetInfo.h"
163347f77bSWeining Lu #include "llvm/MC/MCContext.h"
17a7ec7f6dSwanglei #include "llvm/MC/MCInstBuilder.h"
183347f77bSWeining Lu #include "llvm/MC/MCInstrInfo.h"
193347f77bSWeining Lu #include "llvm/MC/MCParser/MCAsmLexer.h"
203347f77bSWeining Lu #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
213347f77bSWeining Lu #include "llvm/MC/MCParser/MCTargetAsmParser.h"
223a49ad71SWeining Lu #include "llvm/MC/MCRegisterInfo.h"
233347f77bSWeining Lu #include "llvm/MC/MCStreamer.h"
243347f77bSWeining Lu #include "llvm/MC/MCSubtargetInfo.h"
25c2ee21cfSwanglei #include "llvm/MC/MCValue.h"
263347f77bSWeining Lu #include "llvm/MC/TargetRegistry.h"
273347f77bSWeining Lu #include "llvm/Support/Casting.h"
283347f77bSWeining Lu 
293347f77bSWeining Lu using namespace llvm;
303347f77bSWeining Lu 
313347f77bSWeining Lu #define DEBUG_TYPE "loongarch-asm-parser"
323347f77bSWeining Lu 
333347f77bSWeining Lu namespace {
343347f77bSWeining Lu class LoongArchAsmParser : public MCTargetAsmParser {
351a787b3cSwanglei   SmallVector<FeatureBitset, 4> FeatureBitStack;
361a787b3cSwanglei 
373347f77bSWeining Lu   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
38a7ec7f6dSwanglei   bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
391a787b3cSwanglei   LoongArchTargetStreamer &getTargetStreamer() {
401a787b3cSwanglei     assert(getParser().getStreamer().getTargetStreamer() &&
411a787b3cSwanglei            "do not have a target streamer");
421a787b3cSwanglei     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
431a787b3cSwanglei     return static_cast<LoongArchTargetStreamer &>(TS);
441a787b3cSwanglei   }
45a7ec7f6dSwanglei 
46a7ec7f6dSwanglei   struct Inst {
47a7ec7f6dSwanglei     unsigned Opc;
48a7ec7f6dSwanglei     LoongArchMCExpr::VariantKind VK;
49a7ec7f6dSwanglei     Inst(unsigned Opc,
50a7ec7f6dSwanglei          LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None)
51a7ec7f6dSwanglei         : Opc(Opc), VK(VK) {}
52a7ec7f6dSwanglei   };
53a7ec7f6dSwanglei   using InstSeq = SmallVector<Inst>;
543347f77bSWeining Lu 
553347f77bSWeining Lu   /// Parse a register as used in CFI directives.
56a479be0fSSergei Barannikov   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
57a479be0fSSergei Barannikov   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
583347f77bSWeining Lu                                SMLoc &EndLoc) override;
593347f77bSWeining Lu 
604b524088SLei Huang   bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
613347f77bSWeining Lu                         SMLoc NameLoc, OperandVector &Operands) override;
623347f77bSWeining Lu 
634b524088SLei Huang   bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
643347f77bSWeining Lu                                OperandVector &Operands, MCStreamer &Out,
653347f77bSWeining Lu                                uint64_t &ErrorInfo,
663347f77bSWeining Lu                                bool MatchingInlineAsm) override;
673347f77bSWeining Lu 
6824532d05SWeining Lu   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
6924532d05SWeining Lu 
703a49ad71SWeining Lu   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
713a49ad71SWeining Lu                                       unsigned Kind) override;
723a49ad71SWeining Lu 
731a787b3cSwanglei   ParseStatus parseDirective(AsmToken DirectiveID) override;
741a787b3cSwanglei 
753347f77bSWeining Lu   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
767ad4b262SCraig Topper                                   int64_t Lower, int64_t Upper,
777ad4b262SCraig Topper                                   const Twine &Msg);
783347f77bSWeining Lu 
793347f77bSWeining Lu   /// Helper for processing MC instructions that have been successfully matched
804b524088SLei Huang   /// by matchAndEmitInstruction.
813347f77bSWeining Lu   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
823347f77bSWeining Lu                           MCStreamer &Out);
833347f77bSWeining Lu 
843347f77bSWeining Lu // Auto-generated instruction matching functions.
853347f77bSWeining Lu #define GET_ASSEMBLER_HEADER
863347f77bSWeining Lu #include "LoongArchGenAsmMatcher.inc"
873347f77bSWeining Lu 
88cc6fabf4SSergei Barannikov   ParseStatus parseRegister(OperandVector &Operands);
89cc6fabf4SSergei Barannikov   ParseStatus parseImmediate(OperandVector &Operands);
90cc6fabf4SSergei Barannikov   ParseStatus parseOperandWithModifier(OperandVector &Operands);
91cc6fabf4SSergei Barannikov   ParseStatus parseSImm26Operand(OperandVector &Operands);
92cc6fabf4SSergei Barannikov   ParseStatus parseAtomicMemOp(OperandVector &Operands);
933347f77bSWeining Lu 
943347f77bSWeining Lu   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
953347f77bSWeining Lu 
961a787b3cSwanglei   bool parseDirectiveOption();
971a787b3cSwanglei 
981a787b3cSwanglei   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
991a787b3cSwanglei     if (!(getSTI().hasFeature(Feature))) {
1001a787b3cSwanglei       MCSubtargetInfo &STI = copySTI();
1011a787b3cSwanglei       setAvailableFeatures(
1021a787b3cSwanglei           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
1031a787b3cSwanglei     }
1041a787b3cSwanglei   }
1051a787b3cSwanglei 
1061a787b3cSwanglei   void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
1071a787b3cSwanglei     if (getSTI().hasFeature(Feature)) {
1081a787b3cSwanglei       MCSubtargetInfo &STI = copySTI();
1091a787b3cSwanglei       setAvailableFeatures(
1101a787b3cSwanglei           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
1111a787b3cSwanglei     }
1121a787b3cSwanglei   }
1131a787b3cSwanglei 
1141a787b3cSwanglei   void pushFeatureBits() {
1151a787b3cSwanglei     FeatureBitStack.push_back(getSTI().getFeatureBits());
1161a787b3cSwanglei   }
1171a787b3cSwanglei 
1181a787b3cSwanglei   bool popFeatureBits() {
1191a787b3cSwanglei     if (FeatureBitStack.empty())
1201a787b3cSwanglei       return true;
1211a787b3cSwanglei 
1221a787b3cSwanglei     FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
1231a787b3cSwanglei     copySTI().setFeatureBits(FeatureBits);
1241a787b3cSwanglei     setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
1251a787b3cSwanglei 
1261a787b3cSwanglei     return false;
1271a787b3cSwanglei   }
1281a787b3cSwanglei 
129a7ec7f6dSwanglei   // Helper to emit the sequence of instructions generated by the
130a7ec7f6dSwanglei   // "emitLoadAddress*" functions.
131a7ec7f6dSwanglei   void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
132a7ec7f6dSwanglei                      const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
133b3ef8dceSJinyang He                      SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
134a7ec7f6dSwanglei 
135a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.abs $rd, sym".
136a7ec7f6dSwanglei   void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
137a7ec7f6dSwanglei 
138a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.pcrel $rd, sym".
139a7ec7f6dSwanglei   void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
140a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
141a7ec7f6dSwanglei   void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
142a7ec7f6dSwanglei 
143a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.got $rd, sym".
144a7ec7f6dSwanglei   void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
145a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
146a7ec7f6dSwanglei   void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147a7ec7f6dSwanglei 
148a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.le $rd, sym".
149a7ec7f6dSwanglei   void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
150a7ec7f6dSwanglei 
151a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
152a7ec7f6dSwanglei   void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
153a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
154a7ec7f6dSwanglei   void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
155a7ec7f6dSwanglei 
156a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
157a7ec7f6dSwanglei   void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
158a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
159a7ec7f6dSwanglei   void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
160a7ec7f6dSwanglei 
161a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
162a7ec7f6dSwanglei   void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
163a7ec7f6dSwanglei   // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
164a7ec7f6dSwanglei   void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
165a7ec7f6dSwanglei 
1664a84d8e4Swanglei   // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
167affb2b73Swanglei   void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1684a84d8e4Swanglei   // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
169affb2b73Swanglei   void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1704a84d8e4Swanglei 
171f873c50cSwanglei   // Helper to emit pseudo instruction "li.w/d $rd, $imm".
172f873c50cSwanglei   void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
173f873c50cSwanglei 
1742cf420d5Swanglei   // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
1752cf420d5Swanglei   void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1762cf420d5Swanglei                       bool IsTailCall);
1772cf420d5Swanglei 
1783347f77bSWeining Lu public:
1793347f77bSWeining Lu   enum LoongArchMatchResultTy {
1803347f77bSWeining Lu     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
18124532d05SWeining Lu     Match_RequiresMsbNotLessThanLsb,
18211ec7307SWeining Lu     Match_RequiresOpnd2NotR0R1,
183c98add7aSWeining Lu     Match_RequiresAMORdDifferRkRj,
184a7ec7f6dSwanglei     Match_RequiresLAORdDifferRj,
1854a84d8e4Swanglei     Match_RequiresLAORdR4,
1863347f77bSWeining Lu #define GET_OPERAND_DIAGNOSTIC_TYPES
1873347f77bSWeining Lu #include "LoongArchGenAsmMatcher.inc"
1883347f77bSWeining Lu #undef GET_OPERAND_DIAGNOSTIC_TYPES
1893347f77bSWeining Lu   };
1903347f77bSWeining Lu 
191c2ee21cfSwanglei   static bool classifySymbolRef(const MCExpr *Expr,
192c2ee21cfSwanglei                                 LoongArchMCExpr::VariantKind &Kind);
193c2ee21cfSwanglei 
1943347f77bSWeining Lu   LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
1953347f77bSWeining Lu                      const MCInstrInfo &MII, const MCTargetOptions &Options)
1963347f77bSWeining Lu       : MCTargetAsmParser(Options, STI, MII) {
1973347f77bSWeining Lu     Parser.addAliasForDirective(".half", ".2byte");
1983347f77bSWeining Lu     Parser.addAliasForDirective(".hword", ".2byte");
1993347f77bSWeining Lu     Parser.addAliasForDirective(".word", ".4byte");
2003347f77bSWeining Lu     Parser.addAliasForDirective(".dword", ".8byte");
2013347f77bSWeining Lu 
2023347f77bSWeining Lu     // Initialize the set of available features.
2033347f77bSWeining Lu     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
2043347f77bSWeining Lu   }
2053347f77bSWeining Lu };
2063347f77bSWeining Lu 
20788436afeSFangrui Song // Instances of this class represent a parsed LoongArch machine instruction.
2083347f77bSWeining Lu class LoongArchOperand : public MCParsedAsmOperand {
2093347f77bSWeining Lu   enum class KindTy {
2103347f77bSWeining Lu     Token,
2113347f77bSWeining Lu     Register,
2123347f77bSWeining Lu     Immediate,
2133347f77bSWeining Lu   } Kind;
2143347f77bSWeining Lu 
2153347f77bSWeining Lu   struct RegOp {
2163347f77bSWeining Lu     MCRegister RegNum;
2173347f77bSWeining Lu   };
2183347f77bSWeining Lu 
2193347f77bSWeining Lu   struct ImmOp {
2203347f77bSWeining Lu     const MCExpr *Val;
2213347f77bSWeining Lu   };
2223347f77bSWeining Lu 
2233347f77bSWeining Lu   SMLoc StartLoc, EndLoc;
2243347f77bSWeining Lu   union {
2253347f77bSWeining Lu     StringRef Tok;
2263347f77bSWeining Lu     struct RegOp Reg;
2273347f77bSWeining Lu     struct ImmOp Imm;
2283347f77bSWeining Lu   };
2293347f77bSWeining Lu 
2303347f77bSWeining Lu public:
2313347f77bSWeining Lu   LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
2323347f77bSWeining Lu 
2333347f77bSWeining Lu   bool isToken() const override { return Kind == KindTy::Token; }
2343347f77bSWeining Lu   bool isReg() const override { return Kind == KindTy::Register; }
2353347f77bSWeining Lu   bool isImm() const override { return Kind == KindTy::Immediate; }
2363347f77bSWeining Lu   bool isMem() const override { return false; }
2373a49ad71SWeining Lu   void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
238899226adSwanglei   bool isGPR() const {
239899226adSwanglei     return Kind == KindTy::Register &&
240899226adSwanglei            LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
241899226adSwanglei                Reg.RegNum);
242899226adSwanglei   }
2433347f77bSWeining Lu 
244c2ee21cfSwanglei   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
245c2ee21cfSwanglei                                   LoongArchMCExpr::VariantKind &VK) {
246c2ee21cfSwanglei     if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
247c2ee21cfSwanglei       VK = LE->getKind();
248c2ee21cfSwanglei       return false;
249c2ee21cfSwanglei     }
250c2ee21cfSwanglei 
2513347f77bSWeining Lu     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
2523347f77bSWeining Lu       Imm = CE->getValue();
2533347f77bSWeining Lu       return true;
2543347f77bSWeining Lu     }
2553347f77bSWeining Lu 
2563347f77bSWeining Lu     return false;
2573347f77bSWeining Lu   }
2583347f77bSWeining Lu 
2593347f77bSWeining Lu   template <unsigned N, int P = 0> bool isUImm() const {
2603347f77bSWeining Lu     if (!isImm())
2613347f77bSWeining Lu       return false;
2623347f77bSWeining Lu 
2633347f77bSWeining Lu     int64_t Imm;
264c2ee21cfSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
265c2ee21cfSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
266c2ee21cfSwanglei     return IsConstantImm && isUInt<N>(Imm - P) &&
267c2ee21cfSwanglei            VK == LoongArchMCExpr::VK_LoongArch_None;
2683347f77bSWeining Lu   }
2693347f77bSWeining Lu 
2703347f77bSWeining Lu   template <unsigned N, unsigned S = 0> bool isSImm() const {
2713347f77bSWeining Lu     if (!isImm())
2723347f77bSWeining Lu       return false;
2733347f77bSWeining Lu 
2743347f77bSWeining Lu     int64_t Imm;
275c2ee21cfSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
276c2ee21cfSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
277c2ee21cfSwanglei     return IsConstantImm && isShiftedInt<N, S>(Imm) &&
278c2ee21cfSwanglei            VK == LoongArchMCExpr::VK_LoongArch_None;
2793347f77bSWeining Lu   }
2803347f77bSWeining Lu 
281a7ec7f6dSwanglei   bool isBareSymbol() const {
282a7ec7f6dSwanglei     int64_t Imm;
283a7ec7f6dSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
284a7ec7f6dSwanglei     // Must be of 'immediate' type but not a constant.
285a7ec7f6dSwanglei     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
286a7ec7f6dSwanglei       return false;
287a7ec7f6dSwanglei     return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
288a7ec7f6dSwanglei            VK == LoongArchMCExpr::VK_LoongArch_None;
289a7ec7f6dSwanglei   }
290a7ec7f6dSwanglei 
2910f231567Swanglei   bool isTPRelAddSymbol() const {
2920f231567Swanglei     int64_t Imm;
2930f231567Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
2940f231567Swanglei     // Must be of 'immediate' type but not a constant.
2950f231567Swanglei     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
2960f231567Swanglei       return false;
2970f231567Swanglei     return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
2980f231567Swanglei            VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
2990f231567Swanglei   }
3000f231567Swanglei 
3011aa3b64eSwanglei   bool isUImm1() const { return isUImm<1>(); }
3023347f77bSWeining Lu   bool isUImm2() const { return isUImm<2>(); }
3033347f77bSWeining Lu   bool isUImm2plus1() const { return isUImm<2, 1>(); }
3043347f77bSWeining Lu   bool isUImm3() const { return isUImm<3>(); }
3051aa3b64eSwanglei   bool isUImm4() const { return isUImm<4>(); }
3061aa3b64eSwanglei   bool isSImm5() const { return isSImm<5>(); }
3073347f77bSWeining Lu   bool isUImm5() const { return isUImm<5>(); }
3083347f77bSWeining Lu   bool isUImm6() const { return isUImm<6>(); }
3091aa3b64eSwanglei   bool isUImm7() const { return isUImm<7>(); }
3101aa3b64eSwanglei   bool isSImm8() const { return isSImm<8>(); }
3111aa3b64eSwanglei   bool isSImm8lsl1() const { return isSImm<8, 1>(); }
3121aa3b64eSwanglei   bool isSImm8lsl2() const { return isSImm<8, 2>(); }
3131aa3b64eSwanglei   bool isSImm8lsl3() const { return isSImm<8, 3>(); }
31411ec7307SWeining Lu   bool isUImm8() const { return isUImm<8>(); }
3151aa3b64eSwanglei   bool isSImm9lsl3() const { return isSImm<9, 3>(); }
3161aa3b64eSwanglei   bool isSImm10() const { return isSImm<10>(); }
3171aa3b64eSwanglei   bool isSImm10lsl2() const { return isSImm<10, 2>(); }
3181aa3b64eSwanglei   bool isSImm11lsl1() const { return isSImm<11, 1>(); }
319bf479547Swanglei   bool isSImm12() const { return isSImm<12>(); }
320c2ee21cfSwanglei 
321bf479547Swanglei   bool isSImm12addlike() const {
322c2ee21cfSwanglei     if (!isImm())
323c2ee21cfSwanglei       return false;
324c2ee21cfSwanglei 
325c2ee21cfSwanglei     int64_t Imm;
326c2ee21cfSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
327c2ee21cfSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
328bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
329bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
330bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
3314a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
3320f231567Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||
3334a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
3344a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
335c2ee21cfSwanglei     return IsConstantImm
336bf479547Swanglei                ? isInt<12>(Imm) && IsValidKind
337bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
338bf479547Swanglei                      IsValidKind;
339c2ee21cfSwanglei   }
340c2ee21cfSwanglei 
341bf479547Swanglei   bool isSImm12lu52id() const {
342bf479547Swanglei     if (!isImm())
343bf479547Swanglei       return false;
344bf479547Swanglei 
345bf479547Swanglei     int64_t Imm;
346bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
347bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
348bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
349bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
350bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
351bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
352bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
353bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
354bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
3554a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 ||
3564a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 ||
3574a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
358bf479547Swanglei     return IsConstantImm
359bf479547Swanglei                ? isInt<12>(Imm) && IsValidKind
360bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
361bf479547Swanglei                      IsValidKind;
362bf479547Swanglei   }
363bf479547Swanglei 
364bf479547Swanglei   bool isUImm12() const { return isUImm<12>(); }
365bf479547Swanglei 
366bf479547Swanglei   bool isUImm12ori() const {
367bf479547Swanglei     if (!isImm())
368bf479547Swanglei       return false;
369bf479547Swanglei 
370bf479547Swanglei     int64_t Imm;
371bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
372bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
373bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
374bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
375bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
376bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
377bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
378bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
379bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
3804a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
3814a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12;
382bf479547Swanglei     return IsConstantImm
383bf479547Swanglei                ? isUInt<12>(Imm) && IsValidKind
384bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
385bf479547Swanglei                      IsValidKind;
386bf479547Swanglei   }
387bf479547Swanglei 
3881aa3b64eSwanglei   bool isSImm13() const { return isSImm<13>(); }
389bf479547Swanglei   bool isUImm14() const { return isUImm<14>(); }
390bf479547Swanglei   bool isUImm15() const { return isUImm<15>(); }
391bf479547Swanglei 
3923347f77bSWeining Lu   bool isSImm14lsl2() const { return isSImm<14, 2>(); }
3933347f77bSWeining Lu   bool isSImm16() const { return isSImm<16>(); }
394bf479547Swanglei 
395bf479547Swanglei   bool isSImm16lsl2() const {
396bf479547Swanglei     if (!isImm())
397bf479547Swanglei       return false;
398bf479547Swanglei 
399bf479547Swanglei     int64_t Imm;
400bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
401bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
402bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
403af6c43c8SWANG Xuerui                        VK == LoongArchMCExpr::VK_LoongArch_B16 ||
4044a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
4054a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
406bf479547Swanglei     return IsConstantImm
407bf479547Swanglei                ? isShiftedInt<16, 2>(Imm) && IsValidKind
408bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
409bf479547Swanglei                      IsValidKind;
410bf479547Swanglei   }
411bf479547Swanglei 
4123347f77bSWeining Lu   bool isSImm20() const { return isSImm<20>(); }
413c2ee21cfSwanglei 
414c2ee21cfSwanglei   bool isSImm20pcalau12i() const {
415c2ee21cfSwanglei     if (!isImm())
416c2ee21cfSwanglei       return false;
417c2ee21cfSwanglei 
418c2ee21cfSwanglei     int64_t Imm;
419c2ee21cfSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
420c2ee21cfSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
421bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
422bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
423bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
424bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
425bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
4264a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 ||
4274a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
428c2ee21cfSwanglei     return IsConstantImm
429bf479547Swanglei                ? isInt<20>(Imm) && IsValidKind
430bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
431bf479547Swanglei                      IsValidKind;
432c2ee21cfSwanglei   }
433c2ee21cfSwanglei 
434bf479547Swanglei   bool isSImm20lu12iw() const {
435bf479547Swanglei     if (!isImm())
436bf479547Swanglei       return false;
437c2ee21cfSwanglei 
438c2ee21cfSwanglei     int64_t Imm;
439c2ee21cfSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
440c2ee21cfSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
441bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
442bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
443bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
444bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
445bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
446bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
4474a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||
4480f231567Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||
4494a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
450bf479547Swanglei     return IsConstantImm
451bf479547Swanglei                ? isInt<20>(Imm) && IsValidKind
452bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
453bf479547Swanglei                      IsValidKind;
454bf479547Swanglei   }
455bf479547Swanglei 
456bf479547Swanglei   bool isSImm20lu32id() const {
457bf479547Swanglei     if (!isImm())
458bf479547Swanglei       return false;
459bf479547Swanglei 
460bf479547Swanglei     int64_t Imm;
461bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
462bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
463bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
464bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
465bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
466bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
467bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
468bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
469bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
4704a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 ||
4714a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 ||
4724a84d8e4Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20;
473c2ee21cfSwanglei 
474c2ee21cfSwanglei     return IsConstantImm
475bf479547Swanglei                ? isInt<20>(Imm) && IsValidKind
476bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
477bf479547Swanglei                      IsValidKind;
478bf479547Swanglei   }
479bf479547Swanglei 
4802cf420d5Swanglei   bool isSImm20pcaddu18i() const {
4812cf420d5Swanglei     if (!isImm())
4822cf420d5Swanglei       return false;
4832cf420d5Swanglei 
4842cf420d5Swanglei     int64_t Imm;
4852cf420d5Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
4862cf420d5Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
4872cf420d5Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
4882cf420d5Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_CALL36;
4892cf420d5Swanglei 
4902cf420d5Swanglei     return IsConstantImm
4912cf420d5Swanglei                ? isInt<20>(Imm) && IsValidKind
4922cf420d5Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
4932cf420d5Swanglei                      IsValidKind;
4942cf420d5Swanglei   }
4952cf420d5Swanglei 
496e27358c8Swanglei   bool isSImm20pcaddi() const {
497e27358c8Swanglei     if (!isImm())
498e27358c8Swanglei       return false;
499e27358c8Swanglei 
500e27358c8Swanglei     int64_t Imm;
501e27358c8Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
502e27358c8Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
503e27358c8Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
504e27358c8Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_PCREL20_S2 ||
505e27358c8Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 ||
506e27358c8Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 ||
507e27358c8Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2;
508e27358c8Swanglei     return IsConstantImm
509e27358c8Swanglei                ? isInt<20>(Imm) && IsValidKind
510e27358c8Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
511e27358c8Swanglei                      IsValidKind;
512e27358c8Swanglei   }
513e27358c8Swanglei 
514bf479547Swanglei   bool isSImm21lsl2() const {
515bf479547Swanglei     if (!isImm())
516bf479547Swanglei       return false;
517bf479547Swanglei 
518bf479547Swanglei     int64_t Imm;
519bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
520bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
521bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
522bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_B21;
523bf479547Swanglei     return IsConstantImm
524bf479547Swanglei                ? isShiftedInt<21, 2>(Imm) && IsValidKind
525bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
526bf479547Swanglei                      IsValidKind;
527bf479547Swanglei   }
528bf479547Swanglei 
529bf479547Swanglei   bool isSImm26Operand() const {
530bf479547Swanglei     if (!isImm())
531bf479547Swanglei       return false;
532bf479547Swanglei 
533bf479547Swanglei     int64_t Imm;
534bf479547Swanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
535bf479547Swanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
536bf479547Swanglei     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
537bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_CALL ||
538bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
539bf479547Swanglei                        VK == LoongArchMCExpr::VK_LoongArch_B26;
540bf479547Swanglei     return IsConstantImm
541bf479547Swanglei                ? isShiftedInt<26, 2>(Imm) && IsValidKind
542bf479547Swanglei                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
543bf479547Swanglei                      IsValidKind;
544c2ee21cfSwanglei   }
5453347f77bSWeining Lu 
546f873c50cSwanglei   bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
547078aaf1fSwanglei   bool isImm64() const {
548078aaf1fSwanglei     if (!isImm())
549078aaf1fSwanglei       return false;
550078aaf1fSwanglei     int64_t Imm;
551078aaf1fSwanglei     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
552078aaf1fSwanglei     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
553078aaf1fSwanglei     return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
554078aaf1fSwanglei   }
555f873c50cSwanglei 
5563347f77bSWeining Lu   /// Gets location of the first token of this operand.
5573347f77bSWeining Lu   SMLoc getStartLoc() const override { return StartLoc; }
5583347f77bSWeining Lu   /// Gets location of the last token of this operand.
5593347f77bSWeining Lu   SMLoc getEndLoc() const override { return EndLoc; }
5603347f77bSWeining Lu 
5615e5b6561SSergei Barannikov   MCRegister getReg() const override {
5623347f77bSWeining Lu     assert(Kind == KindTy::Register && "Invalid type access!");
5635e5b6561SSergei Barannikov     return Reg.RegNum;
5643347f77bSWeining Lu   }
5653347f77bSWeining Lu 
5663347f77bSWeining Lu   const MCExpr *getImm() const {
5673347f77bSWeining Lu     assert(Kind == KindTy::Immediate && "Invalid type access!");
5683347f77bSWeining Lu     return Imm.Val;
5693347f77bSWeining Lu   }
5703347f77bSWeining Lu 
5713347f77bSWeining Lu   StringRef getToken() const {
5723347f77bSWeining Lu     assert(Kind == KindTy::Token && "Invalid type access!");
5733347f77bSWeining Lu     return Tok;
5743347f77bSWeining Lu   }
5753347f77bSWeining Lu 
5763347f77bSWeining Lu   void print(raw_ostream &OS) const override {
5776ae84d66SSergei Barannikov     auto RegName = [](MCRegister Reg) {
5783347f77bSWeining Lu       if (Reg)
5793347f77bSWeining Lu         return LoongArchInstPrinter::getRegisterName(Reg);
5803347f77bSWeining Lu       else
5813347f77bSWeining Lu         return "noreg";
5823347f77bSWeining Lu     };
5833347f77bSWeining Lu 
5843347f77bSWeining Lu     switch (Kind) {
5853347f77bSWeining Lu     case KindTy::Immediate:
5863347f77bSWeining Lu       OS << *getImm();
5873347f77bSWeining Lu       break;
5883347f77bSWeining Lu     case KindTy::Register:
5893347f77bSWeining Lu       OS << "<register " << RegName(getReg()) << ">";
5903347f77bSWeining Lu       break;
5913347f77bSWeining Lu     case KindTy::Token:
5923347f77bSWeining Lu       OS << "'" << getToken() << "'";
5933347f77bSWeining Lu       break;
5943347f77bSWeining Lu     }
5953347f77bSWeining Lu   }
5963347f77bSWeining Lu 
5973347f77bSWeining Lu   static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
5983347f77bSWeining Lu     auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
5993347f77bSWeining Lu     Op->Tok = Str;
6003347f77bSWeining Lu     Op->StartLoc = S;
6013347f77bSWeining Lu     Op->EndLoc = S;
6023347f77bSWeining Lu     return Op;
6033347f77bSWeining Lu   }
6043347f77bSWeining Lu 
605c38b5c81SCraig Topper   static std::unique_ptr<LoongArchOperand> createReg(MCRegister Reg, SMLoc S,
6063347f77bSWeining Lu                                                      SMLoc E) {
6073347f77bSWeining Lu     auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
608c38b5c81SCraig Topper     Op->Reg.RegNum = Reg;
6093347f77bSWeining Lu     Op->StartLoc = S;
6103347f77bSWeining Lu     Op->EndLoc = E;
6113347f77bSWeining Lu     return Op;
6123347f77bSWeining Lu   }
6133347f77bSWeining Lu 
6143347f77bSWeining Lu   static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
6153347f77bSWeining Lu                                                      SMLoc E) {
6163347f77bSWeining Lu     auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
6173347f77bSWeining Lu     Op->Imm.Val = Val;
6183347f77bSWeining Lu     Op->StartLoc = S;
6193347f77bSWeining Lu     Op->EndLoc = E;
6203347f77bSWeining Lu     return Op;
6213347f77bSWeining Lu   }
6223347f77bSWeining Lu 
6233347f77bSWeining Lu   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
6243347f77bSWeining Lu     if (auto CE = dyn_cast<MCConstantExpr>(Expr))
6253347f77bSWeining Lu       Inst.addOperand(MCOperand::createImm(CE->getValue()));
6263347f77bSWeining Lu     else
6273347f77bSWeining Lu       Inst.addOperand(MCOperand::createExpr(Expr));
6283347f77bSWeining Lu   }
6293347f77bSWeining Lu 
6303347f77bSWeining Lu   // Used by the TableGen Code.
6313347f77bSWeining Lu   void addRegOperands(MCInst &Inst, unsigned N) const {
6323347f77bSWeining Lu     assert(N == 1 && "Invalid number of operands!");
6333347f77bSWeining Lu     Inst.addOperand(MCOperand::createReg(getReg()));
6343347f77bSWeining Lu   }
6353347f77bSWeining Lu   void addImmOperands(MCInst &Inst, unsigned N) const {
6363347f77bSWeining Lu     assert(N == 1 && "Invalid number of operands!");
6373347f77bSWeining Lu     addExpr(Inst, getImm());
6383347f77bSWeining Lu   }
6393347f77bSWeining Lu };
640904a87acSWeining Lu } // end namespace
6413347f77bSWeining Lu 
6423347f77bSWeining Lu #define GET_REGISTER_MATCHER
6433347f77bSWeining Lu #define GET_SUBTARGET_FEATURE_NAME
6443347f77bSWeining Lu #define GET_MATCHER_IMPLEMENTATION
6453347f77bSWeining Lu #define GET_MNEMONIC_SPELL_CHECKER
6463347f77bSWeining Lu #include "LoongArchGenAsmMatcher.inc"
6473347f77bSWeining Lu 
6483a49ad71SWeining Lu static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
6493a49ad71SWeining Lu   assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
6503a49ad71SWeining Lu   return Reg - LoongArch::F0 + LoongArch::F0_64;
6513a49ad71SWeining Lu }
6523a49ad71SWeining Lu 
6533a49ad71SWeining Lu // Attempts to match Name as a register (either using the default name or
6543a49ad71SWeining Lu // alternative ABI names), setting RegNo to the matching register. Upon
6553a49ad71SWeining Lu // failure, returns true and sets RegNo to 0.
6563347f77bSWeining Lu static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
6573347f77bSWeining Lu   RegNo = MatchRegisterName(Name);
6583a49ad71SWeining Lu   // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
6593a49ad71SWeining Lu   // match always matches the 32-bit variant, and not the 64-bit one.
6603a49ad71SWeining Lu   assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
6613a49ad71SWeining Lu   // The default FPR register class is based on the tablegen enum ordering.
6623a49ad71SWeining Lu   static_assert(LoongArch::F0 < LoongArch::F0_64,
6633a49ad71SWeining Lu                 "FPR matching must be updated");
6643347f77bSWeining Lu   if (RegNo == LoongArch::NoRegister)
6653347f77bSWeining Lu     RegNo = MatchRegisterAltName(Name);
6663347f77bSWeining Lu 
6673347f77bSWeining Lu   return RegNo == LoongArch::NoRegister;
6683347f77bSWeining Lu }
6693347f77bSWeining Lu 
670a479be0fSSergei Barannikov bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
6713347f77bSWeining Lu                                        SMLoc &EndLoc) {
6723f1e7ef5Swanglei   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
6733f1e7ef5Swanglei     return Error(getLoc(), "invalid register name");
6743f1e7ef5Swanglei 
6753f1e7ef5Swanglei   if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
6763f1e7ef5Swanglei       !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
6773f1e7ef5Swanglei     return Error(getLoc(), "invalid register name");
6783f1e7ef5Swanglei 
6793f1e7ef5Swanglei   return false;
6803347f77bSWeining Lu }
6813347f77bSWeining Lu 
682a479be0fSSergei Barannikov ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
6833347f77bSWeining Lu                                                  SMLoc &StartLoc,
6843347f77bSWeining Lu                                                  SMLoc &EndLoc) {
6853f1e7ef5Swanglei   const AsmToken &Tok = getParser().getTok();
6863f1e7ef5Swanglei   StartLoc = Tok.getLoc();
6873f1e7ef5Swanglei   EndLoc = Tok.getEndLoc();
6883f1e7ef5Swanglei 
6893f1e7ef5Swanglei   parseOptionalToken(AsmToken::Dollar);
6903f1e7ef5Swanglei   if (getLexer().getKind() != AsmToken::Identifier)
6913f1e7ef5Swanglei     return ParseStatus::NoMatch;
6923f1e7ef5Swanglei 
6933f1e7ef5Swanglei   StringRef Name = Tok.getIdentifier();
6943f1e7ef5Swanglei   if (matchRegisterNameHelper(Reg, Name))
6953f1e7ef5Swanglei     return ParseStatus::NoMatch;
6963f1e7ef5Swanglei 
6973f1e7ef5Swanglei   getParser().Lex(); // Eat identifier token.
6983f1e7ef5Swanglei   return ParseStatus::Success;
6993347f77bSWeining Lu }
7003347f77bSWeining Lu 
701c2ee21cfSwanglei bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
702c2ee21cfSwanglei                                            LoongArchMCExpr::VariantKind &Kind) {
703c2ee21cfSwanglei   Kind = LoongArchMCExpr::VK_LoongArch_None;
704c2ee21cfSwanglei 
705c2ee21cfSwanglei   if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
706c2ee21cfSwanglei     Kind = RE->getKind();
707c2ee21cfSwanglei     Expr = RE->getSubExpr();
708c2ee21cfSwanglei   }
709c2ee21cfSwanglei 
710c2ee21cfSwanglei   MCValue Res;
711c2ee21cfSwanglei   if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
712c2ee21cfSwanglei     return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;
713c2ee21cfSwanglei   return false;
714c2ee21cfSwanglei }
715c2ee21cfSwanglei 
716cc6fabf4SSergei Barannikov ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
717f03a16e6SFangrui Song   if (!parseOptionalToken(AsmToken::Dollar))
718cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
7193347f77bSWeining Lu   if (getLexer().getKind() != AsmToken::Identifier)
720cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
7213347f77bSWeining Lu 
7223347f77bSWeining Lu   StringRef Name = getLexer().getTok().getIdentifier();
7233347f77bSWeining Lu   MCRegister RegNo;
7243347f77bSWeining Lu   matchRegisterNameHelper(RegNo, Name);
7253347f77bSWeining Lu   if (RegNo == LoongArch::NoRegister)
726cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
7273347f77bSWeining Lu 
7283347f77bSWeining Lu   SMLoc S = getLoc();
7293347f77bSWeining Lu   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
7303347f77bSWeining Lu   getLexer().Lex();
7313347f77bSWeining Lu   Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
7323347f77bSWeining Lu 
733cc6fabf4SSergei Barannikov   return ParseStatus::Success;
7343347f77bSWeining Lu }
7353347f77bSWeining Lu 
736cc6fabf4SSergei Barannikov ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
7373347f77bSWeining Lu   SMLoc S = getLoc();
7383347f77bSWeining Lu   SMLoc E;
7393347f77bSWeining Lu   const MCExpr *Res;
7403347f77bSWeining Lu 
741c2ee21cfSwanglei   switch (getLexer().getKind()) {
742c2ee21cfSwanglei   default:
743cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
744c2ee21cfSwanglei   case AsmToken::LParen:
745c2ee21cfSwanglei   case AsmToken::Dot:
746c2ee21cfSwanglei   case AsmToken::Minus:
747c2ee21cfSwanglei   case AsmToken::Plus:
748c2ee21cfSwanglei   case AsmToken::Exclaim:
749c2ee21cfSwanglei   case AsmToken::Tilde:
750c2ee21cfSwanglei   case AsmToken::Integer:
751c2ee21cfSwanglei   case AsmToken::String:
752c2ee21cfSwanglei   case AsmToken::Identifier:
7533347f77bSWeining Lu     if (getParser().parseExpression(Res, E))
754cc6fabf4SSergei Barannikov       return ParseStatus::Failure;
755c2ee21cfSwanglei     break;
756c2ee21cfSwanglei   case AsmToken::Percent:
757c2ee21cfSwanglei     return parseOperandWithModifier(Operands);
758c2ee21cfSwanglei   }
7593347f77bSWeining Lu 
7603347f77bSWeining Lu   Operands.push_back(LoongArchOperand::createImm(Res, S, E));
761cc6fabf4SSergei Barannikov   return ParseStatus::Success;
7623347f77bSWeining Lu }
7633347f77bSWeining Lu 
764cc6fabf4SSergei Barannikov ParseStatus
765c2ee21cfSwanglei LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
766c2ee21cfSwanglei   SMLoc S = getLoc();
767c2ee21cfSwanglei   SMLoc E;
768c2ee21cfSwanglei 
769cc6fabf4SSergei Barannikov   if (getLexer().getKind() != AsmToken::Percent)
770cc6fabf4SSergei Barannikov     return Error(getLoc(), "expected '%' for operand modifier");
771c2ee21cfSwanglei 
772c2ee21cfSwanglei   getParser().Lex(); // Eat '%'
773c2ee21cfSwanglei 
774cc6fabf4SSergei Barannikov   if (getLexer().getKind() != AsmToken::Identifier)
775cc6fabf4SSergei Barannikov     return Error(getLoc(), "expected valid identifier for operand modifier");
776c2ee21cfSwanglei   StringRef Identifier = getParser().getTok().getIdentifier();
777c2ee21cfSwanglei   LoongArchMCExpr::VariantKind VK =
778c2ee21cfSwanglei       LoongArchMCExpr::getVariantKindForName(Identifier);
779cc6fabf4SSergei Barannikov   if (VK == LoongArchMCExpr::VK_LoongArch_Invalid)
780cc6fabf4SSergei Barannikov     return Error(getLoc(), "unrecognized operand modifier");
781c2ee21cfSwanglei 
782c2ee21cfSwanglei   getParser().Lex(); // Eat the identifier
783cc6fabf4SSergei Barannikov   if (getLexer().getKind() != AsmToken::LParen)
784cc6fabf4SSergei Barannikov     return Error(getLoc(), "expected '('");
785c2ee21cfSwanglei   getParser().Lex(); // Eat '('
786c2ee21cfSwanglei 
787c2ee21cfSwanglei   const MCExpr *SubExpr;
788cc6fabf4SSergei Barannikov   if (getParser().parseParenExpression(SubExpr, E))
789cc6fabf4SSergei Barannikov     return ParseStatus::Failure;
790c2ee21cfSwanglei 
791c2ee21cfSwanglei   const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
792c2ee21cfSwanglei   Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
793cc6fabf4SSergei Barannikov   return ParseStatus::Success;
794c2ee21cfSwanglei }
795c2ee21cfSwanglei 
796cc6fabf4SSergei Barannikov ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
797c2ee21cfSwanglei   SMLoc S = getLoc();
798c2ee21cfSwanglei   const MCExpr *Res;
799c2ee21cfSwanglei 
800c2ee21cfSwanglei   if (getLexer().getKind() == AsmToken::Percent)
801c2ee21cfSwanglei     return parseOperandWithModifier(Operands);
802c2ee21cfSwanglei 
803c2ee21cfSwanglei   if (getLexer().getKind() != AsmToken::Identifier)
804cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
805c2ee21cfSwanglei 
806c2ee21cfSwanglei   StringRef Identifier;
807c2ee21cfSwanglei   if (getParser().parseIdentifier(Identifier))
808cc6fabf4SSergei Barannikov     return ParseStatus::Failure;
809c2ee21cfSwanglei 
810c2ee21cfSwanglei   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
811c2ee21cfSwanglei 
812c2ee21cfSwanglei   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
813c2ee21cfSwanglei   Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
814c2ee21cfSwanglei   Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL,
815c2ee21cfSwanglei                                 getContext());
816c2ee21cfSwanglei   Operands.push_back(LoongArchOperand::createImm(Res, S, E));
817cc6fabf4SSergei Barannikov   return ParseStatus::Success;
818c2ee21cfSwanglei }
819c2ee21cfSwanglei 
820cc6fabf4SSergei Barannikov ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
821899226adSwanglei   // Parse "$r*".
822cc6fabf4SSergei Barannikov   if (!parseRegister(Operands).isSuccess())
823cc6fabf4SSergei Barannikov     return ParseStatus::NoMatch;
824899226adSwanglei 
825899226adSwanglei   // If there is a next operand and it is 0, ignore it. Otherwise print a
826899226adSwanglei   // diagnostic message.
827f03a16e6SFangrui Song   if (parseOptionalToken(AsmToken::Comma)) {
828899226adSwanglei     int64_t ImmVal;
829899226adSwanglei     SMLoc ImmStart = getLoc();
830899226adSwanglei     if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
831cc6fabf4SSergei Barannikov       return ParseStatus::Failure;
832cc6fabf4SSergei Barannikov     if (ImmVal)
833cc6fabf4SSergei Barannikov       return Error(ImmStart, "optional integer offset must be 0");
834899226adSwanglei   }
835899226adSwanglei 
836cc6fabf4SSergei Barannikov   return ParseStatus::Success;
837899226adSwanglei }
8383347f77bSWeining Lu /// Looks at a token type and creates the relevant operand from this
8393347f77bSWeining Lu /// information, adding to Operands. Return true upon an error.
8403347f77bSWeining Lu bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
8413347f77bSWeining Lu                                       StringRef Mnemonic) {
842c2ee21cfSwanglei   // Check if the current operand has a custom associated parser, if so, try to
843c2ee21cfSwanglei   // custom parse the operand, or fallback to the general approach.
844cc6fabf4SSergei Barannikov   ParseStatus Result =
845c2ee21cfSwanglei       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
846cc6fabf4SSergei Barannikov   if (Result.isSuccess())
847c2ee21cfSwanglei     return false;
848cc6fabf4SSergei Barannikov   if (Result.isFailure())
849c2ee21cfSwanglei     return true;
850c2ee21cfSwanglei 
851cc6fabf4SSergei Barannikov   if (parseRegister(Operands).isSuccess() ||
852cc6fabf4SSergei Barannikov       parseImmediate(Operands).isSuccess())
8533347f77bSWeining Lu     return false;
8543347f77bSWeining Lu 
8553347f77bSWeining Lu   // Finally we have exhausted all options and must declare defeat.
856cc6fabf4SSergei Barannikov   return Error(getLoc(), "unknown operand");
8573347f77bSWeining Lu }
8583347f77bSWeining Lu 
8594b524088SLei Huang bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo &Info,
8603347f77bSWeining Lu                                           StringRef Name, SMLoc NameLoc,
8613347f77bSWeining Lu                                           OperandVector &Operands) {
8623347f77bSWeining Lu   // First operand in MCInst is instruction mnemonic.
8633347f77bSWeining Lu   Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
8643347f77bSWeining Lu 
8653347f77bSWeining Lu   // If there are no more operands, then finish.
8663347f77bSWeining Lu   if (parseOptionalToken(AsmToken::EndOfStatement))
8673347f77bSWeining Lu     return false;
8683347f77bSWeining Lu 
8693347f77bSWeining Lu   // Parse first operand.
8703347f77bSWeining Lu   if (parseOperand(Operands, Name))
8713347f77bSWeining Lu     return true;
8723347f77bSWeining Lu 
8733347f77bSWeining Lu   // Parse until end of statement, consuming commas between operands.
8743347f77bSWeining Lu   while (parseOptionalToken(AsmToken::Comma))
8753347f77bSWeining Lu     if (parseOperand(Operands, Name))
8763347f77bSWeining Lu       return true;
8773347f77bSWeining Lu 
8783347f77bSWeining Lu   // Parse end of statement and return successfully.
8793347f77bSWeining Lu   if (parseOptionalToken(AsmToken::EndOfStatement))
8803347f77bSWeining Lu     return false;
8813347f77bSWeining Lu 
8823347f77bSWeining Lu   SMLoc Loc = getLexer().getLoc();
8833347f77bSWeining Lu   getParser().eatToEndOfStatement();
8843347f77bSWeining Lu   return Error(Loc, "unexpected token");
8853347f77bSWeining Lu }
8863347f77bSWeining Lu 
887a7ec7f6dSwanglei void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
888a7ec7f6dSwanglei                                        const MCExpr *Symbol,
889a7ec7f6dSwanglei                                        SmallVectorImpl<Inst> &Insts,
890b3ef8dceSJinyang He                                        SMLoc IDLoc, MCStreamer &Out,
891b3ef8dceSJinyang He                                        bool RelaxHint) {
892a7ec7f6dSwanglei   MCContext &Ctx = getContext();
893a7ec7f6dSwanglei   for (LoongArchAsmParser::Inst &Inst : Insts) {
894a7ec7f6dSwanglei     unsigned Opc = Inst.Opc;
895a7ec7f6dSwanglei     LoongArchMCExpr::VariantKind VK = Inst.VK;
896b3ef8dceSJinyang He     const LoongArchMCExpr *LE =
897b3ef8dceSJinyang He         LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
898a7ec7f6dSwanglei     switch (Opc) {
899a7ec7f6dSwanglei     default:
900a7ec7f6dSwanglei       llvm_unreachable("unexpected opcode");
901a7ec7f6dSwanglei     case LoongArch::PCALAU12I:
902a7ec7f6dSwanglei     case LoongArch::LU12I_W:
903a7ec7f6dSwanglei       Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
904a7ec7f6dSwanglei                           getSTI());
905a7ec7f6dSwanglei       break;
906a7ec7f6dSwanglei     case LoongArch::ORI:
907a7ec7f6dSwanglei     case LoongArch::ADDI_W:
908a7ec7f6dSwanglei     case LoongArch::LD_W:
909a7ec7f6dSwanglei     case LoongArch::LD_D: {
910a7ec7f6dSwanglei       if (VK == LoongArchMCExpr::VK_LoongArch_None) {
911a7ec7f6dSwanglei         Out.emitInstruction(
912a7ec7f6dSwanglei             MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
913a7ec7f6dSwanglei             getSTI());
914a7ec7f6dSwanglei         continue;
9154a84d8e4Swanglei       } else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) {
9164a84d8e4Swanglei         Out.emitInstruction(MCInstBuilder(Opc)
9174a84d8e4Swanglei                                 .addReg(LoongArch::R1)
9184a84d8e4Swanglei                                 .addReg(DestReg)
9194a84d8e4Swanglei                                 .addExpr(LE),
9204a84d8e4Swanglei                             getSTI());
9214a84d8e4Swanglei         continue;
922a7ec7f6dSwanglei       }
923a7ec7f6dSwanglei       Out.emitInstruction(
924a7ec7f6dSwanglei           MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
925a7ec7f6dSwanglei           getSTI());
926a7ec7f6dSwanglei       break;
927a7ec7f6dSwanglei     }
928a7ec7f6dSwanglei     case LoongArch::LU32I_D:
929a7ec7f6dSwanglei       Out.emitInstruction(MCInstBuilder(Opc)
930a7ec7f6dSwanglei                               .addReg(DestReg == TmpReg ? DestReg : TmpReg)
931a7ec7f6dSwanglei                               .addReg(DestReg == TmpReg ? DestReg : TmpReg)
932a7ec7f6dSwanglei                               .addExpr(LE),
933a7ec7f6dSwanglei                           getSTI());
934a7ec7f6dSwanglei       break;
935a7ec7f6dSwanglei     case LoongArch::LU52I_D:
936a7ec7f6dSwanglei       Out.emitInstruction(
937a7ec7f6dSwanglei           MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
938a7ec7f6dSwanglei           getSTI());
939a7ec7f6dSwanglei       break;
940a7ec7f6dSwanglei     case LoongArch::ADDI_D:
941a7ec7f6dSwanglei       Out.emitInstruction(
942a7ec7f6dSwanglei           MCInstBuilder(Opc)
943a7ec7f6dSwanglei               .addReg(TmpReg)
944a7ec7f6dSwanglei               .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
945a7ec7f6dSwanglei               .addExpr(LE),
946a7ec7f6dSwanglei           getSTI());
947a7ec7f6dSwanglei       break;
948a7ec7f6dSwanglei     case LoongArch::ADD_D:
949a7ec7f6dSwanglei     case LoongArch::LDX_D:
950a7ec7f6dSwanglei       Out.emitInstruction(
951a7ec7f6dSwanglei           MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
952a7ec7f6dSwanglei           getSTI());
953a7ec7f6dSwanglei       break;
9544a84d8e4Swanglei     case LoongArch::JIRL:
9554a84d8e4Swanglei       Out.emitInstruction(MCInstBuilder(Opc)
9564a84d8e4Swanglei                               .addReg(LoongArch::R1)
9574a84d8e4Swanglei                               .addReg(LoongArch::R1)
9584a84d8e4Swanglei                               .addExpr(LE),
9594a84d8e4Swanglei                           getSTI());
9604a84d8e4Swanglei       break;
961a7ec7f6dSwanglei     }
962a7ec7f6dSwanglei   }
963a7ec7f6dSwanglei }
964a7ec7f6dSwanglei 
965a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
966a7ec7f6dSwanglei                                             MCStreamer &Out) {
967a7ec7f6dSwanglei   // la.abs $rd, sym
968a7ec7f6dSwanglei   // expands to:
969a7ec7f6dSwanglei   //   lu12i.w $rd, %abs_hi20(sym)
970a7ec7f6dSwanglei   //   ori     $rd, $rd, %abs_lo12(sym)
971a7ec7f6dSwanglei   //
972a7ec7f6dSwanglei   // for 64bit appends:
973a7ec7f6dSwanglei   //   lu32i.d $rd, %abs64_lo20(sym)
974a7ec7f6dSwanglei   //   lu52i.d $rd, $rd, %abs64_hi12(sym)
975a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
976a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
977a7ec7f6dSwanglei                              ? Inst.getOperand(1).getExpr()
978a7ec7f6dSwanglei                              : Inst.getOperand(2).getExpr();
979a7ec7f6dSwanglei   InstSeq Insts;
980a7ec7f6dSwanglei 
981a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
982a7ec7f6dSwanglei       LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
983a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
984a7ec7f6dSwanglei       LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12));
985a7ec7f6dSwanglei 
986a7ec7f6dSwanglei   if (is64Bit()) {
987a7ec7f6dSwanglei     Insts.push_back(LoongArchAsmParser::Inst(
988a7ec7f6dSwanglei         LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
989a7ec7f6dSwanglei     Insts.push_back(LoongArchAsmParser::Inst(
990a7ec7f6dSwanglei         LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
991a7ec7f6dSwanglei   }
992a7ec7f6dSwanglei 
993a7ec7f6dSwanglei   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
994a7ec7f6dSwanglei }
995a7ec7f6dSwanglei 
996a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
997a7ec7f6dSwanglei                                               MCStreamer &Out) {
998a7ec7f6dSwanglei   // la.pcrel $rd, sym
999a7ec7f6dSwanglei   // expands to:
1000a7ec7f6dSwanglei   //   pcalau12i $rd, %pc_hi20(sym)
1001a7ec7f6dSwanglei   //   addi.w/d  $rd, rd, %pc_lo12(sym)
1002a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1003a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1004a7ec7f6dSwanglei   InstSeq Insts;
1005a7ec7f6dSwanglei   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1006a7ec7f6dSwanglei 
1007a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1008a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
1009a7ec7f6dSwanglei   Insts.push_back(
1010a7ec7f6dSwanglei       LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
1011a7ec7f6dSwanglei 
1012*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1013*89e3a649SZhaoQi                 /*RelaxHint=*/true);
1014a7ec7f6dSwanglei }
1015a7ec7f6dSwanglei 
1016a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
1017a7ec7f6dSwanglei                                                    MCStreamer &Out) {
1018a7ec7f6dSwanglei   // la.pcrel $rd, $rj, sym
1019a7ec7f6dSwanglei   // expands to:
1020a7ec7f6dSwanglei   //   pcalau12i $rd, %pc_hi20(sym)
1021a7ec7f6dSwanglei   //   addi.d    $rj, $r0, %pc_lo12(sym)
1022a7ec7f6dSwanglei   //   lu32i.d   $rj, %pc64_lo20(sym)
1023a7ec7f6dSwanglei   //   lu52i.d   $rj, $rj, %pc64_hi12(sym)
1024a7ec7f6dSwanglei   //   add.d     $rd, $rd, $rj
1025a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1026a7ec7f6dSwanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
1027a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1028a7ec7f6dSwanglei   InstSeq Insts;
1029a7ec7f6dSwanglei 
1030a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1031a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
1032a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1033a7ec7f6dSwanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
1034a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1035a7ec7f6dSwanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
1036a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1037a7ec7f6dSwanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
1038a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1039a7ec7f6dSwanglei 
1040a7ec7f6dSwanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1041a7ec7f6dSwanglei }
1042a7ec7f6dSwanglei 
1043a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
1044a7ec7f6dSwanglei                                             MCStreamer &Out) {
1045a7ec7f6dSwanglei   // la.got $rd, sym
1046a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1047a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1048a7ec7f6dSwanglei   InstSeq Insts;
1049a7ec7f6dSwanglei   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1050a7ec7f6dSwanglei 
1051affb2b73Swanglei   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1052affb2b73Swanglei     // with feature: +la-glabal-with-abs
1053affb2b73Swanglei     // for 32bit:
1054affb2b73Swanglei     //   lu12i.w $rd, %got_hi20(sym)
1055affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1056affb2b73Swanglei     //   ld.w    $rd, $rd, 0
1057affb2b73Swanglei     //
1058affb2b73Swanglei     // for 64bit:
1059affb2b73Swanglei     //   lu12i.w $rd, %got_hi20(sym)
1060affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1061affb2b73Swanglei     //   lu32i.d $rd, %got64_lo20(sym)
1062affb2b73Swanglei     //   lu52i.d $rd, $rd, %got64_hi12(sym)
1063affb2b73Swanglei     //   ld.d    $rd, $rd, 0
1064affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1065affb2b73Swanglei         LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_GOT_HI20));
1066affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1067affb2b73Swanglei         LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));
1068affb2b73Swanglei 
1069affb2b73Swanglei     if (is64Bit()) {
1070affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1071affb2b73Swanglei           LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1072affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1073affb2b73Swanglei           LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1074affb2b73Swanglei     }
1075affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(LD));
1076affb2b73Swanglei     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1077affb2b73Swanglei     return;
1078affb2b73Swanglei   }
1079affb2b73Swanglei   // expands to:
1080affb2b73Swanglei   //   pcalau12i $rd, %got_pc_hi20(sym)
1081affb2b73Swanglei   //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)
1082a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1083a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
1084a7ec7f6dSwanglei   Insts.push_back(
1085a7ec7f6dSwanglei       LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1086a7ec7f6dSwanglei 
1087*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1088*89e3a649SZhaoQi                 /*RelaxHint=*/true);
1089a7ec7f6dSwanglei }
1090a7ec7f6dSwanglei 
1091a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
1092a7ec7f6dSwanglei                                                  MCStreamer &Out) {
1093a7ec7f6dSwanglei   // la.got $rd, $rj, sym
1094a7ec7f6dSwanglei   // expands to:
1095a7ec7f6dSwanglei   //   pcalau12i $rd, %got_pc_hi20(sym)
1096a7ec7f6dSwanglei   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
1097a7ec7f6dSwanglei   //   lu32i.d   $rj, %got64_pc_lo20(sym)
1098a7ec7f6dSwanglei   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
1099a7ec7f6dSwanglei   //   ldx.d     $rd, $rd, $rj
1100a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1101a7ec7f6dSwanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
1102a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1103a7ec7f6dSwanglei   InstSeq Insts;
1104a7ec7f6dSwanglei 
1105a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1106a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
1107a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1108a7ec7f6dSwanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1109a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1110a7ec7f6dSwanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1111a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1112a7ec7f6dSwanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1113a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1114a7ec7f6dSwanglei 
1115a7ec7f6dSwanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1116a7ec7f6dSwanglei }
1117a7ec7f6dSwanglei 
1118a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1119a7ec7f6dSwanglei                                               MCStreamer &Out) {
1120a7ec7f6dSwanglei   // la.tls.le $rd, sym
1121a7ec7f6dSwanglei   // expands to:
1122a7ec7f6dSwanglei   //   lu12i.w $rd, %le_hi20(sym)
1123a7ec7f6dSwanglei   //   ori     $rd, $rd, %le_lo12(sym)
1124a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1125a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1126a7ec7f6dSwanglei   InstSeq Insts;
1127a7ec7f6dSwanglei 
1128a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1129a7ec7f6dSwanglei       LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
1130a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1131a7ec7f6dSwanglei       LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12));
1132a7ec7f6dSwanglei 
1133a7ec7f6dSwanglei   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1134a7ec7f6dSwanglei }
1135a7ec7f6dSwanglei 
1136a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1137a7ec7f6dSwanglei                                               MCStreamer &Out) {
1138a7ec7f6dSwanglei   // la.tls.ie $rd, sym
1139a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1140a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1141a7ec7f6dSwanglei   InstSeq Insts;
1142a7ec7f6dSwanglei   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1143a7ec7f6dSwanglei 
1144affb2b73Swanglei   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1145affb2b73Swanglei     // with feature: +la-glabal-with-abs
1146affb2b73Swanglei     // for 32bit:
1147affb2b73Swanglei     //   lu12i.w $rd, %ie_hi20(sym)
1148affb2b73Swanglei     //   ori     $rd, $rd, %ie_lo12(sym)
1149affb2b73Swanglei     //   ld.w    $rd, $rd, 0
1150affb2b73Swanglei     //
1151affb2b73Swanglei     // for 64bit:
1152affb2b73Swanglei     //   lu12i.w $rd, %ie_hi20(sym)
1153affb2b73Swanglei     //   ori     $rd, $rd, %ie_lo12(sym)
1154affb2b73Swanglei     //   lu32i.d $rd, %ie64_lo20(sym)
1155affb2b73Swanglei     //   lu52i.d $rd, $rd, %ie64_hi12(sym)
1156affb2b73Swanglei     //   ld.d    $rd, $rd, 0
1157affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1158affb2b73Swanglei         LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20));
1159affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1160affb2b73Swanglei         LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12));
1161affb2b73Swanglei 
1162affb2b73Swanglei     if (is64Bit()) {
1163affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1164affb2b73Swanglei           LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20));
1165affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1166affb2b73Swanglei           LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12));
1167affb2b73Swanglei     }
1168affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(LD));
1169affb2b73Swanglei     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1170affb2b73Swanglei     return;
1171affb2b73Swanglei   }
1172affb2b73Swanglei 
1173affb2b73Swanglei   // expands to:
1174affb2b73Swanglei   //   pcalau12i $rd, %ie_pc_hi20(sym)
1175affb2b73Swanglei   //   ld.w/d    $rd, $rd, %ie_pc_lo12(sym)
1176a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1177a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1178a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1179a7ec7f6dSwanglei       LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
1180a7ec7f6dSwanglei 
1181*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1182*89e3a649SZhaoQi                 /*RelaxHint=*/true);
1183a7ec7f6dSwanglei }
1184a7ec7f6dSwanglei 
1185a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1186a7ec7f6dSwanglei                                                    MCStreamer &Out) {
1187a7ec7f6dSwanglei   // la.tls.ie $rd, $rj, sym
1188a7ec7f6dSwanglei   // expands to:
1189a7ec7f6dSwanglei   //   pcalau12i $rd, %ie_pc_hi20(sym)
1190a7ec7f6dSwanglei   //   addi.d    $rj, $r0, %ie_pc_lo12(sym)
1191a7ec7f6dSwanglei   //   lu32i.d   $rj, %ie64_pc_lo20(sym)
1192a7ec7f6dSwanglei   //   lu52i.d   $rj, $rj, %ie64_pc_hi12(sym)
1193a7ec7f6dSwanglei   //   ldx.d     $rd, $rd, $rj
1194a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1195a7ec7f6dSwanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
1196a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1197a7ec7f6dSwanglei   InstSeq Insts;
1198a7ec7f6dSwanglei 
1199a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1200a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1201a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1202a7ec7f6dSwanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
1203a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1204a7ec7f6dSwanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20));
1205a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1206a7ec7f6dSwanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12));
1207a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1208a7ec7f6dSwanglei 
1209a7ec7f6dSwanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1210a7ec7f6dSwanglei }
1211a7ec7f6dSwanglei 
1212a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1213a7ec7f6dSwanglei                                               MCStreamer &Out) {
1214a7ec7f6dSwanglei   // la.tls.ld $rd, sym
1215a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1216a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1217a7ec7f6dSwanglei   InstSeq Insts;
1218a7ec7f6dSwanglei   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1219a7ec7f6dSwanglei 
1220affb2b73Swanglei   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1221affb2b73Swanglei     // with feature: +la-glabal-with-abs
1222affb2b73Swanglei     // for 32bit:
1223affb2b73Swanglei     //   lu12i.w $rd, %ld_hi20(sym)
1224affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1225affb2b73Swanglei     //
1226affb2b73Swanglei     // for 64bit:
1227affb2b73Swanglei     //   lu12i.w $rd, %ld_hi20(sym)
1228affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1229affb2b73Swanglei     //   lu32i.d $rd, %got64_lo20(sym)
1230affb2b73Swanglei     //   lu52i.d $rd, $rd, %got64_hi12(sym)
1231affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1232affb2b73Swanglei         LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20));
1233affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1234affb2b73Swanglei         LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));
1235affb2b73Swanglei 
1236affb2b73Swanglei     if (is64Bit()) {
1237affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1238affb2b73Swanglei           LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1239affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1240affb2b73Swanglei           LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1241affb2b73Swanglei     }
1242affb2b73Swanglei     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1243affb2b73Swanglei     return;
1244affb2b73Swanglei   }
1245affb2b73Swanglei 
1246affb2b73Swanglei   // expands to:
1247affb2b73Swanglei   //   pcalau12i $rd, %ld_pc_hi20(sym)
1248affb2b73Swanglei   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
1249a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1250a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1251a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1252a7ec7f6dSwanglei       ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1253a7ec7f6dSwanglei 
1254*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1255*89e3a649SZhaoQi                 /*RelaxHint=*/true);
1256a7ec7f6dSwanglei }
1257a7ec7f6dSwanglei 
1258a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1259a7ec7f6dSwanglei                                                    MCStreamer &Out) {
1260a7ec7f6dSwanglei   // la.tls.ld $rd, $rj, sym
1261a7ec7f6dSwanglei   // expands to:
1262a7ec7f6dSwanglei   //   pcalau12i $rd, %ld_pc_hi20(sym)
1263a7ec7f6dSwanglei   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
1264a7ec7f6dSwanglei   //   lu32i.d   $rj, %got64_pc_lo20(sym)
1265a7ec7f6dSwanglei   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
1266a7ec7f6dSwanglei   //   add.d     $rd, $rd, $rj
1267a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1268a7ec7f6dSwanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
1269a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1270a7ec7f6dSwanglei   InstSeq Insts;
1271a7ec7f6dSwanglei 
1272a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1273a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1274a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1275a7ec7f6dSwanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1276a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1277a7ec7f6dSwanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1278a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1279a7ec7f6dSwanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1280a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1281a7ec7f6dSwanglei 
1282a7ec7f6dSwanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1283a7ec7f6dSwanglei }
1284a7ec7f6dSwanglei 
1285a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1286a7ec7f6dSwanglei                                               MCStreamer &Out) {
1287a7ec7f6dSwanglei   // la.tls.gd $rd, sym
1288a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1289a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1290a7ec7f6dSwanglei   InstSeq Insts;
1291a7ec7f6dSwanglei   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1292a7ec7f6dSwanglei 
1293affb2b73Swanglei   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1294affb2b73Swanglei     // with feature: +la-glabal-with-abs
1295affb2b73Swanglei     // for 32bit:
1296affb2b73Swanglei     //   lu12i.w $rd, %gd_hi20(sym)
1297affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1298affb2b73Swanglei     //
1299affb2b73Swanglei     // for 64bit:
1300affb2b73Swanglei     //   lu12i.w $rd, %gd_hi20(sym)
1301affb2b73Swanglei     //   ori     $rd, $rd, %got_lo12(sym)
1302affb2b73Swanglei     //   lu32i.d $rd, %got64_lo20(sym)
1303affb2b73Swanglei     //   lu52i.d $rd, $rd, %got64_hi12(sym)
1304affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1305affb2b73Swanglei         LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20));
1306affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1307affb2b73Swanglei         LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_GOT_LO12));
1308affb2b73Swanglei 
1309affb2b73Swanglei     if (is64Bit()) {
1310affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1311affb2b73Swanglei           LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1312affb2b73Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
1313affb2b73Swanglei           LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1314affb2b73Swanglei     }
1315affb2b73Swanglei     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1316affb2b73Swanglei     return;
1317affb2b73Swanglei   }
1318affb2b73Swanglei 
1319affb2b73Swanglei   // expands to:
1320affb2b73Swanglei   //   pcalau12i $rd, %gd_pc_hi20(sym)
1321affb2b73Swanglei   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
1322a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1323a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1324a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1325a7ec7f6dSwanglei       ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1326a7ec7f6dSwanglei 
1327*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1328*89e3a649SZhaoQi                 /*RelaxHint=*/true);
1329a7ec7f6dSwanglei }
1330a7ec7f6dSwanglei 
1331a7ec7f6dSwanglei void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1332a7ec7f6dSwanglei                                                    MCStreamer &Out) {
1333a7ec7f6dSwanglei   // la.tls.gd $rd, $rj, sym
1334a7ec7f6dSwanglei   // expands to:
1335a7ec7f6dSwanglei   //   pcalau12i $rd, %gd_pc_hi20(sym)
1336a7ec7f6dSwanglei   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
1337a7ec7f6dSwanglei   //   lu32i.d   $rj, %got64_pc_lo20(sym)
1338a7ec7f6dSwanglei   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
1339a7ec7f6dSwanglei   //   add.d     $rd, $rd, $rj
1340a7ec7f6dSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1341a7ec7f6dSwanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
1342a7ec7f6dSwanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1343a7ec7f6dSwanglei   InstSeq Insts;
1344a7ec7f6dSwanglei 
1345a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1346a7ec7f6dSwanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1347a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1348a7ec7f6dSwanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1349a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1350a7ec7f6dSwanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1351a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(
1352a7ec7f6dSwanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1353a7ec7f6dSwanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1354a7ec7f6dSwanglei 
1355a7ec7f6dSwanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1356a7ec7f6dSwanglei }
1357a7ec7f6dSwanglei 
1358affb2b73Swanglei void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
13594a84d8e4Swanglei                                                 MCStreamer &Out) {
1360affb2b73Swanglei   // la.tls.desc $rd, sym
1361affb2b73Swanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1362affb2b73Swanglei   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1363affb2b73Swanglei   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1364affb2b73Swanglei   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1365affb2b73Swanglei   InstSeq Insts;
1366affb2b73Swanglei 
1367affb2b73Swanglei   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1368affb2b73Swanglei     // with feature: +la-glabal-with-abs
13694a84d8e4Swanglei     // for la32 expands to:
13704a84d8e4Swanglei     //   lu12i.w $rd, %desc_hi20(sym)
13714a84d8e4Swanglei     //   ori     $rd, $rd, %desc_lo12(sym)
13724a84d8e4Swanglei     //   ld.w    $ra, $rd, %desc_ld(sym)
13734a84d8e4Swanglei     //   jirl    $ra, $ra, %desc_call(sym)
13744a84d8e4Swanglei     //
13754a84d8e4Swanglei     // for la64 expands to:
13764a84d8e4Swanglei     //   lu12i.w $rd, %desc_hi20(sym)
13774a84d8e4Swanglei     //   ori     $rd, $rd, %desc_lo12(sym)
13784a84d8e4Swanglei     //   lu32i.d $rd, %desc64_lo20(sym)
13794a84d8e4Swanglei     //   lu52i.d $rd, $rd, %desc64_hi12(sym)
13804a84d8e4Swanglei     //   ld.d    $ra, $rd, %desc_ld(sym)
13814a84d8e4Swanglei     //   jirl    $ra, $ra, %desc_call(sym)
13824a84d8e4Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
13834a84d8e4Swanglei         LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
13844a84d8e4Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
13854a84d8e4Swanglei         LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));
13864a84d8e4Swanglei 
13874a84d8e4Swanglei     if (is64Bit()) {
13884a84d8e4Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
13894a84d8e4Swanglei           LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
13904a84d8e4Swanglei       Insts.push_back(LoongArchAsmParser::Inst(
13914a84d8e4Swanglei           LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
13924a84d8e4Swanglei     }
13934a84d8e4Swanglei 
1394affb2b73Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
1395affb2b73Swanglei         LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
13964a84d8e4Swanglei     Insts.push_back(LoongArchAsmParser::Inst(
13974a84d8e4Swanglei         LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
13984a84d8e4Swanglei 
13994a84d8e4Swanglei     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1400affb2b73Swanglei     return;
14014a84d8e4Swanglei   }
14024a84d8e4Swanglei 
14034a84d8e4Swanglei   // expands to:
14044a84d8e4Swanglei   //   pcalau12i $rd, %desc_pc_hi20(sym)
14054a84d8e4Swanglei   //   addi.w/d  $rd, $rd, %desc_pc_lo12(sym)
14064a84d8e4Swanglei   //   ld.w/d    $ra, $rd, %desc_ld(sym)
14074a84d8e4Swanglei   //   jirl      $ra, $ra, %desc_call(sym)
14084a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14094a84d8e4Swanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
14104a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14114a84d8e4Swanglei       ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
14124a84d8e4Swanglei   Insts.push_back(
14134a84d8e4Swanglei       LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
14144a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14154a84d8e4Swanglei       LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
14164a84d8e4Swanglei 
1417*89e3a649SZhaoQi   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1418*89e3a649SZhaoQi                 /*RelaxHint=*/true);
14194a84d8e4Swanglei }
14204a84d8e4Swanglei 
1421affb2b73Swanglei void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
14224a84d8e4Swanglei                                                      MCStreamer &Out) {
14234a84d8e4Swanglei   // la.tls.desc $rd, $rj, sym
14244a84d8e4Swanglei   // expands to:
14254a84d8e4Swanglei   //   pcalau12i $rd, %desc_pc_hi20(sym)
14264a84d8e4Swanglei   //   addi.d    $rj, $r0, %desc_pc_lo12(sym)
14274a84d8e4Swanglei   //   lu32i.d   $rj, %desc64_pc_lo20(sym)
14284a84d8e4Swanglei   //   lu52i.d   $rj, $rj, %desc64_pc_hi12(sym)
14294a84d8e4Swanglei   //   add.d     $rd, $rd, $rj
14304a84d8e4Swanglei   //   ld.w/d    $ra, $rd, %desc_ld(sym)
14314a84d8e4Swanglei   //   jirl      $ra, $ra, %desc_call(sym)
14324a84d8e4Swanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
14334a84d8e4Swanglei   MCRegister TmpReg = Inst.getOperand(1).getReg();
14344a84d8e4Swanglei   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
14354a84d8e4Swanglei   InstSeq Insts;
14364a84d8e4Swanglei 
14374a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14384a84d8e4Swanglei       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
14394a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14404a84d8e4Swanglei       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
14414a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14424a84d8e4Swanglei       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20));
14434a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14444a84d8e4Swanglei       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12));
14454a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
14464a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14474a84d8e4Swanglei       LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
14484a84d8e4Swanglei   Insts.push_back(LoongArchAsmParser::Inst(
14494a84d8e4Swanglei       LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
14504a84d8e4Swanglei 
14514a84d8e4Swanglei   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
14524a84d8e4Swanglei }
14534a84d8e4Swanglei 
1454f873c50cSwanglei void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1455f873c50cSwanglei                                      MCStreamer &Out) {
1456f873c50cSwanglei   MCRegister DestReg = Inst.getOperand(0).getReg();
1457f873c50cSwanglei   int64_t Imm = Inst.getOperand(1).getImm();
1458f873c50cSwanglei   MCRegister SrcReg = LoongArch::R0;
1459f873c50cSwanglei 
1460f873c50cSwanglei   if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1461f873c50cSwanglei     Imm = SignExtend64<32>(Imm);
1462f873c50cSwanglei 
1463f873c50cSwanglei   for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
1464eaf87d32Swanglei     switch (Inst.Opc) {
1465eaf87d32Swanglei     case LoongArch::LU12I_W:
1466f873c50cSwanglei       Out.emitInstruction(
1467eaf87d32Swanglei           MCInstBuilder(Inst.Opc).addReg(DestReg).addImm(Inst.Imm), getSTI());
1468eaf87d32Swanglei       break;
1469eaf87d32Swanglei     case LoongArch::ADDI_W:
1470eaf87d32Swanglei     case LoongArch::ORI:
1471eaf87d32Swanglei     case LoongArch::LU32I_D:
1472eaf87d32Swanglei     case LoongArch::LU52I_D:
1473eaf87d32Swanglei       Out.emitInstruction(
1474eaf87d32Swanglei           MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1475eaf87d32Swanglei               Inst.Imm),
1476f873c50cSwanglei           getSTI());
1477eaf87d32Swanglei       break;
1478eaf87d32Swanglei     case LoongArch::BSTRINS_D:
1479eaf87d32Swanglei       Out.emitInstruction(MCInstBuilder(Inst.Opc)
1480eaf87d32Swanglei                               .addReg(DestReg)
1481eaf87d32Swanglei                               .addReg(SrcReg)
1482eaf87d32Swanglei                               .addReg(SrcReg)
1483eaf87d32Swanglei                               .addImm(Inst.Imm >> 32)
1484eaf87d32Swanglei                               .addImm(Inst.Imm & 0xFF),
1485eaf87d32Swanglei                           getSTI());
1486eaf87d32Swanglei       break;
1487eaf87d32Swanglei     default:
1488eaf87d32Swanglei       llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
1489eaf87d32Swanglei     }
1490f873c50cSwanglei     SrcReg = DestReg;
1491f873c50cSwanglei   }
1492f873c50cSwanglei }
1493f873c50cSwanglei 
14942cf420d5Swanglei void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
14952cf420d5Swanglei                                         MCStreamer &Out, bool IsTailCall) {
14962cf420d5Swanglei   // call36 sym
14972cf420d5Swanglei   // expands to:
14982cf420d5Swanglei   //   pcaddu18i $ra, %call36(sym)
14992cf420d5Swanglei   //   jirl      $ra, $ra, 0
15002cf420d5Swanglei   //
15012cf420d5Swanglei   // tail36 $rj, sym
15022cf420d5Swanglei   // expands to:
15032cf420d5Swanglei   //   pcaddu18i $rj, %call36(sym)
15042cf420d5Swanglei   //   jirl      $r0, $rj, 0
1505c1b3ebbaSCraig Topper   MCRegister ScratchReg =
1506c1b3ebbaSCraig Topper       IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
15072cf420d5Swanglei   const MCExpr *Sym =
15082cf420d5Swanglei       IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1509*89e3a649SZhaoQi   const LoongArchMCExpr *LE =
1510*89e3a649SZhaoQi       LoongArchMCExpr::create(Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36,
1511*89e3a649SZhaoQi                               getContext(), /*RelaxHint=*/true);
15122cf420d5Swanglei 
15132cf420d5Swanglei   Out.emitInstruction(
15142cf420d5Swanglei       MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
15152cf420d5Swanglei       getSTI());
15162cf420d5Swanglei   Out.emitInstruction(
15172cf420d5Swanglei       MCInstBuilder(LoongArch::JIRL)
1518c1b3ebbaSCraig Topper           .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
15192cf420d5Swanglei           .addReg(ScratchReg)
15202cf420d5Swanglei           .addImm(0),
15212cf420d5Swanglei       getSTI());
15222cf420d5Swanglei }
15232cf420d5Swanglei 
15243347f77bSWeining Lu bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
15253347f77bSWeining Lu                                             OperandVector &Operands,
15263347f77bSWeining Lu                                             MCStreamer &Out) {
15273347f77bSWeining Lu   Inst.setLoc(IDLoc);
1528a7ec7f6dSwanglei   switch (Inst.getOpcode()) {
1529a7ec7f6dSwanglei   default:
1530a7ec7f6dSwanglei     break;
1531a7ec7f6dSwanglei   case LoongArch::PseudoLA_ABS:
1532a7ec7f6dSwanglei   case LoongArch::PseudoLA_ABS_LARGE:
1533a7ec7f6dSwanglei     emitLoadAddressAbs(Inst, IDLoc, Out);
1534a7ec7f6dSwanglei     return false;
1535a7ec7f6dSwanglei   case LoongArch::PseudoLA_PCREL:
1536a7ec7f6dSwanglei     emitLoadAddressPcrel(Inst, IDLoc, Out);
1537a7ec7f6dSwanglei     return false;
1538a7ec7f6dSwanglei   case LoongArch::PseudoLA_PCREL_LARGE:
1539a7ec7f6dSwanglei     emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1540a7ec7f6dSwanglei     return false;
1541a7ec7f6dSwanglei   case LoongArch::PseudoLA_GOT:
1542a7ec7f6dSwanglei     emitLoadAddressGot(Inst, IDLoc, Out);
1543a7ec7f6dSwanglei     return false;
1544a7ec7f6dSwanglei   case LoongArch::PseudoLA_GOT_LARGE:
1545a7ec7f6dSwanglei     emitLoadAddressGotLarge(Inst, IDLoc, Out);
1546a7ec7f6dSwanglei     return false;
1547a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_LE:
1548a7ec7f6dSwanglei     emitLoadAddressTLSLE(Inst, IDLoc, Out);
1549a7ec7f6dSwanglei     return false;
1550a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_IE:
1551a7ec7f6dSwanglei     emitLoadAddressTLSIE(Inst, IDLoc, Out);
1552a7ec7f6dSwanglei     return false;
1553a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_IE_LARGE:
1554a7ec7f6dSwanglei     emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1555a7ec7f6dSwanglei     return false;
1556a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_LD:
1557a7ec7f6dSwanglei     emitLoadAddressTLSLD(Inst, IDLoc, Out);
1558a7ec7f6dSwanglei     return false;
1559a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_LD_LARGE:
1560a7ec7f6dSwanglei     emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1561a7ec7f6dSwanglei     return false;
1562a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_GD:
1563a7ec7f6dSwanglei     emitLoadAddressTLSGD(Inst, IDLoc, Out);
1564a7ec7f6dSwanglei     return false;
1565a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_GD_LARGE:
1566a7ec7f6dSwanglei     emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1567a7ec7f6dSwanglei     return false;
1568affb2b73Swanglei   case LoongArch::PseudoLA_TLS_DESC:
1569affb2b73Swanglei     emitLoadAddressTLSDesc(Inst, IDLoc, Out);
15704a84d8e4Swanglei     return false;
1571affb2b73Swanglei   case LoongArch::PseudoLA_TLS_DESC_LARGE:
1572affb2b73Swanglei     emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
15734a84d8e4Swanglei     return false;
1574f873c50cSwanglei   case LoongArch::PseudoLI_W:
1575f873c50cSwanglei   case LoongArch::PseudoLI_D:
1576f873c50cSwanglei     emitLoadImm(Inst, IDLoc, Out);
1577f873c50cSwanglei     return false;
15782cf420d5Swanglei   case LoongArch::PseudoCALL36:
15792cf420d5Swanglei     emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
15802cf420d5Swanglei     return false;
15812cf420d5Swanglei   case LoongArch::PseudoTAIL36:
15822cf420d5Swanglei     emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
15832cf420d5Swanglei     return false;
1584a7ec7f6dSwanglei   }
15853347f77bSWeining Lu   Out.emitInstruction(Inst, getSTI());
15863347f77bSWeining Lu   return false;
15873347f77bSWeining Lu }
15883347f77bSWeining Lu 
158924532d05SWeining Lu unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1590c98add7aSWeining Lu   unsigned Opc = Inst.getOpcode();
15918234c612SWÁNG Xuěruì   const MCInstrDesc &MCID = MII.get(Opc);
1592c98add7aSWeining Lu   switch (Opc) {
159324532d05SWeining Lu   default:
15948234c612SWÁNG Xuěruì     if (LoongArchII::isSubjectToAMORdConstraint(MCID.TSFlags)) {
15958234c612SWÁNG Xuěruì       const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);
159675a04c65SWÁNG Xuěruì       MCRegister Rd = Inst.getOperand(0).getReg();
15978234c612SWÁNG Xuěruì       MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();
15988234c612SWÁNG Xuěruì       MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();
159943cf2f81SWeining Lu       if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
160043cf2f81SWeining Lu         return Match_RequiresAMORdDifferRkRj;
1601c98add7aSWeining Lu     }
160224532d05SWeining Lu     break;
1603affb2b73Swanglei   case LoongArch::PseudoLA_TLS_DESC:
1604affb2b73Swanglei   case LoongArch::PseudoLA_TLS_DESC_LARGE: {
1605c38b5c81SCraig Topper     MCRegister Rd = Inst.getOperand(0).getReg();
16064a84d8e4Swanglei     if (Rd != LoongArch::R4)
16074a84d8e4Swanglei       return Match_RequiresLAORdR4;
16084a84d8e4Swanglei     break;
16094a84d8e4Swanglei   }
1610a7ec7f6dSwanglei   case LoongArch::PseudoLA_PCREL_LARGE:
1611a7ec7f6dSwanglei   case LoongArch::PseudoLA_GOT_LARGE:
1612a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_IE_LARGE:
1613a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_LD_LARGE:
1614a7ec7f6dSwanglei   case LoongArch::PseudoLA_TLS_GD_LARGE: {
1615c38b5c81SCraig Topper     MCRegister Rd = Inst.getOperand(0).getReg();
1616c38b5c81SCraig Topper     MCRegister Rj = Inst.getOperand(1).getReg();
1617a7ec7f6dSwanglei     if (Rd == Rj)
1618a7ec7f6dSwanglei       return Match_RequiresLAORdDifferRj;
1619a7ec7f6dSwanglei     break;
1620a7ec7f6dSwanglei   }
1621d6675b6aSwanglei   case LoongArch::CSRXCHG:
1622d6675b6aSwanglei   case LoongArch::GCSRXCHG: {
1623c38b5c81SCraig Topper     MCRegister Rj = Inst.getOperand(2).getReg();
162411ec7307SWeining Lu     if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
162511ec7307SWeining Lu       return Match_RequiresOpnd2NotR0R1;
162611ec7307SWeining Lu     return Match_Success;
162711ec7307SWeining Lu   }
162824532d05SWeining Lu   case LoongArch::BSTRINS_W:
162924532d05SWeining Lu   case LoongArch::BSTRINS_D:
163024532d05SWeining Lu   case LoongArch::BSTRPICK_W:
163124532d05SWeining Lu   case LoongArch::BSTRPICK_D: {
163224532d05SWeining Lu     unsigned Opc = Inst.getOpcode();
163324532d05SWeining Lu     const signed Msb =
163424532d05SWeining Lu         (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
163524532d05SWeining Lu             ? Inst.getOperand(3).getImm()
163624532d05SWeining Lu             : Inst.getOperand(2).getImm();
163724532d05SWeining Lu     const signed Lsb =
163824532d05SWeining Lu         (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
163924532d05SWeining Lu             ? Inst.getOperand(4).getImm()
164024532d05SWeining Lu             : Inst.getOperand(3).getImm();
164124532d05SWeining Lu     if (Msb < Lsb)
164224532d05SWeining Lu       return Match_RequiresMsbNotLessThanLsb;
164324532d05SWeining Lu     return Match_Success;
164424532d05SWeining Lu   }
164524532d05SWeining Lu   }
164624532d05SWeining Lu 
164724532d05SWeining Lu   return Match_Success;
164824532d05SWeining Lu }
164924532d05SWeining Lu 
16503a49ad71SWeining Lu unsigned
16513a49ad71SWeining Lu LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
16523a49ad71SWeining Lu                                                unsigned Kind) {
16533a49ad71SWeining Lu   LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
16543a49ad71SWeining Lu   if (!Op.isReg())
16553a49ad71SWeining Lu     return Match_InvalidOperand;
16563a49ad71SWeining Lu 
16573a49ad71SWeining Lu   MCRegister Reg = Op.getReg();
16583a49ad71SWeining Lu   // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
16593a49ad71SWeining Lu   // register from FPR32 to FPR64 if necessary.
16603a49ad71SWeining Lu   if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
16613a49ad71SWeining Lu       Kind == MCK_FPR64) {
16623a49ad71SWeining Lu     Op.setReg(convertFPR32ToFPR64(Reg));
16633a49ad71SWeining Lu     return Match_Success;
16643a49ad71SWeining Lu   }
16653a49ad71SWeining Lu 
16663a49ad71SWeining Lu   return Match_InvalidOperand;
16673a49ad71SWeining Lu }
16683a49ad71SWeining Lu 
16693347f77bSWeining Lu bool LoongArchAsmParser::generateImmOutOfRangeError(
16703347f77bSWeining Lu     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
16717ad4b262SCraig Topper     const Twine &Msg = "immediate must be an integer in the range") {
16723347f77bSWeining Lu   SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
16733347f77bSWeining Lu   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
16743347f77bSWeining Lu }
16753347f77bSWeining Lu 
16764b524088SLei Huang bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16773347f77bSWeining Lu                                                  OperandVector &Operands,
16783347f77bSWeining Lu                                                  MCStreamer &Out,
16793347f77bSWeining Lu                                                  uint64_t &ErrorInfo,
16803347f77bSWeining Lu                                                  bool MatchingInlineAsm) {
16813347f77bSWeining Lu   MCInst Inst;
16823347f77bSWeining Lu   FeatureBitset MissingFeatures;
16833347f77bSWeining Lu 
16843347f77bSWeining Lu   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
16853347f77bSWeining Lu                                      MatchingInlineAsm);
16863347f77bSWeining Lu   switch (Result) {
16873347f77bSWeining Lu   default:
16883347f77bSWeining Lu     break;
16893347f77bSWeining Lu   case Match_Success:
16903347f77bSWeining Lu     return processInstruction(Inst, IDLoc, Operands, Out);
16913347f77bSWeining Lu   case Match_MissingFeature: {
16923347f77bSWeining Lu     assert(MissingFeatures.any() && "Unknown missing features!");
16933347f77bSWeining Lu     bool FirstFeature = true;
16943347f77bSWeining Lu     std::string Msg = "instruction requires the following:";
16953347f77bSWeining Lu     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
16963347f77bSWeining Lu       if (MissingFeatures[i]) {
16973347f77bSWeining Lu         Msg += FirstFeature ? " " : ", ";
16983347f77bSWeining Lu         Msg += getSubtargetFeatureName(i);
16993347f77bSWeining Lu         FirstFeature = false;
17003347f77bSWeining Lu       }
17013347f77bSWeining Lu     }
17023347f77bSWeining Lu     return Error(IDLoc, Msg);
17033347f77bSWeining Lu   }
17043347f77bSWeining Lu   case Match_MnemonicFail: {
17053347f77bSWeining Lu     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
17063347f77bSWeining Lu     std::string Suggestion = LoongArchMnemonicSpellCheck(
17073347f77bSWeining Lu         ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
17083347f77bSWeining Lu     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
17093347f77bSWeining Lu   }
17103347f77bSWeining Lu   case Match_InvalidOperand: {
17113347f77bSWeining Lu     SMLoc ErrorLoc = IDLoc;
17123347f77bSWeining Lu     if (ErrorInfo != ~0ULL) {
17133347f77bSWeining Lu       if (ErrorInfo >= Operands.size())
17143347f77bSWeining Lu         return Error(ErrorLoc, "too few operands for instruction");
17153347f77bSWeining Lu 
17163347f77bSWeining Lu       ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
17173347f77bSWeining Lu       if (ErrorLoc == SMLoc())
17183347f77bSWeining Lu         ErrorLoc = IDLoc;
17193347f77bSWeining Lu     }
17203347f77bSWeining Lu     return Error(ErrorLoc, "invalid operand for instruction");
17213347f77bSWeining Lu   }
17223347f77bSWeining Lu   }
17233347f77bSWeining Lu 
17243347f77bSWeining Lu   // Handle the case when the error message is of specific type
17253347f77bSWeining Lu   // other than the generic Match_InvalidOperand, and the
17263347f77bSWeining Lu   // corresponding operand is missing.
17273347f77bSWeining Lu   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
17283347f77bSWeining Lu     SMLoc ErrorLoc = IDLoc;
17293347f77bSWeining Lu     if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
17303347f77bSWeining Lu       return Error(ErrorLoc, "too few operands for instruction");
17313347f77bSWeining Lu   }
17323347f77bSWeining Lu 
17333347f77bSWeining Lu   switch (Result) {
17343347f77bSWeining Lu   default:
17353347f77bSWeining Lu     break;
173624532d05SWeining Lu   case Match_RequiresMsbNotLessThanLsb: {
173724532d05SWeining Lu     SMLoc ErrorStart = Operands[3]->getStartLoc();
173824532d05SWeining Lu     return Error(ErrorStart, "msb is less than lsb",
173924532d05SWeining Lu                  SMRange(ErrorStart, Operands[4]->getEndLoc()));
174024532d05SWeining Lu   }
174111ec7307SWeining Lu   case Match_RequiresOpnd2NotR0R1:
174211ec7307SWeining Lu     return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1743c98add7aSWeining Lu   case Match_RequiresAMORdDifferRkRj:
1744c98add7aSWeining Lu     return Error(Operands[1]->getStartLoc(),
1745c98add7aSWeining Lu                  "$rd must be different from both $rk and $rj");
1746a7ec7f6dSwanglei   case Match_RequiresLAORdDifferRj:
1747a7ec7f6dSwanglei     return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
17484a84d8e4Swanglei   case Match_RequiresLAORdR4:
17494a84d8e4Swanglei     return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
17501aa3b64eSwanglei   case Match_InvalidUImm1:
17511aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17521aa3b64eSwanglei                                       /*Upper=*/(1 << 1) - 1);
17533347f77bSWeining Lu   case Match_InvalidUImm2:
17543347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17553347f77bSWeining Lu                                       /*Upper=*/(1 << 2) - 1);
17563347f77bSWeining Lu   case Match_InvalidUImm2plus1:
17573347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
17583347f77bSWeining Lu                                       /*Upper=*/(1 << 2));
17593347f77bSWeining Lu   case Match_InvalidUImm3:
17603347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17613347f77bSWeining Lu                                       /*Upper=*/(1 << 3) - 1);
17621aa3b64eSwanglei   case Match_InvalidUImm4:
17631aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17641aa3b64eSwanglei                                       /*Upper=*/(1 << 4) - 1);
17653347f77bSWeining Lu   case Match_InvalidUImm5:
17663347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17673347f77bSWeining Lu                                       /*Upper=*/(1 << 5) - 1);
17683347f77bSWeining Lu   case Match_InvalidUImm6:
17693347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17703347f77bSWeining Lu                                       /*Upper=*/(1 << 6) - 1);
17711aa3b64eSwanglei   case Match_InvalidUImm7:
17721aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17731aa3b64eSwanglei                                       /*Upper=*/(1 << 7) - 1);
17743b78065eSwanglei   case Match_InvalidUImm8:
17753b78065eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17763b78065eSwanglei                                       /*Upper=*/(1 << 8) - 1);
17773347f77bSWeining Lu   case Match_InvalidUImm12:
17783347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17793347f77bSWeining Lu                                       /*Upper=*/(1 << 12) - 1);
1780bf479547Swanglei   case Match_InvalidUImm12ori:
1781bf479547Swanglei     return generateImmOutOfRangeError(
1782bf479547Swanglei         Operands, ErrorInfo, /*Lower=*/0,
1783bf479547Swanglei         /*Upper=*/(1 << 12) - 1,
1784bf479547Swanglei         "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1785bf479547Swanglei         "integer in the range");
1786d6675b6aSwanglei   case Match_InvalidUImm14:
1787d6675b6aSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1788d6675b6aSwanglei                                       /*Upper=*/(1 << 14) - 1);
17893347f77bSWeining Lu   case Match_InvalidUImm15:
17903347f77bSWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
17913347f77bSWeining Lu                                       /*Upper=*/(1 << 15) - 1);
17921aa3b64eSwanglei   case Match_InvalidSImm5:
17931aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
17941aa3b64eSwanglei                                       /*Upper=*/(1 << 4) - 1);
17951aa3b64eSwanglei   case Match_InvalidSImm8:
17961aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
17971aa3b64eSwanglei                                       /*Upper=*/(1 << 7) - 1);
17981aa3b64eSwanglei   case Match_InvalidSImm8lsl1:
17991aa3b64eSwanglei     return generateImmOutOfRangeError(
18001aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
18011aa3b64eSwanglei         "immediate must be a multiple of 2 in the range");
18021aa3b64eSwanglei   case Match_InvalidSImm8lsl2:
18031aa3b64eSwanglei     return generateImmOutOfRangeError(
18041aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
18051aa3b64eSwanglei         "immediate must be a multiple of 4 in the range");
18061aa3b64eSwanglei   case Match_InvalidSImm10:
18071aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
18081aa3b64eSwanglei                                       /*Upper=*/(1 << 9) - 1);
18091aa3b64eSwanglei   case Match_InvalidSImm8lsl3:
18101aa3b64eSwanglei     return generateImmOutOfRangeError(
18111aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
18121aa3b64eSwanglei         "immediate must be a multiple of 8 in the range");
18131aa3b64eSwanglei   case Match_InvalidSImm9lsl3:
18141aa3b64eSwanglei     return generateImmOutOfRangeError(
18151aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
18161aa3b64eSwanglei         "immediate must be a multiple of 8 in the range");
18171aa3b64eSwanglei   case Match_InvalidSImm10lsl2:
18181aa3b64eSwanglei     return generateImmOutOfRangeError(
18191aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
18201aa3b64eSwanglei         "immediate must be a multiple of 4 in the range");
18211aa3b64eSwanglei   case Match_InvalidSImm11lsl1:
18221aa3b64eSwanglei     return generateImmOutOfRangeError(
18231aa3b64eSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
18241aa3b64eSwanglei         "immediate must be a multiple of 2 in the range");
18253347f77bSWeining Lu   case Match_InvalidSImm12:
1826bf479547Swanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1827bf479547Swanglei                                       /*Upper=*/(1 << 11) - 1);
1828bf479547Swanglei   case Match_InvalidSImm12addlike:
1829c2ee21cfSwanglei     return generateImmOutOfRangeError(
1830c2ee21cfSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1831c2ee21cfSwanglei         /*Upper=*/(1 << 11) - 1,
1832c2ee21cfSwanglei         "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1833c2ee21cfSwanglei         "in the range");
1834bf479547Swanglei   case Match_InvalidSImm12lu52id:
1835bf479547Swanglei     return generateImmOutOfRangeError(
1836bf479547Swanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1837bf479547Swanglei         /*Upper=*/(1 << 11) - 1,
1838bf479547Swanglei         "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1839bf479547Swanglei         "integer in the range");
18401aa3b64eSwanglei   case Match_InvalidSImm13:
18411aa3b64eSwanglei     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
18421aa3b64eSwanglei                                       /*Upper=*/(1 << 12) - 1);
18433347f77bSWeining Lu   case Match_InvalidSImm14lsl2:
18443347f77bSWeining Lu     return generateImmOutOfRangeError(
18453347f77bSWeining Lu         Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
18463347f77bSWeining Lu         "immediate must be a multiple of 4 in the range");
18473347f77bSWeining Lu   case Match_InvalidSImm16:
1848c008a697SWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1849c008a697SWeining Lu                                       /*Upper=*/(1 << 15) - 1);
18503347f77bSWeining Lu   case Match_InvalidSImm16lsl2:
18513347f77bSWeining Lu     return generateImmOutOfRangeError(
18523347f77bSWeining Lu         Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1853bf479547Swanglei         "operand must be a symbol with modifier (e.g. %b16) or an integer "
1854bf479547Swanglei         "in the range");
18553347f77bSWeining Lu   case Match_InvalidSImm20:
1856c008a697SWeining Lu     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1857c008a697SWeining Lu                                       /*Upper=*/(1 << 19) - 1);
1858bf479547Swanglei   case Match_InvalidSImm20lu12iw:
1859bf479547Swanglei     return generateImmOutOfRangeError(
1860bf479547Swanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1861bf479547Swanglei         /*Upper=*/(1 << 19) - 1,
1862bf479547Swanglei         "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1863bf479547Swanglei         "in the range");
1864bf479547Swanglei   case Match_InvalidSImm20lu32id:
1865bf479547Swanglei     return generateImmOutOfRangeError(
1866bf479547Swanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1867bf479547Swanglei         /*Upper=*/(1 << 19) - 1,
1868bf479547Swanglei         "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1869bf479547Swanglei         "integer in the range");
1870c2ee21cfSwanglei   case Match_InvalidSImm20pcalau12i:
1871c2ee21cfSwanglei     return generateImmOutOfRangeError(
1872c2ee21cfSwanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1873c2ee21cfSwanglei         /*Upper=*/(1 << 19) - 1,
1874c2ee21cfSwanglei         "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1875c2ee21cfSwanglei         "in the range");
18762cf420d5Swanglei   case Match_InvalidSImm20pcaddu18i:
18772cf420d5Swanglei     return generateImmOutOfRangeError(
18782cf420d5Swanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
18792cf420d5Swanglei         /*Upper=*/(1 << 19) - 1,
18802cf420d5Swanglei         "operand must be a symbol with modifier (e.g. %call36) or an integer "
18812cf420d5Swanglei         "in the range");
1882e27358c8Swanglei   case Match_InvalidSImm20pcaddi:
1883e27358c8Swanglei     return generateImmOutOfRangeError(
1884e27358c8Swanglei         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1885e27358c8Swanglei         /*Upper=*/(1 << 19) - 1,
1886e27358c8Swanglei         "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1887e27358c8Swanglei         "in the range");
18883347f77bSWeining Lu   case Match_InvalidSImm21lsl2:
18893347f77bSWeining Lu     return generateImmOutOfRangeError(
18903347f77bSWeining Lu         Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1891bf479547Swanglei         "operand must be a symbol with modifier (e.g. %b21) or an integer "
1892bf479547Swanglei         "in the range");
1893c2ee21cfSwanglei   case Match_InvalidSImm26Operand:
18943347f77bSWeining Lu     return generateImmOutOfRangeError(
18953347f77bSWeining Lu         Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1896c2ee21cfSwanglei         "operand must be a bare symbol name or an immediate must be a multiple "
1897c2ee21cfSwanglei         "of 4 in the range");
1898f873c50cSwanglei   case Match_InvalidImm32: {
1899f873c50cSwanglei     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1900f873c50cSwanglei     return Error(ErrorLoc, "operand must be a 32 bit immediate");
1901f873c50cSwanglei   }
1902078aaf1fSwanglei   case Match_InvalidImm64: {
1903078aaf1fSwanglei     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1904078aaf1fSwanglei     return Error(ErrorLoc, "operand must be a 64 bit immediate");
1905078aaf1fSwanglei   }
1906a7ec7f6dSwanglei   case Match_InvalidBareSymbol: {
1907a7ec7f6dSwanglei     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1908a7ec7f6dSwanglei     return Error(ErrorLoc, "operand must be a bare symbol name");
1909a7ec7f6dSwanglei   }
19100f231567Swanglei   case Match_InvalidTPRelAddSymbol: {
19110f231567Swanglei     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
19120f231567Swanglei     return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
19130f231567Swanglei   }
19143347f77bSWeining Lu   }
19153347f77bSWeining Lu   llvm_unreachable("Unknown match type detected!");
19163347f77bSWeining Lu }
19173347f77bSWeining Lu 
19181a787b3cSwanglei bool LoongArchAsmParser::parseDirectiveOption() {
19191a787b3cSwanglei   MCAsmParser &Parser = getParser();
19201a787b3cSwanglei   // Get the option token.
19211a787b3cSwanglei   AsmToken Tok = Parser.getTok();
19221a787b3cSwanglei 
19231a787b3cSwanglei   // At the moment only identifiers are supported.
19241a787b3cSwanglei   if (parseToken(AsmToken::Identifier, "expected identifier"))
19251a787b3cSwanglei     return true;
19261a787b3cSwanglei 
19271a787b3cSwanglei   StringRef Option = Tok.getIdentifier();
19281a787b3cSwanglei 
19291a787b3cSwanglei   if (Option == "push") {
19301a787b3cSwanglei     if (Parser.parseEOL())
19311a787b3cSwanglei       return true;
19321a787b3cSwanglei 
19331a787b3cSwanglei     getTargetStreamer().emitDirectiveOptionPush();
19341a787b3cSwanglei     pushFeatureBits();
19351a787b3cSwanglei     return false;
19361a787b3cSwanglei   }
19371a787b3cSwanglei 
19381a787b3cSwanglei   if (Option == "pop") {
19391a787b3cSwanglei     SMLoc StartLoc = Parser.getTok().getLoc();
19401a787b3cSwanglei     if (Parser.parseEOL())
19411a787b3cSwanglei       return true;
19421a787b3cSwanglei 
19431a787b3cSwanglei     getTargetStreamer().emitDirectiveOptionPop();
19441a787b3cSwanglei     if (popFeatureBits())
19451a787b3cSwanglei       return Error(StartLoc, ".option pop with no .option push");
19461a787b3cSwanglei 
19471a787b3cSwanglei     return false;
19481a787b3cSwanglei   }
19491a787b3cSwanglei 
19501a787b3cSwanglei   if (Option == "relax") {
19511a787b3cSwanglei     if (Parser.parseEOL())
19521a787b3cSwanglei       return true;
19531a787b3cSwanglei 
19541a787b3cSwanglei     getTargetStreamer().emitDirectiveOptionRelax();
19551a787b3cSwanglei     setFeatureBits(LoongArch::FeatureRelax, "relax");
19561a787b3cSwanglei     return false;
19571a787b3cSwanglei   }
19581a787b3cSwanglei 
19591a787b3cSwanglei   if (Option == "norelax") {
19601a787b3cSwanglei     if (Parser.parseEOL())
19611a787b3cSwanglei       return true;
19621a787b3cSwanglei 
19631a787b3cSwanglei     getTargetStreamer().emitDirectiveOptionNoRelax();
19641a787b3cSwanglei     clearFeatureBits(LoongArch::FeatureRelax, "relax");
19651a787b3cSwanglei     return false;
19661a787b3cSwanglei   }
19671a787b3cSwanglei 
19681a787b3cSwanglei   // Unknown option.
19691a787b3cSwanglei   Warning(Parser.getTok().getLoc(),
19701a787b3cSwanglei           "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
19711a787b3cSwanglei   Parser.eatToEndOfStatement();
19721a787b3cSwanglei   return false;
19731a787b3cSwanglei }
19741a787b3cSwanglei 
19751a787b3cSwanglei ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
19761a787b3cSwanglei   if (DirectiveID.getString() == ".option")
19771a787b3cSwanglei     return parseDirectiveOption();
19781a787b3cSwanglei 
19791a787b3cSwanglei   return ParseStatus::NoMatch;
19801a787b3cSwanglei }
19811a787b3cSwanglei 
19823347f77bSWeining Lu extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
19833347f77bSWeining Lu   RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
19843347f77bSWeining Lu   RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
19853347f77bSWeining Lu }
1986