qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 01/11] target-ppc: exceptions handling in ico


From: David Gibson
Subject: Re: [Qemu-devel] [PATCH v2 01/11] target-ppc: exceptions handling in icount mode
Date: Tue, 20 Sep 2016 15:51:24 +1000
User-agent: Mutt/1.7.0 (2016-08-17)

On Thu, Sep 15, 2016 at 11:09:59AM +0300, Pavel Dovgalyuk wrote:
> From: Pavel Dovgalyuk <address@hidden>
> 
> This patch fixes exception handling in PowerPC.
> Instructions generate several types of exceptions.
> When exception is generated, it breaks the execution of the current 
> translation
> block. Implementation of the exceptions handling does not correctly
> restore icount for the instruction which caused the exception. In most cases
> icount will be decreased by the value equal to the size of TB.
> This patch passes pointer to the translation block internals to the exception
> handler. It allows correct restoring of the icount value.
> 
> Signed-off-by: Pavel Dovgalyuk <address@hidden>

I'm not really confident reviewing changes in this area.

I've CCed Ben Herrenshmidt, who did some work on the exception
handling recently.  Ben, if you get a chance can you please review
this change.

> ---
>  target-ppc/cpu.h             |    3 +
>  target-ppc/excp_helper.c     |   38 ++++++--
>  target-ppc/fpu_helper.c      |  192 
> ++++++++++++++++++++++--------------------
>  target-ppc/helper.h          |    1 
>  target-ppc/mem_helper.c      |    6 +
>  target-ppc/misc_helper.c     |    8 +-
>  target-ppc/mmu-hash64.c      |   12 +--
>  target-ppc/mmu_helper.c      |   18 ++--
>  target-ppc/timebase_helper.c |   21 ++---
>  target-ppc/translate.c       |   76 +----------------
>  10 files changed, 169 insertions(+), 206 deletions(-)
> 
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 786ab5c..95baae3 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -2434,4 +2434,7 @@ int ppc_get_vcpu_dt_id(PowerPCCPU *cpu);
>  PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id);
>  
>  void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len);
> +void raise_exception_err(CPUPPCState *env, uint32_t exception,
> +                         uint32_t error_code, uintptr_t pc);
> +
>  #endif /* PPC_CPU_H */
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index d6e1678..3da1c32 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -898,8 +898,8 @@ static void cpu_dump_rfi(target_ulong RA, target_ulong 
> msr)
>  
> /*****************************************************************************/
>  /* Exceptions processing helpers */
>  
> -void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
> -                                uint32_t error_code)
> +void raise_exception_err(CPUPPCState *env, uint32_t exception,
> +                         uint32_t error_code, uintptr_t pc)
>  {
>      CPUState *cs = CPU(ppc_env_get_cpu(env));
>  
> @@ -908,15 +908,32 @@ void helper_raise_exception_err(CPUPPCState *env, 
> uint32_t exception,
>  #endif
>      cs->exception_index = exception;
>      env->error_code = error_code;
> -    cpu_loop_exit(cs);
> +    cpu_loop_exit_restore(cs, pc);
> +}
> +
> +void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
> +                                uint32_t error_code)
> +{
> +    raise_exception_err(env, exception, error_code, GETPC());
> +}
> +
> +void helper_raise_exception_end(CPUPPCState *env, uint32_t exception,
> +                                uint32_t error_code)
> +{
> +    raise_exception_err(env, exception, error_code, 0);

I'm struggling to see how raising an exception with a return address
of 0 could ever be useful...

>  }
>  
>  void helper_raise_exception(CPUPPCState *env, uint32_t exception)
>  {
> -    helper_raise_exception_err(env, exception, 0);
> +    raise_exception_err(env, exception, 0, GETPC());
>  }
>  
>  #if !defined(CONFIG_USER_ONLY)
> +static void raise_exception(CPUPPCState *env, uint32_t exception, uintptr_t 
> pc)
> +{
> +    raise_exception_err(env, exception, 0, pc);
> +}
> +
>  void helper_store_msr(CPUPPCState *env, target_ulong val)
>  {
>      CPUState *cs;
> @@ -925,7 +942,8 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
>      if (val != 0) {
>          cs = CPU(ppc_env_get_cpu(env));
>          cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
> -        helper_raise_exception(env, val);
> +        /* nip is updated by generated code */
> +        raise_exception(env, val, 0);
>      }
>  }
>  
> @@ -1041,8 +1059,9 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
> target_ulong arg2,
>                    ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
>                    ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
>                    ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_TRAP);
> +        /* nip is updated in TB */
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_TRAP, 0);
>      }
>  }
>  
> @@ -1055,8 +1074,9 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
> target_ulong arg2,
>                    ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
>                    ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
>                    ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_TRAP);
> +        /* nip is updated in TB */
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_TRAP, 0);
>      }
>  }
>  #endif
> diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
> index d9795d0..6eaa3f4 100644
> --- a/target-ppc/fpu_helper.c
> +++ b/target-ppc/fpu_helper.c
> @@ -19,6 +19,7 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
>  
>  #define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ULL)
>  #define float32_snan_to_qnan(x) ((x) | 0x00400000)
> @@ -117,7 +118,7 @@ void helper_compute_fprf(CPUPPCState *env, uint64_t arg)
>  
>  /* Floating-point invalid operations exception */
>  static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op,
> -                                             int set_fpcc)
> +                                             int set_fpcc, uintptr_t retaddr)
>  {
>      CPUState *cs = CPU(ppc_env_get_cpu(env));
>      uint64_t ret = 0;
> @@ -200,14 +201,14 @@ static inline uint64_t 
> fload_invalid_op_excp(CPUPPCState *env, int op,
>          /* Update the floating-point enabled exception summary */
>          env->fpscr |= 1 << FPSCR_FEX;
>          if (msr_fe0 != 0 || msr_fe1 != 0) {
> -            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                       POWERPC_EXCP_FP | op);
> +            raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                                POWERPC_EXCP_FP | op, retaddr);
>          }
>      }
>      return ret;
>  }
>  
> -static inline void float_zero_divide_excp(CPUPPCState *env)
> +static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t 
> retaddr)
>  {
>      env->fpscr |= 1 << FPSCR_ZX;
>      env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
> @@ -217,8 +218,8 @@ static inline void float_zero_divide_excp(CPUPPCState 
> *env)
>          /* Update the floating-point enabled exception summary */
>          env->fpscr |= 1 << FPSCR_FEX;
>          if (msr_fe0 != 0 || msr_fe1 != 0) {
> -            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
> +            raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                                POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX, 
> retaddr);
>          }
>      }
>  }
> @@ -491,13 +492,13 @@ void store_fpscr(CPUPPCState *env, uint64_t arg, 
> uint32_t mask)
>      helper_store_fpscr(env, arg, mask);
>  }
>  
> -void helper_float_check_status(CPUPPCState *env)
> +static void do_float_check_status(CPUPPCState *env, uintptr_t retaddr)
>  {
>      CPUState *cs = CPU(ppc_env_get_cpu(env));
>      int status = get_float_exception_flags(&env->fp_status);
>  
>      if (status & float_flag_divbyzero) {
> -        float_zero_divide_excp(env);
> +        float_zero_divide_excp(env, retaddr);
>      } else if (status & float_flag_overflow) {
>          float_overflow_excp(env);
>      } else if (status & float_flag_underflow) {
> @@ -510,12 +511,17 @@ void helper_float_check_status(CPUPPCState *env)
>          (env->error_code & POWERPC_EXCP_FP)) {
>          /* Differred floating-point exception after target FPR update */
>          if (msr_fe0 != 0 || msr_fe1 != 0) {
> -            helper_raise_exception_err(env, cs->exception_index,
> -                                       env->error_code);
> +            raise_exception_err(env, cs->exception_index,
> +                                env->error_code, retaddr);
>          }
>      }
>  }
>  
> +void helper_float_check_status(CPUPPCState *env)
> +{
> +    do_float_check_status(env, GETPC());
> +}
> +
>  void helper_reset_fpstatus(CPUPPCState *env)
>  {
>      set_float_exception_flags(0, &env->fp_status);
> @@ -532,12 +538,12 @@ uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2)
>      if (unlikely(float64_is_infinity(farg1.d) && 
> float64_is_infinity(farg2.d) &&
>                   float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
>          /* Magnitude subtraction of infinities */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status))) {
>              /* sNaN addition */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
>      }
> @@ -556,12 +562,12 @@ uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2)
>      if (unlikely(float64_is_infinity(farg1.d) && 
> float64_is_infinity(farg2.d) &&
>                   float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
>          /* Magnitude subtraction of infinities */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status))) {
>              /* sNaN subtraction */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
>      }
> @@ -580,12 +586,12 @@ uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2)
>      if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) 
> ||
>                   (float64_is_zero(farg1.d) && 
> float64_is_infinity(farg2.d)))) {
>          /* Multiplication of zero by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status))) {
>              /* sNaN multiplication */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
>      }
> @@ -604,15 +610,15 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2)
>      if (unlikely(float64_is_infinity(farg1.d) &&
>                   float64_is_infinity(farg2.d))) {
>          /* Division of infinity by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1, 
> GETPC());
>      } else if (unlikely(float64_is_zero(farg1.d) && 
> float64_is_zero(farg2.d))) {
>          /* Division of zero by zero */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status))) {
>              /* sNaN division */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
>      }
> @@ -631,16 +637,16 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)    
>                \
>                                                                         \
>      if (unlikely(env->fp_status.float_exception_flags)) {              \
>          if (float64_is_any_nan(arg)) {                                 \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1, GETPC());\
>              if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, 
> GETPC());\
>              }                                                          \
>              farg.ll = nanval;                                          \
>          } else if (env->fp_status.float_exception_flags &              \
>                     float_flag_invalid) {                               \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1, GETPC());\
>          }                                                              \
> -        helper_float_check_status(env);                                \
> +        do_float_check_status(env, GETPC());                           \
>      }                                                                  \
>      return farg.ll;                                                    \
>   }
> @@ -665,7 +671,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)      
>  \
>      } else {                                               \
>          farg.d = cvtr(arg, &env->fp_status);               \
>      }                                                      \
> -    helper_float_check_status(env);                        \
> +    do_float_check_status(env, GETPC());                   \
>      return farg.ll;                                        \
>  }
>  
> @@ -675,7 +681,7 @@ FPU_FCFI(fcfidu, uint64_to_float64, 0)
>  FPU_FCFI(fcfidus, uint64_to_float32, 1)
>  
>  static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
> -                              int rounding_mode)
> +                              int rounding_mode, uint64_t retaddr)
>  {
>      CPU_DoubleU farg;
>  
> @@ -683,7 +689,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t 
> arg,
>  
>      if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>          /* sNaN round */
> -        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, retaddr);
>          farg.ll = arg | 0x0008000000000000ULL;
>      } else {
>          int inexact = get_float_exception_flags(&env->fp_status) &
> @@ -698,28 +704,28 @@ static inline uint64_t do_fri(CPUPPCState *env, 
> uint64_t arg,
>              env->fp_status.float_exception_flags &= ~float_flag_inexact;
>          }
>      }
> -    helper_float_check_status(env);
> +    do_float_check_status(env, GETPC());
>      return farg.ll;
>  }
>  
>  uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
>  {
> -    return do_fri(env, arg, float_round_ties_away);
> +    return do_fri(env, arg, float_round_ties_away, GETPC());
>  }
>  
>  uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
>  {
> -    return do_fri(env, arg, float_round_to_zero);
> +    return do_fri(env, arg, float_round_to_zero, GETPC());
>  }
>  
>  uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
>  {
> -    return do_fri(env, arg, float_round_up);
> +    return do_fri(env, arg, float_round_up, GETPC());
>  }
>  
>  uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
>  {
> -    return do_fri(env, arg, float_round_down);
> +    return do_fri(env, arg, float_round_down, GETPC());
>  }
>  
>  /* fmadd - fmadd. */
> @@ -735,13 +741,13 @@ uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>      if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) 
> ||
>                   (float64_is_zero(farg1.d) && 
> float64_is_infinity(farg2.d)))) {
>          /* Multiplication of zero by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg3.d, &env->fp_status))) {
>              /* sNaN operation */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          /* This is the way the PowerPC specification defines it */
>          float128 ft0_128, ft1_128;
> @@ -753,7 +759,7 @@ uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                       float64_is_infinity(farg3.d) &&
>                       float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
>              /* Magnitude subtraction of infinities */
> -            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>          } else {
>              ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
>              ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
> @@ -778,13 +784,13 @@ uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                   (float64_is_zero(farg1.d) &&
>                    float64_is_infinity(farg2.d)))) {
>          /* Multiplication of zero by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg3.d, &env->fp_status))) {
>              /* sNaN operation */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          /* This is the way the PowerPC specification defines it */
>          float128 ft0_128, ft1_128;
> @@ -796,7 +802,7 @@ uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                       float64_is_infinity(farg3.d) &&
>                       float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
>              /* Magnitude subtraction of infinities */
> -            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>          } else {
>              ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
>              ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
> @@ -819,13 +825,13 @@ uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>      if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) 
> ||
>                   (float64_is_zero(farg1.d) && 
> float64_is_infinity(farg2.d)))) {
>          /* Multiplication of zero by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg3.d, &env->fp_status))) {
>              /* sNaN operation */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          /* This is the way the PowerPC specification defines it */
>          float128 ft0_128, ft1_128;
> @@ -837,7 +843,7 @@ uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                       float64_is_infinity(farg3.d) &&
>                       float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
>              /* Magnitude subtraction of infinities */
> -            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>          } else {
>              ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
>              ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
> @@ -864,13 +870,13 @@ uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                   (float64_is_zero(farg1.d) &&
>                    float64_is_infinity(farg2.d)))) {
>          /* Multiplication of zero by infinity */
> -        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
> +        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1, 
> GETPC());
>      } else {
>          if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg3.d, &env->fp_status))) {
>              /* sNaN operation */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>          }
>          /* This is the way the PowerPC specification defines it */
>          float128 ft0_128, ft1_128;
> @@ -882,7 +888,7 @@ uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                       float64_is_infinity(farg3.d) &&
>                       float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
>              /* Magnitude subtraction of infinities */
> -            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
> +            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1, 
> GETPC());
>          } else {
>              ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
>              ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
> @@ -905,7 +911,7 @@ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
>  
>      if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>          /* sNaN square root */
> -        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>      }
>      f32 = float64_to_float32(farg.d, &env->fp_status);
>      farg.d = float32_to_float64(f32, &env->fp_status);
> @@ -923,12 +929,12 @@ uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
>      if (unlikely(float64_is_any_nan(farg.d))) {
>          if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>              /* sNaN reciprocal square root */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>              farg.ll = float64_snan_to_qnan(farg.ll);
>          }
>      } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) 
> {
>          /* Square root of a negative nonzero number */
> -        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
> +        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1, 
> GETPC());
>      } else {
>          farg.d = float64_sqrt(farg.d, &env->fp_status);
>      }
> @@ -944,7 +950,7 @@ uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
>  
>      if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>          /* sNaN reciprocal */
> -        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>      }
>      farg.d = float64_div(float64_one, farg.d, &env->fp_status);
>      return farg.d;
> @@ -960,7 +966,7 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
>  
>      if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>          /* sNaN reciprocal */
> -        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>      }
>      farg.d = float64_div(float64_one, farg.d, &env->fp_status);
>      f32 = float64_to_float32(farg.d, &env->fp_status);
> @@ -979,12 +985,12 @@ uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
>      if (unlikely(float64_is_any_nan(farg.d))) {
>          if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
>              /* sNaN reciprocal square root */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>              farg.ll = float64_snan_to_qnan(farg.ll);
>          }
>      } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) 
> {
>          /* Reciprocal square root of a negative nonzero number */
> -        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
> +        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1, 
> GETPC());
>      } else {
>          farg.d = float64_sqrt(farg.d, &env->fp_status);
>          farg.d = float64_div(float64_one, farg.d, &env->fp_status);
> @@ -1103,7 +1109,7 @@ void helper_fcmpu(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>                   && (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
>                       float64_is_signaling_nan(farg2.d, &env->fp_status)))) {
>          /* sNaN comparison */
> -        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
> +        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1, GETPC());
>      }
>  }
>  
> @@ -1135,10 +1141,10 @@ void helper_fcmpo(CPUPPCState *env, uint64_t arg1, 
> uint64_t arg2,
>              float64_is_signaling_nan(farg2.d, &env->fp_status)) {
>              /* sNaN comparison */
>              fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
> -                                  POWERPC_EXCP_FP_VXVC, 1);
> +                                  POWERPC_EXCP_FP_VXVC, 1, GETPC());
>          } else {
>              /* qNaN comparison */
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1, GETPC());
>          }
>      }
>  }
> @@ -1838,10 +1844,10 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) 
>                        \
>                                                                               
> \
>          if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    
> \
>              if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf, 
> GETPC());\
>              } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              
> \
>                         tp##_is_signaling_nan(xb.fld, &tstat)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>              }                                                                
> \
>          }                                                                    
> \
>                                                                               
> \
> @@ -1854,7 +1860,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)   
>                      \
>          }                                                                    
> \
>      }                                                                        
> \
>      putVSR(xT(opcode), &xt, env);                                            
> \
> -    helper_float_check_status(env);                                          
> \
> +    do_float_check_status(env, GETPC());                                     
> \
>  }
>  
>  VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
> @@ -1893,10 +1899,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                        \
>          if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    
> \
>              if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        
> \
>                  (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf);    
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf, 
> GETPC());\
>              } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              
> \
>                         tp##_is_signaling_nan(xb.fld, &tstat)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>              }                                                                
> \
>          }                                                                    
> \
>                                                                               
> \
> @@ -1910,7 +1916,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                      \
>      }                                                                        
> \
>                                                                               
> \
>      putVSR(xT(opcode), &xt, env);                                            
> \
> -    helper_float_check_status(env);                                          
> \
> +    do_float_check_status(env, GETPC());                                     
> \
>  }
>  
>  VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
> @@ -1944,13 +1950,13 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                         \
>                                                                               
>  \
>          if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    
>  \
>              if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf);    
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf, 
> GETPC());\
>              } else if (tp##_is_zero(xa.fld) &&                               
>  \
>                  tp##_is_zero(xb.fld)) {                                      
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf);    
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf, 
> GETPC());\
>              } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              
>  \
>                  tp##_is_signaling_nan(xb.fld, &tstat)) {                     
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>              }                                                                
>  \
>          }                                                                    
>  \
>                                                                               
>  \
> @@ -1964,7 +1970,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                       \
>      }                                                                        
>  \
>                                                                               
>  \
>      putVSR(xT(opcode), &xt, env);                                            
>  \
> -    helper_float_check_status(env);                                          
>  \
> +    do_float_check_status(env, GETPC());                                     
>  \
>  }
>  
>  VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
> @@ -1991,7 +1997,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                       \
>                                                                               
>  \
>      for (i = 0; i < nels; i++) {                                             
>  \
>          if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) {      
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>          }                                                                    
>  \
>          xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status);                
>  \
>                                                                               
>  \
> @@ -2005,7 +2011,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                       \
>      }                                                                        
>  \
>                                                                               
>  \
>      putVSR(xT(opcode), &xt, env);                                            
>  \
> -    helper_float_check_status(env);                                          
>  \
> +    do_float_check_status(env, GETPC());                                     
>  \
>  }
>  
>  VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
> @@ -2038,9 +2044,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                      \
>                                                                               
> \
>          if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    
> \
>              if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf, 
> GETPC());\
>              } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>              }                                                                
> \
>          }                                                                    
> \
>                                                                               
> \
> @@ -2054,7 +2060,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                      \
>      }                                                                        
> \
>                                                                               
> \
>      putVSR(xT(opcode), &xt, env);                                            
> \
> -    helper_float_check_status(env);                                          
> \
> +    do_float_check_status(env, GETPC());                                     
> \
>  }
>  
>  VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
> @@ -2088,9 +2094,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                      \
>                                                                               
> \
>          if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    
> \
>              if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf, 
> GETPC());\
>              } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>              }                                                                
> \
>          }                                                                    
> \
>                                                                               
> \
> @@ -2104,7 +2110,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                      \
>      }                                                                        
> \
>                                                                               
> \
>      putVSR(xT(opcode), &xt, env);                                            
> \
> -    helper_float_check_status(env);                                          
> \
> +    do_float_check_status(env, GETPC());                                     
> \
>  }
>  
>  VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
> @@ -2277,20 +2283,20 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                         \
>              if (tp##_is_signaling_nan(xa.fld, &tstat) ||                     
>  \
>                  tp##_is_signaling_nan(b->fld, &tstat) ||                     
>  \
>                  tp##_is_signaling_nan(c->fld, &tstat)) {                     
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf, 
> GETPC());\
>                  tstat.float_exception_flags &= ~float_flag_invalid;          
>  \
>              }                                                                
>  \
>              if ((tp##_is_infinity(xa.fld) && tp##_is_zero(b->fld)) ||        
>  \
>                  (tp##_is_zero(xa.fld) && tp##_is_infinity(b->fld))) {        
>  \
>                  xt_out.fld = float64_to_##tp(fload_invalid_op_excp(env,      
>  \
> -                    POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status);         
>  \
> +                    POWERPC_EXCP_FP_VXIMZ, sfprf, GETPC()), 
> &env->fp_status); \
>                  tstat.float_exception_flags &= ~float_flag_invalid;          
>  \
>              }                                                                
>  \
>              if ((tstat.float_exception_flags & float_flag_invalid) &&        
>  \
>                  ((tp##_is_infinity(xa.fld) ||                                
>  \
>                    tp##_is_infinity(b->fld)) &&                               
>  \
>                    tp##_is_infinity(c->fld))) {                               
>  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    
>  \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf, 
> GETPC());\
>              }                                                                
>  \
>          }                                                                    
>  \
>                                                                               
>  \
> @@ -2303,7 +2309,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                       \
>          }                                                                    
>  \
>      }                                                                        
>  \
>      putVSR(xT(opcode), &xt_out, env);                                        
>  \
> -    helper_float_check_status(env);                                          
>  \
> +    do_float_check_status(env, GETPC());                                     
>  \
>  }
>  
>  #define MADD_FLGS 0
> @@ -2360,10 +2366,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                    \
>                   float64_is_any_nan(xb.VsrD(0)))) {                      \
>          if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) ||     \
>              float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) {     \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, GETPC());\
>          }                                                                \
>          if (ordered) {                                                   \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);         \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0, GETPC());\
>          }                                                                \
>          cc = 1;                                                          \
>      } else {                                                             \
> @@ -2381,7 +2387,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                  \
>      env->fpscr |= cc << FPSCR_FPRF;                                      \
>      env->crf[BF(opcode)] = cc;                                           \
>                                                                           \
> -    helper_float_check_status(env);                                      \
> +    do_float_check_status(env, GETPC());                                 \
>  }
>  
>  VSX_SCALAR_CMP(xscmpodp, 1)
> @@ -2408,12 +2414,12 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) 
>                         \
>          xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status);                 
>  \
>          if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) ||       
>  \
>                       tp##_is_signaling_nan(xb.fld, &env->fp_status))) {      
>  \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);           
>  \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, GETPC());  
>  \
>          }                                                                    
>  \
>      }                                                                        
>  \
>                                                                               
>  \
>      putVSR(xT(opcode), &xt, env);                                            
>  \
> -    helper_float_check_status(env);                                          
>  \
> +    do_float_check_status(env, GETPC());                                     
>  \
>  }
>  
>  VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
> @@ -2448,10 +2454,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                     \
>                       tp##_is_any_nan(xb.fld))) {                          \
>              if (tp##_is_signaling_nan(xa.fld, &env->fp_status) ||         \
>                  tp##_is_signaling_nan(xb.fld, &env->fp_status)) {         \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);    \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, 
> GETPC());\
>              }                                                             \
>              if (svxvc) {                                                  \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);      \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0, 
> GETPC());\
>              }                                                             \
>              xt.fld = 0;                                                   \
>              all_true = 0;                                                 \
> @@ -2470,7 +2476,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                   \
>      if ((opcode >> (31-21)) & 1) {                                        \
>          env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0);       \
>      }                                                                     \
> -    helper_float_check_status(env);                                       \
> +    do_float_check_status(env, GETPC());                                  \
>   }
>  
>  VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0)
> @@ -2502,7 +2508,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>            \
>          xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);        \
>          if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
>                                              &env->fp_status))) {   \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, GETPC()); \
>              xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
>          }                                                          \
>          if (sfprf) {                                               \
> @@ -2512,7 +2518,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>            \
>      }                                                              \
>                                                                     \
>      putVSR(xT(opcode), &xt, env);                                  \
> -    helper_float_check_status(env);                                \
> +    do_float_check_status(env, GETPC());                           \
>  }
>  
>  VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
> @@ -2557,21 +2563,21 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
>                        \
>      for (i = 0; i < nels; i++) {                                             
> \
>          if (unlikely(stp##_is_any_nan(xb.sfld))) {                           
> \
>              if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, 
> GETPC());\
>              }                                                                
> \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            
> \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0, GETPC());   
> \
>              xt.tfld = rnan;                                                  
> \
>          } else {                                                             
> \
>              xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                
> \
>                            &env->fp_status);                                  
> \
>              if (env->fp_status.float_exception_flags & float_flag_invalid) { 
> \
> -                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);        
> \
> +                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0, 
> GETPC());\
>              }                                                                
> \
>          }                                                                    
> \
>      }                                                                        
> \
>                                                                               
> \
>      putVSR(xT(opcode), &xt, env);                                            
> \
> -    helper_float_check_status(env);                                          
> \
> +    do_float_check_status(env, GETPC());                                     
> \
>  }
>  
>  VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
> @@ -2622,7 +2628,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                 \
>      }                                                                   \
>                                                                          \
>      putVSR(xT(opcode), &xt, env);                                       \
> -    helper_float_check_status(env);                                     \
> +    do_float_check_status(env, GETPC());                                \
>  }
>  
>  VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
> @@ -2667,7 +2673,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                \
>      for (i = 0; i < nels; i++) {                                       \
>          if (unlikely(tp##_is_signaling_nan(xb.fld,                     \
>                                             &env->fp_status))) {        \
> -            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);     \
> +            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0, GETPC());\
>              xt.fld = tp##_snan_to_qnan(xb.fld);                        \
>          } else {                                                       \
>              xt.fld = tp##_round_to_int(xb.fld, &env->fp_status);       \
> @@ -2686,7 +2692,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)     
>                \
>      }                                                                  \
>                                                                         \
>      putVSR(xT(opcode), &xt, env);                                      \
> -    helper_float_check_status(env);                                    \
> +    do_float_check_status(env, GETPC());                               \
>  }
>  
>  VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1)
> @@ -2714,6 +2720,6 @@ uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
>      uint64_t xt = helper_frsp(env, xb);
>  
>      helper_compute_fprf(env, xt);
> -    helper_float_check_status(env);
> +    do_float_check_status(env, GETPC());
>      return xt;
>  }
> diff --git a/target-ppc/helper.h b/target-ppc/helper.h
> index 1f5cfd0..34560f9 100644
> --- a/target-ppc/helper.h
> +++ b/target-ppc/helper.h
> @@ -1,4 +1,5 @@
>  DEF_HELPER_3(raise_exception_err, void, env, i32, i32)
> +DEF_HELPER_3(raise_exception_end, void, env, i32, i32)
>  DEF_HELPER_2(raise_exception, void, env, i32)
>  DEF_HELPER_4(tw, void, env, tl, tl, i32)
>  #if defined(TARGET_PPC64)
> diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
> index e4ed377..5cee620 100644
> --- a/target-ppc/mem_helper.c
> +++ b/target-ppc/mem_helper.c
> @@ -107,9 +107,9 @@ void helper_lswx(CPUPPCState *env, target_ulong addr, 
> uint32_t reg,
>          if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) ||
>                       lsw_reg_in_range(reg, num_used_regs, rb))) {
>              env->nip += 4;     /* Compensate the "nip - 4" from gen_lswx() */
> -            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                       POWERPC_EXCP_INVAL |
> -                                       POWERPC_EXCP_INVAL_LSWX);
> +            raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                                POWERPC_EXCP_INVAL |
> +                                POWERPC_EXCP_INVAL_LSWX, GETPC());
>          } else {
>              helper_lsw(env, addr, xer_bc, reg);
>          }
> diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
> index cb5ebf5..6661650 100644
> --- a/target-ppc/misc_helper.c
> +++ b/target-ppc/misc_helper.c
> @@ -39,7 +39,7 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
>  
>  #ifdef TARGET_PPC64
>  static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
> -                               uint32_t sprn, uint32_t cause)
> +                               uint32_t sprn, uint32_t cause, uintptr_t 
> retaddr)
>  {
>      qemu_log("Facility SPR %d is unavailable (SPR FSCR:%d)\n", sprn, bit);
>  
> @@ -47,7 +47,7 @@ static void raise_fu_exception(CPUPPCState *env, uint32_t 
> bit,
>      cause &= FSCR_IC_MASK;
>      env->spr[SPR_FSCR] |= (target_ulong)cause << FSCR_IC_POS;
>  
> -    helper_raise_exception_err(env, POWERPC_EXCP_FU, 0);
> +    raise_exception_err(env, POWERPC_EXCP_FU, 0, retaddr);
>  }
>  #endif
>  
> @@ -59,7 +59,7 @@ void helper_fscr_facility_check(CPUPPCState *env, uint32_t 
> bit,
>          /* Facility is enabled, continue */
>          return;
>      }
> -    raise_fu_exception(env, bit, sprn, cause);
> +    raise_fu_exception(env, bit, sprn, cause, GETPC());
>  #endif
>  }
>  
> @@ -71,7 +71,7 @@ void helper_msr_facility_check(CPUPPCState *env, uint32_t 
> bit,
>          /* Facility is enabled, continue */
>          return;
>      }
> -    raise_fu_exception(env, bit, sprn, cause);
> +    raise_fu_exception(env, bit, sprn, cause, GETPC());
>  #endif
>  }
>  
> diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
> index 5de1358..a1b27b0 100644
> --- a/target-ppc/mmu-hash64.c
> +++ b/target-ppc/mmu-hash64.c
> @@ -241,8 +241,8 @@ void helper_store_slb(CPUPPCState *env, target_ulong rb, 
> target_ulong rs)
>      PowerPCCPU *cpu = ppc_env_get_cpu(env);
>  
>      if (ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs) < 0) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL, GETPC());
>      }
>  }
>  
> @@ -252,8 +252,8 @@ target_ulong helper_load_slb_esid(CPUPPCState *env, 
> target_ulong rb)
>      target_ulong rt = 0;
>  
>      if (ppc_load_slb_esid(cpu, rb, &rt) < 0) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL, GETPC());
>      }
>      return rt;
>  }
> @@ -276,8 +276,8 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, 
> target_ulong rb)
>      target_ulong rt = 0;
>  
>      if (ppc_load_slb_vsid(cpu, rb, &rt) < 0) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL, GETPC());
>      }
>      return rt;
>  }
> diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
> index 3eb3cd7..7cd9c2c 100644
> --- a/target-ppc/mmu_helper.c
> +++ b/target-ppc/mmu_helper.c
> @@ -2598,9 +2598,9 @@ void helper_booke206_tlbwe(CPUPPCState *env)
>      tlb = booke206_cur_tlb(env);
>  
>      if (!tlb) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL |
> -                                   POWERPC_EXCP_INVAL_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL |
> +                            POWERPC_EXCP_INVAL_INVAL, GETPC());
>      }
>  
>      /* check that we support the targeted size */
> @@ -2608,9 +2608,9 @@ void helper_booke206_tlbwe(CPUPPCState *env)
>      size_ps = booke206_tlbnps(env, tlbn);
>      if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) 
> &&
>          !(size_ps & (1 << size_tlb))) {
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL |
> -                                   POWERPC_EXCP_INVAL_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL |
> +                            POWERPC_EXCP_INVAL_INVAL, GETPC());
>      }
>  
>      if (msr_gs) {
> @@ -2892,10 +2892,6 @@ void tlb_fill(CPUState *cs, target_ulong addr, 
> MMUAccessType access_type,
>          ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
>      }
>      if (unlikely(ret != 0)) {
> -        if (likely(retaddr)) {
> -            /* now we have a real cpu fault */
> -            cpu_restore_state(cs, retaddr);
> -        }
> -        helper_raise_exception_err(env, cs->exception_index, 
> env->error_code);
> +        raise_exception_err(env, cs->exception_index, env->error_code, 
> retaddr);
>      }
>  }
> diff --git a/target-ppc/timebase_helper.c b/target-ppc/timebase_helper.c
> index a07faa4..af328ca 100644
> --- a/target-ppc/timebase_helper.c
> +++ b/target-ppc/timebase_helper.c
> @@ -19,6 +19,7 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
>  #include "qemu/log.h"
>  
>  
> /*****************************************************************************/
> @@ -143,15 +144,15 @@ target_ulong helper_load_dcr(CPUPPCState *env, 
> target_ulong dcrn)
>  
>      if (unlikely(env->dcr_env == NULL)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL |
> -                                   POWERPC_EXCP_INVAL_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL |
> +                            POWERPC_EXCP_INVAL_INVAL, GETPC());
>      } else if (unlikely(ppc_dcr_read(env->dcr_env,
>                                       (uint32_t)dcrn, &val) != 0)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "DCR read error %d %03x\n",
>                        (uint32_t)dcrn, (uint32_t)dcrn);
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL | 
> POWERPC_EXCP_PRIV_REG);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG, 
> GETPC());
>      }
>      return val;
>  }
> @@ -160,14 +161,14 @@ void helper_store_dcr(CPUPPCState *env, target_ulong 
> dcrn, target_ulong val)
>  {
>      if (unlikely(env->dcr_env == NULL)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL |
> -                                   POWERPC_EXCP_INVAL_INVAL);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL |
> +                            POWERPC_EXCP_INVAL_INVAL, GETPC());
>      } else if (unlikely(ppc_dcr_write(env->dcr_env, (uint32_t)dcrn,
>                                        (uint32_t)val) != 0)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "DCR write error %d %03x\n",
>                        (uint32_t)dcrn, (uint32_t)dcrn);
> -        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -                                   POWERPC_EXCP_INVAL | 
> POWERPC_EXCP_PRIV_REG);
> +        raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> +                            POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG, 
> GETPC());
>      }
>  }
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 92030b6..0e16578 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -292,7 +292,7 @@ static void gen_exception_err(DisasContext *ctx, uint32_t 
> excp, uint32_t error)
>      }
>      t0 = tcg_const_i32(excp);
>      t1 = tcg_const_i32(error);
> -    gen_helper_raise_exception_err(cpu_env, t0, t1);
> +    gen_helper_raise_exception_end(cpu_env, t0, t1);
>      tcg_temp_free_i32(t0);
>      tcg_temp_free_i32(t1);
>      ctx->exception = (excp);
> @@ -300,14 +300,7 @@ static void gen_exception_err(DisasContext *ctx, 
> uint32_t excp, uint32_t error)
>  
>  static void gen_exception(DisasContext *ctx, uint32_t excp)
>  {
> -    TCGv_i32 t0;
> -    if (ctx->exception == POWERPC_EXCP_NONE) {
> -        gen_update_nip(ctx, ctx->nip);
> -    }
> -    t0 = tcg_const_i32(excp);
> -    gen_helper_raise_exception(cpu_env, t0);
> -    tcg_temp_free_i32(t0);
> -    ctx->exception = (excp);
> +    gen_exception_err(ctx, excp, 0);
>  }
>  
>  static void gen_debug_exception(DisasContext *ctx)
> @@ -2149,8 +2142,6 @@ static void gen_f##name(DisasContext *ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_FPU);                                
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      gen_reset_fpstatus();                                                    
>  \
>      gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                      
>  \
>                       cpu_fpr[rA(ctx->opcode)],                               
>  \
> @@ -2178,8 +2169,6 @@ static void gen_f##name(DisasContext *ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_FPU);                                
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      gen_reset_fpstatus();                                                    
>  \
>      gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                      
>  \
>                       cpu_fpr[rA(ctx->opcode)],                               
>  \
> @@ -2206,8 +2195,6 @@ static void gen_f##name(DisasContext *ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_FPU);                                
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      gen_reset_fpstatus();                                                    
>  \
>      gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                      
>  \
>                       cpu_fpr[rA(ctx->opcode)],                               
>  \
> @@ -2234,8 +2221,6 @@ static void gen_f##name(DisasContext *ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_FPU);                                
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      gen_reset_fpstatus();                                                    
>  \
>      gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                    
>  \
>                         cpu_fpr[rB(ctx->opcode)]);                            
>  \
> @@ -2254,8 +2239,6 @@ static void gen_f##name(DisasContext *ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_FPU);                                
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      gen_reset_fpstatus();                                                    
>  \
>      gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                    
>  \
>                         cpu_fpr[rB(ctx->opcode)]);                            
>  \
> @@ -2290,8 +2273,6 @@ static void gen_frsqrtes(DisasContext *ctx)
>          gen_exception(ctx, POWERPC_EXCP_FPU);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
>                         cpu_fpr[rB(ctx->opcode)]);
> @@ -2316,8 +2297,6 @@ static void gen_fsqrt(DisasContext *ctx)
>          gen_exception(ctx, POWERPC_EXCP_FPU);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
>                       cpu_fpr[rB(ctx->opcode)]);
> @@ -2333,8 +2312,6 @@ static void gen_fsqrts(DisasContext *ctx)
>          gen_exception(ctx, POWERPC_EXCP_FPU);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
>                       cpu_fpr[rB(ctx->opcode)]);
> @@ -2424,8 +2401,6 @@ static void gen_fcmpo(DisasContext *ctx)
>          gen_exception(ctx, POWERPC_EXCP_FPU);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      crf = tcg_const_i32(crfD(ctx->opcode));
>      gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
> @@ -2442,8 +2417,6 @@ static void gen_fcmpu(DisasContext *ctx)
>          gen_exception(ctx, POWERPC_EXCP_FPU);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      crf = tcg_const_i32(crfD(ctx->opcode));
>      gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
> @@ -2613,8 +2586,6 @@ static void gen_mtfsb0(DisasContext *ctx)
>      gen_reset_fpstatus();
>      if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
>          TCGv_i32 t0;
> -        /* NIP cannot be restored if the memory exception comes from an 
> helper */
> -        gen_update_nip(ctx, ctx->nip - 4);
>          t0 = tcg_const_i32(crb);
>          gen_helper_fpscr_clrbit(cpu_env, t0);
>          tcg_temp_free_i32(t0);
> @@ -2639,8 +2610,6 @@ static void gen_mtfsb1(DisasContext *ctx)
>      /* XXX: we pretend we can only do IEEE floating-point computations */
>      if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
>          TCGv_i32 t0;
> -        /* NIP cannot be restored if the memory exception comes from an 
> helper */
> -        gen_update_nip(ctx, ctx->nip - 4);
>          t0 = tcg_const_i32(crb);
>          gen_helper_fpscr_setbit(cpu_env, t0);
>          tcg_temp_free_i32(t0);
> @@ -2670,8 +2639,6 @@ static void gen_mtfsf(DisasContext *ctx)
>          gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
>          return;
>      }
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      if (l) {
>          t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 
> 0xff);
> @@ -2706,8 +2673,6 @@ static void gen_mtfsfi(DisasContext *ctx)
>          return;
>      }
>      sh = (8 * w) + 7 - bf;
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_reset_fpstatus();
>      t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
>      t1 = tcg_const_i32(1 << sh);
> @@ -2790,8 +2755,6 @@ static inline void gen_check_align(DisasContext *ctx, 
> TCGv EA, int mask)
>      TCGLabel *l1 = gen_new_label();
>      TCGv t0 = tcg_temp_new();
>      TCGv_i32 t1, t2;
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      tcg_gen_andi_tl(t0, EA, mask);
>      tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
>      t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
> @@ -3261,8 +3224,6 @@ static void gen_lmw(DisasContext *ctx)
>      TCGv t0;
>      TCGv_i32 t1;
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      t1 = tcg_const_i32(rD(ctx->opcode));
>      gen_addr_imm_index(ctx, t0, 0);
> @@ -3277,8 +3238,6 @@ static void gen_stmw(DisasContext *ctx)
>      TCGv t0;
>      TCGv_i32 t1;
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      t1 = tcg_const_i32(rS(ctx->opcode));
>      gen_addr_imm_index(ctx, t0, 0);
> @@ -3312,8 +3271,6 @@ static void gen_lswi(DisasContext *ctx)
>          return;
>      }
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      gen_addr_register(ctx, t0);
>      t1 = tcg_const_i32(nb);
> @@ -3330,8 +3287,6 @@ static void gen_lswx(DisasContext *ctx)
>      TCGv t0;
>      TCGv_i32 t1, t2, t3;
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      gen_addr_reg_index(ctx, t0);
>      t1 = tcg_const_i32(rD(ctx->opcode));
> @@ -3351,8 +3306,6 @@ static void gen_stswi(DisasContext *ctx)
>      TCGv_i32 t1, t2;
>      int nb = NB(ctx->opcode);
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      gen_addr_register(ctx, t0);
>      if (nb == 0)
> @@ -3371,8 +3324,6 @@ static void gen_stswx(DisasContext *ctx)
>      TCGv t0;
>      TCGv_i32 t1, t2;
>      gen_set_access_type(ctx, ACCESS_INT);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      gen_addr_reg_index(ctx, t0);
>      t1 = tcg_temp_new_i32();
> @@ -4306,7 +4257,7 @@ static void gen_tw(DisasContext *ctx)
>  {
>      TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_stop_exception(ctx);
>      gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>                    t0);
>      tcg_temp_free_i32(t0);
> @@ -4318,7 +4269,7 @@ static void gen_twi(DisasContext *ctx)
>      TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>      TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_stop_exception(ctx);
>      gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>      tcg_temp_free(t0);
>      tcg_temp_free_i32(t1);
> @@ -4330,7 +4281,7 @@ static void gen_td(DisasContext *ctx)
>  {
>      TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_stop_exception(ctx);
>      gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>                    t0);
>      tcg_temp_free_i32(t0);
> @@ -4342,7 +4293,7 @@ static void gen_tdi(DisasContext *ctx)
>      TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>      TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_stop_exception(ctx);
>      gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>      tcg_temp_free(t0);
>      tcg_temp_free_i32(t1);
> @@ -4768,8 +4719,6 @@ static void gen_dcbz(DisasContext *ctx)
>      int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
>  
>      gen_set_access_type(ctx, ACCESS_CACHE);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      tcgv_addr = tcg_temp_new();
>      tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
>  
> @@ -4812,8 +4761,6 @@ static void gen_icbi(DisasContext *ctx)
>  {
>      TCGv t0;
>      gen_set_access_type(ctx, ACCESS_CACHE);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      t0 = tcg_temp_new();
>      gen_addr_reg_index(ctx, t0);
>      gen_helper_icbi(cpu_env, t0);
> @@ -5299,8 +5246,6 @@ static void gen_lscbx(DisasContext *ctx)
>      TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
>  
>      gen_addr_reg_index(ctx, t0);
> -    /* NIP cannot be restored if the memory exception comes from an helper */
> -    gen_update_nip(ctx, ctx->nip - 4);
>      gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
>      tcg_temp_free_i32(t1);
>      tcg_temp_free_i32(t2);
> @@ -6386,8 +6331,6 @@ static void gen_mtdcrx(DisasContext *ctx)
>  /* mfdcrux (PPC 460) : user-mode access to DCR */
>  static void gen_mfdcrux(DisasContext *ctx)
>  {
> -    /* 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 */
> @@ -6396,8 +6339,6 @@ static void gen_mfdcrux(DisasContext *ctx)
>  /* mtdcrux (PPC 460) : user-mode access to DCR */
>  static void gen_mtdcrux(DisasContext *ctx)
>  {
> -    /* 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 */
> @@ -8027,8 +7968,6 @@ static void gen_##name(DisasContext * ctx)              
>                       \
>          gen_exception(ctx, POWERPC_EXCP_VSXU);                               
>  \
>          return;                                                              
>  \
>      }                                                                        
>  \
> -    /* NIP cannot be restored if the memory exception comes from an helper 
> */ \
> -    gen_update_nip(ctx, ctx->nip - 4);                                       
>  \
>      opc = tcg_const_i32(ctx->opcode);                                        
>  \
>      gen_helper_##name(cpu_env, opc);                                         
>  \
>      tcg_temp_free_i32(opc);                                                  
>  \
> @@ -8041,9 +7980,6 @@ static void gen_##name(DisasContext * ctx)              
>       \
>          gen_exception(ctx, POWERPC_EXCP_VSXU);                \
>          return;                                               \
>      }                                                         \
> -    /* NIP cannot be restored if the exception comes */       \
> -    /* from a helper. */                                      \
> -    gen_update_nip(ctx, ctx->nip - 4);                        \
>                                                                \
>      gen_helper_##name(cpu_vsrh(xT(ctx->opcode)), cpu_env,     \
>                        cpu_vsrh(xB(ctx->opcode)));             \
> 

-- 
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]