LoongArchAsmParser.cpp 53 KB

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