diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 357dac39c5..0c78b4b0b0 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -165,10 +165,6 @@ void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip, { E2KCrs crs; - if ((env->pcsp.size - env->pcsp.index) <= (sizeof(E2KCrs) * 2)) { - raise_exception_ra(env, E2K_EXCP_CHAIN_STACK_BOUNDS, GETPC()); - } - crs.cr0_lo = env->pregs; crs.cr0_hi = ret_ip & ~7; crs.cr1.wbs = base / 2; @@ -219,6 +215,15 @@ static inline void do_call(CPUE2KState *env, int wbs, target_ulong ret_ip) reset_ctprs(env); } +#ifdef CONFIG_USER_ONLY +void HELPER(expand_proc_chain_stack)(CPUE2KState *env) +{ + if ((env->pcsp.size - env->pcsp.index) <= (sizeof(E2KCrs) * 2)) { + raise_exception_ra(env, E2K_EXCP_CHAIN_STACK_BOUNDS, GETPC()); + } +} +#endif /* CONFIG_USER_ONLY */ + void HELPER(call)(CPUE2KState *env, uint64_t ctpr_raw, int call_wbs, target_ulong pc_next) { diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 7d756d397b..a12b6c199d 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -2,6 +2,9 @@ #define vec i128 DEF_HELPER_2(raise_exception, noreturn, env, int) +#ifdef CONFIG_USER_ONLY +DEF_HELPER_1(expand_proc_chain_stack, void, env) +#endif DEF_HELPER_4(call, void, env, i64, int, tl) DEF_HELPER_4(icalld, void, env, tl, int, tl) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 30c79ccbf7..6b0a141cf2 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -6787,6 +6787,14 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) pc_next = do_decode(ctx, cs); ctx->loop_mode = (ctx->bundle.hs & (1 << 10)) != 0; if (validate_bundle(ctx)) { +#ifdef CONFIG_USER_ONLY + if (ctx->cs1.type == CS1_CALL) { + gen_save_cpu_state(ctx); + // NOTE: Keep this call before any state modification + // so bundle can be safely restarted. + gen_helper_expand_proc_chain_stack(tcg_env); + } +#endif /* CONFIG_USER_ONLY */ gen_setwd(ctx); gen_cs0(ctx); gen_cs1(ctx);