From 4ea449a809f1e0382969f6a09526b3c788c64d8b Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 18 Mar 2019 16:16:32 -0400 Subject: [PATCH] target/riscv: Convert RVXI csr insns to decodetree Backports commit 771fbe156a2a2be964a4fbe6251339a5570a26c4 from qemu --- qemu/target/riscv/insn32.decode | 8 ++ qemu/target/riscv/insn_trans/trans_rvi.inc.c | 83 ++++++++++++++++++++ qemu/target/riscv/translate.c | 45 +---------- 3 files changed, 92 insertions(+), 44 deletions(-) diff --git a/qemu/target/riscv/insn32.decode b/qemu/target/riscv/insn32.decode index 804b721c..977b1b10 100644 --- a/qemu/target/riscv/insn32.decode +++ b/qemu/target/riscv/insn32.decode @@ -22,6 +22,7 @@ %rd 7:5 %sh10 20:10 +%csr 20:12 # immediates: %imm_i 20:s12 @@ -43,6 +44,7 @@ @j .................... ..... ....... imm=%imm_j %rd @sh ...... ...... ..... ... ..... ....... &shift shamt=%sh10 %rs1 %rd +@csr ............ ..... ... ..... ....... %csr %rs1 %rd # *** RV32I Base Instruction Set *** lui .................... ..... 0110111 @u @@ -84,3 +86,9 @@ 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 diff --git a/qemu/target/riscv/insn_trans/trans_rvi.inc.c b/qemu/target/riscv/insn_trans/trans_rvi.inc.c index 751b67d1..22c873a2 100644 --- a/qemu/target/riscv/insn_trans/trans_rvi.inc.c +++ b/qemu/target/riscv/insn_trans/trans_rvi.inc.c @@ -343,3 +343,86 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) ctx->base.is_jmp = DISAS_NORETURN; return true; } + +#define RISCV_OP_CSR_PRE do {\ + source1 = tcg_temp_new(tcg_ctx); \ + csr_store = tcg_temp_new(tcg_ctx); \ + dest = tcg_temp_new(tcg_ctx); \ + rs1_pass = tcg_temp_new(tcg_ctx); \ + gen_get_gpr(ctx, source1, a->rs1); \ + tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc_risc, ctx->base.pc_next); \ + tcg_gen_movi_tl(tcg_ctx, rs1_pass, a->rs1); \ + tcg_gen_movi_tl(tcg_ctx, csr_store, a->csr); \ +} while (0) + +#define RISCV_OP_CSR_POST do {\ + gen_set_gpr(ctx, a->rd, dest); \ + tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc_risc, ctx->pc_succ_insn); \ + tcg_gen_exit_tb(tcg_ctx, NULL, 0); \ + ctx->base.is_jmp = DISAS_NORETURN; \ + tcg_temp_free(tcg_ctx, source1); \ + tcg_temp_free(tcg_ctx, csr_store); \ + tcg_temp_free(tcg_ctx, dest); \ + tcg_temp_free(tcg_ctx, rs1_pass); \ +} while (0) + + +static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrw(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store); + RISCV_OP_CSR_POST; + return true; +} + +static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrs(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store, rs1_pass); + RISCV_OP_CSR_POST; + return true; +} + +static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrc(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store, rs1_pass); + RISCV_OP_CSR_POST; + return true; +} + +static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrw(tcg_ctx, dest, tcg_ctx->cpu_env, rs1_pass, csr_store); + RISCV_OP_CSR_POST; + return true; +} + +static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrs(tcg_ctx, dest, tcg_ctx->cpu_env, rs1_pass, csr_store, rs1_pass); + RISCV_OP_CSR_POST; + return true; +} + +static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a) +{ + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + TCGv source1, csr_store, dest, rs1_pass; + RISCV_OP_CSR_PRE; + gen_helper_csrrc(tcg_ctx, dest, tcg_ctx->cpu_env, rs1_pass, csr_store, rs1_pass); + RISCV_OP_CSR_POST; + return true; +} diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index a01588cf..e3d90643 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -1545,16 +1545,11 @@ static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1, { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; - TCGv source1, csr_store, dest, rs1_pass, imm_rs1; + TCGv source1, dest; source1 = tcg_temp_new(tcg_ctx); - csr_store = tcg_temp_new(tcg_ctx); dest = tcg_temp_new(tcg_ctx); - rs1_pass = tcg_temp_new(tcg_ctx); - imm_rs1 = tcg_temp_new(tcg_ctx); gen_get_gpr(ctx, source1, rs1); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc_risc, ctx->base.pc_next); - tcg_gen_movi_tl(tcg_ctx, rs1_pass, rs1); - tcg_gen_movi_tl(tcg_ctx, 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 */ @@ -1625,47 +1620,9 @@ static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1, break; } break; - default: - tcg_gen_movi_tl(tcg_ctx, imm_rs1, rs1); - // Unicorn: Commented out - //gen_io_start(); - switch (opc) { - case OPC_RISC_CSRRW: - gen_helper_csrrw(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store); - break; - case OPC_RISC_CSRRS: - gen_helper_csrrs(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store, rs1_pass); - break; - case OPC_RISC_CSRRC: - gen_helper_csrrc(tcg_ctx, dest, tcg_ctx->cpu_env, source1, csr_store, rs1_pass); - break; - case OPC_RISC_CSRRWI: - gen_helper_csrrw(tcg_ctx, dest, tcg_ctx->cpu_env, imm_rs1, csr_store); - break; - case OPC_RISC_CSRRSI: - gen_helper_csrrs(tcg_ctx, dest, tcg_ctx->cpu_env, imm_rs1, csr_store, rs1_pass); - break; - case OPC_RISC_CSRRCI: - gen_helper_csrrc(tcg_ctx, dest, tcg_ctx->cpu_env, imm_rs1, csr_store, rs1_pass); - break; - default: - gen_exception_illegal(ctx); - return; - } - // Unicorn: Commented out - //gen_io_end(); - gen_set_gpr(ctx, rd, dest); - /* end tb since we may be changing priv modes, to get mmu_index right */ - tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc_risc, ctx->pc_succ_insn); - tcg_gen_exit_tb(tcg_ctx, NULL, 0); /* no chaining */ - ctx->base.is_jmp = DISAS_NORETURN; - break; } tcg_temp_free(tcg_ctx, source1); - tcg_temp_free(tcg_ctx, csr_store); tcg_temp_free(tcg_ctx, dest); - tcg_temp_free(tcg_ctx, rs1_pass); - tcg_temp_free(tcg_ctx, imm_rs1); } static void decode_RV32_64C0(DisasContext *ctx)