LoongArchInstrInfo.td 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736
  1. //== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file describes the LoongArch instructions in TableGen format.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. //===----------------------------------------------------------------------===//
  13. // LoongArch specific DAG Nodes.
  14. //===----------------------------------------------------------------------===//
  15. // Target-independent type requirements, but with target-specific formats.
  16. def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
  17. SDTCisVT<1, i32>]>;
  18. def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
  19. SDTCisVT<1, i32>]>;
  20. // Target-dependent type requirements.
  21. def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>;
  22. def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [
  23. SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>
  24. ]>;
  25. def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [
  26. SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>,
  27. SDTCisSameAs<3, 4>
  28. ]>;
  29. def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [
  30. SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3>
  31. ]>;
  32. // "VI" means no output and an integer input.
  33. def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
  34. def SDT_LoongArchCsrrd : SDTypeProfile<1, 1, [SDTCisInt<0>,
  35. SDTCisVT<1, GRLenVT>]>;
  36. def SDT_LoongArchCsrwr : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>,
  37. SDTCisVT<2, GRLenVT>]>;
  38. def SDT_LoongArchCsrxchg : SDTypeProfile<1, 3, [SDTCisInt<0>,
  39. SDTCisSameAs<0, 1>,
  40. SDTCisSameAs<0, 2>,
  41. SDTCisVT<3, GRLenVT>]>;
  42. def SDT_LoongArchIocsrwr : SDTypeProfile<0, 2, [SDTCisInt<0>,
  43. SDTCisSameAs<0, 1>]>;
  44. def SDT_LoongArchMovgr2fcsr : SDTypeProfile<0, 2, [SDTCisVT<0, GRLenVT>,
  45. SDTCisSameAs<0, 1>]>;
  46. def SDT_LoongArchMovfcsr2gr : SDTypeProfile<1, 1, [SDTCisVT<0, GRLenVT>,
  47. SDTCisSameAs<0, 1>]>;
  48. // TODO: Add LoongArch specific DAG Nodes
  49. // Target-independent nodes, but with target-specific formats.
  50. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
  51. [SDNPHasChain, SDNPOutGlue]>;
  52. def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
  53. [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
  54. // Target-dependent nodes.
  55. def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall,
  56. [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
  57. SDNPVariadic]>;
  58. def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone,
  59. [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
  60. def loongarch_tail : SDNode<"LoongArchISD::TAIL", SDT_LoongArchCall,
  61. [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
  62. SDNPVariadic]>;
  63. def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>;
  64. def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>;
  65. def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>;
  66. def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>;
  67. def loongarch_rotl_w : SDNode<"LoongArchISD::ROTL_W", SDT_LoongArchIntBinOpW>;
  68. def loongarch_crc_w_b_w
  69. : SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW>;
  70. def loongarch_crc_w_h_w
  71. : SDNode<"LoongArchISD::CRC_W_H_W", SDT_LoongArchIntBinOpW>;
  72. def loongarch_crc_w_w_w
  73. : SDNode<"LoongArchISD::CRC_W_W_W", SDT_LoongArchIntBinOpW>;
  74. def loongarch_crc_w_d_w
  75. : SDNode<"LoongArchISD::CRC_W_D_W", SDT_LoongArchIntBinOpW>;
  76. def loongarch_crcc_w_b_w
  77. : SDNode<"LoongArchISD::CRCC_W_B_W", SDT_LoongArchIntBinOpW>;
  78. def loongarch_crcc_w_h_w
  79. : SDNode<"LoongArchISD::CRCC_W_H_W", SDT_LoongArchIntBinOpW>;
  80. def loongarch_crcc_w_w_w
  81. : SDNode<"LoongArchISD::CRCC_W_W_W", SDT_LoongArchIntBinOpW>;
  82. def loongarch_crcc_w_d_w
  83. : SDNode<"LoongArchISD::CRCC_W_D_W", SDT_LoongArchIntBinOpW>;
  84. def loongarch_bstrins
  85. : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>;
  86. def loongarch_bstrpick
  87. : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>;
  88. def loongarch_revb_2h : SDNode<"LoongArchISD::REVB_2H", SDTUnaryOp>;
  89. def loongarch_revb_2w : SDNode<"LoongArchISD::REVB_2W", SDTUnaryOp>;
  90. def loongarch_bitrev_4b : SDNode<"LoongArchISD::BITREV_4B", SDTUnaryOp>;
  91. def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>;
  92. def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>;
  93. def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>;
  94. def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI,
  95. [SDNPHasChain, SDNPSideEffect]>;
  96. def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI,
  97. [SDNPHasChain, SDNPSideEffect]>;
  98. def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI,
  99. [SDNPHasChain, SDNPSideEffect]>;
  100. def loongarch_movfcsr2gr : SDNode<"LoongArchISD::MOVFCSR2GR", SDT_LoongArchMovfcsr2gr>;
  101. def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR", SDT_LoongArchMovgr2fcsr,
  102. [SDNPHasChain, SDNPSideEffect]>;
  103. def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
  104. [SDNPHasChain, SDNPSideEffect]>;
  105. def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd,
  106. [SDNPHasChain, SDNPSideEffect]>;
  107. def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr,
  108. [SDNPHasChain, SDNPSideEffect]>;
  109. def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG",
  110. SDT_LoongArchCsrxchg,
  111. [SDNPHasChain, SDNPSideEffect]>;
  112. def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp,
  113. [SDNPHasChain, SDNPSideEffect]>;
  114. def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp,
  115. [SDNPHasChain, SDNPSideEffect]>;
  116. def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp,
  117. [SDNPHasChain, SDNPSideEffect]>;
  118. def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp,
  119. [SDNPHasChain, SDNPSideEffect]>;
  120. def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B",
  121. SDT_LoongArchIocsrwr,
  122. [SDNPHasChain, SDNPSideEffect]>;
  123. def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H",
  124. SDT_LoongArchIocsrwr,
  125. [SDNPHasChain, SDNPSideEffect]>;
  126. def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W",
  127. SDT_LoongArchIocsrwr,
  128. [SDNPHasChain, SDNPSideEffect]>;
  129. def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
  130. SDT_LoongArchIocsrwr,
  131. [SDNPHasChain, SDNPSideEffect]>;
  132. def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp,
  133. [SDNPHasChain, SDNPSideEffect]>;
  134. //===----------------------------------------------------------------------===//
  135. // Operand and SDNode transformation definitions.
  136. //===----------------------------------------------------------------------===//
  137. class ImmAsmOperand<string prefix, int width, string suffix>
  138. : AsmOperandClass {
  139. let Name = prefix # "Imm" # width # suffix;
  140. let DiagnosticType = !strconcat("Invalid", Name);
  141. let RenderMethod = "addImmOperands";
  142. }
  143. class SImmAsmOperand<int width, string suffix = "">
  144. : ImmAsmOperand<"S", width, suffix> {
  145. }
  146. class UImmAsmOperand<int width, string suffix = "">
  147. : ImmAsmOperand<"U", width, suffix> {
  148. }
  149. // A parse method for "$r*" or "$r*, 0", where the 0 is be silently ignored.
  150. // Only used for "AM*" instructions, in order to be compatible with GAS.
  151. def AtomicMemAsmOperand : AsmOperandClass {
  152. let Name = "AtomicMemAsmOperand";
  153. let RenderMethod = "addRegOperands";
  154. let PredicateMethod = "isGPR";
  155. let ParserMethod = "parseAtomicMemOp";
  156. }
  157. def GPRMemAtomic : RegisterOperand<GPR> {
  158. let ParserMatchClass = AtomicMemAsmOperand;
  159. let PrintMethod = "printAtomicMemOp";
  160. }
  161. // A parameterized register class alternative to i32imm/i64imm from Target.td.
  162. def grlenimm : Operand<GRLenVT>;
  163. def imm32 : Operand<GRLenVT> {
  164. let ParserMatchClass = ImmAsmOperand<"", 32, "">;
  165. }
  166. def uimm2 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]> {
  167. let ParserMatchClass = UImmAsmOperand<2>;
  168. }
  169. def uimm2_plus1 : Operand<GRLenVT>,
  170. ImmLeaf<GRLenVT, [{return isUInt<2>(Imm - 1);}]> {
  171. let ParserMatchClass = UImmAsmOperand<2, "plus1">;
  172. let EncoderMethod = "getImmOpValueSub1";
  173. let DecoderMethod = "decodeUImmOperand<2, 1>";
  174. }
  175. def uimm3 : Operand<GRLenVT> {
  176. let ParserMatchClass = UImmAsmOperand<3>;
  177. }
  178. def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> {
  179. let ParserMatchClass = UImmAsmOperand<5>;
  180. }
  181. def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> {
  182. let ParserMatchClass = UImmAsmOperand<6>;
  183. }
  184. def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> {
  185. let ParserMatchClass = UImmAsmOperand<8>;
  186. }
  187. class UImm12Operand : Operand<GRLenVT>,
  188. ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> {
  189. let DecoderMethod = "decodeUImmOperand<12>";
  190. }
  191. def uimm12 : UImm12Operand {
  192. let ParserMatchClass = UImmAsmOperand<12>;
  193. }
  194. def uimm12_ori : UImm12Operand {
  195. let ParserMatchClass = UImmAsmOperand<12, "ori">;
  196. }
  197. def uimm14 : Operand<GRLenVT>,
  198. ImmLeaf <GRLenVT, [{return isUInt<14>(Imm);}]> {
  199. let ParserMatchClass = UImmAsmOperand<14>;
  200. }
  201. def uimm15 : Operand<GRLenVT>,
  202. ImmLeaf <GRLenVT, [{return isUInt<15>(Imm);}]> {
  203. let ParserMatchClass = UImmAsmOperand<15>;
  204. }
  205. class SImm12Operand : Operand<GRLenVT>,
  206. ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> {
  207. let DecoderMethod = "decodeSImmOperand<12>";
  208. }
  209. def simm12 : SImm12Operand {
  210. let ParserMatchClass = SImmAsmOperand<12>;
  211. }
  212. def simm12_addlike : SImm12Operand {
  213. let ParserMatchClass = SImmAsmOperand<12, "addlike">;
  214. }
  215. def simm12_lu52id : SImm12Operand {
  216. let ParserMatchClass = SImmAsmOperand<12, "lu52id">;
  217. }
  218. def simm14_lsl2 : Operand<GRLenVT>,
  219. ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> {
  220. let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
  221. let EncoderMethod = "getImmOpValueAsr2";
  222. let DecoderMethod = "decodeSImmOperand<14, 2>";
  223. }
  224. def simm16 : Operand<GRLenVT> {
  225. let ParserMatchClass = SImmAsmOperand<16>;
  226. let DecoderMethod = "decodeSImmOperand<16>";
  227. }
  228. def simm16_lsl2 : Operand<GRLenVT>,
  229. ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> {
  230. let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
  231. let EncoderMethod = "getImmOpValueAsr2";
  232. let DecoderMethod = "decodeSImmOperand<16, 2>";
  233. }
  234. def simm16_lsl2_br : Operand<OtherVT> {
  235. let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
  236. let EncoderMethod = "getImmOpValueAsr2";
  237. let DecoderMethod = "decodeSImmOperand<16, 2>";
  238. }
  239. class SImm20Operand : Operand<GRLenVT> {
  240. let DecoderMethod = "decodeSImmOperand<20>";
  241. }
  242. def simm20 : SImm20Operand {
  243. let ParserMatchClass = SImmAsmOperand<20>;
  244. }
  245. def simm20_pcalau12i : SImm20Operand {
  246. let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">;
  247. }
  248. def simm20_lu12iw : SImm20Operand {
  249. let ParserMatchClass = SImmAsmOperand<20, "lu12iw">;
  250. }
  251. def simm20_lu32id : SImm20Operand {
  252. let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
  253. }
  254. def simm21_lsl2 : Operand<OtherVT> {
  255. let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
  256. let EncoderMethod = "getImmOpValueAsr2";
  257. let DecoderMethod = "decodeSImmOperand<21, 2>";
  258. }
  259. def SImm26OperandB: AsmOperandClass {
  260. let Name = "SImm26OperandB";
  261. let PredicateMethod = "isSImm26Operand";
  262. let RenderMethod = "addImmOperands";
  263. let DiagnosticType = "InvalidSImm26Operand";
  264. let ParserMethod = "parseImmediate";
  265. }
  266. // A symbol or an imm used in B/PseudoBR.
  267. def simm26_b : Operand<OtherVT> {
  268. let ParserMatchClass = SImm26OperandB;
  269. let EncoderMethod = "getImmOpValueAsr2";
  270. let DecoderMethod = "decodeSImmOperand<26, 2>";
  271. }
  272. def SImm26OperandBL: AsmOperandClass {
  273. let Name = "SImm26OperandBL";
  274. let PredicateMethod = "isSImm26Operand";
  275. let RenderMethod = "addImmOperands";
  276. let DiagnosticType = "InvalidSImm26Operand";
  277. let ParserMethod = "parseSImm26Operand";
  278. }
  279. // A symbol or an imm used in BL/PseudoCALL/PseudoTAIL.
  280. def simm26_symbol : Operand<GRLenVT> {
  281. let ParserMatchClass = SImm26OperandBL;
  282. let EncoderMethod = "getImmOpValueAsr2";
  283. let DecoderMethod = "decodeSImmOperand<26, 2>";
  284. }
  285. def BareSymbol : AsmOperandClass {
  286. let Name = "BareSymbol";
  287. let RenderMethod = "addImmOperands";
  288. let DiagnosticType = "InvalidBareSymbol";
  289. let ParserMethod = "parseImmediate";
  290. }
  291. // A bare symbol used in "PseudoLA_*" instructions.
  292. def bare_symbol : Operand<GRLenVT> {
  293. let ParserMatchClass = BareSymbol;
  294. }
  295. // Standalone (codegen-only) immleaf patterns.
  296. // A 12-bit signed immediate plus one where the imm range will be [-2047, 2048].
  297. def simm12_plus1 : ImmLeaf<GRLenVT,
  298. [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>;
  299. // Return the negation of an immediate value.
  300. def NegImm : SDNodeXForm<imm, [{
  301. return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
  302. N->getValueType(0));
  303. }]>;
  304. // FP immediate patterns.
  305. def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
  306. def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
  307. def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>;
  308. // Return an immediate subtracted from 32.
  309. def ImmSubFrom32 : SDNodeXForm<imm, [{
  310. return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
  311. N->getValueType(0));
  312. }]>;
  313. def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
  314. def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
  315. def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
  316. (fma node:$fj, node:$fk, node:$fa), [{
  317. return N->getFlags().hasNoSignedZeros();
  318. }]>;
  319. //===----------------------------------------------------------------------===//
  320. // Instruction Formats
  321. //===----------------------------------------------------------------------===//
  322. include "LoongArchInstrFormats.td"
  323. include "LoongArchFloatInstrFormats.td"
  324. //===----------------------------------------------------------------------===//
  325. // Instruction Class Templates
  326. //===----------------------------------------------------------------------===//
  327. class ALU_3R<bits<17> op, string opstr>
  328. : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
  329. class ALU_2R<bits<22> op, string opstr>
  330. : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
  331. class ALU_3RI2<bits<15> op, string opstr, Operand ImmOpnd>
  332. : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2), opstr,
  333. "$rd, $rj, $rk, $imm2">;
  334. class ALU_3RI3<bits<14> op, string opstr, Operand ImmOpnd>
  335. : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3), opstr,
  336. "$rd, $rj, $rk, $imm3">;
  337. class ALU_2RI5<bits<17> op, string opstr, Operand ImmOpnd>
  338. : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5), opstr,
  339. "$rd, $rj, $imm5">;
  340. class ALU_2RI6<bits<16> op, string opstr, Operand ImmOpnd>
  341. : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6), opstr,
  342. "$rd, $rj, $imm6">;
  343. class ALU_2RI12<bits<10> op, string opstr, Operand ImmOpnd>
  344. : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12), opstr,
  345. "$rd, $rj, $imm12">;
  346. class ALU_2RI16<bits<6> op, string opstr, Operand ImmOpnd>
  347. : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16), opstr,
  348. "$rd, $rj, $imm16">;
  349. class ALU_1RI20<bits<7> op, string opstr, Operand ImmOpnd>
  350. : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), opstr, "$rd, $imm20">;
  351. class MISC_I15<bits<17> op, string opstr>
  352. : FmtI15<op, (outs), (ins uimm15:$imm15), opstr, "$imm15">;
  353. class RDTIME_2R<bits<22> op, string opstr>
  354. : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), opstr, "$rd, $rj">;
  355. class BrCC_2RI16<bits<6> op, string opstr>
  356. : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16), opstr,
  357. "$rj, $rd, $imm16"> {
  358. let isBranch = 1;
  359. let isTerminator = 1;
  360. }
  361. class BrCCZ_1RI21<bits<6> op, string opstr>
  362. : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21), opstr,
  363. "$rj, $imm21"> {
  364. let isBranch = 1;
  365. let isTerminator = 1;
  366. }
  367. class Br_I26<bits<6> op, string opstr>
  368. : FmtI26<op, (outs), (ins simm26_b:$imm26), opstr, "$imm26"> {
  369. let isBranch = 1;
  370. let isTerminator = 1;
  371. }
  372. let mayLoad = 1 in {
  373. class LOAD_3R<bits<17> op, string opstr>
  374. : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
  375. class LOAD_2RI12<bits<10> op, string opstr>
  376. : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), opstr,
  377. "$rd, $rj, $imm12">;
  378. class LOAD_2RI14<bits<8> op, string opstr>
  379. : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
  380. "$rd, $rj, $imm14">;
  381. } // mayLoad = 1
  382. let mayStore = 1 in {
  383. class STORE_3R<bits<17> op, string opstr>
  384. : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr,
  385. "$rd, $rj, $rk">;
  386. class STORE_2RI12<bits<10> op, string opstr>
  387. : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), opstr,
  388. "$rd, $rj, $imm12">;
  389. class STORE_2RI14<bits<8> op, string opstr>
  390. : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr,
  391. "$rd, $rj, $imm14">;
  392. } // mayStore = 1
  393. let mayLoad = 1, mayStore = 1, Constraints = "@earlyclobber $rd" in
  394. class AM_3R<bits<17> op, string opstr>
  395. : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj), opstr,
  396. "$rd, $rk, $rj">;
  397. let mayLoad = 1 in
  398. class LLBase<bits<8> op, string opstr>
  399. : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
  400. "$rd, $rj, $imm14">;
  401. let mayStore = 1, Constraints = "$rd = $dst" in
  402. class SCBase<bits<8> op, string opstr>
  403. : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
  404. opstr, "$rd, $rj, $imm14">;
  405. class IOCSRRD<bits<22> op, string opstr>
  406. : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
  407. class IOCSRWR<bits<22> op, string opstr>
  408. : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), opstr, "$rd, $rj">;
  409. //===----------------------------------------------------------------------===//
  410. // Basic Integer Instructions
  411. //===----------------------------------------------------------------------===//
  412. // Arithmetic Operation Instructions
  413. def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
  414. def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
  415. def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12_addlike>;
  416. def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
  417. def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20_lu12iw>;
  418. def SLT : ALU_3R<0b00000000000100100, "slt">;
  419. def SLTU : ALU_3R<0b00000000000100101, "sltu">;
  420. def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>;
  421. def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>;
  422. def PCADDI : ALU_1RI20<0b0001100, "pcaddi", simm20>;
  423. def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>;
  424. def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20_pcalau12i>;
  425. def AND : ALU_3R<0b00000000000101001, "and">;
  426. def OR : ALU_3R<0b00000000000101010, "or">;
  427. def NOR : ALU_3R<0b00000000000101000, "nor">;
  428. def XOR : ALU_3R<0b00000000000101011, "xor">;
  429. def ANDN : ALU_3R<0b00000000000101101, "andn">;
  430. def ORN : ALU_3R<0b00000000000101100, "orn">;
  431. def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
  432. def ORI : ALU_2RI12<0b0000001110, "ori", uimm12_ori>;
  433. def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
  434. def MUL_W : ALU_3R<0b00000000000111000, "mul.w">;
  435. def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">;
  436. def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">;
  437. let usesCustomInserter = true in {
  438. def DIV_W : ALU_3R<0b00000000001000000, "div.w">;
  439. def MOD_W : ALU_3R<0b00000000001000001, "mod.w">;
  440. def DIV_WU : ALU_3R<0b00000000001000010, "div.wu">;
  441. def MOD_WU : ALU_3R<0b00000000001000011, "mod.wu">;
  442. } // usesCustomInserter = true
  443. // Bit-shift Instructions
  444. def SLL_W : ALU_3R<0b00000000000101110, "sll.w">;
  445. def SRL_W : ALU_3R<0b00000000000101111, "srl.w">;
  446. def SRA_W : ALU_3R<0b00000000000110000, "sra.w">;
  447. def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">;
  448. def SLLI_W : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>;
  449. def SRLI_W : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>;
  450. def SRAI_W : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>;
  451. def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>;
  452. // Bit-manipulation Instructions
  453. def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">;
  454. def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">;
  455. def CLO_W : ALU_2R<0b0000000000000000000100, "clo.w">;
  456. def CLZ_W : ALU_2R<0b0000000000000000000101, "clz.w">;
  457. def CTO_W : ALU_2R<0b0000000000000000000110, "cto.w">;
  458. def CTZ_W : ALU_2R<0b0000000000000000000111, "ctz.w">;
  459. def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>;
  460. def REVB_2H : ALU_2R<0b0000000000000000001100, "revb.2h">;
  461. def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">;
  462. def BITREV_W : ALU_2R<0b0000000000000000010100, "bitrev.w">;
  463. let Constraints = "$rd = $dst" in {
  464. def BSTRINS_W : FmtBSTR_W<0b000000000110, (outs GPR:$dst),
  465. (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
  466. "bstrins.w", "$rd, $rj, $msbw, $lsbw">;
  467. }
  468. def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd),
  469. (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
  470. "bstrpick.w", "$rd, $rj, $msbw, $lsbw">;
  471. def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">;
  472. def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">;
  473. // Branch Instructions
  474. def BEQ : BrCC_2RI16<0b010110, "beq">;
  475. def BNE : BrCC_2RI16<0b010111, "bne">;
  476. def BLT : BrCC_2RI16<0b011000, "blt">;
  477. def BGE : BrCC_2RI16<0b011001, "bge">;
  478. def BLTU : BrCC_2RI16<0b011010, "bltu">;
  479. def BGEU : BrCC_2RI16<0b011011, "bgeu">;
  480. def BEQZ : BrCCZ_1RI21<0b010000, "beqz">;
  481. def BNEZ : BrCCZ_1RI21<0b010001, "bnez">;
  482. def B : Br_I26<0b010100, "b">;
  483. let isCall = 1, Defs=[R1] in
  484. def BL : FmtI26<0b010101, (outs), (ins simm26_symbol:$imm26), "bl", "$imm26">;
  485. def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd),
  486. (ins GPR:$rj, simm16_lsl2:$imm16), "jirl",
  487. "$rd, $rj, $imm16">;
  488. // Common Memory Access Instructions
  489. def LD_B : LOAD_2RI12<0b0010100000, "ld.b">;
  490. def LD_H : LOAD_2RI12<0b0010100001, "ld.h">;
  491. def LD_W : LOAD_2RI12<0b0010100010, "ld.w">;
  492. def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">;
  493. def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">;
  494. def ST_B : STORE_2RI12<0b0010100100, "st.b">;
  495. def ST_H : STORE_2RI12<0b0010100101, "st.h">;
  496. def ST_W : STORE_2RI12<0b0010100110, "st.w">;
  497. def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld",
  498. "$imm5, $rj, $imm12">;
  499. // Atomic Memory Access Instructions
  500. def LL_W : LLBase<0b00100000, "ll.w">;
  501. def SC_W : SCBase<0b00100001, "sc.w">;
  502. // Barrier Instructions
  503. def DBAR : MISC_I15<0b00111000011100100, "dbar">;
  504. def IBAR : MISC_I15<0b00111000011100101, "ibar">;
  505. // Other Miscellaneous Instructions
  506. def SYSCALL : MISC_I15<0b00000000001010110, "syscall">;
  507. def BREAK : MISC_I15<0b00000000001010100, "break">;
  508. def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">;
  509. def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">;
  510. def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">;
  511. // Cache Maintenance Instructions
  512. def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop",
  513. "$op, $rj, $imm12">;
  514. /// LA64 instructions
  515. let Predicates = [IsLA64] in {
  516. // Arithmetic Operation Instructions for 64-bits
  517. def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
  518. def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
  519. def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12_addlike>;
  520. def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
  521. def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
  522. def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
  523. let Constraints = "$rd = $dst" in {
  524. def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst),
  525. (ins GPR:$rd, simm20_lu32id:$imm20), "lu32i.d",
  526. "$rd, $imm20">;
  527. }
  528. def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12_lu52id>;
  529. def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
  530. def MUL_D : ALU_3R<0b00000000000111011, "mul.d">;
  531. def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">;
  532. def MULH_DU : ALU_3R<0b00000000000111101, "mulh.du">;
  533. def MULW_D_W : ALU_3R<0b00000000000111110, "mulw.d.w">;
  534. def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">;
  535. let usesCustomInserter = true in {
  536. def DIV_D : ALU_3R<0b00000000001000100, "div.d">;
  537. def MOD_D : ALU_3R<0b00000000001000101, "mod.d">;
  538. def DIV_DU : ALU_3R<0b00000000001000110, "div.du">;
  539. def MOD_DU : ALU_3R<0b00000000001000111, "mod.du">;
  540. } // usesCustomInserter = true
  541. // Bit-shift Instructions for 64-bits
  542. def SLL_D : ALU_3R<0b00000000000110001, "sll.d">;
  543. def SRL_D : ALU_3R<0b00000000000110010, "srl.d">;
  544. def SRA_D : ALU_3R<0b00000000000110011, "sra.d">;
  545. def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">;
  546. def SLLI_D : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>;
  547. def SRLI_D : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>;
  548. def SRAI_D : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>;
  549. def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>;
  550. // Bit-manipulation Instructions for 64-bits
  551. def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">;
  552. def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">;
  553. def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">;
  554. def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">;
  555. def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>;
  556. def REVB_4H : ALU_2R<0b0000000000000000001101, "revb.4h">;
  557. def REVB_2W : ALU_2R<0b0000000000000000001110, "revb.2w">;
  558. def REVB_D : ALU_2R<0b0000000000000000001111, "revb.d">;
  559. def REVH_2W : ALU_2R<0b0000000000000000010000, "revh.2w">;
  560. def REVH_D : ALU_2R<0b0000000000000000010001, "revh.d">;
  561. def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">;
  562. def BITREV_D : ALU_2R<0b0000000000000000010101, "bitrev.d">;
  563. let Constraints = "$rd = $dst" in {
  564. def BSTRINS_D : FmtBSTR_D<0b0000000010, (outs GPR:$dst),
  565. (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
  566. "bstrins.d", "$rd, $rj, $msbd, $lsbd">;
  567. }
  568. def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd),
  569. (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
  570. "bstrpick.d", "$rd, $rj, $msbd, $lsbd">;
  571. // Common Memory Access Instructions for 64-bits
  572. def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">;
  573. def LD_D : LOAD_2RI12<0b0010100011, "ld.d">;
  574. def ST_D : STORE_2RI12<0b0010100111, "st.d">;
  575. def LDX_B : LOAD_3R<0b00111000000000000, "ldx.b">;
  576. def LDX_H : LOAD_3R<0b00111000000001000, "ldx.h">;
  577. def LDX_W : LOAD_3R<0b00111000000010000, "ldx.w">;
  578. def LDX_D : LOAD_3R<0b00111000000011000, "ldx.d">;
  579. def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">;
  580. def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">;
  581. def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">;
  582. def STX_B : STORE_3R<0b00111000000100000, "stx.b">;
  583. def STX_H : STORE_3R<0b00111000000101000, "stx.h">;
  584. def STX_W : STORE_3R<0b00111000000110000, "stx.w">;
  585. def STX_D : STORE_3R<0b00111000000111000, "stx.d">;
  586. def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">;
  587. def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">;
  588. def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">;
  589. def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">;
  590. def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx",
  591. "$imm5, $rj, $rk">;
  592. // Bound Check Memory Access Instructions
  593. def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">;
  594. def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">;
  595. def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">;
  596. def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">;
  597. def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">;
  598. def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">;
  599. def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">;
  600. def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">;
  601. def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">;
  602. def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">;
  603. def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">;
  604. def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">;
  605. def STLE_B : STORE_3R<0b00111000011111100, "stle.b">;
  606. def STLE_H : STORE_3R<0b00111000011111101, "stle.h">;
  607. def STLE_W : STORE_3R<0b00111000011111110, "stle.w">;
  608. def STLE_D : STORE_3R<0b00111000011111111, "stle.d">;
  609. // Atomic Memory Access Instructions for 64-bits
  610. def AMSWAP_W : AM_3R<0b00111000011000000, "amswap.w">;
  611. def AMSWAP_D : AM_3R<0b00111000011000001, "amswap.d">;
  612. def AMADD_W : AM_3R<0b00111000011000010, "amadd.w">;
  613. def AMADD_D : AM_3R<0b00111000011000011, "amadd.d">;
  614. def AMAND_W : AM_3R<0b00111000011000100, "amand.w">;
  615. def AMAND_D : AM_3R<0b00111000011000101, "amand.d">;
  616. def AMOR_W : AM_3R<0b00111000011000110, "amor.w">;
  617. def AMOR_D : AM_3R<0b00111000011000111, "amor.d">;
  618. def AMXOR_W : AM_3R<0b00111000011001000, "amxor.w">;
  619. def AMXOR_D : AM_3R<0b00111000011001001, "amxor.d">;
  620. def AMMAX_W : AM_3R<0b00111000011001010, "ammax.w">;
  621. def AMMAX_D : AM_3R<0b00111000011001011, "ammax.d">;
  622. def AMMIN_W : AM_3R<0b00111000011001100, "ammin.w">;
  623. def AMMIN_D : AM_3R<0b00111000011001101, "ammin.d">;
  624. def AMMAX_WU : AM_3R<0b00111000011001110, "ammax.wu">;
  625. def AMMAX_DU : AM_3R<0b00111000011001111, "ammax.du">;
  626. def AMMIN_WU : AM_3R<0b00111000011010000, "ammin.wu">;
  627. def AMMIN_DU : AM_3R<0b00111000011010001, "ammin.du">;
  628. def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">;
  629. def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">;
  630. def AMADD_DB_W : AM_3R<0b00111000011010100, "amadd_db.w">;
  631. def AMADD_DB_D : AM_3R<0b00111000011010101, "amadd_db.d">;
  632. def AMAND_DB_W : AM_3R<0b00111000011010110, "amand_db.w">;
  633. def AMAND_DB_D : AM_3R<0b00111000011010111, "amand_db.d">;
  634. def AMOR_DB_W : AM_3R<0b00111000011011000, "amor_db.w">;
  635. def AMOR_DB_D : AM_3R<0b00111000011011001, "amor_db.d">;
  636. def AMXOR_DB_W : AM_3R<0b00111000011011010, "amxor_db.w">;
  637. def AMXOR_DB_D : AM_3R<0b00111000011011011, "amxor_db.d">;
  638. def AMMAX_DB_W : AM_3R<0b00111000011011100, "ammax_db.w">;
  639. def AMMAX_DB_D : AM_3R<0b00111000011011101, "ammax_db.d">;
  640. def AMMIN_DB_W : AM_3R<0b00111000011011110, "ammin_db.w">;
  641. def AMMIN_DB_D : AM_3R<0b00111000011011111, "ammin_db.d">;
  642. def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">;
  643. def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">;
  644. def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">;
  645. def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">;
  646. def LL_D : LLBase<0b00100010, "ll.d">;
  647. def SC_D : SCBase<0b00100011, "sc.d">;
  648. // CRC Check Instructions
  649. def CRC_W_B_W : ALU_3R<0b00000000001001000, "crc.w.b.w">;
  650. def CRC_W_H_W : ALU_3R<0b00000000001001001, "crc.w.h.w">;
  651. def CRC_W_W_W : ALU_3R<0b00000000001001010, "crc.w.w.w">;
  652. def CRC_W_D_W : ALU_3R<0b00000000001001011, "crc.w.d.w">;
  653. def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">;
  654. def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">;
  655. def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">;
  656. def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">;
  657. // Other Miscellaneous Instructions for 64-bits
  658. def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk),
  659. "asrtle.d", "$rj, $rk">;
  660. def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk),
  661. "asrtgt.d", "$rj, $rk">;
  662. def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">;
  663. } // Predicates = [IsLA64]
  664. //===----------------------------------------------------------------------===//
  665. // Pseudo-instructions and codegen patterns
  666. //
  667. // Naming convention: For 'generic' pattern classes, we use the naming
  668. // convention PatTy1Ty2.
  669. //===----------------------------------------------------------------------===//
  670. /// Generic pattern classes
  671. class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
  672. : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
  673. class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
  674. : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
  675. class PatGpr<SDPatternOperator OpNode, LAInst Inst>
  676. : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>;
  677. class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
  678. : Pat<(OpNode GPR:$rj, ImmOpnd:$imm),
  679. (Inst GPR:$rj, ImmOpnd:$imm)>;
  680. class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
  681. : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
  682. (Inst GPR:$rj, ImmOpnd:$imm)>;
  683. /// Predicates
  684. def AddLike: PatFrags<(ops node:$A, node:$B),
  685. [(add node:$A, node:$B), (or node:$A, node:$B)], [{
  686. return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N);
  687. }]>;
  688. /// Simple arithmetic operations
  689. // Match both a plain shift and one where the shift amount is masked (this is
  690. // typically introduced when the legalizer promotes the shift amount and
  691. // zero-extends it). For LoongArch, the mask is unnecessary as shifts in the
  692. // base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64).
  693. def shiftMaskGRLen
  694. : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>;
  695. def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
  696. def sexti32 : ComplexPattern<i64, 1, "selectSExti32">;
  697. def zexti32 : ComplexPattern<i64, 1, "selectZExti32">;
  698. class shiftop<SDPatternOperator operator>
  699. : PatFrag<(ops node:$val, node:$count),
  700. (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>;
  701. class shiftopw<SDPatternOperator operator>
  702. : PatFrag<(ops node:$val, node:$count),
  703. (operator node:$val, (i64 (shiftMask32 node:$count)))>;
  704. let Predicates = [IsLA32] in {
  705. def : PatGprGpr<add, ADD_W>;
  706. def : PatGprImm<add, ADDI_W, simm12>;
  707. def : PatGprGpr<sub, SUB_W>;
  708. def : PatGprGpr<sdiv, DIV_W>;
  709. def : PatGprGpr<udiv, DIV_WU>;
  710. def : PatGprGpr<srem, MOD_W>;
  711. def : PatGprGpr<urem, MOD_WU>;
  712. def : PatGprGpr<mul, MUL_W>;
  713. def : PatGprGpr<mulhs, MULH_W>;
  714. def : PatGprGpr<mulhu, MULH_WU>;
  715. def : PatGprGpr<rotr, ROTR_W>;
  716. def : PatGprImm<rotr, ROTRI_W, uimm5>;
  717. } // Predicates = [IsLA32]
  718. let Predicates = [IsLA64] in {
  719. def : PatGprGpr<add, ADD_D>;
  720. def : PatGprGpr_32<add, ADD_W>;
  721. def : PatGprImm<add, ADDI_D, simm12>;
  722. def : PatGprImm_32<add, ADDI_W, simm12>;
  723. def : PatGprGpr<sub, SUB_D>;
  724. def : PatGprGpr_32<sub, SUB_W>;
  725. def : PatGprGpr<sdiv, DIV_D>;
  726. def : PatGprGpr<udiv, DIV_DU>;
  727. def : PatGprGpr<srem, MOD_D>;
  728. def : PatGprGpr<urem, MOD_DU>;
  729. def : PatGprGpr<rotr, ROTR_D>;
  730. def : PatGprGpr<loongarch_rotr_w, ROTR_W>;
  731. def : PatGprImm<rotr, ROTRI_D, uimm6>;
  732. def : PatGprImm_32<rotr, ROTRI_W, uimm5>;
  733. def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm),
  734. (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
  735. def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32),
  736. (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
  737. // TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the
  738. // product are used.
  739. def : PatGprGpr<mul, MUL_D>;
  740. def : PatGprGpr<mulhs, MULH_D>;
  741. def : PatGprGpr<mulhu, MULH_DU>;
  742. // Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed
  743. // multiplication.
  744. def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))),
  745. (MULW_D_W GPR:$rj, GPR:$rk)>;
  746. // Select MULW_D_WU for calculating the full 64 bits product of i32xi32
  747. // unsigned multiplication.
  748. def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)),
  749. (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))),
  750. (MULW_D_WU GPR:$rj, GPR:$rk)>;
  751. } // Predicates = [IsLA64]
  752. def : PatGprGpr<and, AND>;
  753. def : PatGprImm<and, ANDI, uimm12>;
  754. def : PatGprGpr<or, OR>;
  755. def : PatGprImm<or, ORI, uimm12>;
  756. def : PatGprGpr<xor, XOR>;
  757. def : PatGprImm<xor, XORI, uimm12>;
  758. def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>;
  759. def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>;
  760. def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>;
  761. def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>;
  762. /// Traps
  763. // We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed
  764. // to trap with an INE (non-existent on LA32, explicitly documented to INE on
  765. // LA64). And the resulting signal is different from `debugtrap` like on some
  766. // other existing ports so programs/porters might have an easier time.
  767. def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>,
  768. PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>;
  769. // We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work,
  770. // even for LA32 Primary. Also, because so far the ISA does not provide a
  771. // specific trap instruction/kind exclusively for alerting the debugger,
  772. // every other project uses the generic immediate of 0 for this.
  773. def : Pat<(debugtrap), (BREAK 0)>;
  774. /// Bit counting operations
  775. let Predicates = [IsLA64] in {
  776. def : PatGpr<ctlz, CLZ_D>;
  777. def : PatGpr<cttz, CTZ_D>;
  778. def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>;
  779. def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>;
  780. def : PatGpr<loongarch_clzw, CLZ_W>;
  781. def : PatGpr<loongarch_ctzw, CTZ_W>;
  782. def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>;
  783. def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>;
  784. } // Predicates = [IsLA64]
  785. let Predicates = [IsLA32] in {
  786. def : PatGpr<ctlz, CLZ_W>;
  787. def : PatGpr<cttz, CTZ_W>;
  788. def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>;
  789. def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>;
  790. } // Predicates = [IsLA32]
  791. /// FrameIndex calculations
  792. let Predicates = [IsLA32] in {
  793. def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12),
  794. (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>;
  795. } // Predicates = [IsLA32]
  796. let Predicates = [IsLA64] in {
  797. def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12),
  798. (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>;
  799. } // Predicates = [IsLA64]
  800. /// Shifted addition
  801. let Predicates = [IsLA32] in {
  802. def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
  803. (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
  804. } // Predicates = [IsLA32]
  805. let Predicates = [IsLA64] in {
  806. def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
  807. (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
  808. def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)),
  809. (i64 31), (i64 0)),
  810. (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>;
  811. } // Predicates = [IsLA64]
  812. /// Shift
  813. let Predicates = [IsLA32] in {
  814. def : PatGprGpr<shiftop<shl>, SLL_W>;
  815. def : PatGprGpr<shiftop<sra>, SRA_W>;
  816. def : PatGprGpr<shiftop<srl>, SRL_W>;
  817. def : PatGprImm<shl, SLLI_W, uimm5>;
  818. def : PatGprImm<sra, SRAI_W, uimm5>;
  819. def : PatGprImm<srl, SRLI_W, uimm5>;
  820. } // Predicates = [IsLA32]
  821. let Predicates = [IsLA64] in {
  822. def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>;
  823. def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>;
  824. def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>;
  825. def : PatGprGpr<shiftop<shl>, SLL_D>;
  826. def : PatGprGpr<shiftop<sra>, SRA_D>;
  827. def : PatGprGpr<shiftop<srl>, SRL_D>;
  828. def : PatGprImm<shl, SLLI_D, uimm6>;
  829. def : PatGprImm<sra, SRAI_D, uimm6>;
  830. def : PatGprImm<srl, SRLI_D, uimm6>;
  831. } // Predicates = [IsLA64]
  832. /// sext and zext
  833. def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>;
  834. def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>;
  835. let Predicates = [IsLA64] in {
  836. def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
  837. } // Predicates = [IsLA64]
  838. /// Setcc
  839. def : PatGprGpr<setlt, SLT>;
  840. def : PatGprImm<setlt, SLTI, simm12>;
  841. def : PatGprGpr<setult, SLTU>;
  842. def : PatGprImm<setult, SLTUI, simm12>;
  843. // Define pattern expansions for setcc operations that aren't directly
  844. // handled by a LoongArch instruction.
  845. def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>;
  846. def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>;
  847. let Predicates = [IsLA32] in {
  848. def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
  849. (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
  850. } // Predicates = [IsLA32]
  851. let Predicates = [IsLA64] in {
  852. def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
  853. (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
  854. } // Predicates = [IsLA64]
  855. def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>;
  856. def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>;
  857. let Predicates = [IsLA32] in {
  858. def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
  859. (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
  860. } // Predicates = [IsLA32]
  861. let Predicates = [IsLA64] in {
  862. def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
  863. (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
  864. } // Predicates = [IsLA64]
  865. def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>;
  866. def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>;
  867. def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>;
  868. def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>;
  869. def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>;
  870. def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>;
  871. /// Select
  872. def : Pat<(select GPR:$cond, GPR:$t, GPR:$f),
  873. (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>;
  874. /// Branches and jumps
  875. class BccPat<PatFrag CondOp, LAInst Inst>
  876. : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16),
  877. (Inst GPR:$rj, GPR:$rd, bb:$imm16)>;
  878. def : BccPat<seteq, BEQ>;
  879. def : BccPat<setne, BNE>;
  880. def : BccPat<setlt, BLT>;
  881. def : BccPat<setge, BGE>;
  882. def : BccPat<setult, BLTU>;
  883. def : BccPat<setuge, BGEU>;
  884. class BccSwapPat<PatFrag CondOp, LAInst InstBcc>
  885. : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16),
  886. (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>;
  887. // Condition codes that don't have matching LoongArch branch instructions, but
  888. // are trivially supported by swapping the two input operands.
  889. def : BccSwapPat<setgt, BLT>;
  890. def : BccSwapPat<setle, BGE>;
  891. def : BccSwapPat<setugt, BLTU>;
  892. def : BccSwapPat<setule, BGEU>;
  893. // An extra pattern is needed for a brcond without a setcc (i.e. where the
  894. // condition was calculated elsewhere).
  895. def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>;
  896. def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21),
  897. (BEQZ GPR:$rj, bb:$imm21)>;
  898. def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21),
  899. (BNEZ GPR:$rj, bb:$imm21)>;
  900. let isBarrier = 1, isBranch = 1, isTerminator = 1 in
  901. def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>,
  902. PseudoInstExpansion<(B simm26_b:$imm26)>;
  903. let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
  904. def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
  905. PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
  906. def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
  907. def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
  908. (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
  909. let isCall = 1, Defs = [R1] in
  910. def PseudoCALL : Pseudo<(outs), (ins simm26_symbol:$func)>;
  911. def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
  912. def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
  913. let isCall = 1, Defs = [R1] in
  914. def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
  915. [(loongarch_call GPR:$rj)]>,
  916. PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
  917. let isCall = 1, Defs = [R1] in
  918. def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
  919. PseudoInstExpansion<(JIRL R1, GPR:$rj,
  920. simm16_lsl2:$imm16)>;
  921. let isBarrier = 1, isReturn = 1, isTerminator = 1 in
  922. def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
  923. PseudoInstExpansion<(JIRL R0, R1, 0)>;
  924. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
  925. def PseudoTAIL : Pseudo<(outs), (ins simm26_symbol:$dst)>;
  926. def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)),
  927. (PseudoTAIL tglobaladdr:$dst)>;
  928. def : Pat<(loongarch_tail (iPTR texternalsym:$dst)),
  929. (PseudoTAIL texternalsym:$dst)>;
  930. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
  931. def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj),
  932. [(loongarch_tail GPRT:$rj)]>,
  933. PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>;
  934. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
  935. def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>,
  936. PseudoInstExpansion<(B simm26_b:$imm26)>;
  937. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
  938. def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
  939. PseudoInstExpansion<(JIRL R0, GPR:$rj,
  940. simm16_lsl2:$imm16)>;
  941. /// Load address (la*) macro instructions.
  942. // Define isCodeGenOnly = 0 to expose them to tablegened assembly parser.
  943. let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
  944. isAsmParserOnly = 1 in {
  945. def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  946. "la.abs", "$dst, $src">;
  947. def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst),
  948. (ins GPR:$tmp, bare_symbol:$src), [],
  949. "la.abs", "$dst, $src">;
  950. def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  951. "la.pcrel", "$dst, $src">;
  952. def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst),
  953. (ins GPR:$tmp, bare_symbol:$src), [],
  954. "la.pcrel", "$dst, $tmp, $src">,
  955. Requires<[IsLA64]>;
  956. def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  957. "la.tls.le", "$dst, $src">;
  958. }
  959. let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
  960. isAsmParserOnly = 1 in {
  961. def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  962. "la.got", "$dst, $src">;
  963. def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst),
  964. (ins GPR:$tmp, bare_symbol:$src), [],
  965. "la.got", "$dst, $tmp, $src">,
  966. Requires<[IsLA64]>;
  967. def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  968. "la.tls.ie", "$dst, $src">;
  969. def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst),
  970. (ins GPR:$tmp, bare_symbol:$src), [],
  971. "la.tls.ie", "$dst, $tmp, $src">,
  972. Requires<[IsLA64]>;
  973. def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  974. "la.tls.ld", "$dst, $src">;
  975. def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst),
  976. (ins GPR:$tmp, bare_symbol:$src), [],
  977. "la.tls.ld", "$dst, $tmp, $src">,
  978. Requires<[IsLA64]>;
  979. def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
  980. "la.tls.gd", "$dst, $src">;
  981. def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
  982. (ins GPR:$tmp, bare_symbol:$src), [],
  983. "la.tls.gd", "$dst, $tmp, $src">,
  984. Requires<[IsLA64]>;
  985. }
  986. // Load address inst alias: "la", "la.global" and "la.local".
  987. // Default:
  988. // la = la.global = la.got
  989. // la.local = la.pcrel
  990. // With feature "+la-global-with-pcrel":
  991. // la = la.global = la.pcrel
  992. // With feature "+la-global-with-abs":
  993. // la = la.global = la.abs
  994. // With feature "+la-local-with-abs":
  995. // la.local = la.abs
  996. // With features "+la-global-with-pcrel,+la-global-with-abs"(disorder):
  997. // la = la.global = la.pcrel
  998. // Note: To keep consistent with gnu-as behavior, the "la" can only have one
  999. // register operand.
  1000. def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
  1001. def : InstAlias<"la.global $dst, $src",
  1002. (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>;
  1003. def : InstAlias<"la.global $dst, $tmp, $src",
  1004. (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
  1005. def : InstAlias<"la.local $dst, $src",
  1006. (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
  1007. def : InstAlias<"la.local $dst, $tmp, $src",
  1008. (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
  1009. // Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure
  1010. // "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and
  1011. // "la-global-with-abs" are enabled.
  1012. let Predicates = [HasLaGlobalWithPcrel] in {
  1013. def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
  1014. def : InstAlias<"la.global $dst, $src",
  1015. (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>;
  1016. def : InstAlias<"la.global $dst, $tmp, $src",
  1017. (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
  1018. } // Predicates = [HasLaGlobalWithPcrel]
  1019. let Predicates = [HasLaGlobalWithAbs] in {
  1020. def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
  1021. def : InstAlias<"la.global $dst, $src",
  1022. (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
  1023. def : InstAlias<"la.global $dst, $tmp, $src",
  1024. (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
  1025. } // Predicates = [HasLaGlobalWithAbs]
  1026. let Predicates = [HasLaLocalWithAbs] in {
  1027. def : InstAlias<"la.local $dst, $src",
  1028. (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>;
  1029. def : InstAlias<"la.local $dst, $tmp, $src",
  1030. (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
  1031. } // Predicates = [HasLaLocalWithAbs]
  1032. /// BSTRINS and BSTRPICK
  1033. let Predicates = [IsLA32] in {
  1034. def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
  1035. (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
  1036. def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
  1037. (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
  1038. } // Predicates = [IsLA32]
  1039. let Predicates = [IsLA64] in {
  1040. def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
  1041. (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
  1042. def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
  1043. (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
  1044. } // Predicates = [IsLA64]
  1045. /// Byte-swapping and bit-reversal
  1046. def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>;
  1047. def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>;
  1048. let Predicates = [IsLA32] in {
  1049. def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>;
  1050. def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>;
  1051. def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>;
  1052. def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>;
  1053. } // Predicates = [IsLA32]
  1054. let Predicates = [IsLA64] in {
  1055. def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>;
  1056. def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>;
  1057. def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>;
  1058. def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>;
  1059. def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>;
  1060. def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>;
  1061. } // Predicates = [IsLA64]
  1062. /// Loads
  1063. multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
  1064. def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>;
  1065. def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))),
  1066. (Inst BaseAddr:$rj, simm12:$imm12)>;
  1067. }
  1068. defm : LdPat<sextloadi8, LD_B>;
  1069. defm : LdPat<extloadi8, LD_B>;
  1070. defm : LdPat<sextloadi16, LD_H>;
  1071. defm : LdPat<extloadi16, LD_H>;
  1072. defm : LdPat<load, LD_W>, Requires<[IsLA32]>;
  1073. defm : LdPat<zextloadi8, LD_BU>;
  1074. defm : LdPat<zextloadi16, LD_HU>;
  1075. let Predicates = [IsLA64] in {
  1076. defm : LdPat<sextloadi32, LD_W, i64>;
  1077. defm : LdPat<extloadi32, LD_W, i64>;
  1078. defm : LdPat<zextloadi32, LD_WU, i64>;
  1079. defm : LdPat<load, LD_D, i64>;
  1080. } // Predicates = [IsLA64]
  1081. // LA64 register-register-addressed loads
  1082. let Predicates = [IsLA64] in {
  1083. class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt>
  1084. : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))),
  1085. (Inst NonFIBaseAddr:$rj, GPR:$rk)>;
  1086. def : RegRegLdPat<extloadi8, LDX_B, i64>;
  1087. def : RegRegLdPat<sextloadi8, LDX_B, i64>;
  1088. def : RegRegLdPat<zextloadi8, LDX_BU, i64>;
  1089. def : RegRegLdPat<extloadi16, LDX_H, i64>;
  1090. def : RegRegLdPat<sextloadi16, LDX_H, i64>;
  1091. def : RegRegLdPat<zextloadi16, LDX_HU, i64>;
  1092. def : RegRegLdPat<extloadi32, LDX_W, i64>;
  1093. def : RegRegLdPat<sextloadi32, LDX_W, i64>;
  1094. def : RegRegLdPat<zextloadi32, LDX_WU, i64>;
  1095. def : RegRegLdPat<load, LDX_D, i64>;
  1096. } // Predicates = [IsLA64]
  1097. /// Stores
  1098. multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
  1099. ValueType vt> {
  1100. def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj),
  1101. (Inst StTy:$rd, BaseAddr:$rj, 0)>;
  1102. def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)),
  1103. (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>;
  1104. }
  1105. defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
  1106. defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>;
  1107. defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>;
  1108. let Predicates = [IsLA64] in {
  1109. defm : StPat<truncstorei32, ST_W, GPR, i64>;
  1110. defm : StPat<store, ST_D, GPR, i64>;
  1111. } // Predicates = [IsLA64]
  1112. let Predicates = [IsLA64] in {
  1113. def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
  1114. (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>;
  1115. def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))),
  1116. (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>;
  1117. def : Pat<(truncstorei32 (i64 GPR:$rd),
  1118. (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
  1119. (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
  1120. def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
  1121. (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>;
  1122. } // Predicates = [IsLA64]
  1123. // LA64 register-register-addressed stores
  1124. let Predicates = [IsLA64] in {
  1125. class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
  1126. ValueType vt>
  1127. : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)),
  1128. (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>;
  1129. def : RegRegStPat<truncstorei8, STX_B, GPR, i64>;
  1130. def : RegRegStPat<truncstorei16, STX_H, GPR, i64>;
  1131. def : RegRegStPat<truncstorei32, STX_W, GPR, i64>;
  1132. def : RegRegStPat<store, STX_D, GPR, i64>;
  1133. } // Predicates = [IsLA64]
  1134. /// Atomic loads and stores
  1135. def : Pat<(atomic_fence timm, timm), (DBAR 0)>;
  1136. defm : LdPat<atomic_load_8, LD_B>;
  1137. defm : LdPat<atomic_load_16, LD_H>;
  1138. defm : LdPat<atomic_load_32, LD_W>;
  1139. class release_seqcst_store<PatFrag base>
  1140. : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
  1141. AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
  1142. return isReleaseOrStronger(Ordering);
  1143. }]>;
  1144. class unordered_monotonic_store<PatFrag base>
  1145. : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
  1146. AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering();
  1147. return !isReleaseOrStronger(Ordering);
  1148. }]>;
  1149. def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>;
  1150. def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>;
  1151. def atomic_store_unordered_monotonic_32
  1152. : unordered_monotonic_store<atomic_store_32>;
  1153. def atomic_store_unordered_monotonic_64
  1154. : unordered_monotonic_store<atomic_store_64>;
  1155. /// AtomicStores
  1156. multiclass AtomicStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
  1157. ValueType vt> {
  1158. def : Pat<(StoreOp BaseAddr:$ptr, (vt StTy:$val)),
  1159. (Inst StTy:$val, BaseAddr:$ptr, 0)>;
  1160. def : Pat<(StoreOp (AddLike BaseAddr:$ptr, simm12:$imm12), (vt StTy:$val)),
  1161. (Inst StTy:$val, BaseAddr:$ptr, simm12:$imm12)>;
  1162. }
  1163. defm : AtomicStPat<atomic_store_8, ST_B, GPR, GRLenVT>;
  1164. defm : AtomicStPat<atomic_store_16, ST_H, GPR, GRLenVT>;
  1165. defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>,
  1166. Requires<[IsLA32]>;
  1167. def PseudoAtomicStoreW
  1168. : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>,
  1169. PseudoInstExpansion<(AMSWAP_DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>;
  1170. def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk),
  1171. (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>;
  1172. let Predicates = [IsLA64] in {
  1173. def PseudoAtomicStoreD
  1174. : Pseudo<(outs GPR:$dst), (ins GPR:$rj, GPR:$rk)>,
  1175. PseudoInstExpansion<(AMSWAP_DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>;
  1176. def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk),
  1177. (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>;
  1178. defm : LdPat<atomic_load_64, LD_D>;
  1179. defm : AtomicStPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>;
  1180. defm : AtomicStPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>;
  1181. } // Predicates = [IsLA64]
  1182. /// Atomic Ops
  1183. class PseudoMaskedAM
  1184. : Pseudo<(outs GPR:$res, GPR:$scratch),
  1185. (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
  1186. let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
  1187. let mayLoad = 1;
  1188. let mayStore = 1;
  1189. let hasSideEffects = 0;
  1190. let Size = 36;
  1191. }
  1192. def PseudoMaskedAtomicSwap32 : PseudoMaskedAM;
  1193. def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM;
  1194. def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM;
  1195. def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM;
  1196. class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch),
  1197. (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> {
  1198. let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
  1199. let mayLoad = 1;
  1200. let mayStore = 1;
  1201. let hasSideEffects = 0;
  1202. let Size = 24;
  1203. }
  1204. def PseudoAtomicSwap32 : PseudoAM;
  1205. def PseudoAtomicLoadNand32 : PseudoAM;
  1206. def PseudoAtomicLoadNand64 : PseudoAM;
  1207. def PseudoAtomicLoadAdd32 : PseudoAM;
  1208. def PseudoAtomicLoadSub32 : PseudoAM;
  1209. def PseudoAtomicLoadAnd32 : PseudoAM;
  1210. def PseudoAtomicLoadOr32 : PseudoAM;
  1211. def PseudoAtomicLoadXor32 : PseudoAM;
  1212. multiclass PseudoBinPat<string Op, Pseudo BinInst> {
  1213. def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr),
  1214. (BinInst GPR:$addr, GPR:$incr, 2)>;
  1215. def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr),
  1216. (BinInst GPR:$addr, GPR:$incr, 4)>;
  1217. def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr),
  1218. (BinInst GPR:$addr, GPR:$incr, 5)>;
  1219. def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr),
  1220. (BinInst GPR:$addr, GPR:$incr, 6)>;
  1221. def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr),
  1222. (BinInst GPR:$addr, GPR:$incr, 7)>;
  1223. }
  1224. class PseudoMaskedAMUMinUMax
  1225. : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
  1226. (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> {
  1227. let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
  1228. "@earlyclobber $scratch2";
  1229. let mayLoad = 1;
  1230. let mayStore = 1;
  1231. let hasSideEffects = 0;
  1232. let Size = 48;
  1233. }
  1234. def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax;
  1235. def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax;
  1236. class PseudoMaskedAMMinMax
  1237. : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2),
  1238. (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt,
  1239. grlenimm:$ordering)> {
  1240. let Constraints = "@earlyclobber $res,@earlyclobber $scratch1,"
  1241. "@earlyclobber $scratch2";
  1242. let mayLoad = 1;
  1243. let mayStore = 1;
  1244. let hasSideEffects = 0;
  1245. let Size = 56;
  1246. }
  1247. def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
  1248. def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax;
  1249. /// Compare and exchange
  1250. class PseudoCmpXchg
  1251. : Pseudo<(outs GPR:$res, GPR:$scratch),
  1252. (ins GPR:$addr, GPR:$cmpval, GPR:$newval)> {
  1253. let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
  1254. let mayLoad = 1;
  1255. let mayStore = 1;
  1256. let hasSideEffects = 0;
  1257. let Size = 36;
  1258. }
  1259. def PseudoCmpXchg32 : PseudoCmpXchg;
  1260. def PseudoCmpXchg64 : PseudoCmpXchg;
  1261. def PseudoMaskedCmpXchg32
  1262. : Pseudo<(outs GPR:$res, GPR:$scratch),
  1263. (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
  1264. grlenimm:$ordering)> {
  1265. let Constraints = "@earlyclobber $res,@earlyclobber $scratch";
  1266. let mayLoad = 1;
  1267. let mayStore = 1;
  1268. let hasSideEffects = 0;
  1269. let Size = 44;
  1270. }
  1271. class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst>
  1272. : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
  1273. timm:$ordering),
  1274. (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
  1275. timm:$ordering)>;
  1276. class AtomicPat<Intrinsic intrin, Pseudo AMInst>
  1277. : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
  1278. (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
  1279. let Predicates = [IsLA64] in {
  1280. def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64,
  1281. PseudoMaskedAtomicSwap32>;
  1282. def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr),
  1283. (AMSWAP_DB_W GPR:$incr, GPR:$addr)>;
  1284. def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr),
  1285. (AMSWAP_DB_D GPR:$incr, GPR:$addr)>;
  1286. def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk),
  1287. (AMADD_DB_D GPR:$rk, GPR:$rj)>;
  1288. def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64,
  1289. PseudoMaskedAtomicLoadAdd32>;
  1290. def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk),
  1291. (AMADD_DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>;
  1292. def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk),
  1293. (AMADD_DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>;
  1294. def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64,
  1295. PseudoMaskedAtomicLoadSub32>;
  1296. defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>;
  1297. def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64,
  1298. PseudoMaskedAtomicLoadNand32>;
  1299. def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk),
  1300. (AMADD_DB_W GPR:$rk, GPR:$rj)>;
  1301. def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk),
  1302. (AMAND_DB_W GPR:$rk, GPR:$rj)>;
  1303. def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk),
  1304. (AMAND_DB_D GPR:$rk, GPR:$rj)>;
  1305. def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk),
  1306. (AMOR_DB_W GPR:$rk, GPR:$rj)>;
  1307. def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk),
  1308. (AMOR_DB_D GPR:$rk, GPR:$rj)>;
  1309. def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk),
  1310. (AMXOR_DB_W GPR:$rk, GPR:$rj)>;
  1311. def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk),
  1312. (AMXOR_DB_D GPR:$rk, GPR:$rj)>;
  1313. def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk),
  1314. (AMMIN_DB_WU GPR:$rk, GPR:$rj)>;
  1315. def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk),
  1316. (AMMIN_DB_DU GPR:$rk, GPR:$rj)>;
  1317. def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk),
  1318. (AMMAX_DB_WU GPR:$rk, GPR:$rj)>;
  1319. def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk),
  1320. (AMMAX_DB_DU GPR:$rk, GPR:$rj)>;
  1321. def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk),
  1322. (AMMIN_DB_W GPR:$rk, GPR:$rj)>;
  1323. def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk),
  1324. (AMMIN_DB_D GPR:$rk, GPR:$rj)>;
  1325. def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk),
  1326. (AMMAX_DB_W GPR:$rk, GPR:$rj)>;
  1327. def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk),
  1328. (AMMAX_DB_D GPR:$rk, GPR:$rj)>;
  1329. def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64,
  1330. PseudoMaskedAtomicLoadUMax32>;
  1331. def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64,
  1332. PseudoMaskedAtomicLoadUMin32>;
  1333. def : Pat<(atomic_cmp_swap_64 GPR:$addr, GPR:$cmp, GPR:$new),
  1334. (PseudoCmpXchg64 GPR:$addr, GPR:$cmp, GPR:$new)>;
  1335. def : Pat<(int_loongarch_masked_cmpxchg_i64
  1336. GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
  1337. (PseudoMaskedCmpXchg32
  1338. GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
  1339. def : Pat<(atomic_cmp_swap_32 GPR:$addr, GPR:$cmp, GPR:$new),
  1340. (PseudoCmpXchg32 GPR:$addr, GPR:$cmp, GPR:$new)>;
  1341. def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64,
  1342. PseudoMaskedAtomicLoadMax32>;
  1343. def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64,
  1344. PseudoMaskedAtomicLoadMin32>;
  1345. } // Predicates = [IsLA64]
  1346. defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>;
  1347. let Predicates = [IsLA32] in {
  1348. def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32,
  1349. PseudoMaskedAtomicSwap32>;
  1350. defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>;
  1351. def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32,
  1352. PseudoMaskedAtomicLoadAdd32>;
  1353. def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32,
  1354. PseudoMaskedAtomicLoadSub32>;
  1355. def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32,
  1356. PseudoMaskedAtomicLoadNand32>;
  1357. defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>;
  1358. defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>;
  1359. defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>;
  1360. defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>;
  1361. defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>;
  1362. } // Predicates = [IsLA32]
  1363. /// Intrinsics
  1364. def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12),
  1365. (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>;
  1366. def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12),
  1367. (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>;
  1368. def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
  1369. def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
  1370. def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
  1371. def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
  1372. let Predicates = [IsLA64] in {
  1373. // CRC Check Instructions
  1374. def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>;
  1375. def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>;
  1376. def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>;
  1377. def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>;
  1378. def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>;
  1379. def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>;
  1380. def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>;
  1381. def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>;
  1382. } // Predicates = [IsLA64]
  1383. /// Other pseudo-instructions
  1384. // Pessimistically assume the stack pointer will be clobbered
  1385. let Defs = [R3], Uses = [R3] in {
  1386. def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
  1387. [(callseq_start timm:$amt1, timm:$amt2)]>;
  1388. def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
  1389. [(callseq_end timm:$amt1, timm:$amt2)]>;
  1390. } // Defs = [R3], Uses = [R3]
  1391. //===----------------------------------------------------------------------===//
  1392. // Assembler Pseudo Instructions
  1393. //===----------------------------------------------------------------------===//
  1394. def : InstAlias<"nop", (ANDI R0, R0, 0)>;
  1395. def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
  1396. // `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and
  1397. // later).
  1398. def : InstAlias<"ret", (JIRL R0, R1, 0)>;
  1399. def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>;
  1400. // Branches implemented with alias.
  1401. // Always output the canonical mnemonic for the pseudo branch instructions.
  1402. // The GNU tools emit the canonical mnemonic for the branch pseudo instructions
  1403. // as well (e.g. "bgt" will be recognised by the assembler but never printed by
  1404. // objdump). Match this behaviour by setting a zero weight.
  1405. def : InstAlias<"bgt $rj, $rd, $imm16",
  1406. (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1407. def : InstAlias<"bgtu $rj, $rd, $imm16",
  1408. (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1409. def : InstAlias<"ble $rj, $rd, $imm16",
  1410. (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1411. def : InstAlias<"bleu $rj, $rd, $imm16",
  1412. (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1413. def : InstAlias<"bltz $rd, $imm16",
  1414. (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
  1415. def : InstAlias<"bgtz $rj, $imm16",
  1416. (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1417. def : InstAlias<"blez $rj, $imm16",
  1418. (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>;
  1419. def : InstAlias<"bgez $rd, $imm16",
  1420. (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>;
  1421. // Load immediate.
  1422. let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
  1423. isAsmParserOnly = 1 in {
  1424. def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [],
  1425. "li.w", "$rd, $imm">;
  1426. def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [],
  1427. "li.d", "$rd, $imm">, Requires<[IsLA64]>;
  1428. }
  1429. //===----------------------------------------------------------------------===//
  1430. // Basic Floating-Point Instructions
  1431. //===----------------------------------------------------------------------===//
  1432. include "LoongArchFloat32InstrInfo.td"
  1433. include "LoongArchFloat64InstrInfo.td"
  1434. let Predicates = [HasBasicF], usesCustomInserter = 1 in {
  1435. def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src),
  1436. [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>;
  1437. def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr),
  1438. [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>;
  1439. }
  1440. //===----------------------------------------------------------------------===//
  1441. // Privilege Instructions
  1442. //===----------------------------------------------------------------------===//
  1443. // CSR Access Instructions
  1444. def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num),
  1445. "csrrd", "$rd, $csr_num">;
  1446. let Constraints = "$rd = $dst" in {
  1447. def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst),
  1448. (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">;
  1449. def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst),
  1450. (ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
  1451. "csrxchg", "$rd, $rj, $csr_num">;
  1452. } // Constraints = "$rd = $dst"
  1453. // IOCSR Access Instructions
  1454. def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">;
  1455. def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">;
  1456. def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">;
  1457. def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">;
  1458. def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">;
  1459. def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">;
  1460. let Predicates = [IsLA64] in {
  1461. def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">;
  1462. def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">;
  1463. } // Predicates = [IsLA64]
  1464. // TLB Maintenance Instructions
  1465. def TLBSRCH : FmtI32<0b00000110010010000010100000000000, "tlbsrch">;
  1466. def TLBRD : FmtI32<0b00000110010010000010110000000000, "tlbrd">;
  1467. def TLBWR : FmtI32<0b00000110010010000011000000000000, "tlbwr">;
  1468. def TLBFILL : FmtI32<0b00000110010010000011010000000000, "tlbfill">;
  1469. def TLBCLR : FmtI32<0b00000110010010000010000000000000, "tlbclr">;
  1470. def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">;
  1471. def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb",
  1472. "$op, $rj, $rk">;
  1473. // Software Page Walking Instructions
  1474. def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd),
  1475. (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">;
  1476. def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">;
  1477. // Other Miscellaneous Instructions
  1478. def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">;
  1479. def DBCL : MISC_I15<0b00000000001010101, "dbcl">;
  1480. def IDLE : MISC_I15<0b00000110010010001, "idle">;
  1481. //===----------------------------------------------------------------------===//
  1482. // Privilege Intrinsics
  1483. //===----------------------------------------------------------------------===//
  1484. def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>;
  1485. def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
  1486. (CSRWR GPR:$rd, uimm14:$imm14)>;
  1487. def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
  1488. (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
  1489. def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
  1490. def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>;
  1491. def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>;
  1492. def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>;
  1493. def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>;
  1494. def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>;
  1495. def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>;
  1496. let Predicates = [IsLA64] in {
  1497. def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>;
  1498. def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>;
  1499. def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk),
  1500. (ASRTLE_D GPR:$rj, GPR:$rk)>;
  1501. def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk),
  1502. (ASRTGT_D GPR:$rj, GPR:$rk)>;
  1503. def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8),
  1504. (LDDIR GPR:$rj, uimm8:$imm8)>;
  1505. def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8),
  1506. (LDPTE GPR:$rj, uimm8:$imm8)>;
  1507. } // Predicates = [IsLA64]