1 //===-- RISCVInstructions.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_RISCVINSTRUCTION_H
10 #define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H
11 
12 #include <cstdint>
13 #include <optional>
14 #include <variant>
15 
16 #include "llvm/ADT/APFloat.h"
17 
18 namespace lldb_private {
19 
20 class EmulateInstructionRISCV;
21 
22 struct Rd {
23   uint32_t rd;
24   bool Write(EmulateInstructionRISCV &emulator, uint64_t value);
25   bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value);
26 };
27 
28 struct Rs {
29   uint32_t rs;
30   std::optional<uint64_t> Read(EmulateInstructionRISCV &emulator);
31   std::optional<int32_t> ReadI32(EmulateInstructionRISCV &emulator);
32   std::optional<int64_t> ReadI64(EmulateInstructionRISCV &emulator);
33   std::optional<uint32_t> ReadU32(EmulateInstructionRISCV &emulator);
34   std::optional<llvm::APFloat> ReadAPFloat(EmulateInstructionRISCV &emulator,
35                                            bool isDouble);
36 };
37 
38 #define DERIVE_EQ(NAME)                                                        \
39   bool operator==(const NAME &r) const {                                       \
40     return std::memcmp(this, &r, sizeof(NAME)) == 0;                           \
41   }
42 
43 #define I_TYPE_INST(NAME)                                                      \
44   struct NAME {                                                                \
45     Rd rd;                                                                     \
46     Rs rs1;                                                                    \
47     uint32_t imm;                                                              \
48     DERIVE_EQ(NAME);                                                           \
49   }
50 #define S_TYPE_INST(NAME)                                                      \
51   struct NAME {                                                                \
52     Rs rs1;                                                                    \
53     Rs rs2;                                                                    \
54     uint32_t imm;                                                              \
55     DERIVE_EQ(NAME);                                                           \
56   }
57 #define U_TYPE_INST(NAME)                                                      \
58   struct NAME {                                                                \
59     Rd rd;                                                                     \
60     uint32_t imm;                                                              \
61     DERIVE_EQ(NAME);                                                           \
62   }
63 /// The memory layout are the same in our code.
64 #define J_TYPE_INST(NAME) U_TYPE_INST(NAME)
65 #define R_TYPE_INST(NAME)                                                      \
66   struct NAME {                                                                \
67     Rd rd;                                                                     \
68     Rs rs1;                                                                    \
69     Rs rs2;                                                                    \
70     DERIVE_EQ(NAME);                                                           \
71   }
72 #define R_SHAMT_TYPE_INST(NAME)                                                \
73   struct NAME {                                                                \
74     Rd rd;                                                                     \
75     Rs rs1;                                                                    \
76     uint32_t shamt;                                                            \
77     DERIVE_EQ(NAME);                                                           \
78   }
79 #define R_RS1_TYPE_INST(NAME)                                                  \
80   struct NAME {                                                                \
81     Rd rd;                                                                     \
82     Rs rs1;                                                                    \
83     DERIVE_EQ(NAME);                                                           \
84   }
85 #define R4_TYPE_INST(NAME)                                                     \
86   struct NAME {                                                                \
87     Rd rd;                                                                     \
88     Rs rs1;                                                                    \
89     Rs rs2;                                                                    \
90     Rs rs3;                                                                    \
91     int32_t rm;                                                                \
92     DERIVE_EQ(NAME);                                                           \
93   }
94 /// The `inst` fields are used for debugging.
95 #define INVALID_INST(NAME)                                                     \
96   struct NAME {                                                                \
97     uint32_t inst;                                                             \
98     DERIVE_EQ(NAME);                                                           \
99   }
100 
101 // RV32I instructions (The base integer ISA)
102 struct B {
103   Rs rs1;
104   Rs rs2;
105   uint32_t imm;
106   uint32_t funct3;
107   DERIVE_EQ(B);
108 };
109 U_TYPE_INST(LUI);
110 U_TYPE_INST(AUIPC);
111 J_TYPE_INST(JAL);
112 I_TYPE_INST(JALR);
113 I_TYPE_INST(LB);
114 I_TYPE_INST(LH);
115 I_TYPE_INST(LW);
116 I_TYPE_INST(LBU);
117 I_TYPE_INST(LHU);
118 S_TYPE_INST(SB);
119 S_TYPE_INST(SH);
120 S_TYPE_INST(SW);
121 I_TYPE_INST(ADDI);
122 I_TYPE_INST(SLTI);
123 I_TYPE_INST(SLTIU);
124 I_TYPE_INST(XORI);
125 I_TYPE_INST(ORI);
126 I_TYPE_INST(ANDI);
127 R_TYPE_INST(ADD);
128 R_TYPE_INST(SUB);
129 R_TYPE_INST(SLL);
130 R_TYPE_INST(SLT);
131 R_TYPE_INST(SLTU);
132 R_TYPE_INST(XOR);
133 R_TYPE_INST(SRL);
134 R_TYPE_INST(SRA);
135 R_TYPE_INST(OR);
136 R_TYPE_INST(AND);
137 
138 // RV64I inst (The base integer ISA)
139 I_TYPE_INST(LWU);
140 I_TYPE_INST(LD);
141 S_TYPE_INST(SD);
142 R_SHAMT_TYPE_INST(SLLI);
143 R_SHAMT_TYPE_INST(SRLI);
144 R_SHAMT_TYPE_INST(SRAI);
145 I_TYPE_INST(ADDIW);
146 R_SHAMT_TYPE_INST(SLLIW);
147 R_SHAMT_TYPE_INST(SRLIW);
148 R_SHAMT_TYPE_INST(SRAIW);
149 R_TYPE_INST(ADDW);
150 R_TYPE_INST(SUBW);
151 R_TYPE_INST(SLLW);
152 R_TYPE_INST(SRLW);
153 R_TYPE_INST(SRAW);
154 
155 // RV32M inst (The standard integer multiplication and division extension)
156 R_TYPE_INST(MUL);
157 R_TYPE_INST(MULH);
158 R_TYPE_INST(MULHSU);
159 R_TYPE_INST(MULHU);
160 R_TYPE_INST(DIV);
161 R_TYPE_INST(DIVU);
162 R_TYPE_INST(REM);
163 R_TYPE_INST(REMU);
164 
165 // RV64M inst (The standard integer multiplication and division extension)
166 R_TYPE_INST(MULW);
167 R_TYPE_INST(DIVW);
168 R_TYPE_INST(DIVUW);
169 R_TYPE_INST(REMW);
170 R_TYPE_INST(REMUW);
171 
172 // RV32A inst (The standard atomic instruction extension)
173 R_RS1_TYPE_INST(LR_W);
174 R_TYPE_INST(SC_W);
175 R_TYPE_INST(AMOSWAP_W);
176 R_TYPE_INST(AMOADD_W);
177 R_TYPE_INST(AMOXOR_W);
178 R_TYPE_INST(AMOAND_W);
179 R_TYPE_INST(AMOOR_W);
180 R_TYPE_INST(AMOMIN_W);
181 R_TYPE_INST(AMOMAX_W);
182 R_TYPE_INST(AMOMINU_W);
183 R_TYPE_INST(AMOMAXU_W);
184 
185 // RV64A inst (The standard atomic instruction extension)
186 R_RS1_TYPE_INST(LR_D);
187 R_TYPE_INST(SC_D);
188 R_TYPE_INST(AMOSWAP_D);
189 R_TYPE_INST(AMOADD_D);
190 R_TYPE_INST(AMOXOR_D);
191 R_TYPE_INST(AMOAND_D);
192 R_TYPE_INST(AMOOR_D);
193 R_TYPE_INST(AMOMIN_D);
194 R_TYPE_INST(AMOMAX_D);
195 R_TYPE_INST(AMOMINU_D);
196 R_TYPE_INST(AMOMAXU_D);
197 
198 // RV32F inst (The standard single-precision floating-point extension)
199 I_TYPE_INST(FLW);
200 S_TYPE_INST(FSW);
201 R4_TYPE_INST(FMADD_S);
202 R4_TYPE_INST(FMSUB_S);
203 R4_TYPE_INST(FNMADD_S);
204 R4_TYPE_INST(FNMSUB_S);
205 R_TYPE_INST(FADD_S);
206 R_TYPE_INST(FSUB_S);
207 R_TYPE_INST(FMUL_S);
208 R_TYPE_INST(FDIV_S);
209 I_TYPE_INST(FSQRT_S);
210 R_TYPE_INST(FSGNJ_S);
211 R_TYPE_INST(FSGNJN_S);
212 R_TYPE_INST(FSGNJX_S);
213 R_TYPE_INST(FMIN_S);
214 R_TYPE_INST(FMAX_S);
215 I_TYPE_INST(FCVT_W_S);
216 I_TYPE_INST(FCVT_WU_S);
217 I_TYPE_INST(FMV_X_W);
218 R_TYPE_INST(FEQ_S);
219 R_TYPE_INST(FLT_S);
220 R_TYPE_INST(FLE_S);
221 I_TYPE_INST(FCLASS_S);
222 I_TYPE_INST(FCVT_S_W);
223 I_TYPE_INST(FCVT_S_WU);
224 I_TYPE_INST(FMV_W_X);
225 
226 // RV64F inst (The standard single-precision floating-point extension)
227 I_TYPE_INST(FCVT_L_S);
228 I_TYPE_INST(FCVT_LU_S);
229 I_TYPE_INST(FCVT_S_L);
230 I_TYPE_INST(FCVT_S_LU);
231 
232 // RV32D inst (Extension for Double-Precision Floating-Point)
233 I_TYPE_INST(FLD);
234 S_TYPE_INST(FSD);
235 R4_TYPE_INST(FMADD_D);
236 R4_TYPE_INST(FMSUB_D);
237 R4_TYPE_INST(FNMSUB_D);
238 R4_TYPE_INST(FNMADD_D);
239 R_TYPE_INST(FADD_D);
240 R_TYPE_INST(FSUB_D);
241 R_TYPE_INST(FMUL_D);
242 R_TYPE_INST(FDIV_D);
243 I_TYPE_INST(FSQRT_D);
244 R_TYPE_INST(FSGNJ_D);
245 R_TYPE_INST(FSGNJN_D);
246 R_TYPE_INST(FSGNJX_D);
247 R_TYPE_INST(FMIN_D);
248 R_TYPE_INST(FMAX_D);
249 I_TYPE_INST(FCVT_S_D);
250 I_TYPE_INST(FCVT_D_S);
251 R_TYPE_INST(FEQ_D);
252 R_TYPE_INST(FLT_D);
253 R_TYPE_INST(FLE_D);
254 I_TYPE_INST(FCLASS_D);
255 I_TYPE_INST(FCVT_W_D);
256 I_TYPE_INST(FCVT_WU_D);
257 I_TYPE_INST(FCVT_D_W);
258 I_TYPE_INST(FCVT_D_WU);
259 
260 // RV64D inst (Extension for Double-Precision Floating-Point)
261 I_TYPE_INST(FCVT_L_D);
262 I_TYPE_INST(FCVT_LU_D);
263 I_TYPE_INST(FMV_X_D);
264 I_TYPE_INST(FCVT_D_L);
265 I_TYPE_INST(FCVT_D_LU);
266 I_TYPE_INST(FMV_D_X);
267 
268 /// Invalid and reserved instructions, the `inst` fields are used for debugging.
269 INVALID_INST(INVALID);
270 INVALID_INST(RESERVED);
271 INVALID_INST(EBREAK);
272 INVALID_INST(HINT);
273 INVALID_INST(NOP);
274 
275 using RISCVInst = std::variant<
276     LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI,
277     SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND,
278     LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW, SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW,
279     SRLW, SRAW, MUL, MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW,
280     DIVUW, REMW, REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W,
281     AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D, AMOSWAP_D,
282     AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D, AMOMAX_D, AMOMINU_D,
283     AMOMAXU_D, FLW, FSW, FMADD_S, FMSUB_S, FNMADD_S, FNMSUB_S, FADD_S, FSUB_S,
284     FMUL_S, FDIV_S, FSQRT_S, FSGNJ_S, FSGNJN_S, FSGNJX_S, FMIN_S, FMAX_S,
285     FCVT_W_S, FCVT_WU_S, FMV_X_W, FEQ_S, FLT_S, FLE_S, FCLASS_S, FCVT_S_W,
286     FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, FLD, FSD,
287     FMADD_D, FMSUB_D, FNMSUB_D, FNMADD_D, FADD_D, FSUB_D, FMUL_D, FDIV_D,
288     FSQRT_D, FSGNJ_D, FSGNJN_D, FSGNJX_D, FMIN_D, FMAX_D, FCVT_S_D, FCVT_D_S,
289     FEQ_D, FLT_D, FLE_D, FCLASS_D, FCVT_W_D, FCVT_WU_D, FCVT_D_W, FCVT_D_WU,
290     FCVT_L_D, FCVT_LU_D, FMV_X_D, FCVT_D_L, FCVT_D_LU, FMV_D_X, INVALID, EBREAK,
291     RESERVED, HINT, NOP>;
292 
293 constexpr uint8_t RV32 = 1;
294 constexpr uint8_t RV64 = 2;
295 constexpr uint8_t RV128 = 4;
296 
297 struct InstrPattern {
298   const char *name;
299   /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.)
300   uint32_t type_mask;
301   /// Characteristic value after bitwise-and with type_mask.
302   uint32_t eigen;
303   RISCVInst (*decode)(uint32_t inst);
304   /// If not specified, the inst will be supported by all RV versions.
305   uint8_t inst_type = RV32 | RV64 | RV128;
306 };
307 
308 struct DecodeResult {
309   RISCVInst decoded;
310   uint32_t inst;
311   bool is_rvc;
312   InstrPattern pattern;
313 };
314 
DecodeRD(uint32_t inst)315 constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; }
DecodeRS1(uint32_t inst)316 constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; }
DecodeRS2(uint32_t inst)317 constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; }
DecodeRS3(uint32_t inst)318 constexpr uint32_t DecodeRS3(uint32_t inst) {
319   return (inst & 0xF0000000) >> 27;
320 }
DecodeFunct3(uint32_t inst)321 constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; }
DecodeFunct2(uint32_t inst)322 constexpr uint32_t DecodeFunct2(uint32_t inst) {
323   return (inst & 0xE000000) >> 25;
324 }
DecodeFunct7(uint32_t inst)325 constexpr uint32_t DecodeFunct7(uint32_t inst) {
326   return (inst & 0xFE000000) >> 25;
327 }
328 
DecodeRM(uint32_t inst)329 constexpr int32_t DecodeRM(uint32_t inst) { return DecodeFunct3(inst); }
330 
331 /// RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s.
NanBoxing(uint64_t val)332 constexpr uint64_t NanBoxing(uint64_t val) {
333   return val | 0xFFFF'FFFF'0000'0000;
334 }
335 constexpr uint32_t NanUnBoxing(uint64_t val) {
336   return val & (~0xFFFF'FFFF'0000'0000);
337 }
338 
339 #undef R_TYPE_INST
340 #undef R_SHAMT_TYPE_INST
341 #undef R_RS1_TYPE_INST
342 #undef R4_TYPE_INST
343 #undef I_TYPE_INST
344 #undef S_TYPE_INST
345 #undef B_TYPE_INST
346 #undef U_TYPE_INST
347 #undef J_TYPE_INST
348 #undef INVALID_INST
349 #undef DERIVE_EQ
350 
351 } // namespace lldb_private
352 #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H
353