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