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 <richard.henderson@linaro.org>
Message-ID: <20240502054417.234340-10-richard.henderson@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Richard Henderson 2024-05-01 22:44:12 -07:00 committed by Thomas Huth
parent 619f6891ff
commit 5331339651
3 changed files with 27 additions and 38 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)