From patchwork Wed Nov 11 00:27:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 542686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6255214027C for ; Wed, 11 Nov 2015 11:41:34 +1100 (AEDT) Received: from localhost ([::1]:36502 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZwJTU-0005cT-Vn for incoming@patchwork.ozlabs.org; Tue, 10 Nov 2015 19:41:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37606) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZwJIS-0001VF-0e for qemu-devel@nongnu.org; Tue, 10 Nov 2015 19:29:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZwJIO-0004BR-2w for qemu-devel@nongnu.org; Tue, 10 Nov 2015 19:29:55 -0500 Received: from gate.crashing.org ([63.228.1.57]:48630) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZwJIN-0004BE-Ac; Tue, 10 Nov 2015 19:29:52 -0500 Received: from pasglop.ozlabs.ibm.com. (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.13.8) with ESMTP id tAB0Sb2Z024031; Tue, 10 Nov 2015 18:29:28 -0600 From: Benjamin Herrenschmidt To: qemu-ppc@nongnu.org Date: Wed, 11 Nov 2015 11:27:34 +1100 Message-Id: <1447201710-10229-22-git-send-email-benh@kernel.crashing.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1447201710-10229-1-git-send-email-benh@kernel.crashing.org> References: <1447201710-10229-1-git-send-email-benh@kernel.crashing.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 63.228.1.57 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 21/77] ppc: Rework generation of priv and inval interrupts X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Recent server processors use the Hypervisor Emulation Assistance interrupt for illegal instructions and *some* type of SPR accesses. Also the code was always generating inval instructions even for priv violations due to setting the wrong flags Finally, the checking for PR/HV was open coded everywhere. This reworks it all, using little helper macros for checking, and adding the HV interrupt (which gets converted back to program check in the slow path of excp_helper.c on CPUs that don't want it). Signed-off-by: Benjamin Herrenschmidt --- linux-user/main.c | 1 + target-ppc/excp_helper.c | 19 ++ target-ppc/translate.c | 678 ++++++++++++++++++++--------------------------- 3 files changed, 302 insertions(+), 396 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 8acfe0f..beb621f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1654,6 +1654,7 @@ void cpu_loop(CPUPPCState *env) queue_signal(env, info.si_signo, &info); break; case POWERPC_EXCP_PROGRAM: /* Program exception */ + case POWERPC_EXCP_HV_EMU: /* HV emulation */ /* XXX: check this */ switch (env->error_code & ~0xF) { case POWERPC_EXCP_FP: diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 716b27b..80a70f4 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -127,6 +127,19 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) ail = 0; } + /* Hypervisor emulation assistance interrupt only exists on server + * arch 2.05 server or later. We also don't want to generate it if + * we don't have HVB in msr_mask (PAPR mode). + */ + if (excp == POWERPC_EXCP_HV_EMU +#if defined(TARGET_PPC64) + && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB)) +#endif /* defined(TARGET_PPC64) */ + + ) { + excp = POWERPC_EXCP_PROGRAM; + } + switch (excp) { case POWERPC_EXCP_NONE: /* Should never happen */ @@ -249,6 +262,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; } goto store_current; + case POWERPC_EXCP_HV_EMU: + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + goto store_current; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ goto store_current; case POWERPC_EXCP_SYSCALL: /* System call exception */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e8bbd59..3f657b1 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -321,7 +321,19 @@ static inline void gen_debug_exception(DisasContext *ctx) static inline void gen_inval_exception(DisasContext *ctx, uint32_t error) { - gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error); + /* Will be converted to program check if needed */ + gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error); +} + +static inline void gen_priv_exception(DisasContext *ctx, uint32_t error) +{ + gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error); +} + +static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error) +{ + /* Will be converted to program check if needed */ + gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error); } /* Stop translation */ @@ -362,6 +374,20 @@ typedef struct opcode_t { const char *oname; } opcode_t; +/* Helpers for priv. check */ +#define GEN_PRIV do { gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } while(0) + +#if defined(CONFIG_USER_ONLY) +#define CHK_HV GEN_PRIV +#define CHK_SV GEN_PRIV +#else +#define CHK_HV do { if (unlikely(ctx->pr || !ctx->hv)) GEN_PRIV; } while(0) +#define CHK_SV do { if (unlikely(ctx->pr)) GEN_PRIV; } while(0) +#endif + +#define CHK_NONE + + /*****************************************************************************/ /*** Instruction decoding ***/ #define EXTRACT_HELPER(name, shift, nb) \ @@ -2950,7 +2976,7 @@ static void gen_lq(DisasContext *ctx) bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; if (!legal_in_user_mode && ctx->pr) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } @@ -3073,7 +3099,7 @@ static void gen_std(DisasContext *ctx) bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; if (!legal_in_user_mode && ctx->pr) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } @@ -4086,13 +4112,10 @@ static void gen_mcrf(DisasContext *ctx) static void gen_rfi(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else /* Restore CPU state */ - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_update_cfar(ctx, ctx->nip); gen_helper_rfi(cpu_env); gen_sync_exception(ctx); @@ -4103,13 +4126,10 @@ static void gen_rfi(DisasContext *ctx) static void gen_rfid(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else /* Restore CPU state */ - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_update_cfar(ctx, ctx->nip); gen_helper_rfid(cpu_env); gen_sync_exception(ctx); @@ -4119,13 +4139,10 @@ static void gen_rfid(DisasContext *ctx) static void gen_hrfid(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else /* Restore CPU state */ - if (unlikely(!ctx->hv)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_HV; gen_helper_hrfid(cpu_env); gen_sync_exception(ctx); #endif @@ -4288,15 +4305,8 @@ static void gen_mfcr(DisasContext *ctx) /* mfmsr */ static void gen_mfmsr(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr); -#endif } static void spr_noaccess(DisasContext *ctx, int gprn, int sprn) @@ -4340,7 +4350,7 @@ static inline void gen_op_mfspr(DisasContext *ctx) printf("Trying to read privileged spr %d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); } - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); } } else { /* Not defined */ @@ -4348,7 +4358,25 @@ static inline void gen_op_mfspr(DisasContext *ctx) TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); printf("Trying to read invalid spr %d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR); + + /* The behaviour depends on MSR:PR and SPR# bit 0x10, + * it can generate a priv, a hv emu or a no-op + */ + if (sprn & 0x10) { + if (ctx->pr) { + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } + } else { + if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) { + gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } + } +#if !defined(CONFIG_USER_ONLY) + /* HV priv */ + if (ctx->spr_cb[sprn].hea_read) { + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } +#endif } } @@ -4395,13 +4423,9 @@ static void gen_mtcrf(DisasContext *ctx) #if defined(TARGET_PPC64) static void gen_mtmsrd(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; + +#if !defined(CONFIG_USER_ONLY) if (ctx->opcode & 0x00010000) { /* Special form that does not need any synchronisation */ TCGv t0 = tcg_temp_new(); @@ -4420,20 +4444,16 @@ static void gen_mtmsrd(DisasContext *ctx) /* Note that mtmsr is not always defined as context-synchronizing */ gen_stop_exception(ctx); } -#endif +#endif /* !defined(CONFIG_USER_ONLY) */ } -#endif +#endif /* defined(TARGET_PPC64) */ static void gen_mtmsr(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } - if (ctx->opcode & 0x00010000) { + CHK_SV; + +#if !defined(CONFIG_USER_ONLY) + if (ctx->opcode & 0x00010000) { /* Special form that does not need any synchronisation */ TCGv t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE)); @@ -4488,7 +4508,7 @@ static void gen_mtspr(DisasContext *ctx) TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); printf("Trying to write privileged spr %d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); } } else { /* Not defined */ @@ -4496,7 +4516,25 @@ static void gen_mtspr(DisasContext *ctx) TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); printf("Trying to write invalid spr %d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR); + + /* The behaviour depends on MSR:PR and SPR# bit 0x10, + * it can generate a priv, a hv emu or a no-op + */ + if (sprn & 0x10) { + if (ctx->pr) { + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } + } else { + if (ctx->pr || sprn == 0) { + gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } + } +#if !defined(CONFIG_USER_ONLY) + /* HV priv */ + if (ctx->spr_cb[sprn].hea_write) { + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); + } +#endif } } @@ -4518,13 +4556,11 @@ static void gen_dcbf(DisasContext *ctx) static void gen_dcbi(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv EA, val; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; EA = tcg_temp_new(); gen_set_access_type(ctx, ACCESS_CACHE); gen_addr_reg_index(ctx, EA); @@ -4534,7 +4570,7 @@ static void gen_dcbi(DisasContext *ctx) gen_qemu_st8(ctx, val, EA); tcg_temp_free(val); tcg_temp_free(EA); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* dcdst */ @@ -4655,72 +4691,64 @@ static void gen_dcba(DisasContext *ctx) static void gen_mfsr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_const_tl(SR(ctx->opcode)); gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mfsrin */ static void gen_mfsrin(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtsr */ static void gen_mtsr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_const_tl(SR(ctx->opcode)); gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtsrin */ static void gen_mtsrin(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; + t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } #if defined(TARGET_PPC64) @@ -4730,115 +4758,101 @@ static void gen_mtsrin(DisasContext *ctx) static void gen_mfsr_64b(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_const_tl(SR(ctx->opcode)); gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mfsrin */ static void gen_mfsrin_64b(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtsr */ static void gen_mtsr_64b(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_const_tl(SR(ctx->opcode)); gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtsrin */ static void gen_mtsrin_64b(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* slbmte */ static void gen_slbmte(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; + gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_slbmfee(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; + gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_slbmfev(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; + gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } #endif /* defined(TARGET_PPC64) */ @@ -4849,40 +4863,34 @@ static void gen_slbmfev(DisasContext *ctx) static void gen_tlbia(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr || !ctx->hv)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_HV; + gen_helper_tlbia(cpu_env); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbiel */ static void gen_tlbiel(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr || !ctx->hv)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbie */ static void gen_tlbie(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr || !ctx->hv)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_HV; + if (NARROW_MODE(ctx)) { TCGv t0 = tcg_temp_new(); tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]); @@ -4891,56 +4899,52 @@ static void gen_tlbie(DisasContext *ctx) } else { gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbsync */ static void gen_tlbsync(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + GEN_PRIV; +#else + CHK_HV; + /* tlbsync is a nop for server, ptesync handles delayed tlb flush, * embedded however needs to deal with tlbsync. We don't try to be * fancy and swallow the overhead of checking for both. */ gen_check_tlb_flush(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } #if defined(TARGET_PPC64) + /* slbia */ static void gen_slbia(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + gen_helper_slbia(cpu_env); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* slbie */ static void gen_slbie(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } -#endif + +#endif /* defined(TARGET_PPC64) */ /*** External control ***/ /* Optional: */ @@ -5639,14 +5643,11 @@ static void gen_esa(DisasContext *ctx) static void gen_mfrom(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* 602 - 603 - G2 TLB management */ @@ -5655,28 +5656,22 @@ static void gen_mfrom(DisasContext *ctx) static void gen_tlbld_6xx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbli */ static void gen_tlbli_6xx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* 74xx TLB management */ @@ -5685,28 +5680,22 @@ static void gen_tlbli_6xx(DisasContext *ctx) static void gen_tlbld_74xx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbli */ static void gen_tlbli_74xx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* POWER instructions not in PowerPC 601 */ @@ -5720,15 +5709,12 @@ static void gen_clf(DisasContext *ctx) /* cli */ static void gen_cli(DisasContext *ctx) { - /* Cache line invalidate: privileged and treated as no-op */ #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } -#endif + /* Cache line invalidate: privileged and treated as no-op */ + CHK_SV; +#endif /* defined(CONFIG_USER_ONLY) */ } /* dclst */ @@ -5740,15 +5726,13 @@ static void gen_dclst(DisasContext *ctx) static void gen_mfsri(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); tcg_gen_shri_tl(t0, t0, 28); @@ -5757,38 +5741,34 @@ static void gen_mfsri(DisasContext *ctx) tcg_temp_free(t0); if (ra != 0 && ra != rd) tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_rac(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_rfsvc(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + gen_helper_rfsvc(cpu_env); gen_sync_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* svc is not implemented for now */ @@ -5941,18 +5921,16 @@ static void gen_mfapidi(DisasContext *ctx) static void gen_tlbiva(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* All 405 MAC instructions are translated here */ @@ -6174,38 +6152,34 @@ GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C); static void gen_mfdcr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv dcrn; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); dcrn = tcg_const_tl(SPR(ctx->opcode)); gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn); tcg_temp_free(dcrn); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtdcr */ static void gen_mtdcr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else TCGv dcrn; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + + CHK_SV; /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); dcrn = tcg_const_tl(SPR(ctx->opcode)); gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(dcrn); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mfdcrx */ @@ -6213,18 +6187,15 @@ static void gen_mtdcr(DisasContext *ctx) static void gen_mfdcrx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)]); /* Note: Rc update flag set leads to undefined state of Rc0 */ -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mtdcrx */ @@ -6232,18 +6203,15 @@ static void gen_mfdcrx(DisasContext *ctx) static void gen_mtdcrx(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); - return; - } + CHK_SV; /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); /* Note: Rc update flag set leads to undefined state of Rc0 */ -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* mfdcrux (PPC 460) : user-mode access to DCR */ @@ -6269,28 +6237,19 @@ static void gen_mtdcrux(DisasContext *ctx) /* dccci */ static void gen_dccci(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* interpreted as no-op */ -#endif } /* dcread */ static void gen_dcread(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv EA, val; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; gen_set_access_type(ctx, ACCESS_CACHE); EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); @@ -6299,7 +6258,7 @@ static void gen_dcread(DisasContext *ctx) tcg_temp_free(val); tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA); tcg_temp_free(EA); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* icbt */ @@ -6314,60 +6273,40 @@ static void gen_icbt_40x(DisasContext *ctx) /* iccci */ static void gen_iccci(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* interpreted as no-op */ -#endif } /* icread */ static void gen_icread(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); -#else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* interpreted as no-op */ -#endif } /* rfci (supervisor only) */ static void gen_rfci_40x(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* Restore CPU state */ gen_helper_40x_rfci(cpu_env); gen_sync_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_rfci(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* Restore CPU state */ gen_helper_rfci(cpu_env); gen_sync_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* BookE specific */ @@ -6376,32 +6315,26 @@ static void gen_rfci(DisasContext *ctx) static void gen_rfdi(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* Restore CPU state */ gen_helper_rfdi(cpu_env); gen_sync_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* XXX: not implemented on 440 ? */ static void gen_rfmci(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; /* Restore CPU state */ gen_helper_rfmci(cpu_env); gen_sync_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* TLB management - PowerPC 405 implementation */ @@ -6410,12 +6343,9 @@ static void gen_rfmci(DisasContext *ctx) static void gen_tlbre_40x(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; switch (rB(ctx->opcode)) { case 0: gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env, @@ -6429,20 +6359,18 @@ static void gen_tlbre_40x(DisasContext *ctx) gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbsx - tlbsx. */ static void gen_tlbsx_40x(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); @@ -6454,19 +6382,17 @@ static void gen_tlbsx_40x(DisasContext *ctx) tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); gen_set_label(l1); } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbwe */ static void gen_tlbwe_40x(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + switch (rB(ctx->opcode)) { case 0: gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)], @@ -6480,7 +6406,7 @@ static void gen_tlbwe_40x(DisasContext *ctx) gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* TLB management - PowerPC 440 implementation */ @@ -6489,12 +6415,10 @@ static void gen_tlbwe_40x(DisasContext *ctx) static void gen_tlbre_440(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; + switch (rB(ctx->opcode)) { case 0: case 1: @@ -6510,20 +6434,18 @@ static void gen_tlbre_440(DisasContext *ctx) gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbsx - tlbsx. */ static void gen_tlbsx_440(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); @@ -6535,19 +6457,16 @@ static void gen_tlbsx_440(DisasContext *ctx) tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); gen_set_label(l1); } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbwe */ static void gen_tlbwe_440(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; switch (rB(ctx->opcode)) { case 0: case 1: @@ -6563,7 +6482,7 @@ static void gen_tlbwe_440(DisasContext *ctx) gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* TLB management - PowerPC BookE 2.06 implementation */ @@ -6571,30 +6490,23 @@ static void gen_tlbwe_440(DisasContext *ctx) /* tlbre */ static void gen_tlbre_booke206(DisasContext *ctx) { -#if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + #if defined(CONFIG_USER_ONLY) + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } - + CHK_SV; gen_helper_booke206_tlbre(cpu_env); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbsx - tlbsx. */ static void gen_tlbsx_booke206(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; if (rA(ctx->opcode)) { t0 = tcg_temp_new(); tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]); @@ -6605,54 +6517,44 @@ static void gen_tlbsx_booke206(DisasContext *ctx) tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]); gen_helper_booke206_tlbsx(cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* tlbwe */ static void gen_tlbwe_booke206(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; gen_update_nip(ctx, ctx->nip - 4); gen_helper_booke206_tlbwe(cpu_env); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_tlbivax_booke206(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); - gen_helper_booke206_tlbivax(cpu_env, t0); tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_tlbilx_booke206(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; t0 = tcg_temp_new(); gen_addr_reg_index(ctx, t0); @@ -6672,7 +6574,7 @@ static void gen_tlbilx_booke206(DisasContext *ctx) } tcg_temp_free(t0); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } @@ -6680,13 +6582,11 @@ static void gen_tlbilx_booke206(DisasContext *ctx) static void gen_wrtee(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else TCGv t0; - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + + CHK_SV; t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE)); tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE)); @@ -6696,19 +6596,16 @@ static void gen_wrtee(DisasContext *ctx) * if we just set msr_ee to 1 */ gen_stop_exception(ctx); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* wrteei */ static void gen_wrteei(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } + CHK_SV; if (ctx->opcode & 0x00008000) { tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); /* Stop translation to have a chance to raise an exception */ @@ -6716,7 +6613,7 @@ static void gen_wrteei(DisasContext *ctx) } else { tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE)); } -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /* PowerPC 440 specific instructions */ @@ -6756,29 +6653,21 @@ static void gen_icbt_440(DisasContext *ctx) static void gen_msgclr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } - + CHK_SV; gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } static void gen_msgsnd(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + GEN_PRIV; #else - if (unlikely(ctx->pr)) { - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); - return; - } - + CHK_SV; gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]); -#endif +#endif /* defined(CONFIG_USER_ONLY) */ } /*** Altivec vector extension ***/ @@ -9780,7 +9669,7 @@ static void gen_tcheck(DisasContext *ctx) #define GEN_TM_PRIV_NOOP(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); \ + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); \ } #else @@ -9788,10 +9677,7 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_TM_PRIV_NOOP(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - if (unlikely(ctx->pr)) { \ - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); \ - return; \ - } \ + CHK_SV; \ if (unlikely(!ctx->tm_enabled)) { \ gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \ return; \