* [Qemu-devel] [PATCH 1/3] target-ppc: remove PRECISE_EMULATION define
2011-01-02 14:39 [Qemu-devel] [PATCH 0/3] target-ppc: improve FPU emulation Aurelien Jarno
@ 2011-01-02 14:39 ` Aurelien Jarno
2011-01-05 17:02 ` [Qemu-devel] " Alexander Graf
2011-01-02 14:39 ` [Qemu-devel] [PATCH 2/3] target-ppc: fix default qNaN Aurelien Jarno
2011-01-02 14:39 ` [Qemu-devel] [PATCH 3/3] target-ppc: fix sNaN propagation Aurelien Jarno
2 siblings, 1 reply; 11+ messages in thread
From: Aurelien Jarno @ 2011-01-02 14:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf, Aurelien Jarno
The PRECISE_EMULATION is "hardcoded" to one in target-ppc/exec.h and not
something easily tunable. Remove it and non-precise emulation code as
it doesn't make a noticeable difference in speed. People wanting speed
improvement should use softfloat-native instead.
Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
target-ppc/exec.h | 3 --
target-ppc/op_helper.c | 58 +++++++++--------------------------------------
2 files changed, 11 insertions(+), 50 deletions(-)
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
index 44cc5e9..4688ef5 100644
--- a/target-ppc/exec.h
+++ b/target-ppc/exec.h
@@ -26,9 +26,6 @@
#include "cpu.h"
#include "exec-all.h"
-/* Precise emulation is needed to correctly emulate exception flags */
-#define USE_PRECISE_EMULATION 1
-
register struct CPUPPCState *env asm(AREG0);
#if !defined(CONFIG_USER_ONLY)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 89be0f4..858877e 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -974,7 +974,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
-#if USE_PRECISE_EMULATION
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN addition */
@@ -986,9 +986,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
-#else
- farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
-#endif
+
return farg1.ll;
}
@@ -999,8 +997,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
-#if USE_PRECISE_EMULATION
-{
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN subtraction */
@@ -1012,10 +1009,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
-}
-#else
- farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
-#endif
+
return farg1.ll;
}
@@ -1026,7 +1020,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
-#if USE_PRECISE_EMULATION
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN multiplication */
@@ -1038,9 +1032,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
}
-#else
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
-#endif
+
return farg1.ll;
}
@@ -1051,7 +1043,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
-#if USE_PRECISE_EMULATION
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN division */
@@ -1065,9 +1057,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
-#else
- farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
-#endif
+
return farg1.ll;
}
@@ -1116,12 +1106,10 @@ uint64_t helper_fctiw (uint64_t arg)
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
farg.ll = float64_to_int32(farg.d, &env->fp_status);
-#if USE_PRECISE_EMULATION
/* XXX: higher bits are not supposed to be significant.
* to make tests easier, return the same as a real PowerPC 750
*/
farg.ll |= 0xFFF80000ULL << 32;
-#endif
}
return farg.ll;
}
@@ -1140,12 +1128,10 @@ uint64_t helper_fctiwz (uint64_t arg)
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
-#if USE_PRECISE_EMULATION
/* XXX: higher bits are not supposed to be significant.
* to make tests easier, return the same as a real PowerPC 750
*/
farg.ll |= 0xFFF80000ULL << 32;
-#endif
}
return farg.ll;
}
@@ -1245,7 +1231,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
farg2.ll = arg2;
farg3.ll = arg3;
-#if USE_PRECISE_EMULATION
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
@@ -1277,10 +1263,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
}
-#else
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
- farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
-#endif
+
return farg1.ll;
}
@@ -1292,7 +1275,7 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
farg2.ll = arg2;
farg3.ll = arg3;
-#if USE_PRECISE_EMULATION
+
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
@@ -1324,10 +1307,6 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
}
-#else
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
- farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
-#endif
return farg1.ll;
}
@@ -1350,7 +1329,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
-#if USE_PRECISE_EMULATION
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1371,10 +1349,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
-#else
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
- farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
-#endif
if (likely(!float64_is_quiet_nan(farg1.d)))
farg1.d = float64_chs(farg1.d);
}
@@ -1400,7 +1374,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
-#if USE_PRECISE_EMULATION
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1421,10 +1394,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
-#else
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
- farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
-#endif
if (likely(!float64_is_quiet_nan(farg1.d)))
farg1.d = float64_chs(farg1.d);
}
@@ -1438,7 +1407,6 @@ uint64_t helper_frsp (uint64_t arg)
float32 f32;
farg.ll = arg;
-#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
@@ -1446,10 +1414,6 @@ uint64_t helper_frsp (uint64_t arg)
f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status);
}
-#else
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
-#endif
return farg.ll;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 3/3] target-ppc: fix sNaN propagation
2011-01-02 14:39 [Qemu-devel] [PATCH 0/3] target-ppc: improve FPU emulation Aurelien Jarno
2011-01-02 14:39 ` [Qemu-devel] [PATCH 1/3] target-ppc: remove PRECISE_EMULATION define Aurelien Jarno
2011-01-02 14:39 ` [Qemu-devel] [PATCH 2/3] target-ppc: fix default qNaN Aurelien Jarno
@ 2011-01-02 14:39 ` Aurelien Jarno
2011-01-05 17:20 ` [Qemu-devel] " Alexander Graf
2011-01-11 0:14 ` [Qemu-devel] " Peter Maydell
2 siblings, 2 replies; 11+ messages in thread
From: Aurelien Jarno @ 2011-01-02 14:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf, Aurelien Jarno
The current FPU code returns 0.0 if one of the operand is a
signaling NaN and the VXSNAN exception is disabled.
fload_invalid_op_excp() doesn't return a qNaN in case of a VXSNAN
exception as the operand should be propagated instead of a new
qNaN to be generated. Fix that by calling fload_invalid_op_excp()
only for the exception generation (if enabled), and use the softfloat
code to correctly compute the result.
Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
target-ppc/op_helper.c | 145 +++++++++++++++++++++++++----------------------
1 files changed, 77 insertions(+), 68 deletions(-)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 279f345..ea030d0 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -975,15 +975,16 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN addition */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
+ 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(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN addition */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
@@ -998,15 +999,16 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN subtraction */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
+ 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(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN subtraction */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
@@ -1021,16 +1023,17 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN multiplication */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ 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(POWERPC_EXCP_FP_VXIMZ);
} else {
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN multiplication */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
+ float64_mul(farg1.d, farg2.d, &env->fp_status);
}
return farg1.ll;
@@ -1044,17 +1047,18 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN division */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
/* Division of infinity by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
} else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
/* Division of zero by zero */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN division */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
@@ -1232,16 +1236,17 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ 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(POWERPC_EXCP_FP_VXIMZ);
} 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(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1276,16 +1281,17 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else 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)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} 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(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1319,16 +1325,17 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ 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(POWERPC_EXCP_FP_VXIMZ);
} 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(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1364,16 +1371,17 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else 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)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} 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(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1410,10 +1418,10 @@ uint64_t helper_frsp (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
}
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1423,13 +1431,14 @@ uint64_t helper_fsqrt (uint64_t arg)
CPU_DoubleU farg;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else 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 */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(farg.d, &env->fp_status);
}
return farg.ll;
@@ -1443,10 +1452,9 @@ uint64_t helper_fre (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
return farg.d;
}
@@ -1460,11 +1468,11 @@ uint64_t helper_fres (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, 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 = float64_div(float64_one, farg.d, &env->fp_status);
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1475,13 +1483,14 @@ uint64_t helper_frsqrte (uint64_t arg)
float32 f32;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN reciprocal square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else 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 */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN reciprocal square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(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);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread