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