@@ -2391,4 +2391,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 /* !defined (__CPU_PPC_H__) */
@@ -887,8 +887,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));
@@ -897,15 +897,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);
}
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;
@@ -914,7 +931,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);
}
}
@@ -1015,8 +1033,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);
}
}
@@ -1029,8 +1048,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
@@ -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) ||
float64_is_signaling_nan(farg2.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d))) {
/* 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)) { \
- 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))) {
/* 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) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
/* 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) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
/* 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))) {
/* 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))) {
/* 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))) {
/* 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))) {
/* 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))) {
/* 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) ||
float64_is_signaling_nan(farg2.d)))) {
/* 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)) {
/* 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) || \
tp##_is_signaling_nan(xb.fld)) { \
- 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) || \
tp##_is_signaling_nan(xb.fld)) { \
- 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) || \
tp##_is_signaling_nan(xb.fld)) { \
- 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))) { \
- 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)) { \
- 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)) { \
- 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) || \
tp##_is_signaling_nan(b->fld) || \
tp##_is_signaling_nan(c->fld)) { \
- 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)) || \
float64_is_signaling_nan(xb.VsrD(0))) { \
- 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) || \
tp##_is_signaling_nan(xb.fld))) { \
- 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) || \
tp##_is_signaling_nan(xb.fld)) { \
- 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)
@@ -2501,7 +2507,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb.sfld))) { \
- 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) { \
@@ -2511,7 +2517,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)
@@ -2556,21 +2562,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)) { \
- 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), \
@@ -2621,7 +2627,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)
@@ -2665,7 +2671,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_signaling_nan(xb.fld))) { \
- 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); \
@@ -2684,7 +2690,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_nearest_even, 1)
@@ -2712,6 +2718,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;
}
@@ -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)
@@ -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);
}
@@ -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
}
@@ -224,8 +224,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());
}
}
@@ -235,8 +235,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;
}
@@ -247,8 +247,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;
}
@@ -2608,9 +2608,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 */
@@ -2618,9 +2618,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) {
@@ -2902,10 +2902,6 @@ void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, 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);
}
}
@@ -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"
/*****************************************************************************/
@@ -133,15 +134,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;
}
@@ -150,14 +151,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());
}
}
@@ -291,7 +291,7 @@ static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t
}
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);
@@ -299,14 +299,7 @@ static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t
static inline 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 inline void gen_debug_exception(DisasContext *ctx)
@@ -2070,8 +2063,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)], \
@@ -2099,8 +2090,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)], \
@@ -2127,8 +2116,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)], \
@@ -2155,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##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
cpu_fpr[rB(ctx->opcode)]); \
@@ -2175,8 +2160,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)]); \
@@ -2211,8 +2194,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)]);
@@ -2237,8 +2218,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)]);
@@ -2254,8 +2233,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)]);
@@ -2345,8 +2322,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)],
@@ -2363,8 +2338,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)],
@@ -2534,8 +2507,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);
@@ -2560,8 +2531,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);
@@ -2591,8 +2560,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);
@@ -2627,8 +2594,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);
@@ -2711,8 +2676,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);
@@ -3160,8 +3123,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);
@@ -3176,8 +3137,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);
@@ -3211,8 +3170,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);
@@ -3229,8 +3186,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));
@@ -3250,8 +3205,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)
@@ -3270,8 +3223,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();
@@ -4139,7 +4090,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);
@@ -4151,7 +4102,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);
@@ -4163,7 +4114,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);
@@ -4175,7 +4126,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);
@@ -4580,8 +4531,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);
@@ -4624,8 +4573,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);
@@ -5120,8 +5067,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);
@@ -6175,8 +6120,6 @@ static void gen_mfdcr(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
return;
}
- /* 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);
@@ -6194,8 +6137,6 @@ static void gen_mtdcr(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
return;
}
- /* 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);
@@ -6213,8 +6154,6 @@ static void gen_mfdcrx(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
return;
}
- /* 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 */
@@ -6232,8 +6171,6 @@ static void gen_mtdcrx(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
return;
}
- /* 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 */
@@ -6243,8 +6180,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 */
@@ -6253,8 +6188,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 */
@@ -7963,8 +7896,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); \
@@ -7977,9 +7908,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))); \