summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorGiuseppe Musacchio2020-11-13 00:01:29 +0100
committerDavid Gibson2020-12-14 05:53:52 +0100
commitbc92c260f6f0da73d3bdee5e1c2bf38d6f22e20a (patch)
treeda1d5c4702c49ca4f74b04ec27b9b0f71d59657b /target
parentppc/translate: Turn the helper macros into functions (diff)
downloadqemu-bc92c260f6f0da73d3bdee5e1c2bf38d6f22e20a.tar.gz
qemu-bc92c260f6f0da73d3bdee5e1c2bf38d6f22e20a.tar.xz
qemu-bc92c260f6f0da73d3bdee5e1c2bf38d6f22e20a.zip
ppc/translate: Delay NaN checking after comparison
Since we always perform a comparison between the two operands avoid checking for NaN unless the result states they're unordered. Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Giuseppe Musacchio <thatlemon@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20201112230130.65262-4-thatlemon@gmail.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target')
-rw-r--r--target/ppc/fpu_helper.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 34f5bc1f3c..f5a4be595a 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2475,25 +2475,6 @@ static inline void do_scalar_cmp(CPUPPCState *env, ppc_vsr_t *xa, ppc_vsr_t *xb,
helper_reset_fpstatus(env);
- if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) ||
- float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) {
- vxsnan_flag = true;
- if (fpscr_ve == 0 && ordered) {
- vxvc_flag = true;
- }
- } else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) ||
- float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) {
- if (ordered) {
- vxvc_flag = true;
- }
- }
- if (vxsnan_flag) {
- float_invalid_op_vxsnan(env, GETPC());
- }
- if (vxvc_flag) {
- float_invalid_op_vxvc(env, 0, GETPC());
- }
-
switch (float64_compare(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) {
case float_relation_less:
cc = CRF_LT;
@@ -2506,6 +2487,27 @@ static inline void do_scalar_cmp(CPUPPCState *env, ppc_vsr_t *xa, ppc_vsr_t *xb,
break;
case float_relation_unordered:
cc = CRF_SO;
+
+ if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) ||
+ float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) {
+ vxsnan_flag = true;
+ if (fpscr_ve == 0 && ordered) {
+ vxvc_flag = true;
+ }
+ } else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) ||
+ float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) {
+ if (ordered) {
+ vxvc_flag = true;
+ }
+ }
+
+ if (vxsnan_flag) {
+ float_invalid_op_vxsnan(env, GETPC());
+ }
+ if (vxvc_flag) {
+ float_invalid_op_vxvc(env, 0, GETPC());
+ }
+
break;
default:
g_assert_not_reached();
@@ -2538,25 +2540,6 @@ static inline void do_scalar_cmpq(CPUPPCState *env, ppc_vsr_t *xa,
helper_reset_fpstatus(env);
- if (float128_is_signaling_nan(xa->f128, &env->fp_status) ||
- float128_is_signaling_nan(xb->f128, &env->fp_status)) {
- vxsnan_flag = true;
- if (fpscr_ve == 0 && ordered) {
- vxvc_flag = true;
- }
- } else if (float128_is_quiet_nan(xa->f128, &env->fp_status) ||
- float128_is_quiet_nan(xb->f128, &env->fp_status)) {
- if (ordered) {
- vxvc_flag = true;
- }
- }
- if (vxsnan_flag) {
- float_invalid_op_vxsnan(env, GETPC());
- }
- if (vxvc_flag) {
- float_invalid_op_vxvc(env, 0, GETPC());
- }
-
switch (float128_compare(xa->f128, xb->f128, &env->fp_status)) {
case float_relation_less:
cc = CRF_LT;
@@ -2569,6 +2552,27 @@ static inline void do_scalar_cmpq(CPUPPCState *env, ppc_vsr_t *xa,
break;
case float_relation_unordered:
cc = CRF_SO;
+
+ if (float128_is_signaling_nan(xa->f128, &env->fp_status) ||
+ float128_is_signaling_nan(xb->f128, &env->fp_status)) {
+ vxsnan_flag = true;
+ if (fpscr_ve == 0 && ordered) {
+ vxvc_flag = true;
+ }
+ } else if (float128_is_quiet_nan(xa->f128, &env->fp_status) ||
+ float128_is_quiet_nan(xb->f128, &env->fp_status)) {
+ if (ordered) {
+ vxvc_flag = true;
+ }
+ }
+
+ if (vxsnan_flag) {
+ float_invalid_op_vxsnan(env, GETPC());
+ }
+ if (vxvc_flag) {
+ float_invalid_op_vxvc(env, 0, GETPC());
+ }
+
break;
default:
g_assert_not_reached();