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