diff options
Diffstat (limited to 'target/hppa')
| -rw-r--r-- | target/hppa/int_helper.c | 20 | ||||
| -rw-r--r-- | target/hppa/sys_helper.c | 18 | ||||
| -rw-r--r-- | target/hppa/translate.c | 10 |
3 files changed, 25 insertions, 23 deletions
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 90437a92cd..a667ee380d 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -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 */ diff --git a/target/hppa/sys_helper.c b/target/hppa/sys_helper.c index 208e51c086..22d6c89964 100644 --- a/target/hppa/sys_helper.c +++ b/target/hppa/sys_helper.c @@ -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) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 8a1a8bc3aa..42fa480950 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -44,7 +44,6 @@ typedef struct DisasCond { typedef struct DisasContext { DisasContextBase base; CPUState *cs; - TCGOp *insn_start; uint64_t iaoq_f; uint64_t iaoq_b; @@ -62,6 +61,7 @@ typedef struct DisasContext { int privilege; bool psw_n_nonzero; bool is_pa20; + bool insn_start_updated; #ifdef CONFIG_USER_ONLY MemOp unalign; @@ -300,9 +300,9 @@ void hppa_translate_init(void) static void set_insn_breg(DisasContext *ctx, int breg) { - assert(ctx->insn_start != NULL); - tcg_set_insn_start_param(ctx->insn_start, 2, breg); - ctx->insn_start = NULL; + assert(!ctx->insn_start_updated); + ctx->insn_start_updated = true; + tcg_set_insn_start_param(ctx->base.insn_start, 2, breg); } static DisasCond cond_make_f(void) @@ -4694,7 +4694,7 @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) DisasContext *ctx = container_of(dcbase, DisasContext, base); tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b, 0); - ctx->insn_start = tcg_last_op(); + ctx->insn_start_updated = false; } static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |