[aarch64-port-dev ] Simulator: fix floating-point comparisons

Andrew Haley aph at redhat.com
Tue Dec 3 06:59:54 PST 2013


-0.0 is not less than 0.0, whatever our simulator thinks!

Fixed thusly.

Andrew.



# HG changeset patch
# User aph
# Date 1386082562 0
# Node ID 41c33f33771eaf0bc22146b92ad6f5480b0ee08f
# Parent  4754e0317b1913eabd32b85bd6a3d55b4eca2b1d
Correct floating-point comparisons

diff -r 4754e0317b19 -r 41c33f33771e simulator.cpp
--- a/simulator.cpp	Tue Nov 26 17:13:16 2013 +0000
+++ b/simulator.cpp	Tue Dec 03 14:56:02 2013 +0000
@@ -8157,136 +8157,25 @@
 static const int CPSR_ZC = 0b0110;
 static const int CPSR_C  = 0b0010;

-static void fcomps(float f1, float f2, CPUState &cpuState, bool setFPSR)
-{
-  int state1 = fpclassify(f1);
-  int state2 = fpclassify(f2);
-
+template<typename T>
+static void fcomp(T d1, T d2, CPUState &cpuState, bool setFPSR)
+{
   // a NaN in either produces flags --CV i.e. unordered
   // all other compares can be as value comparisons
   // taking infinities into account
-  if (state1 == FP_NAN || state2 == FP_NAN) {
+  if (d1 == d2) {
+    // set flags to -ZC-
+    cpuState.setCPSRRegister(CPSR_ZC);
+  } else if (isless(d1, d2)) {
+    // set flags to N----
+    cpuState.setCPSRRegister(CPSR_N);
+  } else if (isgreater(d1, d2)) {
+    // set flags to --C-
+    cpuState.setCPSRRegister(CPSR_C);
+  } else {
     // set flags to --CV
     cpuState.setCPSRRegister(CPSR_CV);
-  } else {
-    int sign1 = signbit(f1);
-    int sign2 = signbit(f2);;
-    int signum = sign2 - sign1;
-    if (signum < 0) {
-      // f1 < f2
-      // set flags to N----
-      cpuState.setCPSRRegister(CPSR_N);
-    } else if (signum > 0) {
-      // f1 > f2
-      // set flags to --C-
-      cpuState.setCPSRRegister(CPSR_C);
-    } else {
-      // both signs are the same
-      if (state1 == FP_INFINITE) {
-        if (state2 == FP_INFINITE) {
-          // f1 == f2
-          // set flags to -ZC-
-          cpuState.setCPSRRegister(CPSR_ZC);
-        } else if (sign1) {
-          // f1 < f2
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        } else {
-          // f1 > f2
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        }
-      } else if (state2 == FP_INFINITE) {
-        if (sign2) {
-          // f1 > f2
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        } else {
-          // f1 < f2
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        }
-      } else {
-        // just use a normal compare
-        if (f1 < f2) {
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        } else if (f1 > f2) {
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        } else {
-          // f1 == f2
-          // set flags to -ZC-
-          cpuState.setCPSRRegister(CPSR_ZC);
-        }
-      }
-    }
-  }
-}
-
-static void fcompd(double d1, double d2, CPUState &cpuState, bool setFPSR)
-{
-  int state1 = fpclassify(d1);
-  int state2 = fpclassify(d2);
-
-  // a NaN in either produces flags --CV i.e. unordered
-  // all other compares can be as value comparisons
-  // taking infinities into account
-  if (state1 == FP_NAN || state2 == FP_NAN) {
-   cpuState.setCPSRRegister(CPSR_CV);
-  } else {
-    int sign1 = signbit(d1);
-    int sign2 = signbit(d2);;
-    int signum = sign2 - sign1;
-    if (signum < 0) {
-      // d1 < d2
-      // set flags to N----
-      cpuState.setCPSRRegister(CPSR_N);
-    } else if (signum > 0) {
-      // d1 > d2
-      // set flags to --C-
-      cpuState.setCPSRRegister(CPSR_C);
-    } else {
-      // both signs are the same
-      if (state1 == FP_INFINITE) {
-        if (state2 == FP_INFINITE) {
-          // d1 == d2
-          // set flags to -ZC-
-          cpuState.setCPSRRegister(CPSR_ZC);
-        } else if (sign1) {
-          // d1 < d2
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        } else {
-          // d1 > d2
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        }
-      } else if (state2 == FP_INFINITE) {
-        if (sign2) {
-          // d1 > d2
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        } else {
-          // d1 < d2
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        }
-      } else {
-        // just use a normal compare
-        if (d1 < d2) {
-          // set flags to N----
-          cpuState.setCPSRRegister(CPSR_N);
-        } else if (d1 > d2) {
-          // set flags to --C-
-          cpuState.setCPSRRegister(CPSR_C);
-        } else {
-          // d1 == d2
-          // set flags to -ZC-
-          cpuState.setCPSRRegister(CPSR_ZC);
-        }
-      }
-    }
+    assert(isunordered(d1, d2));
   }
 }

@@ -8298,7 +8187,7 @@
   float fvalue = sreg(5);
   float fvalue2 = sreg(16);

-  fcomps(fvalue, fvalue2, cpuState, false);
+  fcomp(fvalue, fvalue2, cpuState, false);
 }
 // float compare to zero -- Invalid Operation exception only on signaling NaNs.
 void AArch64Simulator::fcmpzs()
@@ -8309,7 +8198,7 @@
   float fvalue = sreg(5);
   float fvalue2 = 0.0f;

-  fcomps(fvalue, fvalue2, cpuState, false);
+  fcomp(fvalue, fvalue2, cpuState, false);
 }
 // double compare -- Invalid Operation exception only on signaling NaNs.
 void AArch64Simulator::fcmpd()
