target/hppa: Fix IIAOQ, IIASQ for pa2.0

The contents of IIAOQ depend on PSW_W.
Follow the text in "Interruption Instruction Address Queues",
pages 2-13 through 2-15.

Tested-by: Sven Schnelle <svens@stackframe.org>
Tested-by: Helge Deller <deller@gmx.de>
Reported-by: Sven Schnelle <svens@stackframe.org>
Fixes: b10700d826 ("target/hppa: Update IIAOQ, IIASQ for pa2.0")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
master
Richard Henderson 2024-04-01 14:52:39 -10:00
parent 2ee80bce4f
commit 26d937237f
2 changed files with 20 additions and 18 deletions

View File

@ -107,14 +107,10 @@ void hppa_cpu_do_interrupt(CPUState *cs)
/* step 3 */
/*
* For pa1.x, IIASQ is simply a copy of IASQ.
* For pa2.0, IIASQ is the top bits of the virtual address,
* or zero if translation is disabled.
* IIASQ is the top bits of the virtual address, or zero if translation
* is disabled -- with PSW_W == 0, this will reduce to the space.
*/
if (!hppa_is_pa20(env)) {
env->cr[CR_IIASQ] = env->iasq_f >> 32;
env->cr_back[0] = env->iasq_b >> 32;
} else if (old_psw & PSW_C) {
if (old_psw & PSW_C) {
env->cr[CR_IIASQ] =
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
env->cr_back[0] =
@ -123,8 +119,14 @@ void hppa_cpu_do_interrupt(CPUState *cs)
env->cr[CR_IIASQ] = 0;
env->cr_back[0] = 0;
}
env->cr[CR_IIAOQ] = env->iaoq_f;
env->cr_back[1] = env->iaoq_b;
/* IIAOQ is the full offset for wide mode, or 32 bits for narrow mode. */
if (old_psw & PSW_W) {
env->cr[CR_IIAOQ] = env->iaoq_f;
env->cr_back[1] = env->iaoq_b;
} else {
env->cr[CR_IIAOQ] = (uint32_t)env->iaoq_f;
env->cr_back[1] = (uint32_t)env->iaoq_b;
}
if (old_psw & PSW_Q) {
/* step 5 */

View File

@ -78,21 +78,21 @@ target_ulong HELPER(swap_system_mask)(CPUHPPAState *env, target_ulong nsm)
void HELPER(rfi)(CPUHPPAState *env)
{
env->iasq_f = (uint64_t)env->cr[CR_IIASQ] << 32;
env->iasq_b = (uint64_t)env->cr_back[0] << 32;
env->iaoq_f = env->cr[CR_IIAOQ];
env->iaoq_b = env->cr_back[1];
uint64_t mask;
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
/*
* For pa2.0, IIASQ is the top bits of the virtual address.
* To recreate the space identifier, remove the offset bits.
* For pa1.x, the mask reduces to no change to space.
*/
if (hppa_is_pa20(env)) {
env->iasq_f &= ~env->iaoq_f;
env->iasq_b &= ~env->iaoq_b;
}
mask = gva_offset_mask(env->psw);
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
env->iaoq_f = env->cr[CR_IIAOQ];
env->iaoq_b = env->cr_back[1];
env->iasq_f = (env->cr[CR_IIASQ] << 32) & ~(env->iaoq_f & mask);
env->iasq_b = (env->cr_back[0] << 32) & ~(env->iaoq_b & mask);
}
static void getshadowregs(CPUHPPAState *env)