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