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
18namespace lldb_private {
19
20class EmulateInstructionRISCV;
21
22struct Rd {
23  uint32_t rd;
24  bool Write(EmulateInstructionRISCV &emulator, uint64_t value);
25  bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value);
26};
27
28struct 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)
102struct B {
103  Rs rs1;
104  Rs rs2;
105  uint32_t imm;
106  uint32_t funct3;
107  DERIVE_EQ(B);
108};
109U_TYPE_INST(LUI);
110U_TYPE_INST(AUIPC);
111J_TYPE_INST(JAL);
112I_TYPE_INST(JALR);
113I_TYPE_INST(LB);
114I_TYPE_INST(LH);
115I_TYPE_INST(LW);
116I_TYPE_INST(LBU);
117I_TYPE_INST(LHU);
118S_TYPE_INST(SB);
119S_TYPE_INST(SH);
120S_TYPE_INST(SW);
121I_TYPE_INST(ADDI);
122I_TYPE_INST(SLTI);
123I_TYPE_INST(SLTIU);
124I_TYPE_INST(XORI);
125I_TYPE_INST(ORI);
126I_TYPE_INST(ANDI);
127R_TYPE_INST(ADD);
128R_TYPE_INST(SUB);
129R_TYPE_INST(SLL);
130R_TYPE_INST(SLT);
131R_TYPE_INST(SLTU);
132R_TYPE_INST(XOR);
133R_TYPE_INST(SRL);
134R_TYPE_INST(SRA);
135R_TYPE_INST(OR);
136R_TYPE_INST(AND);
137
138// RV64I inst (The base integer ISA)
139I_TYPE_INST(LWU);
140I_TYPE_INST(LD);
141S_TYPE_INST(SD);
142R_SHAMT_TYPE_INST(SLLI);
143R_SHAMT_TYPE_INST(SRLI);
144R_SHAMT_TYPE_INST(SRAI);
145I_TYPE_INST(ADDIW);
146R_SHAMT_TYPE_INST(SLLIW);
147R_SHAMT_TYPE_INST(SRLIW);
148R_SHAMT_TYPE_INST(SRAIW);
149R_TYPE_INST(ADDW);
150R_TYPE_INST(SUBW);
151R_TYPE_INST(SLLW);
152R_TYPE_INST(SRLW);
153R_TYPE_INST(SRAW);
154
155// RV32M inst (The standard integer multiplication and division extension)
156R_TYPE_INST(MUL);
157R_TYPE_INST(MULH);
158R_TYPE_INST(MULHSU);
159R_TYPE_INST(MULHU);
160R_TYPE_INST(DIV);
161R_TYPE_INST(DIVU);
162R_TYPE_INST(REM);
163R_TYPE_INST(REMU);
164
165// RV64M inst (The standard integer multiplication and division extension)
166R_TYPE_INST(MULW);
167R_TYPE_INST(DIVW);
168R_TYPE_INST(DIVUW);
169R_TYPE_INST(REMW);
170R_TYPE_INST(REMUW);
171
172// RV32A inst (The standard atomic instruction extension)
173R_RS1_TYPE_INST(LR_W);
174R_TYPE_INST(SC_W);
175R_TYPE_INST(AMOSWAP_W);
176R_TYPE_INST(AMOADD_W);
177R_TYPE_INST(AMOXOR_W);
178R_TYPE_INST(AMOAND_W);
179R_TYPE_INST(AMOOR_W);
180R_TYPE_INST(AMOMIN_W);
181R_TYPE_INST(AMOMAX_W);
182R_TYPE_INST(AMOMINU_W);
183R_TYPE_INST(AMOMAXU_W);
184
185// RV64A inst (The standard atomic instruction extension)
186R_RS1_TYPE_INST(LR_D);
187R_TYPE_INST(SC_D);
188R_TYPE_INST(AMOSWAP_D);
189R_TYPE_INST(AMOADD_D);
190R_TYPE_INST(AMOXOR_D);
191R_TYPE_INST(AMOAND_D);
192R_TYPE_INST(AMOOR_D);
193R_TYPE_INST(AMOMIN_D);
194R_TYPE_INST(AMOMAX_D);
195R_TYPE_INST(AMOMINU_D);
196R_TYPE_INST(AMOMAXU_D);
197
198// RV32F inst (The standard single-precision floating-point extension)
199I_TYPE_INST(FLW);
200S_TYPE_INST(FSW);
201R4_TYPE_INST(FMADD_S);
202R4_TYPE_INST(FMSUB_S);
203R4_TYPE_INST(FNMADD_S);
204R4_TYPE_INST(FNMSUB_S);
205R_TYPE_INST(FADD_S);
206R_TYPE_INST(FSUB_S);
207R_TYPE_INST(FMUL_S);
208R_TYPE_INST(FDIV_S);
209I_TYPE_INST(FSQRT_S);
210R_TYPE_INST(FSGNJ_S);
211R_TYPE_INST(FSGNJN_S);
212R_TYPE_INST(FSGNJX_S);
213R_TYPE_INST(FMIN_S);
214R_TYPE_INST(FMAX_S);
215I_TYPE_INST(FCVT_W_S);
216I_TYPE_INST(FCVT_WU_S);
217I_TYPE_INST(FMV_X_W);
218R_TYPE_INST(FEQ_S);
219R_TYPE_INST(FLT_S);
220R_TYPE_INST(FLE_S);
221I_TYPE_INST(FCLASS_S);
222I_TYPE_INST(FCVT_S_W);
223I_TYPE_INST(FCVT_S_WU);
224I_TYPE_INST(FMV_W_X);
225
226// RV64F inst (The standard single-precision floating-point extension)
227I_TYPE_INST(FCVT_L_S);
228I_TYPE_INST(FCVT_LU_S);
229I_TYPE_INST(FCVT_S_L);
230I_TYPE_INST(FCVT_S_LU);
231
232// RV32D inst (Extension for Double-Precision Floating-Point)
233I_TYPE_INST(FLD);
234S_TYPE_INST(FSD);
235R4_TYPE_INST(FMADD_D);
236R4_TYPE_INST(FMSUB_D);
237R4_TYPE_INST(FNMSUB_D);
238R4_TYPE_INST(FNMADD_D);
239R_TYPE_INST(FADD_D);
240R_TYPE_INST(FSUB_D);
241R_TYPE_INST(FMUL_D);
242R_TYPE_INST(FDIV_D);
243I_TYPE_INST(FSQRT_D);
244R_TYPE_INST(FSGNJ_D);
245R_TYPE_INST(FSGNJN_D);
246R_TYPE_INST(FSGNJX_D);
247R_TYPE_INST(FMIN_D);
248R_TYPE_INST(FMAX_D);
249I_TYPE_INST(FCVT_S_D);
250I_TYPE_INST(FCVT_D_S);
251R_TYPE_INST(FEQ_D);
252R_TYPE_INST(FLT_D);
253R_TYPE_INST(FLE_D);
254I_TYPE_INST(FCLASS_D);
255I_TYPE_INST(FCVT_W_D);
256I_TYPE_INST(FCVT_WU_D);
257I_TYPE_INST(FCVT_D_W);
258I_TYPE_INST(FCVT_D_WU);
259
260// RV64D inst (Extension for Double-Precision Floating-Point)
261I_TYPE_INST(FCVT_L_D);
262I_TYPE_INST(FCVT_LU_D);
263I_TYPE_INST(FMV_X_D);
264I_TYPE_INST(FCVT_D_L);
265I_TYPE_INST(FCVT_D_LU);
266I_TYPE_INST(FMV_D_X);
267
268/// Invalid and reserved instructions, the `inst` fields are used for debugging.
269INVALID_INST(INVALID);
270INVALID_INST(RESERVED);
271INVALID_INST(EBREAK);
272INVALID_INST(HINT);
273INVALID_INST(NOP);
274
275using 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
293constexpr uint8_t RV32 = 1;
294constexpr uint8_t RV64 = 2;
295constexpr uint8_t RV128 = 4;
296
297struct 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
308struct DecodeResult {
309  RISCVInst decoded;
310  uint32_t inst;
311  bool is_rvc;
312  InstrPattern pattern;
313};
314
315constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; }
316constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; }
317constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; }
318constexpr uint32_t DecodeRS3(uint32_t inst) {
319  return (inst & 0xF0000000) >> 27;
320}
321constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; }
322constexpr uint32_t DecodeFunct2(uint32_t inst) {
323  return (inst & 0xE000000) >> 25;
324}
325constexpr uint32_t DecodeFunct7(uint32_t inst) {
326  return (inst & 0xFE000000) >> 25;
327}
328
329constexpr 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.
332constexpr uint64_t NanBoxing(uint64_t val) {
333  return val | 0xFFFF'FFFF'0000'0000;
334}
335constexpr 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