On Mon, Jun 13, 2016 at 07:24:52AM +0200, Cédric Le Goater wrote: > From: Benjamin Herrenschmidt <[email protected]> > > 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 <[email protected]> > [clg: fixed checkpatch.pl errors ] > Signed-off-by: Cédric Le Goater <[email protected]> > --- > linux-user/main.c | 1 + > target-ppc/excp_helper.c | 19 ++ > target-ppc/translate.c | 690 > ++++++++++++++++++++--------------------------- > 3 files changed, 311 insertions(+), 399 deletions(-) > > diff --git a/linux-user/main.c b/linux-user/main.c > index f8a8764ae97a..9e9b88b458c4 100644 > --- a/linux-user/main.c > +++ b/linux-user/main.c > @@ -1721,6 +1721,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 7c44c102db39..054c12de3bff 100644 > --- a/target-ppc/excp_helper.c > +++ b/target-ppc/excp_helper.c > @@ -128,6 +128,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 a02ddf52bfe6..2ec858063ecc 100644 > --- a/target-ppc/translate.c > +++ b/target-ppc/translate.c > @@ -325,7 +325,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 */ > @@ -366,6 +378,33 @@ 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) > \ > @@ -2929,7 +2968,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; > } > > @@ -3055,7 +3094,7 @@ static void gen_std(DisasContext *ctx) > } > > if (!legal_in_user_mode && ctx->pr) { > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); > + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); > return; > } > > @@ -4085,7 +4124,7 @@ 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 > /* This instruction doesn't exist anymore on 64-bit server > * processors compliant with arch 2.x > @@ -4095,10 +4134,7 @@ static void gen_rfi(DisasContext *ctx) > return; > } > /* 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); > @@ -4109,13 +4145,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); > @@ -4125,13 +4158,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->pr || !ctx->hv)) { > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); > - return; > - } > + CHK_HV; > gen_helper_hrfid(cpu_env); > gen_sync_exception(ctx); > #endif > @@ -4294,15 +4324,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) > @@ -4348,9 +4371,15 @@ static inline void gen_op_mfspr(DisasContext *ctx) > 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 { > + /* ISA 2.07 defines these as no-ops */ > + if ((ctx->insns_flags2 & PPC2_ISA207S) && > + (sprn >= 808 && sprn <= 811)) { > + /* This is a nop */ > + return; > + } > /* Not defined */ > fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at " > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); > @@ -4358,9 +4387,18 @@ static inline void gen_op_mfspr(DisasContext *ctx) > qemu_log("Trying to read invalid spr %d (0x%03x) at " > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); > } > - /* Only generate an exception in user space, otherwise this is a nop > */ > - if (ctx->pr) { > - 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);
Just double checking this logic. So in this case we get an exception
to the hypervisor if executed in guest user mode, but a no-op if
executed in guest supervisor mode. That seems.. odd.
> + }
> }
> }
> }
> @@ -4408,13 +4446,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();
> @@ -4433,20 +4467,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));
> @@ -4503,9 +4533,16 @@ static void gen_mtspr(DisasContext *ctx)
> qemu_log("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 {
> + /* ISA 2.07 defines these as no-ops */
> + if ((ctx->insns_flags2 & PPC2_ISA207S) &&
> + (sprn >= 808 && sprn <= 811)) {
> + /* This is a nop */
> + return;
> + }
> +
> /* Not defined */
> if (qemu_log_separate()) {
> qemu_log("Trying to write invalid spr %d (0x%03x) at "
> @@ -4514,9 +4551,18 @@ static void gen_mtspr(DisasContext *ctx)
> fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
> TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
>
> - /* Only generate an exception in user space, otherwise this is a nop
> */
> - if (ctx->pr) {
> - 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);
> + }
> }
> }
> }
> @@ -4539,13 +4585,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);
> @@ -4555,7 +4599,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 */
> @@ -4676,72 +4720,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)
> @@ -4751,115 +4787,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) */
> }
>
> static void gen_slbfee_(DisasContext *ctx)
> @@ -4895,40 +4917,34 @@ static void gen_slbfee_(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)) {
> - 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)]);
> @@ -4937,25 +4953,23 @@ 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);
> + GEN_PRIV;
> #else
> - if (unlikely(ctx->pr || !ctx->hv)) {
> - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> - return;
> - }
> + 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)
> @@ -4963,30 +4977,26 @@ static void gen_tlbsync(DisasContext *ctx)
> 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: */
> @@ -5685,14 +5695,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 */
> @@ -5701,28 +5708,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 */
> @@ -5731,28 +5732,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 */
> @@ -5766,15 +5761,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 */
> @@ -5786,15 +5778,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);
> @@ -5803,38 +5793,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 */
> @@ -5987,18 +5973,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_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> tcg_temp_free(t0);
> -#endif
> +#endif /* defined(CONFIG_USER_ONLY) */
> }
>
> /* All 405 MAC instructions are translated here */
> @@ -6220,38 +6204,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 */
> @@ -6259,18 +6239,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 */
> @@ -6278,18 +6255,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 */
> @@ -6315,28 +6289,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);
> @@ -6345,7 +6310,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 */
> @@ -6360,60 +6325,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 */
> @@ -6422,32 +6367,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 */
> @@ -6456,12 +6395,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,
> @@ -6475,20 +6411,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);
> @@ -6500,19 +6434,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)],
> @@ -6526,7 +6458,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 */
> @@ -6535,12 +6467,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:
> @@ -6556,20 +6486,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);
> @@ -6581,19 +6509,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:
> @@ -6609,7 +6534,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 */
> @@ -6617,30 +6542,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)]);
> @@ -6651,54 +6569,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);
>
> @@ -6718,7 +6626,7 @@ static void gen_tlbilx_booke206(DisasContext *ctx)
> }
>
> tcg_temp_free(t0);
> -#endif
> +#endif /* defined(CONFIG_USER_ONLY) */
> }
>
>
> @@ -6726,13 +6634,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));
> @@ -6742,19 +6648,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 */
> @@ -6762,7 +6665,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 */
> @@ -6802,29 +6705,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
> ***/
> @@ -9826,7 +9721,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
> @@ -9834,10 +9729,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; \
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature
