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

These registers have a different format for pa2.0.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-10-27 04:10:45 -07:00
parent 8a02b9a68e
commit b10700d826
2 changed files with 38 additions and 18 deletions

View File

@ -102,11 +102,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
int i = cs->exception_index;
target_ulong iaoq_f = env->iaoq_f;
target_ulong iaoq_b = env->iaoq_b;
uint64_t iasq_f = env->iasq_f;
uint64_t iasq_b = env->iasq_b;
target_ulong old_psw;
uint64_t old_psw;
/* As documented in pa2.0 -- interruption handling. */
/* step 1 */
@ -118,10 +114,25 @@ void hppa_cpu_do_interrupt(CPUState *cs)
(i == EXCP_HPMC ? PSW_M : 0));
/* step 3 */
env->cr[CR_IIASQ] = iasq_f >> 32;
env->cr_back[0] = iasq_b >> 32;
env->cr[CR_IIAOQ] = iaoq_f;
env->cr_back[1] = iaoq_b;
/*
* 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.
*/
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) {
env->cr[CR_IIASQ] =
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
env->cr_back[0] =
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32;
} else {
env->cr[CR_IIASQ] = 0;
env->cr_back[0] = 0;
}
env->cr[CR_IIAOQ] = env->iaoq_f;
env->cr_back[1] = env->iaoq_b;
if (old_psw & PSW_Q) {
/* step 5 */
@ -154,14 +165,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
/* ??? An alternate fool-proof method would be to store the
instruction data into the unwind info. That's probably
a bit too much in the way of extra storage required. */
vaddr vaddr;
hwaddr paddr;
vaddr vaddr = env->iaoq_f & -4;
hwaddr paddr = vaddr;
paddr = vaddr = iaoq_f & -4;
if (old_psw & PSW_C) {
int prot, t;
vaddr = hppa_form_gva_psw(old_psw, iasq_f, vaddr);
vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr);
t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
0, &paddr, &prot, NULL);
if (t >= 0) {
@ -191,14 +201,14 @@ void hppa_cpu_do_interrupt(CPUState *cs)
/* step 7 */
if (i == EXCP_TOC) {
env->iaoq_f = FIRMWARE_START;
env->iaoq_f = hppa_form_gva(env, 0, FIRMWARE_START);
/* help SeaBIOS and provide iaoq_b and iasq_back in shadow regs */
env->gr[24] = env->cr_back[0];
env->gr[25] = env->cr_back[1];
} else {
env->iaoq_f = env->cr[CR_IVA] + 32 * i;
env->iaoq_f = hppa_form_gva(env, 0, env->cr[CR_IVA] + 32 * i);
}
env->iaoq_b = env->iaoq_f + 4;
env->iaoq_b = hppa_form_gva(env, 0, env->iaoq_f + 4);
env->iasq_f = 0;
env->iasq_b = 0;
@ -251,8 +261,8 @@ void hppa_cpu_do_interrupt(CPUState *cs)
qemu_log("INT %6d: %s @ " TARGET_FMT_lx "," TARGET_FMT_lx
" -> " TARGET_FMT_lx " " TARGET_FMT_lx "\n",
++count, name,
hppa_form_gva(env, iasq_f, iaoq_f),
hppa_form_gva(env, iasq_b, iaoq_b),
hppa_form_gva(env, env->iasq_f, env->iaoq_f),
hppa_form_gva(env, env->iasq_b, env->iaoq_b),
env->iaoq_f,
hppa_form_gva(env, (uint64_t)env->cr[CR_ISR] << 32,
env->cr[CR_IOR]));

View File

@ -80,6 +80,16 @@ void HELPER(rfi)(CPUHPPAState *env)
env->iasq_b = (uint64_t)env->cr_back[0] << 32;
env->iaoq_f = env->cr[CR_IIAOQ];
env->iaoq_b = env->cr_back[1];
/*
* For pa2.0, IIASQ is the top bits of the virtual address.
* To recreate the space identifier, remove the offset bits.
*/
if (hppa_is_pa20(env)) {
env->iasq_f &= ~env->iaoq_f;
env->iasq_b &= ~env->iaoq_b;
}
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
}