Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/biscuit/src/assembler.cpp
4253 views
1
#include <biscuit/assert.hpp>
2
#include <biscuit/assembler.hpp>
3
4
#include <cstring>
5
#include <utility>
6
7
namespace biscuit {
8
namespace {
9
// Determines if a value lies within the range of a 6-bit immediate.
10
[[nodiscard]] bool IsValidSigned6BitImm(ptrdiff_t value) noexcept {
11
return value >= -32 && value <= 31;
12
}
13
14
// S-type and I-type immediates are 12 bits in size
15
[[nodiscard]] bool IsValidSigned12BitImm(ptrdiff_t value) noexcept {
16
return value >= -2048 && value <= 2047;
17
}
18
19
// B-type immediates only provide -4KiB to +4KiB range branches.
20
[[nodiscard]] bool IsValidBTypeImm(ptrdiff_t value) noexcept {
21
return value >= -4096 && value <= 4095;
22
}
23
24
// J-type immediates only provide -1MiB to +1MiB range branches.
25
[[nodiscard]] bool IsValidJTypeImm(ptrdiff_t value) noexcept {
26
return value >= -0x80000 && value <= 0x7FFFF;
27
}
28
29
// CB-type immediates only provide -256B to +256B range branches.
30
[[nodiscard]] bool IsValidCBTypeImm(ptrdiff_t value) noexcept {
31
return value >= -256 && value <= 255;
32
}
33
34
// CJ-type immediates only provide -2KiB to +2KiB range branches.
35
[[nodiscard]] bool IsValidCJTypeImm(ptrdiff_t value) noexcept {
36
return IsValidSigned12BitImm(value);
37
}
38
39
// Determines whether or not the register fits in 3-bit compressed encoding.
40
[[nodiscard]] bool IsValid3BitCompressedReg(Register reg) noexcept {
41
const auto index = reg.Index();
42
return index >= 8 && index <= 15;
43
}
44
45
// Determines whether or not the given shift amount is valid for a compressed shift instruction
46
[[nodiscard]] bool IsValidCompressedShiftAmount(uint32_t shift) noexcept {
47
return shift > 0 && shift <= 64;
48
}
49
50
// Turns a compressed register into its encoding.
51
[[nodiscard]] uint32_t CompressedRegTo3BitEncoding(Register reg) noexcept {
52
return reg.Index() - 8;
53
}
54
55
// Transforms a regular value into an immediate encoded in a B-type instruction.
56
[[nodiscard]] uint32_t TransformToBTypeImm(uint32_t imm) noexcept {
57
// clang-format off
58
return ((imm & 0x07E0) << 20) |
59
((imm & 0x1000) << 19) |
60
((imm & 0x001E) << 7) |
61
((imm & 0x0800) >> 4);
62
// clang-format on
63
}
64
65
// Transforms a regular value into an immediate encoded in a J-type instruction.
66
[[nodiscard]] uint32_t TransformToJTypeImm(uint32_t imm) noexcept {
67
// clang-format off
68
return ((imm & 0x0FF000) >> 0) |
69
((imm & 0x000800) << 9) |
70
((imm & 0x0007FE) << 20) |
71
((imm & 0x100000) << 11);
72
// clang-format on
73
}
74
75
// Transforms a regular value into an immediate encoded in a CB-type instruction.
76
[[nodiscard]] uint32_t TransformToCBTypeImm(uint32_t imm) noexcept {
77
// clang-format off
78
return ((imm & 0x0C0) >> 1) |
79
((imm & 0x006) << 2) |
80
((imm & 0x020) >> 3) |
81
((imm & 0x018) << 7) |
82
((imm & 0x100) << 4);
83
// clang-format on
84
}
85
86
// Transforms a regular value into an immediate encoded in a CJ-type instruction.
87
[[nodiscard]] uint32_t TransformToCJTypeImm(uint32_t imm) noexcept {
88
// clang-format off
89
return ((imm & 0x800) << 1) |
90
((imm & 0x010) << 7) |
91
((imm & 0x300) << 1) |
92
((imm & 0x400) >> 2) |
93
((imm & 0x040) << 1) |
94
((imm & 0x080) >> 1) |
95
((imm & 0x00E) << 4) |
96
((imm & 0x020) >> 3);
97
// clang-format on
98
}
99
100
// Emits a B type RISC-V instruction. These consist of:
101
// imm[12|10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode
102
void EmitBType(CodeBuffer& buffer, uint32_t imm, GPR rs2, GPR rs1, uint32_t funct3, uint32_t opcode) noexcept {
103
imm &= 0x1FFE;
104
105
buffer.Emit32(TransformToBTypeImm(imm) | (rs2.Index() << 20) | (rs1.Index() << 15) | ((funct3 & 0b111) << 12) | (opcode & 0x7F));
106
}
107
108
// Emits a I type RISC-V instruction. These consist of:
109
// imm[11:0] | rs1 | funct3 | rd | opcode
110
void EmitIType(CodeBuffer& buffer, uint32_t imm, Register rs1, uint32_t funct3, Register rd, uint32_t opcode) noexcept {
111
imm &= 0xFFF;
112
113
buffer.Emit32((imm << 20) | (rs1.Index() << 15) | ((funct3 & 0b111) << 12) | (rd.Index() << 7) | (opcode & 0x7F));
114
}
115
116
// Emits a J type RISC-V instruction. These consist of:
117
// imm[20|10:1|11|19:12] | rd | opcode
118
void EmitJType(CodeBuffer& buffer, uint32_t imm, GPR rd, uint32_t opcode) noexcept {
119
imm &= 0x1FFFFE;
120
121
buffer.Emit32(TransformToJTypeImm(imm) | rd.Index() << 7 | (opcode & 0x7F));
122
}
123
124
// Emits a R type RISC instruction. These consist of:
125
// funct7 | rs2 | rs1 | funct3 | rd | opcode
126
void EmitRType(CodeBuffer& buffer, uint32_t funct7, Register rs2, Register rs1, uint32_t funct3,
127
Register rd, uint32_t opcode) noexcept {
128
// clang-format off
129
const auto value = ((funct7 & 0xFF) << 25) |
130
(rs2.Index() << 20) |
131
(rs1.Index() << 15) |
132
((funct3 & 0b111) << 12) |
133
(rd.Index() << 7) |
134
(opcode & 0x7F);
135
// clang-format off
136
137
buffer.Emit32(value);
138
}
139
140
// Emits a R type RISC instruction. These consist of:
141
// funct7 | rs2 | rs1 | funct3 | rd | opcode
142
void EmitRType(CodeBuffer& buffer, uint32_t funct7, FPR rs2, FPR rs1, RMode funct3, FPR rd, uint32_t opcode) noexcept {
143
EmitRType(buffer, funct7, rs2, rs1, static_cast<uint32_t>(funct3), rd, opcode);
144
}
145
146
// Emits a R4 type RISC instruction. These consist of:
147
// rs3 | funct2 | rs2 | rs1 | funct3 | rd | opcode
148
void EmitR4Type(CodeBuffer& buffer, FPR rs3, uint32_t funct2, FPR rs2, FPR rs1, RMode funct3, FPR rd, uint32_t opcode) noexcept {
149
const auto reg_bits = (rs3.Index() << 27) | (rs2.Index() << 20) | (rs1.Index() << 15) | (rd.Index() << 7);
150
const auto funct_bits = ((funct2 & 0b11) << 25) | (static_cast<uint32_t>(funct3) << 12);
151
buffer.Emit32(reg_bits | funct_bits | (opcode & 0x7F));
152
}
153
154
// Emits a S type RISC-V instruction. These consist of:
155
// imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode
156
void EmitSType(CodeBuffer& buffer, uint32_t imm, Register rs2, GPR rs1, uint32_t funct3, uint32_t opcode) noexcept {
157
imm &= 0xFFF;
158
159
// clang-format off
160
const auto new_imm = ((imm & 0x01F) << 7) |
161
((imm & 0xFE0) << 20);
162
// clang-format on
163
164
buffer.Emit32(new_imm | (rs2.Index() << 20) | (rs1.Index() << 15) | ((funct3 & 0b111) << 12) | (opcode & 0x7F));
165
}
166
167
// Emits a U type RISC-V instruction. These consist of:
168
// imm[31:12] | rd | opcode
169
void EmitUType(CodeBuffer& buffer, uint32_t imm, GPR rd, uint32_t opcode) noexcept {
170
buffer.Emit32((imm & 0x000FFFFF) << 12 | rd.Index() << 7 | (opcode & 0x7F));
171
}
172
173
// Emits an atomic instruction.
174
void EmitAtomic(CodeBuffer& buffer, uint32_t funct5, Ordering ordering, GPR rs2, GPR rs1,
175
uint32_t funct3, GPR rd, uint32_t opcode) noexcept {
176
const auto funct7 = (funct5 << 2) | static_cast<uint32_t>(ordering);
177
EmitRType(buffer, funct7, rs2, rs1, funct3, rd, opcode);
178
}
179
180
// Emits a fence instruction
181
void EmitFENCE(CodeBuffer& buffer, uint32_t fm, FenceOrder pred, FenceOrder succ,
182
GPR rs, uint32_t funct3, GPR rd, uint32_t opcode) noexcept {
183
// clang-format off
184
buffer.Emit32(((fm & 0b1111) << 28) |
185
(static_cast<uint32_t>(pred) << 24) |
186
(static_cast<uint32_t>(succ) << 20) |
187
(rs.Index() << 15) |
188
((funct3 & 0b111) << 12) |
189
(rd.Index() << 7) |
190
(opcode & 0x7F));
191
// clang-format on
192
}
193
194
// Emits a compressed branch instruction. These consist of:
195
// funct3 | imm[8|4:3] | rs | imm[7:6|2:1|5] | op
196
void EmitCompressedBranch(CodeBuffer& buffer, uint32_t funct3, int32_t offset, GPR rs, uint32_t op) noexcept {
197
BISCUIT_ASSERT(IsValidCBTypeImm(offset));
198
BISCUIT_ASSERT(IsValid3BitCompressedReg(rs));
199
200
const auto transformed_imm = TransformToCBTypeImm(static_cast<uint32_t>(offset));
201
const auto rs_san = CompressedRegTo3BitEncoding(rs);
202
buffer.Emit16(((funct3 & 0b111) << 13) | transformed_imm | (rs_san << 7) | (op & 0b11));
203
}
204
205
// Emits a compressed jump instruction. These consist of:
206
// funct3 | imm | op
207
void EmitCompressedJump(CodeBuffer& buffer, uint32_t funct3, int32_t offset, uint32_t op) noexcept {
208
BISCUIT_ASSERT(IsValidCJTypeImm(offset));
209
buffer.Emit16(TransformToCJTypeImm(static_cast<uint32_t>(offset)) | ((funct3 & 0b111) << 13) | (op & 0b11));
210
}
211
212
// Emits a compress immediate instruction. These consist of:
213
// funct3 | imm | rd | imm | op
214
void EmitCompressedImmediate(CodeBuffer& buffer, uint32_t funct3, uint32_t imm, GPR rd, uint32_t op) noexcept {
215
BISCUIT_ASSERT(rd != x0);
216
const auto new_imm = ((imm & 0b11111) << 2) | ((imm & 0b100000) << 7);
217
buffer.Emit16(((funct3 & 0b111) << 13) | new_imm | (rd.Index() << 7) | (op & 0b11));
218
}
219
220
// Emits a compressed load instruction. These consist of:
221
// funct3 | imm | rs1 | imm | rd | op
222
void EmitCompressedLoad(CodeBuffer& buffer, uint32_t funct3, uint32_t imm, GPR rs, Register rd, uint32_t op) noexcept {
223
BISCUIT_ASSERT(IsValid3BitCompressedReg(rs));
224
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
225
226
imm &= 0xF8;
227
228
const auto imm_enc = ((imm & 0x38) << 7) | ((imm & 0xC0) >> 1);
229
const auto rd_san = CompressedRegTo3BitEncoding(rd);
230
const auto rs_san = CompressedRegTo3BitEncoding(rs);
231
buffer.Emit16(((funct3 & 0b111) << 13) | imm_enc | (rs_san << 7) | (rd_san << 2) | (op & 0b11));
232
}
233
234
// Emits a compressed register arithmetic instruction. These consist of:
235
// funct6 | rd | funct2 | rs | op
236
void EmitCompressedRegArith(CodeBuffer& buffer, uint32_t funct6, GPR rd, uint32_t funct2, GPR rs, uint32_t op) noexcept {
237
BISCUIT_ASSERT(IsValid3BitCompressedReg(rs));
238
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
239
240
const auto rd_san = CompressedRegTo3BitEncoding(rd);
241
const auto rs_san = CompressedRegTo3BitEncoding(rs);
242
buffer.Emit16(((funct6 & 0b111111) << 10) | (rd_san << 7) | ((funct2 & 0b11) << 5) | (rs_san << 2) | (op & 0b11));
243
}
244
245
// Emits a compressed store instruction. These consist of:
246
// funct3 | imm | rs1 | imm | rs2 | op
247
void EmitCompressedStore(CodeBuffer& buffer, uint32_t funct3, uint32_t imm, GPR rs1, Register rs2, uint32_t op) noexcept {
248
// This has the same format as a compressed load, with rs2 taking the place of rd.
249
// We can reuse the code we've already written to handle this.
250
EmitCompressedLoad(buffer, funct3, imm, rs1, rs2, op);
251
}
252
253
// Emits a compressed wide immediate instruction. These consist of:
254
// funct3 | imm | rd | opcode
255
void EmitCompressedWideImmediate(CodeBuffer& buffer, uint32_t funct3, uint32_t imm, GPR rd, uint32_t op) noexcept {
256
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
257
const auto rd_sanitized = CompressedRegTo3BitEncoding(rd);
258
buffer.Emit16(((funct3 & 0b111) << 13) | ((imm & 0xFF) << 5) | (rd_sanitized << 2) | (op & 0b11));
259
}
260
} // Anonymous namespace
261
262
Assembler::Assembler(size_t capacity)
263
: m_buffer(capacity) {}
264
265
Assembler::Assembler(uint8_t* buffer, size_t capacity)
266
: m_buffer(buffer, capacity) {}
267
268
Assembler::~Assembler() = default;
269
270
CodeBuffer& Assembler::GetCodeBuffer() {
271
return m_buffer;
272
}
273
274
CodeBuffer Assembler::SwapCodeBuffer(CodeBuffer&& buffer) noexcept {
275
return std::exchange(m_buffer, std::move(buffer));
276
}
277
278
void Assembler::Bind(Label* label) {
279
BindToOffset(label, m_buffer.GetCursorOffset());
280
}
281
282
void Assembler::ADD(GPR rd, GPR lhs, GPR rhs) noexcept {
283
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b000, rd, 0b0110011);
284
}
285
286
void Assembler::ADDI(GPR rd, GPR rs, int32_t imm) noexcept {
287
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b000, rd, 0b0010011);
288
}
289
290
void Assembler::AND(GPR rd, GPR lhs, GPR rhs) noexcept {
291
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b111, rd, 0b0110011);
292
}
293
294
void Assembler::ANDI(GPR rd, GPR rs, uint32_t imm) noexcept {
295
EmitIType(m_buffer, imm, rs, 0b111, rd, 0b0010011);
296
}
297
298
void Assembler::AUIPC(GPR rd, int32_t imm) noexcept {
299
EmitUType(m_buffer, static_cast<uint32_t>(imm), rd, 0b0010111);
300
}
301
302
void Assembler::BEQ(GPR rs1, GPR rs2, Label* label) noexcept {
303
const auto address = LinkAndGetOffset(label);
304
BEQ(rs1, rs2, static_cast<int32_t>(address));
305
}
306
307
void Assembler::BEQZ(GPR rs, Label* label) noexcept {
308
const auto address = LinkAndGetOffset(label);
309
BEQZ(rs, static_cast<int32_t>(address));
310
}
311
312
void Assembler::BGE(GPR rs1, GPR rs2, Label* label) noexcept {
313
const auto address = LinkAndGetOffset(label);
314
BGE(rs1, rs2, static_cast<int32_t>(address));
315
}
316
317
void Assembler::BGEU(GPR rs1, GPR rs2, Label* label) noexcept {
318
const auto address = LinkAndGetOffset(label);
319
BGEU(rs1, rs2, static_cast<int32_t>(address));
320
}
321
322
void Assembler::BGEZ(GPR rs, Label* label) noexcept {
323
const auto address = LinkAndGetOffset(label);
324
BGEZ(rs, static_cast<int32_t>(address));
325
}
326
327
void Assembler::BGT(GPR rs, GPR rt, Label* label) noexcept {
328
const auto address = LinkAndGetOffset(label);
329
BGT(rs, rt, static_cast<int32_t>(address));
330
}
331
332
void Assembler::BGTU(GPR rs, GPR rt, Label* label) noexcept {
333
const auto address = LinkAndGetOffset(label);
334
BGTU(rs, rt, static_cast<int32_t>(address));
335
}
336
337
void Assembler::BGTZ(GPR rs, Label* label) noexcept {
338
const auto address = LinkAndGetOffset(label);
339
BGTZ(rs, static_cast<int32_t>(address));
340
}
341
342
void Assembler::BLE(GPR rs, GPR rt, Label* label) noexcept {
343
const auto address = LinkAndGetOffset(label);
344
BLE(rs, rt, static_cast<int32_t>(address));
345
}
346
347
void Assembler::BLEU(GPR rs, GPR rt, Label* label) noexcept {
348
const auto address = LinkAndGetOffset(label);
349
BLEU(rs, rt, static_cast<int32_t>(address));
350
}
351
352
void Assembler::BLEZ(GPR rs, Label* label) noexcept {
353
const auto address = LinkAndGetOffset(label);
354
BLEZ(rs, static_cast<int32_t>(address));
355
}
356
357
void Assembler::BLT(GPR rs1, GPR rs2, Label* label) noexcept {
358
const auto address = LinkAndGetOffset(label);
359
BLT(rs1, rs2, static_cast<int32_t>(address));
360
}
361
362
void Assembler::BLTU(GPR rs1, GPR rs2, Label* label) noexcept {
363
const auto address = LinkAndGetOffset(label);
364
BLTU(rs1, rs2, static_cast<int32_t>(address));
365
}
366
367
void Assembler::BLTZ(GPR rs, Label* label) noexcept {
368
const auto address = LinkAndGetOffset(label);
369
BLTZ(rs, static_cast<int32_t>(address));
370
}
371
372
void Assembler::BNE(GPR rs1, GPR rs2, Label* label) noexcept {
373
const auto address = LinkAndGetOffset(label);
374
BNE(rs1, rs2, static_cast<int32_t>(address));
375
}
376
377
void Assembler::BNEZ(GPR rs, Label* label) noexcept {
378
const auto address = LinkAndGetOffset(label);
379
BNEZ(rs, static_cast<int32_t>(address));
380
}
381
382
void Assembler::BEQ(GPR rs1, GPR rs2, int32_t imm) noexcept {
383
BISCUIT_ASSERT(IsValidBTypeImm(imm));
384
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b000, 0b1100011);
385
}
386
387
void Assembler::BEQZ(GPR rs, int32_t imm) noexcept {
388
BEQ(rs, x0, imm);
389
}
390
391
void Assembler::BGE(GPR rs1, GPR rs2, int32_t imm) noexcept {
392
BISCUIT_ASSERT(IsValidBTypeImm(imm));
393
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b101, 0b1100011);
394
}
395
396
void Assembler::BGEU(GPR rs1, GPR rs2, int32_t imm) noexcept {
397
BISCUIT_ASSERT(IsValidBTypeImm(imm));
398
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b111, 0b1100011);
399
}
400
401
void Assembler::BGEZ(GPR rs, int32_t imm) noexcept {
402
BGE(rs, x0, imm);
403
}
404
405
void Assembler::BGT(GPR rs, GPR rt, int32_t imm) noexcept {
406
BLT(rt, rs, imm);
407
}
408
409
void Assembler::BGTU(GPR rs, GPR rt, int32_t imm) noexcept {
410
BLTU(rt, rs, imm);
411
}
412
413
void Assembler::BGTZ(GPR rs, int32_t imm) noexcept {
414
BLT(x0, rs, imm);
415
}
416
417
void Assembler::BLE(GPR rs, GPR rt, int32_t imm) noexcept {
418
BGE(rt, rs, imm);
419
}
420
421
void Assembler::BLEU(GPR rs, GPR rt, int32_t imm) noexcept {
422
BGEU(rt, rs, imm);
423
}
424
425
void Assembler::BLEZ(GPR rs, int32_t imm) noexcept {
426
BGE(x0, rs, imm);
427
}
428
429
void Assembler::BLT(GPR rs1, GPR rs2, int32_t imm) noexcept {
430
BISCUIT_ASSERT(IsValidBTypeImm(imm));
431
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b100, 0b1100011);
432
}
433
434
void Assembler::BLTU(GPR rs1, GPR rs2, int32_t imm) noexcept {
435
BISCUIT_ASSERT(IsValidBTypeImm(imm));
436
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b110, 0b1100011);
437
}
438
439
void Assembler::BLTZ(GPR rs, int32_t imm) noexcept {
440
BLT(rs, x0, imm);
441
}
442
443
void Assembler::BNE(GPR rs1, GPR rs2, int32_t imm) noexcept {
444
BISCUIT_ASSERT(IsValidBTypeImm(imm));
445
EmitBType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b001, 0b1100011);
446
}
447
448
void Assembler::BNEZ(GPR rs, int32_t imm) noexcept {
449
BNE(x0, rs, imm);
450
}
451
452
void Assembler::CALL(int32_t offset) noexcept {
453
const auto uimm = static_cast<uint32_t>(offset);
454
const auto lower = uimm & 0xFFF;
455
const auto upper = (uimm & 0xFFFFF000) >> 12;
456
const auto needs_increment = (uimm & 0x800) != 0;
457
458
// Sign-extend the lower portion if the MSB of it is set.
459
const auto new_lower = needs_increment ? static_cast<int32_t>(lower << 20) >> 20
460
: static_cast<int32_t>(lower);
461
const auto new_upper = needs_increment ? upper + 1 : upper;
462
463
AUIPC(x1, static_cast<int32_t>(new_upper));
464
JALR(x1, new_lower, x1);
465
}
466
467
void Assembler::EBREAK() noexcept {
468
m_buffer.Emit32(0x00100073);
469
}
470
471
void Assembler::ECALL() noexcept {
472
m_buffer.Emit32(0x00000073);
473
}
474
475
void Assembler::FENCE() noexcept {
476
FENCE(FenceOrder::IORW, FenceOrder::IORW);
477
}
478
479
void Assembler::FENCE(FenceOrder pred, FenceOrder succ) noexcept {
480
EmitFENCE(m_buffer, 0b0000, pred, succ, x0, 0b000, x0, 0b0001111);
481
}
482
483
void Assembler::FENCEI(GPR rd, GPR rs, uint32_t imm) noexcept {
484
m_buffer.Emit32(((imm & 0xFFF) << 20) | (rs.Index() << 15) | 0x1000U | (rd.Index() << 7) | 0b0001111);
485
}
486
487
void Assembler::FENCETSO() noexcept {
488
EmitFENCE(m_buffer, 0b1000, FenceOrder::RW, FenceOrder::RW, x0, 0b000, x0, 0b0001111);
489
}
490
491
void Assembler::J(Label* label) noexcept {
492
const auto address = LinkAndGetOffset(label);
493
BISCUIT_ASSERT(IsValidJTypeImm(address));
494
J(static_cast<int32_t>(address));
495
}
496
497
void Assembler::JAL(Label* label) noexcept {
498
const auto address = LinkAndGetOffset(label);
499
BISCUIT_ASSERT(IsValidJTypeImm(address));
500
JAL(static_cast<int32_t>(address));
501
}
502
503
void Assembler::JAL(GPR rd, Label* label) noexcept {
504
const auto address = LinkAndGetOffset(label);
505
BISCUIT_ASSERT(IsValidJTypeImm(address));
506
JAL(rd, static_cast<int32_t>(address));
507
}
508
509
void Assembler::J(int32_t imm) noexcept {
510
BISCUIT_ASSERT(IsValidJTypeImm(imm));
511
JAL(x0, imm);
512
}
513
514
void Assembler::JAL(int32_t imm) noexcept {
515
BISCUIT_ASSERT(IsValidJTypeImm(imm));
516
EmitJType(m_buffer, static_cast<uint32_t>(imm), x1, 0b1101111);
517
}
518
519
void Assembler::JAL(GPR rd, int32_t imm) noexcept {
520
BISCUIT_ASSERT(IsValidJTypeImm(imm));
521
EmitJType(m_buffer, static_cast<uint32_t>(imm), rd, 0b1101111);
522
}
523
524
void Assembler::JALR(GPR rs) noexcept {
525
JALR(x1, 0, rs);
526
}
527
528
void Assembler::JALR(GPR rd, int32_t imm, GPR rs1) noexcept {
529
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
530
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs1, 0b000, rd, 0b1100111);
531
}
532
533
void Assembler::JR(GPR rs) noexcept {
534
JALR(x0, 0, rs);
535
}
536
537
void Assembler::LB(GPR rd, int32_t imm, GPR rs) noexcept {
538
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
539
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b000, rd, 0b0000011);
540
}
541
542
void Assembler::LBU(GPR rd, int32_t imm, GPR rs) noexcept {
543
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
544
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b100, rd, 0b0000011);
545
}
546
547
void Assembler::LH(GPR rd, int32_t imm, GPR rs) noexcept {
548
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
549
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b001, rd, 0b0000011);
550
}
551
552
void Assembler::LHU(GPR rd, int32_t imm, GPR rs) noexcept {
553
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
554
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b101, rd, 0b0000011);
555
}
556
557
void Assembler::LI(GPR rd, uint32_t imm) noexcept {
558
const auto lower = imm & 0xFFF;
559
const auto upper = (imm & 0xFFFFF000) >> 12;
560
const auto simm = static_cast<int32_t>(imm);
561
562
// If the immediate can fit within 12 bits, we only need to emit an ADDI.
563
if (IsValidSigned12BitImm(simm)) {
564
ADDI(rd, x0, static_cast<int32_t>(lower));
565
} else {
566
const bool needs_increment = (lower & 0x800) != 0;
567
const auto upper_imm = needs_increment ? upper + 1 : upper;
568
569
// Note that we add 1 to the upper portion of the immediate if the lower
570
// immediate's most significant bit is set. This is necessary, as ADDI
571
// sign-extends its 12-bit immediate before performing addition.
572
//
573
// In the event of the sign-extension, this means that we'll be adding
574
// an equivalent of "lower - 4096" to the upper immediate.
575
//
576
// We add 1 to the upper part of the immediate. the upper part's least
577
// significant bit is bit 12. Adding 1 to this bit is equivalent to adding
578
// 4096, which counteracts the sign-extension, preserving the value.
579
580
LUI(rd, upper_imm);
581
ADDI(rd, rd, static_cast<int32_t>(lower));
582
}
583
}
584
585
void Assembler::LUI(GPR rd, uint32_t imm) noexcept {
586
EmitUType(m_buffer, imm, rd, 0b0110111);
587
}
588
589
void Assembler::LW(GPR rd, int32_t imm, GPR rs) noexcept {
590
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
591
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b010, rd, 0b0000011);
592
}
593
594
void Assembler::MV(GPR rd, GPR rs) noexcept {
595
ADDI(rd, rs, 0);
596
}
597
598
void Assembler::NEG(GPR rd, GPR rs) noexcept {
599
SUB(rd, x0, rs);
600
}
601
602
void Assembler::NOP() noexcept {
603
ADDI(x0, x0, 0);
604
}
605
606
void Assembler::NOT(GPR rd, GPR rs) noexcept {
607
XORI(rd, rs, UINT32_MAX);
608
}
609
610
void Assembler::OR(GPR rd, GPR lhs, GPR rhs) noexcept {
611
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b110, rd, 0b0110011);
612
}
613
614
void Assembler::ORI(GPR rd, GPR rs, uint32_t imm) noexcept {
615
EmitIType(m_buffer, imm, rs, 0b110, rd, 0b0010011);
616
}
617
618
void Assembler::PAUSE() noexcept {
619
m_buffer.Emit32(0x0100000F);
620
}
621
622
void Assembler::RET() noexcept {
623
JALR(x0, 0, x1);
624
}
625
626
void Assembler::SB(GPR rs2, int32_t imm, GPR rs1) noexcept {
627
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
628
EmitSType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b000, 0b0100011);
629
}
630
631
void Assembler::SEQZ(GPR rd, GPR rs) noexcept {
632
SLTIU(rd, rs, 1);
633
}
634
635
void Assembler::SGTZ(GPR rd, GPR rs) noexcept {
636
SLT(rd, x0, rs);
637
}
638
639
void Assembler::SH(GPR rs2, int32_t imm, GPR rs1) noexcept {
640
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
641
EmitSType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b001, 0b0100011);
642
}
643
644
void Assembler::SLL(GPR rd, GPR lhs, GPR rhs) noexcept {
645
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b001, rd, 0b0110011);
646
}
647
648
void Assembler::SLLI(GPR rd, GPR rs, uint32_t shift) noexcept {
649
BISCUIT_ASSERT(shift <= 31);
650
EmitIType(m_buffer, shift & 0x1F, rs, 0b001, rd, 0b0010011);
651
}
652
653
void Assembler::SLT(GPR rd, GPR lhs, GPR rhs) noexcept {
654
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b010, rd, 0b0110011);
655
}
656
657
void Assembler::SLTI(GPR rd, GPR rs, int32_t imm) noexcept {
658
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
659
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b010, rd, 0b0010011);
660
}
661
662
void Assembler::SLTIU(GPR rd, GPR rs, int32_t imm) noexcept {
663
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
664
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b011, rd, 0b0010011);
665
}
666
667
void Assembler::SLTU(GPR rd, GPR lhs, GPR rhs) noexcept {
668
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b011, rd, 0b0110011);
669
}
670
671
void Assembler::SLTZ(GPR rd, GPR rs) noexcept {
672
SLT(rd, rs, x0);
673
}
674
675
void Assembler::SNEZ(GPR rd, GPR rs) noexcept {
676
SLTU(rd, x0, rs);
677
}
678
679
void Assembler::SRA(GPR rd, GPR lhs, GPR rhs) noexcept {
680
EmitRType(m_buffer, 0b0100000, rhs, lhs, 0b101, rd, 0b0110011);
681
}
682
683
void Assembler::SRAI(GPR rd, GPR rs, uint32_t shift) noexcept {
684
BISCUIT_ASSERT(shift <= 31);
685
EmitIType(m_buffer, (0b0100000 << 5) | (shift & 0x1F), rs, 0b101, rd, 0b0010011);
686
}
687
688
void Assembler::SRL(GPR rd, GPR lhs, GPR rhs) noexcept {
689
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b101, rd, 0b0110011);
690
}
691
692
void Assembler::SRLI(GPR rd, GPR rs, uint32_t shift) noexcept {
693
BISCUIT_ASSERT(shift <= 31);
694
EmitIType(m_buffer, shift & 0x1F, rs, 0b101, rd, 0b0010011);
695
}
696
697
void Assembler::SUB(GPR rd, GPR lhs, GPR rhs) noexcept {
698
EmitRType(m_buffer, 0b0100000, rhs, lhs, 0b000, rd, 0b0110011);
699
}
700
701
void Assembler::SW(GPR rs2, int32_t imm, GPR rs1) noexcept {
702
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
703
EmitSType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b010, 0b0100011);
704
}
705
706
void Assembler::XOR(GPR rd, GPR lhs, GPR rhs) noexcept {
707
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b100, rd, 0b0110011);
708
}
709
710
void Assembler::XORI(GPR rd, GPR rs, uint32_t imm) noexcept {
711
EmitIType(m_buffer, imm, rs, 0b100, rd, 0b0010011);
712
}
713
714
// RV64I Instructions
715
716
void Assembler::ADDIW(GPR rd, GPR rs, int32_t imm) noexcept {
717
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b000, rd, 0b0011011);
718
}
719
720
void Assembler::ADDW(GPR rd, GPR lhs, GPR rhs) noexcept {
721
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b000, rd, 0b0111011);
722
}
723
724
void Assembler::LD(GPR rd, int32_t imm, GPR rs) noexcept {
725
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
726
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b011, rd, 0b0000011);
727
}
728
729
void Assembler::LWU(GPR rd, int32_t imm, GPR rs) noexcept {
730
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
731
EmitIType(m_buffer, static_cast<uint32_t>(imm), rs, 0b110, rd, 0b0000011);
732
}
733
734
void Assembler::SD(GPR rs2, int32_t imm, GPR rs1) noexcept {
735
BISCUIT_ASSERT(IsValidSigned12BitImm(imm));
736
EmitSType(m_buffer, static_cast<uint32_t>(imm), rs2, rs1, 0b011, 0b0100011);
737
}
738
739
void Assembler::SRAI64(GPR rd, GPR rs, uint32_t shift) noexcept {
740
BISCUIT_ASSERT(shift <= 63);
741
EmitIType(m_buffer, (0b0100000 << 5) | (shift & 0x3F), rs, 0b101, rd, 0b0010011);
742
}
743
void Assembler::SLLI64(GPR rd, GPR rs, uint32_t shift) noexcept {
744
BISCUIT_ASSERT(shift <= 63);
745
EmitIType(m_buffer, shift & 0x3F, rs, 0b001, rd, 0b0010011);
746
}
747
void Assembler::SRLI64(GPR rd, GPR rs, uint32_t shift) noexcept {
748
BISCUIT_ASSERT(shift <= 63);
749
EmitIType(m_buffer, shift & 0x3F, rs, 0b101, rd, 0b0010011);
750
}
751
752
void Assembler::SLLIW(GPR rd, GPR rs, uint32_t shift) noexcept {
753
BISCUIT_ASSERT(shift <= 31);
754
EmitIType(m_buffer, shift & 0x1F, rs, 0b001, rd, 0b0011011);
755
}
756
void Assembler::SRAIW(GPR rd, GPR rs, uint32_t shift) noexcept {
757
BISCUIT_ASSERT(shift <= 31);
758
EmitIType(m_buffer, (0b0100000 << 5) | (shift & 0x1F), rs, 0b101, rd, 0b0011011);
759
}
760
void Assembler::SRLIW(GPR rd, GPR rs, uint32_t shift) noexcept {
761
BISCUIT_ASSERT(shift <= 31);
762
EmitIType(m_buffer, shift & 0x1F, rs, 0b101, rd, 0b0011011);
763
}
764
765
void Assembler::SLLW(GPR rd, GPR lhs, GPR rhs) noexcept {
766
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b001, rd, 0b0111011);
767
}
768
void Assembler::SRAW(GPR rd, GPR lhs, GPR rhs) noexcept {
769
EmitRType(m_buffer, 0b0100000, rhs, lhs, 0b101, rd, 0b0111011);
770
}
771
void Assembler::SRLW(GPR rd, GPR lhs, GPR rhs) noexcept {
772
EmitRType(m_buffer, 0b0000000, rhs, lhs, 0b101, rd, 0b0111011);
773
}
774
775
void Assembler::SUBW(GPR rd, GPR lhs, GPR rhs) noexcept {
776
EmitRType(m_buffer, 0b0100000, rhs, lhs, 0b000, rd, 0b0111011);
777
}
778
779
// Zicsr Extension Instructions
780
781
void Assembler::CSRRC(GPR rd, CSR csr, GPR rs) noexcept {
782
EmitIType(m_buffer, static_cast<uint32_t>(csr), rs, 0b011, rd, 0b1110011);
783
}
784
void Assembler::CSRRCI(GPR rd, CSR csr, uint32_t imm) noexcept {
785
BISCUIT_ASSERT(imm <= 0x1F);
786
EmitIType(m_buffer, static_cast<uint32_t>(csr), GPR{imm & 0x1F}, 0b111, rd, 0b1110011);
787
}
788
void Assembler::CSRRS(GPR rd, CSR csr, GPR rs) noexcept {
789
EmitIType(m_buffer, static_cast<uint32_t>(csr), rs, 0b010, rd, 0b1110011);
790
}
791
void Assembler::CSRRSI(GPR rd, CSR csr, uint32_t imm) noexcept {
792
BISCUIT_ASSERT(imm <= 0x1F);
793
EmitIType(m_buffer, static_cast<uint32_t>(csr), GPR{imm & 0x1F}, 0b110, rd, 0b1110011);
794
}
795
void Assembler::CSRRW(GPR rd, CSR csr, GPR rs) noexcept {
796
EmitIType(m_buffer, static_cast<uint32_t>(csr), rs, 0b001, rd, 0b1110011);
797
}
798
void Assembler::CSRRWI(GPR rd, CSR csr, uint32_t imm) noexcept {
799
BISCUIT_ASSERT(imm <= 0x1F);
800
EmitIType(m_buffer, static_cast<uint32_t>(csr), GPR{imm & 0x1F}, 0b101, rd, 0b1110011);
801
}
802
803
void Assembler::CSRR(GPR rd, CSR csr) noexcept {
804
CSRRS(rd, csr, x0);
805
}
806
void Assembler::CSWR(CSR csr, GPR rs) noexcept {
807
CSRRW(x0, csr, rs);
808
}
809
810
void Assembler::CSRS(CSR csr, GPR rs) noexcept {
811
CSRRS(x0, csr, rs);
812
}
813
void Assembler::CSRC(CSR csr, GPR rs) noexcept {
814
CSRRC(x0, csr, rs);
815
}
816
817
void Assembler::CSRCI(CSR csr, uint32_t imm) noexcept {
818
CSRRCI(x0, csr, imm);
819
}
820
void Assembler::CSRSI(CSR csr, uint32_t imm) noexcept {
821
CSRRSI(x0, csr, imm);
822
}
823
void Assembler::CSRWI(CSR csr, uint32_t imm) noexcept {
824
CSRRWI(x0, csr, imm);
825
}
826
827
void Assembler::FRCSR(GPR rd) noexcept {
828
CSRRS(rd, CSR::FCSR, x0);
829
}
830
void Assembler::FSCSR(GPR rd, GPR rs) noexcept {
831
CSRRW(rd, CSR::FCSR, rs);
832
}
833
void Assembler::FSCSR(GPR rs) noexcept {
834
CSRRW(x0, CSR::FCSR, rs);
835
}
836
837
void Assembler::FRRM(GPR rd) noexcept {
838
CSRRS(rd, CSR::FRM, x0);
839
}
840
void Assembler::FSRM(GPR rd, GPR rs) noexcept {
841
CSRRW(rd, CSR::FRM, rs);
842
}
843
void Assembler::FSRM(GPR rs) noexcept {
844
CSRRW(x0, CSR::FRM, rs);
845
}
846
847
void Assembler::FSRMI(GPR rd, uint32_t imm) noexcept {
848
CSRRWI(rd, CSR::FRM, imm);
849
}
850
void Assembler::FSRMI(uint32_t imm) noexcept {
851
CSRRWI(x0, CSR::FRM, imm);
852
}
853
854
void Assembler::FRFLAGS(GPR rd) noexcept {
855
CSRRS(rd, CSR::FFlags, x0);
856
}
857
void Assembler::FSFLAGS(GPR rd, GPR rs) noexcept {
858
CSRRW(rd, CSR::FFlags, rs);
859
}
860
void Assembler::FSFLAGS(GPR rs) noexcept {
861
CSRRW(x0, CSR::FFlags, rs);
862
}
863
864
void Assembler::FSFLAGSI(GPR rd, uint32_t imm) noexcept {
865
CSRRWI(rd, CSR::FFlags, imm);
866
}
867
void Assembler::FSFLAGSI(uint32_t imm) noexcept {
868
CSRRWI(x0, CSR::FFlags, imm);
869
}
870
871
void Assembler::RDCYCLE(GPR rd) noexcept {
872
CSRRS(rd, CSR::Cycle, x0);
873
}
874
void Assembler::RDCYCLEH(GPR rd) noexcept {
875
CSRRS(rd, CSR::CycleH, x0);
876
}
877
878
void Assembler::RDINSTRET(GPR rd) noexcept {
879
CSRRS(rd, CSR::InstRet, x0);
880
}
881
void Assembler::RDINSTRETH(GPR rd) noexcept {
882
CSRRS(rd, CSR::InstRetH, x0);
883
}
884
885
void Assembler::RDTIME(GPR rd) noexcept {
886
CSRRS(rd, CSR::Time, x0);
887
}
888
void Assembler::RDTIMEH(GPR rd) noexcept {
889
CSRRS(rd, CSR::TimeH, x0);
890
}
891
892
// Zihintntl Extension Instructions
893
894
void Assembler::C_NTL_ALL() noexcept {
895
C_ADD(x0, x5);
896
}
897
void Assembler::C_NTL_S1() noexcept {
898
C_ADD(x0, x4);
899
}
900
void Assembler::C_NTL_P1() noexcept {
901
C_ADD(x0, x2);
902
}
903
void Assembler::C_NTL_PALL() noexcept {
904
C_ADD(x0, x3);
905
}
906
void Assembler::NTL_ALL() noexcept {
907
ADD(x0, x0, x5);
908
}
909
void Assembler::NTL_S1() noexcept {
910
ADD(x0, x0, x4);
911
}
912
void Assembler::NTL_P1() noexcept {
913
ADD(x0, x0, x2);
914
}
915
void Assembler::NTL_PALL() noexcept {
916
ADD(x0, x0, x3);
917
}
918
919
// RV32M Extension Instructions
920
921
void Assembler::DIV(GPR rd, GPR rs1, GPR rs2) noexcept {
922
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b100, rd, 0b0110011);
923
}
924
void Assembler::DIVU(GPR rd, GPR rs1, GPR rs2) noexcept {
925
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b101, rd, 0b0110011);
926
}
927
void Assembler::MUL(GPR rd, GPR rs1, GPR rs2) noexcept {
928
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b000, rd, 0b0110011);
929
}
930
void Assembler::MULH(GPR rd, GPR rs1, GPR rs2) noexcept {
931
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b001, rd, 0b0110011);
932
}
933
void Assembler::MULHSU(GPR rd, GPR rs1, GPR rs2) noexcept {
934
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b010, rd, 0b0110011);
935
}
936
void Assembler::MULHU(GPR rd, GPR rs1, GPR rs2) noexcept {
937
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b011, rd, 0b0110011);
938
}
939
void Assembler::REM(GPR rd, GPR rs1, GPR rs2) noexcept {
940
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b110, rd, 0b0110011);
941
}
942
void Assembler::REMU(GPR rd, GPR rs1, GPR rs2) noexcept {
943
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b111, rd, 0b0110011);
944
}
945
946
// RV64M Extension Instructions
947
948
void Assembler::DIVW(GPR rd, GPR rs1, GPR rs2) noexcept {
949
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b100, rd, 0b0111011);
950
}
951
void Assembler::DIVUW(GPR rd, GPR rs1, GPR rs2) noexcept {
952
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b101, rd, 0b0111011);
953
}
954
void Assembler::MULW(GPR rd, GPR rs1, GPR rs2) noexcept {
955
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b000, rd, 0b0111011);
956
}
957
void Assembler::REMW(GPR rd, GPR rs1, GPR rs2) noexcept {
958
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b110, rd, 0b0111011);
959
}
960
void Assembler::REMUW(GPR rd, GPR rs1, GPR rs2) noexcept {
961
EmitRType(m_buffer, 0b0000001, rs2, rs1, 0b111, rd, 0b0111011);
962
}
963
964
// RV32A Extension Instructions
965
966
void Assembler::AMOADD_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
967
EmitAtomic(m_buffer, 0b00000, ordering, rs2, rs1, 0b010, rd, 0b0101111);
968
}
969
void Assembler::AMOAND_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
970
EmitAtomic(m_buffer, 0b01100, ordering, rs2, rs1, 0b010, rd, 0b0101111);
971
}
972
void Assembler::AMOMAX_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
973
EmitAtomic(m_buffer, 0b10100, ordering, rs2, rs1, 0b010, rd, 0b0101111);
974
}
975
void Assembler::AMOMAXU_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
976
EmitAtomic(m_buffer, 0b11100, ordering, rs2, rs1, 0b010, rd, 0b0101111);
977
}
978
void Assembler::AMOMIN_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
979
EmitAtomic(m_buffer, 0b10000, ordering, rs2, rs1, 0b010, rd, 0b0101111);
980
}
981
void Assembler::AMOMINU_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
982
EmitAtomic(m_buffer, 0b11000, ordering, rs2, rs1, 0b010, rd, 0b0101111);
983
}
984
void Assembler::AMOOR_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
985
EmitAtomic(m_buffer, 0b01000, ordering, rs2, rs1, 0b010, rd, 0b0101111);
986
}
987
void Assembler::AMOSWAP_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
988
EmitAtomic(m_buffer, 0b00001, ordering, rs2, rs1, 0b010, rd, 0b0101111);
989
}
990
void Assembler::AMOXOR_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
991
EmitAtomic(m_buffer, 0b00100, ordering, rs2, rs1, 0b010, rd, 0b0101111);
992
}
993
void Assembler::LR_W(Ordering ordering, GPR rd, GPR rs) noexcept {
994
EmitAtomic(m_buffer, 0b00010, ordering, x0, rs, 0b010, rd, 0b0101111);
995
}
996
void Assembler::SC_W(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
997
EmitAtomic(m_buffer, 0b00011, ordering, rs2, rs1, 0b010, rd, 0b0101111);
998
}
999
1000
// RV64A Extension Instructions
1001
1002
void Assembler::AMOADD_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1003
EmitAtomic(m_buffer, 0b00000, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1004
}
1005
void Assembler::AMOAND_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1006
EmitAtomic(m_buffer, 0b01100, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1007
}
1008
void Assembler::AMOMAX_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1009
EmitAtomic(m_buffer, 0b10100, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1010
}
1011
void Assembler::AMOMAXU_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1012
EmitAtomic(m_buffer, 0b11100, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1013
}
1014
void Assembler::AMOMIN_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1015
EmitAtomic(m_buffer, 0b10000, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1016
}
1017
void Assembler::AMOMINU_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1018
EmitAtomic(m_buffer, 0b11000, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1019
}
1020
void Assembler::AMOOR_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1021
EmitAtomic(m_buffer, 0b01000, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1022
}
1023
void Assembler::AMOSWAP_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1024
EmitAtomic(m_buffer, 0b00001, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1025
}
1026
void Assembler::AMOXOR_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1027
EmitAtomic(m_buffer, 0b00100, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1028
}
1029
void Assembler::LR_D(Ordering ordering, GPR rd, GPR rs) noexcept {
1030
EmitAtomic(m_buffer, 0b00010, ordering, x0, rs, 0b011, rd, 0b0101111);
1031
}
1032
void Assembler::SC_D(Ordering ordering, GPR rd, GPR rs2, GPR rs1) noexcept {
1033
EmitAtomic(m_buffer, 0b00011, ordering, rs2, rs1, 0b011, rd, 0b0101111);
1034
}
1035
1036
// RV32F Extension Instructions
1037
1038
void Assembler::FADD_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1039
EmitRType(m_buffer, 0b0000000, rs2, rs1, rmode, rd, 0b1010011);
1040
}
1041
void Assembler::FCLASS_S(GPR rd, FPR rs1) noexcept {
1042
EmitRType(m_buffer, 0b1110000, f0, rs1, 0b001, rd, 0b1010011);
1043
}
1044
void Assembler::FCVT_S_W(FPR rd, GPR rs1, RMode rmode) noexcept {
1045
EmitRType(m_buffer, 0b1101000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1046
}
1047
void Assembler::FCVT_S_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
1048
EmitRType(m_buffer, 0b1101000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1049
}
1050
void Assembler::FCVT_W_S(GPR rd, FPR rs1, RMode rmode) noexcept {
1051
EmitRType(m_buffer, 0b1100000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1052
}
1053
void Assembler::FCVT_WU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
1054
EmitRType(m_buffer, 0b1100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1055
}
1056
void Assembler::FDIV_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1057
EmitRType(m_buffer, 0b0001100, rs2, rs1, rmode, rd, 0b1010011);
1058
}
1059
void Assembler::FEQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
1060
EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b010, rd, 0b1010011);
1061
}
1062
void Assembler::FLE_S(GPR rd, FPR rs1, FPR rs2) noexcept {
1063
EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b000, rd, 0b1010011);
1064
}
1065
void Assembler::FLT_S(GPR rd, FPR rs1, FPR rs2) noexcept {
1066
EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b001, rd, 0b1010011);
1067
}
1068
void Assembler::FLW(FPR rd, int32_t offset, GPR rs) noexcept {
1069
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1070
EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b010, rd, 0b0000111);
1071
}
1072
void Assembler::FMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1073
EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000011);
1074
}
1075
void Assembler::FMAX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
1076
EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b001, rd, 0b1010011);
1077
}
1078
void Assembler::FMIN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
1079
EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b000, rd, 0b1010011);
1080
}
1081
void Assembler::FMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1082
EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000111);
1083
}
1084
void Assembler::FMUL_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1085
EmitRType(m_buffer, 0b0001000, rs2, rs1, rmode, rd, 0b1010011);
1086
}
1087
void Assembler::FMV_W_X(FPR rd, GPR rs1) noexcept {
1088
EmitRType(m_buffer, 0b1111000, f0, rs1, 0b000, rd, 0b1010011);
1089
}
1090
void Assembler::FMV_X_W(GPR rd, FPR rs1) noexcept {
1091
EmitRType(m_buffer, 0b1110000, f0, rs1, 0b000, rd, 0b1010011);
1092
}
1093
void Assembler::FNMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1094
EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001111);
1095
}
1096
void Assembler::FNMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1097
EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001011);
1098
}
1099
void Assembler::FSGNJ_S(FPR rd, FPR rs1, FPR rs2) noexcept {
1100
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b000, rd, 0b1010011);
1101
}
1102
void Assembler::FSGNJN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
1103
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b001, rd, 0b1010011);
1104
}
1105
void Assembler::FSGNJX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
1106
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b010, rd, 0b1010011);
1107
}
1108
void Assembler::FSQRT_S(FPR rd, FPR rs1, RMode rmode) noexcept {
1109
EmitRType(m_buffer, 0b0101100, f0, rs1, rmode, rd, 0b1010011);
1110
}
1111
void Assembler::FSUB_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1112
EmitRType(m_buffer, 0b0000100, rs2, rs1, rmode, rd, 0b1010011);
1113
}
1114
void Assembler::FSW(FPR rs2, int32_t offset, GPR rs1) noexcept {
1115
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1116
EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b010, 0b0100111);
1117
}
1118
1119
void Assembler::FABS_S(FPR rd, FPR rs) noexcept {
1120
FSGNJX_S(rd, rs, rs);
1121
}
1122
void Assembler::FMV_S(FPR rd, FPR rs) noexcept {
1123
FSGNJ_S(rd, rs, rs);
1124
}
1125
void Assembler::FNEG_S(FPR rd, FPR rs) noexcept {
1126
FSGNJN_S(rd, rs, rs);
1127
}
1128
1129
// RV64F Extension Instructions
1130
1131
void Assembler::FCVT_L_S(GPR rd, FPR rs1, RMode rmode) noexcept {
1132
EmitRType(m_buffer, 0b1100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1133
}
1134
void Assembler::FCVT_LU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
1135
EmitRType(m_buffer, 0b1100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1136
}
1137
void Assembler::FCVT_S_L(FPR rd, GPR rs1, RMode rmode) noexcept {
1138
EmitRType(m_buffer, 0b1101000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1139
}
1140
void Assembler::FCVT_S_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
1141
EmitRType(m_buffer, 0b1101000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1142
}
1143
1144
// RV32D Extension Instructions
1145
1146
void Assembler::FADD_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1147
EmitRType(m_buffer, 0b0000001, rs2, rs1, rmode, rd, 0b1010011);
1148
}
1149
void Assembler::FCLASS_D(GPR rd, FPR rs1) noexcept {
1150
EmitRType(m_buffer, 0b1110001, f0, rs1, 0b001, rd, 0b1010011);
1151
}
1152
void Assembler::FCVT_D_W(FPR rd, GPR rs1, RMode rmode) noexcept {
1153
EmitRType(m_buffer, 0b1101001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1154
}
1155
void Assembler::FCVT_D_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
1156
EmitRType(m_buffer, 0b1101001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1157
}
1158
void Assembler::FCVT_W_D(GPR rd, FPR rs1, RMode rmode) noexcept {
1159
EmitRType(m_buffer, 0b1100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1160
}
1161
void Assembler::FCVT_WU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
1162
EmitRType(m_buffer, 0b1100001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1163
}
1164
void Assembler::FCVT_D_S(FPR rd, FPR rs1, RMode rmode) noexcept {
1165
EmitRType(m_buffer, 0b0100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1166
}
1167
void Assembler::FCVT_S_D(FPR rd, FPR rs1, RMode rmode) noexcept {
1168
EmitRType(m_buffer, 0b0100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1169
}
1170
void Assembler::FDIV_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1171
EmitRType(m_buffer, 0b0001101, rs2, rs1, rmode, rd, 0b1010011);
1172
}
1173
void Assembler::FEQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
1174
EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b010, rd, 0b1010011);
1175
}
1176
void Assembler::FLE_D(GPR rd, FPR rs1, FPR rs2) noexcept {
1177
EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b000, rd, 0b1010011);
1178
}
1179
void Assembler::FLT_D(GPR rd, FPR rs1, FPR rs2) noexcept {
1180
EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b001, rd, 0b1010011);
1181
}
1182
void Assembler::FLD(FPR rd, int32_t offset, GPR rs) noexcept {
1183
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1184
EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b011, rd, 0b0000111);
1185
}
1186
void Assembler::FMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1187
EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000011);
1188
}
1189
void Assembler::FMAX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
1190
EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b001, rd, 0b1010011);
1191
}
1192
void Assembler::FMIN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
1193
EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b000, rd, 0b1010011);
1194
}
1195
void Assembler::FMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1196
EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000111);
1197
}
1198
void Assembler::FMUL_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1199
EmitRType(m_buffer, 0b0001001, rs2, rs1, rmode, rd, 0b1010011);
1200
}
1201
void Assembler::FNMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1202
EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001111);
1203
}
1204
void Assembler::FNMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1205
EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001011);
1206
}
1207
void Assembler::FSGNJ_D(FPR rd, FPR rs1, FPR rs2) noexcept {
1208
EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b000, rd, 0b1010011);
1209
}
1210
void Assembler::FSGNJN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
1211
EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b001, rd, 0b1010011);
1212
}
1213
void Assembler::FSGNJX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
1214
EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b010, rd, 0b1010011);
1215
}
1216
void Assembler::FSQRT_D(FPR rd, FPR rs1, RMode rmode) noexcept {
1217
EmitRType(m_buffer, 0b0101101, f0, rs1, rmode, rd, 0b1010011);
1218
}
1219
void Assembler::FSUB_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1220
EmitRType(m_buffer, 0b0000101, rs2, rs1, rmode, rd, 0b1010011);
1221
}
1222
void Assembler::FSD(FPR rs2, int32_t offset, GPR rs1) noexcept {
1223
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1224
EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b011, 0b0100111);
1225
}
1226
1227
void Assembler::FABS_D(FPR rd, FPR rs) noexcept {
1228
FSGNJX_D(rd, rs, rs);
1229
}
1230
void Assembler::FMV_D(FPR rd, FPR rs) noexcept {
1231
FSGNJ_D(rd, rs, rs);
1232
}
1233
void Assembler::FNEG_D(FPR rd, FPR rs) noexcept {
1234
FSGNJN_D(rd, rs, rs);
1235
}
1236
1237
// RV64D Extension Instructions
1238
1239
void Assembler::FCVT_L_D(GPR rd, FPR rs1, RMode rmode) noexcept {
1240
EmitRType(m_buffer, 0b1100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1241
}
1242
void Assembler::FCVT_LU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
1243
EmitRType(m_buffer, 0b1100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1244
}
1245
void Assembler::FCVT_D_L(FPR rd, GPR rs1, RMode rmode) noexcept {
1246
EmitRType(m_buffer, 0b1101001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1247
}
1248
void Assembler::FCVT_D_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
1249
EmitRType(m_buffer, 0b1101001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1250
}
1251
void Assembler::FMV_D_X(FPR rd, GPR rs1) noexcept {
1252
EmitRType(m_buffer, 0b1111001, f0, rs1, 0b000, rd, 0b1010011);
1253
}
1254
void Assembler::FMV_X_D(GPR rd, FPR rs1) noexcept {
1255
EmitRType(m_buffer, 0b1110001, f0, rs1, 0b000, rd, 0b1010011);
1256
}
1257
1258
// RV32Q Extension Instructions
1259
1260
void Assembler::FADD_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1261
EmitRType(m_buffer, 0b0000011, rs2, rs1, rmode, rd, 0b1010011);
1262
}
1263
void Assembler::FCLASS_Q(GPR rd, FPR rs1) noexcept {
1264
EmitRType(m_buffer, 0b1110011, f0, rs1, 0b001, rd, 0b1010011);
1265
}
1266
void Assembler::FCVT_Q_W(FPR rd, GPR rs1, RMode rmode) noexcept {
1267
EmitRType(m_buffer, 0b1101011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1268
}
1269
void Assembler::FCVT_Q_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
1270
EmitRType(m_buffer, 0b1101011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1271
}
1272
void Assembler::FCVT_W_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
1273
EmitRType(m_buffer, 0b1100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1274
}
1275
void Assembler::FCVT_WU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
1276
EmitRType(m_buffer, 0b1100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1277
}
1278
void Assembler::FCVT_Q_D(FPR rd, FPR rs1, RMode rmode) noexcept {
1279
EmitRType(m_buffer, 0b0100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1280
}
1281
void Assembler::FCVT_D_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
1282
EmitRType(m_buffer, 0b0100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1283
}
1284
void Assembler::FCVT_Q_S(FPR rd, FPR rs1, RMode rmode) noexcept {
1285
EmitRType(m_buffer, 0b0100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1286
}
1287
void Assembler::FCVT_S_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
1288
EmitRType(m_buffer, 0b0100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1289
}
1290
void Assembler::FDIV_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1291
EmitRType(m_buffer, 0b0001111, rs2, rs1, rmode, rd, 0b1010011);
1292
}
1293
void Assembler::FEQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
1294
EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b010, rd, 0b1010011);
1295
}
1296
void Assembler::FLE_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
1297
EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b000, rd, 0b1010011);
1298
}
1299
void Assembler::FLT_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
1300
EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b001, rd, 0b1010011);
1301
}
1302
void Assembler::FLQ(FPR rd, int32_t offset, GPR rs) noexcept {
1303
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1304
EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b100, rd, 0b0000111);
1305
}
1306
void Assembler::FMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1307
EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000011);
1308
}
1309
void Assembler::FMAX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
1310
EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b001, rd, 0b1010011);
1311
}
1312
void Assembler::FMIN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
1313
EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b000, rd, 0b1010011);
1314
}
1315
void Assembler::FMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1316
EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000111);
1317
}
1318
void Assembler::FMUL_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1319
EmitRType(m_buffer, 0b0001011, rs2, rs1, rmode, rd, 0b1010011);
1320
}
1321
void Assembler::FNMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1322
EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001111);
1323
}
1324
void Assembler::FNMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1325
EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001011);
1326
}
1327
void Assembler::FSGNJ_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
1328
EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b000, rd, 0b1010011);
1329
}
1330
void Assembler::FSGNJN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
1331
EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b001, rd, 0b1010011);
1332
}
1333
void Assembler::FSGNJX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
1334
EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b010, rd, 0b1010011);
1335
}
1336
void Assembler::FSQRT_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
1337
EmitRType(m_buffer, 0b0101111, f0, rs1, rmode, rd, 0b1010011);
1338
}
1339
void Assembler::FSUB_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1340
EmitRType(m_buffer, 0b0000111, rs2, rs1, rmode, rd, 0b1010011);
1341
}
1342
void Assembler::FSQ(FPR rs2, int32_t offset, GPR rs1) noexcept {
1343
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1344
EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b100, 0b0100111);
1345
}
1346
1347
void Assembler::FABS_Q(FPR rd, FPR rs) noexcept {
1348
FSGNJX_Q(rd, rs, rs);
1349
}
1350
void Assembler::FMV_Q(FPR rd, FPR rs) noexcept {
1351
FSGNJ_Q(rd, rs, rs);
1352
}
1353
void Assembler::FNEG_Q(FPR rd, FPR rs) noexcept {
1354
FSGNJN_Q(rd, rs, rs);
1355
}
1356
1357
// RV64Q Extension Instructions
1358
1359
void Assembler::FCVT_L_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
1360
EmitRType(m_buffer, 0b1100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1361
}
1362
void Assembler::FCVT_LU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
1363
EmitRType(m_buffer, 0b1100011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1364
}
1365
void Assembler::FCVT_Q_L(FPR rd, GPR rs1, RMode rmode) noexcept {
1366
EmitRType(m_buffer, 0b1101011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1367
}
1368
void Assembler::FCVT_Q_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
1369
EmitRType(m_buffer, 0b1101011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1370
}
1371
1372
// RV32Zfh Extension Instructions
1373
1374
void Assembler::FADD_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1375
EmitRType(m_buffer, 0b0000010, rs2, rs1, rmode, rd, 0b1010011);
1376
}
1377
void Assembler::FCLASS_H(GPR rd, FPR rs1) noexcept {
1378
EmitRType(m_buffer, 0b1110010, f0, rs1, 0b001, rd, 0b1010011);
1379
}
1380
void Assembler::FCVT_D_H(FPR rd, FPR rs1, RMode rmode) noexcept {
1381
EmitRType(m_buffer, 0b0100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1382
}
1383
void Assembler::FCVT_H_D(FPR rd, FPR rs1, RMode rmode) noexcept {
1384
EmitRType(m_buffer, 0b0100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1385
}
1386
void Assembler::FCVT_H_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
1387
EmitRType(m_buffer, 0b0100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1388
}
1389
void Assembler::FCVT_H_S(FPR rd, FPR rs1, RMode rmode) noexcept {
1390
EmitRType(m_buffer, 0b0100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1391
}
1392
void Assembler::FCVT_H_W(FPR rd, GPR rs1, RMode rmode) noexcept {
1393
EmitRType(m_buffer, 0b1101010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1394
}
1395
void Assembler::FCVT_H_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
1396
EmitRType(m_buffer, 0b1101010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1397
}
1398
void Assembler::FCVT_Q_H(FPR rd, FPR rs1, RMode rmode) noexcept {
1399
EmitRType(m_buffer, 0b0100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1400
}
1401
void Assembler::FCVT_S_H(FPR rd, FPR rs1, RMode rmode) noexcept {
1402
EmitRType(m_buffer, 0b0100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1403
}
1404
void Assembler::FCVT_W_H(GPR rd, FPR rs1, RMode rmode) noexcept {
1405
EmitRType(m_buffer, 0b1100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1406
}
1407
void Assembler::FCVT_WU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
1408
EmitRType(m_buffer, 0b1100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1409
}
1410
void Assembler::FDIV_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1411
EmitRType(m_buffer, 0b0001110, rs2, rs1, rmode, rd, 0b1010011);
1412
}
1413
void Assembler::FEQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
1414
EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b010, rd, 0b1010011);
1415
}
1416
void Assembler::FLE_H(GPR rd, FPR rs1, FPR rs2) noexcept {
1417
EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b000, rd, 0b1010011);
1418
}
1419
void Assembler::FLH(FPR rd, int32_t offset, GPR rs) noexcept {
1420
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1421
EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b001, rd, 0b0000111);
1422
}
1423
void Assembler::FLT_H(GPR rd, FPR rs1, FPR rs2) noexcept {
1424
EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b001, rd, 0b1010011);
1425
}
1426
void Assembler::FMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1427
EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000011);
1428
}
1429
void Assembler::FMAX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
1430
EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b001, rd, 0b1010011);
1431
}
1432
void Assembler::FMIN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
1433
EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b000, rd, 0b1010011);
1434
}
1435
void Assembler::FMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1436
EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000111);
1437
}
1438
void Assembler::FMUL_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1439
EmitRType(m_buffer, 0b0001010, rs2, rs1, rmode, rd, 0b1010011);
1440
}
1441
void Assembler::FMV_H_X(FPR rd, GPR rs1) noexcept {
1442
EmitRType(m_buffer, 0b1111010, f0, rs1, 0b000, rd, 0b1010011);
1443
}
1444
void Assembler::FMV_X_H(GPR rd, FPR rs1) noexcept {
1445
EmitRType(m_buffer, 0b1110010, f0, rs1, 0b000, rd, 0b1010011);
1446
}
1447
void Assembler::FNMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1448
EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001111);
1449
}
1450
void Assembler::FNMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
1451
EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001011);
1452
}
1453
void Assembler::FSGNJ_H(FPR rd, FPR rs1, FPR rs2) noexcept {
1454
EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b000, rd, 0b1010011);
1455
}
1456
void Assembler::FSGNJN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
1457
EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b001, rd, 0b1010011);
1458
}
1459
void Assembler::FSGNJX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
1460
EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b010, rd, 0b1010011);
1461
}
1462
void Assembler::FSH(FPR rs2, int32_t offset, GPR rs1) noexcept {
1463
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
1464
EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b001, 0b0100111);
1465
}
1466
void Assembler::FSQRT_H(FPR rd, FPR rs1, RMode rmode) noexcept {
1467
EmitRType(m_buffer, 0b0101110, f0, rs1, rmode, rd, 0b1010011);
1468
}
1469
void Assembler::FSUB_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
1470
EmitRType(m_buffer, 0b0000110, rs2, rs1, rmode, rd, 0b1010011);
1471
}
1472
1473
// RV64Zfh Extension Instructions
1474
1475
void Assembler::FCVT_L_H(GPR rd, FPR rs1, RMode rmode) noexcept {
1476
EmitRType(m_buffer, 0b1100010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1477
}
1478
void Assembler::FCVT_LU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
1479
EmitRType(m_buffer, 0b1100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1480
}
1481
void Assembler::FCVT_H_L(FPR rd, GPR rs1, RMode rmode) noexcept {
1482
EmitRType(m_buffer, 0b1101010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1483
}
1484
void Assembler::FCVT_H_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
1485
EmitRType(m_buffer, 0b1101010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
1486
}
1487
1488
// RVB Extension Instructions
1489
1490
void Assembler::ADDUW(GPR rd, GPR rs1, GPR rs2) noexcept {
1491
EmitRType(m_buffer, 0b0000100, rs2, rs1, 0b000, rd, 0b0111011);
1492
}
1493
1494
void Assembler::ANDN(GPR rd, GPR rs1, GPR rs2) noexcept {
1495
EmitRType(m_buffer, 0b0100000, rs2, rs1, 0b111, rd, 0b0110011);
1496
}
1497
1498
void Assembler::BCLR(GPR rd, GPR rs1, GPR rs2) noexcept {
1499
EmitRType(m_buffer, 0b0100100, rs2, rs1, 0b001, rd, 0b0110011);
1500
}
1501
1502
void Assembler::BCLRI(GPR rd, GPR rs, uint32_t bit) noexcept {
1503
BISCUIT_ASSERT(bit <= 63);
1504
const auto imm = (0b010010U << 6) | bit;
1505
EmitIType(m_buffer, imm, rs, 0b001, rd, 0b0010011);
1506
}
1507
1508
void Assembler::BEXT(GPR rd, GPR rs1, GPR rs2) noexcept {
1509
EmitRType(m_buffer, 0b0100100, rs2, rs1, 0b101, rd, 0b0110011);
1510
}
1511
1512
void Assembler::BEXTI(GPR rd, GPR rs, uint32_t bit) noexcept {
1513
BISCUIT_ASSERT(bit <= 63);
1514
const auto imm = (0b010010U << 6) | bit;
1515
EmitIType(m_buffer, imm, rs, 0b101, rd, 0b0010011);
1516
}
1517
1518
void Assembler::BINV(GPR rd, GPR rs1, GPR rs2) noexcept {
1519
EmitRType(m_buffer, 0b0110100, rs2, rs1, 0b001, rd, 0b0110011);
1520
}
1521
1522
void Assembler::BINVI(GPR rd, GPR rs, uint32_t bit) noexcept {
1523
BISCUIT_ASSERT(bit <= 63);
1524
const auto imm = (0b011010U << 6) | bit;
1525
EmitIType(m_buffer, imm, rs, 0b001, rd, 0b0010011);
1526
}
1527
1528
void Assembler::CLMUL(GPR rd, GPR rs1, GPR rs2) noexcept {
1529
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b001, rd, 0b0110011);
1530
}
1531
1532
void Assembler::CLMULH(GPR rd, GPR rs1, GPR rs2) noexcept {
1533
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b011, rd, 0b0110011);
1534
}
1535
1536
void Assembler::CLMULR(GPR rd, GPR rs1, GPR rs2) noexcept {
1537
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b010, rd, 0b0110011);
1538
}
1539
1540
void Assembler::CLZ(GPR rd, GPR rs) noexcept {
1541
EmitIType(m_buffer, 0b011000000000, rs, 0b001, rd, 0b0010011);
1542
}
1543
1544
void Assembler::CLZW(GPR rd, GPR rs) noexcept {
1545
EmitIType(m_buffer, 0b011000000000, rs, 0b001, rd, 0b0011011);
1546
}
1547
1548
void Assembler::CPOP(GPR rd, GPR rs) noexcept {
1549
EmitIType(m_buffer, 0b011000000010, rs, 0b001, rd, 0b0010011);
1550
}
1551
1552
void Assembler::CPOPW(GPR rd, GPR rs) noexcept {
1553
EmitIType(m_buffer, 0b011000000010, rs, 0b001, rd, 0b0011011);
1554
}
1555
1556
void Assembler::CTZ(GPR rd, GPR rs) noexcept {
1557
EmitIType(m_buffer, 0b011000000001, rs, 0b001, rd, 0b0010011);
1558
}
1559
1560
void Assembler::CTZW(GPR rd, GPR rs) noexcept {
1561
EmitIType(m_buffer, 0b011000000001, rs, 0b001, rd, 0b0011011);
1562
}
1563
1564
void Assembler::MAX(GPR rd, GPR rs1, GPR rs2) noexcept {
1565
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b110, rd, 0b0110011);
1566
}
1567
1568
void Assembler::MAXU(GPR rd, GPR rs1, GPR rs2) noexcept {
1569
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b111, rd, 0b0110011);
1570
}
1571
1572
void Assembler::MIN(GPR rd, GPR rs1, GPR rs2) noexcept {
1573
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b100, rd, 0b0110011);
1574
}
1575
1576
void Assembler::MINU(GPR rd, GPR rs1, GPR rs2) noexcept {
1577
EmitRType(m_buffer, 0b0000101, rs2, rs1, 0b101, rd, 0b0110011);
1578
}
1579
1580
void Assembler::ORCB(GPR rd, GPR rs) noexcept {
1581
EmitIType(m_buffer, 0b001010000111, rs, 0b101, rd, 0b0010011);
1582
}
1583
1584
void Assembler::ORN(GPR rd, GPR rs1, GPR rs2) noexcept {
1585
EmitRType(m_buffer, 0b0100000, rs2, rs1, 0b110, rd, 0b0110011);
1586
}
1587
1588
void Assembler::PACK(GPR rd, GPR rs1, GPR rs2) noexcept {
1589
EmitRType(m_buffer, 0b0000100, rs2, rs1, 0b100, rd, 0b0110011);
1590
}
1591
1592
void Assembler::PACKH(GPR rd, GPR rs1, GPR rs2) noexcept {
1593
EmitRType(m_buffer, 0b0000100, rs2, rs1, 0b111, rd, 0b0110011);
1594
}
1595
1596
void Assembler::PACKW(GPR rd, GPR rs1, GPR rs2) noexcept {
1597
EmitRType(m_buffer, 0b0000100, rs2, rs1, 0b100, rd, 0b0111011);
1598
}
1599
1600
void Assembler::REV8_32(GPR rd, GPR rs) noexcept {
1601
EmitIType(m_buffer, 0b011010011000, rs, 0b101, rd, 0b0010011);
1602
}
1603
1604
void Assembler::REV8_64(GPR rd, GPR rs) noexcept {
1605
EmitIType(m_buffer, 0b011010111000, rs, 0b101, rd, 0b0010011);
1606
}
1607
1608
void Assembler::REV_B(GPR rd, GPR rs) noexcept {
1609
EmitIType(m_buffer, 0b011010000111, rs, 0b101, rd, 0b0010011);
1610
}
1611
1612
void Assembler::ROL(GPR rd, GPR rs1, GPR rs2) noexcept {
1613
EmitRType(m_buffer, 0b0110000, rs2, rs1, 0b001, rd, 0b0110011);
1614
}
1615
1616
void Assembler::ROLW(GPR rd, GPR rs1, GPR rs2) noexcept {
1617
EmitRType(m_buffer, 0b0110000, rs2, rs1, 0b001, rd, 0b0111011);
1618
}
1619
1620
void Assembler::ROR(GPR rd, GPR rs1, GPR rs2) noexcept {
1621
EmitRType(m_buffer, 0b0110000, rs2, rs1, 0b101, rd, 0b0110011);
1622
}
1623
1624
void Assembler::RORI(GPR rd, GPR rs, uint32_t rotate_amount) noexcept {
1625
BISCUIT_ASSERT(rotate_amount <= 63);
1626
const auto imm = (0b011000U << 6) | rotate_amount;
1627
EmitIType(m_buffer, imm, rs, 0b101, rd, 0b0010011);
1628
}
1629
1630
void Assembler::RORIW(GPR rd, GPR rs, uint32_t rotate_amount) noexcept {
1631
BISCUIT_ASSERT(rotate_amount <= 63);
1632
const auto imm = (0b011000U << 6) | rotate_amount;
1633
EmitIType(m_buffer, imm, rs, 0b101, rd, 0b0011011);
1634
}
1635
1636
void Assembler::RORW(GPR rd, GPR rs1, GPR rs2) noexcept {
1637
EmitRType(m_buffer, 0b0110000, rs2, rs1, 0b101, rd, 0b0111011);
1638
}
1639
1640
void Assembler::SEXTB(GPR rd, GPR rs) noexcept {
1641
EmitIType(m_buffer, 0b011000000100, rs, 0b001, rd, 0b0010011);
1642
}
1643
1644
void Assembler::SEXTH(GPR rd, GPR rs) noexcept {
1645
EmitIType(m_buffer, 0b011000000101, rs, 0b001, rd, 0b0010011);
1646
}
1647
1648
void Assembler::SH1ADD(GPR rd, GPR rs1, GPR rs2) noexcept {
1649
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b010, rd, 0b0110011);
1650
}
1651
1652
void Assembler::SH1ADDUW(GPR rd, GPR rs1, GPR rs2) noexcept {
1653
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b010, rd, 0b0111011);
1654
}
1655
1656
void Assembler::SH2ADD(GPR rd, GPR rs1, GPR rs2) noexcept {
1657
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b100, rd, 0b0110011);
1658
}
1659
1660
void Assembler::SH2ADDUW(GPR rd, GPR rs1, GPR rs2) noexcept {
1661
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b100, rd, 0b0111011);
1662
}
1663
1664
void Assembler::SH3ADD(GPR rd, GPR rs1, GPR rs2) noexcept {
1665
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b110, rd, 0b0110011);
1666
}
1667
1668
void Assembler::SH3ADDUW(GPR rd, GPR rs1, GPR rs2) noexcept {
1669
EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b110, rd, 0b0111011);
1670
}
1671
1672
void Assembler::SLLIUW(GPR rd, GPR rs, uint32_t shift_amount) noexcept {
1673
BISCUIT_ASSERT(shift_amount <= 63);
1674
const auto imm = (0b000010U << 6) | shift_amount;
1675
EmitIType(m_buffer, imm, rs, 0b001, rd, 0b0011011);
1676
}
1677
1678
void Assembler::UNZIP(GPR rd, GPR rs) noexcept {
1679
EmitIType(m_buffer, 0b000010011111, rs, 0b101, rd, 0b0010011);
1680
}
1681
1682
void Assembler::XNOR(GPR rd, GPR rs1, GPR rs2) noexcept {
1683
EmitRType(m_buffer, 0b0100000, rs2, rs1, 0b100, rd, 0b0110011);
1684
}
1685
1686
void Assembler::XPERMB(GPR rd, GPR rs1, GPR rs2) noexcept {
1687
EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b100, rd, 0b0110011);
1688
}
1689
1690
void Assembler::XPERMN(GPR rd, GPR rs1, GPR rs2) noexcept {
1691
EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b010, rd, 0b0110011);
1692
}
1693
1694
void Assembler::ZEXTH_32(GPR rd, GPR rs) noexcept {
1695
EmitIType(m_buffer, 0b000010000000, rs, 0b100, rd, 0b0110011);
1696
}
1697
1698
void Assembler::ZEXTH_64(GPR rd, GPR rs) noexcept {
1699
EmitIType(m_buffer, 0b000010000000, rs, 0b100, rd, 0b0111011);
1700
}
1701
1702
void Assembler::ZEXTW(GPR rd, GPR rs) noexcept {
1703
ADDUW(rd, rs, x0);
1704
}
1705
1706
void Assembler::ZIP(GPR rd, GPR rs) noexcept {
1707
EmitIType(m_buffer, 0b000010011110, rs, 0b001, rd, 0b0010011);
1708
}
1709
1710
void Assembler::BSET(GPR rd, GPR rs1, GPR rs2) noexcept {
1711
EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b001, rd, 0b0110011);
1712
}
1713
1714
void Assembler::BSETI(GPR rd, GPR rs, uint32_t bit) noexcept {
1715
BISCUIT_ASSERT(bit <= 63);
1716
const auto imm = (0b001010U << 6) | bit;
1717
EmitIType(m_buffer, imm, rs, 0b001, rd, 0b0110011);
1718
}
1719
1720
// RVC Extension Instructions
1721
1722
void Assembler::C_ADD(GPR rd, GPR rs) noexcept {
1723
BISCUIT_ASSERT(rs != x0);
1724
m_buffer.Emit16(0x9002 | (rd.Index() << 7) | (rs.Index() << 2));
1725
}
1726
1727
void Assembler::C_ADDI(GPR rd, int32_t imm) noexcept {
1728
BISCUIT_ASSERT(imm != 0);
1729
BISCUIT_ASSERT(IsValidSigned6BitImm(imm));
1730
EmitCompressedImmediate(m_buffer, 0b000, static_cast<uint32_t>(imm), rd, 0b01);
1731
}
1732
1733
void Assembler::C_ADDIW(GPR rd, int32_t imm) noexcept {
1734
BISCUIT_ASSERT(IsValidSigned6BitImm(imm));
1735
EmitCompressedImmediate(m_buffer, 0b001, static_cast<uint32_t>(imm), rd, 0b01);
1736
}
1737
1738
void Assembler::C_ADDI4SPN(GPR rd, uint32_t imm) noexcept {
1739
BISCUIT_ASSERT(imm != 0);
1740
BISCUIT_ASSERT(imm <= 1020);
1741
BISCUIT_ASSERT(imm % 4 == 0);
1742
1743
// clang-format off
1744
const auto new_imm = ((imm & 0x030) << 2) |
1745
((imm & 0x3C0) >> 4) |
1746
((imm & 0x004) >> 1) |
1747
((imm & 0x008) >> 3);
1748
// clang-format on
1749
1750
EmitCompressedWideImmediate(m_buffer, 0b000, new_imm, rd, 0b00);
1751
}
1752
1753
void Assembler::C_ADDW(GPR rd, GPR rs) noexcept {
1754
EmitCompressedRegArith(m_buffer, 0b100111, rd, 0b01, rs, 0b01);
1755
}
1756
1757
void Assembler::C_ADDI16SP(int32_t imm) noexcept {
1758
BISCUIT_ASSERT(imm != 0);
1759
BISCUIT_ASSERT(imm >= -512 && imm <= 496);
1760
BISCUIT_ASSERT(imm % 16 == 0);
1761
1762
// clang-format off
1763
const auto uimm = static_cast<uint32_t>(imm);
1764
const auto new_imm = ((uimm & 0x020) >> 3) |
1765
((uimm & 0x180) >> 4) |
1766
((uimm & 0x040) >> 1) |
1767
((uimm & 0x010) << 2) |
1768
((uimm & 0x200) << 3);
1769
// clang-format on
1770
1771
m_buffer.Emit16(0x6000U | new_imm | (x2.Index() << 7) | 0b01U);
1772
}
1773
1774
void Assembler::C_AND(GPR rd, GPR rs) noexcept {
1775
EmitCompressedRegArith(m_buffer, 0b100011, rd, 0b11, rs, 0b01);
1776
}
1777
1778
void Assembler::C_ANDI(GPR rd, uint32_t imm) noexcept {
1779
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
1780
1781
constexpr auto base = 0x8801U;
1782
const auto shift_enc = ((imm & 0b11111) << 2) | ((imm & 0b100000) << 7);
1783
const auto reg = CompressedRegTo3BitEncoding(rd);
1784
1785
m_buffer.Emit16(base | shift_enc | (reg << 7));
1786
}
1787
1788
void Assembler::C_BEQZ(GPR rs, int32_t offset) noexcept {
1789
EmitCompressedBranch(m_buffer, 0b110, offset, rs, 0b01);
1790
}
1791
1792
void Assembler::C_BEQZ(GPR rs, Label* label) noexcept {
1793
const auto address = LinkAndGetOffset(label);
1794
C_BEQZ(rs, static_cast<int32_t>(address));
1795
}
1796
1797
void Assembler::C_BNEZ(GPR rs, int32_t offset) noexcept {
1798
EmitCompressedBranch(m_buffer, 0b111, offset, rs, 0b01);
1799
}
1800
1801
void Assembler::C_BNEZ(GPR rs, Label* label) noexcept {
1802
const auto address = LinkAndGetOffset(label);
1803
C_BNEZ(rs, static_cast<int32_t>(address));
1804
}
1805
1806
void Assembler::C_EBREAK() noexcept {
1807
m_buffer.Emit16(0x9002);
1808
}
1809
1810
void Assembler::C_FLD(FPR rd, uint32_t imm, GPR rs) noexcept {
1811
BISCUIT_ASSERT(imm <= 248);
1812
BISCUIT_ASSERT(imm % 8 == 0);
1813
1814
EmitCompressedLoad(m_buffer, 0b001, imm, rs, rd, 0b00);
1815
}
1816
1817
void Assembler::C_FLDSP(FPR rd, uint32_t imm) noexcept {
1818
BISCUIT_ASSERT(imm <= 504);
1819
BISCUIT_ASSERT(imm % 8 == 0);
1820
1821
// clang-format off
1822
const auto new_imm = ((imm & 0x018) << 2) |
1823
((imm & 0x1C0) >> 4) |
1824
((imm & 0x020) << 7);
1825
// clang-format on
1826
1827
m_buffer.Emit16(0x2002U | (rd.Index() << 7) | new_imm);
1828
}
1829
1830
void Assembler::C_FLW(FPR rd, uint32_t imm, GPR rs) noexcept {
1831
BISCUIT_ASSERT(imm <= 124);
1832
BISCUIT_ASSERT(imm % 4 == 0);
1833
1834
imm &= 0x7C;
1835
const auto new_imm = ((imm & 0b0100) << 5) | (imm & 0x78);
1836
EmitCompressedLoad(m_buffer, 0b011, new_imm, rs, rd, 0b00);
1837
}
1838
1839
void Assembler::C_FLWSP(FPR rd, uint32_t imm) noexcept {
1840
BISCUIT_ASSERT(imm <= 252);
1841
BISCUIT_ASSERT(imm % 4 == 0);
1842
1843
// clang-format off
1844
const auto new_imm = ((imm & 0x020) << 7) |
1845
((imm & 0x0C0) >> 4) |
1846
((imm & 0x01C) << 2);
1847
// clang-format on
1848
1849
m_buffer.Emit16(0x6002U | (rd.Index() << 7) | new_imm);
1850
}
1851
1852
void Assembler::C_FSD(FPR rs2, uint32_t imm, GPR rs1) noexcept {
1853
BISCUIT_ASSERT(imm <= 248);
1854
BISCUIT_ASSERT(imm % 8 == 0);
1855
1856
EmitCompressedStore(m_buffer, 0b101, imm, rs1, rs2, 0b00);
1857
}
1858
1859
void Assembler::C_FSDSP(FPR rs, uint32_t imm) noexcept {
1860
BISCUIT_ASSERT(imm <= 504);
1861
BISCUIT_ASSERT(imm % 8 == 0);
1862
1863
// clang-format off
1864
const auto new_imm = ((imm & 0x038) << 7) |
1865
((imm & 0x1C0) << 1);
1866
// clang-format on
1867
1868
m_buffer.Emit16(0xA002U | (rs.Index() << 2) | new_imm);
1869
}
1870
1871
void Assembler::C_J(Label* label) noexcept {
1872
const auto address = LinkAndGetOffset(label);
1873
C_J(static_cast<int32_t>(address));
1874
}
1875
1876
void Assembler::C_J(int32_t offset) noexcept {
1877
EmitCompressedJump(m_buffer, 0b101, offset, 0b01);
1878
}
1879
1880
void Assembler::C_JAL(Label* label) noexcept {
1881
const auto address = LinkAndGetOffset(label);
1882
C_JAL(static_cast<int32_t>(address));
1883
}
1884
1885
void Assembler::C_JAL(int32_t offset) noexcept {
1886
EmitCompressedJump(m_buffer, 0b001, offset, 0b01);
1887
}
1888
1889
void Assembler::C_FSW(FPR rs2, uint32_t imm, GPR rs1) noexcept {
1890
imm &= 0x7C;
1891
const auto new_imm = ((imm & 0b0100) << 5) | (imm & 0x78);
1892
EmitCompressedStore(m_buffer, 0b111, new_imm, rs1, rs2, 0b00);
1893
}
1894
1895
void Assembler::C_FSWSP(FPR rs, uint32_t imm) noexcept {
1896
BISCUIT_ASSERT(imm <= 252);
1897
BISCUIT_ASSERT(imm % 4 == 0);
1898
1899
// clang-format off
1900
const auto new_imm = ((imm & 0x0C0) << 1) |
1901
((imm & 0x03C) << 7);
1902
// clang-format on
1903
1904
m_buffer.Emit16(0xE002U | (rs.Index() << 2) | new_imm);
1905
}
1906
1907
void Assembler::C_JALR(GPR rs) noexcept {
1908
BISCUIT_ASSERT(rs != x0);
1909
m_buffer.Emit16(0x9002 | (rs.Index() << 7));
1910
}
1911
1912
void Assembler::C_JR(GPR rs) noexcept {
1913
BISCUIT_ASSERT(rs != x0);
1914
m_buffer.Emit16(0x8002 | (rs.Index() << 7));
1915
}
1916
1917
void Assembler::C_LD(GPR rd, uint32_t imm, GPR rs) noexcept {
1918
BISCUIT_ASSERT(imm <= 248);
1919
BISCUIT_ASSERT(imm % 8 == 0);
1920
1921
EmitCompressedLoad(m_buffer, 0b011, imm, rs, rd, 0b00);
1922
}
1923
1924
void Assembler::C_LDSP(GPR rd, uint32_t imm) noexcept {
1925
BISCUIT_ASSERT(rd != x0);
1926
BISCUIT_ASSERT(imm <= 504);
1927
BISCUIT_ASSERT(imm % 8 == 0);
1928
1929
// clang-format off
1930
const auto new_imm = ((imm & 0x018) << 2) |
1931
((imm & 0x1C0) >> 4) |
1932
((imm & 0x020) << 7);
1933
// clang-format on
1934
1935
m_buffer.Emit16(0x6002U | (rd.Index() << 7) | new_imm);
1936
}
1937
1938
void Assembler::C_LI(GPR rd, int32_t imm) noexcept {
1939
BISCUIT_ASSERT(IsValidSigned6BitImm(imm));
1940
EmitCompressedImmediate(m_buffer, 0b010, static_cast<uint32_t>(imm), rd, 0b01);
1941
}
1942
1943
void Assembler::C_LQ(GPR rd, uint32_t imm, GPR rs) noexcept {
1944
BISCUIT_ASSERT(imm <= 496);
1945
BISCUIT_ASSERT(imm % 16 == 0);
1946
1947
imm &= 0x1F0;
1948
const auto new_imm = ((imm & 0x100) >> 5) | (imm & 0xF0);
1949
EmitCompressedLoad(m_buffer, 0b001, new_imm, rs, rd, 0b00);
1950
}
1951
1952
void Assembler::C_LQSP(GPR rd, uint32_t imm) noexcept {
1953
BISCUIT_ASSERT(rd != x0);
1954
BISCUIT_ASSERT(imm <= 1008);
1955
BISCUIT_ASSERT(imm % 16 == 0);
1956
1957
// clang-format off
1958
const auto new_imm = ((imm & 0x020) << 7) |
1959
((imm & 0x010) << 2) |
1960
((imm & 0x3C0) >> 4);
1961
// clang-format on
1962
1963
m_buffer.Emit16(0x2002U | (rd.Index() << 7) | new_imm);
1964
}
1965
1966
void Assembler::C_LUI(GPR rd, uint32_t imm) noexcept {
1967
BISCUIT_ASSERT(imm != 0);
1968
BISCUIT_ASSERT(rd != x0 && rd != x2);
1969
1970
const auto new_imm = (imm & 0x3F000) >> 12;
1971
EmitCompressedImmediate(m_buffer, 0b011, new_imm, rd, 0b01);
1972
}
1973
1974
void Assembler::C_LW(GPR rd, uint32_t imm, GPR rs) noexcept {
1975
BISCUIT_ASSERT(imm <= 124);
1976
BISCUIT_ASSERT(imm % 4 == 0);
1977
1978
imm &= 0x7C;
1979
const auto new_imm = ((imm & 0b0100) << 5) | (imm & 0x78);
1980
EmitCompressedLoad(m_buffer, 0b010, new_imm, rs, rd, 0b00);
1981
}
1982
1983
void Assembler::C_LWSP(GPR rd, uint32_t imm) noexcept {
1984
BISCUIT_ASSERT(rd != x0);
1985
BISCUIT_ASSERT(imm <= 252);
1986
BISCUIT_ASSERT(imm % 4 == 0);
1987
1988
// clang-format off
1989
const auto new_imm = ((imm & 0x020) << 7) |
1990
((imm & 0x0C0) >> 4) |
1991
((imm & 0x01C) << 2);
1992
// clang-format on
1993
1994
m_buffer.Emit16(0x4002U | (rd.Index() << 7) | new_imm);
1995
}
1996
1997
void Assembler::C_MV(GPR rd, GPR rs) noexcept {
1998
BISCUIT_ASSERT(rd != x0);
1999
BISCUIT_ASSERT(rs != x0);
2000
m_buffer.Emit16(0x8002 | (rd.Index() << 7) | (rs.Index() << 2));
2001
}
2002
2003
void Assembler::C_NOP() noexcept {
2004
m_buffer.Emit16(1);
2005
}
2006
2007
void Assembler::C_OR(GPR rd, GPR rs) noexcept {
2008
EmitCompressedRegArith(m_buffer, 0b100011, rd, 0b10, rs, 0b01);
2009
}
2010
2011
void Assembler::C_SD(GPR rs2, uint32_t imm, GPR rs1) noexcept {
2012
BISCUIT_ASSERT(imm <= 248);
2013
BISCUIT_ASSERT(imm % 8 == 0);
2014
2015
EmitCompressedLoad(m_buffer, 0b111, imm, rs1, rs2, 0b00);
2016
}
2017
2018
void Assembler::C_SDSP(GPR rs, uint32_t imm) noexcept {
2019
BISCUIT_ASSERT(imm <= 504);
2020
BISCUIT_ASSERT(imm % 8 == 0);
2021
2022
// clang-format off
2023
const auto new_imm = ((imm & 0x038) << 7) |
2024
((imm & 0x1C0) << 1);
2025
// clang-format on
2026
2027
m_buffer.Emit16(0xE002U | (rs.Index() << 2) | new_imm);
2028
}
2029
2030
void Assembler::C_SLLI(GPR rd, uint32_t shift) noexcept {
2031
BISCUIT_ASSERT(rd != x0);
2032
BISCUIT_ASSERT(IsValidCompressedShiftAmount(shift));
2033
2034
// RV128C encodes a 64-bit shift with an encoding of 0.
2035
if (shift == 64) {
2036
shift = 0;
2037
}
2038
2039
const auto shift_enc = ((shift & 0b11111) << 2) | ((shift & 0b100000) << 7);
2040
m_buffer.Emit16(0x0002U | shift_enc | (rd.Index() << 7));
2041
}
2042
2043
void Assembler::C_SQ(GPR rs2, uint32_t imm, GPR rs1) noexcept {
2044
BISCUIT_ASSERT(imm <= 496);
2045
BISCUIT_ASSERT(imm % 16 == 0);
2046
2047
imm &= 0x1F0;
2048
const auto new_imm = ((imm & 0x100) >> 5) | (imm & 0xF0);
2049
EmitCompressedStore(m_buffer, 0b101, new_imm, rs1, rs2, 0b00);
2050
}
2051
2052
void Assembler::C_SQSP(GPR rs, uint32_t imm) noexcept {
2053
BISCUIT_ASSERT(imm <= 1008);
2054
BISCUIT_ASSERT(imm % 16 == 0);
2055
2056
// clang-format off
2057
const auto new_imm = ((imm & 0x3C0) << 1) |
2058
((imm & 0x030) << 7);
2059
// clang-format on
2060
2061
m_buffer.Emit16(0xA002U | (rs.Index() << 2) | new_imm);
2062
}
2063
2064
void Assembler::C_SRAI(GPR rd, uint32_t shift) noexcept {
2065
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
2066
BISCUIT_ASSERT(IsValidCompressedShiftAmount(shift));
2067
2068
// RV128C encodes a 64-bit shift with an encoding of 0.
2069
if (shift == 64) {
2070
shift = 0;
2071
}
2072
2073
constexpr auto base = 0x8401U;
2074
const auto shift_enc = ((shift & 0b11111) << 2) | ((shift & 0b100000) << 7);
2075
const auto reg = CompressedRegTo3BitEncoding(rd);
2076
2077
m_buffer.Emit16(base | shift_enc | (reg << 7));
2078
}
2079
2080
void Assembler::C_SRLI(GPR rd, uint32_t shift) noexcept {
2081
BISCUIT_ASSERT(IsValid3BitCompressedReg(rd));
2082
BISCUIT_ASSERT(IsValidCompressedShiftAmount(shift));
2083
2084
// RV128C encodes a 64-bit shift with an encoding of 0.
2085
if (shift == 64) {
2086
shift = 0;
2087
}
2088
2089
constexpr auto base = 0x8001U;
2090
const auto shift_enc = ((shift & 0b11111) << 2) | ((shift & 0b100000) << 7);
2091
const auto reg = CompressedRegTo3BitEncoding(rd);
2092
2093
m_buffer.Emit16(base | shift_enc | (reg << 7));
2094
}
2095
2096
void Assembler::C_SUB(GPR rd, GPR rs) noexcept {
2097
EmitCompressedRegArith(m_buffer, 0b100011, rd, 0b00, rs, 0b01);
2098
}
2099
2100
void Assembler::C_SUBW(GPR rd, GPR rs) noexcept {
2101
EmitCompressedRegArith(m_buffer, 0b100111, rd, 0b00, rs, 0b01);
2102
}
2103
2104
void Assembler::C_SW(GPR rs2, uint32_t imm, GPR rs1) noexcept {
2105
BISCUIT_ASSERT(imm <= 124);
2106
BISCUIT_ASSERT(imm % 4 == 0);
2107
2108
imm &= 0x7C;
2109
const auto new_imm = ((imm & 0b0100) << 5) | (imm & 0x78);
2110
EmitCompressedStore(m_buffer, 0b110, new_imm, rs1, rs2, 0b00);
2111
}
2112
2113
void Assembler::C_SWSP(GPR rs, uint32_t imm) noexcept {
2114
BISCUIT_ASSERT(imm <= 252);
2115
BISCUIT_ASSERT(imm % 4 == 0);
2116
2117
// clang-format off
2118
const auto new_imm = ((imm & 0x0C0) << 1) |
2119
((imm & 0x03C) << 7);
2120
// clang-format on
2121
2122
m_buffer.Emit16(0xC002U | (rs.Index() << 2) | new_imm);
2123
}
2124
2125
void Assembler::C_UNDEF() noexcept {
2126
m_buffer.Emit16(0);
2127
}
2128
2129
void Assembler::C_XOR(GPR rd, GPR rs) noexcept {
2130
EmitCompressedRegArith(m_buffer, 0b100011, rd, 0b01, rs, 0b01);
2131
}
2132
2133
// Cache Management Operation Extension Instructions
2134
2135
void Assembler::CBO_CLEAN(GPR rs) noexcept {
2136
EmitRType(m_buffer, 0b0000000, x1, rs, 0b010, x0, 0b0001111);
2137
}
2138
2139
void Assembler::CBO_FLUSH(GPR rs) noexcept {
2140
EmitRType(m_buffer, 0b0000000, x2, rs, 0b010, x0, 0b0001111);
2141
}
2142
2143
void Assembler::CBO_INVAL(GPR rs) noexcept {
2144
EmitRType(m_buffer, 0b0000000, x0, rs, 0b010, x0, 0b0001111);
2145
}
2146
2147
void Assembler::CBO_ZERO(GPR rs) noexcept {
2148
EmitRType(m_buffer, 0b0000000, x4, rs, 0b010, x0, 0b0001111);
2149
}
2150
2151
void Assembler::PREFETCH_I(GPR rs, int32_t offset) noexcept {
2152
// Offset must be able to fit in a 12-bit signed immediate and be
2153
// cleanly divisible by 32 since the bottom 5 bits are encoded as zero.
2154
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
2155
BISCUIT_ASSERT(offset % 32 == 0);
2156
EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b110, x0, 0b0010011);
2157
}
2158
2159
void Assembler::PREFETCH_R(GPR rs, int32_t offset) noexcept {
2160
// Offset must be able to fit in a 12-bit signed immediate and be
2161
// cleanly divisible by 32 since the bottom 5 bits are encoded as zero.
2162
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
2163
BISCUIT_ASSERT(offset % 32 == 0);
2164
EmitIType(m_buffer, static_cast<uint32_t>(offset) | 0b01, rs, 0b110, x0, 0b0010011);
2165
}
2166
2167
void Assembler::PREFETCH_W(GPR rs, int32_t offset) noexcept {
2168
// Offset must be able to fit in a 12-bit signed immediate and be
2169
// cleanly divisible by 32 since the bottom 5 bits are encoded as zero.
2170
BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
2171
BISCUIT_ASSERT(offset % 32 == 0);
2172
EmitIType(m_buffer, static_cast<uint32_t>(offset) | 0b11, rs, 0b110, x0, 0b0010011);
2173
}
2174
2175
// Privileged Instructions
2176
2177
void Assembler::HFENCE_GVMA(GPR rs1, GPR rs2) noexcept {
2178
EmitRType(m_buffer, 0b0110001, rs2, rs1, 0b000, x0, 0b1110011);
2179
}
2180
2181
void Assembler::HFENCE_VVMA(GPR rs1, GPR rs2) noexcept {
2182
EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b000, x0, 0b1110011);
2183
}
2184
2185
void Assembler::HINVAL_GVMA(GPR rs1, GPR rs2) noexcept {
2186
EmitRType(m_buffer, 0b0110011, rs2, rs1, 0b000, x0, 0b1110011);
2187
}
2188
2189
void Assembler::HINVAL_VVMA(GPR rs1, GPR rs2) noexcept {
2190
EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b000, x0, 0b1110011);
2191
}
2192
2193
void Assembler::HLV_B(GPR rd, GPR rs) noexcept {
2194
EmitRType(m_buffer, 0b0110000, x0, rs, 0b100, rd, 0b1110011);
2195
}
2196
2197
void Assembler::HLV_BU(GPR rd, GPR rs) noexcept {
2198
EmitRType(m_buffer, 0b0110000, x1, rs, 0b100, rd, 0b1110011);
2199
}
2200
2201
void Assembler::HLV_D(GPR rd, GPR rs) noexcept {
2202
EmitRType(m_buffer, 0b0110110, x0, rs, 0b100, rd, 0b1110011);
2203
}
2204
2205
void Assembler::HLV_H(GPR rd, GPR rs) noexcept {
2206
EmitRType(m_buffer, 0b0110010, x0, rs, 0b100, rd, 0b1110011);
2207
}
2208
2209
void Assembler::HLV_HU(GPR rd, GPR rs) noexcept {
2210
EmitRType(m_buffer, 0b0110010, x1, rs, 0b100, rd, 0b1110011);
2211
}
2212
2213
void Assembler::HLV_W(GPR rd, GPR rs) noexcept {
2214
EmitRType(m_buffer, 0b0110100, x0, rs, 0b100, rd, 0b1110011);
2215
}
2216
2217
void Assembler::HLV_WU(GPR rd, GPR rs) noexcept {
2218
EmitRType(m_buffer, 0b0110100, x1, rs, 0b100, rd, 0b1110011);
2219
}
2220
2221
void Assembler::HLVX_HU(GPR rd, GPR rs) noexcept {
2222
EmitRType(m_buffer, 0b0110010, x3, rs, 0b100, rd, 0b1110011);
2223
}
2224
2225
void Assembler::HLVX_WU(GPR rd, GPR rs) noexcept {
2226
EmitRType(m_buffer, 0b0110100, x3, rs, 0b100, rd, 0b1110011);
2227
}
2228
2229
void Assembler::HSV_B(GPR rs2, GPR rs1) noexcept {
2230
EmitRType(m_buffer, 0b0110001, rs2, rs1, 0b100, x0, 0b1110011);
2231
}
2232
2233
void Assembler::HSV_D(GPR rs2, GPR rs1) noexcept {
2234
EmitRType(m_buffer, 0b0110111, rs2, rs1, 0b100, x0, 0b1110011);
2235
}
2236
2237
void Assembler::HSV_H(GPR rs2, GPR rs1) noexcept {
2238
EmitRType(m_buffer, 0b0110011, rs2, rs1, 0b100, x0, 0b1110011);
2239
}
2240
2241
void Assembler::HSV_W(GPR rs2, GPR rs1) noexcept {
2242
EmitRType(m_buffer, 0b0110101, rs2, rs1, 0b100, x0, 0b1110011);
2243
}
2244
2245
void Assembler::MRET() noexcept {
2246
m_buffer.Emit32(0x30200073);
2247
}
2248
2249
void Assembler::SFENCE_INVAL_IR() noexcept {
2250
m_buffer.Emit32(0x18100073U);
2251
}
2252
2253
void Assembler::SFENCE_VMA(GPR rs1, GPR rs2) noexcept {
2254
EmitRType(m_buffer, 0b0001001, rs2, rs1, 0b000, x0, 0b1110011);
2255
}
2256
2257
void Assembler::SFENCE_W_INVAL() noexcept {
2258
m_buffer.Emit32(0x18000073U);
2259
}
2260
2261
void Assembler::SINVAL_VMA(GPR rs1, GPR rs2) noexcept {
2262
EmitRType(m_buffer, 0b0001011, rs2, rs1, 0b000, x0, 0b1110011);
2263
}
2264
2265
void Assembler::SRET() noexcept {
2266
m_buffer.Emit32(0x10200073);
2267
}
2268
2269
void Assembler::URET() noexcept {
2270
m_buffer.Emit32(0x00200073);
2271
}
2272
2273
void Assembler::WFI() noexcept {
2274
m_buffer.Emit32(0x10500073);
2275
}
2276
2277
void Assembler::BindToOffset(Label* label, Label::LocationOffset offset) {
2278
BISCUIT_ASSERT(label != nullptr);
2279
BISCUIT_ASSERT(offset >= 0 && offset <= m_buffer.GetCursorOffset());
2280
2281
label->Bind(offset);
2282
ResolveLabelOffsets(label);
2283
label->ClearOffsets();
2284
}
2285
2286
ptrdiff_t Assembler::LinkAndGetOffset(Label* label) {
2287
BISCUIT_ASSERT(label != nullptr);
2288
2289
// If we have a bound label, then it's straightforward to calculate
2290
// the offsets.
2291
if (label->IsBound()) {
2292
const auto cursor_address = m_buffer.GetCursorAddress();
2293
const auto label_offset = m_buffer.GetOffsetAddress(*label->GetLocation());
2294
return static_cast<ptrdiff_t>(label_offset - cursor_address);
2295
}
2296
2297
// If we don't have a bound location, we return an offset of zero.
2298
// While the emitter will emit a bogus branch instruction initially,
2299
// the offset will be patched over once the label has been properly
2300
// bound to a location.
2301
label->AddOffset(m_buffer.GetCursorOffset());
2302
return 0;
2303
}
2304
2305
void Assembler::ResolveLabelOffsets(Label* label) {
2306
// Conditional branch instructions make use of the B-type immediate encoding for offsets.
2307
const auto is_b_type = [](uint32_t instruction) {
2308
return (instruction & 0x7F) == 0b1100011;
2309
};
2310
// JAL makes use of the J-type immediate encoding for offsets.
2311
const auto is_j_type = [](uint32_t instruction) {
2312
return (instruction & 0x7F) == 0b1101111;
2313
};
2314
// C.BEQZ and C.BNEZ make use of this encoding type.
2315
const auto is_cb_type = [](uint32_t instruction) {
2316
const auto op = instruction & 0b11;
2317
const auto funct3 = instruction & 0xE000;
2318
return op == 0b01 && funct3 >= 0xC000;
2319
};
2320
// C.JAL and C.J make use of this encoding type.
2321
const auto is_cj_type = [](uint32_t instruction) {
2322
const auto op = instruction & 0b11;
2323
const auto funct3 = instruction & 0xE000;
2324
return op == 0b01 && (funct3 == 0x2000 || funct3 == 0xA000);
2325
};
2326
// If we know an instruction is a compressed branch, then it's a 16-bit instruction
2327
// Otherwise it's a regular-sized 32-bit instruction.
2328
const auto determine_inst_size = [&](uint32_t instruction) -> size_t {
2329
if (is_cj_type(instruction) || is_cb_type(instruction)) {
2330
return 2;
2331
} else {
2332
return 4;
2333
}
2334
};
2335
2336
const auto label_location = *label->GetLocation();
2337
2338
for (const auto offset : label->m_offsets) {
2339
const auto address = m_buffer.GetOffsetAddress(offset);
2340
auto* const ptr = reinterpret_cast<uint8_t*>(address);
2341
const auto inst_size = determine_inst_size(uint32_t{*ptr} | (uint32_t{*(ptr + 1)} << 8));
2342
2343
uint32_t instruction = 0;
2344
std::memcpy(&instruction, ptr, inst_size);
2345
2346
// Given all branch instructions we need to patch have 0 encoded as
2347
// their branch offset, we don't need to worry about any masking work.
2348
//
2349
// It's enough to verify that the immediate is going to be valid
2350
// and then OR it into the instruction.
2351
2352
const auto encoded_offset = label_location - offset;
2353
2354
if (inst_size == sizeof(uint32_t)) {
2355
if (is_b_type(instruction)) {
2356
BISCUIT_ASSERT(IsValidBTypeImm(encoded_offset));
2357
instruction |= TransformToBTypeImm(static_cast<uint32_t>(encoded_offset));
2358
} else if (is_j_type(instruction)) {
2359
BISCUIT_ASSERT(IsValidJTypeImm(encoded_offset));
2360
instruction |= TransformToJTypeImm(static_cast<uint32_t>(encoded_offset));
2361
}
2362
} else {
2363
if (is_cb_type(instruction)) {
2364
BISCUIT_ASSERT(IsValidCBTypeImm(encoded_offset));
2365
instruction |= TransformToCBTypeImm(static_cast<uint32_t>(encoded_offset));
2366
} else if (is_cj_type(instruction)) {
2367
BISCUIT_ASSERT(IsValidCJTypeImm(encoded_offset));
2368
instruction |= TransformToCJTypeImm(static_cast<uint32_t>(encoded_offset));
2369
}
2370
}
2371
2372
std::memcpy(ptr, &instruction, inst_size);
2373
}
2374
}
2375
2376
} // namespace biscuit
2377
2378