1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- tablegen -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file describes the RISC-V instructions in TableGen format.
11//
12//===----------------------------------------------------------------------===//
13
14include "RISCVInstrFormats.td"
15
16//===----------------------------------------------------------------------===//
17// RISC-V specific DAG Nodes.
18//===----------------------------------------------------------------------===//
19
20def SDT_RISCVCall         : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;
21def SDT_RISCVCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
22                                            SDTCisVT<1, i32>]>;
23def SDT_RISCVCallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, i32>,
24                                          SDTCisVT<1, i32>]>;
25def SDT_RISCVSelectCC     : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
26                                                 SDTCisSameAs<0, 4>,
27                                                 SDTCisSameAs<4, 5>]>;
28
29
30def Call         : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
31                          [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
32                           SDNPVariadic]>;
33def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_RISCVCallSeqStart,
34                          [SDNPHasChain, SDNPOutGlue]>;
35def CallSeqEnd   : SDNode<"ISD::CALLSEQ_END", SDT_RISCVCallSeqEnd,
36                          [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
37def RetFlag      : SDNode<"RISCVISD::RET_FLAG", SDTNone,
38                          [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
39def URetFlag     : SDNode<"RISCVISD::URET_FLAG", SDTNone,
40                          [SDNPHasChain, SDNPOptInGlue]>;
41def SRetFlag     : SDNode<"RISCVISD::SRET_FLAG", SDTNone,
42                          [SDNPHasChain, SDNPOptInGlue]>;
43def MRetFlag     : SDNode<"RISCVISD::MRET_FLAG", SDTNone,
44                          [SDNPHasChain, SDNPOptInGlue]>;
45def SelectCC     : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC,
46                          [SDNPInGlue]>;
47def Tail         : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
48                          [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
49                           SDNPVariadic]>;
50
51//===----------------------------------------------------------------------===//
52// Operand and SDNode transformation definitions.
53//===----------------------------------------------------------------------===//
54
55class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
56  let Name = prefix # "ImmXLen" # suffix;
57  let RenderMethod = "addImmOperands";
58  let DiagnosticType = !strconcat("Invalid", Name);
59}
60
61class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
62  let Name = prefix # "Imm" # width # suffix;
63  let RenderMethod = "addImmOperands";
64  let DiagnosticType = !strconcat("Invalid", Name);
65}
66
67class SImmAsmOperand<int width, string suffix = "">
68    : ImmAsmOperand<"S", width, suffix> {
69}
70
71class UImmAsmOperand<int width, string suffix = "">
72    : ImmAsmOperand<"U", width, suffix> {
73}
74
75def FenceArg : AsmOperandClass {
76  let Name = "FenceArg";
77  let RenderMethod = "addFenceArgOperands";
78  let DiagnosticType = "InvalidFenceArg";
79}
80
81def fencearg : Operand<XLenVT> {
82  let ParserMatchClass = FenceArg;
83  let PrintMethod = "printFenceArg";
84  let DecoderMethod = "decodeUImmOperand<4>";
85}
86
87def UImmLog2XLenAsmOperand : AsmOperandClass {
88  let Name = "UImmLog2XLen";
89  let RenderMethod = "addImmOperands";
90  let DiagnosticType = "InvalidUImmLog2XLen";
91}
92
93def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
94  if (Subtarget->is64Bit())
95    return isUInt<6>(Imm);
96  return isUInt<5>(Imm);
97}]> {
98  let ParserMatchClass = UImmLog2XLenAsmOperand;
99  // TODO: should ensure invalid shamt is rejected when decoding.
100  let DecoderMethod = "decodeUImmOperand<6>";
101  let MCOperandPredicate = [{
102    int64_t Imm;
103    if (!MCOp.evaluateAsConstantImm(Imm))
104      return false;
105    if (STI.getTargetTriple().isArch64Bit())
106      return  isUInt<6>(Imm);
107    return isUInt<5>(Imm);
108  }];
109}
110
111def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
112  let ParserMatchClass = UImmAsmOperand<5>;
113  let DecoderMethod = "decodeUImmOperand<5>";
114}
115
116def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
117  let ParserMatchClass = SImmAsmOperand<12>;
118  let EncoderMethod = "getImmOpValue";
119  let DecoderMethod = "decodeSImmOperand<12>";
120  let MCOperandPredicate = [{
121    int64_t Imm;
122    if (MCOp.evaluateAsConstantImm(Imm))
123      return isInt<12>(Imm);
124    return MCOp.isBareSymbolRef();
125  }];
126}
127
128def uimm12 : Operand<XLenVT> {
129  let ParserMatchClass = UImmAsmOperand<12>;
130  let DecoderMethod = "decodeUImmOperand<12>";
131}
132
133// A 13-bit signed immediate where the least significant bit is zero.
134def simm13_lsb0 : Operand<OtherVT> {
135  let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
136  let EncoderMethod = "getImmOpValueAsr1";
137  let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
138  let MCOperandPredicate = [{
139    int64_t Imm;
140    if (MCOp.evaluateAsConstantImm(Imm))
141      return isShiftedInt<12, 1>(Imm);
142    return MCOp.isBareSymbolRef();
143  }];
144}
145
146def uimm20 : Operand<XLenVT> {
147  let ParserMatchClass = UImmAsmOperand<20>;
148  let EncoderMethod = "getImmOpValue";
149  let DecoderMethod = "decodeUImmOperand<20>";
150  let MCOperandPredicate = [{
151    int64_t Imm;
152    if (MCOp.evaluateAsConstantImm(Imm))
153      return isUInt<20>(Imm);
154    return MCOp.isBareSymbolRef();
155  }];
156}
157
158// A 21-bit signed immediate where the least significant bit is zero.
159def simm21_lsb0 : Operand<OtherVT> {
160  let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
161  let EncoderMethod = "getImmOpValueAsr1";
162  let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
163  let MCOperandPredicate = [{
164    int64_t Imm;
165    if (MCOp.evaluateAsConstantImm(Imm))
166      return isShiftedInt<20, 1>(Imm);
167    return MCOp.isBareSymbolRef();
168  }];
169}
170
171def BareSymbol : AsmOperandClass {
172  let Name = "BareSymbol";
173  let RenderMethod = "addImmOperands";
174  let DiagnosticType = "InvalidBareSymbol";
175}
176
177// A bare symbol.
178def bare_symbol : Operand<XLenVT> {
179  let ParserMatchClass = BareSymbol;
180  let MCOperandPredicate = [{
181     return MCOp.isBareSymbolRef();
182  }];
183}
184
185// A parameterized register class alternative to i32imm/i64imm from Target.td.
186def ixlenimm : Operand<XLenVT> {
187  let ParserMatchClass = ImmXLenAsmOperand<"">;
188}
189
190// Standalone (codegen-only) immleaf patterns.
191def simm32     : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
192def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>;
193
194// Addressing modes.
195// Necessary because a frameindex can't be matched directly in a pattern.
196def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>;
197
198// Extract least significant 12 bits from an immediate value and sign extend
199// them.
200def LO12Sext : SDNodeXForm<imm, [{
201  return CurDAG->getTargetConstant(SignExtend64<12>(N->getZExtValue()),
202                                   SDLoc(N), N->getValueType(0));
203}]>;
204
205// Extract the most significant 20 bits from an immediate value. Add 1 if bit
206// 11 is 1, to compensate for the low 12 bits in the matching immediate addi
207// or ld/st being negative.
208def HI20 : SDNodeXForm<imm, [{
209  return CurDAG->getTargetConstant(((N->getZExtValue()+0x800) >> 12) & 0xfffff,
210                                   SDLoc(N), N->getValueType(0));
211}]>;
212
213//===----------------------------------------------------------------------===//
214// Instruction Class Templates
215//===----------------------------------------------------------------------===//
216
217let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
218class BranchCC_rri<bits<3> funct3, string opcodestr>
219    : RVInstB<funct3, OPC_BRANCH, (outs),
220              (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
221              opcodestr, "$rs1, $rs2, $imm12"> {
222  let isBranch = 1;
223  let isTerminator = 1;
224}
225
226let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
227class Load_ri<bits<3> funct3, string opcodestr>
228    : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
229              opcodestr, "$rd, ${imm12}(${rs1})">;
230
231// Operands for stores are in the order srcreg, base, offset rather than
232// reflecting the order these fields are specified in the instruction
233// encoding.
234let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
235class Store_rri<bits<3> funct3, string opcodestr>
236    : RVInstS<funct3, OPC_STORE, (outs),
237              (ins GPR:$rs2, GPR:$rs1, simm12:$imm12),
238              opcodestr, "$rs2, ${imm12}(${rs1})">;
239
240let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
241class ALU_ri<bits<3> funct3, string opcodestr>
242    : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
243              opcodestr, "$rd, $rs1, $imm12">;
244
245let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
246class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr>
247    : RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd),
248                   (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
249                   "$rd, $rs1, $shamt">;
250
251let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
252class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
253    : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
254              opcodestr, "$rd, $rs1, $rs2">;
255
256let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
257class CSR_ir<bits<3> funct3, string opcodestr>
258    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins uimm12:$imm12, GPR:$rs1),
259              opcodestr, "$rd, $imm12, $rs1">;
260
261let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
262class CSR_ii<bits<3> funct3, string opcodestr>
263    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
264              (ins uimm12:$imm12, uimm5:$rs1),
265              opcodestr, "$rd, $imm12, $rs1">;
266
267let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
268class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr>
269    : RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
270                    (ins GPR:$rs1, uimm5:$shamt), opcodestr,
271                    "$rd, $rs1, $shamt">;
272
273let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
274class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
275    : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
276              (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;
277
278let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
279class Priv<string opcodestr, bits<7> funct7>
280    : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
281              opcodestr, "">;
282
283//===----------------------------------------------------------------------===//
284// Instructions
285//===----------------------------------------------------------------------===//
286
287let hasSideEffects = 0, isReMaterializable = 1, mayLoad = 0, mayStore = 0 in {
288def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20:$imm20),
289                  "lui", "$rd, $imm20">;
290
291def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20:$imm20),
292                    "auipc", "$rd, $imm20">;
293
294let isCall = 1 in
295def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0:$imm20),
296                  "jal", "$rd, $imm20">;
297
298let isCall = 1 in
299def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
300                   (ins GPR:$rs1, simm12:$imm12),
301                   "jalr", "$rd, $rs1, $imm12">;
302} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
303
304def BEQ  : BranchCC_rri<0b000, "beq">;
305def BNE  : BranchCC_rri<0b001, "bne">;
306def BLT  : BranchCC_rri<0b100, "blt">;
307def BGE  : BranchCC_rri<0b101, "bge">;
308def BLTU : BranchCC_rri<0b110, "bltu">;
309def BGEU : BranchCC_rri<0b111, "bgeu">;
310
311def LB  : Load_ri<0b000, "lb">;
312def LH  : Load_ri<0b001, "lh">;
313def LW  : Load_ri<0b010, "lw">;
314def LBU : Load_ri<0b100, "lbu">;
315def LHU : Load_ri<0b101, "lhu">;
316
317def SB : Store_rri<0b000, "sb">;
318def SH : Store_rri<0b001, "sh">;
319def SW : Store_rri<0b010, "sw">;
320
321// ADDI isn't always rematerializable, but isReMaterializable will be used as
322// a hint which is verified in isReallyTriviallyReMaterializable.
323let isReMaterializable = 1 in
324def ADDI  : ALU_ri<0b000, "addi">;
325
326def SLTI  : ALU_ri<0b010, "slti">;
327def SLTIU : ALU_ri<0b011, "sltiu">;
328def XORI  : ALU_ri<0b100, "xori">;
329def ORI   : ALU_ri<0b110, "ori">;
330def ANDI  : ALU_ri<0b111, "andi">;
331
332def SLLI : Shift_ri<0, 0b001, "slli">;
333def SRLI : Shift_ri<0, 0b101, "srli">;
334def SRAI : Shift_ri<1, 0b101, "srai">;
335
336def ADD  : ALU_rr<0b0000000, 0b000, "add">;
337def SUB  : ALU_rr<0b0100000, 0b000, "sub">;
338def SLL  : ALU_rr<0b0000000, 0b001, "sll">;
339def SLT  : ALU_rr<0b0000000, 0b010, "slt">;
340def SLTU : ALU_rr<0b0000000, 0b011, "sltu">;
341def XOR  : ALU_rr<0b0000000, 0b100, "xor">;
342def SRL  : ALU_rr<0b0000000, 0b101, "srl">;
343def SRA  : ALU_rr<0b0100000, 0b101, "sra">;
344def OR   : ALU_rr<0b0000000, 0b110, "or">;
345def AND  : ALU_rr<0b0000000, 0b111, "and">;
346
347let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
348def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
349                    (ins fencearg:$pred, fencearg:$succ),
350                    "fence", "$pred, $succ"> {
351  bits<4> pred;
352  bits<4> succ;
353
354  let rs1 = 0;
355  let rd = 0;
356  let imm12 = {0b0000,pred,succ};
357}
358
359def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", ""> {
360  let rs1 = 0;
361  let rd = 0;
362  let imm12 = {0b1000,0b0011,0b0011};
363}
364
365def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> {
366  let rs1 = 0;
367  let rd = 0;
368  let imm12 = 0;
369}
370
371def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> {
372  let rs1 = 0;
373  let rd = 0;
374  let imm12 = 0;
375}
376
377def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> {
378  let rs1 = 0;
379  let rd = 0;
380  let imm12 = 1;
381}
382} // hasSideEffects = 1, mayLoad = 0, mayStore = 0
383
384def CSRRW : CSR_ir<0b001, "csrrw">;
385def CSRRS : CSR_ir<0b010, "csrrs">;
386def CSRRC : CSR_ir<0b011, "csrrc">;
387
388def CSRRWI : CSR_ii<0b101, "csrrwi">;
389def CSRRSI : CSR_ii<0b110, "csrrsi">;
390def CSRRCI : CSR_ii<0b111, "csrrci">;
391
392/// RV64I instructions
393
394let Predicates = [IsRV64] in {
395def LWU   : Load_ri<0b110, "lwu">;
396def LD    : Load_ri<0b011, "ld">;
397def SD    : Store_rri<0b011, "sd">;
398
399let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
400def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
401                    (ins GPR:$rs1, simm12:$imm12),
402                    "addiw", "$rd, $rs1, $imm12">;
403
404def SLLIW : ShiftW_ri<0, 0b001, "slliw">;
405def SRLIW : ShiftW_ri<0, 0b101, "srliw">;
406def SRAIW : ShiftW_ri<1, 0b101, "sraiw">;
407
408def ADDW  : ALUW_rr<0b0000000, 0b000, "addw">;
409def SUBW  : ALUW_rr<0b0100000, 0b000, "subw">;
410def SLLW  : ALUW_rr<0b0000000, 0b001, "sllw">;
411def SRLW  : ALUW_rr<0b0000000, 0b101, "srlw">;
412def SRAW  : ALUW_rr<0b0100000, 0b101, "sraw">;
413} // Predicates = [IsRV64]
414
415//===----------------------------------------------------------------------===//
416// Privileged instructions
417//===----------------------------------------------------------------------===//
418
419let isBarrier = 1, isReturn = 1, isTerminator = 1 in {
420def URET : Priv<"uret", 0b0000000> {
421  let rd = 0;
422  let rs1 = 0;
423  let rs2 = 0b00010;
424}
425
426def SRET : Priv<"sret", 0b0001000> {
427  let rd = 0;
428  let rs1 = 0;
429  let rs2 = 0b00010;
430}
431
432def MRET : Priv<"mret", 0b0011000> {
433  let rd = 0;
434  let rs1 = 0;
435  let rs2 = 0b00010;
436}
437} // isBarrier = 1, isReturn = 1, isTerminator = 1
438
439def WFI : Priv<"wfi", 0b0001000> {
440  let rd = 0;
441  let rs1 = 0;
442  let rs2 = 0b00101;
443}
444
445let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
446def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs),
447                         (ins GPR:$rs1, GPR:$rs2),
448                         "sfence.vma", "$rs1, $rs2"> {
449  let rd = 0;
450}
451
452//===----------------------------------------------------------------------===//
453// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
454//===----------------------------------------------------------------------===//
455
456// TODO la
457// TODO lb lh lw
458// TODO RV64I: ld
459// TODO sb sh sw
460// TODO RV64I: sd
461
462def : InstAlias<"nop",           (ADDI      X0,      X0,       0)>;
463
464// Note that the size is 32 because up to 8 32-bit instructions are needed to
465// generate an arbitrary 64-bit immediate. However, the size does not really
466// matter since PseudoLI is currently only used in the AsmParser where it gets
467// expanded to real instructions immediately.
468let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
469    isCodeGenOnly = 0, isAsmParserOnly = 1 in
470def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm:$imm), [],
471                      "li", "$rd, $imm">;
472
473def : InstAlias<"mv $rd, $rs",   (ADDI GPR:$rd, GPR:$rs,       0)>;
474def : InstAlias<"not $rd, $rs",  (XORI GPR:$rd, GPR:$rs,      -1)>;
475def : InstAlias<"neg $rd, $rs",  (SUB  GPR:$rd,      X0, GPR:$rs)>;
476
477let Predicates = [IsRV64] in {
478def : InstAlias<"negw $rd, $rs",   (SUBW  GPR:$rd,      X0, GPR:$rs)>;
479def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs,       0)>;
480} // Predicates = [IsRV64]
481
482def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs,       1)>;
483def : InstAlias<"snez $rd, $rs", (SLTU  GPR:$rd,      X0, GPR:$rs)>;
484def : InstAlias<"sltz $rd, $rs", (SLT   GPR:$rd, GPR:$rs,      X0)>;
485def : InstAlias<"sgtz $rd, $rs", (SLT   GPR:$rd,      X0, GPR:$rs)>;
486
487// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
488// form will always be printed. Therefore, set a zero weight.
489def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
490def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
491
492def : InstAlias<"beqz $rs, $offset",
493                (BEQ GPR:$rs,      X0, simm13_lsb0:$offset)>;
494def : InstAlias<"bnez $rs, $offset",
495                (BNE GPR:$rs,      X0, simm13_lsb0:$offset)>;
496def : InstAlias<"blez $rs, $offset",
497                (BGE      X0, GPR:$rs, simm13_lsb0:$offset)>;
498def : InstAlias<"bgez $rs, $offset",
499                (BGE GPR:$rs,      X0, simm13_lsb0:$offset)>;
500def : InstAlias<"bltz $rs, $offset",
501                (BLT GPR:$rs,      X0, simm13_lsb0:$offset)>;
502def : InstAlias<"bgtz $rs, $offset",
503                (BLT      X0, GPR:$rs, simm13_lsb0:$offset)>;
504
505// Always output the canonical mnemonic for the pseudo branch instructions.
506// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
507// as well (e.g. "bgt" will be recognised by the assembler but never printed by
508// objdump). Match this behaviour by setting a zero weight.
509def : InstAlias<"bgt $rs, $rt, $offset",
510                (BLT  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
511def : InstAlias<"ble $rs, $rt, $offset",
512                (BGE  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
513def : InstAlias<"bgtu $rs, $rt, $offset",
514                (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
515def : InstAlias<"bleu $rs, $rt, $offset",
516                (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
517
518// "ret" has more weight since "ret" and "jr" alias the same "jalr" instruction.
519def : InstAlias<"j $offset",   (JAL  X0, simm21_lsb0:$offset)>;
520def : InstAlias<"jal $offset", (JAL  X1, simm21_lsb0:$offset)>;
521def : InstAlias<"jr $rs",      (JALR X0, GPR:$rs, 0)>;
522def : InstAlias<"jalr $rs",    (JALR X1, GPR:$rs, 0)>;
523def : InstAlias<"ret",         (JALR X0,      X1, 0), 2>;
524// TODO call
525// TODO tail
526
527def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
528
529// CSR Addresses: 0xC00 == cycle,  0xC01 == time,  0xC02 == instret
530//                0xC80 == cycleh, 0xC81 == timeh, 0xC82 == instreth
531def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, 0xC02, X0)>;
532def : InstAlias<"rdcycle $rd",   (CSRRS GPR:$rd, 0xC00, X0)>;
533def : InstAlias<"rdtime $rd",    (CSRRS GPR:$rd, 0xC01, X0)>;
534
535let Predicates = [IsRV32] in {
536def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, 0xC82, X0)>;
537def : InstAlias<"rdcycleh $rd",   (CSRRS GPR:$rd, 0xC80, X0)>;
538def : InstAlias<"rdtimeh $rd",    (CSRRS GPR:$rd, 0xC81, X0)>;
539} // Predicates = [IsRV32]
540
541def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, uimm12:$csr,      X0)>;
542def : InstAlias<"csrw $csr, $rs", (CSRRW      X0, uimm12:$csr, GPR:$rs)>;
543def : InstAlias<"csrs $csr, $rs", (CSRRS      X0, uimm12:$csr, GPR:$rs)>;
544def : InstAlias<"csrc $csr, $rs", (CSRRC      X0, uimm12:$csr, GPR:$rs)>;
545
546def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, uimm12:$csr, uimm5:$imm)>;
547def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, uimm12:$csr, uimm5:$imm)>;
548def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, uimm12:$csr, uimm5:$imm)>;
549
550def : InstAlias<"sfence.vma",     (SFENCE_VMA      X0, X0)>;
551def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
552
553//===----------------------------------------------------------------------===//
554// Pseudo-instructions and codegen patterns
555//
556// Naming convention: For 'generic' pattern classes, we use the naming
557// convention PatTy1Ty2. For pattern classes which offer a more complex
558// expension, prefix the class name, e.g. BccPat.
559//===----------------------------------------------------------------------===//
560
561/// Generic pattern classes
562
563class PatGprGpr<SDPatternOperator OpNode, RVInstR Inst>
564    : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
565class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
566    : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
567class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
568    : Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
569          (Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
570
571/// Predicates
572
573def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
574  return isOrEquivalentToAdd(N);
575}]>;
576
577/// Immediates
578
579def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
580def : Pat<(simm32hi20:$imm), (LUI (HI20 imm:$imm))>;
581def : Pat<(simm32:$imm), (ADDI (LUI (HI20 imm:$imm)), (LO12Sext imm:$imm))>;
582
583/// Simple arithmetic operations
584
585def : PatGprGpr<add, ADD>;
586def : PatGprSimm12<add, ADDI>;
587def : PatGprGpr<sub, SUB>;
588def : PatGprGpr<or, OR>;
589def : PatGprSimm12<or, ORI>;
590def : PatGprGpr<and, AND>;
591def : PatGprSimm12<and, ANDI>;
592def : PatGprGpr<xor, XOR>;
593def : PatGprSimm12<xor, XORI>;
594def : PatGprGpr<shl, SLL>;
595def : PatGprUimmLog2XLen<shl, SLLI>;
596def : PatGprGpr<srl, SRL>;
597def : PatGprUimmLog2XLen<srl, SRLI>;
598def : PatGprGpr<sra, SRA>;
599def : PatGprUimmLog2XLen<sra, SRAI>;
600
601/// FrameIndex calculations
602
603def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
604          (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
605def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12),
606          (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
607
608/// Setcc
609
610def : PatGprGpr<setlt, SLT>;
611def : PatGprSimm12<setlt, SLTI>;
612def : PatGprGpr<setult, SLTU>;
613def : PatGprSimm12<setult, SLTIU>;
614
615// Define pattern expansions for setcc operations that aren't directly
616// handled by a RISC-V instruction.
617def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>;
618def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>;
619def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>;
620def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>;
621def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>;
622def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>;
623def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>;
624def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>;
625
626let usesCustomInserter = 1 in
627class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty>
628    : Pseudo<(outs valty:$dst),
629             (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm,
630              valty:$truev, valty:$falsev),
631             [(set valty:$dst, (SelectCC cmpty:$lhs, cmpty:$rhs,
632              (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>;
633
634def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>;
635
636/// Branches and jumps
637
638// Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch
639// instruction.
640class BccPat<PatFrag CondOp, RVInstB Inst>
641    : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
642          (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
643
644def : BccPat<seteq, BEQ>;
645def : BccPat<setne, BNE>;
646def : BccPat<setlt, BLT>;
647def : BccPat<setge, BGE>;
648def : BccPat<setult, BLTU>;
649def : BccPat<setuge, BGEU>;
650
651class BccSwapPat<PatFrag CondOp, RVInst InstBcc>
652    : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
653          (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>;
654
655// Condition codes that don't have matching RISC-V branch instructions, but
656// are trivially supported by swapping the two input operands
657def : BccSwapPat<setgt, BLT>;
658def : BccSwapPat<setle, BGE>;
659def : BccSwapPat<setugt, BLTU>;
660def : BccSwapPat<setule, BGEU>;
661
662// An extra pattern is needed for a brcond without a setcc (i.e. where the
663// condition was calculated elsewhere).
664def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
665
666let isBarrier = 1, isBranch = 1, isTerminator = 1 in
667def PseudoBR : Pseudo<(outs), (ins simm21_lsb0:$imm20), [(br bb:$imm20)]>,
668               PseudoInstExpansion<(JAL X0, simm21_lsb0:$imm20)>;
669
670let isCall = 1, Defs=[X1] in
671let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
672def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>,
673                  PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
674
675def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>;
676def : Pat<(brind (add GPR:$rs1, simm12:$imm12)),
677          (PseudoBRIND GPR:$rs1, simm12:$imm12)>;
678
679// PseudoCALL is a pseudo instruction which will eventually expand to auipc
680// and jalr while encoding. This is desirable, as an auipc+jalr pair with
681// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
682// if the offset fits in a signed 21-bit immediate.
683// Define AsmString to print "call" when compile with -S flag.
684// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
685let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in
686def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func),
687                        [(Call tglobaladdr:$func)]> {
688  let AsmString = "call\t$func";
689}
690
691def : Pat<(Call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
692
693def : Pat<(URetFlag), (URET X0, X0)>;
694def : Pat<(SRetFlag), (SRET X0, X0)>;
695def : Pat<(MRetFlag), (MRET X0, X0)>;
696
697let isCall = 1, Defs = [X1] in
698def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1), [(Call GPR:$rs1)]>,
699                         PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
700
701let isBarrier = 1, isReturn = 1, isTerminator = 1 in
702def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>,
703                PseudoInstExpansion<(JALR X0, X1, 0)>;
704
705// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
706// expand to auipc and jalr while encoding.
707// Define AsmString to print "tail" when compile with -S flag.
708let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
709    isCodeGenOnly = 0 in
710def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst), []> {
711  let AsmString = "tail\t$dst";
712}
713
714let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
715def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), [(Tail GPRTC:$rs1)]>,
716                         PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
717
718def : Pat<(Tail (iPTR tglobaladdr:$dst)),
719          (PseudoTAIL texternalsym:$dst)>;
720def : Pat<(Tail (iPTR texternalsym:$dst)),
721          (PseudoTAIL texternalsym:$dst)>;
722
723/// Loads
724
725multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
726  def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>;
727  def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>;
728  def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)),
729            (Inst GPR:$rs1, simm12:$imm12)>;
730  def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)),
731            (Inst AddrFI:$rs1, simm12:$imm12)>;
732  def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
733            (Inst AddrFI:$rs1, simm12:$imm12)>;
734}
735
736defm : LdPat<sextloadi8, LB>;
737defm : LdPat<extloadi8, LB>;
738defm : LdPat<sextloadi16, LH>;
739defm : LdPat<extloadi16, LH>;
740defm : LdPat<load, LW>;
741defm : LdPat<zextloadi8, LBU>;
742defm : LdPat<zextloadi16, LHU>;
743
744/// Stores
745
746multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy> {
747  def : Pat<(StoreOp StTy:$rs2, GPR:$rs1), (Inst StTy:$rs2, GPR:$rs1, 0)>;
748  def : Pat<(StoreOp StTy:$rs2, AddrFI:$rs1), (Inst StTy:$rs2, AddrFI:$rs1, 0)>;
749  def : Pat<(StoreOp StTy:$rs2, (add GPR:$rs1, simm12:$imm12)),
750            (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
751  def : Pat<(StoreOp StTy:$rs2, (add AddrFI:$rs1, simm12:$imm12)),
752            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
753  def : Pat<(StoreOp StTy:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
754            (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>;
755}
756
757defm : StPat<truncstorei8, SB, GPR>;
758defm : StPat<truncstorei16, SH, GPR>;
759defm : StPat<store, SW, GPR>;
760
761/// Fences
762
763// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
764// Manual: Volume I.
765
766// fence acquire -> fence r, rw
767def : Pat<(atomic_fence (i32 4), (imm)), (FENCE 0b10, 0b11)>;
768// fence release -> fence rw, w
769def : Pat<(atomic_fence (i32 5), (imm)), (FENCE 0b11, 0b1)>;
770// fence acq_rel -> fence.tso
771def : Pat<(atomic_fence (i32 6), (imm)), (FENCE_TSO)>;
772// fence seq_cst -> fence rw, rw
773def : Pat<(atomic_fence (i32 7), (imm)), (FENCE 0b11, 0b11)>;
774
775// Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
776// Although these are lowered to fence+load/store instructions defined in the
777// base RV32I/RV64I ISA, this lowering is only used when the A extension is
778// present. This is necessary as it isn't valid to mix __atomic_* libcalls
779// with inline atomic operations for the same object.
780
781/// Other pseudo-instructions
782
783// Pessimistically assume the stack pointer will be clobbered
784let Defs = [X2], Uses = [X2] in {
785def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
786                              [(CallSeqStart timm:$amt1, timm:$amt2)]>;
787def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
788                              [(CallSeqEnd timm:$amt1, timm:$amt2)]>;
789} // Defs = [X2], Uses = [X2]
790
791//===----------------------------------------------------------------------===//
792// Standard extensions
793//===----------------------------------------------------------------------===//
794
795include "RISCVInstrInfoM.td"
796include "RISCVInstrInfoA.td"
797include "RISCVInstrInfoF.td"
798include "RISCVInstrInfoD.td"
799include "RISCVInstrInfoC.td"
800