qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 06/10] ppc: Rework generation of priv and inval


From: David Gibson
Subject: Re: [Qemu-devel] [PATCH 06/10] ppc: Rework generation of priv and inval interrupts
Date: Wed, 15 Jun 2016 11:19:06 +1000
User-agent: Mutt/1.6.1 (2016-04-27)

On Mon, Jun 13, 2016 at 07:24:52AM +0200, Cédric Le Goater wrote:
> From: Benjamin Herrenschmidt <address@hidden>
> 
> 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 <address@hidden>
> [clg: fixed checkpatch.pl errors ]
> Signed-off-by: Cédric Le Goater <address@hidden>
> ---
>  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

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]