@@ -23,6 +23,7 @@
%sh6 20:6
%sh5 20:5
+%csr 20:12
%pred 24:4
%succ 20:4
@@ -49,6 +50,7 @@
@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
+@csr ............ ..... ... ..... ....... %csr %rs1 %rd
# *** RV32I Base Instruction Set ***
lui .................... ..... 0110111 @u
@@ -90,6 +92,13 @@ or 0000000 ..... ..... 110 ..... 0110011 @r
and 0000000 ..... ..... 111 ..... 0110011 @r
fence ---- pred:4 succ:4 ----- 000 ----- 0001111
fence_i ---- ---- ---- ----- 001 ----- 0001111
+csrrw ............ ..... 001 ..... 1110011 @csr
+csrrs ............ ..... 010 ..... 1110011 @csr
+csrrc ............ ..... 011 ..... 1110011 @csr
+csrrwi ............ ..... 101 ..... 1110011 @csr
+csrrsi ............ ..... 110 ..... 1110011 @csr
+csrrci ............ ..... 111 ..... 1110011 @csr
+
# *** RV64I Base Instruction Set (in addition to RV32I) ***
lwu ............ ..... 110 ..... 0000011 @i
@@ -361,3 +361,82 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a, uint32_t insn)
#endif
return true;
}
+
+#define RISCV_OP_CSR_PRE do {\
+ source1 = tcg_temp_new(); \
+ csr_store = tcg_temp_new(); \
+ dest = tcg_temp_new(); \
+ rs1_pass = tcg_temp_new(); \
+ gen_get_gpr(source1, a->rs1); \
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); \
+ tcg_gen_movi_tl(rs1_pass, a->rs1); \
+ tcg_gen_movi_tl(csr_store, a->csr); \
+ gen_io_start();\
+} while (0)
+
+#define RISCV_OP_CSR_POST do {\
+ gen_io_end(); \
+ gen_set_gpr(a->rd, dest); \
+ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \
+ tcg_gen_exit_tb(NULL, 0); \
+ ctx->base.is_jmp = DISAS_NORETURN; \
+ tcg_temp_free(source1); \
+ tcg_temp_free(csr_store); \
+ tcg_temp_free(dest); \
+ tcg_temp_free(rs1_pass); \
+} while (0)
+
+
+static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrw(dest, cpu_env, source1, csr_store);
+ RISCV_OP_CSR_POST;
+ return true;
+}
+
+static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass);
+ RISCV_OP_CSR_POST;
+ return true;
+}
+
+static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrc(dest, cpu_env, source1, csr_store, rs1_pass);
+ RISCV_OP_CSR_POST;
+ return true;
+}
+
+static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrw(dest, cpu_env, rs1_pass, csr_store);
+ RISCV_OP_CSR_POST;
+ return true;
+}
+
+static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrs(dest, cpu_env, rs1_pass, csr_store, rs1_pass);
+ RISCV_OP_CSR_POST;
+ return true;
+}
+
+static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a, uint32_t insn)
+{
+ TCGv source1, csr_store, dest, rs1_pass;
+ RISCV_OP_CSR_PRE;
+ gen_helper_csrrc(dest, cpu_env, rs1_pass, csr_store, rs1_pass);
+ RISCV_OP_CSR_POST;
+ return true;
+}
@@ -1277,16 +1277,11 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
int rd, int rs1, int csr)
{
- TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
+ TCGv source1, dest;
source1 = tcg_temp_new();
- csr_store = tcg_temp_new();
dest = tcg_temp_new();
- rs1_pass = tcg_temp_new();
- imm_rs1 = tcg_temp_new();
gen_get_gpr(source1, rs1);
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
- tcg_gen_movi_tl(rs1_pass, rs1);
- tcg_gen_movi_tl(csr_store, csr); /* copy into temp reg to feed to helper */
#ifndef CONFIG_USER_ONLY
/* Extract funct7 value and check whether it matches SFENCE.VMA */
@@ -1349,45 +1344,9 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
break;
}
break;
- default:
- tcg_gen_movi_tl(imm_rs1, rs1);
- gen_io_start();
- switch (opc) {
- case OPC_RISC_CSRRW:
- gen_helper_csrrw(dest, cpu_env, source1, csr_store);
- break;
- case OPC_RISC_CSRRS:
- gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass);
- break;
- case OPC_RISC_CSRRC:
- gen_helper_csrrc(dest, cpu_env, source1, csr_store, rs1_pass);
- break;
- case OPC_RISC_CSRRWI:
- gen_helper_csrrw(dest, cpu_env, imm_rs1, csr_store);
- break;
- case OPC_RISC_CSRRSI:
- gen_helper_csrrs(dest, cpu_env, imm_rs1, csr_store, rs1_pass);
- break;
- case OPC_RISC_CSRRCI:
- gen_helper_csrrc(dest, cpu_env, imm_rs1, csr_store, rs1_pass);
- break;
- default:
- gen_exception_illegal(ctx);
- return;
- }
- gen_io_end();
- gen_set_gpr(rd, dest);
- /* end tb since we may be changing priv modes, to get mmu_index right */
- tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
- tcg_gen_exit_tb(NULL, 0); /* no chaining */
- ctx->base.is_jmp = DISAS_NORETURN;
- break;
}
tcg_temp_free(source1);
- tcg_temp_free(csr_store);
tcg_temp_free(dest);
- tcg_temp_free(rs1_pass);
- tcg_temp_free(imm_rs1);
}
static void decode_RV32_64C0(DisasContext *ctx)