diff options
Diffstat (limited to 'target/hppa/translate.c')
| -rw-r--r-- | target/hppa/translate.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/target/hppa/translate.c b/target/hppa/translate.c index dc04f9f3c0..0d0d1bc99b 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -73,6 +73,7 @@ typedef struct DisasContext { /* IAOQ_Front at entry to TB. */ uint64_t iaoq_first; + uint64_t gva_offset_mask; DisasCond null_cond; TCGLabel *null_lab; @@ -1577,7 +1578,7 @@ static void form_gva(DisasContext *ctx, TCGv_i64 *pgva, TCGv_i64 *pofs, *pofs = ofs; *pgva = addr = tcg_temp_new_i64(); tcg_gen_andi_i64(addr, modify <= 0 ? ofs : base, - gva_offset_mask(ctx->tb_flags)); + ctx->gva_offset_mask); #ifndef CONFIG_USER_ONLY if (!is_phys) { tcg_gen_or_i64(addr, addr, space_select(ctx, sp, base)); @@ -4593,19 +4594,37 @@ static bool trans_diag_getshadowregs_pa1(DisasContext *ctx, arg_empty *a) return !ctx->is_pa20 && do_getshadowregs(ctx); } -static bool trans_diag_getshadowregs_pa2(DisasContext *ctx, arg_empty *a) +static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a) { - return ctx->is_pa20 && do_getshadowregs(ctx); + return !ctx->is_pa20 && do_putshadowregs(ctx); } -static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a) +static bool trans_diag_mfdiag(DisasContext *ctx, arg_diag_mfdiag *a) { - return !ctx->is_pa20 && do_putshadowregs(ctx); + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + TCGv_i64 dest = dest_gpr(ctx, a->rt); + tcg_gen_ld_i64(dest, tcg_env, + offsetof(CPUHPPAState, dr[a->dr])); + save_gpr(ctx, a->rt, dest); + return nullify_end(ctx); } -static bool trans_diag_putshadowregs_pa2(DisasContext *ctx, arg_empty *a) +static bool trans_diag_mtdiag(DisasContext *ctx, arg_diag_mtdiag *a) { - return ctx->is_pa20 && do_putshadowregs(ctx); + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + tcg_gen_st_i64(load_gpr(ctx, a->r1), tcg_env, + offsetof(CPUHPPAState, dr[a->dr])); +#ifndef CONFIG_USER_ONLY + if (ctx->is_pa20 && (a->dr == 2)) { + /* Update gva_offset_mask from the new value of %dr2 */ + gen_helper_update_gva_offset_mask(tcg_env); + /* Exit to capture the new value for the next TB. */ + ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT; + } +#endif + return nullify_end(ctx); } static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a) @@ -4625,6 +4644,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->tb_flags = ctx->base.tb->flags; ctx->is_pa20 = hppa_is_pa20(cpu_env(cs)); ctx->psw_xb = ctx->tb_flags & (PSW_X | PSW_B); + ctx->gva_offset_mask = cpu_env(cs)->gva_offset_mask; #ifdef CONFIG_USER_ONLY ctx->privilege = PRIV_USER; |