181ad6265SDimitry Andric // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "MCTargetDesc/LoongArchInstPrinter.h" 10*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMCExpr.h" 1181ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h" 12*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMatInt.h" 1381ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h" 1481ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 15*bdd1243dSDimitry Andric #include "llvm/MC/MCInstBuilder.h" 1681ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 1781ad6265SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 1881ad6265SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 1981ad6265SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2181ad6265SDimitry Andric #include "llvm/MC/MCStreamer.h" 2281ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 23*bdd1243dSDimitry Andric #include "llvm/MC/MCValue.h" 2481ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2581ad6265SDimitry Andric #include "llvm/Support/Casting.h" 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric using namespace llvm; 2881ad6265SDimitry Andric 2981ad6265SDimitry Andric #define DEBUG_TYPE "loongarch-asm-parser" 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric namespace { 3281ad6265SDimitry Andric class LoongArchAsmParser : public MCTargetAsmParser { 3381ad6265SDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); } 34*bdd1243dSDimitry Andric bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); } 35*bdd1243dSDimitry Andric 36*bdd1243dSDimitry Andric struct Inst { 37*bdd1243dSDimitry Andric unsigned Opc; 38*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK; 39*bdd1243dSDimitry Andric Inst(unsigned Opc, 40*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None) 41*bdd1243dSDimitry Andric : Opc(Opc), VK(VK) {} 42*bdd1243dSDimitry Andric }; 43*bdd1243dSDimitry Andric using InstSeq = SmallVector<Inst>; 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric /// Parse a register as used in CFI directives. 46*bdd1243dSDimitry Andric bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 47*bdd1243dSDimitry Andric SMLoc &EndLoc) override; 48*bdd1243dSDimitry Andric OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 4981ad6265SDimitry Andric SMLoc &EndLoc) override; 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 5281ad6265SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override; 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric bool ParseDirective(AsmToken DirectiveID) override { return true; } 5581ad6265SDimitry Andric 5681ad6265SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 5781ad6265SDimitry Andric OperandVector &Operands, MCStreamer &Out, 5881ad6265SDimitry Andric uint64_t &ErrorInfo, 5981ad6265SDimitry Andric bool MatchingInlineAsm) override; 6081ad6265SDimitry Andric 6181ad6265SDimitry Andric unsigned checkTargetMatchPredicate(MCInst &Inst) override; 6281ad6265SDimitry Andric 6381ad6265SDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 6481ad6265SDimitry Andric unsigned Kind) override; 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 6781ad6265SDimitry Andric int64_t Lower, int64_t Upper, Twine Msg); 6881ad6265SDimitry Andric 6981ad6265SDimitry Andric /// Helper for processing MC instructions that have been successfully matched 7081ad6265SDimitry Andric /// by MatchAndEmitInstruction. 7181ad6265SDimitry Andric bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 7281ad6265SDimitry Andric MCStreamer &Out); 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric // Auto-generated instruction matching functions. 7581ad6265SDimitry Andric #define GET_ASSEMBLER_HEADER 7681ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric OperandMatchResultTy parseRegister(OperandVector &Operands); 7981ad6265SDimitry Andric OperandMatchResultTy parseImmediate(OperandVector &Operands); 80*bdd1243dSDimitry Andric OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); 81*bdd1243dSDimitry Andric OperandMatchResultTy parseSImm26Operand(OperandVector &Operands); 82*bdd1243dSDimitry Andric OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands); 8381ad6265SDimitry Andric 8481ad6265SDimitry Andric bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 8581ad6265SDimitry Andric 86*bdd1243dSDimitry Andric // Helper to emit the sequence of instructions generated by the 87*bdd1243dSDimitry Andric // "emitLoadAddress*" functions. 88*bdd1243dSDimitry Andric void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 89*bdd1243dSDimitry Andric const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts, 90*bdd1243dSDimitry Andric SMLoc IDLoc, MCStreamer &Out); 91*bdd1243dSDimitry Andric 92*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.abs $rd, sym". 93*bdd1243dSDimitry Andric void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 94*bdd1243dSDimitry Andric 95*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.pcrel $rd, sym". 96*bdd1243dSDimitry Andric void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 97*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym". 98*bdd1243dSDimitry Andric void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 99*bdd1243dSDimitry Andric 100*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.got $rd, sym". 101*bdd1243dSDimitry Andric void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 102*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.got $rd, $rj, sym". 103*bdd1243dSDimitry Andric void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 104*bdd1243dSDimitry Andric 105*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.le $rd, sym". 106*bdd1243dSDimitry Andric void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 107*bdd1243dSDimitry Andric 108*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ie $rd, sym". 109*bdd1243dSDimitry Andric void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 110*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym". 111*bdd1243dSDimitry Andric void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 112*bdd1243dSDimitry Andric 113*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ld $rd, sym". 114*bdd1243dSDimitry Andric void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 115*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym". 116*bdd1243dSDimitry Andric void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 117*bdd1243dSDimitry Andric 118*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.gd $rd, sym". 119*bdd1243dSDimitry Andric void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 120*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym". 121*bdd1243dSDimitry Andric void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 122*bdd1243dSDimitry Andric 123*bdd1243dSDimitry Andric // Helper to emit pseudo instruction "li.w/d $rd, $imm". 124*bdd1243dSDimitry Andric void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 125*bdd1243dSDimitry Andric 12681ad6265SDimitry Andric public: 12781ad6265SDimitry Andric enum LoongArchMatchResultTy { 12881ad6265SDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 12981ad6265SDimitry Andric Match_RequiresMsbNotLessThanLsb, 13081ad6265SDimitry Andric Match_RequiresOpnd2NotR0R1, 131*bdd1243dSDimitry Andric Match_RequiresAMORdDifferRkRj, 132*bdd1243dSDimitry Andric Match_RequiresLAORdDifferRj, 13381ad6265SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES 13481ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 13581ad6265SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES 13681ad6265SDimitry Andric }; 13781ad6265SDimitry Andric 138*bdd1243dSDimitry Andric static bool classifySymbolRef(const MCExpr *Expr, 139*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind); 140*bdd1243dSDimitry Andric 14181ad6265SDimitry Andric LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 14281ad6265SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 14381ad6265SDimitry Andric : MCTargetAsmParser(Options, STI, MII) { 14481ad6265SDimitry Andric Parser.addAliasForDirective(".half", ".2byte"); 14581ad6265SDimitry Andric Parser.addAliasForDirective(".hword", ".2byte"); 14681ad6265SDimitry Andric Parser.addAliasForDirective(".word", ".4byte"); 14781ad6265SDimitry Andric Parser.addAliasForDirective(".dword", ".8byte"); 14881ad6265SDimitry Andric 14981ad6265SDimitry Andric // Initialize the set of available features. 15081ad6265SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 15181ad6265SDimitry Andric } 15281ad6265SDimitry Andric }; 15381ad6265SDimitry Andric 15481ad6265SDimitry Andric // Instances of this class represent a parsed LoongArch machine instruction. 15581ad6265SDimitry Andric class LoongArchOperand : public MCParsedAsmOperand { 15681ad6265SDimitry Andric enum class KindTy { 15781ad6265SDimitry Andric Token, 15881ad6265SDimitry Andric Register, 15981ad6265SDimitry Andric Immediate, 16081ad6265SDimitry Andric } Kind; 16181ad6265SDimitry Andric 16281ad6265SDimitry Andric struct RegOp { 16381ad6265SDimitry Andric MCRegister RegNum; 16481ad6265SDimitry Andric }; 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric struct ImmOp { 16781ad6265SDimitry Andric const MCExpr *Val; 16881ad6265SDimitry Andric }; 16981ad6265SDimitry Andric 17081ad6265SDimitry Andric SMLoc StartLoc, EndLoc; 17181ad6265SDimitry Andric union { 17281ad6265SDimitry Andric StringRef Tok; 17381ad6265SDimitry Andric struct RegOp Reg; 17481ad6265SDimitry Andric struct ImmOp Imm; 17581ad6265SDimitry Andric }; 17681ad6265SDimitry Andric 17781ad6265SDimitry Andric public: 17881ad6265SDimitry Andric LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 17981ad6265SDimitry Andric 18081ad6265SDimitry Andric bool isToken() const override { return Kind == KindTy::Token; } 18181ad6265SDimitry Andric bool isReg() const override { return Kind == KindTy::Register; } 18281ad6265SDimitry Andric bool isImm() const override { return Kind == KindTy::Immediate; } 18381ad6265SDimitry Andric bool isMem() const override { return false; } 18481ad6265SDimitry Andric void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } 185*bdd1243dSDimitry Andric bool isGPR() const { 186*bdd1243dSDimitry Andric return Kind == KindTy::Register && 187*bdd1243dSDimitry Andric LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains( 188*bdd1243dSDimitry Andric Reg.RegNum); 189*bdd1243dSDimitry Andric } 19081ad6265SDimitry Andric 191*bdd1243dSDimitry Andric static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 192*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &VK) { 193*bdd1243dSDimitry Andric if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) { 194*bdd1243dSDimitry Andric VK = LE->getKind(); 195*bdd1243dSDimitry Andric return false; 196*bdd1243dSDimitry Andric } 197*bdd1243dSDimitry Andric 19881ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 19981ad6265SDimitry Andric Imm = CE->getValue(); 20081ad6265SDimitry Andric return true; 20181ad6265SDimitry Andric } 20281ad6265SDimitry Andric 20381ad6265SDimitry Andric return false; 20481ad6265SDimitry Andric } 20581ad6265SDimitry Andric 20681ad6265SDimitry Andric template <unsigned N, int P = 0> bool isUImm() const { 20781ad6265SDimitry Andric if (!isImm()) 20881ad6265SDimitry Andric return false; 20981ad6265SDimitry Andric 21081ad6265SDimitry Andric int64_t Imm; 211*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 212*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 213*bdd1243dSDimitry Andric return IsConstantImm && isUInt<N>(Imm - P) && 214*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric template <unsigned N, unsigned S = 0> bool isSImm() const { 21881ad6265SDimitry Andric if (!isImm()) 21981ad6265SDimitry Andric return false; 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric int64_t Imm; 222*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 223*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 224*bdd1243dSDimitry Andric return IsConstantImm && isShiftedInt<N, S>(Imm) && 225*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 226*bdd1243dSDimitry Andric } 227*bdd1243dSDimitry Andric 228*bdd1243dSDimitry Andric bool isBareSymbol() const { 229*bdd1243dSDimitry Andric int64_t Imm; 230*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 231*bdd1243dSDimitry Andric // Must be of 'immediate' type but not a constant. 232*bdd1243dSDimitry Andric if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 233*bdd1243dSDimitry Andric return false; 234*bdd1243dSDimitry Andric return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 235*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 23681ad6265SDimitry Andric } 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric bool isUImm2() const { return isUImm<2>(); } 23981ad6265SDimitry Andric bool isUImm2plus1() const { return isUImm<2, 1>(); } 24081ad6265SDimitry Andric bool isUImm3() const { return isUImm<3>(); } 24181ad6265SDimitry Andric bool isUImm5() const { return isUImm<5>(); } 24281ad6265SDimitry Andric bool isUImm6() const { return isUImm<6>(); } 24381ad6265SDimitry Andric bool isUImm8() const { return isUImm<8>(); } 244*bdd1243dSDimitry Andric bool isSImm12() const { return isSImm<12>(); } 245*bdd1243dSDimitry Andric 246*bdd1243dSDimitry Andric bool isSImm12addlike() const { 247*bdd1243dSDimitry Andric if (!isImm()) 248*bdd1243dSDimitry Andric return false; 249*bdd1243dSDimitry Andric 250*bdd1243dSDimitry Andric int64_t Imm; 251*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 252*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 253*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 254*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 255*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 256*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 257*bdd1243dSDimitry Andric return IsConstantImm 258*bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 259*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 260*bdd1243dSDimitry Andric IsValidKind; 261*bdd1243dSDimitry Andric } 262*bdd1243dSDimitry Andric 263*bdd1243dSDimitry Andric bool isSImm12lu52id() const { 264*bdd1243dSDimitry Andric if (!isImm()) 265*bdd1243dSDimitry Andric return false; 266*bdd1243dSDimitry Andric 267*bdd1243dSDimitry Andric int64_t Imm; 268*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 269*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 270*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 271*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 || 272*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 || 273*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 || 274*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 || 275*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 || 276*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 || 277*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12; 278*bdd1243dSDimitry Andric return IsConstantImm 279*bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 280*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 281*bdd1243dSDimitry Andric IsValidKind; 282*bdd1243dSDimitry Andric } 283*bdd1243dSDimitry Andric 28481ad6265SDimitry Andric bool isUImm12() const { return isUImm<12>(); } 285*bdd1243dSDimitry Andric 286*bdd1243dSDimitry Andric bool isUImm12ori() const { 287*bdd1243dSDimitry Andric if (!isImm()) 288*bdd1243dSDimitry Andric return false; 289*bdd1243dSDimitry Andric 290*bdd1243dSDimitry Andric int64_t Imm; 291*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 292*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 293*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 294*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 || 295*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 296*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 || 297*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 298*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 || 299*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 || 300*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 301*bdd1243dSDimitry Andric return IsConstantImm 302*bdd1243dSDimitry Andric ? isUInt<12>(Imm) && IsValidKind 303*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 304*bdd1243dSDimitry Andric IsValidKind; 305*bdd1243dSDimitry Andric } 306*bdd1243dSDimitry Andric 30781ad6265SDimitry Andric bool isUImm14() const { return isUImm<14>(); } 30881ad6265SDimitry Andric bool isUImm15() const { return isUImm<15>(); } 309*bdd1243dSDimitry Andric 31081ad6265SDimitry Andric bool isSImm14lsl2() const { return isSImm<14, 2>(); } 31181ad6265SDimitry Andric bool isSImm16() const { return isSImm<16>(); } 312*bdd1243dSDimitry Andric 313*bdd1243dSDimitry Andric bool isSImm16lsl2() const { 314*bdd1243dSDimitry Andric if (!isImm()) 315*bdd1243dSDimitry Andric return false; 316*bdd1243dSDimitry Andric 317*bdd1243dSDimitry Andric int64_t Imm; 318*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 319*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 320*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 321*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B16 || 322*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12; 323*bdd1243dSDimitry Andric return IsConstantImm 324*bdd1243dSDimitry Andric ? isShiftedInt<16, 2>(Imm) && IsValidKind 325*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 326*bdd1243dSDimitry Andric IsValidKind; 327*bdd1243dSDimitry Andric } 328*bdd1243dSDimitry Andric 32981ad6265SDimitry Andric bool isSImm20() const { return isSImm<20>(); } 330*bdd1243dSDimitry Andric 331*bdd1243dSDimitry Andric bool isSImm20pcalau12i() const { 332*bdd1243dSDimitry Andric if (!isImm()) 333*bdd1243dSDimitry Andric return false; 334*bdd1243dSDimitry Andric 335*bdd1243dSDimitry Andric int64_t Imm; 336*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 337*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 338*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 339*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 || 340*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 || 341*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 || 342*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 || 343*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 344*bdd1243dSDimitry Andric return IsConstantImm 345*bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 346*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 347*bdd1243dSDimitry Andric IsValidKind; 348*bdd1243dSDimitry Andric } 349*bdd1243dSDimitry Andric 350*bdd1243dSDimitry Andric bool isSImm20lu12iw() const { 351*bdd1243dSDimitry Andric if (!isImm()) 352*bdd1243dSDimitry Andric return false; 353*bdd1243dSDimitry Andric 354*bdd1243dSDimitry Andric int64_t Imm; 355*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 356*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 357*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 358*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 || 359*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 || 360*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 || 361*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 || 362*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 || 363*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 364*bdd1243dSDimitry Andric return IsConstantImm 365*bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 366*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 367*bdd1243dSDimitry Andric IsValidKind; 368*bdd1243dSDimitry Andric } 369*bdd1243dSDimitry Andric 370*bdd1243dSDimitry Andric bool isSImm20lu32id() const { 371*bdd1243dSDimitry Andric if (!isImm()) 372*bdd1243dSDimitry Andric return false; 373*bdd1243dSDimitry Andric 374*bdd1243dSDimitry Andric int64_t Imm; 375*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 376*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 377*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 378*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 || 379*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 || 380*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 || 381*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 || 382*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 || 383*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 || 384*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20; 385*bdd1243dSDimitry Andric 386*bdd1243dSDimitry Andric return IsConstantImm 387*bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 388*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 389*bdd1243dSDimitry Andric IsValidKind; 390*bdd1243dSDimitry Andric } 391*bdd1243dSDimitry Andric 392*bdd1243dSDimitry Andric bool isSImm21lsl2() const { 393*bdd1243dSDimitry Andric if (!isImm()) 394*bdd1243dSDimitry Andric return false; 395*bdd1243dSDimitry Andric 396*bdd1243dSDimitry Andric int64_t Imm; 397*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 398*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 399*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 400*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B21; 401*bdd1243dSDimitry Andric return IsConstantImm 402*bdd1243dSDimitry Andric ? isShiftedInt<21, 2>(Imm) && IsValidKind 403*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 404*bdd1243dSDimitry Andric IsValidKind; 405*bdd1243dSDimitry Andric } 406*bdd1243dSDimitry Andric 407*bdd1243dSDimitry Andric bool isSImm26Operand() const { 408*bdd1243dSDimitry Andric if (!isImm()) 409*bdd1243dSDimitry Andric return false; 410*bdd1243dSDimitry Andric 411*bdd1243dSDimitry Andric int64_t Imm; 412*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 413*bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 414*bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 415*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL || 416*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT || 417*bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B26; 418*bdd1243dSDimitry Andric return IsConstantImm 419*bdd1243dSDimitry Andric ? isShiftedInt<26, 2>(Imm) && IsValidKind 420*bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 421*bdd1243dSDimitry Andric IsValidKind; 422*bdd1243dSDimitry Andric } 423*bdd1243dSDimitry Andric 424*bdd1243dSDimitry Andric bool isImm32() const { return isSImm<32>() || isUImm<32>(); } 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric /// Gets location of the first token of this operand. 42781ad6265SDimitry Andric SMLoc getStartLoc() const override { return StartLoc; } 42881ad6265SDimitry Andric /// Gets location of the last token of this operand. 42981ad6265SDimitry Andric SMLoc getEndLoc() const override { return EndLoc; } 43081ad6265SDimitry Andric 43181ad6265SDimitry Andric unsigned getReg() const override { 43281ad6265SDimitry Andric assert(Kind == KindTy::Register && "Invalid type access!"); 43381ad6265SDimitry Andric return Reg.RegNum.id(); 43481ad6265SDimitry Andric } 43581ad6265SDimitry Andric 43681ad6265SDimitry Andric const MCExpr *getImm() const { 43781ad6265SDimitry Andric assert(Kind == KindTy::Immediate && "Invalid type access!"); 43881ad6265SDimitry Andric return Imm.Val; 43981ad6265SDimitry Andric } 44081ad6265SDimitry Andric 44181ad6265SDimitry Andric StringRef getToken() const { 44281ad6265SDimitry Andric assert(Kind == KindTy::Token && "Invalid type access!"); 44381ad6265SDimitry Andric return Tok; 44481ad6265SDimitry Andric } 44581ad6265SDimitry Andric 44681ad6265SDimitry Andric void print(raw_ostream &OS) const override { 447*bdd1243dSDimitry Andric auto RegName = [](MCRegister Reg) { 44881ad6265SDimitry Andric if (Reg) 44981ad6265SDimitry Andric return LoongArchInstPrinter::getRegisterName(Reg); 45081ad6265SDimitry Andric else 45181ad6265SDimitry Andric return "noreg"; 45281ad6265SDimitry Andric }; 45381ad6265SDimitry Andric 45481ad6265SDimitry Andric switch (Kind) { 45581ad6265SDimitry Andric case KindTy::Immediate: 45681ad6265SDimitry Andric OS << *getImm(); 45781ad6265SDimitry Andric break; 45881ad6265SDimitry Andric case KindTy::Register: 45981ad6265SDimitry Andric OS << "<register " << RegName(getReg()) << ">"; 46081ad6265SDimitry Andric break; 46181ad6265SDimitry Andric case KindTy::Token: 46281ad6265SDimitry Andric OS << "'" << getToken() << "'"; 46381ad6265SDimitry Andric break; 46481ad6265SDimitry Andric } 46581ad6265SDimitry Andric } 46681ad6265SDimitry Andric 46781ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) { 46881ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Token); 46981ad6265SDimitry Andric Op->Tok = Str; 47081ad6265SDimitry Andric Op->StartLoc = S; 47181ad6265SDimitry Andric Op->EndLoc = S; 47281ad6265SDimitry Andric return Op; 47381ad6265SDimitry Andric } 47481ad6265SDimitry Andric 47581ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S, 47681ad6265SDimitry Andric SMLoc E) { 47781ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Register); 47881ad6265SDimitry Andric Op->Reg.RegNum = RegNo; 47981ad6265SDimitry Andric Op->StartLoc = S; 48081ad6265SDimitry Andric Op->EndLoc = E; 48181ad6265SDimitry Andric return Op; 48281ad6265SDimitry Andric } 48381ad6265SDimitry Andric 48481ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S, 48581ad6265SDimitry Andric SMLoc E) { 48681ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate); 48781ad6265SDimitry Andric Op->Imm.Val = Val; 48881ad6265SDimitry Andric Op->StartLoc = S; 48981ad6265SDimitry Andric Op->EndLoc = E; 49081ad6265SDimitry Andric return Op; 49181ad6265SDimitry Andric } 49281ad6265SDimitry Andric 49381ad6265SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const { 49481ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) 49581ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue())); 49681ad6265SDimitry Andric else 49781ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 49881ad6265SDimitry Andric } 49981ad6265SDimitry Andric 50081ad6265SDimitry Andric // Used by the TableGen Code. 50181ad6265SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const { 50281ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 50381ad6265SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 50481ad6265SDimitry Andric } 50581ad6265SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const { 50681ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 50781ad6265SDimitry Andric addExpr(Inst, getImm()); 50881ad6265SDimitry Andric } 50981ad6265SDimitry Andric }; 510972a253aSDimitry Andric } // end namespace 51181ad6265SDimitry Andric 51281ad6265SDimitry Andric #define GET_REGISTER_MATCHER 51381ad6265SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME 51481ad6265SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 51581ad6265SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER 51681ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 51781ad6265SDimitry Andric 51881ad6265SDimitry Andric static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 51981ad6265SDimitry Andric assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); 52081ad6265SDimitry Andric return Reg - LoongArch::F0 + LoongArch::F0_64; 52181ad6265SDimitry Andric } 52281ad6265SDimitry Andric 52381ad6265SDimitry Andric // Attempts to match Name as a register (either using the default name or 52481ad6265SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon 52581ad6265SDimitry Andric // failure, returns true and sets RegNo to 0. 52681ad6265SDimitry Andric static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 52781ad6265SDimitry Andric RegNo = MatchRegisterName(Name); 52881ad6265SDimitry Andric // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial 52981ad6265SDimitry Andric // match always matches the 32-bit variant, and not the 64-bit one. 53081ad6265SDimitry Andric assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); 53181ad6265SDimitry Andric // The default FPR register class is based on the tablegen enum ordering. 53281ad6265SDimitry Andric static_assert(LoongArch::F0 < LoongArch::F0_64, 53381ad6265SDimitry Andric "FPR matching must be updated"); 53481ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 53581ad6265SDimitry Andric RegNo = MatchRegisterAltName(Name); 53681ad6265SDimitry Andric 53781ad6265SDimitry Andric return RegNo == LoongArch::NoRegister; 53881ad6265SDimitry Andric } 53981ad6265SDimitry Andric 540*bdd1243dSDimitry Andric bool LoongArchAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 54181ad6265SDimitry Andric SMLoc &EndLoc) { 54281ad6265SDimitry Andric return Error(getLoc(), "invalid register number"); 54381ad6265SDimitry Andric } 54481ad6265SDimitry Andric 545*bdd1243dSDimitry Andric OperandMatchResultTy LoongArchAsmParser::tryParseRegister(MCRegister &RegNo, 54681ad6265SDimitry Andric SMLoc &StartLoc, 54781ad6265SDimitry Andric SMLoc &EndLoc) { 54881ad6265SDimitry Andric llvm_unreachable("Unimplemented function."); 54981ad6265SDimitry Andric } 55081ad6265SDimitry Andric 551*bdd1243dSDimitry Andric bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr, 552*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind) { 553*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_None; 554*bdd1243dSDimitry Andric 555*bdd1243dSDimitry Andric if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) { 556*bdd1243dSDimitry Andric Kind = RE->getKind(); 557*bdd1243dSDimitry Andric Expr = RE->getSubExpr(); 558*bdd1243dSDimitry Andric } 559*bdd1243dSDimitry Andric 560*bdd1243dSDimitry Andric MCValue Res; 561*bdd1243dSDimitry Andric if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr)) 562*bdd1243dSDimitry Andric return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None; 563*bdd1243dSDimitry Andric return false; 564*bdd1243dSDimitry Andric } 565*bdd1243dSDimitry Andric 56681ad6265SDimitry Andric OperandMatchResultTy 56781ad6265SDimitry Andric LoongArchAsmParser::parseRegister(OperandVector &Operands) { 56881ad6265SDimitry Andric if (getLexer().getTok().isNot(AsmToken::Dollar)) 56981ad6265SDimitry Andric return MatchOperand_NoMatch; 57081ad6265SDimitry Andric 57181ad6265SDimitry Andric // Eat the $ prefix. 57281ad6265SDimitry Andric getLexer().Lex(); 57381ad6265SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 57481ad6265SDimitry Andric return MatchOperand_NoMatch; 57581ad6265SDimitry Andric 57681ad6265SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 57781ad6265SDimitry Andric MCRegister RegNo; 57881ad6265SDimitry Andric matchRegisterNameHelper(RegNo, Name); 57981ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 58081ad6265SDimitry Andric return MatchOperand_NoMatch; 58181ad6265SDimitry Andric 58281ad6265SDimitry Andric SMLoc S = getLoc(); 58381ad6265SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 58481ad6265SDimitry Andric getLexer().Lex(); 58581ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric return MatchOperand_Success; 58881ad6265SDimitry Andric } 58981ad6265SDimitry Andric 59081ad6265SDimitry Andric OperandMatchResultTy 59181ad6265SDimitry Andric LoongArchAsmParser::parseImmediate(OperandVector &Operands) { 59281ad6265SDimitry Andric SMLoc S = getLoc(); 59381ad6265SDimitry Andric SMLoc E; 59481ad6265SDimitry Andric const MCExpr *Res; 59581ad6265SDimitry Andric 596*bdd1243dSDimitry Andric switch (getLexer().getKind()) { 597*bdd1243dSDimitry Andric default: 598*bdd1243dSDimitry Andric return MatchOperand_NoMatch; 599*bdd1243dSDimitry Andric case AsmToken::LParen: 600*bdd1243dSDimitry Andric case AsmToken::Dot: 601*bdd1243dSDimitry Andric case AsmToken::Minus: 602*bdd1243dSDimitry Andric case AsmToken::Plus: 603*bdd1243dSDimitry Andric case AsmToken::Exclaim: 604*bdd1243dSDimitry Andric case AsmToken::Tilde: 605*bdd1243dSDimitry Andric case AsmToken::Integer: 606*bdd1243dSDimitry Andric case AsmToken::String: 607*bdd1243dSDimitry Andric case AsmToken::Identifier: 60881ad6265SDimitry Andric if (getParser().parseExpression(Res, E)) 60981ad6265SDimitry Andric return MatchOperand_ParseFail; 610*bdd1243dSDimitry Andric break; 611*bdd1243dSDimitry Andric case AsmToken::Percent: 612*bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 613*bdd1243dSDimitry Andric } 61481ad6265SDimitry Andric 61581ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 61681ad6265SDimitry Andric return MatchOperand_Success; 61781ad6265SDimitry Andric } 61881ad6265SDimitry Andric 619*bdd1243dSDimitry Andric OperandMatchResultTy 620*bdd1243dSDimitry Andric LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) { 621*bdd1243dSDimitry Andric SMLoc S = getLoc(); 622*bdd1243dSDimitry Andric SMLoc E; 623*bdd1243dSDimitry Andric 624*bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::Percent) { 625*bdd1243dSDimitry Andric Error(getLoc(), "expected '%' for operand modifier"); 626*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 627*bdd1243dSDimitry Andric } 628*bdd1243dSDimitry Andric 629*bdd1243dSDimitry Andric getParser().Lex(); // Eat '%' 630*bdd1243dSDimitry Andric 631*bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) { 632*bdd1243dSDimitry Andric Error(getLoc(), "expected valid identifier for operand modifier"); 633*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 634*bdd1243dSDimitry Andric } 635*bdd1243dSDimitry Andric StringRef Identifier = getParser().getTok().getIdentifier(); 636*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = 637*bdd1243dSDimitry Andric LoongArchMCExpr::getVariantKindForName(Identifier); 638*bdd1243dSDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_Invalid) { 639*bdd1243dSDimitry Andric Error(getLoc(), "unrecognized operand modifier"); 640*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 641*bdd1243dSDimitry Andric } 642*bdd1243dSDimitry Andric 643*bdd1243dSDimitry Andric getParser().Lex(); // Eat the identifier 644*bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::LParen) { 645*bdd1243dSDimitry Andric Error(getLoc(), "expected '('"); 646*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 647*bdd1243dSDimitry Andric } 648*bdd1243dSDimitry Andric getParser().Lex(); // Eat '(' 649*bdd1243dSDimitry Andric 650*bdd1243dSDimitry Andric const MCExpr *SubExpr; 651*bdd1243dSDimitry Andric if (getParser().parseParenExpression(SubExpr, E)) { 652*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 653*bdd1243dSDimitry Andric } 654*bdd1243dSDimitry Andric 655*bdd1243dSDimitry Andric const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext()); 656*bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E)); 657*bdd1243dSDimitry Andric return MatchOperand_Success; 658*bdd1243dSDimitry Andric } 659*bdd1243dSDimitry Andric 660*bdd1243dSDimitry Andric OperandMatchResultTy 661*bdd1243dSDimitry Andric LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) { 662*bdd1243dSDimitry Andric SMLoc S = getLoc(); 663*bdd1243dSDimitry Andric const MCExpr *Res; 664*bdd1243dSDimitry Andric 665*bdd1243dSDimitry Andric if (getLexer().getKind() == AsmToken::Percent) 666*bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 667*bdd1243dSDimitry Andric 668*bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 669*bdd1243dSDimitry Andric return MatchOperand_NoMatch; 670*bdd1243dSDimitry Andric 671*bdd1243dSDimitry Andric StringRef Identifier; 672*bdd1243dSDimitry Andric if (getParser().parseIdentifier(Identifier)) 673*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 674*bdd1243dSDimitry Andric 675*bdd1243dSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 676*bdd1243dSDimitry Andric 677*bdd1243dSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 678*bdd1243dSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 679*bdd1243dSDimitry Andric Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL, 680*bdd1243dSDimitry Andric getContext()); 681*bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 682*bdd1243dSDimitry Andric return MatchOperand_Success; 683*bdd1243dSDimitry Andric } 684*bdd1243dSDimitry Andric 685*bdd1243dSDimitry Andric OperandMatchResultTy 686*bdd1243dSDimitry Andric LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) { 687*bdd1243dSDimitry Andric // Parse "$r*". 688*bdd1243dSDimitry Andric if (parseRegister(Operands) != MatchOperand_Success) 689*bdd1243dSDimitry Andric return MatchOperand_NoMatch; 690*bdd1243dSDimitry Andric 691*bdd1243dSDimitry Andric // If there is a next operand and it is 0, ignore it. Otherwise print a 692*bdd1243dSDimitry Andric // diagnostic message. 693*bdd1243dSDimitry Andric if (getLexer().is(AsmToken::Comma)) { 694*bdd1243dSDimitry Andric getLexer().Lex(); // Consume comma token. 695*bdd1243dSDimitry Andric int64_t ImmVal; 696*bdd1243dSDimitry Andric SMLoc ImmStart = getLoc(); 697*bdd1243dSDimitry Andric if (getParser().parseIntToken(ImmVal, "expected optional integer offset")) 698*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 699*bdd1243dSDimitry Andric if (ImmVal) { 700*bdd1243dSDimitry Andric Error(ImmStart, "optional integer offset must be 0"); 701*bdd1243dSDimitry Andric return MatchOperand_ParseFail; 702*bdd1243dSDimitry Andric } 703*bdd1243dSDimitry Andric } 704*bdd1243dSDimitry Andric 705*bdd1243dSDimitry Andric return MatchOperand_Success; 706*bdd1243dSDimitry Andric } 70781ad6265SDimitry Andric /// Looks at a token type and creates the relevant operand from this 70881ad6265SDimitry Andric /// information, adding to Operands. Return true upon an error. 70981ad6265SDimitry Andric bool LoongArchAsmParser::parseOperand(OperandVector &Operands, 71081ad6265SDimitry Andric StringRef Mnemonic) { 711*bdd1243dSDimitry Andric // Check if the current operand has a custom associated parser, if so, try to 712*bdd1243dSDimitry Andric // custom parse the operand, or fallback to the general approach. 713*bdd1243dSDimitry Andric OperandMatchResultTy Result = 714*bdd1243dSDimitry Andric MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 715*bdd1243dSDimitry Andric if (Result == MatchOperand_Success) 716*bdd1243dSDimitry Andric return false; 717*bdd1243dSDimitry Andric if (Result == MatchOperand_ParseFail) 718*bdd1243dSDimitry Andric return true; 719*bdd1243dSDimitry Andric 72081ad6265SDimitry Andric if (parseRegister(Operands) == MatchOperand_Success || 72181ad6265SDimitry Andric parseImmediate(Operands) == MatchOperand_Success) 72281ad6265SDimitry Andric return false; 72381ad6265SDimitry Andric 72481ad6265SDimitry Andric // Finally we have exhausted all options and must declare defeat. 72581ad6265SDimitry Andric Error(getLoc(), "unknown operand"); 72681ad6265SDimitry Andric return true; 72781ad6265SDimitry Andric } 72881ad6265SDimitry Andric 72981ad6265SDimitry Andric bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, 73081ad6265SDimitry Andric StringRef Name, SMLoc NameLoc, 73181ad6265SDimitry Andric OperandVector &Operands) { 73281ad6265SDimitry Andric // First operand in MCInst is instruction mnemonic. 73381ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); 73481ad6265SDimitry Andric 73581ad6265SDimitry Andric // If there are no more operands, then finish. 73681ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 73781ad6265SDimitry Andric return false; 73881ad6265SDimitry Andric 73981ad6265SDimitry Andric // Parse first operand. 74081ad6265SDimitry Andric if (parseOperand(Operands, Name)) 74181ad6265SDimitry Andric return true; 74281ad6265SDimitry Andric 74381ad6265SDimitry Andric // Parse until end of statement, consuming commas between operands. 74481ad6265SDimitry Andric while (parseOptionalToken(AsmToken::Comma)) 74581ad6265SDimitry Andric if (parseOperand(Operands, Name)) 74681ad6265SDimitry Andric return true; 74781ad6265SDimitry Andric 74881ad6265SDimitry Andric // Parse end of statement and return successfully. 74981ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 75081ad6265SDimitry Andric return false; 75181ad6265SDimitry Andric 75281ad6265SDimitry Andric SMLoc Loc = getLexer().getLoc(); 75381ad6265SDimitry Andric getParser().eatToEndOfStatement(); 75481ad6265SDimitry Andric return Error(Loc, "unexpected token"); 75581ad6265SDimitry Andric } 75681ad6265SDimitry Andric 757*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 758*bdd1243dSDimitry Andric const MCExpr *Symbol, 759*bdd1243dSDimitry Andric SmallVectorImpl<Inst> &Insts, 760*bdd1243dSDimitry Andric SMLoc IDLoc, MCStreamer &Out) { 761*bdd1243dSDimitry Andric MCContext &Ctx = getContext(); 762*bdd1243dSDimitry Andric for (LoongArchAsmParser::Inst &Inst : Insts) { 763*bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 764*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = Inst.VK; 765*bdd1243dSDimitry Andric const LoongArchMCExpr *LE = LoongArchMCExpr::create(Symbol, VK, Ctx); 766*bdd1243dSDimitry Andric switch (Opc) { 767*bdd1243dSDimitry Andric default: 768*bdd1243dSDimitry Andric llvm_unreachable("unexpected opcode"); 769*bdd1243dSDimitry Andric case LoongArch::PCALAU12I: 770*bdd1243dSDimitry Andric case LoongArch::LU12I_W: 771*bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE), 772*bdd1243dSDimitry Andric getSTI()); 773*bdd1243dSDimitry Andric break; 774*bdd1243dSDimitry Andric case LoongArch::ORI: 775*bdd1243dSDimitry Andric case LoongArch::ADDI_W: 776*bdd1243dSDimitry Andric case LoongArch::LD_W: 777*bdd1243dSDimitry Andric case LoongArch::LD_D: { 778*bdd1243dSDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_None) { 779*bdd1243dSDimitry Andric Out.emitInstruction( 780*bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0), 781*bdd1243dSDimitry Andric getSTI()); 782*bdd1243dSDimitry Andric continue; 783*bdd1243dSDimitry Andric } 784*bdd1243dSDimitry Andric Out.emitInstruction( 785*bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE), 786*bdd1243dSDimitry Andric getSTI()); 787*bdd1243dSDimitry Andric break; 788*bdd1243dSDimitry Andric } 789*bdd1243dSDimitry Andric case LoongArch::LU32I_D: 790*bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc) 791*bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 792*bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 793*bdd1243dSDimitry Andric .addExpr(LE), 794*bdd1243dSDimitry Andric getSTI()); 795*bdd1243dSDimitry Andric break; 796*bdd1243dSDimitry Andric case LoongArch::LU52I_D: 797*bdd1243dSDimitry Andric Out.emitInstruction( 798*bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE), 799*bdd1243dSDimitry Andric getSTI()); 800*bdd1243dSDimitry Andric break; 801*bdd1243dSDimitry Andric case LoongArch::ADDI_D: 802*bdd1243dSDimitry Andric Out.emitInstruction( 803*bdd1243dSDimitry Andric MCInstBuilder(Opc) 804*bdd1243dSDimitry Andric .addReg(TmpReg) 805*bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0) 806*bdd1243dSDimitry Andric .addExpr(LE), 807*bdd1243dSDimitry Andric getSTI()); 808*bdd1243dSDimitry Andric break; 809*bdd1243dSDimitry Andric case LoongArch::ADD_D: 810*bdd1243dSDimitry Andric case LoongArch::LDX_D: 811*bdd1243dSDimitry Andric Out.emitInstruction( 812*bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg), 813*bdd1243dSDimitry Andric getSTI()); 814*bdd1243dSDimitry Andric break; 815*bdd1243dSDimitry Andric } 816*bdd1243dSDimitry Andric } 817*bdd1243dSDimitry Andric } 818*bdd1243dSDimitry Andric 819*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, 820*bdd1243dSDimitry Andric MCStreamer &Out) { 821*bdd1243dSDimitry Andric // la.abs $rd, sym 822*bdd1243dSDimitry Andric // expands to: 823*bdd1243dSDimitry Andric // lu12i.w $rd, %abs_hi20(sym) 824*bdd1243dSDimitry Andric // ori $rd, $rd, %abs_lo12(sym) 825*bdd1243dSDimitry Andric // 826*bdd1243dSDimitry Andric // for 64bit appends: 827*bdd1243dSDimitry Andric // lu32i.d $rd, %abs64_lo20(sym) 828*bdd1243dSDimitry Andric // lu52i.d $rd, $rd, %abs64_hi12(sym) 829*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 830*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS 831*bdd1243dSDimitry Andric ? Inst.getOperand(1).getExpr() 832*bdd1243dSDimitry Andric : Inst.getOperand(2).getExpr(); 833*bdd1243dSDimitry Andric InstSeq Insts; 834*bdd1243dSDimitry Andric 835*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 836*bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20)); 837*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 838*bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12)); 839*bdd1243dSDimitry Andric 840*bdd1243dSDimitry Andric if (is64Bit()) { 841*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 842*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20)); 843*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 844*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12)); 845*bdd1243dSDimitry Andric } 846*bdd1243dSDimitry Andric 847*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 848*bdd1243dSDimitry Andric } 849*bdd1243dSDimitry Andric 850*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, 851*bdd1243dSDimitry Andric MCStreamer &Out) { 852*bdd1243dSDimitry Andric // la.pcrel $rd, sym 853*bdd1243dSDimitry Andric // expands to: 854*bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 855*bdd1243dSDimitry Andric // addi.w/d $rd, rd, %pc_lo12(sym) 856*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 857*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 858*bdd1243dSDimitry Andric InstSeq Insts; 859*bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 860*bdd1243dSDimitry Andric 861*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 862*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 863*bdd1243dSDimitry Andric Insts.push_back( 864*bdd1243dSDimitry Andric LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 865*bdd1243dSDimitry Andric 866*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 867*bdd1243dSDimitry Andric } 868*bdd1243dSDimitry Andric 869*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, 870*bdd1243dSDimitry Andric MCStreamer &Out) { 871*bdd1243dSDimitry Andric // la.pcrel $rd, $rj, sym 872*bdd1243dSDimitry Andric // expands to: 873*bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 874*bdd1243dSDimitry Andric // addi.d $rj, $r0, %pc_lo12(sym) 875*bdd1243dSDimitry Andric // lu32i.d $rj, %pc64_lo20(sym) 876*bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %pc64_hi12(sym) 877*bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 878*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 879*bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 880*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 881*bdd1243dSDimitry Andric InstSeq Insts; 882*bdd1243dSDimitry Andric 883*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 884*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 885*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 886*bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 887*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 888*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20)); 889*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 890*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12)); 891*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 892*bdd1243dSDimitry Andric 893*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 894*bdd1243dSDimitry Andric } 895*bdd1243dSDimitry Andric 896*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, 897*bdd1243dSDimitry Andric MCStreamer &Out) { 898*bdd1243dSDimitry Andric // la.got $rd, sym 899*bdd1243dSDimitry Andric // expands to: 900*bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 901*bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %got_pc_lo12(sym) 902*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 903*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 904*bdd1243dSDimitry Andric InstSeq Insts; 905*bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 906*bdd1243dSDimitry Andric 907*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 908*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 909*bdd1243dSDimitry Andric Insts.push_back( 910*bdd1243dSDimitry Andric LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 911*bdd1243dSDimitry Andric 912*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 913*bdd1243dSDimitry Andric } 914*bdd1243dSDimitry Andric 915*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, 916*bdd1243dSDimitry Andric MCStreamer &Out) { 917*bdd1243dSDimitry Andric // la.got $rd, $rj, sym 918*bdd1243dSDimitry Andric // expands to: 919*bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 920*bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 921*bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 922*bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 923*bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 924*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 925*bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 926*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 927*bdd1243dSDimitry Andric InstSeq Insts; 928*bdd1243dSDimitry Andric 929*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 930*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 931*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 932*bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 933*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 934*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 935*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 936*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 937*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 938*bdd1243dSDimitry Andric 939*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 940*bdd1243dSDimitry Andric } 941*bdd1243dSDimitry Andric 942*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, 943*bdd1243dSDimitry Andric MCStreamer &Out) { 944*bdd1243dSDimitry Andric // la.tls.le $rd, sym 945*bdd1243dSDimitry Andric // expands to: 946*bdd1243dSDimitry Andric // lu12i.w $rd, %le_hi20(sym) 947*bdd1243dSDimitry Andric // ori $rd, $rd, %le_lo12(sym) 948*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 949*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 950*bdd1243dSDimitry Andric InstSeq Insts; 951*bdd1243dSDimitry Andric 952*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 953*bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20)); 954*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 955*bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12)); 956*bdd1243dSDimitry Andric 957*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 958*bdd1243dSDimitry Andric } 959*bdd1243dSDimitry Andric 960*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, 961*bdd1243dSDimitry Andric MCStreamer &Out) { 962*bdd1243dSDimitry Andric // la.tls.ie $rd, sym 963*bdd1243dSDimitry Andric // expands to: 964*bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 965*bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 966*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 967*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 968*bdd1243dSDimitry Andric InstSeq Insts; 969*bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 970*bdd1243dSDimitry Andric 971*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 972*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 973*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 974*bdd1243dSDimitry Andric LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 975*bdd1243dSDimitry Andric 976*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 977*bdd1243dSDimitry Andric } 978*bdd1243dSDimitry Andric 979*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, 980*bdd1243dSDimitry Andric MCStreamer &Out) { 981*bdd1243dSDimitry Andric // la.tls.ie $rd, $rj, sym 982*bdd1243dSDimitry Andric // expands to: 983*bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 984*bdd1243dSDimitry Andric // addi.d $rj, $r0, %ie_pc_lo12(sym) 985*bdd1243dSDimitry Andric // lu32i.d $rj, %ie64_pc_lo20(sym) 986*bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %ie64_pc_hi12(sym) 987*bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 988*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 989*bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 990*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 991*bdd1243dSDimitry Andric InstSeq Insts; 992*bdd1243dSDimitry Andric 993*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 994*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 995*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 996*bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 997*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 998*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20)); 999*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1000*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12)); 1001*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 1002*bdd1243dSDimitry Andric 1003*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1004*bdd1243dSDimitry Andric } 1005*bdd1243dSDimitry Andric 1006*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, 1007*bdd1243dSDimitry Andric MCStreamer &Out) { 1008*bdd1243dSDimitry Andric // la.tls.ld $rd, sym 1009*bdd1243dSDimitry Andric // expands to: 1010*bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1011*bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1012*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1013*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1014*bdd1243dSDimitry Andric InstSeq Insts; 1015*bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1016*bdd1243dSDimitry Andric 1017*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1018*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1019*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1020*bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1021*bdd1243dSDimitry Andric 1022*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1023*bdd1243dSDimitry Andric } 1024*bdd1243dSDimitry Andric 1025*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, 1026*bdd1243dSDimitry Andric MCStreamer &Out) { 1027*bdd1243dSDimitry Andric // la.tls.ld $rd, $rj, sym 1028*bdd1243dSDimitry Andric // expands to: 1029*bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1030*bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1031*bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1032*bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1033*bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1034*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1035*bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1036*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1037*bdd1243dSDimitry Andric InstSeq Insts; 1038*bdd1243dSDimitry Andric 1039*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1040*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1041*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1042*bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1043*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1044*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1045*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1046*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1047*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1048*bdd1243dSDimitry Andric 1049*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1050*bdd1243dSDimitry Andric } 1051*bdd1243dSDimitry Andric 1052*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, 1053*bdd1243dSDimitry Andric MCStreamer &Out) { 1054*bdd1243dSDimitry Andric // la.tls.gd $rd, sym 1055*bdd1243dSDimitry Andric // expands to: 1056*bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1057*bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1058*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1059*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1060*bdd1243dSDimitry Andric InstSeq Insts; 1061*bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1062*bdd1243dSDimitry Andric 1063*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1064*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1065*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1066*bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1067*bdd1243dSDimitry Andric 1068*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1069*bdd1243dSDimitry Andric } 1070*bdd1243dSDimitry Andric 1071*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, 1072*bdd1243dSDimitry Andric MCStreamer &Out) { 1073*bdd1243dSDimitry Andric // la.tls.gd $rd, $rj, sym 1074*bdd1243dSDimitry Andric // expands to: 1075*bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1076*bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1077*bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1078*bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1079*bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1080*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1081*bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1082*bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1083*bdd1243dSDimitry Andric InstSeq Insts; 1084*bdd1243dSDimitry Andric 1085*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1086*bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1087*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1088*bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1089*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1090*bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1091*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1092*bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1093*bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1094*bdd1243dSDimitry Andric 1095*bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1096*bdd1243dSDimitry Andric } 1097*bdd1243dSDimitry Andric 1098*bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, 1099*bdd1243dSDimitry Andric MCStreamer &Out) { 1100*bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1101*bdd1243dSDimitry Andric int64_t Imm = Inst.getOperand(1).getImm(); 1102*bdd1243dSDimitry Andric MCRegister SrcReg = LoongArch::R0; 1103*bdd1243dSDimitry Andric 1104*bdd1243dSDimitry Andric if (Inst.getOpcode() == LoongArch::PseudoLI_W) 1105*bdd1243dSDimitry Andric Imm = SignExtend64<32>(Imm); 1106*bdd1243dSDimitry Andric 1107*bdd1243dSDimitry Andric for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 1108*bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 1109*bdd1243dSDimitry Andric if (Opc == LoongArch::LU12I_W) 1110*bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm), 1111*bdd1243dSDimitry Andric getSTI()); 1112*bdd1243dSDimitry Andric else 1113*bdd1243dSDimitry Andric Out.emitInstruction( 1114*bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm), 1115*bdd1243dSDimitry Andric getSTI()); 1116*bdd1243dSDimitry Andric SrcReg = DestReg; 1117*bdd1243dSDimitry Andric } 1118*bdd1243dSDimitry Andric } 1119*bdd1243dSDimitry Andric 112081ad6265SDimitry Andric bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 112181ad6265SDimitry Andric OperandVector &Operands, 112281ad6265SDimitry Andric MCStreamer &Out) { 112381ad6265SDimitry Andric Inst.setLoc(IDLoc); 1124*bdd1243dSDimitry Andric switch (Inst.getOpcode()) { 1125*bdd1243dSDimitry Andric default: 1126*bdd1243dSDimitry Andric break; 1127*bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS: 1128*bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS_LARGE: 1129*bdd1243dSDimitry Andric emitLoadAddressAbs(Inst, IDLoc, Out); 1130*bdd1243dSDimitry Andric return false; 1131*bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL: 1132*bdd1243dSDimitry Andric emitLoadAddressPcrel(Inst, IDLoc, Out); 1133*bdd1243dSDimitry Andric return false; 1134*bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1135*bdd1243dSDimitry Andric emitLoadAddressPcrelLarge(Inst, IDLoc, Out); 1136*bdd1243dSDimitry Andric return false; 1137*bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT: 1138*bdd1243dSDimitry Andric emitLoadAddressGot(Inst, IDLoc, Out); 1139*bdd1243dSDimitry Andric return false; 1140*bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1141*bdd1243dSDimitry Andric emitLoadAddressGotLarge(Inst, IDLoc, Out); 1142*bdd1243dSDimitry Andric return false; 1143*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LE: 1144*bdd1243dSDimitry Andric emitLoadAddressTLSLE(Inst, IDLoc, Out); 1145*bdd1243dSDimitry Andric return false; 1146*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE: 1147*bdd1243dSDimitry Andric emitLoadAddressTLSIE(Inst, IDLoc, Out); 1148*bdd1243dSDimitry Andric return false; 1149*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1150*bdd1243dSDimitry Andric emitLoadAddressTLSIELarge(Inst, IDLoc, Out); 1151*bdd1243dSDimitry Andric return false; 1152*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD: 1153*bdd1243dSDimitry Andric emitLoadAddressTLSLD(Inst, IDLoc, Out); 1154*bdd1243dSDimitry Andric return false; 1155*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1156*bdd1243dSDimitry Andric emitLoadAddressTLSLDLarge(Inst, IDLoc, Out); 1157*bdd1243dSDimitry Andric return false; 1158*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD: 1159*bdd1243dSDimitry Andric emitLoadAddressTLSGD(Inst, IDLoc, Out); 1160*bdd1243dSDimitry Andric return false; 1161*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: 1162*bdd1243dSDimitry Andric emitLoadAddressTLSGDLarge(Inst, IDLoc, Out); 1163*bdd1243dSDimitry Andric return false; 1164*bdd1243dSDimitry Andric case LoongArch::PseudoLI_W: 1165*bdd1243dSDimitry Andric case LoongArch::PseudoLI_D: 1166*bdd1243dSDimitry Andric emitLoadImm(Inst, IDLoc, Out); 1167*bdd1243dSDimitry Andric return false; 1168*bdd1243dSDimitry Andric } 116981ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 117081ad6265SDimitry Andric return false; 117181ad6265SDimitry Andric } 117281ad6265SDimitry Andric 117381ad6265SDimitry Andric unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1174*bdd1243dSDimitry Andric unsigned Opc = Inst.getOpcode(); 1175*bdd1243dSDimitry Andric switch (Opc) { 117681ad6265SDimitry Andric default: 1177*bdd1243dSDimitry Andric if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { 1178*bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1179*bdd1243dSDimitry Andric unsigned Rk = Inst.getOperand(1).getReg(); 1180*bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 1181*bdd1243dSDimitry Andric if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0) 1182*bdd1243dSDimitry Andric return Match_RequiresAMORdDifferRkRj; 1183*bdd1243dSDimitry Andric } 118481ad6265SDimitry Andric break; 1185*bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1186*bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1187*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1188*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1189*bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: { 1190*bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1191*bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(1).getReg(); 1192*bdd1243dSDimitry Andric if (Rd == Rj) 1193*bdd1243dSDimitry Andric return Match_RequiresLAORdDifferRj; 1194*bdd1243dSDimitry Andric break; 1195*bdd1243dSDimitry Andric } 119681ad6265SDimitry Andric case LoongArch::CSRXCHG: { 119781ad6265SDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 119881ad6265SDimitry Andric if (Rj == LoongArch::R0 || Rj == LoongArch::R1) 119981ad6265SDimitry Andric return Match_RequiresOpnd2NotR0R1; 120081ad6265SDimitry Andric return Match_Success; 120181ad6265SDimitry Andric } 120281ad6265SDimitry Andric case LoongArch::BSTRINS_W: 120381ad6265SDimitry Andric case LoongArch::BSTRINS_D: 120481ad6265SDimitry Andric case LoongArch::BSTRPICK_W: 120581ad6265SDimitry Andric case LoongArch::BSTRPICK_D: { 120681ad6265SDimitry Andric unsigned Opc = Inst.getOpcode(); 120781ad6265SDimitry Andric const signed Msb = 120881ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 120981ad6265SDimitry Andric ? Inst.getOperand(3).getImm() 121081ad6265SDimitry Andric : Inst.getOperand(2).getImm(); 121181ad6265SDimitry Andric const signed Lsb = 121281ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 121381ad6265SDimitry Andric ? Inst.getOperand(4).getImm() 121481ad6265SDimitry Andric : Inst.getOperand(3).getImm(); 121581ad6265SDimitry Andric if (Msb < Lsb) 121681ad6265SDimitry Andric return Match_RequiresMsbNotLessThanLsb; 121781ad6265SDimitry Andric return Match_Success; 121881ad6265SDimitry Andric } 121981ad6265SDimitry Andric } 122081ad6265SDimitry Andric 122181ad6265SDimitry Andric return Match_Success; 122281ad6265SDimitry Andric } 122381ad6265SDimitry Andric 122481ad6265SDimitry Andric unsigned 122581ad6265SDimitry Andric LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 122681ad6265SDimitry Andric unsigned Kind) { 122781ad6265SDimitry Andric LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp); 122881ad6265SDimitry Andric if (!Op.isReg()) 122981ad6265SDimitry Andric return Match_InvalidOperand; 123081ad6265SDimitry Andric 123181ad6265SDimitry Andric MCRegister Reg = Op.getReg(); 123281ad6265SDimitry Andric // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 123381ad6265SDimitry Andric // register from FPR32 to FPR64 if necessary. 123481ad6265SDimitry Andric if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && 123581ad6265SDimitry Andric Kind == MCK_FPR64) { 123681ad6265SDimitry Andric Op.setReg(convertFPR32ToFPR64(Reg)); 123781ad6265SDimitry Andric return Match_Success; 123881ad6265SDimitry Andric } 123981ad6265SDimitry Andric 124081ad6265SDimitry Andric return Match_InvalidOperand; 124181ad6265SDimitry Andric } 124281ad6265SDimitry Andric 124381ad6265SDimitry Andric bool LoongArchAsmParser::generateImmOutOfRangeError( 124481ad6265SDimitry Andric OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 124581ad6265SDimitry Andric Twine Msg = "immediate must be an integer in the range") { 124681ad6265SDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 124781ad6265SDimitry Andric return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 124881ad6265SDimitry Andric } 124981ad6265SDimitry Andric 125081ad6265SDimitry Andric bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 125181ad6265SDimitry Andric OperandVector &Operands, 125281ad6265SDimitry Andric MCStreamer &Out, 125381ad6265SDimitry Andric uint64_t &ErrorInfo, 125481ad6265SDimitry Andric bool MatchingInlineAsm) { 125581ad6265SDimitry Andric MCInst Inst; 125681ad6265SDimitry Andric FeatureBitset MissingFeatures; 125781ad6265SDimitry Andric 125881ad6265SDimitry Andric auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 125981ad6265SDimitry Andric MatchingInlineAsm); 126081ad6265SDimitry Andric switch (Result) { 126181ad6265SDimitry Andric default: 126281ad6265SDimitry Andric break; 126381ad6265SDimitry Andric case Match_Success: 126481ad6265SDimitry Andric return processInstruction(Inst, IDLoc, Operands, Out); 126581ad6265SDimitry Andric case Match_MissingFeature: { 126681ad6265SDimitry Andric assert(MissingFeatures.any() && "Unknown missing features!"); 126781ad6265SDimitry Andric bool FirstFeature = true; 126881ad6265SDimitry Andric std::string Msg = "instruction requires the following:"; 126981ad6265SDimitry Andric for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 127081ad6265SDimitry Andric if (MissingFeatures[i]) { 127181ad6265SDimitry Andric Msg += FirstFeature ? " " : ", "; 127281ad6265SDimitry Andric Msg += getSubtargetFeatureName(i); 127381ad6265SDimitry Andric FirstFeature = false; 127481ad6265SDimitry Andric } 127581ad6265SDimitry Andric } 127681ad6265SDimitry Andric return Error(IDLoc, Msg); 127781ad6265SDimitry Andric } 127881ad6265SDimitry Andric case Match_MnemonicFail: { 127981ad6265SDimitry Andric FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 128081ad6265SDimitry Andric std::string Suggestion = LoongArchMnemonicSpellCheck( 128181ad6265SDimitry Andric ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); 128281ad6265SDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 128381ad6265SDimitry Andric } 128481ad6265SDimitry Andric case Match_InvalidOperand: { 128581ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 128681ad6265SDimitry Andric if (ErrorInfo != ~0ULL) { 128781ad6265SDimitry Andric if (ErrorInfo >= Operands.size()) 128881ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 128981ad6265SDimitry Andric 129081ad6265SDimitry Andric ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 129181ad6265SDimitry Andric if (ErrorLoc == SMLoc()) 129281ad6265SDimitry Andric ErrorLoc = IDLoc; 129381ad6265SDimitry Andric } 129481ad6265SDimitry Andric return Error(ErrorLoc, "invalid operand for instruction"); 129581ad6265SDimitry Andric } 129681ad6265SDimitry Andric } 129781ad6265SDimitry Andric 129881ad6265SDimitry Andric // Handle the case when the error message is of specific type 129981ad6265SDimitry Andric // other than the generic Match_InvalidOperand, and the 130081ad6265SDimitry Andric // corresponding operand is missing. 130181ad6265SDimitry Andric if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 130281ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 130381ad6265SDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 130481ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 130581ad6265SDimitry Andric } 130681ad6265SDimitry Andric 130781ad6265SDimitry Andric switch (Result) { 130881ad6265SDimitry Andric default: 130981ad6265SDimitry Andric break; 131081ad6265SDimitry Andric case Match_RequiresMsbNotLessThanLsb: { 131181ad6265SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc(); 131281ad6265SDimitry Andric return Error(ErrorStart, "msb is less than lsb", 131381ad6265SDimitry Andric SMRange(ErrorStart, Operands[4]->getEndLoc())); 131481ad6265SDimitry Andric } 131581ad6265SDimitry Andric case Match_RequiresOpnd2NotR0R1: 131681ad6265SDimitry Andric return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); 1317*bdd1243dSDimitry Andric case Match_RequiresAMORdDifferRkRj: 1318*bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), 1319*bdd1243dSDimitry Andric "$rd must be different from both $rk and $rj"); 1320*bdd1243dSDimitry Andric case Match_RequiresLAORdDifferRj: 1321*bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj"); 132281ad6265SDimitry Andric case Match_InvalidUImm2: 132381ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 132481ad6265SDimitry Andric /*Upper=*/(1 << 2) - 1); 132581ad6265SDimitry Andric case Match_InvalidUImm2plus1: 132681ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, 132781ad6265SDimitry Andric /*Upper=*/(1 << 2)); 132881ad6265SDimitry Andric case Match_InvalidUImm3: 132981ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 133081ad6265SDimitry Andric /*Upper=*/(1 << 3) - 1); 133181ad6265SDimitry Andric case Match_InvalidUImm5: 133281ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 133381ad6265SDimitry Andric /*Upper=*/(1 << 5) - 1); 133481ad6265SDimitry Andric case Match_InvalidUImm6: 133581ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 133681ad6265SDimitry Andric /*Upper=*/(1 << 6) - 1); 133781ad6265SDimitry Andric case Match_InvalidUImm12: 133881ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 133981ad6265SDimitry Andric /*Upper=*/(1 << 12) - 1); 1340*bdd1243dSDimitry Andric case Match_InvalidUImm12ori: 1341*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1342*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/0, 1343*bdd1243dSDimitry Andric /*Upper=*/(1 << 12) - 1, 1344*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_lo12) or an " 1345*bdd1243dSDimitry Andric "integer in the range"); 134681ad6265SDimitry Andric case Match_InvalidUImm15: 134781ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 134881ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 134981ad6265SDimitry Andric case Match_InvalidSImm12: 135081ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), 135181ad6265SDimitry Andric /*Upper=*/(1 << 11) - 1); 1352*bdd1243dSDimitry Andric case Match_InvalidSImm12addlike: 1353*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1354*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1355*bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1356*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer " 1357*bdd1243dSDimitry Andric "in the range"); 1358*bdd1243dSDimitry Andric case Match_InvalidSImm12lu52id: 1359*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1360*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1361*bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1362*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc64_hi12) or an " 1363*bdd1243dSDimitry Andric "integer in the range"); 136481ad6265SDimitry Andric case Match_InvalidSImm14lsl2: 136581ad6265SDimitry Andric return generateImmOutOfRangeError( 136681ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, 136781ad6265SDimitry Andric "immediate must be a multiple of 4 in the range"); 136881ad6265SDimitry Andric case Match_InvalidSImm16: 136981ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), 137081ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 137181ad6265SDimitry Andric case Match_InvalidSImm16lsl2: 137281ad6265SDimitry Andric return generateImmOutOfRangeError( 137381ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, 1374*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b16) or an integer " 1375*bdd1243dSDimitry Andric "in the range"); 137681ad6265SDimitry Andric case Match_InvalidSImm20: 137781ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), 137881ad6265SDimitry Andric /*Upper=*/(1 << 19) - 1); 1379*bdd1243dSDimitry Andric case Match_InvalidSImm20lu12iw: 1380*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1381*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1382*bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1383*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer " 1384*bdd1243dSDimitry Andric "in the range"); 1385*bdd1243dSDimitry Andric case Match_InvalidSImm20lu32id: 1386*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1387*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1388*bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1389*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs64_lo20) or an " 1390*bdd1243dSDimitry Andric "integer in the range"); 1391*bdd1243dSDimitry Andric case Match_InvalidSImm20pcalau12i: 1392*bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1393*bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1394*bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1395*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " 1396*bdd1243dSDimitry Andric "in the range"); 139781ad6265SDimitry Andric case Match_InvalidSImm21lsl2: 139881ad6265SDimitry Andric return generateImmOutOfRangeError( 139981ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, 1400*bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b21) or an integer " 1401*bdd1243dSDimitry Andric "in the range"); 1402*bdd1243dSDimitry Andric case Match_InvalidSImm26Operand: 140381ad6265SDimitry Andric return generateImmOutOfRangeError( 140481ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, 1405*bdd1243dSDimitry Andric "operand must be a bare symbol name or an immediate must be a multiple " 1406*bdd1243dSDimitry Andric "of 4 in the range"); 1407*bdd1243dSDimitry Andric case Match_InvalidImm32: { 1408*bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1409*bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a 32 bit immediate"); 1410*bdd1243dSDimitry Andric } 1411*bdd1243dSDimitry Andric case Match_InvalidBareSymbol: { 1412*bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1413*bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a bare symbol name"); 1414*bdd1243dSDimitry Andric } 141581ad6265SDimitry Andric } 141681ad6265SDimitry Andric llvm_unreachable("Unknown match type detected!"); 141781ad6265SDimitry Andric } 141881ad6265SDimitry Andric 141981ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { 142081ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target()); 142181ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target()); 142281ad6265SDimitry Andric } 1423