This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] aarch64 sim fp min/max number bug fix


The fp min/max number routines are using fpclassify to try to
distinguish between a nan and a number, but this is handling zero,
inf, and subnormals incorrectly.  We get the right result if we just
use isnan.

The testcase works with the patch, and fails without the patch.  The
patch also reduces GCC C testsuite failures from 2416 to 2407.

Jim
	sim/aarch64/
	* simulator.c (fmaxnm): Use isnan instead of fpclassify.
	(fminnm, dmaxnm, dminnm): Likewise.

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

diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c
index be3d6c7..cf65a51 100644
--- a/sim/aarch64/simulator.c
+++ b/sim/aarch64/simulator.c
@@ -3831,13 +3831,13 @@ do_vec_MLA (sim_cpu *cpu)
 static float
 fmaxnm (float a, float b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a > b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3845,13 +3845,13 @@ fmaxnm (float a, float b)
 static float
 fminnm (float a, float b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a < b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3859,13 +3859,13 @@ fminnm (float a, float b)
 static double
 dmaxnm (double a, double b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a > b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
@@ -3873,13 +3873,13 @@ dmaxnm (double a, double b)
 static double
 dminnm (double a, double b)
 {
-  if (fpclassify (a) == FP_NORMAL)
+  if (! isnan (a))
     {
-      if (fpclassify (b) == FP_NORMAL)
+      if (! isnan (b))
 	return a < b ? a : b;
       return a;
     }
-  else if (fpclassify (b) == FP_NORMAL)
+  else if (! isnan (b))
     return b;
   return a;
 }
diff --git a/sim/testsuite/sim/aarch64/fminnm.s b/sim/testsuite/sim/aarch64/fminnm.s
new file mode 100644
index 0000000..43ccd7c
--- /dev/null
+++ b/sim/testsuite/sim/aarch64/fminnm.s
@@ -0,0 +1,82 @@
+# mach: aarch64
+
+# Check the FP min/max number instructions: fminnm, fmaxnm, dminnm, dmaxnm.
+# For min, check 2/1, 1/0, -1/-Inf.
+# For max, check 1/2, -1/0, 1/+inf.
+
+.include "testutils.inc"
+
+	start
+	fmov s0, #2.0
+	fmov s1, #1.0
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #2.0
+	fmov d1, #1.0
+	fminnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, wzr
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, xzr
+	fminnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #-1.0
+	fmov s1, wzr
+	fdiv s1, s0, s1
+	fminnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #-1.0
+	fmov d1, xzr
+	fdiv d1, d0, d1
+	fminnm d1, d0, d1
+	fcmp d0, d0
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, #2.0
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, #2.0
+	fmaxnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #-1.0
+	fmov s1, wzr
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #-1.0
+	fmov d1, xzr
+	fmaxnm d2, d0, d1
+	fcmp d2, d1
+	bne .Lfailure
+
+	fmov s0, #1.0
+	fmov s1, wzr
+	fdiv s1, s0, s1
+	fmaxnm s2, s0, s1
+	fcmp s2, s1
+	bne .Lfailure
+	fmov d0, #1.0
+	fmov d1, xzr
+	fdiv d1, d0, d1
+	fmaxnm d1, d0, d1
+	fcmp d0, d0
+	bne .Lfailure
+
+	pass
+.Lfailure:
+	fail

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]