On Wed, 2026-09-09 at 11:48 -0300, Daniel Henrique Barboza wrote:
> From: Chao Liu <[email protected]>
> 
> RISC-V Debug Specification:
> https://github.com/riscv/riscv-debug-spec/releases/tag/1.0
> 
> Add DRET decode/translate and a helper to leave Debug Mode and return
> to dpc. Executing DRET outside Debug Mode raises illegal instruction.
> 
> Signed-off-by: Chao Liu <[email protected]>
> Reviewed-by: Daniel Henrique Barboza
> <[email protected]>
> Tested-by: Tao Tang <[email protected]>
> Signed-off-by: Daniel Henrique Barboza
> <[email protected]>

Reviewed-by: Alistair Francis <[email protected]>

Alistair

> ---
>  target/riscv/helper.h                          |  1 +
>  target/riscv/insn32.decode                     |  1 +
>  .../tcg/insn_trans/trans_privileged.c.inc      | 18
> ++++++++++++++++++
>  target/riscv/tcg/op_helper.c                   | 16 ++++++++++++++++
>  4 files changed, 36 insertions(+)
> 
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 4fc2d3a155..b4c47d0738 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -132,6 +132,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl,
> tl, tl)
>  #ifndef CONFIG_USER_ONLY
>  DEF_HELPER_1(sret, tl, env)
>  DEF_HELPER_1(mret, tl, env)
> +DEF_HELPER_1(dret, tl, env)
>  DEF_HELPER_1(mnret, tl, env)
>  DEF_HELPER_1(ctr_clear, void, env)
>  DEF_HELPER_1(wfi, void, env)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index aa02dae3c9..46b00411ff 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -118,6 +118,7 @@ sctrclr     000100000100     00000 000 00000
> 1110011
>  uret        0000000    00010 00000 000 00000 1110011
>  sret        0001000    00010 00000 000 00000 1110011
>  mret        0011000    00010 00000 000 00000 1110011
> +dret        0111101    10010 00000 000 00000 1110011
>  wfi         0001000    00101 00000 000 00000 1110011
>  sfence_vma  0001001    ..... ..... 000 00000 1110011 @sfence_vma
>  
> diff --git a/target/riscv/tcg/insn_trans/trans_privileged.c.inc
> b/target/riscv/tcg/insn_trans/trans_privileged.c.inc
> index a8eaccef67..4e57901880 100644
> --- a/target/riscv/tcg/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/tcg/insn_trans/trans_privileged.c.inc
> @@ -125,6 +125,24 @@ static bool trans_mret(DisasContext *ctx,
> arg_mret *a)
>  #endif
>  }
>  
> +static bool trans_dret(DisasContext *ctx, arg_dret *a)
> +{
> +#ifndef CONFIG_USER_ONLY
> +    if (!ctx->cfg_ptr->ext_sdext) {
> +        return false;
> +    }
> +    decode_save_opc(ctx, 0);
> +    translator_io_start(&ctx->base);
> +    gen_update_pc(ctx, 0);
> +    gen_helper_dret(cpu_pc, tcg_env);
> +    exit_tb(ctx); /* no chaining */
> +    ctx->base.is_jmp = DISAS_NORETURN;
> +    return true;
> +#else
> +    return false;
> +#endif
> +}
> +
>  static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
>  {
>  #ifndef CONFIG_USER_ONLY
> diff --git a/target/riscv/tcg/op_helper.c
> b/target/riscv/tcg/op_helper.c
> index 3e94005d2b..54269efee1 100644
> --- a/target/riscv/tcg/op_helper.c
> +++ b/target/riscv/tcg/op_helper.c
> @@ -473,6 +473,22 @@ target_ulong helper_mret(CPURISCVState *env)
>      return retpc;
>  }
>  
> +target_ulong helper_dret(CPURISCVState *env)
> +{
> +    uintptr_t ra = GETPC();
> +#ifdef CONFIG_USER_ONLY
> +    riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
> +    return 0;
> +#else
> +    if (!riscv_cpu_cfg(env)->ext_sdext || !env->debug_mode) {
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
> +    }
> +    target_ulong retpc = env->dpc & get_xepc_mask(env);
> +    riscv_cpu_leave_debug_mode(env);
> +    return retpc;
> +#endif
> +}
> +
>  target_ulong helper_mnret(CPURISCVState *env)
>  {
>      target_ulong retpc = env->mnepc;

Reply via email to