1//===- RISCVInstrInfoC.td - Compressed RISC-V instructions -*- tblgen-*----===//
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
9include "RISCVInstrFormatsC.td"
10
11//===----------------------------------------------------------------------===//
12// Operand definitions.
13//===----------------------------------------------------------------------===//
14
15def UImmLog2XLenNonZeroAsmOperand : AsmOperandClass {
16  let Name = "UImmLog2XLenNonZero";
17  let RenderMethod = "addImmOperands";
18  let DiagnosticType = "InvalidUImmLog2XLenNonZero";
19}
20
21def uimmlog2xlennonzero : Operand<XLenVT>, ImmLeaf<XLenVT, [{
22  if (Subtarget->is64Bit())
23    return isUInt<6>(Imm) && (Imm != 0);
24  return isUInt<5>(Imm) && (Imm != 0);
25}]> {
26  let ParserMatchClass = UImmLog2XLenNonZeroAsmOperand;
27  // TODO: should ensure invalid shamt is rejected when decoding.
28  let DecoderMethod = "decodeUImmNonZeroOperand<6>";
29  let OperandType = "OPERAND_UIMMLOG2XLEN_NONZERO";
30  let OperandNamespace = "RISCVOp";
31  let MCOperandPredicate = [{
32    int64_t Imm;
33    if (!MCOp.evaluateAsConstantImm(Imm))
34      return false;
35    if (STI.getTargetTriple().isArch64Bit())
36      return  isUInt<6>(Imm) && (Imm != 0);
37    return isUInt<5>(Imm) && (Imm != 0);
38  }];
39}
40
41def simm6 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<6>(Imm);}]> {
42  let ParserMatchClass = SImmAsmOperand<6>;
43  let EncoderMethod = "getImmOpValue";
44  let DecoderMethod = "decodeSImmOperand<6>";
45  let OperandType = "OPERAND_SIMM6";
46  let OperandNamespace = "RISCVOp";
47  let MCOperandPredicate = [{
48    int64_t Imm;
49    if (MCOp.evaluateAsConstantImm(Imm))
50      return isInt<6>(Imm);
51    return MCOp.isBareSymbolRef();
52  }];
53}
54
55def simm6nonzero : Operand<XLenVT>,
56                   ImmLeaf<XLenVT, [{return (Imm != 0) && isInt<6>(Imm);}]> {
57  let ParserMatchClass = SImmAsmOperand<6, "NonZero">;
58  let EncoderMethod = "getImmOpValue";
59  let DecoderMethod = "decodeSImmNonZeroOperand<6>";
60  let OperandType = "OPERAND_SIMM6_NONZERO";
61  let OperandNamespace = "RISCVOp";
62  let MCOperandPredicate = [{
63    int64_t Imm;
64    if (MCOp.evaluateAsConstantImm(Imm))
65      return (Imm != 0) && isInt<6>(Imm);
66    return MCOp.isBareSymbolRef();
67  }];
68}
69
70def immzero : Operand<XLenVT>,
71              ImmLeaf<XLenVT, [{return (Imm == 0);}]> {
72  let ParserMatchClass = ImmZeroAsmOperand;
73  let OperandType = "OPERAND_ZERO";
74  let OperandNamespace = "RISCVOp";
75}
76
77def CLUIImmAsmOperand : AsmOperandClass {
78  let Name = "CLUIImm";
79  let RenderMethod = "addImmOperands";
80  let DiagnosticType = !strconcat("Invalid", Name);
81}
82
83
84// c_lui_imm checks the immediate range is in [1, 31] or [0xfffe0, 0xfffff].
85// The RISC-V ISA describes the constraint as [1, 63], with that value being
86// loaded in to bits 17-12 of the destination register and sign extended from
87// bit 17. Therefore, this 6-bit immediate can represent values in the ranges
88// [1, 31] and [0xfffe0, 0xfffff].
89def c_lui_imm : Operand<XLenVT>,
90                ImmLeaf<XLenVT, [{return (Imm != 0) &&
91                                 (isUInt<5>(Imm) ||
92                                  (Imm >= 0xfffe0 && Imm <= 0xfffff));}]> {
93  let ParserMatchClass = CLUIImmAsmOperand;
94  let EncoderMethod = "getImmOpValue";
95  let DecoderMethod = "decodeCLUIImmOperand";
96  let OperandType = "OPERAND_CLUI_IMM";
97  let OperandNamespace = "RISCVOp";
98  let MCOperandPredicate = [{
99    int64_t Imm;
100    if (MCOp.evaluateAsConstantImm(Imm))
101      return (Imm != 0) && (isUInt<5>(Imm) ||
102             (Imm >= 0xfffe0 && Imm <= 0xfffff));
103    return MCOp.isBareSymbolRef();
104  }];
105}
106
107// A 7-bit unsigned immediate where the least significant two bits are zero.
108def uimm7_lsb00 : Operand<XLenVT>,
109                  ImmLeaf<XLenVT, [{return isShiftedUInt<5, 2>(Imm);}]> {
110  let ParserMatchClass = UImmAsmOperand<7, "Lsb00">;
111  let EncoderMethod = "getImmOpValue";
112  let DecoderMethod = "decodeUImmOperand<7>";
113  let OperandType = "OPERAND_UIMM7_LSB00";
114  let OperandNamespace = "RISCVOp";
115  let MCOperandPredicate = [{
116    int64_t Imm;
117    if (!MCOp.evaluateAsConstantImm(Imm))
118      return false;
119    return isShiftedUInt<5, 2>(Imm);
120  }];
121}
122
123// A 8-bit unsigned immediate where the least significant two bits are zero.
124def uimm8_lsb00 : Operand<XLenVT>,
125                  ImmLeaf<XLenVT, [{return isShiftedUInt<6, 2>(Imm);}]> {
126  let ParserMatchClass = UImmAsmOperand<8, "Lsb00">;
127  let EncoderMethod = "getImmOpValue";
128  let DecoderMethod = "decodeUImmOperand<8>";
129  let OperandType = "OPERAND_UIMM8_LSB00";
130  let OperandNamespace = "RISCVOp";
131  let MCOperandPredicate = [{
132    int64_t Imm;
133    if (!MCOp.evaluateAsConstantImm(Imm))
134      return false;
135    return isShiftedUInt<6, 2>(Imm);
136  }];
137}
138
139// A 8-bit unsigned immediate where the least significant three bits are zero.
140def uimm8_lsb000 : Operand<XLenVT>,
141                   ImmLeaf<XLenVT, [{return isShiftedUInt<5, 3>(Imm);}]> {
142  let ParserMatchClass = UImmAsmOperand<8, "Lsb000">;
143  let EncoderMethod = "getImmOpValue";
144  let DecoderMethod = "decodeUImmOperand<8>";
145  let OperandType = "OPERAND_UIMM8_LSB000";
146  let OperandNamespace = "RISCVOp";
147  let MCOperandPredicate = [{
148    int64_t Imm;
149    if (!MCOp.evaluateAsConstantImm(Imm))
150      return false;
151    return isShiftedUInt<5, 3>(Imm);
152  }];
153}
154
155// A 9-bit signed immediate where the least significant bit is zero.
156def simm9_lsb0 : Operand<OtherVT>,
157                 ImmLeaf<XLenVT, [{return isShiftedInt<8, 1>(Imm);}]> {
158  let ParserMatchClass = SImmAsmOperand<9, "Lsb0">;
159  let PrintMethod = "printBranchOperand";
160  let EncoderMethod = "getImmOpValueAsr1";
161  let DecoderMethod = "decodeSImmOperandAndLsl1<9>";
162  let MCOperandPredicate = [{
163    int64_t Imm;
164    if (MCOp.evaluateAsConstantImm(Imm))
165      return isShiftedInt<8, 1>(Imm);
166    return MCOp.isBareSymbolRef();
167
168  }];
169  let OperandType = "OPERAND_PCREL";
170}
171
172// A 9-bit unsigned immediate where the least significant three bits are zero.
173def uimm9_lsb000 : Operand<XLenVT>,
174                   ImmLeaf<XLenVT, [{return isShiftedUInt<6, 3>(Imm);}]> {
175  let ParserMatchClass = UImmAsmOperand<9, "Lsb000">;
176  let EncoderMethod = "getImmOpValue";
177  let DecoderMethod = "decodeUImmOperand<9>";
178  let OperandType = "OPERAND_UIMM9_LSB000";
179  let OperandNamespace = "RISCVOp";
180  let MCOperandPredicate = [{
181    int64_t Imm;
182    if (!MCOp.evaluateAsConstantImm(Imm))
183      return false;
184    return isShiftedUInt<6, 3>(Imm);
185  }];
186}
187
188// A 10-bit unsigned immediate where the least significant two bits are zero
189// and the immediate can't be zero.
190def uimm10_lsb00nonzero : Operand<XLenVT>,
191                          ImmLeaf<XLenVT,
192                          [{return isShiftedUInt<8, 2>(Imm) && (Imm != 0);}]> {
193  let ParserMatchClass = UImmAsmOperand<10, "Lsb00NonZero">;
194  let EncoderMethod = "getImmOpValue";
195  let DecoderMethod = "decodeUImmNonZeroOperand<10>";
196  let OperandType = "OPERAND_UIMM10_LSB00_NONZERO";
197  let OperandNamespace = "RISCVOp";
198  let MCOperandPredicate = [{
199    int64_t Imm;
200    if (!MCOp.evaluateAsConstantImm(Imm))
201      return false;
202    return isShiftedUInt<8, 2>(Imm) && (Imm != 0);
203  }];
204}
205
206// A 10-bit signed immediate where the least significant four bits are zero.
207def simm10_lsb0000nonzero : Operand<XLenVT>,
208                            ImmLeaf<XLenVT,
209                            [{return (Imm != 0) && isShiftedInt<6, 4>(Imm);}]> {
210  let ParserMatchClass = SImmAsmOperand<10, "Lsb0000NonZero">;
211  let EncoderMethod = "getImmOpValue";
212  let DecoderMethod = "decodeSImmNonZeroOperand<10>";
213  let OperandType = "OPERAND_SIMM10_LSB0000_NONZERO";
214  let OperandNamespace = "RISCVOp";
215  let MCOperandPredicate = [{
216    int64_t Imm;
217    if (!MCOp.evaluateAsConstantImm(Imm))
218      return false;
219    return isShiftedInt<6, 4>(Imm) && (Imm != 0);
220  }];
221}
222
223// A 12-bit signed immediate where the least significant bit is zero.
224def simm12_lsb0 : Operand<XLenVT>,
225                  ImmLeaf<XLenVT, [{return isShiftedInt<11, 1>(Imm);}]> {
226  let ParserMatchClass = SImmAsmOperand<12, "Lsb0">;
227  let PrintMethod = "printBranchOperand";
228  let EncoderMethod = "getImmOpValueAsr1";
229  let DecoderMethod = "decodeSImmOperandAndLsl1<12>";
230  let MCOperandPredicate = [{
231    int64_t Imm;
232    if (MCOp.evaluateAsConstantImm(Imm))
233      return isShiftedInt<11, 1>(Imm);
234    return MCOp.isBareSymbolRef();
235  }];
236  let OperandType = "OPERAND_PCREL";
237}
238
239def InsnCDirectiveOpcode : AsmOperandClass {
240  let Name = "InsnCDirectiveOpcode";
241  let ParserMethod = "parseInsnCDirectiveOpcode";
242  let RenderMethod = "addImmOperands";
243  let PredicateMethod = "isImm";
244}
245
246def uimm2_opcode : Operand<XLenVT> {
247  let ParserMatchClass = InsnCDirectiveOpcode;
248  let DecoderMethod = "decodeUImmOperand<2>";
249  let OperandType = "OPERAND_UIMM2";
250  let OperandNamespace = "RISCVOp";
251}
252
253//===----------------------------------------------------------------------===//
254// Instruction Class Templates
255//===----------------------------------------------------------------------===//
256
257let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
258class CStackLoad<bits<3> funct3, string OpcodeStr,
259                 RegisterClass cls, DAGOperand opnd>
260    : RVInst16CI<funct3, 0b10, (outs cls:$rd), (ins SPMem:$rs1, opnd:$imm),
261                 OpcodeStr, "$rd, ${imm}(${rs1})">;
262
263let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
264class CStackStore<bits<3> funct3, string OpcodeStr,
265                  RegisterClass cls, DAGOperand opnd>
266    : RVInst16CSS<funct3, 0b10, (outs), (ins cls:$rs2, SPMem:$rs1, opnd:$imm),
267                  OpcodeStr, "$rs2, ${imm}(${rs1})">;
268
269let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
270class CLoad_ri<bits<3> funct3, string OpcodeStr,
271               RegisterClass cls, DAGOperand opnd>
272    : RVInst16CL<funct3, 0b00, (outs cls:$rd), (ins GPRCMem:$rs1, opnd:$imm),
273                 OpcodeStr, "$rd, ${imm}(${rs1})">;
274
275let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
276class CStore_rri<bits<3> funct3, string OpcodeStr,
277                 RegisterClass cls, DAGOperand opnd>
278    : RVInst16CS<funct3, 0b00, (outs), (ins cls:$rs2,GPRCMem:$rs1, opnd:$imm),
279                 OpcodeStr, "$rs2, ${imm}(${rs1})">;
280
281let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
282class Bcz<bits<3> funct3, string OpcodeStr,
283          RegisterClass cls>
284    : RVInst16CB<funct3, 0b01, (outs), (ins cls:$rs1, simm9_lsb0:$imm),
285                 OpcodeStr, "$rs1, $imm"> {
286  let isBranch = 1;
287  let isTerminator = 1;
288  let Inst{12} = imm{7};
289  let Inst{11-10} = imm{3-2};
290  let Inst{6-5} = imm{6-5};
291  let Inst{4-3} = imm{1-0};
292  let Inst{2} = imm{4};
293}
294
295let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
296class Shift_right<bits<2> funct2, string OpcodeStr, RegisterClass cls,
297                  Operand ImmOpnd>
298    : RVInst16CB<0b100, 0b01, (outs cls:$rs1_wb), (ins cls:$rs1, ImmOpnd:$imm),
299                 OpcodeStr, "$rs1, $imm"> {
300  let Constraints = "$rs1 = $rs1_wb";
301  let Inst{12} = imm{5};
302  let Inst{11-10} = funct2;
303  let Inst{6-2} = imm{4-0};
304}
305
306let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
307class CA_ALU<bits<6> funct6, bits<2> funct2, string OpcodeStr,
308             RegisterClass cls>
309    : RVInst16CA<funct6, funct2, 0b01, (outs cls:$rd_wb), (ins cls:$rd, cls:$rs2),
310                 OpcodeStr, "$rd, $rs2"> {
311  bits<3> rd;
312  let Constraints = "$rd = $rd_wb";
313  let Inst{9-7} = rd;
314}
315
316//===----------------------------------------------------------------------===//
317// Instructions
318//===----------------------------------------------------------------------===//
319
320let Predicates = [HasStdExtCOrZca] in {
321
322let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [X2] in
323def C_ADDI4SPN : RVInst16CIW<0b000, 0b00, (outs GPRC:$rd),
324                             (ins SP:$rs1, uimm10_lsb00nonzero:$imm),
325                             "c.addi4spn", "$rd, $rs1, $imm">,
326                             Sched<[WriteIALU, ReadIALU]> {
327  bits<5> rs1;
328  let Inst{12-11} = imm{5-4};
329  let Inst{10-7} = imm{9-6};
330  let Inst{6} = imm{2};
331  let Inst{5} = imm{3};
332}
333
334let Predicates = [HasStdExtCOrZcd, HasStdExtD] in
335def C_FLD  : CLoad_ri<0b001, "c.fld", FPR64C, uimm8_lsb000>,
336             Sched<[WriteFLD64, ReadMemBase]> {
337  bits<8> imm;
338  let Inst{12-10} = imm{5-3};
339  let Inst{6-5} = imm{7-6};
340}
341
342def C_LW : CLoad_ri<0b010, "c.lw", GPRC, uimm7_lsb00>,
343           Sched<[WriteLDW, ReadMemBase]> {
344  bits<7> imm;
345  let Inst{12-10} = imm{5-3};
346  let Inst{6} = imm{2};
347  let Inst{5} = imm{6};
348}
349
350let DecoderNamespace = "RISCV32Only_",
351    Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in
352def C_FLW  : CLoad_ri<0b011, "c.flw", FPR32C, uimm7_lsb00>,
353             Sched<[WriteFLD32, ReadMemBase]> {
354  bits<7> imm;
355  let Inst{12-10} = imm{5-3};
356  let Inst{6} = imm{2};
357  let Inst{5} = imm{6};
358}
359
360let Predicates = [HasStdExtCOrZca, IsRV64] in
361def C_LD : CLoad_ri<0b011, "c.ld", GPRC, uimm8_lsb000>,
362           Sched<[WriteLDD, ReadMemBase]> {
363  bits<8> imm;
364  let Inst{12-10} = imm{5-3};
365  let Inst{6-5} = imm{7-6};
366}
367
368let Predicates = [HasStdExtCOrZcd, HasStdExtD] in
369def C_FSD  : CStore_rri<0b101, "c.fsd", FPR64C, uimm8_lsb000>,
370             Sched<[WriteFST64, ReadStoreData, ReadMemBase]> {
371  bits<8> imm;
372  let Inst{12-10} = imm{5-3};
373  let Inst{6-5} = imm{7-6};
374}
375
376def C_SW : CStore_rri<0b110, "c.sw", GPRC, uimm7_lsb00>,
377           Sched<[WriteSTW, ReadStoreData, ReadMemBase]> {
378  bits<7> imm;
379  let Inst{12-10} = imm{5-3};
380  let Inst{6} = imm{2};
381  let Inst{5} = imm{6};
382}
383
384let DecoderNamespace = "RISCV32Only_",
385    Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32]  in
386def C_FSW  : CStore_rri<0b111, "c.fsw", FPR32C, uimm7_lsb00>,
387             Sched<[WriteFST32, ReadStoreData, ReadMemBase]> {
388  bits<7> imm;
389  let Inst{12-10} = imm{5-3};
390  let Inst{6} = imm{2};
391  let Inst{5} = imm{6};
392}
393
394let Predicates = [HasStdExtCOrZca, IsRV64] in
395def C_SD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000>,
396           Sched<[WriteSTD, ReadStoreData, ReadMemBase]> {
397  bits<8> imm;
398  let Inst{12-10} = imm{5-3};
399  let Inst{6-5} = imm{7-6};
400}
401
402let rd = 0, imm = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
403def C_NOP : RVInst16CI<0b000, 0b01, (outs), (ins), "c.nop", "">,
404            Sched<[WriteNop]> {
405  let Inst{6-2} = 0;
406}
407
408let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
409def C_ADDI : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb),
410                        (ins GPRNoX0:$rd, simm6nonzero:$imm),
411                        "c.addi", "$rd, $imm">,
412             Sched<[WriteIALU, ReadIALU]> {
413  let Constraints = "$rd = $rd_wb";
414  let Inst{6-2} = imm{4-0};
415}
416
417let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
418def C_ADDI_NOP : RVInst16CI<0b000, 0b01, (outs GPRX0:$rd_wb),
419                            (ins GPRX0:$rd, immzero:$imm),
420                            "c.addi", "$rd, $imm">,
421                 Sched<[WriteIALU, ReadIALU]> {
422  let Constraints = "$rd = $rd_wb";
423  let Inst{6-2} = 0;
424  let isAsmParserOnly = 1;
425}
426
427let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1,
428    DecoderNamespace = "RISCV32Only_", Defs = [X1],
429    Predicates = [HasStdExtCOrZca, IsRV32]  in
430def C_JAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset),
431                       "c.jal", "$offset">, Sched<[WriteJal]>;
432
433let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
434    Predicates = [HasStdExtCOrZca, IsRV64] in
435def C_ADDIW : RVInst16CI<0b001, 0b01, (outs GPRNoX0:$rd_wb),
436                         (ins GPRNoX0:$rd, simm6:$imm),
437                         "c.addiw", "$rd, $imm">,
438              Sched<[WriteIALU32, ReadIALU32]> {
439  let Constraints = "$rd = $rd_wb";
440  let Inst{6-2} = imm{4-0};
441}
442
443let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
444def C_LI : RVInst16CI<0b010, 0b01, (outs GPRNoX0:$rd), (ins simm6:$imm),
445                      "c.li", "$rd, $imm">,
446           Sched<[WriteIALU]> {
447  let Inst{6-2} = imm{4-0};
448}
449
450let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
451def C_ADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb),
452                            (ins SP:$rd, simm10_lsb0000nonzero:$imm),
453                            "c.addi16sp", "$rd, $imm">,
454                 Sched<[WriteIALU, ReadIALU]> {
455  let Constraints = "$rd = $rd_wb";
456  let Inst{12} = imm{9};
457  let Inst{11-7} = 2;
458  let Inst{6} = imm{4};
459  let Inst{5} = imm{6};
460  let Inst{4-3} = imm{8-7};
461  let Inst{2} = imm{5};
462}
463
464let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
465def C_LUI : RVInst16CI<0b011, 0b01, (outs GPRNoX0X2:$rd),
466                       (ins c_lui_imm:$imm),
467                       "c.lui", "$rd, $imm">,
468            Sched<[WriteIALU]> {
469  let Inst{6-2} = imm{4-0};
470}
471
472def C_SRLI : Shift_right<0b00, "c.srli", GPRC, uimmlog2xlennonzero>,
473             Sched<[WriteShiftImm, ReadShiftImm]>;
474def C_SRAI : Shift_right<0b01, "c.srai", GPRC, uimmlog2xlennonzero>,
475             Sched<[WriteShiftImm, ReadShiftImm]>;
476
477let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
478def C_ANDI : RVInst16CB<0b100, 0b01, (outs GPRC:$rs1_wb), (ins GPRC:$rs1, simm6:$imm),
479                        "c.andi", "$rs1, $imm">,
480             Sched<[WriteIALU, ReadIALU]> {
481  let Constraints = "$rs1 = $rs1_wb";
482  let Inst{12} = imm{5};
483  let Inst{11-10} = 0b10;
484  let Inst{6-2} = imm{4-0};
485}
486
487def C_SUB  : CA_ALU<0b100011, 0b00, "c.sub", GPRC>,
488             Sched<[WriteIALU, ReadIALU, ReadIALU]>;
489def C_XOR  : CA_ALU<0b100011, 0b01, "c.xor", GPRC>,
490             Sched<[WriteIALU, ReadIALU, ReadIALU]>;
491def C_OR   : CA_ALU<0b100011, 0b10, "c.or" , GPRC>,
492             Sched<[WriteIALU, ReadIALU, ReadIALU]>;
493def C_AND  : CA_ALU<0b100011, 0b11, "c.and", GPRC>,
494             Sched<[WriteIALU, ReadIALU, ReadIALU]>;
495
496let Predicates = [HasStdExtCOrZca, IsRV64] in {
497def C_SUBW : CA_ALU<0b100111, 0b00, "c.subw", GPRC>,
498             Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
499def C_ADDW : CA_ALU<0b100111, 0b01, "c.addw", GPRC>,
500             Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
501}
502
503let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
504def C_J : RVInst16CJ<0b101, 0b01, (outs), (ins simm12_lsb0:$offset),
505                     "c.j", "$offset">, Sched<[WriteJmp]> {
506  let isBranch = 1;
507  let isTerminator=1;
508  let isBarrier=1;
509}
510
511def C_BEQZ : Bcz<0b110, "c.beqz", GPRC>, Sched<[WriteJmp, ReadJmp]>;
512def C_BNEZ : Bcz<0b111, "c.bnez", GPRC>, Sched<[WriteJmp, ReadJmp]>;
513
514let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
515def C_SLLI : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb),
516                        (ins GPRNoX0:$rd, uimmlog2xlennonzero:$imm),
517                        "c.slli", "$rd, $imm">,
518             Sched<[WriteShiftImm, ReadShiftImm]> {
519  let Constraints = "$rd = $rd_wb";
520  let Inst{6-2} = imm{4-0};
521}
522
523let Predicates = [HasStdExtCOrZcd, HasStdExtD] in
524def C_FLDSP  : CStackLoad<0b001, "c.fldsp", FPR64, uimm9_lsb000>,
525               Sched<[WriteFLD64, ReadMemBase]> {
526  let Inst{6-5} = imm{4-3};
527  let Inst{4-2} = imm{8-6};
528}
529
530def C_LWSP : CStackLoad<0b010, "c.lwsp", GPRNoX0, uimm8_lsb00>,
531             Sched<[WriteLDW, ReadMemBase]> {
532  let Inst{6-4} = imm{4-2};
533  let Inst{3-2} = imm{7-6};
534}
535
536let DecoderNamespace = "RISCV32Only_",
537    Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in
538def C_FLWSP  : CStackLoad<0b011, "c.flwsp", FPR32, uimm8_lsb00>,
539               Sched<[WriteFLD32, ReadMemBase]> {
540  let Inst{6-4} = imm{4-2};
541  let Inst{3-2} = imm{7-6};
542}
543
544let Predicates = [HasStdExtCOrZca, IsRV64] in
545def C_LDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000>,
546             Sched<[WriteLDD, ReadMemBase]> {
547  let Inst{6-5} = imm{4-3};
548  let Inst{4-2} = imm{8-6};
549}
550
551let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
552def C_JR : RVInst16CR<0b1000, 0b10, (outs), (ins GPRNoX0:$rs1),
553                      "c.jr", "$rs1">, Sched<[WriteJalr, ReadJalr]> {
554  let isBarrier = 1;
555  let isTerminator = 1;
556  let rs2 = 0;
557}
558
559let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveReg = 1,
560    isAsCheapAsAMove = 1 in
561def C_MV : RVInst16CR<0b1000, 0b10, (outs GPRNoX0:$rs1), (ins GPRNoX0:$rs2),
562                      "c.mv", "$rs1, $rs2">,
563           Sched<[WriteIALU, ReadIALU]>;
564
565let rs1 = 0, rs2 = 0, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
566def C_EBREAK : RVInst16CR<0b1001, 0b10, (outs), (ins), "c.ebreak", "">, Sched<[]>;
567
568let hasSideEffects = 0, mayLoad = 0, mayStore = 0,
569    isCall=1, Defs=[X1], rs2 = 0 in
570def C_JALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPRNoX0:$rs1),
571                        "c.jalr", "$rs1">, Sched<[WriteJalr, ReadJalr]>;
572
573let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
574def C_ADD : RVInst16CR<0b1001, 0b10, (outs GPRNoX0:$rs1_wb),
575                       (ins GPRNoX0:$rs1, GPRNoX0:$rs2),
576                       "c.add", "$rs1, $rs2">,
577            Sched<[WriteIALU, ReadIALU, ReadIALU]> {
578  let Constraints = "$rs1 = $rs1_wb";
579}
580
581let Predicates = [HasStdExtCOrZcd, HasStdExtD] in
582def C_FSDSP  : CStackStore<0b101, "c.fsdsp", FPR64, uimm9_lsb000>,
583               Sched<[WriteFST64, ReadStoreData, ReadMemBase]> {
584  let Inst{12-10} = imm{5-3};
585  let Inst{9-7}   = imm{8-6};
586}
587
588def C_SWSP : CStackStore<0b110, "c.swsp", GPR, uimm8_lsb00>,
589             Sched<[WriteSTW, ReadStoreData, ReadMemBase]> {
590  let Inst{12-9} = imm{5-2};
591  let Inst{8-7}  = imm{7-6};
592}
593
594let DecoderNamespace = "RISCV32Only_",
595    Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in
596def C_FSWSP  : CStackStore<0b111, "c.fswsp", FPR32, uimm8_lsb00>,
597               Sched<[WriteFST32, ReadStoreData, ReadMemBase]> {
598  let Inst{12-9} = imm{5-2};
599  let Inst{8-7}  = imm{7-6};
600}
601
602let Predicates = [HasStdExtCOrZca, IsRV64] in
603def C_SDSP : CStackStore<0b111, "c.sdsp", GPR, uimm9_lsb000>,
604             Sched<[WriteSTD, ReadStoreData, ReadMemBase]> {
605  let Inst{12-10} = imm{5-3};
606  let Inst{9-7}   = imm{8-6};
607}
608
609// The all zeros pattern isn't a valid RISC-V instruction. It's used by GNU
610// binutils as 16-bit instruction known to be unimplemented (i.e., trapping).
611let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
612def C_UNIMP : RVInst16<(outs), (ins), "c.unimp", "", [], InstFormatOther>,
613              Sched<[]> {
614  let Inst{15-0} = 0;
615}
616
617} // Predicates = [HasStdExtCOrZca]
618
619//===----------------------------------------------------------------------===//
620// HINT Instructions
621//===----------------------------------------------------------------------===//
622
623let Predicates = [HasStdExtCOrZca, HasRVCHints], hasSideEffects = 0, mayLoad = 0,
624    mayStore = 0 in {
625
626let rd = 0 in
627def C_NOP_HINT : RVInst16CI<0b000, 0b01, (outs), (ins simm6nonzero:$imm),
628                            "c.nop", "$imm">, Sched<[WriteNop]> {
629  let Inst{6-2} = imm{4-0};
630}
631
632def C_ADDI_HINT_IMM_ZERO : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb),
633                                      (ins GPRNoX0:$rd, immzero:$imm),
634                                      "c.addi", "$rd, $imm">,
635                           Sched<[WriteIALU, ReadIALU]> {
636  let Constraints = "$rd = $rd_wb";
637  let Inst{12} = 0;
638  let Inst{6-2} = 0;
639  let DecoderMethod = "decodeRVCInstrRdRs1ImmZero";
640}
641
642def C_LI_HINT : RVInst16CI<0b010, 0b01, (outs GPRX0:$rd), (ins simm6:$imm),
643                           "c.li", "$rd, $imm">,
644                Sched<[WriteIALU]> {
645  let Inst{6-2} = imm{4-0};
646  let Inst{11-7} = 0;
647  let DecoderMethod = "decodeRVCInstrRdSImm";
648}
649
650def C_LUI_HINT : RVInst16CI<0b011, 0b01, (outs GPRX0:$rd),
651                            (ins c_lui_imm:$imm),
652                            "c.lui", "$rd, $imm">,
653                 Sched<[WriteIALU]> {
654  let Inst{6-2} = imm{4-0};
655  let Inst{11-7} = 0;
656  let DecoderMethod = "decodeRVCInstrRdSImm";
657}
658
659def C_MV_HINT : RVInst16CR<0b1000, 0b10, (outs GPRX0:$rs1), (ins GPRNoX0:$rs2),
660                           "c.mv", "$rs1, $rs2">, Sched<[WriteIALU, ReadIALU]> {
661  let Inst{11-7} = 0;
662  let DecoderMethod = "decodeRVCInstrRdRs2";
663}
664
665def C_ADD_HINT : RVInst16CR<0b1001, 0b10, (outs GPRX0:$rs1_wb),
666                            (ins GPRX0:$rs1, GPRNoX0:$rs2),
667                            "c.add", "$rs1, $rs2">,
668                 Sched<[WriteIALU, ReadIALU, ReadIALU]> {
669  let Constraints = "$rs1 = $rs1_wb";
670  let Inst{11-7} = 0;
671  let DecoderMethod = "decodeRVCInstrRdRs1Rs2";
672}
673
674def C_SLLI_HINT : RVInst16CI<0b000, 0b10, (outs GPRX0:$rd_wb),
675                             (ins GPRX0:$rd, uimmlog2xlennonzero:$imm),
676                             "c.slli", "$rd, $imm">,
677                  Sched<[WriteShiftImm, ReadShiftImm]> {
678  let Constraints = "$rd = $rd_wb";
679  let Inst{6-2} = imm{4-0};
680  let Inst{11-7} = 0;
681  let DecoderMethod = "decodeRVCInstrRdRs1UImm";
682}
683
684def C_SLLI64_HINT : RVInst16CI<0b000, 0b10, (outs GPR:$rd_wb), (ins GPR:$rd),
685                               "c.slli64", "$rd">,
686                    Sched<[WriteShiftImm, ReadShiftImm]> {
687  let Constraints = "$rd = $rd_wb";
688  let Inst{6-2} = 0;
689  let Inst{12} = 0;
690}
691
692def C_SRLI64_HINT : RVInst16CI<0b100, 0b01, (outs GPRC:$rd_wb),
693                               (ins GPRC:$rd),
694                               "c.srli64", "$rd">,
695                    Sched<[WriteShiftImm, ReadShiftImm]> {
696  let Constraints = "$rd = $rd_wb";
697  let Inst{6-2} = 0;
698  let Inst{11-10} = 0;
699  let Inst{12} = 0;
700}
701
702def C_SRAI64_HINT : RVInst16CI<0b100, 0b01, (outs GPRC:$rd_wb),
703                               (ins GPRC:$rd),
704                               "c.srai64", "$rd">,
705                    Sched<[WriteShiftImm, ReadShiftImm]> {
706  let Constraints = "$rd = $rd_wb";
707  let Inst{6-2} = 0;
708  let Inst{11-10} = 1;
709  let Inst{12} = 0;
710}
711
712} // Predicates = [HasStdExtCOrZca, HasRVCHints], hasSideEffects = 0, mayLoad = 0,
713  // mayStore = 0
714
715//===----------------------------------------------------------------------===//
716// Assembler Pseudo Instructions
717//===----------------------------------------------------------------------===//
718
719let Predicates = [HasStdExtCOrZca, HasRVCHints] in {
720// Just a different syntax for the c.nop hint: c.addi x0, simm6 vs c.nop simm6.
721def : InstAlias<"c.addi x0, $imm", (C_NOP_HINT simm6nonzero:$imm), 0>;
722}
723
724let Predicates = [HasStdExtC, HasRVCHints, HasStdExtZihintntl] in {
725def : InstAlias<"c.ntl.p1", (C_ADD_HINT X0, X2)>;
726def : InstAlias<"c.ntl.pall", (C_ADD_HINT X0, X3)>;
727def : InstAlias<"c.ntl.s1", (C_ADD_HINT X0, X4)>;
728def : InstAlias<"c.ntl.all", (C_ADD_HINT X0, X5)>;
729} // Predicates = [HasStdExtC, HasRVCHints, HasStdExtZihintntl]
730
731let EmitPriority = 0 in {
732let Predicates = [HasStdExtCOrZca] in {
733def : InstAlias<"c.lw $rd, (${rs1})", (C_LW GPRC:$rd, GPRCMem:$rs1, 0)>;
734def : InstAlias<"c.sw $rs2, (${rs1})", (C_SW GPRC:$rs2, GPRCMem:$rs1, 0)>;
735def : InstAlias<"c.lwsp $rd, (${rs1})", (C_LWSP GPRC:$rd, SPMem:$rs1, 0)>;
736def : InstAlias<"c.swsp $rs2, (${rs1})", (C_SWSP GPRC:$rs2, SPMem:$rs1, 0)>;
737}
738
739let Predicates = [HasStdExtCOrZca, IsRV64] in {
740def : InstAlias<"c.ld $rd, (${rs1})", (C_LD GPRC:$rd, GPRCMem:$rs1, 0)>;
741def : InstAlias<"c.sd $rs2, (${rs1})", (C_SD GPRC:$rs2, GPRCMem:$rs1, 0)>;
742def : InstAlias<"c.ldsp $rd, (${rs1})", (C_LDSP GPRC:$rd, SPMem:$rs1, 0)>;
743def : InstAlias<"c.sdsp $rs2, (${rs1})", (C_SDSP GPRC:$rs2, SPMem:$rs1, 0)>;
744}
745
746let Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in {
747def : InstAlias<"c.flw $rd, (${rs1})", (C_FLW FPR32C:$rd, GPRCMem:$rs1, 0)>;
748def : InstAlias<"c.fsw $rs2, (${rs1})", (C_FSW FPR32C:$rs2, GPRCMem:$rs1, 0)>;
749def : InstAlias<"c.flwsp $rd, (${rs1})", (C_FLWSP FPR32C:$rd, SPMem:$rs1, 0)>;
750def : InstAlias<"c.fswsp $rs2, (${rs1})", (C_FSWSP FPR32C:$rs2, SPMem:$rs1, 0)>;
751}
752
753let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
754def : InstAlias<"c.fld $rd, (${rs1})", (C_FLD FPR64C:$rd, GPRCMem:$rs1, 0)>;
755def : InstAlias<"c.fsd $rs2, (${rs1})", (C_FSD FPR64C:$rs2, GPRCMem:$rs1, 0)>;
756def : InstAlias<"c.fldsp $rd, (${rs1})", (C_FLDSP FPR64C:$rd, SPMem:$rs1, 0)>;
757def : InstAlias<"c.fsdsp $rs2, (${rs1})", (C_FSDSP FPR64C:$rs2, SPMem:$rs1, 0)>;
758}
759} // EmitPriority = 0
760
761//===----------------------------------------------------------------------===//
762// .insn directive instructions
763//===----------------------------------------------------------------------===//
764
765def AnyRegCOperand : AsmOperandClass {
766  let Name = "AnyRegCOperand";
767  let RenderMethod = "addRegOperands";
768  let PredicateMethod = "isAnyRegC";
769}
770
771def AnyRegC : Operand<XLenVT> {
772  let OperandType = "OPERAND_REGISTER";
773  let ParserMatchClass = AnyRegCOperand;
774}
775
776// isCodeGenOnly = 1 to hide them from the tablegened assembly parser.
777let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,
778    hasNoSchedulingInfo = 1, Predicates = [HasStdExtCOrZca] in {
779def InsnCR : DirectiveInsnCR<(outs AnyReg:$rd), (ins uimm2_opcode:$opcode,
780                                                     uimm4:$funct4,
781                                                     AnyReg:$rs2),
782                             "$opcode, $funct4, $rd, $rs2">;
783def InsnCI : DirectiveInsnCI<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
784                                                      uimm3:$funct3,
785                                                      simm6:$imm6),
786                             "$opcode, $funct3, $rd, $imm6">;
787def InsnCIW : DirectiveInsnCIW<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
788                                                        uimm3:$funct3,
789                                                        uimm8:$imm8),
790                               "$opcode, $funct3, $rd, $imm8">;
791def InsnCSS : DirectiveInsnCSS<(outs), (ins uimm2_opcode:$opcode,
792                                            uimm3:$funct3,
793                                            AnyReg:$rs2,
794                                            uimm6:$imm6),
795                               "$opcode, $funct3, $rs2, $imm6">;
796def InsnCL : DirectiveInsnCL<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
797                                                      uimm3:$funct3,
798                                                      AnyRegC:$rs1,
799                                                      uimm5:$imm5),
800                             "$opcode, $funct3, $rd, ${imm5}(${rs1})">;
801def InsnCS : DirectiveInsnCS<(outs), (ins uimm2_opcode:$opcode,
802                                          uimm3:$funct3,
803                                          AnyRegC:$rs2,
804                                          AnyRegC:$rs1,
805                                          uimm5:$imm5),
806                             "$opcode, $funct3, $rs2, ${imm5}(${rs1})">;
807def InsnCA : DirectiveInsnCA<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
808                                                      uimm6:$funct6,
809                                                      uimm2:$funct2,
810                                                      AnyRegC:$rs2),
811                             "$opcode, $funct6, $funct2, $rd, $rs2">;
812def InsnCB : DirectiveInsnCB<(outs), (ins uimm2_opcode:$opcode, uimm3:$funct3,
813                                          AnyRegC:$rs1,
814                                          simm9_lsb0:$imm8),
815                             "$opcode, $funct3, $rs1, $imm8">;
816def InsnCJ : DirectiveInsnCJ<(outs), (ins uimm2_opcode:$opcode,
817                                          uimm3:$funct3,
818                                          simm12_lsb0:$imm11),
819                             "$opcode, $funct3, $imm11">;
820}
821
822// Use InstAliases to match these so that we can combine the insn and format
823// into a mnemonic to use as the key for the tablegened asm matcher table. The
824// parser will take care of creating these fake mnemonics and will only do it
825// for known formats.
826let EmitPriority = 0, Predicates = [HasStdExtCOrZca] in {
827def : InstAlias<".insn_cr $opcode, $funct4, $rd, $rs2",
828                (InsnCR AnyReg:$rd, uimm2_opcode:$opcode, uimm4:$funct4,
829                        AnyReg:$rs2)>;
830def : InstAlias<".insn_ci $opcode, $funct3, $rd, $imm6",
831                (InsnCI AnyRegC:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
832                        simm6:$imm6)>;
833def : InstAlias<".insn_ciw $opcode, $funct3, $rd, $imm8",
834                (InsnCIW AnyRegC:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
835                         uimm8:$imm8)>;
836def : InstAlias<".insn_css $opcode, $funct3, $rs2, $imm6",
837                (InsnCSS uimm2_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
838                         uimm6:$imm6)>;
839def : InstAlias<".insn_cl $opcode, $funct3, $rd, ${imm5}(${rs1})",
840                (InsnCL AnyRegC:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
841                        AnyRegC:$rs1, uimm5:$imm5)>;
842def : InstAlias<".insn_cs $opcode, $funct3, $rs2, ${imm5}(${rs1})",
843                (InsnCS uimm2_opcode:$opcode, uimm3:$funct3, AnyRegC:$rs2,
844                        AnyRegC:$rs1, uimm5:$imm5)>;
845def : InstAlias<".insn_ca $opcode, $funct6, $funct2, $rd, $rs2",
846                (InsnCA AnyRegC:$rd, uimm2_opcode:$opcode, uimm6:$funct6,
847                        uimm2:$funct2, AnyRegC:$rs2)>;
848def : InstAlias<".insn_cb $opcode, $funct3, $rs1, $imm8",
849                (InsnCB uimm2_opcode:$opcode, uimm3:$funct3, AnyRegC:$rs1,
850                        simm9_lsb0:$imm8)>;
851def : InstAlias<".insn_cj $opcode, $funct3, $imm11",
852                (InsnCJ uimm2_opcode:$opcode, uimm3:$funct3, simm12_lsb0:$imm11)>;
853}
854
855//===----------------------------------------------------------------------===/i
856// Compress Instruction tablegen backend.
857//===----------------------------------------------------------------------===//
858
859// Patterns are defined in the same order the compressed instructions appear
860// on page 82 of the ISA manual.
861
862// Quadrant 0
863let Predicates = [HasStdExtCOrZca] in {
864def : CompressPat<(ADDI GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm),
865                  (C_ADDI4SPN GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm)>;
866} // Predicates = [HasStdExtCOrZca]
867
868let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
869def : CompressPat<(FLD FPR64C:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm),
870                  (C_FLD FPR64C:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
871} // Predicates = [HasStdExtCOrZcd, HasStdExtD]
872
873let Predicates = [HasStdExtCOrZca] in {
874def : CompressPat<(LW GPRC:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm),
875                  (C_LW GPRC:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm)>;
876} // Predicates = [HasStdExtCOrZca]
877
878let Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in {
879def : CompressPat<(FLW FPR32C:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm),
880                  (C_FLW FPR32C:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm)>;
881} // Predicates = [HasStdExtC, HasStdExtF, IsRV32]
882
883let Predicates = [HasStdExtCOrZca, IsRV64] in {
884def : CompressPat<(LD GPRC:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm),
885                  (C_LD GPRC:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
886} // Predicates = [HasStdExtCOrZca, IsRV64]
887
888let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
889def : CompressPat<(FSD FPR64C:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm),
890                  (C_FSD FPR64C:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
891} // Predicates = [HasStdExtCOrZcd, HasStdExtD]
892
893let Predicates = [HasStdExtCOrZca] in {
894def : CompressPat<(SW GPRC:$rs2, GPRCMem:$rs1, uimm7_lsb00:$imm),
895                  (C_SW GPRC:$rs2, GPRCMem:$rs1, uimm7_lsb00:$imm)>;
896} // Predicates = [HasStdExtCOrZca]
897
898let Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in {
899def : CompressPat<(FSW FPR32C:$rs2, GPRCMem:$rs1, uimm7_lsb00:$imm),
900                  (C_FSW FPR32C:$rs2, GPRCMem:$rs1, uimm7_lsb00:$imm)>;
901} // Predicates = [HasStdExtC, HasStdExtF, IsRV32]
902
903let Predicates = [HasStdExtCOrZca, IsRV64] in {
904def : CompressPat<(SD GPRC:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm),
905                  (C_SD GPRC:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
906} // Predicates = [HasStdExtCOrZca, IsRV64]
907
908// Quadrant 1
909let Predicates = [HasStdExtCOrZca] in {
910def : CompressPat<(ADDI X0, X0, 0), (C_NOP)>;
911def : CompressPat<(ADDI GPRNoX0:$rs1, GPRNoX0:$rs1, simm6nonzero:$imm),
912                  (C_ADDI GPRNoX0:$rs1, simm6nonzero:$imm)>;
913} // Predicates = [HasStdExtCOrZca]
914
915let Predicates = [HasStdExtCOrZca, IsRV32] in {
916def : CompressPat<(JAL X1, simm12_lsb0:$offset),
917                  (C_JAL simm12_lsb0:$offset)>;
918} // Predicates = [HasStdExtCOrZca, IsRV32]
919
920let Predicates = [HasStdExtCOrZca, IsRV64] in {
921def : CompressPat<(ADDIW GPRNoX0:$rs1, GPRNoX0:$rs1, simm6:$imm),
922                  (C_ADDIW GPRNoX0:$rs1, simm6:$imm)>;
923} // Predicates = [HasStdExtCOrZca, IsRV64]
924
925let Predicates = [HasStdExtCOrZca] in {
926def : CompressPat<(ADDI GPRNoX0:$rd, X0, simm6:$imm),
927                  (C_LI GPRNoX0:$rd, simm6:$imm)>;
928def : CompressPat<(ADDI X2, X2, simm10_lsb0000nonzero:$imm),
929                  (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
930def : CompressPat<(LUI GPRNoX0X2:$rd, c_lui_imm:$imm),
931                  (C_LUI GPRNoX0X2:$rd, c_lui_imm:$imm)>;
932def : CompressPat<(SRLI GPRC:$rs1, GPRC:$rs1, uimmlog2xlennonzero:$imm),
933                  (C_SRLI GPRC:$rs1, uimmlog2xlennonzero:$imm)>;
934def : CompressPat<(SRAI GPRC:$rs1, GPRC:$rs1, uimmlog2xlennonzero:$imm),
935                  (C_SRAI GPRC:$rs1, uimmlog2xlennonzero:$imm)>;
936def : CompressPat<(ANDI GPRC:$rs1, GPRC:$rs1, simm6:$imm),
937                  (C_ANDI GPRC:$rs1, simm6:$imm)>;
938def : CompressPat<(SUB GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
939                  (C_SUB GPRC:$rs1, GPRC:$rs2)>;
940def : CompressPat<(XOR GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
941                  (C_XOR GPRC:$rs1, GPRC:$rs2)>;
942let isCompressOnly = true in
943def : CompressPat<(XOR GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
944                  (C_XOR GPRC:$rs1, GPRC:$rs2)>;
945def : CompressPat<(OR GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
946                  (C_OR GPRC:$rs1, GPRC:$rs2)>;
947let isCompressOnly = true in
948def : CompressPat<(OR GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
949                  (C_OR GPRC:$rs1, GPRC:$rs2)>;
950def : CompressPat<(AND GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
951                  (C_AND GPRC:$rs1, GPRC:$rs2)>;
952let isCompressOnly = true in
953def : CompressPat<(AND GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
954                  (C_AND GPRC:$rs1, GPRC:$rs2)>;
955} // Predicates = [HasStdExtCOrZca]
956
957let Predicates = [HasStdExtCOrZca, IsRV64] in {
958let isCompressOnly = true in
959def : CompressPat<(ADDIW GPRNoX0:$rd, X0, simm6:$imm),
960                  (C_LI GPRNoX0:$rd, simm6:$imm)>;
961def : CompressPat<(SUBW GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
962                  (C_SUBW GPRC:$rs1, GPRC:$rs2)>;
963def : CompressPat<(ADDW GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
964                   (C_ADDW GPRC:$rs1, GPRC:$rs2)>;
965let isCompressOnly = true in
966def : CompressPat<(ADDW GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
967                   (C_ADDW GPRC:$rs1, GPRC:$rs2)>;
968} // Predicates = [HasStdExtCOrZca, IsRV64]
969
970let Predicates = [HasStdExtCOrZca] in {
971def : CompressPat<(JAL X0, simm12_lsb0:$offset),
972                  (C_J simm12_lsb0:$offset)>;
973def : CompressPat<(BEQ GPRC:$rs1, X0, simm9_lsb0:$imm),
974                  (C_BEQZ GPRC:$rs1, simm9_lsb0:$imm)>;
975def : CompressPat<(BNE GPRC:$rs1, X0, simm9_lsb0:$imm),
976                  (C_BNEZ GPRC:$rs1, simm9_lsb0:$imm)>;
977} // Predicates = [HasStdExtCOrZca]
978
979// Quadrant 2
980let Predicates = [HasStdExtCOrZca] in {
981def : CompressPat<(SLLI GPRNoX0:$rs1, GPRNoX0:$rs1, uimmlog2xlennonzero:$imm),
982                  (C_SLLI GPRNoX0:$rs1, uimmlog2xlennonzero:$imm)>;
983} // Predicates = [HasStdExtCOrZca]
984
985let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
986def : CompressPat<(FLD FPR64:$rd, SPMem:$rs1, uimm9_lsb000:$imm),
987                  (C_FLDSP FPR64:$rd, SPMem:$rs1, uimm9_lsb000:$imm)>;
988} // Predicates = [HasStdExtCOrZcd, HasStdExtD]
989
990let Predicates = [HasStdExtCOrZca] in {
991def : CompressPat<(LW GPRNoX0:$rd, SPMem:$rs1,  uimm8_lsb00:$imm),
992                  (C_LWSP GPRNoX0:$rd, SPMem:$rs1, uimm8_lsb00:$imm)>;
993} // Predicates = [HasStdExtCOrZca]
994
995let Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in {
996def : CompressPat<(FLW FPR32:$rd, SPMem:$rs1, uimm8_lsb00:$imm),
997                  (C_FLWSP FPR32:$rd, SPMem:$rs1, uimm8_lsb00:$imm)>;
998} // Predicates = [HasStdExtC, HasStdExtF, IsRV32]
999
1000let Predicates = [HasStdExtCOrZca, IsRV64] in {
1001def : CompressPat<(LD GPRNoX0:$rd, SPMem:$rs1, uimm9_lsb000:$imm),
1002                  (C_LDSP GPRNoX0:$rd, SPMem:$rs1, uimm9_lsb000:$imm)>;
1003} // Predicates = [HasStdExtCOrZca, IsRV64]
1004
1005let Predicates = [HasStdExtCOrZca] in {
1006def : CompressPat<(JALR X0, GPRNoX0:$rs1, 0),
1007                  (C_JR GPRNoX0:$rs1)>;
1008let isCompressOnly = true in {
1009def : CompressPat<(ADD GPRNoX0:$rs1, X0, GPRNoX0:$rs2),
1010                  (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1011def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs2, X0),
1012                  (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1013}
1014def : CompressPat<(ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, 0),
1015                  (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1016def : CompressPat<(EBREAK), (C_EBREAK)>;
1017def : CompressPat<(UNIMP), (C_UNIMP)>;
1018def : CompressPat<(JALR X1, GPRNoX0:$rs1, 0),
1019                  (C_JALR GPRNoX0:$rs1)>;
1020def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2),
1021                  (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1022let isCompressOnly = true in
1023def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs2, GPRNoX0:$rs1),
1024                  (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1025} // Predicates = [HasStdExtCOrZca]
1026
1027let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
1028def : CompressPat<(FSD FPR64:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
1029                  (C_FSDSP FPR64:$rs2, SPMem:$rs1, uimm9_lsb000:$imm)>;
1030} // Predicates = [HasStdExtCOrZcd, HasStdExtD]
1031
1032let Predicates = [HasStdExtCOrZca] in {
1033def : CompressPat<(SW GPR:$rs2, SPMem:$rs1, uimm8_lsb00:$imm),
1034                  (C_SWSP GPR:$rs2, SPMem:$rs1, uimm8_lsb00:$imm)>;
1035} // Predicates = [HasStdExtCOrZca]
1036
1037let Predicates = [HasStdExtCOrZcfOrZce, HasStdExtF, IsRV32] in {
1038def : CompressPat<(FSW FPR32:$rs2, SPMem:$rs1, uimm8_lsb00:$imm),
1039                  (C_FSWSP FPR32:$rs2, SPMem:$rs1, uimm8_lsb00:$imm)>;
1040} // Predicates = [HasStdExtC, HasStdExtF, IsRV32]
1041
1042let Predicates = [HasStdExtCOrZca, IsRV64] in {
1043def : CompressPat<(SD GPR:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
1044                  (C_SDSP GPR:$rs2, SPMem:$rs1, uimm9_lsb000:$imm)>;
1045} // Predicates = [HasStdExtCOrZca, IsRV64]
1046