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:
parent
619f6891ff
commit
5331339651
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user