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