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