Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
39653 views
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
315
constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; }
316
constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; }
317
constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; }
318
constexpr uint32_t DecodeRS3(uint32_t inst) {
319
return (inst & 0xF0000000) >> 27;
320
}
321
constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; }
322
constexpr uint32_t DecodeFunct2(uint32_t inst) {
323
return (inst & 0xE000000) >> 25;
324
}
325
constexpr uint32_t DecodeFunct7(uint32_t inst) {
326
return (inst & 0xFE000000) >> 25;
327
}
328
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.
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
354