Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/net/bpf_jit.h
26444 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* Common functionality for RV32 and RV64 BPF JIT compilers
4
*
5
* Copyright (c) 2019 Björn Töpel <[email protected]>
6
*
7
*/
8
9
#ifndef _BPF_JIT_H
10
#define _BPF_JIT_H
11
12
#include <linux/bpf.h>
13
#include <linux/filter.h>
14
#include <asm/cacheflush.h>
15
16
static inline bool rvc_enabled(void)
17
{
18
return IS_ENABLED(CONFIG_RISCV_ISA_C);
19
}
20
21
static inline bool rvzba_enabled(void)
22
{
23
return IS_ENABLED(CONFIG_RISCV_ISA_ZBA) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBA);
24
}
25
26
static inline bool rvzbb_enabled(void)
27
{
28
return IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBB);
29
}
30
31
enum {
32
RV_REG_ZERO = 0, /* The constant value 0 */
33
RV_REG_RA = 1, /* Return address */
34
RV_REG_SP = 2, /* Stack pointer */
35
RV_REG_GP = 3, /* Global pointer */
36
RV_REG_TP = 4, /* Thread pointer */
37
RV_REG_T0 = 5, /* Temporaries */
38
RV_REG_T1 = 6,
39
RV_REG_T2 = 7,
40
RV_REG_FP = 8, /* Saved register/frame pointer */
41
RV_REG_S1 = 9, /* Saved register */
42
RV_REG_A0 = 10, /* Function argument/return values */
43
RV_REG_A1 = 11, /* Function arguments */
44
RV_REG_A2 = 12,
45
RV_REG_A3 = 13,
46
RV_REG_A4 = 14,
47
RV_REG_A5 = 15,
48
RV_REG_A6 = 16,
49
RV_REG_A7 = 17,
50
RV_REG_S2 = 18, /* Saved registers */
51
RV_REG_S3 = 19,
52
RV_REG_S4 = 20,
53
RV_REG_S5 = 21,
54
RV_REG_S6 = 22,
55
RV_REG_S7 = 23,
56
RV_REG_S8 = 24,
57
RV_REG_S9 = 25,
58
RV_REG_S10 = 26,
59
RV_REG_S11 = 27,
60
RV_REG_T3 = 28, /* Temporaries */
61
RV_REG_T4 = 29,
62
RV_REG_T5 = 30,
63
RV_REG_T6 = 31,
64
};
65
66
static inline bool is_creg(u8 reg)
67
{
68
return (1 << reg) & (BIT(RV_REG_FP) |
69
BIT(RV_REG_S1) |
70
BIT(RV_REG_A0) |
71
BIT(RV_REG_A1) |
72
BIT(RV_REG_A2) |
73
BIT(RV_REG_A3) |
74
BIT(RV_REG_A4) |
75
BIT(RV_REG_A5));
76
}
77
78
struct rv_jit_context {
79
struct bpf_prog *prog;
80
u16 *insns; /* RV insns */
81
u16 *ro_insns;
82
int ninsns;
83
int prologue_len;
84
int epilogue_offset;
85
int *offset; /* BPF to RV */
86
int nexentries;
87
unsigned long flags;
88
int stack_size;
89
u64 arena_vm_start;
90
u64 user_vm_start;
91
};
92
93
/* Convert from ninsns to bytes. */
94
static inline int ninsns_rvoff(int ninsns)
95
{
96
return ninsns << 1;
97
}
98
99
struct rv_jit_data {
100
struct bpf_binary_header *header;
101
struct bpf_binary_header *ro_header;
102
u8 *image;
103
u8 *ro_image;
104
struct rv_jit_context ctx;
105
};
106
107
static inline void bpf_fill_ill_insns(void *area, unsigned int size)
108
{
109
memset(area, 0, size);
110
}
111
112
static inline void bpf_flush_icache(void *start, void *end)
113
{
114
flush_icache_range((unsigned long)start, (unsigned long)end);
115
}
116
117
/* Emit a 4-byte riscv instruction. */
118
static inline void emit(const u32 insn, struct rv_jit_context *ctx)
119
{
120
if (ctx->insns) {
121
ctx->insns[ctx->ninsns] = insn;
122
ctx->insns[ctx->ninsns + 1] = (insn >> 16);
123
}
124
125
ctx->ninsns += 2;
126
}
127
128
/* Emit a 2-byte riscv compressed instruction. */
129
static inline void emitc(const u16 insn, struct rv_jit_context *ctx)
130
{
131
BUILD_BUG_ON(!rvc_enabled());
132
133
if (ctx->insns)
134
ctx->insns[ctx->ninsns] = insn;
135
136
ctx->ninsns++;
137
}
138
139
static inline int epilogue_offset(struct rv_jit_context *ctx)
140
{
141
int to = ctx->epilogue_offset, from = ctx->ninsns;
142
143
return ninsns_rvoff(to - from);
144
}
145
146
/* Return -1 or inverted cond. */
147
static inline int invert_bpf_cond(u8 cond)
148
{
149
switch (cond) {
150
case BPF_JEQ:
151
return BPF_JNE;
152
case BPF_JGT:
153
return BPF_JLE;
154
case BPF_JLT:
155
return BPF_JGE;
156
case BPF_JGE:
157
return BPF_JLT;
158
case BPF_JLE:
159
return BPF_JGT;
160
case BPF_JNE:
161
return BPF_JEQ;
162
case BPF_JSGT:
163
return BPF_JSLE;
164
case BPF_JSLT:
165
return BPF_JSGE;
166
case BPF_JSGE:
167
return BPF_JSLT;
168
case BPF_JSLE:
169
return BPF_JSGT;
170
}
171
return -1;
172
}
173
174
static inline bool is_6b_int(long val)
175
{
176
return -(1L << 5) <= val && val < (1L << 5);
177
}
178
179
static inline bool is_7b_uint(unsigned long val)
180
{
181
return val < (1UL << 7);
182
}
183
184
static inline bool is_8b_uint(unsigned long val)
185
{
186
return val < (1UL << 8);
187
}
188
189
static inline bool is_9b_uint(unsigned long val)
190
{
191
return val < (1UL << 9);
192
}
193
194
static inline bool is_10b_int(long val)
195
{
196
return -(1L << 9) <= val && val < (1L << 9);
197
}
198
199
static inline bool is_10b_uint(unsigned long val)
200
{
201
return val < (1UL << 10);
202
}
203
204
static inline bool is_12b_int(long val)
205
{
206
return -(1L << 11) <= val && val < (1L << 11);
207
}
208
209
static inline int is_12b_check(int off, int insn)
210
{
211
if (!is_12b_int(off)) {
212
pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n",
213
insn, (int)off);
214
return -1;
215
}
216
return 0;
217
}
218
219
static inline bool is_13b_int(long val)
220
{
221
return -(1L << 12) <= val && val < (1L << 12);
222
}
223
224
static inline bool is_21b_int(long val)
225
{
226
return -(1L << 20) <= val && val < (1L << 20);
227
}
228
229
static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx)
230
{
231
int from, to;
232
233
off++; /* BPF branch is from PC+1, RV is from PC */
234
from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len;
235
to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len;
236
return ninsns_rvoff(to - from);
237
}
238
239
/* Instruction formats. */
240
241
static inline u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd,
242
u8 opcode)
243
{
244
return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
245
(rd << 7) | opcode;
246
}
247
248
static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
249
{
250
return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) |
251
opcode;
252
}
253
254
static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
255
{
256
u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
257
258
return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
259
(imm4_0 << 7) | opcode;
260
}
261
262
static inline u32 rv_b_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
263
{
264
u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4);
265
u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10);
266
267
return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
268
(imm4_1 << 7) | opcode;
269
}
270
271
static inline u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode)
272
{
273
return (imm31_12 << 12) | (rd << 7) | opcode;
274
}
275
276
static inline u32 rv_j_insn(u32 imm20_1, u8 rd, u8 opcode)
277
{
278
u32 imm;
279
280
imm = (imm20_1 & 0x80000) | ((imm20_1 & 0x3ff) << 9) |
281
((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11);
282
283
return (imm << 12) | (rd << 7) | opcode;
284
}
285
286
static inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
287
u8 funct3, u8 rd, u8 opcode)
288
{
289
u8 funct7 = (funct5 << 2) | (aq << 1) | rl;
290
291
return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
292
}
293
294
/* RISC-V compressed instruction formats. */
295
296
static inline u16 rv_cr_insn(u8 funct4, u8 rd, u8 rs2, u8 op)
297
{
298
return (funct4 << 12) | (rd << 7) | (rs2 << 2) | op;
299
}
300
301
static inline u16 rv_ci_insn(u8 funct3, u32 imm6, u8 rd, u8 op)
302
{
303
u32 imm;
304
305
imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2);
306
return (funct3 << 13) | (rd << 7) | op | imm;
307
}
308
309
static inline u16 rv_css_insn(u8 funct3, u32 uimm, u8 rs2, u8 op)
310
{
311
return (funct3 << 13) | (uimm << 7) | (rs2 << 2) | op;
312
}
313
314
static inline u16 rv_ciw_insn(u8 funct3, u32 uimm, u8 rd, u8 op)
315
{
316
return (funct3 << 13) | (uimm << 5) | ((rd & 0x7) << 2) | op;
317
}
318
319
static inline u16 rv_cl_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rd,
320
u8 op)
321
{
322
return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) |
323
(imm_lo << 5) | ((rd & 0x7) << 2) | op;
324
}
325
326
static inline u16 rv_cs_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rs2,
327
u8 op)
328
{
329
return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) |
330
(imm_lo << 5) | ((rs2 & 0x7) << 2) | op;
331
}
332
333
static inline u16 rv_ca_insn(u8 funct6, u8 rd, u8 funct2, u8 rs2, u8 op)
334
{
335
return (funct6 << 10) | ((rd & 0x7) << 7) | (funct2 << 5) |
336
((rs2 & 0x7) << 2) | op;
337
}
338
339
static inline u16 rv_cb_insn(u8 funct3, u32 imm6, u8 funct2, u8 rd, u8 op)
340
{
341
u32 imm;
342
343
imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2);
344
return (funct3 << 13) | (funct2 << 10) | ((rd & 0x7) << 7) | op | imm;
345
}
346
347
/* Instructions shared by both RV32 and RV64. */
348
349
static inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
350
{
351
return rv_i_insn(imm11_0, rs1, 0, rd, 0x13);
352
}
353
354
static inline u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0)
355
{
356
return rv_i_insn(imm11_0, rs1, 7, rd, 0x13);
357
}
358
359
static inline u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0)
360
{
361
return rv_i_insn(imm11_0, rs1, 6, rd, 0x13);
362
}
363
364
static inline u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0)
365
{
366
return rv_i_insn(imm11_0, rs1, 4, rd, 0x13);
367
}
368
369
static inline u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0)
370
{
371
return rv_i_insn(imm11_0, rs1, 1, rd, 0x13);
372
}
373
374
static inline u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0)
375
{
376
return rv_i_insn(imm11_0, rs1, 5, rd, 0x13);
377
}
378
379
static inline u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0)
380
{
381
return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13);
382
}
383
384
static inline u32 rv_lui(u8 rd, u32 imm31_12)
385
{
386
return rv_u_insn(imm31_12, rd, 0x37);
387
}
388
389
static inline u32 rv_auipc(u8 rd, u32 imm31_12)
390
{
391
return rv_u_insn(imm31_12, rd, 0x17);
392
}
393
394
static inline u32 rv_add(u8 rd, u8 rs1, u8 rs2)
395
{
396
return rv_r_insn(0, rs2, rs1, 0, rd, 0x33);
397
}
398
399
static inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2)
400
{
401
return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33);
402
}
403
404
static inline u32 rv_sltu(u8 rd, u8 rs1, u8 rs2)
405
{
406
return rv_r_insn(0, rs2, rs1, 3, rd, 0x33);
407
}
408
409
static inline u32 rv_and(u8 rd, u8 rs1, u8 rs2)
410
{
411
return rv_r_insn(0, rs2, rs1, 7, rd, 0x33);
412
}
413
414
static inline u32 rv_or(u8 rd, u8 rs1, u8 rs2)
415
{
416
return rv_r_insn(0, rs2, rs1, 6, rd, 0x33);
417
}
418
419
static inline u32 rv_xor(u8 rd, u8 rs1, u8 rs2)
420
{
421
return rv_r_insn(0, rs2, rs1, 4, rd, 0x33);
422
}
423
424
static inline u32 rv_sll(u8 rd, u8 rs1, u8 rs2)
425
{
426
return rv_r_insn(0, rs2, rs1, 1, rd, 0x33);
427
}
428
429
static inline u32 rv_srl(u8 rd, u8 rs1, u8 rs2)
430
{
431
return rv_r_insn(0, rs2, rs1, 5, rd, 0x33);
432
}
433
434
static inline u32 rv_sra(u8 rd, u8 rs1, u8 rs2)
435
{
436
return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33);
437
}
438
439
static inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2)
440
{
441
return rv_r_insn(1, rs2, rs1, 0, rd, 0x33);
442
}
443
444
static inline u32 rv_mulhu(u8 rd, u8 rs1, u8 rs2)
445
{
446
return rv_r_insn(1, rs2, rs1, 3, rd, 0x33);
447
}
448
449
static inline u32 rv_div(u8 rd, u8 rs1, u8 rs2)
450
{
451
return rv_r_insn(1, rs2, rs1, 4, rd, 0x33);
452
}
453
454
static inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2)
455
{
456
return rv_r_insn(1, rs2, rs1, 5, rd, 0x33);
457
}
458
459
static inline u32 rv_rem(u8 rd, u8 rs1, u8 rs2)
460
{
461
return rv_r_insn(1, rs2, rs1, 6, rd, 0x33);
462
}
463
464
static inline u32 rv_remu(u8 rd, u8 rs1, u8 rs2)
465
{
466
return rv_r_insn(1, rs2, rs1, 7, rd, 0x33);
467
}
468
469
static inline u32 rv_jal(u8 rd, u32 imm20_1)
470
{
471
return rv_j_insn(imm20_1, rd, 0x6f);
472
}
473
474
static inline u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0)
475
{
476
return rv_i_insn(imm11_0, rs1, 0, rd, 0x67);
477
}
478
479
static inline u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1)
480
{
481
return rv_b_insn(imm12_1, rs2, rs1, 0, 0x63);
482
}
483
484
static inline u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1)
485
{
486
return rv_b_insn(imm12_1, rs2, rs1, 1, 0x63);
487
}
488
489
static inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1)
490
{
491
return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63);
492
}
493
494
static inline u32 rv_bgtu(u8 rs1, u8 rs2, u16 imm12_1)
495
{
496
return rv_bltu(rs2, rs1, imm12_1);
497
}
498
499
static inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1)
500
{
501
return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63);
502
}
503
504
static inline u32 rv_bleu(u8 rs1, u8 rs2, u16 imm12_1)
505
{
506
return rv_bgeu(rs2, rs1, imm12_1);
507
}
508
509
static inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1)
510
{
511
return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63);
512
}
513
514
static inline u32 rv_bgt(u8 rs1, u8 rs2, u16 imm12_1)
515
{
516
return rv_blt(rs2, rs1, imm12_1);
517
}
518
519
static inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1)
520
{
521
return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63);
522
}
523
524
static inline u32 rv_ble(u8 rs1, u8 rs2, u16 imm12_1)
525
{
526
return rv_bge(rs2, rs1, imm12_1);
527
}
528
529
static inline u32 rv_lb(u8 rd, u16 imm11_0, u8 rs1)
530
{
531
return rv_i_insn(imm11_0, rs1, 0, rd, 0x03);
532
}
533
534
static inline u32 rv_lh(u8 rd, u16 imm11_0, u8 rs1)
535
{
536
return rv_i_insn(imm11_0, rs1, 1, rd, 0x03);
537
}
538
539
static inline u32 rv_lw(u8 rd, u16 imm11_0, u8 rs1)
540
{
541
return rv_i_insn(imm11_0, rs1, 2, rd, 0x03);
542
}
543
544
static inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1)
545
{
546
return rv_i_insn(imm11_0, rs1, 4, rd, 0x03);
547
}
548
549
static inline u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1)
550
{
551
return rv_i_insn(imm11_0, rs1, 5, rd, 0x03);
552
}
553
554
static inline u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2)
555
{
556
return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23);
557
}
558
559
static inline u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2)
560
{
561
return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23);
562
}
563
564
static inline u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2)
565
{
566
return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23);
567
}
568
569
static inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
570
{
571
return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
572
}
573
574
static inline u32 rv_amoand_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
575
{
576
return rv_amo_insn(0xc, aq, rl, rs2, rs1, 2, rd, 0x2f);
577
}
578
579
static inline u32 rv_amoor_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
580
{
581
return rv_amo_insn(0x8, aq, rl, rs2, rs1, 2, rd, 0x2f);
582
}
583
584
static inline u32 rv_amoxor_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
585
{
586
return rv_amo_insn(0x4, aq, rl, rs2, rs1, 2, rd, 0x2f);
587
}
588
589
static inline u32 rv_amoswap_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
590
{
591
return rv_amo_insn(0x1, aq, rl, rs2, rs1, 2, rd, 0x2f);
592
}
593
594
static inline u32 rv_lr_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
595
{
596
return rv_amo_insn(0x2, aq, rl, rs2, rs1, 2, rd, 0x2f);
597
}
598
599
static inline u32 rv_sc_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
600
{
601
return rv_amo_insn(0x3, aq, rl, rs2, rs1, 2, rd, 0x2f);
602
}
603
604
static inline u32 rv_fence(u8 pred, u8 succ)
605
{
606
u16 imm11_0 = pred << 4 | succ;
607
608
return rv_i_insn(imm11_0, 0, 0, 0, 0xf);
609
}
610
611
static inline void emit_fence_r_rw(struct rv_jit_context *ctx)
612
{
613
emit(rv_fence(0x2, 0x3), ctx);
614
}
615
616
static inline void emit_fence_rw_w(struct rv_jit_context *ctx)
617
{
618
emit(rv_fence(0x3, 0x1), ctx);
619
}
620
621
static inline void emit_fence_rw_rw(struct rv_jit_context *ctx)
622
{
623
emit(rv_fence(0x3, 0x3), ctx);
624
}
625
626
static inline u32 rv_nop(void)
627
{
628
return rv_i_insn(0, 0, 0, 0, 0x13);
629
}
630
631
/* RVC instructions. */
632
633
static inline u16 rvc_addi4spn(u8 rd, u32 imm10)
634
{
635
u32 imm;
636
637
imm = ((imm10 & 0x30) << 2) | ((imm10 & 0x3c0) >> 4) |
638
((imm10 & 0x4) >> 1) | ((imm10 & 0x8) >> 3);
639
return rv_ciw_insn(0x0, imm, rd, 0x0);
640
}
641
642
static inline u16 rvc_lw(u8 rd, u32 imm7, u8 rs1)
643
{
644
u32 imm_hi, imm_lo;
645
646
imm_hi = (imm7 & 0x38) >> 3;
647
imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6);
648
return rv_cl_insn(0x2, imm_hi, rs1, imm_lo, rd, 0x0);
649
}
650
651
static inline u16 rvc_sw(u8 rs1, u32 imm7, u8 rs2)
652
{
653
u32 imm_hi, imm_lo;
654
655
imm_hi = (imm7 & 0x38) >> 3;
656
imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6);
657
return rv_cs_insn(0x6, imm_hi, rs1, imm_lo, rs2, 0x0);
658
}
659
660
static inline u16 rvc_addi(u8 rd, u32 imm6)
661
{
662
return rv_ci_insn(0, imm6, rd, 0x1);
663
}
664
665
static inline u16 rvc_li(u8 rd, u32 imm6)
666
{
667
return rv_ci_insn(0x2, imm6, rd, 0x1);
668
}
669
670
static inline u16 rvc_addi16sp(u32 imm10)
671
{
672
u32 imm;
673
674
imm = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) | ((imm10 & 0x40) >> 3) |
675
((imm10 & 0x180) >> 6) | ((imm10 & 0x20) >> 5);
676
return rv_ci_insn(0x3, imm, RV_REG_SP, 0x1);
677
}
678
679
static inline u16 rvc_lui(u8 rd, u32 imm6)
680
{
681
return rv_ci_insn(0x3, imm6, rd, 0x1);
682
}
683
684
static inline u16 rvc_srli(u8 rd, u32 imm6)
685
{
686
return rv_cb_insn(0x4, imm6, 0, rd, 0x1);
687
}
688
689
static inline u16 rvc_srai(u8 rd, u32 imm6)
690
{
691
return rv_cb_insn(0x4, imm6, 0x1, rd, 0x1);
692
}
693
694
static inline u16 rvc_andi(u8 rd, u32 imm6)
695
{
696
return rv_cb_insn(0x4, imm6, 0x2, rd, 0x1);
697
}
698
699
static inline u16 rvc_sub(u8 rd, u8 rs)
700
{
701
return rv_ca_insn(0x23, rd, 0, rs, 0x1);
702
}
703
704
static inline u16 rvc_xor(u8 rd, u8 rs)
705
{
706
return rv_ca_insn(0x23, rd, 0x1, rs, 0x1);
707
}
708
709
static inline u16 rvc_or(u8 rd, u8 rs)
710
{
711
return rv_ca_insn(0x23, rd, 0x2, rs, 0x1);
712
}
713
714
static inline u16 rvc_and(u8 rd, u8 rs)
715
{
716
return rv_ca_insn(0x23, rd, 0x3, rs, 0x1);
717
}
718
719
static inline u16 rvc_slli(u8 rd, u32 imm6)
720
{
721
return rv_ci_insn(0, imm6, rd, 0x2);
722
}
723
724
static inline u16 rvc_lwsp(u8 rd, u32 imm8)
725
{
726
u32 imm;
727
728
imm = ((imm8 & 0xc0) >> 6) | (imm8 & 0x3c);
729
return rv_ci_insn(0x2, imm, rd, 0x2);
730
}
731
732
static inline u16 rvc_jr(u8 rs1)
733
{
734
return rv_cr_insn(0x8, rs1, RV_REG_ZERO, 0x2);
735
}
736
737
static inline u16 rvc_mv(u8 rd, u8 rs)
738
{
739
return rv_cr_insn(0x8, rd, rs, 0x2);
740
}
741
742
static inline u16 rvc_jalr(u8 rs1)
743
{
744
return rv_cr_insn(0x9, rs1, RV_REG_ZERO, 0x2);
745
}
746
747
static inline u16 rvc_add(u8 rd, u8 rs)
748
{
749
return rv_cr_insn(0x9, rd, rs, 0x2);
750
}
751
752
static inline u16 rvc_swsp(u32 imm8, u8 rs2)
753
{
754
u32 imm;
755
756
imm = (imm8 & 0x3c) | ((imm8 & 0xc0) >> 6);
757
return rv_css_insn(0x6, imm, rs2, 0x2);
758
}
759
760
/* RVZBA instructions. */
761
static inline u32 rvzba_sh2add(u8 rd, u8 rs1, u8 rs2)
762
{
763
return rv_r_insn(0x10, rs2, rs1, 0x4, rd, 0x33);
764
}
765
766
static inline u32 rvzba_sh3add(u8 rd, u8 rs1, u8 rs2)
767
{
768
return rv_r_insn(0x10, rs2, rs1, 0x6, rd, 0x33);
769
}
770
771
/* RVZBB instructions. */
772
static inline u32 rvzbb_sextb(u8 rd, u8 rs1)
773
{
774
return rv_i_insn(0x604, rs1, 1, rd, 0x13);
775
}
776
777
static inline u32 rvzbb_sexth(u8 rd, u8 rs1)
778
{
779
return rv_i_insn(0x605, rs1, 1, rd, 0x13);
780
}
781
782
static inline u32 rvzbb_zexth(u8 rd, u8 rs)
783
{
784
if (IS_ENABLED(CONFIG_64BIT))
785
return rv_i_insn(0x80, rs, 4, rd, 0x3b);
786
787
return rv_i_insn(0x80, rs, 4, rd, 0x33);
788
}
789
790
static inline u32 rvzbb_rev8(u8 rd, u8 rs)
791
{
792
if (IS_ENABLED(CONFIG_64BIT))
793
return rv_i_insn(0x6b8, rs, 5, rd, 0x13);
794
795
return rv_i_insn(0x698, rs, 5, rd, 0x13);
796
}
797
798
/*
799
* RV64-only instructions.
800
*
801
* These instructions are not available on RV32. Wrap them below a #if to
802
* ensure that the RV32 JIT doesn't emit any of these instructions.
803
*/
804
805
#if __riscv_xlen == 64
806
807
static inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0)
808
{
809
return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b);
810
}
811
812
static inline u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0)
813
{
814
return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b);
815
}
816
817
static inline u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0)
818
{
819
return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b);
820
}
821
822
static inline u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0)
823
{
824
return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b);
825
}
826
827
static inline u32 rv_addw(u8 rd, u8 rs1, u8 rs2)
828
{
829
return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b);
830
}
831
832
static inline u32 rv_subw(u8 rd, u8 rs1, u8 rs2)
833
{
834
return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b);
835
}
836
837
static inline u32 rv_sllw(u8 rd, u8 rs1, u8 rs2)
838
{
839
return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b);
840
}
841
842
static inline u32 rv_srlw(u8 rd, u8 rs1, u8 rs2)
843
{
844
return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b);
845
}
846
847
static inline u32 rv_sraw(u8 rd, u8 rs1, u8 rs2)
848
{
849
return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b);
850
}
851
852
static inline u32 rv_mulw(u8 rd, u8 rs1, u8 rs2)
853
{
854
return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b);
855
}
856
857
static inline u32 rv_divw(u8 rd, u8 rs1, u8 rs2)
858
{
859
return rv_r_insn(1, rs2, rs1, 4, rd, 0x3b);
860
}
861
862
static inline u32 rv_divuw(u8 rd, u8 rs1, u8 rs2)
863
{
864
return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b);
865
}
866
867
static inline u32 rv_remw(u8 rd, u8 rs1, u8 rs2)
868
{
869
return rv_r_insn(1, rs2, rs1, 6, rd, 0x3b);
870
}
871
872
static inline u32 rv_remuw(u8 rd, u8 rs1, u8 rs2)
873
{
874
return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b);
875
}
876
877
static inline u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1)
878
{
879
return rv_i_insn(imm11_0, rs1, 3, rd, 0x03);
880
}
881
882
static inline u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1)
883
{
884
return rv_i_insn(imm11_0, rs1, 6, rd, 0x03);
885
}
886
887
static inline u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2)
888
{
889
return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23);
890
}
891
892
static inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
893
{
894
return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
895
}
896
897
static inline u32 rv_amoand_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
898
{
899
return rv_amo_insn(0xc, aq, rl, rs2, rs1, 3, rd, 0x2f);
900
}
901
902
static inline u32 rv_amoor_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
903
{
904
return rv_amo_insn(0x8, aq, rl, rs2, rs1, 3, rd, 0x2f);
905
}
906
907
static inline u32 rv_amoxor_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
908
{
909
return rv_amo_insn(0x4, aq, rl, rs2, rs1, 3, rd, 0x2f);
910
}
911
912
static inline u32 rv_amoswap_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
913
{
914
return rv_amo_insn(0x1, aq, rl, rs2, rs1, 3, rd, 0x2f);
915
}
916
917
static inline u32 rv_lr_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
918
{
919
return rv_amo_insn(0x2, aq, rl, rs2, rs1, 3, rd, 0x2f);
920
}
921
922
static inline u32 rv_sc_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
923
{
924
return rv_amo_insn(0x3, aq, rl, rs2, rs1, 3, rd, 0x2f);
925
}
926
927
/* RV64-only RVC instructions. */
928
929
static inline u16 rvc_ld(u8 rd, u32 imm8, u8 rs1)
930
{
931
u32 imm_hi, imm_lo;
932
933
imm_hi = (imm8 & 0x38) >> 3;
934
imm_lo = (imm8 & 0xc0) >> 6;
935
return rv_cl_insn(0x3, imm_hi, rs1, imm_lo, rd, 0x0);
936
}
937
938
static inline u16 rvc_sd(u8 rs1, u32 imm8, u8 rs2)
939
{
940
u32 imm_hi, imm_lo;
941
942
imm_hi = (imm8 & 0x38) >> 3;
943
imm_lo = (imm8 & 0xc0) >> 6;
944
return rv_cs_insn(0x7, imm_hi, rs1, imm_lo, rs2, 0x0);
945
}
946
947
static inline u16 rvc_subw(u8 rd, u8 rs)
948
{
949
return rv_ca_insn(0x27, rd, 0, rs, 0x1);
950
}
951
952
static inline u16 rvc_addiw(u8 rd, u32 imm6)
953
{
954
return rv_ci_insn(0x1, imm6, rd, 0x1);
955
}
956
957
static inline u16 rvc_ldsp(u8 rd, u32 imm9)
958
{
959
u32 imm;
960
961
imm = ((imm9 & 0x1c0) >> 6) | (imm9 & 0x38);
962
return rv_ci_insn(0x3, imm, rd, 0x2);
963
}
964
965
static inline u16 rvc_sdsp(u32 imm9, u8 rs2)
966
{
967
u32 imm;
968
969
imm = (imm9 & 0x38) | ((imm9 & 0x1c0) >> 6);
970
return rv_css_insn(0x7, imm, rs2, 0x2);
971
}
972
973
/* RV64-only ZBA instructions. */
974
975
static inline u32 rvzba_zextw(u8 rd, u8 rs1)
976
{
977
/* add.uw rd, rs1, ZERO */
978
return rv_r_insn(0x04, RV_REG_ZERO, rs1, 0, rd, 0x3b);
979
}
980
981
#endif /* __riscv_xlen == 64 */
982
983
/* Helper functions that emit RVC instructions when possible. */
984
985
static inline void emit_jalr(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
986
{
987
if (rvc_enabled() && rd == RV_REG_RA && rs && !imm)
988
emitc(rvc_jalr(rs), ctx);
989
else if (rvc_enabled() && !rd && rs && !imm)
990
emitc(rvc_jr(rs), ctx);
991
else
992
emit(rv_jalr(rd, rs, imm), ctx);
993
}
994
995
static inline void emit_mv(u8 rd, u8 rs, struct rv_jit_context *ctx)
996
{
997
if (rvc_enabled() && rd && rs)
998
emitc(rvc_mv(rd, rs), ctx);
999
else
1000
emit(rv_addi(rd, rs, 0), ctx);
1001
}
1002
1003
static inline void emit_add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1004
{
1005
if (rvc_enabled() && rd && rd == rs1 && rs2)
1006
emitc(rvc_add(rd, rs2), ctx);
1007
else
1008
emit(rv_add(rd, rs1, rs2), ctx);
1009
}
1010
1011
static inline void emit_addi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1012
{
1013
if (rvc_enabled() && rd == RV_REG_SP && rd == rs && is_10b_int(imm) && imm && !(imm & 0xf))
1014
emitc(rvc_addi16sp(imm), ctx);
1015
else if (rvc_enabled() && is_creg(rd) && rs == RV_REG_SP && is_10b_uint(imm) &&
1016
!(imm & 0x3) && imm)
1017
emitc(rvc_addi4spn(rd, imm), ctx);
1018
else if (rvc_enabled() && rd && rd == rs && imm && is_6b_int(imm))
1019
emitc(rvc_addi(rd, imm), ctx);
1020
else
1021
emit(rv_addi(rd, rs, imm), ctx);
1022
}
1023
1024
static inline void emit_li(u8 rd, s32 imm, struct rv_jit_context *ctx)
1025
{
1026
if (rvc_enabled() && rd && is_6b_int(imm))
1027
emitc(rvc_li(rd, imm), ctx);
1028
else
1029
emit(rv_addi(rd, RV_REG_ZERO, imm), ctx);
1030
}
1031
1032
static inline void emit_lui(u8 rd, s32 imm, struct rv_jit_context *ctx)
1033
{
1034
if (rvc_enabled() && rd && rd != RV_REG_SP && is_6b_int(imm) && imm)
1035
emitc(rvc_lui(rd, imm), ctx);
1036
else
1037
emit(rv_lui(rd, imm), ctx);
1038
}
1039
1040
static inline void emit_slli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1041
{
1042
if (rvc_enabled() && rd && rd == rs && imm && (u32)imm < __riscv_xlen)
1043
emitc(rvc_slli(rd, imm), ctx);
1044
else
1045
emit(rv_slli(rd, rs, imm), ctx);
1046
}
1047
1048
static inline void emit_andi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1049
{
1050
if (rvc_enabled() && is_creg(rd) && rd == rs && is_6b_int(imm))
1051
emitc(rvc_andi(rd, imm), ctx);
1052
else
1053
emit(rv_andi(rd, rs, imm), ctx);
1054
}
1055
1056
static inline void emit_srli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1057
{
1058
if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen)
1059
emitc(rvc_srli(rd, imm), ctx);
1060
else
1061
emit(rv_srli(rd, rs, imm), ctx);
1062
}
1063
1064
static inline void emit_srai(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1065
{
1066
if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen)
1067
emitc(rvc_srai(rd, imm), ctx);
1068
else
1069
emit(rv_srai(rd, rs, imm), ctx);
1070
}
1071
1072
static inline void emit_sub(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1073
{
1074
if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
1075
emitc(rvc_sub(rd, rs2), ctx);
1076
else
1077
emit(rv_sub(rd, rs1, rs2), ctx);
1078
}
1079
1080
static inline void emit_or(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1081
{
1082
if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
1083
emitc(rvc_or(rd, rs2), ctx);
1084
else
1085
emit(rv_or(rd, rs1, rs2), ctx);
1086
}
1087
1088
static inline void emit_and(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1089
{
1090
if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
1091
emitc(rvc_and(rd, rs2), ctx);
1092
else
1093
emit(rv_and(rd, rs1, rs2), ctx);
1094
}
1095
1096
static inline void emit_xor(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1097
{
1098
if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
1099
emitc(rvc_xor(rd, rs2), ctx);
1100
else
1101
emit(rv_xor(rd, rs1, rs2), ctx);
1102
}
1103
1104
static inline void emit_lw(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx)
1105
{
1106
if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_8b_uint(off) && !(off & 0x3))
1107
emitc(rvc_lwsp(rd, off), ctx);
1108
else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_7b_uint(off) && !(off & 0x3))
1109
emitc(rvc_lw(rd, off, rs1), ctx);
1110
else
1111
emit(rv_lw(rd, off, rs1), ctx);
1112
}
1113
1114
static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
1115
{
1116
if (rvc_enabled() && rs1 == RV_REG_SP && is_8b_uint(off) && !(off & 0x3))
1117
emitc(rvc_swsp(off, rs2), ctx);
1118
else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_7b_uint(off) && !(off & 0x3))
1119
emitc(rvc_sw(rs1, off, rs2), ctx);
1120
else
1121
emit(rv_sw(rs1, off, rs2), ctx);
1122
}
1123
1124
static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1125
{
1126
if (rvzba_enabled()) {
1127
emit(rvzba_sh2add(rd, rs1, rs2), ctx);
1128
return;
1129
}
1130
1131
emit_slli(rd, rs1, 2, ctx);
1132
emit_add(rd, rd, rs2, ctx);
1133
}
1134
1135
static inline void emit_sh3add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1136
{
1137
if (rvzba_enabled()) {
1138
emit(rvzba_sh3add(rd, rs1, rs2), ctx);
1139
return;
1140
}
1141
1142
emit_slli(rd, rs1, 3, ctx);
1143
emit_add(rd, rd, rs2, ctx);
1144
}
1145
1146
/* RV64-only helper functions. */
1147
#if __riscv_xlen == 64
1148
1149
static inline void emit_addiw(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
1150
{
1151
if (rvc_enabled() && rd && rd == rs && is_6b_int(imm))
1152
emitc(rvc_addiw(rd, imm), ctx);
1153
else
1154
emit(rv_addiw(rd, rs, imm), ctx);
1155
}
1156
1157
static inline void emit_ld(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx)
1158
{
1159
if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_9b_uint(off) && !(off & 0x7))
1160
emitc(rvc_ldsp(rd, off), ctx);
1161
else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_8b_uint(off) && !(off & 0x7))
1162
emitc(rvc_ld(rd, off, rs1), ctx);
1163
else
1164
emit(rv_ld(rd, off, rs1), ctx);
1165
}
1166
1167
static inline void emit_sd(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
1168
{
1169
if (rvc_enabled() && rs1 == RV_REG_SP && is_9b_uint(off) && !(off & 0x7))
1170
emitc(rvc_sdsp(off, rs2), ctx);
1171
else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_8b_uint(off) && !(off & 0x7))
1172
emitc(rvc_sd(rs1, off, rs2), ctx);
1173
else
1174
emit(rv_sd(rs1, off, rs2), ctx);
1175
}
1176
1177
static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1178
{
1179
if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
1180
emitc(rvc_subw(rd, rs2), ctx);
1181
else
1182
emit(rv_subw(rd, rs1, rs2), ctx);
1183
}
1184
1185
static inline void emit_sextb(u8 rd, u8 rs, struct rv_jit_context *ctx)
1186
{
1187
if (rvzbb_enabled()) {
1188
emit(rvzbb_sextb(rd, rs), ctx);
1189
return;
1190
}
1191
1192
emit_slli(rd, rs, 56, ctx);
1193
emit_srai(rd, rd, 56, ctx);
1194
}
1195
1196
static inline void emit_sexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
1197
{
1198
if (rvzbb_enabled()) {
1199
emit(rvzbb_sexth(rd, rs), ctx);
1200
return;
1201
}
1202
1203
emit_slli(rd, rs, 48, ctx);
1204
emit_srai(rd, rd, 48, ctx);
1205
}
1206
1207
static inline void emit_sextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
1208
{
1209
emit_addiw(rd, rs, 0, ctx);
1210
}
1211
1212
static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
1213
{
1214
if (rvzbb_enabled()) {
1215
emit(rvzbb_zexth(rd, rs), ctx);
1216
return;
1217
}
1218
1219
emit_slli(rd, rs, 48, ctx);
1220
emit_srli(rd, rd, 48, ctx);
1221
}
1222
1223
static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
1224
{
1225
if (rvzba_enabled()) {
1226
emit(rvzba_zextw(rd, rs), ctx);
1227
return;
1228
}
1229
1230
emit_slli(rd, rs, 32, ctx);
1231
emit_srli(rd, rd, 32, ctx);
1232
}
1233
1234
static inline void emit_bswap(u8 rd, s32 imm, struct rv_jit_context *ctx)
1235
{
1236
if (rvzbb_enabled()) {
1237
int bits = 64 - imm;
1238
1239
emit(rvzbb_rev8(rd, rd), ctx);
1240
if (bits)
1241
emit_srli(rd, rd, bits, ctx);
1242
return;
1243
}
1244
1245
emit_li(RV_REG_T2, 0, ctx);
1246
1247
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1248
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1249
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1250
emit_srli(rd, rd, 8, ctx);
1251
if (imm == 16)
1252
goto out_be;
1253
1254
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1255
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1256
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1257
emit_srli(rd, rd, 8, ctx);
1258
1259
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1260
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1261
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1262
emit_srli(rd, rd, 8, ctx);
1263
if (imm == 32)
1264
goto out_be;
1265
1266
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1267
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1268
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1269
emit_srli(rd, rd, 8, ctx);
1270
1271
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1272
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1273
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1274
emit_srli(rd, rd, 8, ctx);
1275
1276
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1277
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1278
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1279
emit_srli(rd, rd, 8, ctx);
1280
1281
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1282
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1283
emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
1284
emit_srli(rd, rd, 8, ctx);
1285
out_be:
1286
emit_andi(RV_REG_T1, rd, 0xff, ctx);
1287
emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
1288
1289
emit_mv(rd, RV_REG_T2, ctx);
1290
}
1291
1292
#endif /* __riscv_xlen == 64 */
1293
1294
void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog);
1295
void bpf_jit_build_epilogue(struct rv_jit_context *ctx);
1296
1297
int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
1298
bool extra_pass);
1299
1300
#endif /* _BPF_JIT_H */
1301
1302