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