target/hppa: Manage PSW_X and PSW_B in translator

PSW_X is cleared after every instruction, and only set by RFI.
PSW_B is cleared after every non-branch, or branch not taken,
and only set by taken branches.  We can clear both bits with a
single store, at most once per TB.  Taken branches set PSW_B,
at most once per TB.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-04-16 20:43:00 -07:00
parent ebc9401a40
commit d27fe7c3af
2 changed files with 57 additions and 3 deletions

View file

@ -50,7 +50,7 @@ static vaddr hppa_cpu_get_pc(CPUState *cs)
void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
uint64_t *pcsbase, uint32_t *pflags)
{
uint32_t flags = env->psw_n * PSW_N;
uint32_t flags = 0;
uint64_t cs_base = 0;
/*
@ -80,11 +80,14 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
cs_base |= env->iaoq_b & ~TARGET_PAGE_MASK;
}
/* ??? E, T, H, L bits need to be here, when implemented. */
flags |= env->psw_n * PSW_N;
flags |= env->psw_xb;
flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
#ifdef CONFIG_USER_ONLY
flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
#else
/* ??? E, T, H, L, B bits need to be here, when implemented. */
flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
if ((env->sr[4] == env->sr[5])
& (env->sr[4] == env->sr[6])
& (env->sr[4] == env->sr[7])) {
@ -103,6 +106,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
/* IAQ is always up-to-date before goto_tb. */
cpu->env.psw_n = (tb->flags & PSW_N) != 0;
cpu->env.psw_xb = tb->flags & (PSW_X | PSW_B);
}
static void hppa_restore_state_to_opc(CPUState *cs,