18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Common functionality for RV32 and RV64 BPF JIT compilers 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2019 Björn Töpel <bjorn.topel@gmail.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _BPF_JIT_H 108c2ecf20Sopenharmony_ci#define _BPF_JIT_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/bpf.h> 138c2ecf20Sopenharmony_ci#include <linux/filter.h> 148c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic inline bool rvc_enabled(void) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci return IS_ENABLED(CONFIG_RISCV_ISA_C); 198c2ecf20Sopenharmony_ci} 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cienum { 228c2ecf20Sopenharmony_ci RV_REG_ZERO = 0, /* The constant value 0 */ 238c2ecf20Sopenharmony_ci RV_REG_RA = 1, /* Return address */ 248c2ecf20Sopenharmony_ci RV_REG_SP = 2, /* Stack pointer */ 258c2ecf20Sopenharmony_ci RV_REG_GP = 3, /* Global pointer */ 268c2ecf20Sopenharmony_ci RV_REG_TP = 4, /* Thread pointer */ 278c2ecf20Sopenharmony_ci RV_REG_T0 = 5, /* Temporaries */ 288c2ecf20Sopenharmony_ci RV_REG_T1 = 6, 298c2ecf20Sopenharmony_ci RV_REG_T2 = 7, 308c2ecf20Sopenharmony_ci RV_REG_FP = 8, /* Saved register/frame pointer */ 318c2ecf20Sopenharmony_ci RV_REG_S1 = 9, /* Saved register */ 328c2ecf20Sopenharmony_ci RV_REG_A0 = 10, /* Function argument/return values */ 338c2ecf20Sopenharmony_ci RV_REG_A1 = 11, /* Function arguments */ 348c2ecf20Sopenharmony_ci RV_REG_A2 = 12, 358c2ecf20Sopenharmony_ci RV_REG_A3 = 13, 368c2ecf20Sopenharmony_ci RV_REG_A4 = 14, 378c2ecf20Sopenharmony_ci RV_REG_A5 = 15, 388c2ecf20Sopenharmony_ci RV_REG_A6 = 16, 398c2ecf20Sopenharmony_ci RV_REG_A7 = 17, 408c2ecf20Sopenharmony_ci RV_REG_S2 = 18, /* Saved registers */ 418c2ecf20Sopenharmony_ci RV_REG_S3 = 19, 428c2ecf20Sopenharmony_ci RV_REG_S4 = 20, 438c2ecf20Sopenharmony_ci RV_REG_S5 = 21, 448c2ecf20Sopenharmony_ci RV_REG_S6 = 22, 458c2ecf20Sopenharmony_ci RV_REG_S7 = 23, 468c2ecf20Sopenharmony_ci RV_REG_S8 = 24, 478c2ecf20Sopenharmony_ci RV_REG_S9 = 25, 488c2ecf20Sopenharmony_ci RV_REG_S10 = 26, 498c2ecf20Sopenharmony_ci RV_REG_S11 = 27, 508c2ecf20Sopenharmony_ci RV_REG_T3 = 28, /* Temporaries */ 518c2ecf20Sopenharmony_ci RV_REG_T4 = 29, 528c2ecf20Sopenharmony_ci RV_REG_T5 = 30, 538c2ecf20Sopenharmony_ci RV_REG_T6 = 31, 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic inline bool is_creg(u8 reg) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci return (1 << reg) & (BIT(RV_REG_FP) | 598c2ecf20Sopenharmony_ci BIT(RV_REG_S1) | 608c2ecf20Sopenharmony_ci BIT(RV_REG_A0) | 618c2ecf20Sopenharmony_ci BIT(RV_REG_A1) | 628c2ecf20Sopenharmony_ci BIT(RV_REG_A2) | 638c2ecf20Sopenharmony_ci BIT(RV_REG_A3) | 648c2ecf20Sopenharmony_ci BIT(RV_REG_A4) | 658c2ecf20Sopenharmony_ci BIT(RV_REG_A5)); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistruct rv_jit_context { 698c2ecf20Sopenharmony_ci struct bpf_prog *prog; 708c2ecf20Sopenharmony_ci u16 *insns; /* RV insns */ 718c2ecf20Sopenharmony_ci int ninsns; 728c2ecf20Sopenharmony_ci int prologue_len; 738c2ecf20Sopenharmony_ci int epilogue_offset; 748c2ecf20Sopenharmony_ci int *offset; /* BPF to RV */ 758c2ecf20Sopenharmony_ci unsigned long flags; 768c2ecf20Sopenharmony_ci int stack_size; 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Convert from ninsns to bytes. */ 808c2ecf20Sopenharmony_cistatic inline int ninsns_rvoff(int ninsns) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci return ninsns << 1; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct rv_jit_data { 868c2ecf20Sopenharmony_ci struct bpf_binary_header *header; 878c2ecf20Sopenharmony_ci u8 *image; 888c2ecf20Sopenharmony_ci struct rv_jit_context ctx; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic inline void bpf_fill_ill_insns(void *area, unsigned int size) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci memset(area, 0, size); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void bpf_flush_icache(void *start, void *end) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci flush_icache_range((unsigned long)start, (unsigned long)end); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* Emit a 4-byte riscv instruction. */ 1028c2ecf20Sopenharmony_cistatic inline void emit(const u32 insn, struct rv_jit_context *ctx) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (ctx->insns) { 1058c2ecf20Sopenharmony_ci ctx->insns[ctx->ninsns] = insn; 1068c2ecf20Sopenharmony_ci ctx->insns[ctx->ninsns + 1] = (insn >> 16); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci ctx->ninsns += 2; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* Emit a 2-byte riscv compressed instruction. */ 1138c2ecf20Sopenharmony_cistatic inline void emitc(const u16 insn, struct rv_jit_context *ctx) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci BUILD_BUG_ON(!rvc_enabled()); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (ctx->insns) 1188c2ecf20Sopenharmony_ci ctx->insns[ctx->ninsns] = insn; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci ctx->ninsns++; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline int epilogue_offset(struct rv_jit_context *ctx) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci int to = ctx->epilogue_offset, from = ctx->ninsns; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci return ninsns_rvoff(to - from); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* Return -1 or inverted cond. */ 1318c2ecf20Sopenharmony_cistatic inline int invert_bpf_cond(u8 cond) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci switch (cond) { 1348c2ecf20Sopenharmony_ci case BPF_JEQ: 1358c2ecf20Sopenharmony_ci return BPF_JNE; 1368c2ecf20Sopenharmony_ci case BPF_JGT: 1378c2ecf20Sopenharmony_ci return BPF_JLE; 1388c2ecf20Sopenharmony_ci case BPF_JLT: 1398c2ecf20Sopenharmony_ci return BPF_JGE; 1408c2ecf20Sopenharmony_ci case BPF_JGE: 1418c2ecf20Sopenharmony_ci return BPF_JLT; 1428c2ecf20Sopenharmony_ci case BPF_JLE: 1438c2ecf20Sopenharmony_ci return BPF_JGT; 1448c2ecf20Sopenharmony_ci case BPF_JNE: 1458c2ecf20Sopenharmony_ci return BPF_JEQ; 1468c2ecf20Sopenharmony_ci case BPF_JSGT: 1478c2ecf20Sopenharmony_ci return BPF_JSLE; 1488c2ecf20Sopenharmony_ci case BPF_JSLT: 1498c2ecf20Sopenharmony_ci return BPF_JSGE; 1508c2ecf20Sopenharmony_ci case BPF_JSGE: 1518c2ecf20Sopenharmony_ci return BPF_JSLT; 1528c2ecf20Sopenharmony_ci case BPF_JSLE: 1538c2ecf20Sopenharmony_ci return BPF_JSGT; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci return -1; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic inline bool is_6b_int(long val) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci return -(1L << 5) <= val && val < (1L << 5); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline bool is_7b_uint(unsigned long val) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return val < (1UL << 7); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic inline bool is_8b_uint(unsigned long val) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci return val < (1UL << 8); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic inline bool is_9b_uint(unsigned long val) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci return val < (1UL << 9); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic inline bool is_10b_int(long val) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci return -(1L << 9) <= val && val < (1L << 9); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic inline bool is_10b_uint(unsigned long val) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci return val < (1UL << 10); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic inline bool is_12b_int(long val) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci return -(1L << 11) <= val && val < (1L << 11); 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic inline int is_12b_check(int off, int insn) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci if (!is_12b_int(off)) { 1968c2ecf20Sopenharmony_ci pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n", 1978c2ecf20Sopenharmony_ci insn, (int)off); 1988c2ecf20Sopenharmony_ci return -1; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic inline bool is_13b_int(long val) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci return -(1L << 12) <= val && val < (1L << 12); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline bool is_21b_int(long val) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci return -(1L << 20) <= val && val < (1L << 20); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic inline int rv_offset(int insn, int off, struct rv_jit_context *ctx) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci int from, to; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci off++; /* BPF branch is from PC+1, RV is from PC */ 2188c2ecf20Sopenharmony_ci from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len; 2198c2ecf20Sopenharmony_ci to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len; 2208c2ecf20Sopenharmony_ci return ninsns_rvoff(to - from); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* Instruction formats. */ 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic inline u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd, 2268c2ecf20Sopenharmony_ci u8 opcode) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 2298c2ecf20Sopenharmony_ci (rd << 7) | opcode; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | 2358c2ecf20Sopenharmony_ci opcode; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 2438c2ecf20Sopenharmony_ci (imm4_0 << 7) | opcode; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic inline u32 rv_b_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4); 2498c2ecf20Sopenharmony_ci u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 2528c2ecf20Sopenharmony_ci (imm4_1 << 7) | opcode; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic inline u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci return (imm31_12 << 12) | (rd << 7) | opcode; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic inline u32 rv_j_insn(u32 imm20_1, u8 rd, u8 opcode) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci u32 imm; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci imm = (imm20_1 & 0x80000) | ((imm20_1 & 0x3ff) << 9) | 2658c2ecf20Sopenharmony_ci ((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return (imm << 12) | (rd << 7) | opcode; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1, 2718c2ecf20Sopenharmony_ci u8 funct3, u8 rd, u8 opcode) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci u8 funct7 = (funct5 << 2) | (aq << 1) | rl; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode); 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci/* RISC-V compressed instruction formats. */ 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic inline u16 rv_cr_insn(u8 funct4, u8 rd, u8 rs2, u8 op) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci return (funct4 << 12) | (rd << 7) | (rs2 << 2) | op; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic inline u16 rv_ci_insn(u8 funct3, u32 imm6, u8 rd, u8 op) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci u32 imm; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2); 2908c2ecf20Sopenharmony_ci return (funct3 << 13) | (rd << 7) | op | imm; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic inline u16 rv_css_insn(u8 funct3, u32 uimm, u8 rs2, u8 op) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci return (funct3 << 13) | (uimm << 7) | (rs2 << 2) | op; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic inline u16 rv_ciw_insn(u8 funct3, u32 uimm, u8 rd, u8 op) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci return (funct3 << 13) | (uimm << 5) | ((rd & 0x7) << 2) | op; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic inline u16 rv_cl_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rd, 3048c2ecf20Sopenharmony_ci u8 op) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) | 3078c2ecf20Sopenharmony_ci (imm_lo << 5) | ((rd & 0x7) << 2) | op; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic inline u16 rv_cs_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rs2, 3118c2ecf20Sopenharmony_ci u8 op) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) | 3148c2ecf20Sopenharmony_ci (imm_lo << 5) | ((rs2 & 0x7) << 2) | op; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic inline u16 rv_ca_insn(u8 funct6, u8 rd, u8 funct2, u8 rs2, u8 op) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci return (funct6 << 10) | ((rd & 0x7) << 7) | (funct2 << 5) | 3208c2ecf20Sopenharmony_ci ((rs2 & 0x7) << 2) | op; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic inline u16 rv_cb_insn(u8 funct3, u32 imm6, u8 funct2, u8 rd, u8 op) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci u32 imm; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2); 3288c2ecf20Sopenharmony_ci return (funct3 << 13) | (funct2 << 10) | ((rd & 0x7) << 7) | op | imm; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/* Instructions shared by both RV32 and RV64. */ 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x13); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic inline u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 7, rd, 0x13); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic inline u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 6, rd, 0x13); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic inline u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 4, rd, 0x13); 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic inline u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 1, rd, 0x13); 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic inline u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x13); 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic inline u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic inline u32 rv_lui(u8 rd, u32 imm31_12) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci return rv_u_insn(imm31_12, rd, 0x37); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic inline u32 rv_auipc(u8 rd, u32 imm31_12) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci return rv_u_insn(imm31_12, rd, 0x17); 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic inline u32 rv_add(u8 rd, u8 rs1, u8 rs2) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 0, rd, 0x33); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic inline u32 rv_sltu(u8 rd, u8 rs1, u8 rs2) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 3, rd, 0x33); 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic inline u32 rv_and(u8 rd, u8 rs1, u8 rs2) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 7, rd, 0x33); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic inline u32 rv_or(u8 rd, u8 rs1, u8 rs2) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 6, rd, 0x33); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic inline u32 rv_xor(u8 rd, u8 rs1, u8 rs2) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 4, rd, 0x33); 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic inline u32 rv_sll(u8 rd, u8 rs1, u8 rs2) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 1, rd, 0x33); 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic inline u32 rv_srl(u8 rd, u8 rs1, u8 rs2) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 5, rd, 0x33); 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic inline u32 rv_sra(u8 rd, u8 rs1, u8 rs2) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33); 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 0, rd, 0x33); 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic inline u32 rv_mulhu(u8 rd, u8 rs1, u8 rs2) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 3, rd, 0x33); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 5, rd, 0x33); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic inline u32 rv_remu(u8 rd, u8 rs1, u8 rs2) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 7, rd, 0x33); 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic inline u32 rv_jal(u8 rd, u32 imm20_1) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci return rv_j_insn(imm20_1, rd, 0x6f); 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic inline u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x67); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic inline u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 0, 0x63); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic inline u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 1, 0x63); 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63); 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic inline u32 rv_bgtu(u8 rs1, u8 rs2, u16 imm12_1) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci return rv_bltu(rs2, rs1, imm12_1); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63); 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic inline u32 rv_bleu(u8 rs1, u8 rs2, u16 imm12_1) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci return rv_bgeu(rs2, rs1, imm12_1); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63); 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic inline u32 rv_bgt(u8 rs1, u8 rs2, u16 imm12_1) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci return rv_blt(rs2, rs1, imm12_1); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic inline u32 rv_ble(u8 rs1, u8 rs2, u16 imm12_1) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci return rv_bge(rs2, rs1, imm12_1); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic inline u32 rv_lw(u8 rd, u16 imm11_0, u8 rs1) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 2, rd, 0x03); 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cistatic inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1) 5098c2ecf20Sopenharmony_ci{ 5108c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 4, rd, 0x03); 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic inline u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x03); 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic inline u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic inline u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic inline u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f); 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci/* RVC instrutions. */ 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_cistatic inline u16 rvc_addi4spn(u8 rd, u32 imm10) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci u32 imm; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci imm = ((imm10 & 0x30) << 2) | ((imm10 & 0x3c0) >> 4) | 5458c2ecf20Sopenharmony_ci ((imm10 & 0x4) >> 1) | ((imm10 & 0x8) >> 3); 5468c2ecf20Sopenharmony_ci return rv_ciw_insn(0x0, imm, rd, 0x0); 5478c2ecf20Sopenharmony_ci} 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic inline u16 rvc_lw(u8 rd, u32 imm7, u8 rs1) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci u32 imm_hi, imm_lo; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci imm_hi = (imm7 & 0x38) >> 3; 5548c2ecf20Sopenharmony_ci imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6); 5558c2ecf20Sopenharmony_ci return rv_cl_insn(0x2, imm_hi, rs1, imm_lo, rd, 0x0); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic inline u16 rvc_sw(u8 rs1, u32 imm7, u8 rs2) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci u32 imm_hi, imm_lo; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci imm_hi = (imm7 & 0x38) >> 3; 5638c2ecf20Sopenharmony_ci imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6); 5648c2ecf20Sopenharmony_ci return rv_cs_insn(0x6, imm_hi, rs1, imm_lo, rs2, 0x0); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic inline u16 rvc_addi(u8 rd, u32 imm6) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci return rv_ci_insn(0, imm6, rd, 0x1); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic inline u16 rvc_li(u8 rd, u32 imm6) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci return rv_ci_insn(0x2, imm6, rd, 0x1); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic inline u16 rvc_addi16sp(u32 imm10) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci u32 imm; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci imm = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) | ((imm10 & 0x40) >> 3) | 5828c2ecf20Sopenharmony_ci ((imm10 & 0x180) >> 6) | ((imm10 & 0x20) >> 5); 5838c2ecf20Sopenharmony_ci return rv_ci_insn(0x3, imm, RV_REG_SP, 0x1); 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic inline u16 rvc_lui(u8 rd, u32 imm6) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci return rv_ci_insn(0x3, imm6, rd, 0x1); 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic inline u16 rvc_srli(u8 rd, u32 imm6) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0, rd, 0x1); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_cistatic inline u16 rvc_srai(u8 rd, u32 imm6) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0x1, rd, 0x1); 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic inline u16 rvc_andi(u8 rd, u32 imm6) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0x2, rd, 0x1); 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_cistatic inline u16 rvc_sub(u8 rd, u8 rs) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci return rv_ca_insn(0x23, rd, 0, rs, 0x1); 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic inline u16 rvc_xor(u8 rd, u8 rs) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x1, rs, 0x1); 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic inline u16 rvc_or(u8 rd, u8 rs) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x2, rs, 0x1); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic inline u16 rvc_and(u8 rd, u8 rs) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x3, rs, 0x1); 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic inline u16 rvc_slli(u8 rd, u32 imm6) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci return rv_ci_insn(0, imm6, rd, 0x2); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic inline u16 rvc_lwsp(u8 rd, u32 imm8) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci u32 imm; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci imm = ((imm8 & 0xc0) >> 6) | (imm8 & 0x3c); 6368c2ecf20Sopenharmony_ci return rv_ci_insn(0x2, imm, rd, 0x2); 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic inline u16 rvc_jr(u8 rs1) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci return rv_cr_insn(0x8, rs1, RV_REG_ZERO, 0x2); 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic inline u16 rvc_mv(u8 rd, u8 rs) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci return rv_cr_insn(0x8, rd, rs, 0x2); 6478c2ecf20Sopenharmony_ci} 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_cistatic inline u16 rvc_jalr(u8 rs1) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci return rv_cr_insn(0x9, rs1, RV_REG_ZERO, 0x2); 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic inline u16 rvc_add(u8 rd, u8 rs) 6558c2ecf20Sopenharmony_ci{ 6568c2ecf20Sopenharmony_ci return rv_cr_insn(0x9, rd, rs, 0x2); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic inline u16 rvc_swsp(u32 imm8, u8 rs2) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci u32 imm; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci imm = (imm8 & 0x3c) | ((imm8 & 0xc0) >> 6); 6648c2ecf20Sopenharmony_ci return rv_css_insn(0x6, imm, rs2, 0x2); 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci/* 6688c2ecf20Sopenharmony_ci * RV64-only instructions. 6698c2ecf20Sopenharmony_ci * 6708c2ecf20Sopenharmony_ci * These instructions are not available on RV32. Wrap them below a #if to 6718c2ecf20Sopenharmony_ci * ensure that the RV32 JIT doesn't emit any of these instructions. 6728c2ecf20Sopenharmony_ci */ 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci#if __riscv_xlen == 64 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_cistatic inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b); 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic inline u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b); 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic inline u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b); 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic inline u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic inline u32 rv_addw(u8 rd, u8 rs1, u8 rs2) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b); 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic inline u32 rv_subw(u8 rd, u8 rs1, u8 rs2) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic inline u32 rv_sllw(u8 rd, u8 rs1, u8 rs2) 7078c2ecf20Sopenharmony_ci{ 7088c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b); 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic inline u32 rv_srlw(u8 rd, u8 rs1, u8 rs2) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b); 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic inline u32 rv_sraw(u8 rd, u8 rs1, u8 rs2) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b); 7198c2ecf20Sopenharmony_ci} 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_cistatic inline u32 rv_mulw(u8 rd, u8 rs1, u8 rs2) 7228c2ecf20Sopenharmony_ci{ 7238c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic inline u32 rv_divuw(u8 rd, u8 rs1, u8 rs2) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b); 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic inline u32 rv_remuw(u8 rd, u8 rs1, u8 rs2) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b); 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic inline u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 3, rd, 0x03); 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic inline u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1) 7428c2ecf20Sopenharmony_ci{ 7438c2ecf20Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 6, rd, 0x03); 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic inline u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23); 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f); 7548c2ecf20Sopenharmony_ci} 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci/* RV64-only RVC instructions. */ 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_cistatic inline u16 rvc_ld(u8 rd, u32 imm8, u8 rs1) 7598c2ecf20Sopenharmony_ci{ 7608c2ecf20Sopenharmony_ci u32 imm_hi, imm_lo; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci imm_hi = (imm8 & 0x38) >> 3; 7638c2ecf20Sopenharmony_ci imm_lo = (imm8 & 0xc0) >> 6; 7648c2ecf20Sopenharmony_ci return rv_cl_insn(0x3, imm_hi, rs1, imm_lo, rd, 0x0); 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic inline u16 rvc_sd(u8 rs1, u32 imm8, u8 rs2) 7688c2ecf20Sopenharmony_ci{ 7698c2ecf20Sopenharmony_ci u32 imm_hi, imm_lo; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci imm_hi = (imm8 & 0x38) >> 3; 7728c2ecf20Sopenharmony_ci imm_lo = (imm8 & 0xc0) >> 6; 7738c2ecf20Sopenharmony_ci return rv_cs_insn(0x7, imm_hi, rs1, imm_lo, rs2, 0x0); 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_cistatic inline u16 rvc_subw(u8 rd, u8 rs) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci return rv_ca_insn(0x27, rd, 0, rs, 0x1); 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic inline u16 rvc_addiw(u8 rd, u32 imm6) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci return rv_ci_insn(0x1, imm6, rd, 0x1); 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic inline u16 rvc_ldsp(u8 rd, u32 imm9) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci u32 imm; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci imm = ((imm9 & 0x1c0) >> 6) | (imm9 & 0x38); 7918c2ecf20Sopenharmony_ci return rv_ci_insn(0x3, imm, rd, 0x2); 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic inline u16 rvc_sdsp(u32 imm9, u8 rs2) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci u32 imm; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci imm = (imm9 & 0x38) | ((imm9 & 0x1c0) >> 6); 7998c2ecf20Sopenharmony_ci return rv_css_insn(0x7, imm, rs2, 0x2); 8008c2ecf20Sopenharmony_ci} 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci#endif /* __riscv_xlen == 64 */ 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci/* Helper functions that emit RVC instructions when possible. */ 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistatic inline void emit_jalr(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci if (rvc_enabled() && rd == RV_REG_RA && rs && !imm) 8098c2ecf20Sopenharmony_ci emitc(rvc_jalr(rs), ctx); 8108c2ecf20Sopenharmony_ci else if (rvc_enabled() && !rd && rs && !imm) 8118c2ecf20Sopenharmony_ci emitc(rvc_jr(rs), ctx); 8128c2ecf20Sopenharmony_ci else 8138c2ecf20Sopenharmony_ci emit(rv_jalr(rd, rs, imm), ctx); 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_cistatic inline void emit_mv(u8 rd, u8 rs, struct rv_jit_context *ctx) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && rs) 8198c2ecf20Sopenharmony_ci emitc(rvc_mv(rd, rs), ctx); 8208c2ecf20Sopenharmony_ci else 8218c2ecf20Sopenharmony_ci emit(rv_addi(rd, rs, 0), ctx); 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_cistatic inline void emit_add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && rd == rs1 && rs2) 8278c2ecf20Sopenharmony_ci emitc(rvc_add(rd, rs2), ctx); 8288c2ecf20Sopenharmony_ci else 8298c2ecf20Sopenharmony_ci emit(rv_add(rd, rs1, rs2), ctx); 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_cistatic inline void emit_addi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci if (rvc_enabled() && rd == RV_REG_SP && rd == rs && is_10b_int(imm) && imm && !(imm & 0xf)) 8358c2ecf20Sopenharmony_ci emitc(rvc_addi16sp(imm), ctx); 8368c2ecf20Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && rs == RV_REG_SP && is_10b_uint(imm) && 8378c2ecf20Sopenharmony_ci !(imm & 0x3) && imm) 8388c2ecf20Sopenharmony_ci emitc(rvc_addi4spn(rd, imm), ctx); 8398c2ecf20Sopenharmony_ci else if (rvc_enabled() && rd && rd == rs && imm && is_6b_int(imm)) 8408c2ecf20Sopenharmony_ci emitc(rvc_addi(rd, imm), ctx); 8418c2ecf20Sopenharmony_ci else 8428c2ecf20Sopenharmony_ci emit(rv_addi(rd, rs, imm), ctx); 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic inline void emit_li(u8 rd, s32 imm, struct rv_jit_context *ctx) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && is_6b_int(imm)) 8488c2ecf20Sopenharmony_ci emitc(rvc_li(rd, imm), ctx); 8498c2ecf20Sopenharmony_ci else 8508c2ecf20Sopenharmony_ci emit(rv_addi(rd, RV_REG_ZERO, imm), ctx); 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistatic inline void emit_lui(u8 rd, s32 imm, struct rv_jit_context *ctx) 8548c2ecf20Sopenharmony_ci{ 8558c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && rd != RV_REG_SP && is_6b_int(imm) && imm) 8568c2ecf20Sopenharmony_ci emitc(rvc_lui(rd, imm), ctx); 8578c2ecf20Sopenharmony_ci else 8588c2ecf20Sopenharmony_ci emit(rv_lui(rd, imm), ctx); 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_cistatic inline void emit_slli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && rd == rs && imm && (u32)imm < __riscv_xlen) 8648c2ecf20Sopenharmony_ci emitc(rvc_slli(rd, imm), ctx); 8658c2ecf20Sopenharmony_ci else 8668c2ecf20Sopenharmony_ci emit(rv_slli(rd, rs, imm), ctx); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic inline void emit_andi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && is_6b_int(imm)) 8728c2ecf20Sopenharmony_ci emitc(rvc_andi(rd, imm), ctx); 8738c2ecf20Sopenharmony_ci else 8748c2ecf20Sopenharmony_ci emit(rv_andi(rd, rs, imm), ctx); 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_cistatic inline void emit_srli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen) 8808c2ecf20Sopenharmony_ci emitc(rvc_srli(rd, imm), ctx); 8818c2ecf20Sopenharmony_ci else 8828c2ecf20Sopenharmony_ci emit(rv_srli(rd, rs, imm), ctx); 8838c2ecf20Sopenharmony_ci} 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_cistatic inline void emit_srai(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen) 8888c2ecf20Sopenharmony_ci emitc(rvc_srai(rd, imm), ctx); 8898c2ecf20Sopenharmony_ci else 8908c2ecf20Sopenharmony_ci emit(rv_srai(rd, rs, imm), ctx); 8918c2ecf20Sopenharmony_ci} 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cistatic inline void emit_sub(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 8968c2ecf20Sopenharmony_ci emitc(rvc_sub(rd, rs2), ctx); 8978c2ecf20Sopenharmony_ci else 8988c2ecf20Sopenharmony_ci emit(rv_sub(rd, rs1, rs2), ctx); 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic inline void emit_or(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 9048c2ecf20Sopenharmony_ci emitc(rvc_or(rd, rs2), ctx); 9058c2ecf20Sopenharmony_ci else 9068c2ecf20Sopenharmony_ci emit(rv_or(rd, rs1, rs2), ctx); 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_cistatic inline void emit_and(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 9128c2ecf20Sopenharmony_ci emitc(rvc_and(rd, rs2), ctx); 9138c2ecf20Sopenharmony_ci else 9148c2ecf20Sopenharmony_ci emit(rv_and(rd, rs1, rs2), ctx); 9158c2ecf20Sopenharmony_ci} 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_cistatic inline void emit_xor(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 9208c2ecf20Sopenharmony_ci emitc(rvc_xor(rd, rs2), ctx); 9218c2ecf20Sopenharmony_ci else 9228c2ecf20Sopenharmony_ci emit(rv_xor(rd, rs1, rs2), ctx); 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic inline void emit_lw(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_8b_uint(off) && !(off & 0x3)) 9288c2ecf20Sopenharmony_ci emitc(rvc_lwsp(rd, off), ctx); 9298c2ecf20Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_7b_uint(off) && !(off & 0x3)) 9308c2ecf20Sopenharmony_ci emitc(rvc_lw(rd, off, rs1), ctx); 9318c2ecf20Sopenharmony_ci else 9328c2ecf20Sopenharmony_ci emit(rv_lw(rd, off, rs1), ctx); 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && is_8b_uint(off) && !(off & 0x3)) 9388c2ecf20Sopenharmony_ci emitc(rvc_swsp(off, rs2), ctx); 9398c2ecf20Sopenharmony_ci else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_7b_uint(off) && !(off & 0x3)) 9408c2ecf20Sopenharmony_ci emitc(rvc_sw(rs1, off, rs2), ctx); 9418c2ecf20Sopenharmony_ci else 9428c2ecf20Sopenharmony_ci emit(rv_sw(rs1, off, rs2), ctx); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci/* RV64-only helper functions. */ 9468c2ecf20Sopenharmony_ci#if __riscv_xlen == 64 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic inline void emit_addiw(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci if (rvc_enabled() && rd && rd == rs && is_6b_int(imm)) 9518c2ecf20Sopenharmony_ci emitc(rvc_addiw(rd, imm), ctx); 9528c2ecf20Sopenharmony_ci else 9538c2ecf20Sopenharmony_ci emit(rv_addiw(rd, rs, imm), ctx); 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cistatic inline void emit_ld(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx) 9578c2ecf20Sopenharmony_ci{ 9588c2ecf20Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_9b_uint(off) && !(off & 0x7)) 9598c2ecf20Sopenharmony_ci emitc(rvc_ldsp(rd, off), ctx); 9608c2ecf20Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_8b_uint(off) && !(off & 0x7)) 9618c2ecf20Sopenharmony_ci emitc(rvc_ld(rd, off, rs1), ctx); 9628c2ecf20Sopenharmony_ci else 9638c2ecf20Sopenharmony_ci emit(rv_ld(rd, off, rs1), ctx); 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_cistatic inline void emit_sd(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && is_9b_uint(off) && !(off & 0x7)) 9698c2ecf20Sopenharmony_ci emitc(rvc_sdsp(off, rs2), ctx); 9708c2ecf20Sopenharmony_ci else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_8b_uint(off) && !(off & 0x7)) 9718c2ecf20Sopenharmony_ci emitc(rvc_sd(rs1, off, rs2), ctx); 9728c2ecf20Sopenharmony_ci else 9738c2ecf20Sopenharmony_ci emit(rv_sd(rs1, off, rs2), ctx); 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 9798c2ecf20Sopenharmony_ci emitc(rvc_subw(rd, rs2), ctx); 9808c2ecf20Sopenharmony_ci else 9818c2ecf20Sopenharmony_ci emit(rv_subw(rd, rs1, rs2), ctx); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci#endif /* __riscv_xlen == 64 */ 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_civoid bpf_jit_build_prologue(struct rv_jit_context *ctx); 9878c2ecf20Sopenharmony_civoid bpf_jit_build_epilogue(struct rv_jit_context *ctx); 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ciint bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, 9908c2ecf20Sopenharmony_ci bool extra_pass); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci#endif /* _BPF_JIT_H */ 993