diff options
author | Stephen Canon <scanon@apple.com> | 2010-07-01 15:52:42 +0000 |
---|---|---|
committer | Stephen Canon <scanon@apple.com> | 2010-07-01 15:52:42 +0000 |
commit | e5086322295e5a345af02d09abfcf8ddca2d0897 (patch) | |
tree | 0b45ef6ae008ced53cad21ea62d1b8fb9ecff5bb /lib/comparedf2.c | |
parent | 06dfcbe20aff576643a0ecb2925f5f8e16df0a54 (diff) | |
download | compiler-rt-e5086322295e5a345af02d09abfcf8ddca2d0897.tar.gz compiler-rt-e5086322295e5a345af02d09abfcf8ddca2d0897.tar.bz2 compiler-rt-e5086322295e5a345af02d09abfcf8ddca2d0897.tar.xz |
Adding soft-float comparisons, addition, subtraction, multiplication and negation
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@107400 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/comparedf2.c')
-rw-r--r-- | lib/comparedf2.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/lib/comparedf2.c b/lib/comparedf2.c new file mode 100644 index 00000000..de700808 --- /dev/null +++ b/lib/comparedf2.c @@ -0,0 +1,127 @@ +/* + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + */ + +#define DOUBLE_PRECISION +#include "fp_lib.h" + +// This file implements the following soft-float comparison routines: +// +// __eqdf2 __gedf2 __nedf2 +// __ledf2 __gtdf2 +// __ltdf2 +// __nedf2 +// +// The semantics of the routines grouped in each column are identical, so there +// is a single implementation for each, and wrappers to provide the other names. +// +// The main routines behave as follows: +// +// __ledf2(a,b) returns -1 if a < b +// 0 if a == b +// 1 if a > b +// 1 if either a or b is NaN +// +// __gedf2(a,b) returns -1 if a < b +// 0 if a == b +// 1 if a > b +// -1 if either a or b is NaN +// +// __unorddf2(a,b) returns 0 if both a and b are numbers +// 1 if either a or b is NaN +// +// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of +// NaN values. + +enum LE_RESULT { + LE_LESS = -1, + LE_EQUAL = 0, + LE_GREATER = 1, + LE_UNORDERED = 1 +}; + +enum LE_RESULT __ledf2(fp_t a, fp_t b) { + + const srep_t aInt = toRep(a); + const srep_t bInt = toRep(b); + const rep_t aAbs = aInt & absMask; + const rep_t bAbs = bInt & absMask; + + // If either a or b is NaN, they are unordered. + if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED; + + // If a and b are both zeros, they are equal. + if ((aAbs | bAbs) == 0) return LE_EQUAL; + + // If at least one of a and b is positive, we get the same result comparing + // a and b as signed integers as we would with a floating-point compare. + if ((aInt & bInt) >= 0) { + if (aInt < bInt) return LE_LESS; + else if (aInt == bInt) return LE_EQUAL; + else return LE_GREATER; + } + + // Otherwise, both are negative, so we need to flip the sense of the + // comparison to get the correct result. (This assumes a twos- or ones- + // complement integer representation; if integers are represented in a + // sign-magnitude representation, then this flip is incorrect). + else { + if (aInt > bInt) return LE_LESS; + else if (aInt == bInt) return LE_EQUAL; + else return LE_GREATER; + } +} + + +enum GE_RESULT { + GE_LESS = -1, + GE_EQUAL = 0, + GE_GREATER = 1, + GE_UNORDERED = -1 // Note: different from LE_UNORDERED +}; + +enum GE_RESULT __gedf2(fp_t a, fp_t b) { + + const srep_t aInt = toRep(a); + const srep_t bInt = toRep(b); + const rep_t aAbs = aInt & absMask; + const rep_t bAbs = bInt & absMask; + + if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED; + if ((aAbs | bAbs) == 0) return GE_EQUAL; + if ((aInt & bInt) >= 0) { + if (aInt < bInt) return GE_LESS; + else if (aInt == bInt) return GE_EQUAL; + else return GE_GREATER; + } else { + if (aInt > bInt) return GE_LESS; + else if (aInt == bInt) return GE_EQUAL; + else return GE_GREATER; + } +} + +int __unorddf2(fp_t a, fp_t b) { + const rep_t aAbs = toRep(a) & absMask; + const rep_t bAbs = toRep(b) & absMask; + return aAbs > infRep || bAbs > infRep; +} + +enum LE_RESULT __eqdf2(fp_t a, fp_t b) { + return __ledf2(a, b); +} + +enum LE_RESULT __ltdf2(fp_t a, fp_t b) { + return __ledf2(a, b); +} + +enum LE_RESULT __nedf2(fp_t a, fp_t b) { + return __ledf2(a, b); +} + +enum GE_RESULT __gtdf2(fp_t a, fp_t b) { + return __gedf2(a, b); +} + |