From 5331339651dbf081cb78c219f000dab243022de9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 1 May 2024 22:44:12 -0700 Subject: [PATCH] target/s390x: Raise exception from helper_per_branch Drop from argument, since gbea has always been updated with this address. Add ilen argument for setting int_pgm_ilen. Use update_cc_op before calling per_branch. By raising the exception here, we need not call per_check_exception later, which means we can clean up the normal non-exception branch path. Signed-off-by: Richard Henderson Message-ID: <20240502054417.234340-10-richard.henderson@linaro.org> Signed-off-by: Thomas Huth --- target/s390x/helper.h | 2 +- target/s390x/tcg/misc_helper.c | 15 +++++++---- target/s390x/tcg/translate.c | 48 ++++++++++++---------------------- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 96ab71e877..061b379065 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -360,7 +360,7 @@ DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env) DEF_HELPER_3(lra, i64, env, i64, i64) DEF_HELPER_FLAGS_3(per_check_exception, TCG_CALL_NO_WG, void, env, i64, i32) -DEF_HELPER_FLAGS_3(per_branch, TCG_CALL_NO_RWG, void, env, i64, i64) +DEF_HELPER_FLAGS_3(per_branch, TCG_CALL_NO_WG, void, env, i64, i32) DEF_HELPER_FLAGS_2(per_ifetch, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_FLAGS_1(per_store_real, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c index 3f94f71437..974d14703c 100644 --- a/target/s390x/tcg/misc_helper.c +++ b/target/s390x/tcg/misc_helper.c @@ -625,13 +625,18 @@ static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr) } } -void HELPER(per_branch)(CPUS390XState *env, uint64_t from, uint64_t to) +void HELPER(per_branch)(CPUS390XState *env, uint64_t dest, uint32_t ilen) { - if (!(env->cregs[9] & PER_CR9_CONTROL_BRANCH_ADDRESS) - || get_per_in_range(env, to)) { - env->per_address = from; - env->per_perc_atmid = PER_CODE_EVENT_BRANCH | get_per_atmid(env); + if ((env->cregs[9] & PER_CR9_CONTROL_BRANCH_ADDRESS) + && !get_per_in_range(env, dest)) { + return; } + + env->psw.addr = dest; + env->int_pgm_ilen = ilen; + env->per_address = env->gbea; + env->per_perc_atmid = PER_CODE_EVENT_BRANCH | get_per_atmid(env); + per_raise_exception_log(env); } void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 10d5e87bb4..de029185e0 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -341,12 +341,11 @@ static void update_psw_addr(DisasContext *s) tcg_gen_movi_i64(psw_addr, s->base.pc_next); } -static void per_branch(DisasContext *s, bool to_next) +static void per_branch(DisasContext *s, TCGv_i64 dest) { #ifndef CONFIG_USER_ONLY if (s->base.tb->flags & FLAG_MASK_PER_BRANCH) { - TCGv_i64 next_pc = to_next ? tcg_constant_i64(s->pc_tmp) : psw_addr; - gen_helper_per_branch(tcg_env, gbea, next_pc); + gen_helper_per_branch(tcg_env, dest, tcg_constant_i32(s->ilen)); } #endif } @@ -635,9 +634,6 @@ static void gen_op_calc_cc(DisasContext *s) static bool use_goto_tb(DisasContext *s, uint64_t dest) { - if (unlikely(s->base.tb->flags & FLAG_MASK_PER_BRANCH)) { - return false; - } return translator_use_goto_tb(&s->base, dest); } @@ -1079,37 +1075,38 @@ struct DisasInsn { static DisasJumpType help_goto_direct(DisasContext *s, uint64_t dest) { + update_cc_op(s); per_breaking_event(s); + per_branch(s, tcg_constant_i64(dest)); + if (dest == s->pc_tmp) { - per_branch(s, true); return DISAS_NEXT; } if (use_goto_tb(s, dest)) { - update_cc_op(s); tcg_gen_goto_tb(0); tcg_gen_movi_i64(psw_addr, dest); tcg_gen_exit_tb(s->base.tb, 0); return DISAS_NORETURN; } else { tcg_gen_movi_i64(psw_addr, dest); - per_branch(s, false); - return DISAS_PC_UPDATED; + return DISAS_PC_CC_UPDATED; } } static DisasJumpType help_goto_indirect(DisasContext *s, TCGv_i64 dest) { + update_cc_op(s); per_breaking_event(s); tcg_gen_mov_i64(psw_addr, dest); - per_branch(s, false); - return DISAS_PC_UPDATED; + per_branch(s, psw_addr); + return DISAS_PC_CC_UPDATED; } static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, bool is_imm, int imm, TCGv_i64 cdest) { uint64_t dest = s->base.pc_next + (int64_t)imm * 2; - TCGLabel *lab, *over; + TCGLabel *lab; /* Take care of the special cases first. */ if (c->cond == TCG_COND_NEVER) { @@ -1143,12 +1140,6 @@ static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, * which avoids an otherwise unnecessary spill to the stack. */ lab = gen_new_label(); - if (s->base.tb->flags & FLAG_MASK_PER_BRANCH) { - over = gen_new_label(); - } else { - over = NULL; - } - if (c->is_64) { tcg_gen_brcond_i64(tcg_invert_cond(c->cond), c->u.s64.a, c->u.s64.b, lab); @@ -1164,13 +1155,11 @@ static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, } else { tcg_gen_mov_i64(psw_addr, cdest); } - per_branch(s, false); + per_branch(s, psw_addr); if (is_imm && use_goto_tb(s, dest)) { tcg_gen_goto_tb(0); tcg_gen_exit_tb(s->base.tb, 0); - } else if (over) { - tcg_gen_br(over); } else { tcg_gen_lookup_and_goto_ptr(); } @@ -1182,15 +1171,9 @@ static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, if (use_goto_tb(s, s->pc_tmp)) { tcg_gen_goto_tb(1); tcg_gen_exit_tb(s->base.tb, 1); + return DISAS_NORETURN; } - - if (over) { - gen_set_label(over); - return DISAS_PC_UPDATED; - } - - tcg_gen_lookup_and_goto_ptr(); - return DISAS_NORETURN; + return DISAS_PC_CC_UPDATED; } /* ====================================================================== */ @@ -6372,7 +6355,8 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) } #ifndef CONFIG_USER_ONLY - if (s->base.tb->flags & FLAG_MASK_PER) { + if (s->base.tb->flags & (FLAG_MASK_PER_STORE_REAL | + FLAG_MASK_PER_IFETCH)) { TCGv_i64 next_pc = psw_addr; if (ret == DISAS_NEXT || ret == DISAS_TOO_MANY) { @@ -6402,7 +6386,7 @@ static void s390x_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->cc_op = CC_OP_DYNAMIC; dc->ex_value = dc->base.tb->cs_base; - dc->exit_to_mainloop = (dc->base.tb->flags & FLAG_MASK_PER) || dc->ex_value; + dc->exit_to_mainloop = dc->ex_value; } static void s390x_tr_tb_start(DisasContextBase *db, CPUState *cs)