162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Common functionality for RV32 and RV64 BPF JIT compilers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2019 Björn Töpel <bjorn.topel@gmail.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef _BPF_JIT_H 1062306a36Sopenharmony_ci#define _BPF_JIT_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/bpf.h> 1362306a36Sopenharmony_ci#include <linux/filter.h> 1462306a36Sopenharmony_ci#include <asm/cacheflush.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic inline bool rvc_enabled(void) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci return IS_ENABLED(CONFIG_RISCV_ISA_C); 1962306a36Sopenharmony_ci} 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cienum { 2262306a36Sopenharmony_ci RV_REG_ZERO = 0, /* The constant value 0 */ 2362306a36Sopenharmony_ci RV_REG_RA = 1, /* Return address */ 2462306a36Sopenharmony_ci RV_REG_SP = 2, /* Stack pointer */ 2562306a36Sopenharmony_ci RV_REG_GP = 3, /* Global pointer */ 2662306a36Sopenharmony_ci RV_REG_TP = 4, /* Thread pointer */ 2762306a36Sopenharmony_ci RV_REG_T0 = 5, /* Temporaries */ 2862306a36Sopenharmony_ci RV_REG_T1 = 6, 2962306a36Sopenharmony_ci RV_REG_T2 = 7, 3062306a36Sopenharmony_ci RV_REG_FP = 8, /* Saved register/frame pointer */ 3162306a36Sopenharmony_ci RV_REG_S1 = 9, /* Saved register */ 3262306a36Sopenharmony_ci RV_REG_A0 = 10, /* Function argument/return values */ 3362306a36Sopenharmony_ci RV_REG_A1 = 11, /* Function arguments */ 3462306a36Sopenharmony_ci RV_REG_A2 = 12, 3562306a36Sopenharmony_ci RV_REG_A3 = 13, 3662306a36Sopenharmony_ci RV_REG_A4 = 14, 3762306a36Sopenharmony_ci RV_REG_A5 = 15, 3862306a36Sopenharmony_ci RV_REG_A6 = 16, 3962306a36Sopenharmony_ci RV_REG_A7 = 17, 4062306a36Sopenharmony_ci RV_REG_S2 = 18, /* Saved registers */ 4162306a36Sopenharmony_ci RV_REG_S3 = 19, 4262306a36Sopenharmony_ci RV_REG_S4 = 20, 4362306a36Sopenharmony_ci RV_REG_S5 = 21, 4462306a36Sopenharmony_ci RV_REG_S6 = 22, 4562306a36Sopenharmony_ci RV_REG_S7 = 23, 4662306a36Sopenharmony_ci RV_REG_S8 = 24, 4762306a36Sopenharmony_ci RV_REG_S9 = 25, 4862306a36Sopenharmony_ci RV_REG_S10 = 26, 4962306a36Sopenharmony_ci RV_REG_S11 = 27, 5062306a36Sopenharmony_ci RV_REG_T3 = 28, /* Temporaries */ 5162306a36Sopenharmony_ci RV_REG_T4 = 29, 5262306a36Sopenharmony_ci RV_REG_T5 = 30, 5362306a36Sopenharmony_ci RV_REG_T6 = 31, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic inline bool is_creg(u8 reg) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci return (1 << reg) & (BIT(RV_REG_FP) | 5962306a36Sopenharmony_ci BIT(RV_REG_S1) | 6062306a36Sopenharmony_ci BIT(RV_REG_A0) | 6162306a36Sopenharmony_ci BIT(RV_REG_A1) | 6262306a36Sopenharmony_ci BIT(RV_REG_A2) | 6362306a36Sopenharmony_ci BIT(RV_REG_A3) | 6462306a36Sopenharmony_ci BIT(RV_REG_A4) | 6562306a36Sopenharmony_ci BIT(RV_REG_A5)); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistruct rv_jit_context { 6962306a36Sopenharmony_ci struct bpf_prog *prog; 7062306a36Sopenharmony_ci u16 *insns; /* RV insns */ 7162306a36Sopenharmony_ci u16 *ro_insns; 7262306a36Sopenharmony_ci int ninsns; 7362306a36Sopenharmony_ci int prologue_len; 7462306a36Sopenharmony_ci int epilogue_offset; 7562306a36Sopenharmony_ci int *offset; /* BPF to RV */ 7662306a36Sopenharmony_ci int nexentries; 7762306a36Sopenharmony_ci unsigned long flags; 7862306a36Sopenharmony_ci int stack_size; 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* Convert from ninsns to bytes. */ 8262306a36Sopenharmony_cistatic inline int ninsns_rvoff(int ninsns) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci return ninsns << 1; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct rv_jit_data { 8862306a36Sopenharmony_ci struct bpf_binary_header *header; 8962306a36Sopenharmony_ci struct bpf_binary_header *ro_header; 9062306a36Sopenharmony_ci u8 *image; 9162306a36Sopenharmony_ci u8 *ro_image; 9262306a36Sopenharmony_ci struct rv_jit_context ctx; 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic inline void bpf_fill_ill_insns(void *area, unsigned int size) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci memset(area, 0, size); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic inline void bpf_flush_icache(void *start, void *end) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci flush_icache_range((unsigned long)start, (unsigned long)end); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* Emit a 4-byte riscv instruction. */ 10662306a36Sopenharmony_cistatic inline void emit(const u32 insn, struct rv_jit_context *ctx) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci if (ctx->insns) { 10962306a36Sopenharmony_ci ctx->insns[ctx->ninsns] = insn; 11062306a36Sopenharmony_ci ctx->insns[ctx->ninsns + 1] = (insn >> 16); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ctx->ninsns += 2; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* Emit a 2-byte riscv compressed instruction. */ 11762306a36Sopenharmony_cistatic inline void emitc(const u16 insn, struct rv_jit_context *ctx) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci BUILD_BUG_ON(!rvc_enabled()); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (ctx->insns) 12262306a36Sopenharmony_ci ctx->insns[ctx->ninsns] = insn; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci ctx->ninsns++; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic inline int epilogue_offset(struct rv_jit_context *ctx) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci int to = ctx->epilogue_offset, from = ctx->ninsns; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return ninsns_rvoff(to - from); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* Return -1 or inverted cond. */ 13562306a36Sopenharmony_cistatic inline int invert_bpf_cond(u8 cond) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci switch (cond) { 13862306a36Sopenharmony_ci case BPF_JEQ: 13962306a36Sopenharmony_ci return BPF_JNE; 14062306a36Sopenharmony_ci case BPF_JGT: 14162306a36Sopenharmony_ci return BPF_JLE; 14262306a36Sopenharmony_ci case BPF_JLT: 14362306a36Sopenharmony_ci return BPF_JGE; 14462306a36Sopenharmony_ci case BPF_JGE: 14562306a36Sopenharmony_ci return BPF_JLT; 14662306a36Sopenharmony_ci case BPF_JLE: 14762306a36Sopenharmony_ci return BPF_JGT; 14862306a36Sopenharmony_ci case BPF_JNE: 14962306a36Sopenharmony_ci return BPF_JEQ; 15062306a36Sopenharmony_ci case BPF_JSGT: 15162306a36Sopenharmony_ci return BPF_JSLE; 15262306a36Sopenharmony_ci case BPF_JSLT: 15362306a36Sopenharmony_ci return BPF_JSGE; 15462306a36Sopenharmony_ci case BPF_JSGE: 15562306a36Sopenharmony_ci return BPF_JSLT; 15662306a36Sopenharmony_ci case BPF_JSLE: 15762306a36Sopenharmony_ci return BPF_JSGT; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci return -1; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic inline bool is_6b_int(long val) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci return -(1L << 5) <= val && val < (1L << 5); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic inline bool is_7b_uint(unsigned long val) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci return val < (1UL << 7); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic inline bool is_8b_uint(unsigned long val) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci return val < (1UL << 8); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic inline bool is_9b_uint(unsigned long val) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci return val < (1UL << 9); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic inline bool is_10b_int(long val) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci return -(1L << 9) <= val && val < (1L << 9); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic inline bool is_10b_uint(unsigned long val) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci return val < (1UL << 10); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic inline bool is_12b_int(long val) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci return -(1L << 11) <= val && val < (1L << 11); 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic inline int is_12b_check(int off, int insn) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci if (!is_12b_int(off)) { 20062306a36Sopenharmony_ci pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n", 20162306a36Sopenharmony_ci insn, (int)off); 20262306a36Sopenharmony_ci return -1; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci return 0; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic inline bool is_13b_int(long val) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci return -(1L << 12) <= val && val < (1L << 12); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic inline bool is_21b_int(long val) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci return -(1L << 20) <= val && val < (1L << 20); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline int rv_offset(int insn, int off, struct rv_jit_context *ctx) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci int from, to; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci off++; /* BPF branch is from PC+1, RV is from PC */ 22262306a36Sopenharmony_ci from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len; 22362306a36Sopenharmony_ci to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len; 22462306a36Sopenharmony_ci return ninsns_rvoff(to - from); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/* Instruction formats. */ 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd, 23062306a36Sopenharmony_ci u8 opcode) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 23362306a36Sopenharmony_ci (rd << 7) | opcode; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) | 23962306a36Sopenharmony_ci opcode; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 24762306a36Sopenharmony_ci (imm4_0 << 7) | opcode; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic inline u32 rv_b_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4); 25362306a36Sopenharmony_ci u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | 25662306a36Sopenharmony_ci (imm4_1 << 7) | opcode; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic inline u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return (imm31_12 << 12) | (rd << 7) | opcode; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic inline u32 rv_j_insn(u32 imm20_1, u8 rd, u8 opcode) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci u32 imm; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci imm = (imm20_1 & 0x80000) | ((imm20_1 & 0x3ff) << 9) | 26962306a36Sopenharmony_ci ((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci return (imm << 12) | (rd << 7) | opcode; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1, 27562306a36Sopenharmony_ci u8 funct3, u8 rd, u8 opcode) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci u8 funct7 = (funct5 << 2) | (aq << 1) | rl; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* RISC-V compressed instruction formats. */ 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic inline u16 rv_cr_insn(u8 funct4, u8 rd, u8 rs2, u8 op) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci return (funct4 << 12) | (rd << 7) | (rs2 << 2) | op; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic inline u16 rv_ci_insn(u8 funct3, u32 imm6, u8 rd, u8 op) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci u32 imm; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2); 29462306a36Sopenharmony_ci return (funct3 << 13) | (rd << 7) | op | imm; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic inline u16 rv_css_insn(u8 funct3, u32 uimm, u8 rs2, u8 op) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci return (funct3 << 13) | (uimm << 7) | (rs2 << 2) | op; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic inline u16 rv_ciw_insn(u8 funct3, u32 uimm, u8 rd, u8 op) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci return (funct3 << 13) | (uimm << 5) | ((rd & 0x7) << 2) | op; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic inline u16 rv_cl_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rd, 30862306a36Sopenharmony_ci u8 op) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) | 31162306a36Sopenharmony_ci (imm_lo << 5) | ((rd & 0x7) << 2) | op; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic inline u16 rv_cs_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rs2, 31562306a36Sopenharmony_ci u8 op) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) | 31862306a36Sopenharmony_ci (imm_lo << 5) | ((rs2 & 0x7) << 2) | op; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic inline u16 rv_ca_insn(u8 funct6, u8 rd, u8 funct2, u8 rs2, u8 op) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci return (funct6 << 10) | ((rd & 0x7) << 7) | (funct2 << 5) | 32462306a36Sopenharmony_ci ((rs2 & 0x7) << 2) | op; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic inline u16 rv_cb_insn(u8 funct3, u32 imm6, u8 funct2, u8 rd, u8 op) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci u32 imm; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2); 33262306a36Sopenharmony_ci return (funct3 << 13) | (funct2 << 10) | ((rd & 0x7) << 7) | op | imm; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci/* Instructions shared by both RV32 and RV64. */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x13); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic inline u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 7, rd, 0x13); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic inline u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 6, rd, 0x13); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic inline u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 4, rd, 0x13); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic inline u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 1, rd, 0x13); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic inline u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x13); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic inline u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13); 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic inline u32 rv_lui(u8 rd, u32 imm31_12) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci return rv_u_insn(imm31_12, rd, 0x37); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic inline u32 rv_auipc(u8 rd, u32 imm31_12) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci return rv_u_insn(imm31_12, rd, 0x17); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic inline u32 rv_add(u8 rd, u8 rs1, u8 rs2) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 0, rd, 0x33); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic inline u32 rv_sltu(u8 rd, u8 rs1, u8 rs2) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 3, rd, 0x33); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic inline u32 rv_and(u8 rd, u8 rs1, u8 rs2) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 7, rd, 0x33); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic inline u32 rv_or(u8 rd, u8 rs1, u8 rs2) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 6, rd, 0x33); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic inline u32 rv_xor(u8 rd, u8 rs1, u8 rs2) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 4, rd, 0x33); 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic inline u32 rv_sll(u8 rd, u8 rs1, u8 rs2) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 1, rd, 0x33); 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic inline u32 rv_srl(u8 rd, u8 rs1, u8 rs2) 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 5, rd, 0x33); 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic inline u32 rv_sra(u8 rd, u8 rs1, u8 rs2) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 0, rd, 0x33); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic inline u32 rv_mulhu(u8 rd, u8 rs1, u8 rs2) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 3, rd, 0x33); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic inline u32 rv_div(u8 rd, u8 rs1, u8 rs2) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 4, rd, 0x33); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 5, rd, 0x33); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic inline u32 rv_rem(u8 rd, u8 rs1, u8 rs2) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 6, rd, 0x33); 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic inline u32 rv_remu(u8 rd, u8 rs1, u8 rs2) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 7, rd, 0x33); 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic inline u32 rv_jal(u8 rd, u32 imm20_1) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci return rv_j_insn(imm20_1, rd, 0x6f); 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic inline u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x67); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic inline u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 0, 0x63); 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic inline u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 1, 0x63); 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63); 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic inline u32 rv_bgtu(u8 rs1, u8 rs2, u16 imm12_1) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci return rv_bltu(rs2, rs1, imm12_1); 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63); 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic inline u32 rv_bleu(u8 rs1, u8 rs2, u16 imm12_1) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci return rv_bgeu(rs2, rs1, imm12_1); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63); 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic inline u32 rv_bgt(u8 rs1, u8 rs2, u16 imm12_1) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci return rv_blt(rs2, rs1, imm12_1); 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63); 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic inline u32 rv_ble(u8 rs1, u8 rs2, u16 imm12_1) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci return rv_bge(rs2, rs1, imm12_1); 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic inline u32 rv_lb(u8 rd, u16 imm11_0, u8 rs1) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x03); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic inline u32 rv_lh(u8 rd, u16 imm11_0, u8 rs1) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 1, rd, 0x03); 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic inline u32 rv_lw(u8 rd, u16 imm11_0, u8 rs1) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 2, rd, 0x03); 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 4, rd, 0x03); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic inline u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x03); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic inline u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23); 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cistatic inline u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_cistatic inline u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23); 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 55862306a36Sopenharmony_ci{ 55962306a36Sopenharmony_ci return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f); 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic inline u32 rv_amoand_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci return rv_amo_insn(0xc, aq, rl, rs2, rs1, 2, rd, 0x2f); 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic inline u32 rv_amoor_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci return rv_amo_insn(0x8, aq, rl, rs2, rs1, 2, rd, 0x2f); 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistatic inline u32 rv_amoxor_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci return rv_amo_insn(0x4, aq, rl, rs2, rs1, 2, rd, 0x2f); 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic inline u32 rv_amoswap_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci return rv_amo_insn(0x1, aq, rl, rs2, rs1, 2, rd, 0x2f); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic inline u32 rv_lr_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci return rv_amo_insn(0x2, aq, rl, rs2, rs1, 2, rd, 0x2f); 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic inline u32 rv_sc_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci return rv_amo_insn(0x3, aq, rl, rs2, rs1, 2, rd, 0x2f); 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic inline u32 rv_fence(u8 pred, u8 succ) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci u16 imm11_0 = pred << 4 | succ; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return rv_i_insn(imm11_0, 0, 0, 0, 0xf); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic inline u32 rv_nop(void) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci return rv_i_insn(0, 0, 0, 0, 0x13); 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci/* RVC instrutions. */ 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic inline u16 rvc_addi4spn(u8 rd, u32 imm10) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci u32 imm; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci imm = ((imm10 & 0x30) << 2) | ((imm10 & 0x3c0) >> 4) | 61162306a36Sopenharmony_ci ((imm10 & 0x4) >> 1) | ((imm10 & 0x8) >> 3); 61262306a36Sopenharmony_ci return rv_ciw_insn(0x0, imm, rd, 0x0); 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic inline u16 rvc_lw(u8 rd, u32 imm7, u8 rs1) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci u32 imm_hi, imm_lo; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci imm_hi = (imm7 & 0x38) >> 3; 62062306a36Sopenharmony_ci imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6); 62162306a36Sopenharmony_ci return rv_cl_insn(0x2, imm_hi, rs1, imm_lo, rd, 0x0); 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic inline u16 rvc_sw(u8 rs1, u32 imm7, u8 rs2) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci u32 imm_hi, imm_lo; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci imm_hi = (imm7 & 0x38) >> 3; 62962306a36Sopenharmony_ci imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6); 63062306a36Sopenharmony_ci return rv_cs_insn(0x6, imm_hi, rs1, imm_lo, rs2, 0x0); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic inline u16 rvc_addi(u8 rd, u32 imm6) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci return rv_ci_insn(0, imm6, rd, 0x1); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic inline u16 rvc_li(u8 rd, u32 imm6) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci return rv_ci_insn(0x2, imm6, rd, 0x1); 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic inline u16 rvc_addi16sp(u32 imm10) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci u32 imm; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci imm = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) | ((imm10 & 0x40) >> 3) | 64862306a36Sopenharmony_ci ((imm10 & 0x180) >> 6) | ((imm10 & 0x20) >> 5); 64962306a36Sopenharmony_ci return rv_ci_insn(0x3, imm, RV_REG_SP, 0x1); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic inline u16 rvc_lui(u8 rd, u32 imm6) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci return rv_ci_insn(0x3, imm6, rd, 0x1); 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic inline u16 rvc_srli(u8 rd, u32 imm6) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0, rd, 0x1); 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic inline u16 rvc_srai(u8 rd, u32 imm6) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0x1, rd, 0x1); 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic inline u16 rvc_andi(u8 rd, u32 imm6) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci return rv_cb_insn(0x4, imm6, 0x2, rd, 0x1); 67062306a36Sopenharmony_ci} 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic inline u16 rvc_sub(u8 rd, u8 rs) 67362306a36Sopenharmony_ci{ 67462306a36Sopenharmony_ci return rv_ca_insn(0x23, rd, 0, rs, 0x1); 67562306a36Sopenharmony_ci} 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_cistatic inline u16 rvc_xor(u8 rd, u8 rs) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x1, rs, 0x1); 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic inline u16 rvc_or(u8 rd, u8 rs) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x2, rs, 0x1); 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic inline u16 rvc_and(u8 rd, u8 rs) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci return rv_ca_insn(0x23, rd, 0x3, rs, 0x1); 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic inline u16 rvc_slli(u8 rd, u32 imm6) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci return rv_ci_insn(0, imm6, rd, 0x2); 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic inline u16 rvc_lwsp(u8 rd, u32 imm8) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci u32 imm; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci imm = ((imm8 & 0xc0) >> 6) | (imm8 & 0x3c); 70262306a36Sopenharmony_ci return rv_ci_insn(0x2, imm, rd, 0x2); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_cistatic inline u16 rvc_jr(u8 rs1) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci return rv_cr_insn(0x8, rs1, RV_REG_ZERO, 0x2); 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic inline u16 rvc_mv(u8 rd, u8 rs) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci return rv_cr_insn(0x8, rd, rs, 0x2); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic inline u16 rvc_jalr(u8 rs1) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci return rv_cr_insn(0x9, rs1, RV_REG_ZERO, 0x2); 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic inline u16 rvc_add(u8 rd, u8 rs) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci return rv_cr_insn(0x9, rd, rs, 0x2); 72362306a36Sopenharmony_ci} 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_cistatic inline u16 rvc_swsp(u32 imm8, u8 rs2) 72662306a36Sopenharmony_ci{ 72762306a36Sopenharmony_ci u32 imm; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci imm = (imm8 & 0x3c) | ((imm8 & 0xc0) >> 6); 73062306a36Sopenharmony_ci return rv_css_insn(0x6, imm, rs2, 0x2); 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci/* 73462306a36Sopenharmony_ci * RV64-only instructions. 73562306a36Sopenharmony_ci * 73662306a36Sopenharmony_ci * These instructions are not available on RV32. Wrap them below a #if to 73762306a36Sopenharmony_ci * ensure that the RV32 JIT doesn't emit any of these instructions. 73862306a36Sopenharmony_ci */ 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci#if __riscv_xlen == 64 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cistatic inline u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b); 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic inline u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b); 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic inline u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0) 75862306a36Sopenharmony_ci{ 75962306a36Sopenharmony_ci return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b); 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic inline u32 rv_addw(u8 rd, u8 rs1, u8 rs2) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b); 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic inline u32 rv_subw(u8 rd, u8 rs1, u8 rs2) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b); 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic inline u32 rv_sllw(u8 rd, u8 rs1, u8 rs2) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b); 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cistatic inline u32 rv_srlw(u8 rd, u8 rs1, u8 rs2) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b); 78062306a36Sopenharmony_ci} 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_cistatic inline u32 rv_sraw(u8 rd, u8 rs1, u8 rs2) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b); 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic inline u32 rv_mulw(u8 rd, u8 rs1, u8 rs2) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b); 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic inline u32 rv_divw(u8 rd, u8 rs1, u8 rs2) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 4, rd, 0x3b); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic inline u32 rv_divuw(u8 rd, u8 rs1, u8 rs2) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b); 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic inline u32 rv_remw(u8 rd, u8 rs1, u8 rs2) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 6, rd, 0x3b); 80562306a36Sopenharmony_ci} 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic inline u32 rv_remuw(u8 rd, u8 rs1, u8 rs2) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic inline u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 3, rd, 0x03); 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_cistatic inline u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1) 81862306a36Sopenharmony_ci{ 81962306a36Sopenharmony_ci return rv_i_insn(imm11_0, rs1, 6, rd, 0x03); 82062306a36Sopenharmony_ci} 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_cistatic inline u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23); 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f); 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_cistatic inline u32 rv_amoand_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 83362306a36Sopenharmony_ci{ 83462306a36Sopenharmony_ci return rv_amo_insn(0xc, aq, rl, rs2, rs1, 3, rd, 0x2f); 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_cistatic inline u32 rv_amoor_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci return rv_amo_insn(0x8, aq, rl, rs2, rs1, 3, rd, 0x2f); 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic inline u32 rv_amoxor_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 84362306a36Sopenharmony_ci{ 84462306a36Sopenharmony_ci return rv_amo_insn(0x4, aq, rl, rs2, rs1, 3, rd, 0x2f); 84562306a36Sopenharmony_ci} 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_cistatic inline u32 rv_amoswap_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci return rv_amo_insn(0x1, aq, rl, rs2, rs1, 3, rd, 0x2f); 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cistatic inline u32 rv_lr_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci return rv_amo_insn(0x2, aq, rl, rs2, rs1, 3, rd, 0x2f); 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic inline u32 rv_sc_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci return rv_amo_insn(0x3, aq, rl, rs2, rs1, 3, rd, 0x2f); 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci/* RV64-only RVC instructions. */ 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic inline u16 rvc_ld(u8 rd, u32 imm8, u8 rs1) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci u32 imm_hi, imm_lo; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci imm_hi = (imm8 & 0x38) >> 3; 86962306a36Sopenharmony_ci imm_lo = (imm8 & 0xc0) >> 6; 87062306a36Sopenharmony_ci return rv_cl_insn(0x3, imm_hi, rs1, imm_lo, rd, 0x0); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic inline u16 rvc_sd(u8 rs1, u32 imm8, u8 rs2) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci u32 imm_hi, imm_lo; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci imm_hi = (imm8 & 0x38) >> 3; 87862306a36Sopenharmony_ci imm_lo = (imm8 & 0xc0) >> 6; 87962306a36Sopenharmony_ci return rv_cs_insn(0x7, imm_hi, rs1, imm_lo, rs2, 0x0); 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cistatic inline u16 rvc_subw(u8 rd, u8 rs) 88362306a36Sopenharmony_ci{ 88462306a36Sopenharmony_ci return rv_ca_insn(0x27, rd, 0, rs, 0x1); 88562306a36Sopenharmony_ci} 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_cistatic inline u16 rvc_addiw(u8 rd, u32 imm6) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci return rv_ci_insn(0x1, imm6, rd, 0x1); 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic inline u16 rvc_ldsp(u8 rd, u32 imm9) 89362306a36Sopenharmony_ci{ 89462306a36Sopenharmony_ci u32 imm; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci imm = ((imm9 & 0x1c0) >> 6) | (imm9 & 0x38); 89762306a36Sopenharmony_ci return rv_ci_insn(0x3, imm, rd, 0x2); 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic inline u16 rvc_sdsp(u32 imm9, u8 rs2) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci u32 imm; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci imm = (imm9 & 0x38) | ((imm9 & 0x1c0) >> 6); 90562306a36Sopenharmony_ci return rv_css_insn(0x7, imm, rs2, 0x2); 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci#endif /* __riscv_xlen == 64 */ 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci/* Helper functions that emit RVC instructions when possible. */ 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic inline void emit_jalr(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci if (rvc_enabled() && rd == RV_REG_RA && rs && !imm) 91562306a36Sopenharmony_ci emitc(rvc_jalr(rs), ctx); 91662306a36Sopenharmony_ci else if (rvc_enabled() && !rd && rs && !imm) 91762306a36Sopenharmony_ci emitc(rvc_jr(rs), ctx); 91862306a36Sopenharmony_ci else 91962306a36Sopenharmony_ci emit(rv_jalr(rd, rs, imm), ctx); 92062306a36Sopenharmony_ci} 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_cistatic inline void emit_mv(u8 rd, u8 rs, struct rv_jit_context *ctx) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci if (rvc_enabled() && rd && rs) 92562306a36Sopenharmony_ci emitc(rvc_mv(rd, rs), ctx); 92662306a36Sopenharmony_ci else 92762306a36Sopenharmony_ci emit(rv_addi(rd, rs, 0), ctx); 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic inline void emit_add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci if (rvc_enabled() && rd && rd == rs1 && rs2) 93362306a36Sopenharmony_ci emitc(rvc_add(rd, rs2), ctx); 93462306a36Sopenharmony_ci else 93562306a36Sopenharmony_ci emit(rv_add(rd, rs1, rs2), ctx); 93662306a36Sopenharmony_ci} 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic inline void emit_addi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci if (rvc_enabled() && rd == RV_REG_SP && rd == rs && is_10b_int(imm) && imm && !(imm & 0xf)) 94162306a36Sopenharmony_ci emitc(rvc_addi16sp(imm), ctx); 94262306a36Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && rs == RV_REG_SP && is_10b_uint(imm) && 94362306a36Sopenharmony_ci !(imm & 0x3) && imm) 94462306a36Sopenharmony_ci emitc(rvc_addi4spn(rd, imm), ctx); 94562306a36Sopenharmony_ci else if (rvc_enabled() && rd && rd == rs && imm && is_6b_int(imm)) 94662306a36Sopenharmony_ci emitc(rvc_addi(rd, imm), ctx); 94762306a36Sopenharmony_ci else 94862306a36Sopenharmony_ci emit(rv_addi(rd, rs, imm), ctx); 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic inline void emit_li(u8 rd, s32 imm, struct rv_jit_context *ctx) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci if (rvc_enabled() && rd && is_6b_int(imm)) 95462306a36Sopenharmony_ci emitc(rvc_li(rd, imm), ctx); 95562306a36Sopenharmony_ci else 95662306a36Sopenharmony_ci emit(rv_addi(rd, RV_REG_ZERO, imm), ctx); 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_cistatic inline void emit_lui(u8 rd, s32 imm, struct rv_jit_context *ctx) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci if (rvc_enabled() && rd && rd != RV_REG_SP && is_6b_int(imm) && imm) 96262306a36Sopenharmony_ci emitc(rvc_lui(rd, imm), ctx); 96362306a36Sopenharmony_ci else 96462306a36Sopenharmony_ci emit(rv_lui(rd, imm), ctx); 96562306a36Sopenharmony_ci} 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_cistatic inline void emit_slli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 96862306a36Sopenharmony_ci{ 96962306a36Sopenharmony_ci if (rvc_enabled() && rd && rd == rs && imm && (u32)imm < __riscv_xlen) 97062306a36Sopenharmony_ci emitc(rvc_slli(rd, imm), ctx); 97162306a36Sopenharmony_ci else 97262306a36Sopenharmony_ci emit(rv_slli(rd, rs, imm), ctx); 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic inline void emit_andi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && is_6b_int(imm)) 97862306a36Sopenharmony_ci emitc(rvc_andi(rd, imm), ctx); 97962306a36Sopenharmony_ci else 98062306a36Sopenharmony_ci emit(rv_andi(rd, rs, imm), ctx); 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cistatic inline void emit_srli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen) 98662306a36Sopenharmony_ci emitc(rvc_srli(rd, imm), ctx); 98762306a36Sopenharmony_ci else 98862306a36Sopenharmony_ci emit(rv_srli(rd, rs, imm), ctx); 98962306a36Sopenharmony_ci} 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_cistatic inline void emit_srai(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 99262306a36Sopenharmony_ci{ 99362306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen) 99462306a36Sopenharmony_ci emitc(rvc_srai(rd, imm), ctx); 99562306a36Sopenharmony_ci else 99662306a36Sopenharmony_ci emit(rv_srai(rd, rs, imm), ctx); 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic inline void emit_sub(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 100262306a36Sopenharmony_ci emitc(rvc_sub(rd, rs2), ctx); 100362306a36Sopenharmony_ci else 100462306a36Sopenharmony_ci emit(rv_sub(rd, rs1, rs2), ctx); 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic inline void emit_or(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 100862306a36Sopenharmony_ci{ 100962306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 101062306a36Sopenharmony_ci emitc(rvc_or(rd, rs2), ctx); 101162306a36Sopenharmony_ci else 101262306a36Sopenharmony_ci emit(rv_or(rd, rs1, rs2), ctx); 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_cistatic inline void emit_and(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 101662306a36Sopenharmony_ci{ 101762306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 101862306a36Sopenharmony_ci emitc(rvc_and(rd, rs2), ctx); 101962306a36Sopenharmony_ci else 102062306a36Sopenharmony_ci emit(rv_and(rd, rs1, rs2), ctx); 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_cistatic inline void emit_xor(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 102662306a36Sopenharmony_ci emitc(rvc_xor(rd, rs2), ctx); 102762306a36Sopenharmony_ci else 102862306a36Sopenharmony_ci emit(rv_xor(rd, rs1, rs2), ctx); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic inline void emit_lw(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_8b_uint(off) && !(off & 0x3)) 103462306a36Sopenharmony_ci emitc(rvc_lwsp(rd, off), ctx); 103562306a36Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_7b_uint(off) && !(off & 0x3)) 103662306a36Sopenharmony_ci emitc(rvc_lw(rd, off, rs1), ctx); 103762306a36Sopenharmony_ci else 103862306a36Sopenharmony_ci emit(rv_lw(rd, off, rs1), ctx); 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_cistatic inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && is_8b_uint(off) && !(off & 0x3)) 104462306a36Sopenharmony_ci emitc(rvc_swsp(off, rs2), ctx); 104562306a36Sopenharmony_ci else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_7b_uint(off) && !(off & 0x3)) 104662306a36Sopenharmony_ci emitc(rvc_sw(rs1, off, rs2), ctx); 104762306a36Sopenharmony_ci else 104862306a36Sopenharmony_ci emit(rv_sw(rs1, off, rs2), ctx); 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci/* RV64-only helper functions. */ 105262306a36Sopenharmony_ci#if __riscv_xlen == 64 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_cistatic inline void emit_addiw(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx) 105562306a36Sopenharmony_ci{ 105662306a36Sopenharmony_ci if (rvc_enabled() && rd && rd == rs && is_6b_int(imm)) 105762306a36Sopenharmony_ci emitc(rvc_addiw(rd, imm), ctx); 105862306a36Sopenharmony_ci else 105962306a36Sopenharmony_ci emit(rv_addiw(rd, rs, imm), ctx); 106062306a36Sopenharmony_ci} 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_cistatic inline void emit_ld(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx) 106362306a36Sopenharmony_ci{ 106462306a36Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_9b_uint(off) && !(off & 0x7)) 106562306a36Sopenharmony_ci emitc(rvc_ldsp(rd, off), ctx); 106662306a36Sopenharmony_ci else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_8b_uint(off) && !(off & 0x7)) 106762306a36Sopenharmony_ci emitc(rvc_ld(rd, off, rs1), ctx); 106862306a36Sopenharmony_ci else 106962306a36Sopenharmony_ci emit(rv_ld(rd, off, rs1), ctx); 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic inline void emit_sd(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci if (rvc_enabled() && rs1 == RV_REG_SP && is_9b_uint(off) && !(off & 0x7)) 107562306a36Sopenharmony_ci emitc(rvc_sdsp(off, rs2), ctx); 107662306a36Sopenharmony_ci else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_8b_uint(off) && !(off & 0x7)) 107762306a36Sopenharmony_ci emitc(rvc_sd(rs1, off, rs2), ctx); 107862306a36Sopenharmony_ci else 107962306a36Sopenharmony_ci emit(rv_sd(rs1, off, rs2), ctx); 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistatic inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx) 108362306a36Sopenharmony_ci{ 108462306a36Sopenharmony_ci if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2)) 108562306a36Sopenharmony_ci emitc(rvc_subw(rd, rs2), ctx); 108662306a36Sopenharmony_ci else 108762306a36Sopenharmony_ci emit(rv_subw(rd, rs1, rs2), ctx); 108862306a36Sopenharmony_ci} 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci#endif /* __riscv_xlen == 64 */ 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_civoid bpf_jit_build_prologue(struct rv_jit_context *ctx); 109362306a36Sopenharmony_civoid bpf_jit_build_epilogue(struct rv_jit_context *ctx); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ciint bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, 109662306a36Sopenharmony_ci bool extra_pass); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci#endif /* _BPF_JIT_H */ 1099