xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/comparetf2.c (revision ef84fd3bd8895f4e6be1e38baf19e6dc3255bc64)
161f2f256Sjoerg //===-- lib/comparetf2.c - Quad-precision comparisons -------------*- C -*-===//
261f2f256Sjoerg //
361f2f256Sjoerg //                     The LLVM Compiler Infrastructure
461f2f256Sjoerg //
561f2f256Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open
661f2f256Sjoerg // Source Licenses. See LICENSE.TXT for details.
761f2f256Sjoerg //
861f2f256Sjoerg //===----------------------------------------------------------------------===//
961f2f256Sjoerg //
1061f2f256Sjoerg // // This file implements the following soft-float comparison routines:
1161f2f256Sjoerg //
1261f2f256Sjoerg //   __eqtf2   __getf2   __unordtf2
1361f2f256Sjoerg //   __letf2   __gttf2
1461f2f256Sjoerg //   __lttf2
1561f2f256Sjoerg //   __netf2
1661f2f256Sjoerg //
1761f2f256Sjoerg // The semantics of the routines grouped in each column are identical, so there
1861f2f256Sjoerg // is a single implementation for each, and wrappers to provide the other names.
1961f2f256Sjoerg //
2061f2f256Sjoerg // The main routines behave as follows:
2161f2f256Sjoerg //
2261f2f256Sjoerg //   __letf2(a,b) returns -1 if a < b
2361f2f256Sjoerg //                         0 if a == b
2461f2f256Sjoerg //                         1 if a > b
2561f2f256Sjoerg //                         1 if either a or b is NaN
2661f2f256Sjoerg //
2761f2f256Sjoerg //   __getf2(a,b) returns -1 if a < b
2861f2f256Sjoerg //                         0 if a == b
2961f2f256Sjoerg //                         1 if a > b
3061f2f256Sjoerg //                        -1 if either a or b is NaN
3161f2f256Sjoerg //
3261f2f256Sjoerg //   __unordtf2(a,b) returns 0 if both a and b are numbers
3361f2f256Sjoerg //                           1 if either a or b is NaN
3461f2f256Sjoerg //
3561f2f256Sjoerg // Note that __letf2( ) and __getf2( ) are identical except in their handling of
3661f2f256Sjoerg // NaN values.
3761f2f256Sjoerg //
3861f2f256Sjoerg //===----------------------------------------------------------------------===//
3961f2f256Sjoerg 
4061f2f256Sjoerg #define QUAD_PRECISION
4161f2f256Sjoerg #include "fp_lib.h"
4261f2f256Sjoerg 
4361f2f256Sjoerg #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
4461f2f256Sjoerg enum LE_RESULT {
4561f2f256Sjoerg     LE_LESS      = -1,
4661f2f256Sjoerg     LE_EQUAL     =  0,
4761f2f256Sjoerg     LE_GREATER   =  1,
4861f2f256Sjoerg     LE_UNORDERED =  1
4961f2f256Sjoerg };
5061f2f256Sjoerg 
__letf2(fp_t a,fp_t b)5161f2f256Sjoerg COMPILER_RT_ABI enum LE_RESULT __letf2(fp_t a, fp_t b) {
5261f2f256Sjoerg 
5361f2f256Sjoerg     const srep_t aInt = toRep(a);
5461f2f256Sjoerg     const srep_t bInt = toRep(b);
5561f2f256Sjoerg     const rep_t aAbs = aInt & absMask;
5661f2f256Sjoerg     const rep_t bAbs = bInt & absMask;
5761f2f256Sjoerg 
5861f2f256Sjoerg     // If either a or b is NaN, they are unordered.
5961f2f256Sjoerg     if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
6061f2f256Sjoerg 
6161f2f256Sjoerg     // If a and b are both zeros, they are equal.
6261f2f256Sjoerg     if ((aAbs | bAbs) == 0) return LE_EQUAL;
6361f2f256Sjoerg 
6461f2f256Sjoerg     // If at least one of a and b is positive, we get the same result comparing
6561f2f256Sjoerg     // a and b as signed integers as we would with a floating-point compare.
6661f2f256Sjoerg     if ((aInt & bInt) >= 0) {
6761f2f256Sjoerg         if (aInt < bInt) return LE_LESS;
6861f2f256Sjoerg         else if (aInt == bInt) return LE_EQUAL;
6961f2f256Sjoerg         else return LE_GREATER;
7061f2f256Sjoerg     }
7161f2f256Sjoerg     else {
7261f2f256Sjoerg         // Otherwise, both are negative, so we need to flip the sense of the
7361f2f256Sjoerg         // comparison to get the correct result.  (This assumes a twos- or ones-
7461f2f256Sjoerg         // complement integer representation; if integers are represented in a
7561f2f256Sjoerg         // sign-magnitude representation, then this flip is incorrect).
7661f2f256Sjoerg         if (aInt > bInt) return LE_LESS;
7761f2f256Sjoerg         else if (aInt == bInt) return LE_EQUAL;
7861f2f256Sjoerg         else return LE_GREATER;
7961f2f256Sjoerg     }
8061f2f256Sjoerg }
8161f2f256Sjoerg 
82*ef84fd3bSjoerg #if defined(__ELF__)
83*ef84fd3bSjoerg // Alias for libgcc compatibility
84*ef84fd3bSjoerg FNALIAS(__cmptf2, __letf2);
85*ef84fd3bSjoerg #endif
86*ef84fd3bSjoerg 
8761f2f256Sjoerg enum GE_RESULT {
8861f2f256Sjoerg     GE_LESS      = -1,
8961f2f256Sjoerg     GE_EQUAL     =  0,
9061f2f256Sjoerg     GE_GREATER   =  1,
9161f2f256Sjoerg     GE_UNORDERED = -1   // Note: different from LE_UNORDERED
9261f2f256Sjoerg };
9361f2f256Sjoerg 
__getf2(fp_t a,fp_t b)9461f2f256Sjoerg COMPILER_RT_ABI enum GE_RESULT __getf2(fp_t a, fp_t b) {
9561f2f256Sjoerg 
9661f2f256Sjoerg     const srep_t aInt = toRep(a);
9761f2f256Sjoerg     const srep_t bInt = toRep(b);
9861f2f256Sjoerg     const rep_t aAbs = aInt & absMask;
9961f2f256Sjoerg     const rep_t bAbs = bInt & absMask;
10061f2f256Sjoerg 
10161f2f256Sjoerg     if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
10261f2f256Sjoerg     if ((aAbs | bAbs) == 0) return GE_EQUAL;
10361f2f256Sjoerg     if ((aInt & bInt) >= 0) {
10461f2f256Sjoerg         if (aInt < bInt) return GE_LESS;
10561f2f256Sjoerg         else if (aInt == bInt) return GE_EQUAL;
10661f2f256Sjoerg         else return GE_GREATER;
10761f2f256Sjoerg     } else {
10861f2f256Sjoerg         if (aInt > bInt) return GE_LESS;
10961f2f256Sjoerg         else if (aInt == bInt) return GE_EQUAL;
11061f2f256Sjoerg         else return GE_GREATER;
11161f2f256Sjoerg     }
11261f2f256Sjoerg }
11361f2f256Sjoerg 
__unordtf2(fp_t a,fp_t b)11461f2f256Sjoerg COMPILER_RT_ABI int __unordtf2(fp_t a, fp_t b) {
11561f2f256Sjoerg     const rep_t aAbs = toRep(a) & absMask;
11661f2f256Sjoerg     const rep_t bAbs = toRep(b) & absMask;
11761f2f256Sjoerg     return aAbs > infRep || bAbs > infRep;
11861f2f256Sjoerg }
11961f2f256Sjoerg 
12030308f42Sjoerg // The following are alternative names for the preceding routines.
12161f2f256Sjoerg 
__eqtf2(fp_t a,fp_t b)12261f2f256Sjoerg COMPILER_RT_ABI enum LE_RESULT __eqtf2(fp_t a, fp_t b) {
12361f2f256Sjoerg     return __letf2(a, b);
12461f2f256Sjoerg }
12561f2f256Sjoerg 
__lttf2(fp_t a,fp_t b)12661f2f256Sjoerg COMPILER_RT_ABI enum LE_RESULT __lttf2(fp_t a, fp_t b) {
12761f2f256Sjoerg     return __letf2(a, b);
12861f2f256Sjoerg }
12961f2f256Sjoerg 
__netf2(fp_t a,fp_t b)13061f2f256Sjoerg COMPILER_RT_ABI enum LE_RESULT __netf2(fp_t a, fp_t b) {
13161f2f256Sjoerg     return __letf2(a, b);
13261f2f256Sjoerg }
13361f2f256Sjoerg 
__gttf2(fp_t a,fp_t b)13461f2f256Sjoerg COMPILER_RT_ABI enum GE_RESULT __gttf2(fp_t a, fp_t b) {
13561f2f256Sjoerg     return __getf2(a, b);
13661f2f256Sjoerg }
13761f2f256Sjoerg 
13861f2f256Sjoerg #endif
139