target-ppc: Add set_fprf Argument to fload_invalid_op_excp()

The fload_invalid_op_excp() function sets assorted invalid
operation status bits.  However, it also implicitly modifies
the FPRF field of the PowerPC FPSCR.  Many VSX instructions
set invalid operation bits but do not alter FPRF.  Thus the
function is more generally useful if the setting of the FPRF
field is made conditional via a parameter.

All invocations of this routine in existing instructions are
modified to pass 1 and thus retain their current behavior.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Tom Musta 2014-01-02 16:21:19 -06:00 committed by Alexander Graf
parent 4e38181979
commit 59800ec8e5
1 changed files with 55 additions and 48 deletions

View File

@ -106,7 +106,8 @@ uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf)
} }
/* Floating-point invalid operations exception */ /* Floating-point invalid operations exception */
static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op) static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op,
int set_fpcc)
{ {
uint64_t ret = 0; uint64_t ret = 0;
int ve; int ve;
@ -138,8 +139,10 @@ static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op)
case POWERPC_EXCP_FP_VXVC: case POWERPC_EXCP_FP_VXVC:
/* Ordered comparison of NaN */ /* Ordered comparison of NaN */
env->fpscr |= 1 << FPSCR_VXVC; env->fpscr |= 1 << FPSCR_VXVC;
env->fpscr &= ~(0xF << FPSCR_FPCC); if (set_fpcc) {
env->fpscr |= 0x11 << FPSCR_FPCC; env->fpscr &= ~(0xF << FPSCR_FPCC);
env->fpscr |= 0x11 << FPSCR_FPCC;
}
/* We must update the target FPR before raising the exception */ /* We must update the target FPR before raising the exception */
if (ve != 0) { if (ve != 0) {
env->exception_index = POWERPC_EXCP_PROGRAM; env->exception_index = POWERPC_EXCP_PROGRAM;
@ -158,8 +161,10 @@ static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op)
if (ve == 0) { if (ve == 0) {
/* Set the result to quiet NaN */ /* Set the result to quiet NaN */
ret = 0x7FF8000000000000ULL; ret = 0x7FF8000000000000ULL;
env->fpscr &= ~(0xF << FPSCR_FPCC); if (set_fpcc) {
env->fpscr |= 0x11 << FPSCR_FPCC; env->fpscr &= ~(0xF << FPSCR_FPCC);
env->fpscr |= 0x11 << FPSCR_FPCC;
}
} }
break; break;
case POWERPC_EXCP_FP_VXCVI: case POWERPC_EXCP_FP_VXCVI:
@ -169,8 +174,10 @@ static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op)
if (ve == 0) { if (ve == 0) {
/* Set the result to quiet NaN */ /* Set the result to quiet NaN */
ret = 0x7FF8000000000000ULL; ret = 0x7FF8000000000000ULL;
env->fpscr &= ~(0xF << FPSCR_FPCC); if (set_fpcc) {
env->fpscr |= 0x11 << FPSCR_FPCC; env->fpscr &= ~(0xF << FPSCR_FPCC);
env->fpscr |= 0x11 << FPSCR_FPCC;
}
} }
break; break;
} }
@ -505,12 +512,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) && if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) { float64_is_signaling_nan(farg2.d))) {
/* sNaN addition */ /* sNaN addition */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
} }
@ -529,12 +536,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) && if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) { float64_is_signaling_nan(farg2.d))) {
/* sNaN subtraction */ /* sNaN subtraction */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
} }
@ -553,12 +560,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)) || if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */ /* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) { float64_is_signaling_nan(farg2.d))) {
/* sNaN multiplication */ /* sNaN multiplication */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
} }
@ -577,15 +584,15 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
if (unlikely(float64_is_infinity(farg1.d) && if (unlikely(float64_is_infinity(farg1.d) &&
float64_is_infinity(farg2.d))) { float64_is_infinity(farg2.d))) {
/* Division of infinity by infinity */ /* Division of infinity by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
} else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) { } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
/* Division of zero by zero */ /* Division of zero by zero */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) { float64_is_signaling_nan(farg2.d))) {
/* sNaN division */ /* sNaN division */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
} }
@ -603,11 +610,11 @@ uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */ /* sNaN conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXCVI); POWERPC_EXCP_FP_VXCVI, 1);
} else if (unlikely(float64_is_quiet_nan(farg.d) || } else if (unlikely(float64_is_quiet_nan(farg.d) ||
float64_is_infinity(farg.d))) { float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */ /* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
} else { } else {
farg.ll = float64_to_int32(farg.d, &env->fp_status); farg.ll = float64_to_int32(farg.d, &env->fp_status);
/* XXX: higher bits are not supposed to be significant. /* XXX: higher bits are not supposed to be significant.
@ -628,11 +635,11 @@ uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */ /* sNaN conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXCVI); POWERPC_EXCP_FP_VXCVI, 1);
} else if (unlikely(float64_is_quiet_nan(farg.d) || } else if (unlikely(float64_is_quiet_nan(farg.d) ||
float64_is_infinity(farg.d))) { float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */ /* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
} else { } else {
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status); farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
/* XXX: higher bits are not supposed to be significant. /* XXX: higher bits are not supposed to be significant.
@ -663,11 +670,11 @@ uint64_t helper_fctid(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */ /* sNaN conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXCVI); POWERPC_EXCP_FP_VXCVI, 1);
} else if (unlikely(float64_is_quiet_nan(farg.d) || } else if (unlikely(float64_is_quiet_nan(farg.d) ||
float64_is_infinity(farg.d))) { float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */ /* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
} else { } else {
farg.ll = float64_to_int64(farg.d, &env->fp_status); farg.ll = float64_to_int64(farg.d, &env->fp_status);
} }
@ -684,11 +691,11 @@ uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */ /* sNaN conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXCVI); POWERPC_EXCP_FP_VXCVI, 1);
} else if (unlikely(float64_is_quiet_nan(farg.d) || } else if (unlikely(float64_is_quiet_nan(farg.d) ||
float64_is_infinity(farg.d))) { float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */ /* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
} else { } else {
farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status); farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
} }
@ -707,11 +714,11 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN round */ /* sNaN round */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXCVI); POWERPC_EXCP_FP_VXCVI, 1);
} else if (unlikely(float64_is_quiet_nan(farg.d) || } else if (unlikely(float64_is_quiet_nan(farg.d) ||
float64_is_infinity(farg.d))) { float64_is_infinity(farg.d))) {
/* qNan / infinity round */ /* qNan / infinity round */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
} else { } else {
set_float_rounding_mode(rounding_mode, &env->fp_status); set_float_rounding_mode(rounding_mode, &env->fp_status);
farg.ll = float64_round_to_int(farg.d, &env->fp_status); farg.ll = float64_round_to_int(farg.d, &env->fp_status);
@ -754,13 +761,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)) || if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */ /* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) || float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) { float64_is_signaling_nan(farg3.d))) {
/* sNaN operation */ /* sNaN operation */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
/* This is the way the PowerPC specification defines it */ /* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128; float128 ft0_128, ft1_128;
@ -772,7 +779,7 @@ uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
float64_is_infinity(farg3.d) && float64_is_infinity(farg3.d) &&
float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
ft1_128 = float64_to_float128(farg3.d, &env->fp_status); ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
@ -797,13 +804,13 @@ uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
(float64_is_zero(farg1.d) && (float64_is_zero(farg1.d) &&
float64_is_infinity(farg2.d)))) { float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */ /* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) || float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) { float64_is_signaling_nan(farg3.d))) {
/* sNaN operation */ /* sNaN operation */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
/* This is the way the PowerPC specification defines it */ /* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128; float128 ft0_128, ft1_128;
@ -815,7 +822,7 @@ uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
float64_is_infinity(farg3.d) && float64_is_infinity(farg3.d) &&
float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
ft1_128 = float64_to_float128(farg3.d, &env->fp_status); ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
@ -838,13 +845,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)) || if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */ /* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) || float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) { float64_is_signaling_nan(farg3.d))) {
/* sNaN operation */ /* sNaN operation */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
/* This is the way the PowerPC specification defines it */ /* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128; float128 ft0_128, ft1_128;
@ -856,7 +863,7 @@ uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
float64_is_infinity(farg3.d) && float64_is_infinity(farg3.d) &&
float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
ft1_128 = float64_to_float128(farg3.d, &env->fp_status); ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
@ -883,13 +890,13 @@ uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
(float64_is_zero(farg1.d) && (float64_is_zero(farg1.d) &&
float64_is_infinity(farg2.d)))) { float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */ /* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg1.d) || if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) || float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) { float64_is_signaling_nan(farg3.d))) {
/* sNaN operation */ /* sNaN operation */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
/* This is the way the PowerPC specification defines it */ /* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128; float128 ft0_128, ft1_128;
@ -901,7 +908,7 @@ uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
float64_is_infinity(farg3.d) && float64_is_infinity(farg3.d) &&
float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
/* Magnitude subtraction of infinities */ /* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI); farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
} else { } else {
ft1_128 = float64_to_float128(farg3.d, &env->fp_status); ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
@ -924,7 +931,7 @@ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */ /* sNaN square root */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
f32 = float64_to_float32(farg.d, &env->fp_status); f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status); farg.d = float32_to_float64(f32, &env->fp_status);
@ -941,11 +948,11 @@ uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Square root of a negative nonzero number */ /* Square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */ /* sNaN square root */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg.d = float64_sqrt(farg.d, &env->fp_status); farg.d = float64_sqrt(farg.d, &env->fp_status);
} }
@ -961,7 +968,7 @@ uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */ /* sNaN reciprocal */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg.d = float64_div(float64_one, farg.d, &env->fp_status); farg.d = float64_div(float64_one, farg.d, &env->fp_status);
return farg.d; return farg.d;
@ -977,7 +984,7 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */ /* sNaN reciprocal */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg.d = float64_div(float64_one, farg.d, &env->fp_status); farg.d = float64_div(float64_one, farg.d, &env->fp_status);
f32 = float64_to_float32(farg.d, &env->fp_status); f32 = float64_to_float32(farg.d, &env->fp_status);
@ -996,11 +1003,11 @@ uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Reciprocal square root of a negative nonzero number */ /* Reciprocal square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT); farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
} else { } else {
if (unlikely(float64_is_signaling_nan(farg.d))) { if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal square root */ /* sNaN reciprocal square root */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
farg.d = float64_sqrt(farg.d, &env->fp_status); farg.d = float64_sqrt(farg.d, &env->fp_status);
farg.d = float64_div(float64_one, farg.d, &env->fp_status); farg.d = float64_div(float64_one, farg.d, &env->fp_status);
@ -1053,7 +1060,7 @@ void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
&& (float64_is_signaling_nan(farg1.d) || && (float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d)))) { float64_is_signaling_nan(farg2.d)))) {
/* sNaN comparison */ /* sNaN comparison */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
} }
} }
@ -1085,10 +1092,10 @@ void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
float64_is_signaling_nan(farg2.d)) { float64_is_signaling_nan(farg2.d)) {
/* sNaN comparison */ /* sNaN comparison */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN | fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
POWERPC_EXCP_FP_VXVC); POWERPC_EXCP_FP_VXVC, 1);
} else { } else {
/* qNaN comparison */ /* qNaN comparison */
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC); fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
} }
} }
} }