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/// This version is still experimental as the 'Zc*' extensions haven't been
12/// ratified yet.
13///
14//===----------------------------------------------------------------------===//
15
16//===----------------------------------------------------------------------===//
17// Operand and SDNode transformation definitions.
18//===----------------------------------------------------------------------===//
19
20def uimm2_lsb0 : Operand<XLenVT>,
21                 ImmLeaf<XLenVT, [{return isShiftedUInt<1, 1>(Imm);}]> {
22  let ParserMatchClass = UImmAsmOperand<2, "Lsb0">;
23  let EncoderMethod = "getImmOpValue";
24  let DecoderMethod = "decodeUImmOperand<2>";
25  let OperandType = "OPERAND_UIMM2_LSB0";
26  let OperandNamespace = "RISCVOp";
27  let MCOperandPredicate = [{
28    int64_t Imm;
29    if (!MCOp.evaluateAsConstantImm(Imm))
30      return false;
31    return isShiftedUInt<1, 1>(Imm);
32  }];
33}
34
35def uimm8ge32 : Operand<XLenVT> {
36  let ParserMatchClass = UImmAsmOperand<8, "GE32">;
37  let DecoderMethod = "decodeUImmOperand<8>";
38  let OperandType = "OPERAND_UIMM8_GE32";
39  let OperandNamespace = "RISCVOp";
40}
41
42def RlistAsmOperand : AsmOperandClass {
43  let Name = "Rlist";
44  let ParserMethod = "parseReglist";
45  let DiagnosticType = "InvalidRlist";
46}
47
48def SpimmAsmOperand : AsmOperandClass {
49  let Name = "Spimm";
50  let ParserMethod = "parseZcmpSpimm";
51  let DiagnosticType = "InvalidSpimm";
52}
53
54def rlist : Operand<OtherVT> {
55   let ParserMatchClass = RlistAsmOperand;
56   let PrintMethod = "printRlist";
57   let DecoderMethod = "decodeZcmpRlist";
58   let EncoderMethod = "getRlistOpValue";
59   let MCOperandPredicate = [{
60    int64_t Imm;
61    if (!MCOp.evaluateAsConstantImm(Imm))
62      return false;
63    if (!isUInt<4>(Imm)) return false;
64    // 0~3 Reserved for EABI
65    return (Imm >= 4) && (Imm <= 15);
66  }];
67 }
68
69def spimm : Operand<OtherVT> {
70  let ParserMatchClass = SpimmAsmOperand;
71  let PrintMethod = "printSpimm";
72  let DecoderMethod = "decodeZcmpSpimm";
73  let MCOperandPredicate = [{
74    int64_t Imm;
75    if (!MCOp.evaluateAsConstantImm(Imm))
76      return false;
77    return isShiftedUInt<5, 4>(Imm);
78  }];
79}
80
81//===----------------------------------------------------------------------===//
82// Instruction Class Templates
83//===----------------------------------------------------------------------===//
84
85let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
86class CLoadB_ri<bits<6> funct6, string OpcodeStr>
87    : RVInst16CLB<funct6, 0b00, (outs GPRC:$rd),
88                  (ins GPRCMem:$rs1, uimm2:$imm),
89                  OpcodeStr, "$rd, ${imm}(${rs1})"> {
90  bits<2> imm;
91
92  let Inst{6-5} = imm{0,1};
93}
94
95let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
96class CLoadH_ri<bits<6> funct6, bit funct1, string OpcodeStr>
97    : RVInst16CLH<funct6, funct1, 0b00, (outs GPRC:$rd),
98                  (ins GPRCMem:$rs1, uimm2_lsb0:$imm),
99                  OpcodeStr, "$rd, ${imm}(${rs1})"> {
100  bits<2> imm;
101
102  let Inst{5} = imm{1};
103}
104
105let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
106class CStoreB_rri<bits<6> funct6, string OpcodeStr>
107    : RVInst16CSB<funct6, 0b00, (outs),
108                  (ins GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm),
109                  OpcodeStr, "$rs2, ${imm}(${rs1})"> {
110  bits<2> imm;
111
112  let Inst{6-5} = imm{0,1};
113}
114
115let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
116class CStoreH_rri<bits<6> funct6, bit funct1, string OpcodeStr>
117    : RVInst16CSH<funct6, funct1, 0b00, (outs),
118                  (ins GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
119                  OpcodeStr, "$rs2, ${imm}(${rs1})"> {
120  bits<2> imm;
121
122  let Inst{5} = imm{1};
123}
124
125let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
126class RVZcArith_r<bits<5> funct5, string OpcodeStr> :
127  RVInst16CU<0b100111, funct5, 0b01, (outs GPRC:$rd_wb), (ins GPRC:$rd),
128             OpcodeStr, "$rd"> {
129  let Constraints = "$rd = $rd_wb";
130}
131
132class RVInstZcCPPP<bits<5> funct5, string opcodestr>
133    : RVInst16<(outs), (ins rlist:$rlist, spimm:$spimm),
134               opcodestr, "{$rlist}, $spimm", [], InstFormatOther> {
135  bits<4> rlist;
136  bits<16> spimm;
137
138  let Inst{1-0} = 0b10;
139  let Inst{3-2} = spimm{5-4};
140  let Inst{7-4} = rlist;
141  let Inst{12-8} = funct5;
142  let Inst{15-13} = 0b101;
143}
144
145//===----------------------------------------------------------------------===//
146// Instructions
147//===----------------------------------------------------------------------===//
148
149let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in
150def C_ZEXT_W  : RVZcArith_r<0b11100 , "c.zext.w">,
151                Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
152
153let Predicates = [HasStdExtZcb, HasStdExtZbb] in {
154def C_ZEXT_H  : RVZcArith_r<0b11010 , "c.zext.h">,
155                Sched<[WriteIALU, ReadIALU]>;
156def C_SEXT_B  : RVZcArith_r<0b11001 , "c.sext.b">,
157                Sched<[WriteIALU, ReadIALU]>;
158def C_SEXT_H  : RVZcArith_r<0b11011 , "c.sext.h">,
159                Sched<[WriteIALU, ReadIALU]>;
160}
161
162let Predicates = [HasStdExtZcb] in
163def C_ZEXT_B  : RVZcArith_r<0b11000 , "c.zext.b">,
164                Sched<[WriteIALU, ReadIALU]>;
165
166let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in
167def C_MUL     : CA_ALU<0b100111, 0b10, "c.mul", GPRC>,
168                Sched<[WriteIMul, ReadIMul, ReadIMul]>;
169
170let Predicates = [HasStdExtZcb] in {
171def C_NOT : RVZcArith_r<0b11101 , "c.not">,
172            Sched<[WriteIALU, ReadIALU]>;
173
174def C_LBU : CLoadB_ri<0b100000, "c.lbu">,
175            Sched<[WriteLDB, ReadMemBase]>;
176def C_LHU : CLoadH_ri<0b100001, 0b0, "c.lhu">,
177            Sched<[WriteLDH, ReadMemBase]>;
178def C_LH  : CLoadH_ri<0b100001, 0b1, "c.lh">,
179            Sched<[WriteLDH, ReadMemBase]>;
180
181def C_SB : CStoreB_rri<0b100010, "c.sb">,
182           Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
183def C_SH : CStoreH_rri<0b100011, 0b0, "c.sh">,
184           Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
185}
186
187// Zcmp
188let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp],
189    Defs = [X10, X11], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
190def CM_MVA01S : RVInst16CA<0b101011, 0b11, 0b10, (outs),
191                            (ins SR07:$rs1, SR07:$rs2), "cm.mva01s", "$rs1, $rs2">;
192
193def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
194                            (ins), "cm.mvsa01", "$rs1, $rs2">;
195} // DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp]...
196
197let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp] in {
198let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
199def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push">;
200
201let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
202def CM_POPRET : RVInstZcCPPP<0b11110, "cm.popret">;
203
204let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
205def CM_POPRETZ : RVInstZcCPPP<0b11100, "cm.popretz">;
206
207let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
208def CM_POP : RVInstZcCPPP<0b11010, "cm.pop">;
209} // DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp]...
210
211let DecoderNamespace = "RVZcmt", Predicates = [HasStdExtZcmt],
212    hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
213def CM_JT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm5:$index),
214                       "cm.jt", "$index">{
215  bits<5> index;
216
217  let Inst{12-7} = 0b000000;
218  let Inst{6-2} = index;
219}
220
221let Defs = [X1] in
222def CM_JALT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm8ge32:$index),
223                         "cm.jalt", "$index">{
224  bits<8> index;
225
226  let Inst{12-10} = 0b000;
227  let Inst{9-2} = index;
228}
229} // DecoderNamespace = "RVZcmt", Predicates = [HasStdExtZcmt]...
230
231
232let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in{
233def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
234                  (C_MUL GPRC:$rs1, GPRC:$rs2)>;
235let isCompressOnly = true in
236def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
237                  (C_MUL GPRC:$rs1, GPRC:$rs2)>;
238} // Predicates = [HasStdExtZcb, HasStdExtMOrZmmul]
239
240let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
241def : CompressPat<(SEXT_B GPRC:$rs1, GPRC:$rs1),
242                  (C_SEXT_B GPRC:$rs1, GPRC:$rs1)>;
243def : CompressPat<(SEXT_H GPRC:$rs1, GPRC:$rs1),
244                  (C_SEXT_H GPRC:$rs1, GPRC:$rs1)>;
245} // Predicates = [HasStdExtZcb, HasStdExtZbb]
246
247let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
248def : CompressPat<(ZEXT_H_RV32 GPRC:$rs1, GPRC:$rs1),
249                  (C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
250def : CompressPat<(ZEXT_H_RV64 GPRC:$rs1, GPRC:$rs1),
251                  (C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
252} // Predicates = [HasStdExtZcb, HasStdExtZbb]
253
254let Predicates = [HasStdExtZcb] in{
255def : CompressPat<(ANDI GPRC:$rs1, GPRC:$rs1, 255),
256                  (C_ZEXT_B GPRC:$rs1, GPRC:$rs1)>;
257} // Predicates = [HasStdExtZcb]
258
259let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in{
260def : CompressPat<(ADD_UW GPRC:$rs1, GPRC:$rs1, X0),
261                  (C_ZEXT_W GPRC:$rs1, GPRC:$rs1)>;
262} // Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64]
263
264let Predicates = [HasStdExtZcb] in{
265def : CompressPat<(XORI GPRC:$rs1, GPRC:$rs1, -1),
266                  (C_NOT GPRC:$rs1, GPRC:$rs1)>;
267}
268
269let Predicates = [HasStdExtZcb] in{
270def : CompressPat<(LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm),
271                  (C_LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm)>;
272def : CompressPat<(LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
273                  (C_LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
274def : CompressPat<(LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
275                  (C_LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
276def : CompressPat<(SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm),
277                  (C_SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm)>;
278def : CompressPat<(SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
279                  (C_SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
280}// Predicates = [HasStdExtZcb]
281
282
283//===----------------------------------------------------------------------===//
284// Pseudo Instructions
285//===----------------------------------------------------------------------===//
286
287let Predicates = [HasStdExtZcb] in {
288def : InstAlias<"c.lbu $rd, (${rs1})",(C_LBU GPRC:$rd, GPRC:$rs1, 0)>;
289def : InstAlias<"c.lhu $rd, (${rs1})",(C_LHU GPRC:$rd, GPRC:$rs1, 0)>;
290def : InstAlias<"c.lh $rd, (${rs1})", (C_LH GPRC:$rd, GPRC:$rs1, 0)>;
291def : InstAlias<"c.sb $rd, (${rs1})", (C_SB GPRC:$rd, GPRC:$rs1, 0)>;
292def : InstAlias<"c.sh $rd, (${rs1})", (C_SH GPRC:$rd, GPRC:$rs1, 0)>;
293}
294