Fix bugs with float compare and Inf operands.
authorJim Wilson <jim.wilson@linaro.org>
Wed, 21 Dec 2016 20:33:12 +0000 (12:33 -0800)
committerJim Wilson <jim.wilson@linaro.org>
Wed, 21 Dec 2016 20:33:12 +0000 (12:33 -0800)
sim/aarch64/
* simulator.c (set_flags_for_float_compare): Add code to handle Inf.
Add comment to document NaN issue.
(set_flags_for_double_compare): Likewise.

sim/testsuite/sim/aarch64/
* fcmp.s: New.

sim/aarch64/ChangeLog
sim/aarch64/simulator.c
sim/testsuite/sim/aarch64/ChangeLog
sim/testsuite/sim/aarch64/fcmp.s [new file with mode: 0644]

index 2346a49..b1baf26 100644 (file)
@@ -1,3 +1,9 @@
+2016-12-21  Jim Wilson  <jim.wilson@linaro.org>
+
+       * simulator.c (set_flags_for_float_compare): Add code to handle Inf.
+       Add comment to document NaN issue.
+       (set_flags_for_double_compare): Likewise.
+
 2016-12-13  Jim Wilson  <jim.wilson@linaro.org>
 
        * simulator.c (NEG, POS): Move before set_flags_for_add64.
