xref: /llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td (revision 5d88a84ecddab3471693e44b57a1c1f21ce14f3f)
1//===-- RISCVInstrInfoZc.td - RISC-V 'Zc*' instructions ----*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// This file describes the RISC-V instructions from the 'Zc*' compressed
10/// instruction extensions, version 1.0.3.
11///
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// Operand and SDNode transformation definitions.
16//===----------------------------------------------------------------------===//
17
18def uimm2_lsb0 : RISCVOp,
19                 ImmLeaf<XLenVT, [{return isShiftedUInt<1, 1>(Imm);}]> {
20  let ParserMatchClass = UImmAsmOperand<2, "Lsb0">;
21  let EncoderMethod = "getImmOpValue";
22  let DecoderMethod = "decodeUImmOperand<2>";
23  let OperandType = "OPERAND_UIMM2_LSB0";
24  let MCOperandPredicate = [{
25    int64_t Imm;
26    if (!MCOp.evaluateAsConstantImm(Imm))
27      return false;
28    return isShiftedUInt<1, 1>(Imm);
29  }];
30}
31
32def uimm8ge32 : RISCVOp {
33  let ParserMatchClass = UImmAsmOperand<8, "GE32">;
34  let DecoderMethod = "decodeUImmOperand<8>";
35  let OperandType = "OPERAND_UIMM8_GE32";
36}
37
38def RlistAsmOperand : AsmOperandClass {
39  let Name = "Rlist";
40  let ParserMethod = "parseReglist";
41  let DiagnosticType = "InvalidRlist";
42}
43
44def StackAdjAsmOperand : AsmOperandClass {
45  let Name = "StackAdj";
46  let ParserMethod = "parseZcmpStackAdj";
47  let DiagnosticType = "InvalidStackAdj";
48  let PredicateMethod = "isSpimm";
49  let RenderMethod = "addSpimmOperands";
50}
51
52def NegStackAdjAsmOperand : AsmOperandClass {
53  let Name = "NegStackAdj";
54  let ParserMethod = "parseZcmpNegStackAdj";
55  let DiagnosticType = "InvalidStackAdj";
56  let PredicateMethod = "isSpimm";
57  let RenderMethod = "addSpimmOperands";
58}
59
60def rlist : Operand<OtherVT> {
61   let ParserMatchClass = RlistAsmOperand;
62   let PrintMethod = "printRlist";
63   let DecoderMethod = "decodeZcmpRlist";
64   let EncoderMethod = "getRlistOpValue";
65   let MCOperandPredicate = [{
66    int64_t Imm;
67    if (!MCOp.evaluateAsConstantImm(Imm))
68      return false;
69    // 0~3 Reserved for EABI
70    return isUInt<4>(Imm) && Imm >= 4;
71  }];
72}
73
74def stackadj : RISCVOp<OtherVT> {
75  let ParserMatchClass = StackAdjAsmOperand;
76  let PrintMethod = "printStackAdj";
77  let DecoderMethod = "decodeZcmpSpimm";
78  let OperandType = "OPERAND_SPIMM";
79  let MCOperandPredicate = [{
80    int64_t Imm;
81    if (!MCOp.evaluateAsConstantImm(Imm))
82      return false;
83    return isShiftedUInt<2, 4>(Imm);
84  }];
85}
86
87def negstackadj : RISCVOp<OtherVT> {
88  let ParserMatchClass = NegStackAdjAsmOperand;
89  let PrintMethod = "printNegStackAdj";
90  let DecoderMethod = "decodeZcmpSpimm";
91  let OperandType = "OPERAND_SPIMM";
92  let MCOperandPredicate = [{
93    int64_t Imm;
94    if (!MCOp.evaluateAsConstantImm(Imm))
95      return false;
96    return isShiftedUInt<2, 4>(Imm);
97  }];
98}
99
100//===----------------------------------------------------------------------===//
101// Instruction Class Templates
102//===----------------------------------------------------------------------===//
103
104let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
105class CLoadB_ri<bits<6> funct6, string OpcodeStr>
106    : RVInst16CLB<funct6, 0b00, (outs GPRC:$rd),
107                  (ins GPRCMem:$rs1, uimm2:$imm),
108                  OpcodeStr, "$rd, ${imm}(${rs1})"> {
109  bits<2> imm;
110
111  let Inst{6-5} = imm{0,1};
112}
113
114let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
115class CLoadH_ri<bits<6> funct6, bit funct1, string OpcodeStr,
116                DAGOperand rty = GPRC>
117    : RVInst16CLH<funct6, funct1, 0b00, (outs rty:$rd),
118                  (ins GPRCMem:$rs1, uimm2_lsb0:$imm),
119                  OpcodeStr, "$rd, ${imm}(${rs1})"> {
120  bits<2> imm;
121
122  let Inst{5} = imm{1};
123}
124
125let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
126class CStoreB_rri<bits<6> funct6, string OpcodeStr>
127    : RVInst16CSB<funct6, 0b00, (outs),
128                  (ins GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm),
129                  OpcodeStr, "$rs2, ${imm}(${rs1})"> {
130  bits<2> imm;
131
132  let Inst{6-5} = imm{0,1};
133}
134
135let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
136class CStoreH_rri<bits<6> funct6, bit funct1, string OpcodeStr,
137                  DAGOperand rty = GPRC>
138    : RVInst16CSH<funct6, funct1, 0b00, (outs),
139                  (ins rty:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
140                  OpcodeStr, "$rs2, ${imm}(${rs1})"> {
141  bits<2> imm;
142
143  let Inst{5} = imm{1};
144}
145
146let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
147class RVZcArith_r<bits<5> funct5, string OpcodeStr> :
148  RVInst16CU<0b100111, funct5, 0b01, (outs GPRC:$rd_wb), (ins GPRC:$rd),
149             OpcodeStr, "$rd"> {
150  let Constraints = "$rd = $rd_wb";
151}
152
153class RVInstZcCPPP<bits<5> funct5, string opcodestr,
154                   DAGOperand immtype = stackadj>
155    : RVInst16<(outs), (ins rlist:$rlist, immtype:$stackadj),
156               opcodestr, "$rlist, $stackadj", [], InstFormatOther> {
157  bits<4> rlist;
158  bits<16> stackadj;
159
160  let Inst{1-0} = 0b10;
161  let Inst{3-2} = stackadj{5-4};
162  let Inst{7-4} = rlist;
163  let Inst{12-8} = funct5;
164  let Inst{15-13} = 0b101;
165}
166
167//===----------------------------------------------------------------------===//
168// Instructions
169//===----------------------------------------------------------------------===//
170
171let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in
172def C_ZEXT_W  : RVZcArith_r<0b11100 , "c.zext.w">,
173                Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
174
175let Predicates = [HasStdExtZcb, HasStdExtZbb] in {
176def C_ZEXT_H  : RVZcArith_r<0b11010 , "c.zext.h">,
177                Sched<[WriteIALU, ReadIALU]>;
178def C_SEXT_B  : RVZcArith_r<0b11001 , "c.sext.b">,
179                Sched<[WriteIALU, ReadIALU]>;
180def C_SEXT_H  : RVZcArith_r<0b11011 , "c.sext.h">,
181                Sched<[WriteIALU, ReadIALU]>;
182}
183
184let Predicates = [HasStdExtZcb] in
185def C_ZEXT_B  : RVZcArith_r<0b11000 , "c.zext.b">,
186                Sched<[WriteIALU, ReadIALU]>;
187
188let Predicates = [HasStdExtZcb, HasStdExtZmmul] in
189def C_MUL     : CA_ALU<0b100111, 0b10, "c.mul">,
190                Sched<[WriteIMul, ReadIMul, ReadIMul]>;
191
192let Predicates = [HasStdExtZcb] in {
193def C_NOT : RVZcArith_r<0b11101 , "c.not">,
194            Sched<[WriteIALU, ReadIALU]>;
195
196def C_LBU : CLoadB_ri<0b100000, "c.lbu">,
197            Sched<[WriteLDB, ReadMemBase]>;
198def C_LHU : CLoadH_ri<0b100001, 0b0, "c.lhu">,
199            Sched<[WriteLDH, ReadMemBase]>;
200def C_LH  : CLoadH_ri<0b100001, 0b1, "c.lh">,
201            Sched<[WriteLDH, ReadMemBase]>;
202
203def C_SB : CStoreB_rri<0b100010, "c.sb">,
204           Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
205def C_SH : CStoreH_rri<0b100011, 0b0, "c.sh">,
206           Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
207
208// Compressed versions of Zhinx load/store.
209let isCodeGenOnly = 1 in {
210def C_LH_INX : CLoadH_ri<0b100001, 0b1, "c.lh", GPRF16C>,
211               Sched<[WriteLDH, ReadMemBase]>;
212def C_SH_INX : CStoreH_rri<0b100011, 0b0, "c.sh", GPRF16C>,
213               Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
214}
215} // Predicates = [HasStdExtZcb]
216
217// Zcmp
218let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp],
219    hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
220let Defs = [X10, X11] in
221def CM_MVA01S : RVInst16CA<0b101011, 0b11, 0b10, (outs),
222                            (ins SR07:$rs1, SR07:$rs2), "cm.mva01s", "$rs1, $rs2">,
223                Sched<[WriteIALU, WriteIALU, ReadIALU, ReadIALU]>;
224
225let Uses = [X10, X11] in
226def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
227                            (ins), "cm.mvsa01", "$rs1, $rs2">,
228                Sched<[WriteIALU, WriteIALU, ReadIALU, ReadIALU]>;
229} // DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp]...
230
231let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp] in {
232let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2] in
233def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push", negstackadj>,
234              Sched<[WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
235                     ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
236                     ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
237                     ReadStoreData, ReadStoreData, ReadStoreData]>;
238
239let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isReturn = 1,
240    Uses = [X2], Defs = [X2] in
241def CM_POPRET : RVInstZcCPPP<0b11110, "cm.popret">,
242                Sched<[WriteIALU, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
243                       WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
244                       WriteLDW, WriteLDW, WriteLDW, WriteLDW, ReadIALU]>;
245
246let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isReturn = 1,
247    Uses = [X2], Defs = [X2, X10] in
248def CM_POPRETZ : RVInstZcCPPP<0b11100, "cm.popretz">,
249                 Sched<[WriteIALU, WriteIALU, WriteLDW, WriteLDW, WriteLDW,
250                        WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
251                        WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
252                        ReadIALU]>;
253
254let hasSideEffects = 0, mayLoad = 1, mayStore = 0,
255    Uses = [X2], Defs = [X2] in
256def CM_POP : RVInstZcCPPP<0b11010, "cm.pop">,
257             Sched<[WriteIALU, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
258                    WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
259                    WriteLDW, WriteLDW, WriteLDW, ReadIALU]>;
260} // DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp]...
261
262let DecoderNamespace = "RVZcmt", Predicates = [HasStdExtZcmt],
263    hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
264def CM_JT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm5:$index),
265                       "cm.jt", "$index">{
266  bits<5> index;
267
268  let Inst{12-7} = 0b000000;
269  let Inst{6-2} = index;
270}
271
272let Defs = [X1] in
273def CM_JALT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm8ge32:$index),
274                         "cm.jalt", "$index">{
275  bits<8> index;
276
277  let Inst{12-10} = 0b000;
278  let Inst{9-2} = index;
279}
280} // DecoderNamespace = "RVZcmt", Predicates = [HasStdExtZcmt]...
281
282
283let Predicates = [HasStdExtZcb, HasStdExtZmmul] in{
284def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
285                  (C_MUL GPRC:$rs1, GPRC:$rs2)>;
286let isCompressOnly = true in
287def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
288                  (C_MUL GPRC:$rs1, GPRC:$rs2)>;
289} // Predicates = [HasStdExtZcb, HasStdExtZmmul]
290
291let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
292def : CompressPat<(SEXT_B GPRC:$rs1, GPRC:$rs1),
293                  (C_SEXT_B GPRC:$rs1, GPRC:$rs1)>;
294def : CompressPat<(SEXT_H GPRC:$rs1, GPRC:$rs1),
295                  (C_SEXT_H GPRC:$rs1, GPRC:$rs1)>;
296} // Predicates = [HasStdExtZcb, HasStdExtZbb]
297
298let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
299def : CompressPat<(ZEXT_H_RV32 GPRC:$rs1, GPRC:$rs1),
300                  (C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
301def : CompressPat<(ZEXT_H_RV64 GPRC:$rs1, GPRC:$rs1),
302                  (C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
303} // Predicates = [HasStdExtZcb, HasStdExtZbb]
304
305let Predicates = [HasStdExtZcb] in{
306def : CompressPat<(ANDI GPRC:$rs1, GPRC:$rs1, 255),
307                  (C_ZEXT_B GPRC:$rs1, GPRC:$rs1)>;
308} // Predicates = [HasStdExtZcb]
309
310let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in{
311def : CompressPat<(ADD_UW GPRC:$rs1, GPRC:$rs1, X0),
312                  (C_ZEXT_W GPRC:$rs1, GPRC:$rs1)>;
313} // Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64]
314
315let Predicates = [HasStdExtZcb] in{
316def : CompressPat<(XORI GPRC:$rs1, GPRC:$rs1, -1),
317                  (C_NOT GPRC:$rs1, GPRC:$rs1)>;
318}
319
320let Predicates = [HasStdExtZcb] in{
321def : CompressPat<(LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm),
322                  (C_LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm)>;
323def : CompressPat<(LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
324                  (C_LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
325def : CompressPat<(LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
326                  (C_LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
327def : CompressPat<(SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm),
328                  (C_SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm)>;
329def : CompressPat<(SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
330                  (C_SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
331
332let isCompressOnly = true in {
333def : CompressPat<(LH_INX GPRF16C:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
334                  (C_LH_INX GPRF16C:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
335def : CompressPat<(SH_INX GPRF16C:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
336                  (C_SH_INX GPRF16C:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
337}
338}// Predicates = [HasStdExtZcb]
339
340
341//===----------------------------------------------------------------------===//
342// Pseudo Instructions
343//===----------------------------------------------------------------------===//
344
345let Predicates = [HasStdExtZcb] in {
346def : InstAlias<"c.lbu $rd, (${rs1})",(C_LBU GPRC:$rd, GPRC:$rs1, 0), 0>;
347def : InstAlias<"c.lhu $rd, (${rs1})",(C_LHU GPRC:$rd, GPRC:$rs1, 0), 0>;
348def : InstAlias<"c.lh $rd, (${rs1})", (C_LH GPRC:$rd, GPRC:$rs1, 0), 0>;
349def : InstAlias<"c.sb $rd, (${rs1})", (C_SB GPRC:$rd, GPRC:$rs1, 0), 0>;
350def : InstAlias<"c.sh $rd, (${rs1})", (C_SH GPRC:$rd, GPRC:$rs1, 0), 0>;
351}
352