summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-03-11 08:12:22 +0000
committerAurelien Jarno <aurelien@aurel32.net>2011-04-03 17:05:43 +0200
commitc7498daea76948128c1298d78fe9e7e618b5ff7c (patch)
tree5017076df77d382bcdd2d90d56e112e8173de251
parent51d852672cb8536c541ed5b1dc4ee8f989a96cd7 (diff)
downloadqemu-c7498daea76948128c1298d78fe9e7e618b5ff7c.tar.gz
target-arm: Return right result for Neon comparison with NaNs
Fix the helper functions implementing the Neon floating point comparison ops (VCGE, VCGT, VCEQ, VACGT, VACGE) to return the right answer when one of the values being compared is a NaN. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--target-arm/neon_helper.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 2108664adc..9d54a75ef3 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1810,32 +1810,40 @@ uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b)
}
/* Floating point comparisons produce an integer result. */
-#define NEON_VOP_FCMP(name, cmp) \
+#define NEON_VOP_FCMP(name, ok) \
uint32_t HELPER(neon_##name)(uint32_t a, uint32_t b) \
{ \
- if (float32_compare_quiet(make_float32(a), make_float32(b), NFS) cmp 0) { \
- return ~0; \
- } else { \
- return 0; \
+ switch (float32_compare_quiet(make_float32(a), make_float32(b), NFS)) { \
+ ok return ~0; \
+ default: return 0; \
} \
}
-NEON_VOP_FCMP(ceq_f32, ==)
-NEON_VOP_FCMP(cge_f32, >=)
-NEON_VOP_FCMP(cgt_f32, >)
+NEON_VOP_FCMP(ceq_f32, case float_relation_equal:)
+NEON_VOP_FCMP(cge_f32, case float_relation_equal: case float_relation_greater:)
+NEON_VOP_FCMP(cgt_f32, case float_relation_greater:)
uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b)
{
float32 f0 = float32_abs(make_float32(a));
float32 f1 = float32_abs(make_float32(b));
- return (float32_compare_quiet(f0, f1,NFS) >= 0) ? ~0 : 0;
+ switch (float32_compare_quiet(f0, f1, NFS)) {
+ case float_relation_equal:
+ case float_relation_greater:
+ return ~0;
+ default:
+ return 0;
+ }
}
uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
{
float32 f0 = float32_abs(make_float32(a));
float32 f1 = float32_abs(make_float32(b));
- return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0;
+ if (float32_compare_quiet(f0, f1, NFS) == float_relation_greater) {
+ return ~0;
+ }
+ return 0;
}
#define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))