@@ -8320,7 +8209,7 @@
   double fvalue = dreg(5);
   double fvalue2 = dreg(16);

-  fcompd(fvalue, fvalue2, cpuState, false);
+  fcomp(fvalue, fvalue2, cpuState, false);
 }
 // double compare to zero -- Invalid Operation exception only on signaling NaNs.
 void AArch64Simulator::fcmpzd()
@@ -8331,7 +8220,7 @@
   double fvalue = dreg(5);
   double fvalue2 = 0.0d;

-  fcompd(fvalue, fvalue2, cpuState, false);
+  fcomp(fvalue, fvalue2, cpuState, false);
 }
 // float compare -- Invalid Operation exception on all NaNs.
 void AArch64Simulator::fcmpes()
@@ -8342,7 +8231,7 @@
   float fvalue = sreg(5);
   float fvalue2 = sreg(16);

-  fcomps(fvalue, fvalue2, cpuState, true);
+  fcomp(fvalue, fvalue2, cpuState, true);
 }
 // float compare to zero -- Invalid Operation exception on all NaNs.
 void AArch64Simulator::fcmpzes()
@@ -8353,7 +8242,7 @@
   float fvalue = sreg(5);
   float fvalue2 = 0.0f;

-  fcomps(fvalue, fvalue2, cpuState, true);
+  fcomp(fvalue, fvalue2, cpuState, true);
 }
 // double compare -- Invalid Operation exception on all NaNs.
 void AArch64Simulator::fcmped()
@@ -8364,7 +8253,7 @@
   double fvalue = dreg(5);
   double fvalue2 = dreg(16);

-  fcompd(fvalue, fvalue2, cpuState, true);
+  fcomp(fvalue, fvalue2, cpuState, true);
 }
 // double compare to zero -- Invalid Operation exception on all NaNs.
 void AArch64Simulator::fcmpzed()
@@ -8375,7 +8264,7 @@
   double fvalue = dreg(5);
   double fvalue2 = 0.0d;

-  fcompd(fvalue, fvalue2, cpuState, true);
+  fcomp(fvalue, fvalue2, cpuState, true);
 }

 void AArch64Simulator::fcsels(CondCode cc)



More information about the aarch64-port-dev mailing list