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