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