1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- 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 RISC-V instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// RISC-V 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_RISCVCall     : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;
25def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
26                                             SDTCisSameAs<0, 4>,
27                                             SDTCisSameAs<4, 5>]>;
28
29// Target-independent nodes, but with target-specific formats.
30def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
31                           [SDNPHasChain, SDNPOutGlue]>;
32def callseq_end   : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
33                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
34
35// Target-dependent nodes.
36def riscv_call      : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
37                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
38                              SDNPVariadic]>;
39def riscv_ret_flag  : SDNode<"RISCVISD::RET_FLAG", SDTNone,
40                             [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
41def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone,
42                             [SDNPHasChain, SDNPOptInGlue]>;
43def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone,
44                             [SDNPHasChain, SDNPOptInGlue]>;
45def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", SDTNone,
46                             [SDNPHasChain, SDNPOptInGlue]>;
47def riscv_selectcc  : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC,
48                             [SDNPInGlue]>;
49def riscv_tail      : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
50                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
51                              SDNPVariadic]>;
52def riscv_sllw      : SDNode<"RISCVISD::SLLW", SDTIntShiftOp>;
53def riscv_sraw      : SDNode<"RISCVISD::SRAW", SDTIntShiftOp>;
54def riscv_srlw      : SDNode<"RISCVISD::SRLW", SDTIntShiftOp>;
55
56//===----------------------------------------------------------------------===//
57// Operand and SDNode transformation definitions.
58//===----------------------------------------------------------------------===//
59
60class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
61  let Name = prefix # "ImmXLen" # suffix;
62  let RenderMethod = "addImmOperands";
63  let DiagnosticType = !strconcat("Invalid", Name);
64}
65
66class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
67  let Name = prefix # "Imm" # width # suffix;
68  let RenderMethod = "addImmOperands";
69  let DiagnosticType = !strconcat("Invalid", Name);
70}
71
72class SImmAsmOperand<int width, string suffix = "">
73    : ImmAsmOperand<"S", width, suffix> {
74}
75
76class UImmAsmOperand<int width, string suffix = "">
77    : ImmAsmOperand<"U", width, suffix> {
78}
79
80def FenceArg : AsmOperandClass {
81  let Name = "FenceArg";
82  let RenderMethod = "addFenceArgOperands";
83  let DiagnosticType = "InvalidFenceArg";
84}
85
86def fencearg : Operand<XLenVT> {
87  let ParserMatchClass = FenceArg;
88  let PrintMethod = "printFenceArg";
89  let DecoderMethod = "decodeUImmOperand<4>";
90}
91
92def UImmLog2XLenAsmOperand : AsmOperandClass {
93  let Name = "UImmLog2XLen";
94  let RenderMethod = "addImmOperands";
95  let DiagnosticType = "InvalidUImmLog2XLen";
96}
97
98def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
99  if (Subtarget->is64Bit())
100    return isUInt<6>(Imm);
101  return isUInt<5>(Imm);
102}]> {
103  let ParserMatchClass = UImmLog2XLenAsmOperand;
104  // TODO: should ensure invalid shamt is rejected when decoding.
105  let DecoderMethod = "decodeUImmOperand<6>";
106  let MCOperandPredicate = [{
107    int64_t Imm;
108    if (!MCOp.evaluateAsConstantImm(Imm))
109      return false;
110    if (STI.getTargetTriple().isArch64Bit())
111      return  isUInt<6>(Imm);
112    return isUInt<5>(Imm);
113  }];
114}
115
116def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
117  let ParserMatchClass = UImmAsmOperand<5>;
118  let DecoderMethod = "decodeUImmOperand<5>";
119}
120
121def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
122  let ParserMatchClass = SImmAsmOperand<12>;
123  let EncoderMethod = "getImmOpValue";
124  let DecoderMethod = "decodeSImmOperand<12>";
125  let MCOperandPredicate = [{
126    int64_t Imm;
127    if (MCOp.evaluateAsConstantImm(Imm))
128      return isInt<12>(Imm);
129    return MCOp.isBareSymbolRef();
130  }];
131}
132
133// A 13-bit signed immediate where the least significant bit is zero.
134def simm13_lsb0 : Operand<OtherVT> {
135  let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
136  let EncoderMethod = "getImmOpValueAsr1";
137  let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
138  let MCOperandPredicate = [{
139    int64_t Imm;
140    if (MCOp.evaluateAsConstantImm(Imm))
141      return isShiftedInt<12, 1>(Imm);
142    return MCOp.isBareSymbolRef();
143  }];
144}
145
146class UImm20Operand : Operand<XLenVT> {
147  let EncoderMethod = "getImmOpValue";
148  let DecoderMethod = "decodeUImmOperand<20>";
149  let MCOperandPredicate = [{
150    int64_t Imm;
151    if (MCOp.evaluateAsConstantImm(Imm))
152      return isUInt<20>(Imm);
153    return MCOp.isBareSymbolRef();
154  }];
155}
156
157def uimm20_lui : UImm20Operand {
158  let ParserMatchClass = UImmAsmOperand<20, "LUI">;
159}
160def uimm20_auipc : UImm20Operand {
161  let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
162}
163
164def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
165  let ParserMethod = "parseJALOffset";
166}
167
168// A 21-bit signed immediate where the least significant bit is zero.
169def simm21_lsb0_jal : Operand<OtherVT> {
170  let ParserMatchClass = Simm21Lsb0JALAsmOperand;
171  let EncoderMethod = "getImmOpValueAsr1";
172  let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
173  let MCOperandPredicate = [{
174    int64_t Imm;
175    if (MCOp.evaluateAsConstantImm(Imm))
176      return isShiftedInt<20, 1>(Imm);
177    return MCOp.isBareSymbolRef();
178  }];
179}
180
181def BareSymbol : AsmOperandClass {
182  let Name = "BareSymbol";
183  let RenderMethod = "addImmOperands";
184  let DiagnosticType = "InvalidBareSymbol";
185  let ParserMethod = "parseBareSymbol";
186}
187
188// A bare symbol.
189def bare_symbol : Operand<XLenVT> {
190  let ParserMatchClass = BareSymbol;
191}
192
193def CallSymbol : AsmOperandClass {
194  let Name = "CallSymbol";
195  let RenderMethod = "addImmOperands";
196  let DiagnosticType = "InvalidCallSymbol";
197  let ParserMethod = "parseCallSymbol";
198}
199
200// A bare symbol used in call/tail only.
201def call_symbol : Operand<XLenVT> {
202  let ParserMatchClass = CallSymbol;
203}
204
205def TPRelAddSymbol : AsmOperandClass {
206  let Name = "TPRelAddSymbol";
207  let RenderMethod = "addImmOperands";
208  let DiagnosticType = "InvalidTPRelAddSymbol";
209  let ParserMethod = "parseOperandWithModifier";
210}
211
212// A bare symbol with the %tprel_add variant.
213def tprel_add_symbol : Operand<XLenVT> {
214  let ParserMatchClass = TPRelAddSymbol;
215}
216
217def CSRSystemRegister : AsmOperandClass {
218  let Name = "CSRSystemRegister";
219  let ParserMethod = "parseCSRSystemRegister";
220  let DiagnosticType = "InvalidCSRSystemRegister";
221}
222
223def csr_sysreg : Operand<XLenVT> {
224  let ParserMatchClass = CSRSystemRegister;
225  let PrintMethod = "printCSRSystemRegister";
226  let DecoderMethod = "decodeUImmOperand<12>";
227}
228
229// A parameterized register class alternative to i32imm/i64imm from Target.td.
230def ixlenimm : Operand<XLenVT>;
231
232def ixlenimm_li : Operand<XLenVT> {
233  let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;
234}
235
236// Standalone (codegen-only) immleaf patterns.
237def simm32     : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
238def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>;
239// A mask value that won't affect significant shift bits.
240def immbottomxlenset : ImmLeaf<XLenVT, [{
241  if (Subtarget->is64Bit())
242    return countTrailingOnes<uint64_t>(Imm) >= 6;
243  return countTrailingOnes<uint64_t>(Imm) >= 5;
244}]>;
245
246// Addressing modes.
247// Necessary because a frameindex can't be matched directly in a pattern.
248def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>;
249
250// Extract least significant 12 bits from an immediate value and sign extend
251// them.
252def LO12Sext : SDNodeXForm<imm, [{
253  return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()),
254                                   SDLoc(N), N->getValueType(0));
255}]>;
256
257// Extract the most significant 20 bits from an immediate value. Add 1 if bit
258// 11 is 1, to compensate for the low 12 bits in the matching immediate addi
259// or ld/st being negative.
260def HI20 : SDNodeXForm<imm, [{
261  return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff,
262                                   SDLoc(N), N->getValueType(0));
263}]>;
264
265//===----------------------------------------------------------------------===//
266// Instruction Formats
267//===----------------------------------------------------------------------===//
268
269include "RISCVInstrFormats.td"
270
271//===----------------------------------------------------------------------===//
272// Instruction Class Templates
273//===----------------------------------------------------------------------===//
274
275let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
276class BranchCC_rri<bits<3> funct3, string opcodestr>
277    : RVInstB<funct3, OPC_BRANCH, (outs),
278              (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
279              opcodestr, "$rs1, $rs2, $imm12"> {
280  let isBranch = 1;
281  let isTerminator = 1;
282}
283
284let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
285class Load_ri<bits<3> funct3, string opcodestr>
286    : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
287              opcodestr, "$rd, ${imm12}(${rs1})">;
288
289// Operands for stores are in the order srcreg, base, offset rather than
290// reflecting the order these fields are specified in the instruction
291// encoding.
292let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
293class Store_rri<bits<3> funct3, string opcodestr>
294    : RVInstS<funct3, OPC_STORE, (outs),
295              (ins GPR:$rs2, GPR:$rs1, simm12:$imm12),
296              opcodestr, "$rs2, ${imm12}(${rs1})">;
297
298let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
299class ALU_ri<bits<3> funct3, string opcodestr>
300    : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
301              opcodestr, "$rd, $rs1, $imm12">;
302
303let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
304class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr>
305    : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd),
306                   (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
307                   "$rd, $rs1, $shamt">;
308
309let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
310class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
311    : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
312              opcodestr, "$rd, $rs1, $rs2">;
313
314let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
315class CSR_ir<bits<3> funct3, string opcodestr>
316    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),
317              opcodestr, "$rd, $imm12, $rs1">;
318
319let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
320class CSR_ii<bits<3> funct3, string opcodestr>
321    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
322              (ins csr_sysreg:$imm12, uimm5:$rs1),
323              opcodestr, "$rd, $imm12, $rs1">;
324
325let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
326class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr>
327    : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
328                    (ins GPR:$rs1, uimm5:$shamt), opcodestr,
329                    "$rd, $rs1, $shamt">;
330
331let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
332class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
333    : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
334              (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;
335
336let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
337class Priv<string opcodestr, bits<7> funct7>
338    : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
339              opcodestr, "">;
340
341//===----------------------------------------------------------------------===//
342// Instructions
343//===----------------------------------------------------------------------===//
344
345let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
346let isReMaterializable = 1, isAsCheapAsAMove = 1 in
347def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
348                  "lui", "$rd, $imm20">;
349
350def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
351                    "auipc", "$rd, $imm20">;
352
353let isCall = 1 in
354def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
355                  "jal", "$rd, $imm20">;
356
357let isCall = 1 in
358def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
359                   (ins GPR:$rs1, simm12:$imm12),
360                   "jalr", "$rd, ${imm12}(${rs1})">;
361} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
362
363def BEQ  : BranchCC_rri<0b000, "beq">;
364def BNE  : BranchCC_rri<0b001, "bne">;
365def BLT  : BranchCC_rri<0b100, "blt">;
366def BGE  : BranchCC_rri<0b101, "bge">;
367def BLTU : BranchCC_rri<0b110, "bltu">;
368def BGEU : BranchCC_rri<0b111, "bgeu">;
369
370def LB  : Load_ri<0b000, "lb">;
371def LH  : Load_ri<0b001, "lh">;
372def LW  : Load_ri<0b010, "lw">;
373def LBU : Load_ri<0b100, "lbu">;
374def LHU : Load_ri<0b101, "lhu">;
375
376def SB : Store_rri<0b000, "sb">;
377def SH : Store_rri<0b001, "sh">;
378def SW : Store_rri<0b010, "sw">;
379
380// ADDI isn't always rematerializable, but isReMaterializable will be used as
381// a hint which is verified in isReallyTriviallyReMaterializable.
382let isReMaterializable = 1, isAsCheapAsAMove = 1 in
383def ADDI  : ALU_ri<0b000, "addi">;
384
385def SLTI  : ALU_ri<0b010, "slti">;
386def SLTIU : ALU_ri<0b011, "sltiu">;
387
388let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
389def XORI  : ALU_ri<0b100, "xori">;
390def ORI   : ALU_ri<0b110, "ori">;
391}
392
393def ANDI  : ALU_ri<0b111, "andi">;
394
395def SLLI : Shift_ri<0, 0b001, "slli">;
396def SRLI : Shift_ri<0, 0b101, "srli">;
397def SRAI : Shift_ri<1, 0b101, "srai">;
398
399def ADD  : ALU_rr<0b0000000, 0b000, "add">;
400def SUB  : ALU_rr<0b0100000, 0b000, "sub">;
401def SLL  : ALU_rr<0b0000000, 0b001, "sll">;
402def SLT  : ALU_rr<0b0000000, 0b010, "slt">;
403def SLTU : ALU_rr<0b0000000, 0b011, "sltu">;
404def XOR  : ALU_rr<0b0000000, 0b100, "xor">;
405def SRL  : ALU_rr<0b0000000, 0b101, "srl">;
406def SRA  : ALU_rr<0b0100000, 0b101, "sra">;
407def OR   : ALU_rr<0b0000000, 0b110, "or">;
408def AND  : ALU_rr<0b0000000, 0b111, "and">;
409
410let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
411def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
412                    (ins fencearg:$pred, fencearg:$succ),
413                    "fence", "$pred, $succ"> {
414  bits<4> pred;
415  bits<4> succ;
416
417  let rs1 = 0;
418  let rd = 0;
419  let imm12 = {0b0000,pred,succ};
420}
421
422def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", ""> {
423  let rs1 = 0;
424  let rd = 0;
425  let imm12 = {0b1000,0b0011,0b0011};
426}
427
428def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> {
429  let rs1 = 0;
430  let rd = 0;
431  let imm12 = 0;
432}
433
434def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> {
435  let rs1 = 0;
436  let rd = 0;
437  let imm12 = 0;
438}
439
440def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> {
441  let rs1 = 0;
442  let rd = 0;
443  let imm12 = 1;
444}
445
446// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
447// instruction (i.e., it should always trap, if your implementation has invalid
448// instruction traps).
449def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", ""> {
450  let rs1 = 0;
451  let rd = 0;
452  let imm12 = 0b110000000000;
453}
454} // hasSideEffects = 1, mayLoad = 0, mayStore = 0
455
456def CSRRW : CSR_ir<0b001, "csrrw">;
457def CSRRS : CSR_ir<0b010, "csrrs">;
458def CSRRC : CSR_ir<0b011, "csrrc">;
459
460def CSRRWI : CSR_ii<0b101, "csrrwi">;
461def CSRRSI : CSR_ii<0b110, "csrrsi">;
462def CSRRCI : CSR_ii<0b111, "csrrci">;
463
464/// RV64I instructions
465
466let Predicates = [IsRV64] in {
467def LWU   : Load_ri<0b110, "lwu">;
468def LD    : Load_ri<0b011, "ld">;
469def SD    : Store_rri<0b011, "sd">;
470
471let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
472def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
473                    (ins GPR:$rs1, simm12:$imm12),
474                    "addiw", "$rd, $rs1, $imm12">;
475
476def SLLIW : ShiftW_ri<0, 0b001, "slliw">;
477def SRLIW : ShiftW_ri<0, 0b101, "srliw">;
478def SRAIW : ShiftW_ri<1, 0b101, "sraiw">;
479
480def ADDW  : ALUW_rr<0b0000000, 0b000, "addw">;
481def SUBW  : ALUW_rr<0b0100000, 0b000, "subw">;
482def SLLW  : ALUW_rr<0b0000000, 0b001, "sllw">;
483def SRLW  : ALUW_rr<0b0000000, 0b101, "srlw">;
484def SRAW  : ALUW_rr<0b0100000, 0b101, "sraw">;
485} // Predicates = [IsRV64]
486
487//===----------------------------------------------------------------------===//
488// Privileged instructions
489//===----------------------------------------------------------------------===//
490
491let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
492def URET : Priv<"uret", 0b0000000> {
493  let rd = 0;
494  let rs1 = 0;
495  let rs2 = 0b00010;
496}
497
498def SRET : Priv<"sret", 0b0001000> {
499  let rd = 0;
500  let rs1 = 0;
501  let rs2 = 0b00010;
502}
503
504def MRET : Priv<"mret", 0b0011000> {
505  let rd = 0;
506  let rs1 = 0;
507  let rs2 = 0b00010;
508}
509} // isBarrier = 1, isReturn = 1, isTerminator = 1
510
511def WFI : Priv<"wfi", 0b0001000> {
512  let rd = 0;
513  let rs1 = 0;
514  let rs2 = 0b00101;
515}
516
517let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
518def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs),
519                         (ins GPR:$rs1, GPR:$rs2),
520                         "sfence.vma", "$rs1, $rs2"> {
521  let rd = 0;
522}
523
524//===----------------------------------------------------------------------===//
525// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
526//===----------------------------------------------------------------------===//
527
528def : InstAlias<"nop",           (ADDI      X0,      X0,       0)>;
529
530// Note that the size is 32 because up to 8 32-bit instructions are needed to
531// generate an arbitrary 64-bit immediate. However, the size does not really
532// matter since PseudoLI is currently only used in the AsmParser where it gets
533// expanded to real instructions immediately.
534let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
535    isCodeGenOnly = 0, isAsmParserOnly = 1 in
536def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
537                      "li", "$rd, $imm">;
538
539def PseudoLB  : PseudoLoad<"lb">;
540def PseudoLBU : PseudoLoad<"lbu">;
541def PseudoLH  : PseudoLoad<"lh">;
542def PseudoLHU : PseudoLoad<"lhu">;
543def PseudoLW  : PseudoLoad<"lw">;
544
545def PseudoSB  : PseudoStore<"sb">;
546def PseudoSH  : PseudoStore<"sh">;
547def PseudoSW  : PseudoStore<"sw">;
548
549let Predicates = [IsRV64] in {
550def PseudoLWU : PseudoLoad<"lwu">;
551def PseudoLD  : PseudoLoad<"ld">;
552def PseudoSD  : PseudoStore<"sd">;
553} // Predicates = [IsRV64]
554
555def : InstAlias<"mv $rd, $rs",   (ADDI GPR:$rd, GPR:$rs,       0)>;
556def : InstAlias<"not $rd, $rs",  (XORI GPR:$rd, GPR:$rs,      -1)>;
557def : InstAlias<"neg $rd, $rs",  (SUB  GPR:$rd,      X0, GPR:$rs)>;
558
559let Predicates = [IsRV64] in {
560def : InstAlias<"negw $rd, $rs",   (SUBW  GPR:$rd,      X0, GPR:$rs)>;
561def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs,       0)>;
562} // Predicates = [IsRV64]
563
564def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs,       1)>;
565def : InstAlias<"snez $rd, $rs", (SLTU  GPR:$rd,      X0, GPR:$rs)>;
566def : InstAlias<"sltz $rd, $rs", (SLT   GPR:$rd, GPR:$rs,      X0)>;
567def : InstAlias<"sgtz $rd, $rs", (SLT   GPR:$rd,      X0, GPR:$rs)>;
568
569// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
570// form will always be printed. Therefore, set a zero weight.
571def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
572def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
573
574def : InstAlias<"beqz $rs, $offset",
575                (BEQ GPR:$rs,      X0, simm13_lsb0:$offset)>;
576def : InstAlias<"bnez $rs, $offset",
577                (BNE GPR:$rs,      X0, simm13_lsb0:$offset)>;
578def : InstAlias<"blez $rs, $offset",
579                (BGE      X0, GPR:$rs, simm13_lsb0:$offset)>;
580def : InstAlias<"bgez $rs, $offset",
581                (BGE GPR:$rs,      X0, simm13_lsb0:$offset)>;
582def : InstAlias<"bltz $rs, $offset",
583                (BLT GPR:$rs,      X0, simm13_lsb0:$offset)>;
584def : InstAlias<"bgtz $rs, $offset",
585                (BLT      X0, GPR:$rs, simm13_lsb0:$offset)>;
586
587// Always output the canonical mnemonic for the pseudo branch instructions.
588// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
589// as well (e.g. "bgt" will be recognised by the assembler but never printed by
590// objdump). Match this behaviour by setting a zero weight.
591def : InstAlias<"bgt $rs, $rt, $offset",
592                (BLT  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
593def : InstAlias<"ble $rs, $rt, $offset",
594                (BGE  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
595def : InstAlias<"bgtu $rs, $rt, $offset",
596                (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
597def : InstAlias<"bleu $rs, $rt, $offset",
598                (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
599
600def : InstAlias<"j $offset",   (JAL X0, simm21_lsb0_jal:$offset)>;
601def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
602
603// Non-zero offset aliases of "jalr" are the lowest weight, followed by the
604// two-register form, then the one-register forms and finally "ret".
605def : InstAlias<"jr $rs",                (JALR      X0, GPR:$rs, 0), 3>;
606def : InstAlias<"jr ${offset}(${rs})",   (JALR      X0, GPR:$rs, simm12:$offset)>;
607def : InstAlias<"jalr $rs",              (JALR      X1, GPR:$rs, 0), 3>;
608def : InstAlias<"jalr ${offset}(${rs})", (JALR      X1, GPR:$rs, simm12:$offset)>;
609def : InstAlias<"jalr $rd, $rs",         (JALR GPR:$rd, GPR:$rs, 0), 2>;
610def : InstAlias<"ret",                   (JALR      X0,      X1, 0), 4>;
611
612// Non-canonical forms for jump targets also accepted by the assembler.
613def : InstAlias<"jr $rs, $offset",        (JALR      X0, GPR:$rs, simm12:$offset), 0>;
614def : InstAlias<"jalr $rs, $offset",      (JALR      X1, GPR:$rs, simm12:$offset), 0>;
615def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>;
616
617// TODO call
618// TODO tail
619
620def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
621
622def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
623def : InstAlias<"rdcycle $rd",   (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
624def : InstAlias<"rdtime $rd",    (CSRRS GPR:$rd, TIME.Encoding, X0)>;
625
626let Predicates = [IsRV32] in {
627def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>;
628def : InstAlias<"rdcycleh $rd",   (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>;
629def : InstAlias<"rdtimeh $rd",    (CSRRS GPR:$rd, TIMEH.Encoding, X0)>;
630} // Predicates = [IsRV32]
631
632def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr,      X0)>;
633def : InstAlias<"csrw $csr, $rs", (CSRRW      X0, csr_sysreg:$csr, GPR:$rs)>;
634def : InstAlias<"csrs $csr, $rs", (CSRRS      X0, csr_sysreg:$csr, GPR:$rs)>;
635def : InstAlias<"csrc $csr, $rs", (CSRRC      X0, csr_sysreg:$csr, GPR:$rs)>;
636
637def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
638def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
639def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
640
641let EmitPriority = 0 in {
642def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
643def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
644def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
645
646def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
647def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
648def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
649}
650
651def : InstAlias<"sfence.vma",     (SFENCE_VMA      X0, X0)>;
652def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
653
654let EmitPriority = 0 in {
655def : InstAlias<"lb $rd, (${rs1})",
656                (LB  GPR:$rd, GPR:$rs1, 0)>;
657def : InstAlias<"lh $rd, (${rs1})",
658                (LH  GPR:$rd, GPR:$rs1, 0)>;
659def : InstAlias<"lw $rd, (${rs1})",
660                (LW  GPR:$rd, GPR:$rs1, 0)>;
661def : InstAlias<"lbu $rd, (${rs1})",
662                (LBU  GPR:$rd, GPR:$rs1, 0)>;
663def : InstAlias<"lhu $rd, (${rs1})",
664                (LHU  GPR:$rd, GPR:$rs1, 0)>;
665
666def : InstAlias<"sb $rs2, (${rs1})",
667                (SB  GPR:$rs2, GPR:$rs1, 0)>;
668def : InstAlias<"sh $rs2, (${rs1})",
669                (SH  GPR:$rs2, GPR:$rs1, 0)>;
670def : InstAlias<"sw $rs2, (${rs1})",
671                (SW  GPR:$rs2, GPR:$rs1, 0)>;
672
673def : InstAlias<"add $rd, $rs1, $imm12",
674                (ADDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
675def : InstAlias<"and $rd, $rs1, $imm12",
676                (ANDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
677def : InstAlias<"xor $rd, $rs1, $imm12",
678                (XORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
679def : InstAlias<"or $rd, $rs1, $imm12",
680                (ORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
681def : InstAlias<"sll $rd, $rs1, $shamt",
682                (SLLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
683def : InstAlias<"srl $rd, $rs1, $shamt",
684                (SRLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
685def : InstAlias<"sra $rd, $rs1, $shamt",
686                (SRAI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
687let Predicates = [IsRV64] in {
688def : InstAlias<"lwu $rd, (${rs1})",
689                (LWU  GPR:$rd, GPR:$rs1, 0)>;
690def : InstAlias<"ld $rd, (${rs1})",
691                (LD  GPR:$rd, GPR:$rs1, 0)>;
692def : InstAlias<"sd $rs2, (${rs1})",
693                (SD  GPR:$rs2, GPR:$rs1, 0)>;
694
695def : InstAlias<"addw $rd, $rs1, $imm12",
696                (ADDIW  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
697def : InstAlias<"sllw $rd, $rs1, $shamt",
698                (SLLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
699def : InstAlias<"srlw $rd, $rs1, $shamt",
700                (SRLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
701def : InstAlias<"sraw $rd, $rs1, $shamt",
702                (SRAIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
703} // Predicates = [IsRV64]
704def : InstAlias<"slt $rd, $rs1, $imm12",
705                (SLTI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
706def : InstAlias<"sltu $rd, $rs1, $imm12",
707                (SLTIU  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
708}
709
710def : MnemonicAlias<"move", "mv">;
711
712// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in
713// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept
714// the old name for backwards compatibility.
715def : MnemonicAlias<"scall", "ecall">;
716def : MnemonicAlias<"sbreak", "ebreak">;
717
718//===----------------------------------------------------------------------===//
719// Pseudo-instructions and codegen patterns
720//
721// Naming convention: For 'generic' pattern classes, we use the naming
722// convention PatTy1Ty2. For pattern classes which offer a more complex
723// expension, prefix the class name, e.g. BccPat.
724//===----------------------------------------------------------------------===//
725
726/// Generic pattern classes
727
728class PatGprGpr<SDPatternOperator OpNode, RVInst Inst>
729    : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
730class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
731    : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
732class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
733    : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
734          (Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
735
736/// Predicates
737
738def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
739  return isOrEquivalentToAdd(N);
740}]>;
741def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
742  return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32;
743}]>;
744def sexti32 : PatFrags<(ops node:$src),
745                       [(sext_inreg node:$src, i32),
746                        (assertsexti32 node:$src)]>;
747def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
748  return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32;
749}]>;
750def zexti32 : PatFrags<(ops node:$src),
751                       [(and node:$src, 0xffffffff),
752                        (assertzexti32 node:$src)]>;
753
754/// Immediates
755
756def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
757def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>;
758def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>,
759      Requires<[IsRV32]>;
760
761/// Simple arithmetic operations
762
763def : PatGprGpr<add, ADD>;
764def : PatGprSimm12<add, ADDI>;
765def : PatGprGpr<sub, SUB>;
766def : PatGprGpr<or, OR>;
767def : PatGprSimm12<or, ORI>;
768def : PatGprGpr<and, AND>;
769def : PatGprSimm12<and, ANDI>;
770def : PatGprGpr<xor, XOR>;
771def : PatGprSimm12<xor, XORI>;
772def : PatGprUimmLog2XLen<shl, SLLI>;
773def : PatGprUimmLog2XLen<srl, SRLI>;
774def : PatGprUimmLog2XLen<sra, SRAI>;
775
776// Match both a plain shift and one where the shift amount is masked (this is
777// typically introduced when the legalizer promotes the shift amount and
778// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
779// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
780class shiftop<SDPatternOperator operator>
781    : PatFrags<(ops node:$val, node:$count),
782               [(operator node:$val, node:$count),
783                (operator node:$val, (and node:$count, immbottomxlenset))]>;
784
785def : PatGprGpr<shiftop<shl>, SLL>;
786def : PatGprGpr<shiftop<srl>, SRL>;
787def : PatGprGpr<shiftop<sra>, SRA>;
788
789// This is a special case of the ADD instruction used to facilitate the use of a
790// fourth operand to emit a relocation on a symbol relating to this instruction.
791// The relocation does not affect any bits of the instruction itself but is used
792// as a hint to the linker.
793let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
794def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
795                            (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
796                            "add", "$rd, $rs1, $rs2, $src">;
797
798/// FrameIndex calculations
799
800def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
801          (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
802def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12),
803          (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
804
805/// Setcc
806
807def : PatGprGpr<setlt, SLT>;
808def : PatGprSimm12<setlt, SLTI>;
809def : PatGprGpr<setult, SLTU>;
810def : PatGprSimm12<setult, SLTIU>;
811
812// Define pattern expansions for setcc operations that aren't directly
813// handled by a RISC-V instruction.
814def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>;
815def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>;
816def : Pat<(seteq GPR:$rs1, simm12:$imm12),
817          (SLTIU (XORI GPR:$rs1, simm12:$imm12), 1)>;
818def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>;
819def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>;
820def : Pat<(setne GPR:$rs1, simm12:$imm12),
821          (SLTU X0, (XORI GPR:$rs1, simm12:$imm12))>;
822def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>;
823def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>;
824def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>;
825def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>;
826def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>;
827def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>;
828
829let usesCustomInserter = 1 in
830class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty>
831    : Pseudo<(outs valty:$dst),
832             (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm,
833              valty:$truev, valty:$falsev),
834             [(set valty:$dst, (riscv_selectcc cmpty:$lhs, cmpty:$rhs,
835              (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>;
836
837def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>;
838
839/// Branches and jumps
840
841// Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch
842// instruction.
843class BccPat<PatFrag CondOp, RVInstB Inst>
844    : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
845          (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
846
847def : BccPat<seteq, BEQ>;
848def : BccPat<setne, BNE>;
849def : BccPat<setlt, BLT>;
850def : BccPat<setge, BGE>;
851def : BccPat<setult, BLTU>;
852def : BccPat<setuge, BGEU>;
853
854class BccSwapPat<PatFrag CondOp, RVInst InstBcc>
855    : Pat<(brcond (XLenVT (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
856          (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>;
857
858// Condition codes that don't have matching RISC-V branch instructions, but
859// are trivially supported by swapping the two input operands
860def : BccSwapPat<setgt, BLT>;
861def : BccSwapPat<setle, BGE>;
862def : BccSwapPat<setugt, BLTU>;
863def : BccSwapPat<setule, BGEU>;
864
865// An extra pattern is needed for a brcond without a setcc (i.e. where the
866// condition was calculated elsewhere).
867def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
868
869let isBarrier = 1, isBranch = 1, isTerminator = 1 in
870def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
871               PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
872
873let isCall = 1, Defs=[X1] in
874let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
875def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>,
876                  PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
877
878def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>;
879def : Pat<(brind (add GPR:$rs1, simm12:$imm12)),
880          (PseudoBRIND GPR:$rs1, simm12:$imm12)>;
881
882// PsuedoCALLReg is a generic pseudo instruction for calls which will eventually
883// expand to auipc and jalr while encoding, with any given register used as the
884// destination.
885// Define AsmString to print "call" when compile with -S flag.
886// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
887let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0,
888    mayStore = 0, mayLoad = 0 in
889def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> {
890  let AsmString = "call\t$rd, $func";
891}
892
893// PseudoCALL is a pseudo instruction which will eventually expand to auipc
894// and jalr while encoding. This is desirable, as an auipc+jalr pair with
895// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
896// if the offset fits in a signed 21-bit immediate.
897// Define AsmString to print "call" when compile with -S flag.
898// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
899let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in
900def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> {
901  let AsmString = "call\t$func";
902}
903
904def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
905def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
906
907def : Pat<(riscv_uret_flag), (URET X0, X0)>;
908def : Pat<(riscv_sret_flag), (SRET X0, X0)>;
909def : Pat<(riscv_mret_flag), (MRET X0, X0)>;
910
911let isCall = 1, Defs = [X1] in
912def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1),
913                                [(riscv_call GPR:$rs1)]>,
914                         PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
915
916let isBarrier = 1, isReturn = 1, isTerminator = 1 in
917def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>,
918                PseudoInstExpansion<(JALR X0, X1, 0)>;
919
920// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
921// expand to auipc and jalr while encoding.
922// Define AsmString to print "tail" when compile with -S flag.
923let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
924    isCodeGenOnly = 0 in
925def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> {
926  let AsmString = "tail\t$dst";
927}
928
929let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
930def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
931                                [(riscv_tail GPRTC:$rs1)]>,
932                         PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
933
934def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
935          (PseudoTAIL texternalsym:$dst)>;
936def : Pat<(riscv_tail (iPTR texternalsym:$dst)),
937          (PseudoTAIL texternalsym:$dst)>;
938
939let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0,
940    isAsmParserOnly = 1 in
941def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
942                       "lla", "$dst, $src">;
943
944let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
945    isAsmParserOnly = 1 in
946def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
947                      "la", "$dst, $src">;
948
949let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
950    isAsmParserOnly = 1 in
951def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
952                             "la.tls.ie", "$dst, $src">;
953
954let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
955    isAsmParserOnly = 1 in
956def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
957                             "la.tls.gd", "$dst, $src">;
958
959/// Loads
960
961multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
962  def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>;
963  def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>;
964  def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)),
965            (Inst GPR:$rs1, simm12:$imm12)>;
966  def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)),
967            (Inst AddrFI:$rs1, simm12:$imm12)>;
968  def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
969            (Inst AddrFI:$rs1, simm12:$imm12)>;
970}
971
972defm : LdPat<sextloadi8, LB>;
973defm : LdPat<extloadi8, LB>;
974defm : LdPat<sextloadi16, LH>;
975defm : LdPat<extloadi16, LH>;
976defm : LdPat<load, LW>, Requires<[IsRV32]>;
977defm : LdPat<zextloadi8, LBU>;
978defm : LdPat<zextloadi16, LHU>;
979
980/// Stores
981
982multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> {
983  def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>;
984  def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>;
985  def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)),
986            (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
987  def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)),
988            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
989  def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
990            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
991}
992
993defm : StPat<truncstorei8, SB, GPR>;
994defm : StPat<truncstorei16, SH, GPR>;
995defm : StPat<store, SW, GPR>, Requires<[IsRV32]>;
996
997/// Fences
998
999// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1000// Manual: Volume I.
1001
1002// fence acquire -> fence r, rw
1003def : Pat<(atomic_fence (XLenVT 4), (imm)), (FENCE 0b10, 0b11)>;
1004// fence release -> fence rw, w
1005def : Pat<(atomic_fence (XLenVT 5), (imm)), (FENCE 0b11, 0b1)>;
1006// fence acq_rel -> fence.tso
1007def : Pat<(atomic_fence (XLenVT 6), (imm)), (FENCE_TSO)>;
1008// fence seq_cst -> fence rw, rw
1009def : Pat<(atomic_fence (XLenVT 7), (imm)), (FENCE 0b11, 0b11)>;
1010
1011// Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
1012// Although these are lowered to fence+load/store instructions defined in the
1013// base RV32I/RV64I ISA, this lowering is only used when the A extension is
1014// present. This is necessary as it isn't valid to mix __atomic_* libcalls
1015// with inline atomic operations for the same object.
1016
1017/// Other pseudo-instructions
1018
1019// Pessimistically assume the stack pointer will be clobbered
1020let Defs = [X2], Uses = [X2] in {
1021def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1022                              [(callseq_start timm:$amt1, timm:$amt2)]>;
1023def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
1024                              [(callseq_end timm:$amt1, timm:$amt2)]>;
1025} // Defs = [X2], Uses = [X2]
1026
1027/// RV64 patterns
1028
1029let Predicates = [IsRV64] in {
1030
1031/// sext and zext
1032
1033def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;
1034def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>;
1035
1036/// ALU operations
1037
1038def : Pat<(sext_inreg (add GPR:$rs1, GPR:$rs2), i32),
1039          (ADDW GPR:$rs1, GPR:$rs2)>;
1040def : Pat<(sext_inreg (add GPR:$rs1, simm12:$imm12), i32),
1041          (ADDIW GPR:$rs1, simm12:$imm12)>;
1042def : Pat<(sext_inreg (sub GPR:$rs1, GPR:$rs2), i32),
1043          (SUBW GPR:$rs1, GPR:$rs2)>;
1044def : Pat<(sext_inreg (shl GPR:$rs1, uimm5:$shamt), i32),
1045          (SLLIW GPR:$rs1, uimm5:$shamt)>;
1046// (srl (zexti32 ...), uimm5:$shamt) is matched with custom code due to the
1047// need to undo manipulation of the mask value performed by DAGCombine.
1048def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1049          (SRAIW GPR:$rs1, uimm5:$shamt)>;
1050
1051def : PatGprGpr<riscv_sllw, SLLW>;
1052def : PatGprGpr<riscv_srlw, SRLW>;
1053def : PatGprGpr<riscv_sraw, SRAW>;
1054
1055/// Loads
1056
1057defm : LdPat<sextloadi32, LW>;
1058defm : LdPat<extloadi32, LW>;
1059defm : LdPat<zextloadi32, LWU>;
1060defm : LdPat<load, LD>;
1061
1062/// Stores
1063
1064defm : StPat<truncstorei32, SW, GPR>;
1065defm : StPat<store, SD, GPR>;
1066} // Predicates = [IsRV64]
1067
1068/// readcyclecounter
1069// On RV64, we can directly read the 64-bit "cycle" CSR.
1070let Predicates = [IsRV64] in
1071def : Pat<(readcyclecounter), (CSRRS CYCLE.Encoding, X0)>;
1072// On RV32, ReadCycleWide will be expanded to the suggested loop reading both
1073// halves of the 64-bit "cycle" CSR.
1074let Predicates = [IsRV32], usesCustomInserter = 1, hasSideEffects = 0,
1075mayLoad = 0, mayStore = 0, hasNoSchedulingInfo = 1 in
1076def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), [], "", "">;
1077
1078//===----------------------------------------------------------------------===//
1079// Standard extensions
1080//===----------------------------------------------------------------------===//
1081
1082include "RISCVInstrInfoM.td"
1083include "RISCVInstrInfoA.td"
1084include "RISCVInstrInfoF.td"
1085include "RISCVInstrInfoD.td"
1086include "RISCVInstrInfoC.td"
1087