[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