index e6406dc..be3d6c7 100644 (file)
@@ -8468,8 +8468,22 @@ set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
 {
   uint32_t flags;
 
+  /* FIXME: Add exception raising.  */
   if (isnan (fvalue1) || isnan (fvalue2))
     flags = C|V;
+  else if (isinf (fvalue1) && isinf (fvalue2))
+    {
+      /* Subtracting two infinities may give a NaN.  We only need to compare
+        the signs, which we can get from isinf.  */
+      int result = isinf (fvalue1) - isinf (fvalue2);
+
+      if (result == 0)
+       flags = Z|C;
+      else if (result < 0)
+       flags = N;
+      else /* (result > 0).  */
+       flags = C;
+    }
   else
     {
       float result = fvalue1 - fvalue2;
@@ -8540,8 +8554,22 @@ set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
 {
   uint32_t flags;
 
+  /* FIXME: Add exception raising.  */
   if (isnan (dval1) || isnan (dval2))
     flags = C|V;
+  else if (isinf (dval1) && isinf (dval2))
+    {
+      /* Subtracting two infinities may give a NaN.  We only need to compare
+        the signs, which we can get from isinf.  */
+      int result = isinf (dval1) - isinf (dval2);
+
+      if (result == 0)
+       flags = Z|C;
+      else if (result < 0)
+       flags = N;
+      else /* (result > 0).  */
+       flags = C;
+    }
   else
     {
       double result = dval1 - dval2;
index ff047e3..a130a97 100644 (file)
@@ -1,3 +1,7 @@
+2016-12-21  Jim Wilson  <jim.wilson@linaro.org>
+
+       * fcmp.s: New.
+
 2016-12-13  Jim Wilson  <jim.wilson@linaro.org>
 
        * testutils.inc (pass): Move .Lpass to start.
diff --git a/sim/testsuite/sim/aarch64/fcmp.s b/sim/testsuite/sim/aarch64/fcmp.s
new file mode 100644 (file)
index 0000000..fd826c4
--- /dev/null
@@ -0,0 +1,146 @@
+# mach: aarch64
+
+# Check the FP compare instructions: fcmps, fcmpzs, fcmpes, fcmpzes, fcmpd,
+# fcmpzd, fcmped, fcmpzed.
+# For 1 operand compares, check 0, 1, -1, +Inf, -Inf.
+# For 2 operand compares, check 1/1, 1/-2, -1/2, +Inf/+Inf, +Inf/-Inf.
+# FIXME: Check for qNaN and sNaN when exception raising support added.
+
+.include "testutils.inc"
+
+       start
+       fmov s0, wzr
+       fcmp s0, #0.0
+       bne .Lfailure
+       fcmpe s0, #0.0
+       bne .Lfailure
+       fmov d0, xzr
+       fcmp d0, #0.0
+       bne .Lfailure
+       fcmpe d0, #0.0
+       bne .Lfailure
+
+       fmov s0, #1.0
+       fcmp s0, #0.0
+       blo .Lfailure
+       fcmpe s0, #0.0
+       blo .Lfailure
+       fmov d0, #1.0
+       fcmp d0, #0.0
+       blo .Lfailure
+       fcmpe d0, #0.0
+       blo .Lfailure
+
+       fmov s0, #-1.0
+       fcmp s0, #0.0
+       bpl .Lfailure
+       fcmpe s0, #0.0
+       bpl .Lfailure
+       fmov d0, #-1.0
+       fcmp d0, #0.0
+       bpl .Lfailure
+       fcmpe d0, #0.0
+       bpl .Lfailure
+
+       fmov s0, #1.0
+       fmov s1, wzr
+       fdiv s0, s0, s1
+       fcmp s0, #0.0
+       blo .Lfailure
+       fcmpe s0, #0.0
+       blo .Lfailure
+       fmov d0, #1.0
+       fmov d1, xzr
+       fdiv d0, d0, d1
+       fcmp d0, #0.0
+       blo .Lfailure
+       fcmpe d0, #0.0
+       blo .Lfailure
+
+       fmov s0, #-1.0
+       fmov s1, wzr
+       fdiv s0, s0, s1
+       fcmp s0, #0.0
+       bpl .Lfailure
+       fcmpe s0, #0.0
+       bpl .Lfailure
+       fmov d0, #-1.0
+       fmov d1, xzr
+       fdiv d0, d0, d1
+       fcmp d0, #0.0
+       bpl .Lfailure
+       fcmpe d0, #0.0
+       bpl .Lfailure
+
+       fmov s0, #1.0
+       fmov s1, #1.0
+       fcmp s0, s1
+       bne .Lfailure
+       fcmpe s0, s1
+       bne .Lfailure
+       fmov d0, #1.0
+       fmov d1, #1.0
+       fcmp d0, d1
+       bne .Lfailure
+       fcmpe d0, d1
+       bne .Lfailure
+
+       fmov s0, #1.0
+       fmov s1, #-2.0
+       fcmp s0, s1
+       blo .Lfailure
+       fcmpe s0, s1
+       blo .Lfailure
+       fmov d0, #1.0
+       fmov d1, #-2.0
+       fcmp d0, d1
+       blo .Lfailure
+       fcmpe d0, d1
+       blo .Lfailure
+
+       fmov s0, #-1.0
+       fmov s1, #2.0
+       fcmp s0, s1
+       bpl .Lfailure
+       fcmpe s0, s1
+       bpl .Lfailure
+       fmov d0, #-1.0
+       fmov d1, #2.0
+       fcmp d0, d1
+       bpl .Lfailure
+       fcmpe d0, d1
+       bpl .Lfailure
+
+       fmov s0, #1.0
+       fmov s1, wzr
+       fdiv s0, s0, s1
+       fcmp s0, s0
+       bne .Lfailure
+       fcmpe s0, s0
+       bne .Lfailure
+       fmov s1, #-1.0
+       fmov s2, wzr
+       fdiv s1, s1, s2
+       fcmp s0, s1
+       blo .Lfailure
+       fcmpe s0, s1
+       blo .Lfailure
+
+       fmov d0, #1.0
+       fmov d1, xzr
+       fdiv d0, d0, d1
+       fcmp d0, d0
+       bne .Lfailure
+       fcmpe d0, d0
+       bne .Lfailure
+       fmov d1, #-1.0
+       fmov d2, xzr
+       fdiv d1, d1, d2
+       fcmp d0, d1
+       blo .Lfailure
+       fcmpe d0, d1
+       blo .Lfailure
+
+       pass
+.Lfailure:
+       fail