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//===----------------------------------------------------------------------===//
14// LoongArch specific DAG Nodes.
15//===----------------------------------------------------------------------===//
16
17// Target-independent type requirements, but with target-specific formats.
18def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
19                                       SDTCisVT<1, i32>]>;
20def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
21                                   SDTCisVT<1, i32>]>;
22
23// Target-dependent type requirements.
24def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>;
25def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [
26  SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>
27]>;
28
29def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [
30  SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>,
31  SDTCisSameAs<3, 4>
32]>;
33
34def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [
35  SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3>
36]>;
37
38// TODO: Add LoongArch specific DAG Nodes
39// Target-independent nodes, but with target-specific formats.
40def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
41                           [SDNPHasChain, SDNPOutGlue]>;
42def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
43                         [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
44
45// Target-dependent nodes.
46def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall,
47                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
48                             SDNPVariadic]>;
49def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone,
50                           [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
51def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>;
52def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>;
53def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>;
54def loongarch_bstrins
55    : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>;
56def loongarch_bstrpick
57    : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>;
58
59//===----------------------------------------------------------------------===//
60// Operand and SDNode transformation definitions.
61//===----------------------------------------------------------------------===//
62
63class ImmAsmOperand<string prefix, int width, string suffix>
64    : AsmOperandClass {
65  let Name = prefix # "Imm" # width # suffix;
66  let DiagnosticType = !strconcat("Invalid", Name);
67  let RenderMethod = "addImmOperands";
68}
69
70class SImmAsmOperand<int width, string suffix = "">
71    : ImmAsmOperand<"S", width, suffix> {
72}
73
74class UImmAsmOperand<int width, string suffix = "">
75    : ImmAsmOperand<"U", width, suffix> {
76}
77
78def uimm2 : Operand<GRLenVT> {
79  let ParserMatchClass = UImmAsmOperand<2>;
80}
81
82def uimm2_plus1 : Operand<GRLenVT> {
83  let ParserMatchClass = UImmAsmOperand<2, "plus1">;
84  let EncoderMethod = "getImmOpValueSub1";
85  let DecoderMethod = "decodeUImmOperand<2, 1>";
86}
87
88def uimm3 : Operand<GRLenVT> {
89  let ParserMatchClass = UImmAsmOperand<3>;
90}
91
92def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> {
93  let ParserMatchClass = UImmAsmOperand<5>;
94}
95
96def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> {
97  let ParserMatchClass = UImmAsmOperand<6>;
98}
99
100def uimm8 : Operand<GRLenVT> {
101  let ParserMatchClass = UImmAsmOperand<8>;
102}
103
104def uimm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<12>(Imm);}]> {
105  let ParserMatchClass = UImmAsmOperand<12>;
106}
107
108def uimm14 : Operand<GRLenVT> {
109  let ParserMatchClass = UImmAsmOperand<14>;
110}
111
112def uimm15 : Operand<GRLenVT> {
113  let ParserMatchClass = UImmAsmOperand<15>;
114}
115
116def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]> {
117  let ParserMatchClass = SImmAsmOperand<12>;
118  let DecoderMethod = "decodeSImmOperand<12>";
119}
120
121def simm14_lsl2 : Operand<GRLenVT> {
122  let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
123  let EncoderMethod = "getImmOpValueAsr2";
124  let DecoderMethod = "decodeSImmOperand<14, 2>";
125}
126
127def simm16 : Operand<GRLenVT> {
128  let ParserMatchClass = SImmAsmOperand<16>;
129  let DecoderMethod = "decodeSImmOperand<16>";
130}
131
132def simm16_lsl2 : Operand<GRLenVT>,
133    ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> {
134  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
135  let EncoderMethod = "getImmOpValueAsr2";
136  let DecoderMethod = "decodeSImmOperand<16, 2>";
137}
138
139def simm16_lsl2_br : Operand<OtherVT> {
140  let ParserMatchClass = SImmAsmOperand<16, "lsl2">;
141  let EncoderMethod = "getImmOpValueAsr2";
142  let DecoderMethod = "decodeSImmOperand<16, 2>";
143}
144
145def simm20 : Operand<GRLenVT> {
146  let ParserMatchClass = SImmAsmOperand<20>;
147  let DecoderMethod = "decodeSImmOperand<20>";
148}
149
150def simm21_lsl2 : Operand<OtherVT> {
151  let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
152  let EncoderMethod = "getImmOpValueAsr2";
153  let DecoderMethod = "decodeSImmOperand<21, 2>";
154}
155
156def simm26_lsl2 : Operand<OtherVT> {
157  let ParserMatchClass = SImmAsmOperand<26, "lsl2">;
158  let EncoderMethod = "getImmOpValueAsr2";
159  let DecoderMethod = "decodeSImmOperand<26, 2>";
160}
161
162// Standalone (codegen-only) immleaf patterns.
163
164// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048].
165def simm12_plus1 : ImmLeaf<GRLenVT,
166  [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>;
167
168// Return the negation of an immediate value.
169def NegImm : SDNodeXForm<imm, [{
170  return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
171                                   N->getValueType(0));
172}]>;
173
174// FP immediate patterns.
175def fpimm0    : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
176def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
177def fpimm1    : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>;
178
179def CallSymbol: AsmOperandClass {
180  let Name = "CallSymbol";
181  let RenderMethod = "addImmOperands";
182  let PredicateMethod = "isImm";
183}
184
185// A bare symbol used in call only.
186def call_symbol : Operand<iPTR> {
187  let ParserMatchClass = CallSymbol;
188}
189
190def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
191
192//===----------------------------------------------------------------------===//
193// Instruction Formats
194//===----------------------------------------------------------------------===//
195
196include "LoongArchInstrFormats.td"
197include "LoongArchFloatInstrFormats.td"
198
199//===----------------------------------------------------------------------===//
200// Instruction Class Templates
201//===----------------------------------------------------------------------===//
202
203class ALU_3R<bits<17> op, string opstr>
204    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
205class ALU_2R<bits<22> op, string opstr>
206    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
207
208class ALU_3RI2<bits<15> op, string opstr, Operand ImmOpnd>
209    : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2), opstr,
210              "$rd, $rj, $rk, $imm2">;
211class ALU_3RI3<bits<14> op, string opstr, Operand ImmOpnd>
212    : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3), opstr,
213              "$rd, $rj, $rk, $imm3">;
214class ALU_2RI5<bits<17> op, string opstr, Operand ImmOpnd>
215    : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5), opstr,
216              "$rd, $rj, $imm5">;
217class ALU_2RI6<bits<16> op, string opstr, Operand ImmOpnd>
218    : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6), opstr,
219              "$rd, $rj, $imm6">;
220class ALU_2RI12<bits<10> op, string opstr, Operand ImmOpnd>
221    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12), opstr,
222               "$rd, $rj, $imm12">;
223class ALU_2RI16<bits<6> op, string opstr, Operand ImmOpnd>
224    : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16), opstr,
225               "$rd, $rj, $imm16">;
226class ALU_1RI20<bits<7> op, string opstr, Operand ImmOpnd>
227    : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), opstr, "$rd, $imm20">;
228
229class MISC_I15<bits<17> op, string opstr>
230    : FmtI15<op, (outs), (ins uimm15:$imm15), opstr, "$imm15">;
231
232class RDTIME_2R<bits<22> op, string opstr>
233    : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), opstr, "$rd, $rj">;
234
235class BrCC_2RI16<bits<6> op, string opstr>
236    : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16), opstr,
237               "$rj, $rd, $imm16"> {
238  let isBranch = 1;
239  let isTerminator = 1;
240}
241class BrCCZ_1RI21<bits<6> op, string opstr>
242    : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21), opstr,
243               "$rj, $imm21"> {
244  let isBranch = 1;
245  let isTerminator = 1;
246}
247class Br_I26<bits<6> op, string opstr>
248    : FmtI26<op, (outs), (ins simm26_lsl2:$imm26), opstr, "$imm26"> {
249  let isBranch = 1;
250  let isTerminator = 1;
251}
252
253let mayLoad = 1 in {
254class LOAD_3R<bits<17> op, string opstr>
255    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
256class LOAD_2RI12<bits<10> op, string opstr>
257    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12:$imm12), opstr,
258               "$rd, $rj, $imm12">;
259class LOAD_2RI14<bits<8> op, string opstr>
260    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
261               "$rd, $rj, $imm14">;
262} // mayLoad = 1
263
264let mayStore = 1 in {
265class STORE_3R<bits<17> op, string opstr>
266    : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr,
267            "$rd, $rj, $rk">;
268class STORE_2RI12<bits<10> op, string opstr>
269    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12:$imm12), opstr,
270               "$rd, $rj, $imm12">;
271class STORE_2RI14<bits<8> op, string opstr>
272    : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr,
273               "$rd, $rj, $imm14">;
274} // mayStore = 1
275
276let mayLoad = 1, mayStore = 1 in
277class AM_3R<bits<17> op, string opstr>
278    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPR:$rj), opstr, "$rd, $rk, $rj">;
279
280let mayLoad = 1 in
281class LLBase<bits<8> op, string opstr>
282    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
283               "$rd, $rj, $imm14">;
284
285let mayStore = 1, Constraints = "$rd = $dst" in
286class SCBase<bits<8> op, string opstr>
287    : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
288               opstr, "$rd, $rj, $imm14">;
289
290class IOCSRRD<bits<22> op, string opstr>
291    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), opstr, "$rd, $rj">;
292
293class IOCSRWR<bits<22> op, string opstr>
294    : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), opstr, "$rd, $rj">;
295
296//===----------------------------------------------------------------------===//
297// Basic Integer Instructions
298//===----------------------------------------------------------------------===//
299
300// Arithmetic Operation Instructions
301def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
302def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
303def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>;
304def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
305def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>;
306def SLT  : ALU_3R<0b00000000000100100, "slt">;
307def SLTU : ALU_3R<0b00000000000100101, "sltu">;
308def SLTI  : ALU_2RI12<0b0000001000, "slti", simm12>;
309def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>;
310def PCADDI    : ALU_1RI20<0b0001100, "pcaddi", simm20>;
311def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>;
312def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20>;
313def AND  : ALU_3R<0b00000000000101001, "and">;
314def OR   : ALU_3R<0b00000000000101010, "or">;
315def NOR  : ALU_3R<0b00000000000101000, "nor">;
316def XOR  : ALU_3R<0b00000000000101011, "xor">;
317def ANDN : ALU_3R<0b00000000000101101, "andn">;
318def ORN  : ALU_3R<0b00000000000101100, "orn">;
319def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
320def ORI  : ALU_2RI12<0b0000001110, "ori", uimm12>;
321def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
322def MUL_W   : ALU_3R<0b00000000000111000, "mul.w">;
323def MULH_W  : ALU_3R<0b00000000000111001, "mulh.w">;
324def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">;
325let usesCustomInserter = true in {
326def DIV_W   : ALU_3R<0b00000000001000000, "div.w">;
327def MOD_W   : ALU_3R<0b00000000001000001, "mod.w">;
328def DIV_WU  : ALU_3R<0b00000000001000010, "div.wu">;
329def MOD_WU  : ALU_3R<0b00000000001000011, "mod.wu">;
330} // usesCustomInserter = true
331
332// Bit-shift Instructions
333def SLL_W  : ALU_3R<0b00000000000101110, "sll.w">;
334def SRL_W  : ALU_3R<0b00000000000101111, "srl.w">;
335def SRA_W  : ALU_3R<0b00000000000110000, "sra.w">;
336def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">;
337
338def SLLI_W  : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>;
339def SRLI_W  : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>;
340def SRAI_W  : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>;
341def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>;
342
343// Bit-manipulation Instructions
344def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">;
345def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">;
346def CLO_W   : ALU_2R<0b0000000000000000000100, "clo.w">;
347def CLZ_W   : ALU_2R<0b0000000000000000000101, "clz.w">;
348def CTO_W   : ALU_2R<0b0000000000000000000110, "cto.w">;
349def CTZ_W   : ALU_2R<0b0000000000000000000111, "ctz.w">;
350def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>;
351def REVB_2H   : ALU_2R<0b0000000000000000001100, "revb.2h">;
352def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">;
353def BITREV_W  : ALU_2R<0b0000000000000000010100, "bitrev.w">;
354let Constraints = "$rd = $dst" in {
355def BSTRINS_W  : FmtBSTR_W<0b000000000110, (outs GPR:$dst),
356                           (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
357                           "bstrins.w", "$rd, $rj, $msbw, $lsbw">;
358}
359def BSTRPICK_W : FmtBSTR_W<0b000000000111, (outs GPR:$rd),
360                           (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw),
361                           "bstrpick.w", "$rd, $rj, $msbw, $lsbw">;
362def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">;
363def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">;
364
365// Branch Instructions
366def BEQ  : BrCC_2RI16<0b010110, "beq">;
367def BNE  : BrCC_2RI16<0b010111, "bne">;
368def BLT  : BrCC_2RI16<0b011000, "blt">;
369def BGE  : BrCC_2RI16<0b011001, "bge">;
370def BLTU : BrCC_2RI16<0b011010, "bltu">;
371def BGEU : BrCC_2RI16<0b011011, "bgeu">;
372def BEQZ : BrCCZ_1RI21<0b010000, "beqz">;
373def BNEZ : BrCCZ_1RI21<0b010001, "bnez">;
374def B : Br_I26<0b010100, "b">;
375
376let isCall = 1 in
377def BL : FmtI26<0b010101, (outs), (ins simm26_lsl2:$imm26), "bl", "$imm26">;
378def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd),
379                    (ins GPR:$rj, simm16_lsl2:$imm16), "jirl",
380                    "$rd, $rj, $imm16">;
381
382// Common Memory Access Instructions
383def LD_B  : LOAD_2RI12<0b0010100000, "ld.b">;
384def LD_H  : LOAD_2RI12<0b0010100001, "ld.h">;
385def LD_W  : LOAD_2RI12<0b0010100010, "ld.w">;
386def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">;
387def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">;
388def ST_B : STORE_2RI12<0b0010100100, "st.b">;
389def ST_H : STORE_2RI12<0b0010100101, "st.h">;
390def ST_W : STORE_2RI12<0b0010100110, "st.w">;
391def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), "preld",
392                     "$imm5, $rj, $imm12">;
393
394// Atomic Memory Access Instructions
395def LL_W : LLBase<0b00100000, "ll.w">;
396def SC_W : SCBase<0b00100001, "sc.w">;
397
398// Barrier Instructions
399def DBAR : MISC_I15<0b00111000011100100, "dbar">;
400def IBAR : MISC_I15<0b00111000011100101, "ibar">;
401
402// Other Miscellaneous Instructions
403def SYSCALL : MISC_I15<0b00000000001010110, "syscall">;
404def BREAK   : MISC_I15<0b00000000001010100, "break">;
405def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">;
406def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">;
407def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">;
408
409/// LA64 instructions
410
411let Predicates = [IsLA64] in {
412
413// Arithmetic Operation Instructions for 64-bits
414def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
415def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
416def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>;
417def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
418def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
419def ALSL_D  : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
420let Constraints = "$rd = $dst" in {
421def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst),
422                       (ins GPR:$rd, simm20:$imm20), "lu32i.d",
423                       "$rd, $imm20">;
424}
425def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>;
426def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
427def MUL_D     : ALU_3R<0b00000000000111011, "mul.d">;
428def MULH_D    : ALU_3R<0b00000000000111100, "mulh.d">;
429def MULH_DU   : ALU_3R<0b00000000000111101, "mulh.du">;
430def MULW_D_W  : ALU_3R<0b00000000000111110, "mulw.d.w">;
431def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">;
432let usesCustomInserter = true in {
433def DIV_D     : ALU_3R<0b00000000001000100, "div.d">;
434def MOD_D     : ALU_3R<0b00000000001000101, "mod.d">;
435def DIV_DU    : ALU_3R<0b00000000001000110, "div.du">;
436def MOD_DU    : ALU_3R<0b00000000001000111, "mod.du">;
437} // usesCustomInserter = true
438
439// Bit-shift Instructions for 64-bits
440def SLL_D  : ALU_3R<0b00000000000110001, "sll.d">;
441def SRL_D  : ALU_3R<0b00000000000110010, "srl.d">;
442def SRA_D  : ALU_3R<0b00000000000110011, "sra.d">;
443def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">;
444def SLLI_D  : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>;
445def SRLI_D  : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>;
446def SRAI_D  : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>;
447def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>;
448
449// Bit-manipulation Instructions for 64-bits
450def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">;
451def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">;
452def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">;
453def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">;
454def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>;
455def REVB_4H   : ALU_2R<0b0000000000000000001101, "revb.4h">;
456def REVB_2W   : ALU_2R<0b0000000000000000001110, "revb.2w">;
457def REVB_D    : ALU_2R<0b0000000000000000001111, "revb.d">;
458def REVH_2W   : ALU_2R<0b0000000000000000010000, "revh.2w">;
459def REVH_D    : ALU_2R<0b0000000000000000010001, "revh.d">;
460def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">;
461def BITREV_D  : ALU_2R<0b0000000000000000010101, "bitrev.d">;
462let Constraints = "$rd = $dst" in {
463def BSTRINS_D  : FmtBSTR_D<0b0000000010, (outs GPR:$dst),
464                           (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
465                           "bstrins.d", "$rd, $rj, $msbd, $lsbd">;
466}
467def BSTRPICK_D : FmtBSTR_D<0b0000000011, (outs GPR:$rd),
468                           (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
469                           "bstrpick.d", "$rd, $rj, $msbd, $lsbd">;
470
471// Common Memory Access Instructions for 64-bits
472def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">;
473def LD_D  : LOAD_2RI12<0b0010100011, "ld.d">;
474def ST_D : STORE_2RI12<0b0010100111, "st.d">;
475def LDX_B  : LOAD_3R<0b00111000000000000, "ldx.b">;
476def LDX_H  : LOAD_3R<0b00111000000001000, "ldx.h">;
477def LDX_W  : LOAD_3R<0b00111000000010000, "ldx.w">;
478def LDX_D  : LOAD_3R<0b00111000000011000, "ldx.d">;
479def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">;
480def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">;
481def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">;
482def STX_B : STORE_3R<0b00111000000100000, "stx.b">;
483def STX_H : STORE_3R<0b00111000000101000, "stx.h">;
484def STX_W : STORE_3R<0b00111000000110000, "stx.w">;
485def STX_D : STORE_3R<0b00111000000111000, "stx.d">;
486def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">;
487def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">;
488def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">;
489def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">;
490def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), "preldx",
491                       "$imm5, $rj, $rk">;
492
493// Bound Check Memory Access Instructions
494def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">;
495def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">;
496def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">;
497def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">;
498def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">;
499def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">;
500def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">;
501def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">;
502def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">;
503def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">;
504def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">;
505def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">;
506def STLE_B : STORE_3R<0b00111000011111100, "stle.b">;
507def STLE_H : STORE_3R<0b00111000011111101, "stle.h">;
508def STLE_W : STORE_3R<0b00111000011111110, "stle.w">;
509def STLE_D : STORE_3R<0b00111000011111111, "stle.d">;
510
511// Atomic Memory Access Instructions for 64-bits
512def AMSWAP_W    : AM_3R<0b00111000011000000, "amswap.w">;
513def AMSWAP_D    : AM_3R<0b00111000011000001, "amswap.d">;
514def AMADD_W     : AM_3R<0b00111000011000010, "amadd.w">;
515def AMADD_D     : AM_3R<0b00111000011000011, "amadd.d">;
516def AMAND_W     : AM_3R<0b00111000011000100, "amand.w">;
517def AMAND_D     : AM_3R<0b00111000011000101, "amand.d">;
518def AMOR_W      : AM_3R<0b00111000011000110, "amor.w">;
519def AMOR_D      : AM_3R<0b00111000011000111, "amor.d">;
520def AMXOR_W     : AM_3R<0b00111000011001000, "amxor.w">;
521def AMXOR_D     : AM_3R<0b00111000011001001, "amxor.d">;
522def AMMAX_W     : AM_3R<0b00111000011001010, "ammax.w">;
523def AMMAX_D     : AM_3R<0b00111000011001011, "ammax.d">;
524def AMMIN_W     : AM_3R<0b00111000011001100, "ammin.w">;
525def AMMIN_D     : AM_3R<0b00111000011001101, "ammin.d">;
526def AMMAX_WU    : AM_3R<0b00111000011001110, "ammax.wu">;
527def AMMAX_DU    : AM_3R<0b00111000011001111, "ammax.du">;
528def AMMIN_WU    : AM_3R<0b00111000011010000, "ammin.wu">;
529def AMMIN_DU    : AM_3R<0b00111000011010001, "ammin.du">;
530def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">;
531def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">;
532def AMADD_DB_W  : AM_3R<0b00111000011010100, "amadd_db.w">;
533def AMADD_DB_D  : AM_3R<0b00111000011010101, "amadd_db.d">;
534def AMAND_DB_W  : AM_3R<0b00111000011010110, "amand_db.w">;
535def AMAND_DB_D  : AM_3R<0b00111000011010111, "amand_db.d">;
536def AMOR_DB_W   : AM_3R<0b00111000011011000, "amor_db.w">;
537def AMOR_DB_D   : AM_3R<0b00111000011011001, "amor_db.d">;
538def AMXOR_DB_W  : AM_3R<0b00111000011011010, "amxor_db.w">;
539def AMXOR_DB_D  : AM_3R<0b00111000011011011, "amxor_db.d">;
540def AMMAX_DB_W  : AM_3R<0b00111000011011100, "ammax_db.w">;
541def AMMAX_DB_D  : AM_3R<0b00111000011011101, "ammax_db.d">;
542def AMMIN_DB_W  : AM_3R<0b00111000011011110, "ammin_db.w">;
543def AMMIN_DB_D  : AM_3R<0b00111000011011111, "ammin_db.d">;
544def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">;
545def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">;
546def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">;
547def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">;
548def LL_D : LLBase<0b00100010, "ll.d">;
549def SC_D : SCBase<0b00100011, "sc.d">;
550
551// CRC Check Instructions
552def CRC_W_B_W  : ALU_3R<0b00000000001001000, "crc.w.b.w">;
553def CRC_W_H_W  : ALU_3R<0b00000000001001001, "crc.w.h.w">;
554def CRC_W_W_W  : ALU_3R<0b00000000001001010, "crc.w.w.w">;
555def CRC_W_D_W  : ALU_3R<0b00000000001001011, "crc.w.d.w">;
556def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">;
557def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">;
558def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">;
559def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">;
560
561// Other Miscellaneous Instructions for 64-bits
562def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk),
563                       "asrtle.d", "$rj, $rk">;
564def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk),
565                       "asrtgt.d", "$rj, $rk">;
566def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">;
567} // Predicates = [IsLA64]
568
569//===----------------------------------------------------------------------===//
570// Pseudo-instructions and codegen patterns
571//
572// Naming convention: For 'generic' pattern classes, we use the naming
573// convention PatTy1Ty2.
574//===----------------------------------------------------------------------===//
575
576/// Generic pattern classes
577
578class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
579    : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
580class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
581    : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
582
583class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
584    : Pat<(OpNode GPR:$rj, ImmOpnd:$imm),
585          (Inst GPR:$rj, ImmOpnd:$imm)>;
586class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
587    : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
588          (Inst GPR:$rj, ImmOpnd:$imm)>;
589
590/// Simple arithmetic operations
591
592// Match both a plain shift and one where the shift amount is masked (this is
593// typically introduced when the legalizer promotes the shift amount and
594// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the
595// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64).
596def shiftMaskGRLen
597    : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>;
598def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
599
600def sexti32 : ComplexPattern<i64, 1, "selectSExti32">;
601def zexti32 : ComplexPattern<i64, 1, "selectZExti32">;
602
603class shiftop<SDPatternOperator operator>
604    : PatFrag<(ops node:$val, node:$count),
605              (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>;
606class shiftopw<SDPatternOperator operator>
607    : PatFrag<(ops node:$val, node:$count),
608              (operator node:$val, (i64 (shiftMask32 node:$count)))>;
609
610let Predicates = [IsLA32] in {
611def : PatGprGpr<add, ADD_W>;
612def : PatGprImm<add, ADDI_W, simm12>;
613def : PatGprGpr<sub, SUB_W>;
614def : PatGprGpr<sdiv, DIV_W>;
615def : PatGprGpr<udiv, DIV_WU>;
616def : PatGprGpr<srem, MOD_W>;
617def : PatGprGpr<urem, MOD_WU>;
618def : PatGprGpr<mul, MUL_W>;
619def : PatGprGpr<mulhs, MULH_W>;
620def : PatGprGpr<mulhu, MULH_WU>;
621} // Predicates = [IsLA32]
622
623let Predicates = [IsLA64] in {
624def : PatGprGpr<add, ADD_D>;
625def : PatGprGpr_32<add, ADD_W>;
626def : PatGprImm<add, ADDI_D, simm12>;
627def : PatGprImm_32<add, ADDI_W, simm12>;
628def : PatGprGpr<sub, SUB_D>;
629def : PatGprGpr_32<sub, SUB_W>;
630def : PatGprGpr<sdiv, DIV_D>;
631def : PatGprGpr<udiv, DIV_DU>;
632def : PatGprGpr<srem, MOD_D>;
633def : PatGprGpr<urem, MOD_DU>;
634// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the
635// product are used.
636def : PatGprGpr<mul, MUL_D>;
637def : PatGprGpr<mulhs, MULH_D>;
638def : PatGprGpr<mulhu, MULH_DU>;
639// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed
640// multiplication.
641def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))),
642          (MULW_D_W GPR:$rj, GPR:$rk)>;
643// Select MULW_D_WU for calculating the full 64 bits product of i32xi32
644// unsigned multiplication.
645def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)),
646                    (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))),
647          (MULW_D_WU GPR:$rj, GPR:$rk)>;
648} // Predicates = [IsLA64]
649
650def : PatGprGpr<and, AND>;
651def : PatGprImm<and, ANDI, uimm12>;
652def : PatGprGpr<or, OR>;
653def : PatGprImm<or, ORI, uimm12>;
654def : PatGprGpr<xor, XOR>;
655def : PatGprImm<xor, XORI, uimm12>;
656
657/// Shift
658
659let Predicates = [IsLA32] in {
660def : PatGprGpr<shiftop<shl>, SLL_W>;
661def : PatGprGpr<shiftop<sra>, SRA_W>;
662def : PatGprGpr<shiftop<srl>, SRL_W>;
663def : PatGprImm<shl, SLLI_W, uimm5>;
664def : PatGprImm<sra, SRAI_W, uimm5>;
665def : PatGprImm<srl, SRLI_W, uimm5>;
666} // Predicates = [IsLA32]
667
668let Predicates = [IsLA64] in {
669def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>;
670def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>;
671def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>;
672def : PatGprGpr<shiftop<shl>, SLL_D>;
673def : PatGprGpr<shiftop<sra>, SRA_D>;
674def : PatGprGpr<shiftop<srl>, SRL_D>;
675def : PatGprImm<shl, SLLI_D, uimm6>;
676def : PatGprImm<sra, SRAI_D, uimm6>;
677def : PatGprImm<srl, SRLI_D, uimm6>;
678} // Predicates = [IsLA64]
679
680/// sext and zext
681
682def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>;
683def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>;
684
685let Predicates = [IsLA64] in {
686def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
687} // Predicates = [IsLA64]
688
689/// Setcc
690
691def : PatGprGpr<setlt, SLT>;
692def : PatGprImm<setlt, SLTI, simm12>;
693def : PatGprGpr<setult, SLTU>;
694def : PatGprImm<setult, SLTUI, simm12>;
695
696// Define pattern expansions for setcc operations that aren't directly
697// handled by a LoongArch instruction.
698def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>;
699def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>;
700let Predicates = [IsLA32] in {
701def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
702          (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
703} // Predicates = [IsLA32]
704let Predicates = [IsLA64] in {
705def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12),
706          (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>;
707} // Predicates = [IsLA64]
708def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>;
709def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>;
710let Predicates = [IsLA32] in {
711def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
712          (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
713} // Predicates = [IsLA32]
714let Predicates = [IsLA64] in {
715def : Pat<(setne GPR:$rj, simm12_plus1:$imm12),
716          (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>;
717} // Predicates = [IsLA64]
718def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>;
719def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>;
720def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>;
721def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>;
722def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>;
723def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>;
724
725/// Select
726
727def : Pat<(select GPR:$cond, GPR:$t, GPR:$f),
728          (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>;
729
730/// Branches and jumps
731
732class BccPat<PatFrag CondOp, LAInst Inst>
733    : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16),
734          (Inst GPR:$rj, GPR:$rd, bb:$imm16)>;
735
736def : BccPat<seteq, BEQ>;
737def : BccPat<setne, BNE>;
738def : BccPat<setlt, BLT>;
739def : BccPat<setge, BGE>;
740def : BccPat<setult, BLTU>;
741def : BccPat<setuge, BGEU>;
742
743class BccSwapPat<PatFrag CondOp, LAInst InstBcc>
744    : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16),
745          (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>;
746
747// Condition codes that don't have matching LoongArch branch instructions, but
748// are trivially supported by swapping the two input operands.
749def : BccSwapPat<setgt, BLT>;
750def : BccSwapPat<setle, BGE>;
751def : BccSwapPat<setugt, BLTU>;
752def : BccSwapPat<setule, BGEU>;
753
754// An extra pattern is needed for a brcond without a setcc (i.e. where the
755// condition was calculated elsewhere).
756def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>;
757
758let isBarrier = 1, isBranch = 1, isTerminator = 1 in
759def PseudoBR : Pseudo<(outs), (ins simm26_lsl2:$imm26), [(br bb:$imm26)]>,
760               PseudoInstExpansion<(B simm26_lsl2:$imm26)>;
761
762let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
763def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16), []>,
764                  PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
765
766def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
767def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
768          (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
769
770let isCall = 1, Defs = [R1] in
771def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> {
772  let AsmString = "bl\t$func";
773}
774
775def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
776def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
777
778let isCall = 1, Defs = [R1] in
779def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
780                                [(loongarch_call GPR:$rj)]>,
781                         PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
782
783let isBarrier = 1, isReturn = 1, isTerminator = 1 in
784def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
785                PseudoInstExpansion<(JIRL R0, R1, 0)>;
786
787/// BSTRINS and BSTRPICK
788
789let Predicates = [IsLA32] in {
790def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
791          (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
792def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd),
793          (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>;
794} // Predicates = [IsLA32]
795
796let Predicates = [IsLA64] in {
797def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
798          (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
799def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
800          (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
801} // Predicates = [IsLA64]
802
803/// Loads
804
805multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
806  def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>;
807  def : Pat<(vt (LoadOp (add BaseAddr:$rj, simm12:$imm12))),
808            (Inst BaseAddr:$rj, simm12:$imm12)>;
809}
810
811defm : LdPat<sextloadi8, LD_B>;
812defm : LdPat<extloadi8, LD_B>;
813defm : LdPat<sextloadi16, LD_H>;
814defm : LdPat<extloadi16, LD_H>;
815defm : LdPat<load, LD_W>, Requires<[IsLA32]>;
816defm : LdPat<zextloadi8, LD_BU>;
817defm : LdPat<zextloadi16, LD_HU>;
818let Predicates = [IsLA64] in {
819defm : LdPat<sextloadi32, LD_W, i64>;
820defm : LdPat<extloadi32, LD_W, i64>;
821defm : LdPat<zextloadi32, LD_WU, i64>;
822defm : LdPat<load, LD_D, i64>;
823} // Predicates = [IsLA64]
824
825/// Stores
826
827multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
828                 ValueType vt> {
829  def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj),
830            (Inst StTy:$rd, BaseAddr:$rj, 0)>;
831  def : Pat<(StoreOp (vt StTy:$rd), (add BaseAddr:$rj, simm12:$imm12)),
832            (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>;
833}
834
835defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
836defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>;
837defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>;
838let Predicates = [IsLA64] in {
839defm : StPat<truncstorei32, ST_W, GPR, i64>;
840defm : StPat<store, ST_D, GPR, i64>;
841} // Predicates = [IsLA64]
842
843/// Atomic loads and stores
844
845def : Pat<(atomic_fence timm, timm), (DBAR 0)>;
846
847defm : LdPat<atomic_load_8, LD_B>;
848defm : LdPat<atomic_load_16, LD_H>;
849defm : LdPat<atomic_load_32, LD_W>;
850
851defm : StPat<atomic_store_8, ST_B, GPR, GRLenVT>;
852defm : StPat<atomic_store_16, ST_H, GPR, GRLenVT>;
853defm : StPat<atomic_store_32, ST_W, GPR, i32>, Requires<[IsLA32]>;
854let Predicates = [IsLA64] in {
855defm : LdPat<atomic_load_64, LD_D>;
856defm : StPat<atomic_store_32, ST_W, GPR, i64>;
857defm : StPat<atomic_store_64, ST_D, GPR, i64>;
858} // Predicates = [IsLA64]
859
860/// Other pseudo-instructions
861
862// Pessimistically assume the stack pointer will be clobbered
863let Defs = [R3], Uses = [R3] in {
864def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
865                              [(callseq_start timm:$amt1, timm:$amt2)]>;
866def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
867                              [(callseq_end timm:$amt1, timm:$amt2)]>;
868} // Defs = [R3], Uses = [R3]
869
870//===----------------------------------------------------------------------===//
871// Assembler Pseudo Instructions
872//===----------------------------------------------------------------------===//
873
874def : InstAlias<"nop", (ANDI R0, R0, 0)>;
875def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
876
877//===----------------------------------------------------------------------===//
878// Basic Floating-Point Instructions
879//===----------------------------------------------------------------------===//
880
881include "LoongArchFloat32InstrInfo.td"
882include "LoongArchFloat64InstrInfo.td"
883
884//===----------------------------------------------------------------------===//
885// Privilege Instructions
886//===----------------------------------------------------------------------===//
887
888// CSR Access Instructions
889def CSRRD : FmtCSR<0b0000010000000, (outs GPR:$rd), (ins uimm14:$csr_num),
890                   "csrrd", "$rd, $csr_num">;
891let Constraints = "$rd = $dst" in {
892def CSRWR : FmtCSR<0b0000010000001, (outs GPR:$dst),
893                   (ins GPR:$rd, uimm14:$csr_num), "csrwr", "$rd, $csr_num">;
894def CSRXCHG : FmtCSRXCHG<0b00000100, (outs GPR:$dst),
895                         (ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
896                         "csrxchg", "$rd, $rj, $csr_num">;
897} // Constraints = "$rd = $dst"
898
899// IOCSR Access Instructions
900def IOCSRRD_B : IOCSRRD<0b0000011001001000000000, "iocsrrd.b">;
901def IOCSRRD_H : IOCSRRD<0b0000011001001000000001, "iocsrrd.h">;
902def IOCSRRD_W : IOCSRRD<0b0000011001001000000010, "iocsrrd.w">;
903def IOCSRWR_B : IOCSRWR<0b0000011001001000000100, "iocsrwr.b">;
904def IOCSRWR_H : IOCSRWR<0b0000011001001000000101, "iocsrwr.h">;
905def IOCSRWR_W : IOCSRWR<0b0000011001001000000110, "iocsrwr.w">;
906let Predicates = [IsLA64] in {
907def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">;
908def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">;
909} // Predicates = [IsLA64]
910
911// Cache Maintenance Instructions
912def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop",
913                     "$op, $rj, $imm12">;
914
915// TLB Maintenance Instructions
916def TLBSRCH  : FmtI32<0b00000110010010000010100000000000, "tlbsrch">;
917def TLBRD    : FmtI32<0b00000110010010000010110000000000, "tlbrd">;
918def TLBWR    : FmtI32<0b00000110010010000011000000000000, "tlbwr">;
919def TLBFILL  : FmtI32<0b00000110010010000011010000000000, "tlbfill">;
920def TLBCLR   : FmtI32<0b00000110010010000010000000000000, "tlbclr">;
921def TLBFLUSH : FmtI32<0b00000110010010000010010000000000, "tlbflush">;
922def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), "invtlb",
923                       "$op, $rj, $rk">;
924
925// Software Page Walking Instructions
926def LDDIR : Fmt2RI8<0b00000110010000, (outs GPR:$rd),
927                    (ins GPR:$rj, uimm8:$imm8), "lddir", "$rd, $rj, $imm8">;
928def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "ldpte", "$rj, $seq">;
929
930
931// Other Miscellaneous Instructions
932def ERTN : FmtI32<0b00000110010010000011100000000000, "ertn">;
933def DBCL : MISC_I15<0b00000000001010101, "dbcl">;
934def IDLE : MISC_I15<0b00000110010010001, "idle">;
935