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/LoongArchInstPrinter.h" 10 #include "MCTargetDesc/LoongArchMCExpr.h" 11 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 12 #include "MCTargetDesc/LoongArchMatInt.h" 13 #include "TargetInfo/LoongArchTargetInfo.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCInstBuilder.h" 16 #include "llvm/MC/MCInstrInfo.h" 17 #include "llvm/MC/MCParser/MCAsmLexer.h" 18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 19 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/MC/MCStreamer.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/MCValue.h" 24 #include "llvm/MC/TargetRegistry.h" 25 #include "llvm/Support/Casting.h" 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "loongarch-asm-parser" 30 31 namespace { 32 class LoongArchAsmParser : public MCTargetAsmParser { 33 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 34 bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); } 35 36 struct Inst { 37 unsigned Opc; 38 LoongArchMCExpr::VariantKind VK; 39 Inst(unsigned Opc, 40 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None) 41 : Opc(Opc), VK(VK) {} 42 }; 43 using InstSeq = SmallVector<Inst>; 44 45 /// Parse a register as used in CFI directives. 46 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 47 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 48 SMLoc &EndLoc) override; 49 50 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 51 SMLoc NameLoc, OperandVector &Operands) override; 52 53 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 54 OperandVector &Operands, MCStreamer &Out, 55 uint64_t &ErrorInfo, 56 bool MatchingInlineAsm) override; 57 58 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 59 60 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 61 unsigned Kind) override; 62 63 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 64 int64_t Lower, int64_t Upper, 65 const Twine &Msg); 66 67 /// Helper for processing MC instructions that have been successfully matched 68 /// by MatchAndEmitInstruction. 69 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 70 MCStreamer &Out); 71 72 // Auto-generated instruction matching functions. 73 #define GET_ASSEMBLER_HEADER 74 #include "LoongArchGenAsmMatcher.inc" 75 76 ParseStatus parseRegister(OperandVector &Operands); 77 ParseStatus parseImmediate(OperandVector &Operands); 78 ParseStatus parseOperandWithModifier(OperandVector &Operands); 79 ParseStatus parseSImm26Operand(OperandVector &Operands); 80 ParseStatus parseAtomicMemOp(OperandVector &Operands); 81 82 bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 83 84 // Helper to emit the sequence of instructions generated by the 85 // "emitLoadAddress*" functions. 86 void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 87 const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts, 88 SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false); 89 90 // Helper to emit pseudo instruction "la.abs $rd, sym". 91 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 92 93 // Helper to emit pseudo instruction "la.pcrel $rd, sym". 94 void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 95 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym". 96 void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 97 98 // Helper to emit pseudo instruction "la.got $rd, sym". 99 void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 100 // Helper to emit pseudo instruction "la.got $rd, $rj, sym". 101 void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 102 103 // Helper to emit pseudo instruction "la.tls.le $rd, sym". 104 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 105 106 // Helper to emit pseudo instruction "la.tls.ie $rd, sym". 107 void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 108 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym". 109 void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 110 111 // Helper to emit pseudo instruction "la.tls.ld $rd, sym". 112 void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 113 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym". 114 void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 115 116 // Helper to emit pseudo instruction "la.tls.gd $rd, sym". 117 void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 118 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym". 119 void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 120 121 // Helper to emit pseudo instruction "li.w/d $rd, $imm". 122 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 123 124 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym". 125 void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 126 bool IsTailCall); 127 128 public: 129 enum LoongArchMatchResultTy { 130 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 131 Match_RequiresMsbNotLessThanLsb, 132 Match_RequiresOpnd2NotR0R1, 133 Match_RequiresAMORdDifferRkRj, 134 Match_RequiresLAORdDifferRj, 135 #define GET_OPERAND_DIAGNOSTIC_TYPES 136 #include "LoongArchGenAsmMatcher.inc" 137 #undef GET_OPERAND_DIAGNOSTIC_TYPES 138 }; 139 140 static bool classifySymbolRef(const MCExpr *Expr, 141 LoongArchMCExpr::VariantKind &Kind); 142 143 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 144 const MCInstrInfo &MII, const MCTargetOptions &Options) 145 : MCTargetAsmParser(Options, STI, MII) { 146 Parser.addAliasForDirective(".half", ".2byte"); 147 Parser.addAliasForDirective(".hword", ".2byte"); 148 Parser.addAliasForDirective(".word", ".4byte"); 149 Parser.addAliasForDirective(".dword", ".8byte"); 150 151 // Initialize the set of available features. 152 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 153 } 154 }; 155 156 // Instances of this class represent a parsed LoongArch machine instruction. 157 class LoongArchOperand : public MCParsedAsmOperand { 158 enum class KindTy { 159 Token, 160 Register, 161 Immediate, 162 } Kind; 163 164 struct RegOp { 165 MCRegister RegNum; 166 }; 167 168 struct ImmOp { 169 const MCExpr *Val; 170 }; 171 172 SMLoc StartLoc, EndLoc; 173 union { 174 StringRef Tok; 175 struct RegOp Reg; 176 struct ImmOp Imm; 177 }; 178 179 public: 180 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 181 182 bool isToken() const override { return Kind == KindTy::Token; } 183 bool isReg() const override { return Kind == KindTy::Register; } 184 bool isImm() const override { return Kind == KindTy::Immediate; } 185 bool isMem() const override { return false; } 186 void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } 187 bool isGPR() const { 188 return Kind == KindTy::Register && 189 LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains( 190 Reg.RegNum); 191 } 192 193 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 194 LoongArchMCExpr::VariantKind &VK) { 195 if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) { 196 VK = LE->getKind(); 197 return false; 198 } 199 200 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 201 Imm = CE->getValue(); 202 return true; 203 } 204 205 return false; 206 } 207 208 template <unsigned N, int P = 0> bool isUImm() const { 209 if (!isImm()) 210 return false; 211 212 int64_t Imm; 213 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 214 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 215 return IsConstantImm && isUInt<N>(Imm - P) && 216 VK == LoongArchMCExpr::VK_LoongArch_None; 217 } 218 219 template <unsigned N, unsigned S = 0> bool isSImm() const { 220 if (!isImm()) 221 return false; 222 223 int64_t Imm; 224 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 225 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 226 return IsConstantImm && isShiftedInt<N, S>(Imm) && 227 VK == LoongArchMCExpr::VK_LoongArch_None; 228 } 229 230 bool isBareSymbol() const { 231 int64_t Imm; 232 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 233 // Must be of 'immediate' type but not a constant. 234 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 235 return false; 236 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 237 VK == LoongArchMCExpr::VK_LoongArch_None; 238 } 239 240 bool isUImm1() const { return isUImm<1>(); } 241 bool isUImm2() const { return isUImm<2>(); } 242 bool isUImm2plus1() const { return isUImm<2, 1>(); } 243 bool isUImm3() const { return isUImm<3>(); } 244 bool isUImm4() const { return isUImm<4>(); } 245 bool isSImm5() const { return isSImm<5>(); } 246 bool isUImm5() const { return isUImm<5>(); } 247 bool isUImm6() const { return isUImm<6>(); } 248 bool isUImm7() const { return isUImm<7>(); } 249 bool isSImm8() const { return isSImm<8>(); } 250 bool isSImm8lsl1() const { return isSImm<8, 1>(); } 251 bool isSImm8lsl2() const { return isSImm<8, 2>(); } 252 bool isSImm8lsl3() const { return isSImm<8, 3>(); } 253 bool isUImm8() const { return isUImm<8>(); } 254 bool isSImm9lsl3() const { return isSImm<9, 3>(); } 255 bool isSImm10() const { return isSImm<10>(); } 256 bool isSImm10lsl2() const { return isSImm<10, 2>(); } 257 bool isSImm11lsl1() const { return isSImm<11, 1>(); } 258 bool isSImm12() const { return isSImm<12>(); } 259 260 bool isSImm12addlike() const { 261 if (!isImm()) 262 return false; 263 264 int64_t Imm; 265 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 266 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 267 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 268 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 269 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 270 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 271 return IsConstantImm 272 ? isInt<12>(Imm) && IsValidKind 273 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 274 IsValidKind; 275 } 276 277 bool isSImm12lu52id() const { 278 if (!isImm()) 279 return false; 280 281 int64_t Imm; 282 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 283 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 284 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 285 VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 || 286 VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 || 287 VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 || 288 VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 || 289 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 || 290 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 || 291 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12; 292 return IsConstantImm 293 ? isInt<12>(Imm) && IsValidKind 294 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 295 IsValidKind; 296 } 297 298 bool isUImm12() const { return isUImm<12>(); } 299 300 bool isUImm12ori() const { 301 if (!isImm()) 302 return false; 303 304 int64_t Imm; 305 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 306 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 307 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 308 VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 || 309 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 310 VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 || 311 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 312 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 || 313 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 || 314 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 315 return IsConstantImm 316 ? isUInt<12>(Imm) && IsValidKind 317 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 318 IsValidKind; 319 } 320 321 bool isSImm13() const { return isSImm<13>(); } 322 bool isUImm14() const { return isUImm<14>(); } 323 bool isUImm15() const { return isUImm<15>(); } 324 325 bool isSImm14lsl2() const { return isSImm<14, 2>(); } 326 bool isSImm16() const { return isSImm<16>(); } 327 328 bool isSImm16lsl2() const { 329 if (!isImm()) 330 return false; 331 332 int64_t Imm; 333 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 334 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 335 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 336 VK == LoongArchMCExpr::VK_LoongArch_B16 || 337 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12; 338 return IsConstantImm 339 ? isShiftedInt<16, 2>(Imm) && IsValidKind 340 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 341 IsValidKind; 342 } 343 344 bool isSImm20() const { return isSImm<20>(); } 345 346 bool isSImm20pcalau12i() const { 347 if (!isImm()) 348 return false; 349 350 int64_t Imm; 351 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 352 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 353 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 354 VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 || 355 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 || 356 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 || 357 VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 || 358 VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 359 return IsConstantImm 360 ? isInt<20>(Imm) && IsValidKind 361 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 362 IsValidKind; 363 } 364 365 bool isSImm20lu12iw() const { 366 if (!isImm()) 367 return false; 368 369 int64_t Imm; 370 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 371 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 372 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 373 VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 || 374 VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 || 375 VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 || 376 VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 || 377 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 || 378 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 379 return IsConstantImm 380 ? isInt<20>(Imm) && IsValidKind 381 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 382 IsValidKind; 383 } 384 385 bool isSImm20lu32id() const { 386 if (!isImm()) 387 return false; 388 389 int64_t Imm; 390 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 391 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 392 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 393 VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 || 394 VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 || 395 VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 || 396 VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 || 397 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 || 398 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 || 399 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20; 400 401 return IsConstantImm 402 ? isInt<20>(Imm) && IsValidKind 403 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 404 IsValidKind; 405 } 406 407 bool isSImm20pcaddu18i() const { 408 if (!isImm()) 409 return false; 410 411 int64_t Imm; 412 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 413 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 414 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 415 VK == LoongArchMCExpr::VK_LoongArch_CALL36; 416 417 return IsConstantImm 418 ? isInt<20>(Imm) && IsValidKind 419 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 420 IsValidKind; 421 } 422 423 bool isSImm21lsl2() const { 424 if (!isImm()) 425 return false; 426 427 int64_t Imm; 428 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 429 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 430 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 431 VK == LoongArchMCExpr::VK_LoongArch_B21; 432 return IsConstantImm 433 ? isShiftedInt<21, 2>(Imm) && IsValidKind 434 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 435 IsValidKind; 436 } 437 438 bool isSImm26Operand() const { 439 if (!isImm()) 440 return false; 441 442 int64_t Imm; 443 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 444 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 445 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 446 VK == LoongArchMCExpr::VK_LoongArch_CALL || 447 VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT || 448 VK == LoongArchMCExpr::VK_LoongArch_B26; 449 return IsConstantImm 450 ? isShiftedInt<26, 2>(Imm) && IsValidKind 451 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 452 IsValidKind; 453 } 454 455 bool isImm32() const { return isSImm<32>() || isUImm<32>(); } 456 457 /// Gets location of the first token of this operand. 458 SMLoc getStartLoc() const override { return StartLoc; } 459 /// Gets location of the last token of this operand. 460 SMLoc getEndLoc() const override { return EndLoc; } 461 462 unsigned getReg() const override { 463 assert(Kind == KindTy::Register && "Invalid type access!"); 464 return Reg.RegNum.id(); 465 } 466 467 const MCExpr *getImm() const { 468 assert(Kind == KindTy::Immediate && "Invalid type access!"); 469 return Imm.Val; 470 } 471 472 StringRef getToken() const { 473 assert(Kind == KindTy::Token && "Invalid type access!"); 474 return Tok; 475 } 476 477 void print(raw_ostream &OS) const override { 478 auto RegName = [](MCRegister Reg) { 479 if (Reg) 480 return LoongArchInstPrinter::getRegisterName(Reg); 481 else 482 return "noreg"; 483 }; 484 485 switch (Kind) { 486 case KindTy::Immediate: 487 OS << *getImm(); 488 break; 489 case KindTy::Register: 490 OS << "<register " << RegName(getReg()) << ">"; 491 break; 492 case KindTy::Token: 493 OS << "'" << getToken() << "'"; 494 break; 495 } 496 } 497 498 static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) { 499 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token); 500 Op->Tok = Str; 501 Op->StartLoc = S; 502 Op->EndLoc = S; 503 return Op; 504 } 505 506 static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S, 507 SMLoc E) { 508 auto Op = std::make_unique<LoongArchOperand>(KindTy::Register); 509 Op->Reg.RegNum = RegNo; 510 Op->StartLoc = S; 511 Op->EndLoc = E; 512 return Op; 513 } 514 515 static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S, 516 SMLoc E) { 517 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate); 518 Op->Imm.Val = Val; 519 Op->StartLoc = S; 520 Op->EndLoc = E; 521 return Op; 522 } 523 524 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 525 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) 526 Inst.addOperand(MCOperand::createImm(CE->getValue())); 527 else 528 Inst.addOperand(MCOperand::createExpr(Expr)); 529 } 530 531 // Used by the TableGen Code. 532 void addRegOperands(MCInst &Inst, unsigned N) const { 533 assert(N == 1 && "Invalid number of operands!"); 534 Inst.addOperand(MCOperand::createReg(getReg())); 535 } 536 void addImmOperands(MCInst &Inst, unsigned N) const { 537 assert(N == 1 && "Invalid number of operands!"); 538 addExpr(Inst, getImm()); 539 } 540 }; 541 } // end namespace 542 543 #define GET_REGISTER_MATCHER 544 #define GET_SUBTARGET_FEATURE_NAME 545 #define GET_MATCHER_IMPLEMENTATION 546 #define GET_MNEMONIC_SPELL_CHECKER 547 #include "LoongArchGenAsmMatcher.inc" 548 549 static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 550 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); 551 return Reg - LoongArch::F0 + LoongArch::F0_64; 552 } 553 554 // Attempts to match Name as a register (either using the default name or 555 // alternative ABI names), setting RegNo to the matching register. Upon 556 // failure, returns true and sets RegNo to 0. 557 static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 558 RegNo = MatchRegisterName(Name); 559 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial 560 // match always matches the 32-bit variant, and not the 64-bit one. 561 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); 562 // The default FPR register class is based on the tablegen enum ordering. 563 static_assert(LoongArch::F0 < LoongArch::F0_64, 564 "FPR matching must be updated"); 565 if (RegNo == LoongArch::NoRegister) 566 RegNo = MatchRegisterAltName(Name); 567 568 return RegNo == LoongArch::NoRegister; 569 } 570 571 bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 572 SMLoc &EndLoc) { 573 return Error(getLoc(), "invalid register number"); 574 } 575 576 ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg, 577 SMLoc &StartLoc, 578 SMLoc &EndLoc) { 579 llvm_unreachable("Unimplemented function."); 580 } 581 582 bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr, 583 LoongArchMCExpr::VariantKind &Kind) { 584 Kind = LoongArchMCExpr::VK_LoongArch_None; 585 586 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) { 587 Kind = RE->getKind(); 588 Expr = RE->getSubExpr(); 589 } 590 591 MCValue Res; 592 if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr)) 593 return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None; 594 return false; 595 } 596 597 ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) { 598 if (!parseOptionalToken(AsmToken::Dollar)) 599 return ParseStatus::NoMatch; 600 if (getLexer().getKind() != AsmToken::Identifier) 601 return ParseStatus::NoMatch; 602 603 StringRef Name = getLexer().getTok().getIdentifier(); 604 MCRegister RegNo; 605 matchRegisterNameHelper(RegNo, Name); 606 if (RegNo == LoongArch::NoRegister) 607 return ParseStatus::NoMatch; 608 609 SMLoc S = getLoc(); 610 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 611 getLexer().Lex(); 612 Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); 613 614 return ParseStatus::Success; 615 } 616 617 ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) { 618 SMLoc S = getLoc(); 619 SMLoc E; 620 const MCExpr *Res; 621 622 switch (getLexer().getKind()) { 623 default: 624 return ParseStatus::NoMatch; 625 case AsmToken::LParen: 626 case AsmToken::Dot: 627 case AsmToken::Minus: 628 case AsmToken::Plus: 629 case AsmToken::Exclaim: 630 case AsmToken::Tilde: 631 case AsmToken::Integer: 632 case AsmToken::String: 633 case AsmToken::Identifier: 634 if (getParser().parseExpression(Res, E)) 635 return ParseStatus::Failure; 636 break; 637 case AsmToken::Percent: 638 return parseOperandWithModifier(Operands); 639 } 640 641 Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 642 return ParseStatus::Success; 643 } 644 645 ParseStatus 646 LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) { 647 SMLoc S = getLoc(); 648 SMLoc E; 649 650 if (getLexer().getKind() != AsmToken::Percent) 651 return Error(getLoc(), "expected '%' for operand modifier"); 652 653 getParser().Lex(); // Eat '%' 654 655 if (getLexer().getKind() != AsmToken::Identifier) 656 return Error(getLoc(), "expected valid identifier for operand modifier"); 657 StringRef Identifier = getParser().getTok().getIdentifier(); 658 LoongArchMCExpr::VariantKind VK = 659 LoongArchMCExpr::getVariantKindForName(Identifier); 660 if (VK == LoongArchMCExpr::VK_LoongArch_Invalid) 661 return Error(getLoc(), "unrecognized operand modifier"); 662 663 getParser().Lex(); // Eat the identifier 664 if (getLexer().getKind() != AsmToken::LParen) 665 return Error(getLoc(), "expected '('"); 666 getParser().Lex(); // Eat '(' 667 668 const MCExpr *SubExpr; 669 if (getParser().parseParenExpression(SubExpr, E)) 670 return ParseStatus::Failure; 671 672 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext()); 673 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E)); 674 return ParseStatus::Success; 675 } 676 677 ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) { 678 SMLoc S = getLoc(); 679 const MCExpr *Res; 680 681 if (getLexer().getKind() == AsmToken::Percent) 682 return parseOperandWithModifier(Operands); 683 684 if (getLexer().getKind() != AsmToken::Identifier) 685 return ParseStatus::NoMatch; 686 687 StringRef Identifier; 688 if (getParser().parseIdentifier(Identifier)) 689 return ParseStatus::Failure; 690 691 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 692 693 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 694 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 695 Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL, 696 getContext()); 697 Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 698 return ParseStatus::Success; 699 } 700 701 ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) { 702 // Parse "$r*". 703 if (!parseRegister(Operands).isSuccess()) 704 return ParseStatus::NoMatch; 705 706 // If there is a next operand and it is 0, ignore it. Otherwise print a 707 // diagnostic message. 708 if (parseOptionalToken(AsmToken::Comma)) { 709 int64_t ImmVal; 710 SMLoc ImmStart = getLoc(); 711 if (getParser().parseIntToken(ImmVal, "expected optional integer offset")) 712 return ParseStatus::Failure; 713 if (ImmVal) 714 return Error(ImmStart, "optional integer offset must be 0"); 715 } 716 717 return ParseStatus::Success; 718 } 719 /// Looks at a token type and creates the relevant operand from this 720 /// information, adding to Operands. Return true upon an error. 721 bool LoongArchAsmParser::parseOperand(OperandVector &Operands, 722 StringRef Mnemonic) { 723 // Check if the current operand has a custom associated parser, if so, try to 724 // custom parse the operand, or fallback to the general approach. 725 ParseStatus Result = 726 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 727 if (Result.isSuccess()) 728 return false; 729 if (Result.isFailure()) 730 return true; 731 732 if (parseRegister(Operands).isSuccess() || 733 parseImmediate(Operands).isSuccess()) 734 return false; 735 736 // Finally we have exhausted all options and must declare defeat. 737 return Error(getLoc(), "unknown operand"); 738 } 739 740 bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, 741 StringRef Name, SMLoc NameLoc, 742 OperandVector &Operands) { 743 // First operand in MCInst is instruction mnemonic. 744 Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); 745 746 // If there are no more operands, then finish. 747 if (parseOptionalToken(AsmToken::EndOfStatement)) 748 return false; 749 750 // Parse first operand. 751 if (parseOperand(Operands, Name)) 752 return true; 753 754 // Parse until end of statement, consuming commas between operands. 755 while (parseOptionalToken(AsmToken::Comma)) 756 if (parseOperand(Operands, Name)) 757 return true; 758 759 // Parse end of statement and return successfully. 760 if (parseOptionalToken(AsmToken::EndOfStatement)) 761 return false; 762 763 SMLoc Loc = getLexer().getLoc(); 764 getParser().eatToEndOfStatement(); 765 return Error(Loc, "unexpected token"); 766 } 767 768 void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 769 const MCExpr *Symbol, 770 SmallVectorImpl<Inst> &Insts, 771 SMLoc IDLoc, MCStreamer &Out, 772 bool RelaxHint) { 773 MCContext &Ctx = getContext(); 774 for (LoongArchAsmParser::Inst &Inst : Insts) { 775 unsigned Opc = Inst.Opc; 776 LoongArchMCExpr::VariantKind VK = Inst.VK; 777 const LoongArchMCExpr *LE = 778 LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint); 779 switch (Opc) { 780 default: 781 llvm_unreachable("unexpected opcode"); 782 case LoongArch::PCALAU12I: 783 case LoongArch::LU12I_W: 784 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE), 785 getSTI()); 786 break; 787 case LoongArch::ORI: 788 case LoongArch::ADDI_W: 789 case LoongArch::LD_W: 790 case LoongArch::LD_D: { 791 if (VK == LoongArchMCExpr::VK_LoongArch_None) { 792 Out.emitInstruction( 793 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0), 794 getSTI()); 795 continue; 796 } 797 Out.emitInstruction( 798 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE), 799 getSTI()); 800 break; 801 } 802 case LoongArch::LU32I_D: 803 Out.emitInstruction(MCInstBuilder(Opc) 804 .addReg(DestReg == TmpReg ? DestReg : TmpReg) 805 .addReg(DestReg == TmpReg ? DestReg : TmpReg) 806 .addExpr(LE), 807 getSTI()); 808 break; 809 case LoongArch::LU52I_D: 810 Out.emitInstruction( 811 MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE), 812 getSTI()); 813 break; 814 case LoongArch::ADDI_D: 815 Out.emitInstruction( 816 MCInstBuilder(Opc) 817 .addReg(TmpReg) 818 .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0) 819 .addExpr(LE), 820 getSTI()); 821 break; 822 case LoongArch::ADD_D: 823 case LoongArch::LDX_D: 824 Out.emitInstruction( 825 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg), 826 getSTI()); 827 break; 828 } 829 } 830 } 831 832 void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, 833 MCStreamer &Out) { 834 // la.abs $rd, sym 835 // expands to: 836 // lu12i.w $rd, %abs_hi20(sym) 837 // ori $rd, $rd, %abs_lo12(sym) 838 // 839 // for 64bit appends: 840 // lu32i.d $rd, %abs64_lo20(sym) 841 // lu52i.d $rd, $rd, %abs64_hi12(sym) 842 MCRegister DestReg = Inst.getOperand(0).getReg(); 843 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS 844 ? Inst.getOperand(1).getExpr() 845 : Inst.getOperand(2).getExpr(); 846 InstSeq Insts; 847 848 Insts.push_back(LoongArchAsmParser::Inst( 849 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20)); 850 Insts.push_back(LoongArchAsmParser::Inst( 851 LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12)); 852 853 if (is64Bit()) { 854 Insts.push_back(LoongArchAsmParser::Inst( 855 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20)); 856 Insts.push_back(LoongArchAsmParser::Inst( 857 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12)); 858 } 859 860 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 861 } 862 863 void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, 864 MCStreamer &Out) { 865 // la.pcrel $rd, sym 866 // expands to: 867 // pcalau12i $rd, %pc_hi20(sym) 868 // addi.w/d $rd, rd, %pc_lo12(sym) 869 MCRegister DestReg = Inst.getOperand(0).getReg(); 870 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 871 InstSeq Insts; 872 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 873 874 Insts.push_back(LoongArchAsmParser::Inst( 875 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 876 Insts.push_back( 877 LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 878 879 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 880 } 881 882 void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, 883 MCStreamer &Out) { 884 // la.pcrel $rd, $rj, sym 885 // expands to: 886 // pcalau12i $rd, %pc_hi20(sym) 887 // addi.d $rj, $r0, %pc_lo12(sym) 888 // lu32i.d $rj, %pc64_lo20(sym) 889 // lu52i.d $rj, $rj, %pc64_hi12(sym) 890 // add.d $rd, $rd, $rj 891 MCRegister DestReg = Inst.getOperand(0).getReg(); 892 MCRegister TmpReg = Inst.getOperand(1).getReg(); 893 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 894 InstSeq Insts; 895 896 Insts.push_back(LoongArchAsmParser::Inst( 897 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 898 Insts.push_back(LoongArchAsmParser::Inst( 899 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 900 Insts.push_back(LoongArchAsmParser::Inst( 901 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20)); 902 Insts.push_back(LoongArchAsmParser::Inst( 903 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12)); 904 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 905 906 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 907 } 908 909 void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, 910 MCStreamer &Out) { 911 // la.got $rd, sym 912 // expands to: 913 // pcalau12i $rd, %got_pc_hi20(sym) 914 // ld.w/d $rd, $rd, %got_pc_lo12(sym) 915 MCRegister DestReg = Inst.getOperand(0).getReg(); 916 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 917 InstSeq Insts; 918 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 919 920 Insts.push_back(LoongArchAsmParser::Inst( 921 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 922 Insts.push_back( 923 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 924 925 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 926 } 927 928 void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, 929 MCStreamer &Out) { 930 // la.got $rd, $rj, sym 931 // expands to: 932 // pcalau12i $rd, %got_pc_hi20(sym) 933 // addi.d $rj, $r0, %got_pc_lo12(sym) 934 // lu32i.d $rj, %got64_pc_lo20(sym) 935 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 936 // ldx.d $rd, $rd, $rj 937 MCRegister DestReg = Inst.getOperand(0).getReg(); 938 MCRegister TmpReg = Inst.getOperand(1).getReg(); 939 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 940 InstSeq Insts; 941 942 Insts.push_back(LoongArchAsmParser::Inst( 943 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 944 Insts.push_back(LoongArchAsmParser::Inst( 945 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 946 Insts.push_back(LoongArchAsmParser::Inst( 947 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 948 Insts.push_back(LoongArchAsmParser::Inst( 949 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 950 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 951 952 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 953 } 954 955 void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, 956 MCStreamer &Out) { 957 // la.tls.le $rd, sym 958 // expands to: 959 // lu12i.w $rd, %le_hi20(sym) 960 // ori $rd, $rd, %le_lo12(sym) 961 MCRegister DestReg = Inst.getOperand(0).getReg(); 962 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 963 InstSeq Insts; 964 965 Insts.push_back(LoongArchAsmParser::Inst( 966 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20)); 967 Insts.push_back(LoongArchAsmParser::Inst( 968 LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12)); 969 970 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 971 } 972 973 void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, 974 MCStreamer &Out) { 975 // la.tls.ie $rd, sym 976 // expands to: 977 // pcalau12i $rd, %ie_pc_hi20(sym) 978 // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 979 MCRegister DestReg = Inst.getOperand(0).getReg(); 980 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 981 InstSeq Insts; 982 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 983 984 Insts.push_back(LoongArchAsmParser::Inst( 985 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 986 Insts.push_back(LoongArchAsmParser::Inst( 987 LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 988 989 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 990 } 991 992 void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, 993 MCStreamer &Out) { 994 // la.tls.ie $rd, $rj, sym 995 // expands to: 996 // pcalau12i $rd, %ie_pc_hi20(sym) 997 // addi.d $rj, $r0, %ie_pc_lo12(sym) 998 // lu32i.d $rj, %ie64_pc_lo20(sym) 999 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym) 1000 // ldx.d $rd, $rd, $rj 1001 MCRegister DestReg = Inst.getOperand(0).getReg(); 1002 MCRegister TmpReg = Inst.getOperand(1).getReg(); 1003 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1004 InstSeq Insts; 1005 1006 Insts.push_back(LoongArchAsmParser::Inst( 1007 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 1008 Insts.push_back(LoongArchAsmParser::Inst( 1009 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 1010 Insts.push_back(LoongArchAsmParser::Inst( 1011 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20)); 1012 Insts.push_back(LoongArchAsmParser::Inst( 1013 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12)); 1014 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 1015 1016 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1017 } 1018 1019 void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, 1020 MCStreamer &Out) { 1021 // la.tls.ld $rd, sym 1022 // expands to: 1023 // pcalau12i $rd, %ld_pc_hi20(sym) 1024 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1025 MCRegister DestReg = Inst.getOperand(0).getReg(); 1026 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1027 InstSeq Insts; 1028 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1029 1030 Insts.push_back(LoongArchAsmParser::Inst( 1031 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1032 Insts.push_back(LoongArchAsmParser::Inst( 1033 ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1034 1035 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1036 } 1037 1038 void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, 1039 MCStreamer &Out) { 1040 // la.tls.ld $rd, $rj, sym 1041 // expands to: 1042 // pcalau12i $rd, %ld_pc_hi20(sym) 1043 // addi.d $rj, $r0, %got_pc_lo12(sym) 1044 // lu32i.d $rj, %got64_pc_lo20(sym) 1045 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1046 // add.d $rd, $rd, $rj 1047 MCRegister DestReg = Inst.getOperand(0).getReg(); 1048 MCRegister TmpReg = Inst.getOperand(1).getReg(); 1049 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1050 InstSeq Insts; 1051 1052 Insts.push_back(LoongArchAsmParser::Inst( 1053 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1054 Insts.push_back(LoongArchAsmParser::Inst( 1055 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1056 Insts.push_back(LoongArchAsmParser::Inst( 1057 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1058 Insts.push_back(LoongArchAsmParser::Inst( 1059 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1060 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1061 1062 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1063 } 1064 1065 void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, 1066 MCStreamer &Out) { 1067 // la.tls.gd $rd, sym 1068 // expands to: 1069 // pcalau12i $rd, %gd_pc_hi20(sym) 1070 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1071 MCRegister DestReg = Inst.getOperand(0).getReg(); 1072 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1073 InstSeq Insts; 1074 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1075 1076 Insts.push_back(LoongArchAsmParser::Inst( 1077 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1078 Insts.push_back(LoongArchAsmParser::Inst( 1079 ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1080 1081 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1082 } 1083 1084 void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, 1085 MCStreamer &Out) { 1086 // la.tls.gd $rd, $rj, sym 1087 // expands to: 1088 // pcalau12i $rd, %gd_pc_hi20(sym) 1089 // addi.d $rj, $r0, %got_pc_lo12(sym) 1090 // lu32i.d $rj, %got64_pc_lo20(sym) 1091 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1092 // add.d $rd, $rd, $rj 1093 MCRegister DestReg = Inst.getOperand(0).getReg(); 1094 MCRegister TmpReg = Inst.getOperand(1).getReg(); 1095 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1096 InstSeq Insts; 1097 1098 Insts.push_back(LoongArchAsmParser::Inst( 1099 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1100 Insts.push_back(LoongArchAsmParser::Inst( 1101 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1102 Insts.push_back(LoongArchAsmParser::Inst( 1103 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1104 Insts.push_back(LoongArchAsmParser::Inst( 1105 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1106 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1107 1108 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1109 } 1110 1111 void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, 1112 MCStreamer &Out) { 1113 MCRegister DestReg = Inst.getOperand(0).getReg(); 1114 int64_t Imm = Inst.getOperand(1).getImm(); 1115 MCRegister SrcReg = LoongArch::R0; 1116 1117 if (Inst.getOpcode() == LoongArch::PseudoLI_W) 1118 Imm = SignExtend64<32>(Imm); 1119 1120 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 1121 unsigned Opc = Inst.Opc; 1122 if (Opc == LoongArch::LU12I_W) 1123 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm), 1124 getSTI()); 1125 else 1126 Out.emitInstruction( 1127 MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm), 1128 getSTI()); 1129 SrcReg = DestReg; 1130 } 1131 } 1132 1133 void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc, 1134 MCStreamer &Out, bool IsTailCall) { 1135 // call36 sym 1136 // expands to: 1137 // pcaddu18i $ra, %call36(sym) 1138 // jirl $ra, $ra, 0 1139 // 1140 // tail36 $rj, sym 1141 // expands to: 1142 // pcaddu18i $rj, %call36(sym) 1143 // jirl $r0, $rj, 0 1144 unsigned ScratchReg = 1145 IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1; 1146 const MCExpr *Sym = 1147 IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr(); 1148 const LoongArchMCExpr *LE = LoongArchMCExpr::create( 1149 Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext()); 1150 1151 Out.emitInstruction( 1152 MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE), 1153 getSTI()); 1154 Out.emitInstruction( 1155 MCInstBuilder(LoongArch::JIRL) 1156 .addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg) 1157 .addReg(ScratchReg) 1158 .addImm(0), 1159 getSTI()); 1160 } 1161 1162 bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 1163 OperandVector &Operands, 1164 MCStreamer &Out) { 1165 Inst.setLoc(IDLoc); 1166 switch (Inst.getOpcode()) { 1167 default: 1168 break; 1169 case LoongArch::PseudoLA_ABS: 1170 case LoongArch::PseudoLA_ABS_LARGE: 1171 emitLoadAddressAbs(Inst, IDLoc, Out); 1172 return false; 1173 case LoongArch::PseudoLA_PCREL: 1174 emitLoadAddressPcrel(Inst, IDLoc, Out); 1175 return false; 1176 case LoongArch::PseudoLA_PCREL_LARGE: 1177 emitLoadAddressPcrelLarge(Inst, IDLoc, Out); 1178 return false; 1179 case LoongArch::PseudoLA_GOT: 1180 emitLoadAddressGot(Inst, IDLoc, Out); 1181 return false; 1182 case LoongArch::PseudoLA_GOT_LARGE: 1183 emitLoadAddressGotLarge(Inst, IDLoc, Out); 1184 return false; 1185 case LoongArch::PseudoLA_TLS_LE: 1186 emitLoadAddressTLSLE(Inst, IDLoc, Out); 1187 return false; 1188 case LoongArch::PseudoLA_TLS_IE: 1189 emitLoadAddressTLSIE(Inst, IDLoc, Out); 1190 return false; 1191 case LoongArch::PseudoLA_TLS_IE_LARGE: 1192 emitLoadAddressTLSIELarge(Inst, IDLoc, Out); 1193 return false; 1194 case LoongArch::PseudoLA_TLS_LD: 1195 emitLoadAddressTLSLD(Inst, IDLoc, Out); 1196 return false; 1197 case LoongArch::PseudoLA_TLS_LD_LARGE: 1198 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out); 1199 return false; 1200 case LoongArch::PseudoLA_TLS_GD: 1201 emitLoadAddressTLSGD(Inst, IDLoc, Out); 1202 return false; 1203 case LoongArch::PseudoLA_TLS_GD_LARGE: 1204 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out); 1205 return false; 1206 case LoongArch::PseudoLI_W: 1207 case LoongArch::PseudoLI_D: 1208 emitLoadImm(Inst, IDLoc, Out); 1209 return false; 1210 case LoongArch::PseudoCALL36: 1211 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false); 1212 return false; 1213 case LoongArch::PseudoTAIL36: 1214 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true); 1215 return false; 1216 } 1217 Out.emitInstruction(Inst, getSTI()); 1218 return false; 1219 } 1220 1221 unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1222 unsigned Opc = Inst.getOpcode(); 1223 switch (Opc) { 1224 default: 1225 if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { 1226 unsigned Rd = Inst.getOperand(0).getReg(); 1227 unsigned Rk = Inst.getOperand(1).getReg(); 1228 unsigned Rj = Inst.getOperand(2).getReg(); 1229 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0) 1230 return Match_RequiresAMORdDifferRkRj; 1231 } 1232 break; 1233 case LoongArch::PseudoLA_PCREL_LARGE: 1234 case LoongArch::PseudoLA_GOT_LARGE: 1235 case LoongArch::PseudoLA_TLS_IE_LARGE: 1236 case LoongArch::PseudoLA_TLS_LD_LARGE: 1237 case LoongArch::PseudoLA_TLS_GD_LARGE: { 1238 unsigned Rd = Inst.getOperand(0).getReg(); 1239 unsigned Rj = Inst.getOperand(1).getReg(); 1240 if (Rd == Rj) 1241 return Match_RequiresLAORdDifferRj; 1242 break; 1243 } 1244 case LoongArch::CSRXCHG: 1245 case LoongArch::GCSRXCHG: { 1246 unsigned Rj = Inst.getOperand(2).getReg(); 1247 if (Rj == LoongArch::R0 || Rj == LoongArch::R1) 1248 return Match_RequiresOpnd2NotR0R1; 1249 return Match_Success; 1250 } 1251 case LoongArch::BSTRINS_W: 1252 case LoongArch::BSTRINS_D: 1253 case LoongArch::BSTRPICK_W: 1254 case LoongArch::BSTRPICK_D: { 1255 unsigned Opc = Inst.getOpcode(); 1256 const signed Msb = 1257 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 1258 ? Inst.getOperand(3).getImm() 1259 : Inst.getOperand(2).getImm(); 1260 const signed Lsb = 1261 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 1262 ? Inst.getOperand(4).getImm() 1263 : Inst.getOperand(3).getImm(); 1264 if (Msb < Lsb) 1265 return Match_RequiresMsbNotLessThanLsb; 1266 return Match_Success; 1267 } 1268 } 1269 1270 return Match_Success; 1271 } 1272 1273 unsigned 1274 LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 1275 unsigned Kind) { 1276 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp); 1277 if (!Op.isReg()) 1278 return Match_InvalidOperand; 1279 1280 MCRegister Reg = Op.getReg(); 1281 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 1282 // register from FPR32 to FPR64 if necessary. 1283 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && 1284 Kind == MCK_FPR64) { 1285 Op.setReg(convertFPR32ToFPR64(Reg)); 1286 return Match_Success; 1287 } 1288 1289 return Match_InvalidOperand; 1290 } 1291 1292 bool LoongArchAsmParser::generateImmOutOfRangeError( 1293 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 1294 const Twine &Msg = "immediate must be an integer in the range") { 1295 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1296 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 1297 } 1298 1299 bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1300 OperandVector &Operands, 1301 MCStreamer &Out, 1302 uint64_t &ErrorInfo, 1303 bool MatchingInlineAsm) { 1304 MCInst Inst; 1305 FeatureBitset MissingFeatures; 1306 1307 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 1308 MatchingInlineAsm); 1309 switch (Result) { 1310 default: 1311 break; 1312 case Match_Success: 1313 return processInstruction(Inst, IDLoc, Operands, Out); 1314 case Match_MissingFeature: { 1315 assert(MissingFeatures.any() && "Unknown missing features!"); 1316 bool FirstFeature = true; 1317 std::string Msg = "instruction requires the following:"; 1318 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 1319 if (MissingFeatures[i]) { 1320 Msg += FirstFeature ? " " : ", "; 1321 Msg += getSubtargetFeatureName(i); 1322 FirstFeature = false; 1323 } 1324 } 1325 return Error(IDLoc, Msg); 1326 } 1327 case Match_MnemonicFail: { 1328 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 1329 std::string Suggestion = LoongArchMnemonicSpellCheck( 1330 ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); 1331 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 1332 } 1333 case Match_InvalidOperand: { 1334 SMLoc ErrorLoc = IDLoc; 1335 if (ErrorInfo != ~0ULL) { 1336 if (ErrorInfo >= Operands.size()) 1337 return Error(ErrorLoc, "too few operands for instruction"); 1338 1339 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1340 if (ErrorLoc == SMLoc()) 1341 ErrorLoc = IDLoc; 1342 } 1343 return Error(ErrorLoc, "invalid operand for instruction"); 1344 } 1345 } 1346 1347 // Handle the case when the error message is of specific type 1348 // other than the generic Match_InvalidOperand, and the 1349 // corresponding operand is missing. 1350 if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 1351 SMLoc ErrorLoc = IDLoc; 1352 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 1353 return Error(ErrorLoc, "too few operands for instruction"); 1354 } 1355 1356 switch (Result) { 1357 default: 1358 break; 1359 case Match_RequiresMsbNotLessThanLsb: { 1360 SMLoc ErrorStart = Operands[3]->getStartLoc(); 1361 return Error(ErrorStart, "msb is less than lsb", 1362 SMRange(ErrorStart, Operands[4]->getEndLoc())); 1363 } 1364 case Match_RequiresOpnd2NotR0R1: 1365 return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); 1366 case Match_RequiresAMORdDifferRkRj: 1367 return Error(Operands[1]->getStartLoc(), 1368 "$rd must be different from both $rk and $rj"); 1369 case Match_RequiresLAORdDifferRj: 1370 return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj"); 1371 case Match_InvalidUImm1: 1372 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1373 /*Upper=*/(1 << 1) - 1); 1374 case Match_InvalidUImm2: 1375 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1376 /*Upper=*/(1 << 2) - 1); 1377 case Match_InvalidUImm2plus1: 1378 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, 1379 /*Upper=*/(1 << 2)); 1380 case Match_InvalidUImm3: 1381 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1382 /*Upper=*/(1 << 3) - 1); 1383 case Match_InvalidUImm4: 1384 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1385 /*Upper=*/(1 << 4) - 1); 1386 case Match_InvalidUImm5: 1387 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1388 /*Upper=*/(1 << 5) - 1); 1389 case Match_InvalidUImm6: 1390 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1391 /*Upper=*/(1 << 6) - 1); 1392 case Match_InvalidUImm7: 1393 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1394 /*Upper=*/(1 << 7) - 1); 1395 case Match_InvalidUImm8: 1396 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1397 /*Upper=*/(1 << 8) - 1); 1398 case Match_InvalidUImm12: 1399 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1400 /*Upper=*/(1 << 12) - 1); 1401 case Match_InvalidUImm12ori: 1402 return generateImmOutOfRangeError( 1403 Operands, ErrorInfo, /*Lower=*/0, 1404 /*Upper=*/(1 << 12) - 1, 1405 "operand must be a symbol with modifier (e.g. %abs_lo12) or an " 1406 "integer in the range"); 1407 case Match_InvalidUImm14: 1408 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1409 /*Upper=*/(1 << 14) - 1); 1410 case Match_InvalidUImm15: 1411 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1412 /*Upper=*/(1 << 15) - 1); 1413 case Match_InvalidSImm5: 1414 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4), 1415 /*Upper=*/(1 << 4) - 1); 1416 case Match_InvalidSImm8: 1417 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7), 1418 /*Upper=*/(1 << 7) - 1); 1419 case Match_InvalidSImm8lsl1: 1420 return generateImmOutOfRangeError( 1421 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2, 1422 "immediate must be a multiple of 2 in the range"); 1423 case Match_InvalidSImm8lsl2: 1424 return generateImmOutOfRangeError( 1425 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4, 1426 "immediate must be a multiple of 4 in the range"); 1427 case Match_InvalidSImm10: 1428 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9), 1429 /*Upper=*/(1 << 9) - 1); 1430 case Match_InvalidSImm8lsl3: 1431 return generateImmOutOfRangeError( 1432 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8, 1433 "immediate must be a multiple of 8 in the range"); 1434 case Match_InvalidSImm9lsl3: 1435 return generateImmOutOfRangeError( 1436 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8, 1437 "immediate must be a multiple of 8 in the range"); 1438 case Match_InvalidSImm10lsl2: 1439 return generateImmOutOfRangeError( 1440 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4, 1441 "immediate must be a multiple of 4 in the range"); 1442 case Match_InvalidSImm11lsl1: 1443 return generateImmOutOfRangeError( 1444 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2, 1445 "immediate must be a multiple of 2 in the range"); 1446 case Match_InvalidSImm12: 1447 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1448 /*Upper=*/(1 << 11) - 1); 1449 case Match_InvalidSImm12addlike: 1450 return generateImmOutOfRangeError( 1451 Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1452 /*Upper=*/(1 << 11) - 1, 1453 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer " 1454 "in the range"); 1455 case Match_InvalidSImm12lu52id: 1456 return generateImmOutOfRangeError( 1457 Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1458 /*Upper=*/(1 << 11) - 1, 1459 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an " 1460 "integer in the range"); 1461 case Match_InvalidSImm13: 1462 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12), 1463 /*Upper=*/(1 << 12) - 1); 1464 case Match_InvalidSImm14lsl2: 1465 return generateImmOutOfRangeError( 1466 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, 1467 "immediate must be a multiple of 4 in the range"); 1468 case Match_InvalidSImm16: 1469 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), 1470 /*Upper=*/(1 << 15) - 1); 1471 case Match_InvalidSImm16lsl2: 1472 return generateImmOutOfRangeError( 1473 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, 1474 "operand must be a symbol with modifier (e.g. %b16) or an integer " 1475 "in the range"); 1476 case Match_InvalidSImm20: 1477 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1478 /*Upper=*/(1 << 19) - 1); 1479 case Match_InvalidSImm20lu12iw: 1480 return generateImmOutOfRangeError( 1481 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1482 /*Upper=*/(1 << 19) - 1, 1483 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer " 1484 "in the range"); 1485 case Match_InvalidSImm20lu32id: 1486 return generateImmOutOfRangeError( 1487 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1488 /*Upper=*/(1 << 19) - 1, 1489 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an " 1490 "integer in the range"); 1491 case Match_InvalidSImm20pcalau12i: 1492 return generateImmOutOfRangeError( 1493 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1494 /*Upper=*/(1 << 19) - 1, 1495 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " 1496 "in the range"); 1497 case Match_InvalidSImm20pcaddu18i: 1498 return generateImmOutOfRangeError( 1499 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1500 /*Upper=*/(1 << 19) - 1, 1501 "operand must be a symbol with modifier (e.g. %call36) or an integer " 1502 "in the range"); 1503 case Match_InvalidSImm21lsl2: 1504 return generateImmOutOfRangeError( 1505 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, 1506 "operand must be a symbol with modifier (e.g. %b21) or an integer " 1507 "in the range"); 1508 case Match_InvalidSImm26Operand: 1509 return generateImmOutOfRangeError( 1510 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, 1511 "operand must be a bare symbol name or an immediate must be a multiple " 1512 "of 4 in the range"); 1513 case Match_InvalidImm32: { 1514 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1515 return Error(ErrorLoc, "operand must be a 32 bit immediate"); 1516 } 1517 case Match_InvalidBareSymbol: { 1518 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1519 return Error(ErrorLoc, "operand must be a bare symbol name"); 1520 } 1521 } 1522 llvm_unreachable("Unknown match type detected!"); 1523 } 1524 1525 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { 1526 RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target()); 1527 RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target()); 1528 } 1529