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