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