target/riscv: Convert RV priv insns to decodetree

Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Peer Adelt <peer.adelt@hni.uni-paderborn.de>
This commit is contained in:
Bastian Koppelmann 2019-02-13 07:53:55 -08:00
parent 31fe4d35f2
commit 4ba79c47a2
3 changed files with 126 additions and 56 deletions

View file

@ -57,6 +57,21 @@
@r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd
@r2 ....... ..... ..... ... ..... ....... %rs1 %rd
@sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
# *** Privileged Instructions ***
ecall 000000000000 00000 000 00000 1110011
ebreak 000000000001 00000 000 00000 1110011
uret 0000000 00010 00000 000 00000 1110011
sret 0001000 00010 00000 000 00000 1110011
hret 0010000 00010 00000 000 00000 1110011
mret 0011000 00010 00000 000 00000 1110011
wfi 0001000 00101 00000 000 00000 1110011
sfence_vma 0001001 ..... ..... 000 00000 1110011 @sfence_vma
sfence_vm 0001000 00100 ..... 000 00000 1110011 @sfence_vm
# *** RV32I Base Instruction Set ***
lui .................... ..... 0110111 @u
auipc .................... ..... 0010111 @u

View file

@ -0,0 +1,110 @@
/*
* RISC-V translation routines for the RISC-V privileged instructions.
*
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
* Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
* Bastian Koppelmann, kbastian@mail.uni-paderborn.de
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
{
/* always generates U-level ECALL, fixed in do_interrupt handler */
generate_exception(ctx, RISCV_EXCP_U_ECALL);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
}
static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
{
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
}
static bool trans_uret(DisasContext *ctx, arg_uret *a)
{
return false;
}
static bool trans_sret(DisasContext *ctx, arg_sret *a)
{
#ifndef CONFIG_USER_ONLY
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
if (has_ext(ctx, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
} else {
return false;
}
return true;
#else
return false;
#endif
}
static bool trans_hret(DisasContext *ctx, arg_hret *a)
{
return false;
}
static bool trans_mret(DisasContext *ctx, arg_mret *a)
{
#ifndef CONFIG_USER_ONLY
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
#else
return false;
#endif
}
static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
{
#ifndef CONFIG_USER_ONLY
tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
gen_helper_wfi(cpu_env);
return true;
#else
return false;
#endif
}
static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
{
#ifndef CONFIG_USER_ONLY
if (ctx->priv_ver == PRIV_VERSION_1_10_0) {
gen_helper_tlb_flush(cpu_env);
return true;
}
#endif
return false;
}
static bool trans_sfence_vm(DisasContext *ctx, arg_sfence_vm *a)
{
#ifndef CONFIG_USER_ONLY
if (ctx->priv_ver <= PRIV_VERSION_1_09_1) {
gen_helper_tlb_flush(cpu_env);
return true;
}
#endif
return false;
}

View file

@ -772,26 +772,8 @@ static void gen_set_rm(DisasContext *ctx, int rm)
static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
int csr)
{
TCGv source1, dest;
source1 = tcg_temp_new();
dest = tcg_temp_new();
gen_get_gpr(source1, rs1);
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
#ifndef CONFIG_USER_ONLY
/* Extract funct7 value and check whether it matches SFENCE.VMA */
if ((opc == OPC_RISC_ECALL) && ((csr >> 5) == 9)) {
if (ctx->priv_ver == PRIV_VERSION_1_10_0) {
/* sfence.vma */
/* TODO: handle ASID specific fences */
gen_helper_tlb_flush(cpu_env);
return;
} else {
gen_exception_illegal(ctx);
}
}
#endif
switch (opc) {
case OPC_RISC_ECALL:
switch (csr) {
@ -806,50 +788,12 @@ static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
break;
#ifndef CONFIG_USER_ONLY
case 0x002: /* URET */
gen_exception_illegal(ctx);
break;
case 0x102: /* SRET */
if (has_ext(ctx, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
} else {
gen_exception_illegal(ctx);
}
break;
case 0x202: /* HRET */
gen_exception_illegal(ctx);
break;
case 0x302: /* MRET */
gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(NULL, 0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
break;
case 0x7b2: /* DRET */
gen_exception_illegal(ctx);
break;
case 0x105: /* WFI */
tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
gen_helper_wfi(cpu_env);
break;
case 0x104: /* SFENCE.VM */
if (ctx->priv_ver <= PRIV_VERSION_1_09_1) {
gen_helper_tlb_flush(cpu_env);
} else {
gen_exception_illegal(ctx);
}
break;
#endif
default:
gen_exception_illegal(ctx);
break;
}
break;
}
tcg_temp_free(source1);
tcg_temp_free(dest);
}
static void decode_RV32_64C0(DisasContext *ctx)
@ -1152,6 +1096,7 @@ bool decode_insn32(DisasContext *ctx, uint32_t insn);
#include "insn_trans/trans_rva.inc.c"
#include "insn_trans/trans_rvf.inc.c"
#include "insn_trans/trans_rvd.inc.c"
#include "insn_trans/trans_privileged.inc.c"
static void decode_RV32_64G(DisasContext *ctx)
{