1 | //===-- RISCVCInstructions.h ----------------------------------------------===// |
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 | #ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H |
10 | #define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H |
11 | |
12 | #include <cstdint> |
13 | #include <variant> |
14 | |
15 | #include "Plugins/Process/Utility/lldb-riscv-register-enums.h" |
16 | #include "RISCVInstructions.h" |
17 | |
18 | namespace lldb_private { |
19 | |
20 | /// Unified RISC-V C register encoding. |
21 | struct RxC { |
22 | uint32_t rd; |
23 | bool shift = true; |
24 | operator int() { return rd; } |
25 | operator Rd() { return Rd{.rd: rd + (shift ? 8 : 0)}; } |
26 | operator Rs() { return Rs{.rs: rd + (shift ? 8 : 0)}; } |
27 | }; |
28 | |
29 | // decode register for RVC |
30 | constexpr RxC DecodeCR_RD(uint32_t inst) { return RxC{.rd: DecodeRD(inst), .shift: false}; } |
31 | constexpr RxC DecodeCI_RD(uint32_t inst) { return RxC{.rd: DecodeRD(inst), .shift: false}; } |
32 | constexpr RxC DecodeCR_RS1(uint32_t inst) { return RxC{.rd: DecodeRD(inst), .shift: false}; } |
33 | constexpr RxC DecodeCI_RS1(uint32_t inst) { return RxC{.rd: DecodeRD(inst), .shift: false}; } |
34 | constexpr RxC DecodeCR_RS2(uint32_t inst) { |
35 | return RxC{.rd: (inst & 0x7C) >> 2, .shift: false}; |
36 | } |
37 | |
38 | constexpr RxC DecodeCIW_RD(uint32_t inst) { return RxC{.rd: (inst & 0x1C) >> 2}; } |
39 | constexpr RxC DecodeCL_RD(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } |
40 | constexpr RxC DecodeCA_RD(uint32_t inst) { return RxC{.rd: (inst & 0x380) >> 7}; } |
41 | constexpr RxC DecodeCB_RD(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } |
42 | |
43 | constexpr RxC DecodeCL_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } |
44 | constexpr RxC DecodeCS_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } |
45 | constexpr RxC DecodeCA_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } |
46 | constexpr RxC DecodeCB_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } |
47 | |
48 | constexpr RxC DecodeCSS_RS2(uint32_t inst) { return DecodeCR_RS2(inst); } |
49 | constexpr RxC DecodeCS_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } |
50 | constexpr RxC DecodeCA_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } |
51 | |
52 | RISCVInst DecodeC_LWSP(uint32_t inst) { |
53 | auto rd = DecodeCI_RD(inst); |
54 | uint16_t offset = ((inst << 4) & 0xc0) // offset[7:6] |
55 | | ((inst >> 7) & 0x20) // offset[5] |
56 | | ((inst >> 2) & 0x1c); // offset[4:2] |
57 | if (rd == 0) |
58 | return RESERVED{.inst: inst}; |
59 | return LW{.rd: rd, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(offset)}; |
60 | } |
61 | |
62 | RISCVInst DecodeC_LDSP(uint32_t inst) { |
63 | auto rd = DecodeCI_RD(inst); |
64 | uint16_t offset = ((inst << 4) & 0x1c0) // offset[8:6] |
65 | | ((inst >> 7) & 0x20) // offset[5] |
66 | | ((inst >> 2) & 0x18); // offset[4:3] |
67 | if (rd == 0) |
68 | return RESERVED{.inst: inst}; |
69 | return LD{.rd: rd, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(offset)}; |
70 | } |
71 | |
72 | RISCVInst DecodeC_SWSP(uint32_t inst) { |
73 | uint16_t offset = ((inst >> 1) & 0xc0) // offset[7:6] |
74 | | ((inst >> 7) & 0x3c); // offset[5:2] |
75 | return SW{.rs1: Rs{.rs: gpr_sp_riscv}, .rs2: DecodeCSS_RS2(inst), .imm: uint32_t(offset)}; |
76 | } |
77 | |
78 | RISCVInst DecodeC_SDSP(uint32_t inst) { |
79 | uint16_t offset = ((inst >> 1) & 0x1c0) // offset[8:6] |
80 | | ((inst >> 7) & 0x38); // offset[5:3] |
81 | return SD{.rs1: Rs{.rs: gpr_sp_riscv}, .rs2: DecodeCSS_RS2(inst), .imm: uint32_t(offset)}; |
82 | } |
83 | |
84 | RISCVInst DecodeC_LW(uint32_t inst) { |
85 | uint16_t offset = ((inst << 1) & 0x40) // imm[6] |
86 | | ((inst >> 7) & 0x38) // imm[5:3] |
87 | | ((inst >> 4) & 0x4); // imm[2] |
88 | return LW{.rd: DecodeCL_RD(inst), .rs1: DecodeCL_RS1(inst), .imm: uint32_t(offset)}; |
89 | } |
90 | |
91 | RISCVInst DecodeC_LD(uint32_t inst) { |
92 | uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] |
93 | | ((inst >> 7) & 0x38); // imm[5:3] |
94 | return LD{.rd: DecodeCL_RD(inst), .rs1: DecodeCL_RS1(inst), .imm: uint32_t(offset)}; |
95 | } |
96 | |
97 | RISCVInst DecodeC_SW(uint32_t inst) { |
98 | uint16_t offset = ((inst << 1) & 0x40) // imm[6] |
99 | | ((inst >> 7) & 0x38) // imm[5:3] |
100 | | ((inst >> 4) & 0x4); // imm[2] |
101 | return SW{.rs1: DecodeCS_RS1(inst), .rs2: DecodeCS_RS2(inst), .imm: uint32_t(offset)}; |
102 | } |
103 | |
104 | RISCVInst DecodeC_SD(uint32_t inst) { |
105 | uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] |
106 | | ((inst >> 7) & 0x38); // imm[5:3] |
107 | return SD{.rs1: DecodeCS_RS1(inst), .rs2: DecodeCS_RS2(inst), .imm: uint32_t(offset)}; |
108 | } |
109 | |
110 | RISCVInst DecodeC_J(uint32_t inst) { |
111 | uint16_t offset = ((inst >> 1) & 0x800) // offset[11] |
112 | | ((inst << 2) & 0x400) // offset[10] |
113 | | ((inst >> 1) & 0x300) // offset[9:8] |
114 | | ((inst << 1) & 0x80) // offset[7] |
115 | | ((inst >> 1) & 0x40) // offset[6] |
116 | | ((inst << 3) & 0x20) // offset[5] |
117 | | ((inst >> 7) & 0x10) // offset[4] |
118 | | ((inst >> 2) & 0xe); // offset[3:1] |
119 | if ((offset & 0x800) == 0) |
120 | return JAL{.rd: Rd{.rd: 0}, .imm: uint32_t(offset)}; |
121 | return JAL{.rd: Rd{.rd: 0}, .imm: uint32_t(int32_t(int16_t(offset | 0xf000)))}; |
122 | } |
123 | |
124 | RISCVInst DecodeC_JR(uint32_t inst) { |
125 | auto rs1 = DecodeCR_RS1(inst); |
126 | if (rs1 == 0) |
127 | return RESERVED{.inst: inst}; |
128 | return JALR{.rd: Rd{.rd: 0}, .rs1: rs1, .imm: 0}; |
129 | } |
130 | |
131 | RISCVInst DecodeC_JALR(uint32_t inst) { |
132 | auto rs1 = DecodeCR_RS1(inst); |
133 | if (rs1 == 0) |
134 | return EBREAK{.inst: inst}; |
135 | return JALR{.rd: Rd{.rd: 1}, .rs1: rs1, .imm: 0}; |
136 | } |
137 | |
138 | constexpr uint16_t BOffset(uint32_t inst) { |
139 | return ((inst >> 4) & 0x100) // offset[8] |
140 | | ((inst << 1) & 0xc0) // offset[7:6] |
141 | | ((inst << 3) & 0x20) // offset[5] |
142 | | ((inst >> 7) & 0x18) // offset[4:3] |
143 | | ((inst >> 2) & 0x6); // offset[2:1] |
144 | } |
145 | |
146 | RISCVInst DecodeC_BNEZ(uint32_t inst) { |
147 | auto rs1 = DecodeCB_RS1(inst); |
148 | uint16_t offset = BOffset(inst); |
149 | if ((offset & 0x100) == 0) |
150 | return B{.rs1: rs1, .rs2: Rs{.rs: 0}, .imm: uint32_t(offset), .funct3: 0b001}; |
151 | return B{.rs1: rs1, .rs2: Rs{.rs: 0}, .imm: uint32_t(int32_t(int16_t(offset | 0xfe00))), .funct3: 0b001}; |
152 | } |
153 | |
154 | RISCVInst DecodeC_BEQZ(uint32_t inst) { |
155 | auto rs1 = DecodeCB_RS1(inst); |
156 | uint16_t offset = BOffset(inst); |
157 | if ((offset & 0x100) == 0) |
158 | return B{.rs1: rs1, .rs2: Rs{.rs: 0}, .imm: uint32_t(offset), .funct3: 0b000}; |
159 | return B{.rs1: rs1, .rs2: Rs{.rs: 0}, .imm: uint32_t(int32_t(int16_t(offset | 0xfe00))), .funct3: 0b000}; |
160 | } |
161 | |
162 | RISCVInst DecodeC_LI(uint32_t inst) { |
163 | auto rd = DecodeCI_RD(inst); |
164 | uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
165 | if ((imm & 0x20) == 0) |
166 | return ADDI{.rd: rd, .rs1: Rs{.rs: 0}, .imm: uint32_t(imm)}; |
167 | return ADDI{.rd: rd, .rs1: Rs{.rs: 0}, .imm: uint32_t(int32_t(int8_t(imm | 0xc0)))}; |
168 | } |
169 | |
170 | RISCVInst DecodeC_LUI_ADDI16SP(uint32_t inst) { |
171 | auto rd = DecodeCI_RD(inst); |
172 | if (rd == 0) |
173 | return HINT{.inst: inst}; |
174 | if (rd == 2) { |
175 | uint16_t nzimm = ((inst >> 3) & 0x200) // nzimm[9] |
176 | | ((inst >> 2) & 0x10) // nzimm[4] |
177 | | ((inst << 1) & 0x40) // nzimm[6] |
178 | | ((inst << 4) & 0x180) // nzimm[8:7] |
179 | | ((inst << 3) & 0x20); // nzimm[5] |
180 | if (nzimm == 0) |
181 | return RESERVED{.inst: inst}; |
182 | if ((nzimm & 0x200) == 0) |
183 | return ADDI{.rd: Rd{.rd: gpr_sp_riscv}, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(nzimm)}; |
184 | return ADDI{.rd: Rd{.rd: gpr_sp_riscv}, .rs1: Rs{.rs: gpr_sp_riscv}, |
185 | .imm: uint32_t(int32_t(int16_t(nzimm | 0xfc00)))}; |
186 | } |
187 | uint32_t imm = |
188 | ((uint32_t(inst) << 5) & 0x20000) | ((uint32_t(inst) << 10) & 0x1f000); |
189 | if ((imm & 0x20000) == 0) |
190 | return LUI{.rd: rd, .imm: imm}; |
191 | return LUI{.rd: rd, .imm: uint32_t(int32_t(imm | 0xfffc0000))}; |
192 | } |
193 | |
194 | RISCVInst DecodeC_ADDI(uint32_t inst) { |
195 | auto rd = DecodeCI_RD(inst); |
196 | if (rd == 0) |
197 | return NOP{.inst: inst}; |
198 | uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
199 | if ((imm & 0x20) == 0) |
200 | return ADDI{.rd: rd, .rs1: rd, .imm: uint32_t(imm)}; |
201 | return ADDI{.rd: rd, .rs1: rd, .imm: uint32_t(int32_t(int8_t(imm | 0xc0)))}; |
202 | } |
203 | |
204 | RISCVInst DecodeC_ADDIW(uint32_t inst) { |
205 | auto rd = DecodeCI_RD(inst); |
206 | if (rd == 0) |
207 | return RESERVED{.inst: inst}; |
208 | uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
209 | if ((imm & 0x20) == 0) |
210 | return ADDIW{.rd: rd, .rs1: rd, .imm: uint32_t(imm)}; |
211 | return ADDIW{.rd: rd, .rs1: rd, .imm: uint32_t(int32_t(int8_t(imm | 0xc0)))}; |
212 | } |
213 | |
214 | RISCVInst DecodeC_ADDI4SPN(uint32_t inst) { |
215 | auto rd = DecodeCIW_RD(inst); |
216 | uint16_t nzuimm = ((inst >> 1) & 0x3c0) // nzuimm[9:6] |
217 | | ((inst >> 7) & 0x30) // nzuimm[5:4] |
218 | | ((inst >> 2) & 0x8) // nzuimm[3] |
219 | | ((inst >> 4) & 0x4); // nzuimm[2] |
220 | |
221 | if (rd == 0 && nzuimm == 0) |
222 | return INVALID{.inst: inst}; |
223 | if (nzuimm == 0) |
224 | return RESERVED{.inst: inst}; |
225 | return ADDI{.rd: rd, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(nzuimm)}; |
226 | } |
227 | |
228 | RISCVInst DecodeC_SLLI(uint32_t inst) { |
229 | auto rd = DecodeCI_RD(inst); |
230 | uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
231 | if (rd == 0 || shamt == 0) |
232 | return HINT{.inst: inst}; |
233 | return SLLI{.rd: rd, .rs1: rd, .shamt: uint8_t(shamt)}; |
234 | } |
235 | |
236 | RISCVInst DecodeC_SRLI(uint32_t inst) { |
237 | auto rd = DecodeCB_RD(inst); |
238 | uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
239 | if (shamt == 0) |
240 | return HINT{.inst: inst}; |
241 | return SRLI{.rd: rd, .rs1: rd, .shamt: uint8_t(shamt)}; |
242 | } |
243 | |
244 | RISCVInst DecodeC_SRAI(uint32_t inst) { |
245 | auto rd = DecodeCB_RD(inst); |
246 | uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
247 | if (shamt == 0) |
248 | return HINT{.inst: inst}; |
249 | return SRAI{.rd: rd, .rs1: rd, .shamt: uint8_t(shamt)}; |
250 | } |
251 | |
252 | RISCVInst DecodeC_ANDI(uint32_t inst) { |
253 | auto rd = DecodeCB_RD(inst); |
254 | uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); |
255 | if ((imm & 0x20) == 0) |
256 | return ANDI{.rd: rd, .rs1: rd, .imm: uint32_t(imm)}; |
257 | return ANDI{.rd: rd, .rs1: rd, .imm: uint32_t(int32_t(int8_t(imm | 0xc0)))}; |
258 | } |
259 | |
260 | RISCVInst DecodeC_MV(uint32_t inst) { |
261 | auto rd = DecodeCR_RD(inst); |
262 | auto rs2 = DecodeCR_RS2(inst); |
263 | if (rd == 0) |
264 | return HINT{.inst: inst}; |
265 | return ADD{.rd: rd, .rs1: Rs{.rs: 0}, .rs2: rs2}; |
266 | } |
267 | |
268 | RISCVInst DecodeC_ADD(uint32_t inst) { |
269 | auto rd = DecodeCR_RD(inst); |
270 | return ADD{.rd: rd, .rs1: rd, .rs2: DecodeCR_RS2(inst)}; |
271 | } |
272 | |
273 | RISCVInst DecodeC_AND(uint32_t inst) { |
274 | auto rd = DecodeCA_RD(inst); |
275 | return AND{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
276 | } |
277 | |
278 | RISCVInst DecodeC_OR(uint32_t inst) { |
279 | auto rd = DecodeCA_RD(inst); |
280 | return OR{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
281 | } |
282 | |
283 | RISCVInst DecodeC_XOR(uint32_t inst) { |
284 | auto rd = DecodeCA_RD(inst); |
285 | return XOR{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
286 | } |
287 | |
288 | RISCVInst DecodeC_SUB(uint32_t inst) { |
289 | auto rd = DecodeCA_RD(inst); |
290 | return SUB{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
291 | } |
292 | |
293 | RISCVInst DecodeC_SUBW(uint32_t inst) { |
294 | auto rd = DecodeCA_RD(inst); |
295 | return SUBW{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
296 | } |
297 | |
298 | RISCVInst DecodeC_ADDW(uint32_t inst) { |
299 | auto rd = DecodeCA_RD(inst); |
300 | return ADDW{.rd: rd, .rs1: rd, .rs2: DecodeCA_RS2(inst)}; |
301 | } |
302 | RISCVInst DecodeC_FLW(uint32_t inst) { |
303 | uint16_t offset = ((inst << 1) & 0x40) // imm[6] |
304 | | ((inst >> 7) & 0x38) // imm[5:3] |
305 | | ((inst >> 4) & 0x4); // imm[2] |
306 | return FLW{.rd: DecodeCL_RD(inst), .rs1: DecodeCL_RS1(inst), .imm: uint32_t(offset)}; |
307 | } |
308 | |
309 | RISCVInst DecodeC_FSW(uint32_t inst) { |
310 | uint16_t offset = ((inst << 1) & 0x40) // imm[6] |
311 | | ((inst >> 7) & 0x38) // imm[5:3] |
312 | | ((inst >> 4) & 0x4); // imm[2] |
313 | return FSW{.rs1: DecodeCS_RS1(inst), .rs2: DecodeCS_RS2(inst), .imm: uint32_t(offset)}; |
314 | } |
315 | |
316 | RISCVInst DecodeC_FLWSP(uint32_t inst) { |
317 | auto rd = DecodeCI_RD(inst); |
318 | uint16_t offset = ((inst << 4) & 0xc0) // offset[7:6] |
319 | | ((inst >> 7) & 0x20) // offset[5] |
320 | | ((inst >> 2) & 0x1c); // offset[4:2] |
321 | return FLW{.rd: rd, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(offset)}; |
322 | } |
323 | |
324 | RISCVInst DecodeC_FSWSP(uint32_t inst) { |
325 | uint16_t offset = ((inst >> 1) & 0xc0) // offset[7:6] |
326 | | ((inst >> 7) & 0x3c); // offset[5:2] |
327 | return FSW{.rs1: Rs{.rs: gpr_sp_riscv}, .rs2: DecodeCSS_RS2(inst), .imm: uint32_t(offset)}; |
328 | } |
329 | |
330 | RISCVInst DecodeC_FLDSP(uint32_t inst) { |
331 | auto rd = DecodeCI_RD(inst); |
332 | uint16_t offset = ((inst << 4) & 0x1c0) // offset[8:6] |
333 | | ((inst >> 7) & 0x20) // offset[5] |
334 | | ((inst >> 2) & 0x18); // offset[4:3] |
335 | return FLD{.rd: rd, .rs1: Rs{.rs: gpr_sp_riscv}, .imm: uint32_t(offset)}; |
336 | } |
337 | |
338 | RISCVInst DecodeC_FSDSP(uint32_t inst) { |
339 | uint16_t offset = ((inst >> 1) & 0x1c0) // offset[8:6] |
340 | | ((inst >> 7) & 0x38); // offset[5:3] |
341 | return FSD{.rs1: Rs{.rs: gpr_sp_riscv}, .rs2: DecodeCSS_RS2(inst), .imm: uint32_t(offset)}; |
342 | } |
343 | |
344 | RISCVInst DecodeC_FLD(uint32_t inst) { |
345 | uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] |
346 | | ((inst >> 7) & 0x38); // imm[5:3] |
347 | return FLD{.rd: DecodeCL_RD(inst), .rs1: DecodeCL_RS1(inst), .imm: uint32_t(offset)}; |
348 | } |
349 | |
350 | RISCVInst DecodeC_FSD(uint32_t inst) { |
351 | uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] |
352 | | ((inst >> 7) & 0x38); // imm[5:3] |
353 | return FSD{.rs1: DecodeCS_RS1(inst), .rs2: DecodeCS_RS2(inst), .imm: uint32_t(offset)}; |
354 | } |
355 | |
356 | } // namespace lldb_private |
357 | #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H |
358 | |