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