xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/comparedf2.c (revision d31434597b255f3fd7646698e04170d148f1de49)
1156cd587Sjoerg //===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===//
2156cd587Sjoerg //
3156cd587Sjoerg //                     The LLVM Compiler Infrastructure
4156cd587Sjoerg //
5156cd587Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open
6156cd587Sjoerg // Source Licenses. See LICENSE.TXT for details.
7156cd587Sjoerg //
8156cd587Sjoerg //===----------------------------------------------------------------------===//
9156cd587Sjoerg //
10156cd587Sjoerg // // This file implements the following soft-float comparison routines:
11156cd587Sjoerg //
12156cd587Sjoerg //   __eqdf2   __gedf2   __unorddf2
13156cd587Sjoerg //   __ledf2   __gtdf2
14156cd587Sjoerg //   __ltdf2
15156cd587Sjoerg //   __nedf2
16156cd587Sjoerg //
17156cd587Sjoerg // The semantics of the routines grouped in each column are identical, so there
18156cd587Sjoerg // is a single implementation for each, and wrappers to provide the other names.
19156cd587Sjoerg //
20156cd587Sjoerg // The main routines behave as follows:
21156cd587Sjoerg //
22156cd587Sjoerg //   __ledf2(a,b) returns -1 if a < b
23156cd587Sjoerg //                         0 if a == b
24156cd587Sjoerg //                         1 if a > b
25156cd587Sjoerg //                         1 if either a or b is NaN
26156cd587Sjoerg //
27156cd587Sjoerg //   __gedf2(a,b) returns -1 if a < b
28156cd587Sjoerg //                         0 if a == b
29156cd587Sjoerg //                         1 if a > b
30156cd587Sjoerg //                        -1 if either a or b is NaN
31156cd587Sjoerg //
32156cd587Sjoerg //   __unorddf2(a,b) returns 0 if both a and b are numbers
33156cd587Sjoerg //                           1 if either a or b is NaN
34156cd587Sjoerg //
35156cd587Sjoerg // Note that __ledf2( ) and __gedf2( ) are identical except in their handling of
36156cd587Sjoerg // NaN values.
37156cd587Sjoerg //
38156cd587Sjoerg //===----------------------------------------------------------------------===//
39156cd587Sjoerg 
40156cd587Sjoerg #define DOUBLE_PRECISION
41156cd587Sjoerg #include "fp_lib.h"
42156cd587Sjoerg 
43156cd587Sjoerg enum LE_RESULT {
44156cd587Sjoerg     LE_LESS      = -1,
45156cd587Sjoerg     LE_EQUAL     =  0,
46156cd587Sjoerg     LE_GREATER   =  1,
47156cd587Sjoerg     LE_UNORDERED =  1
48156cd587Sjoerg };
49156cd587Sjoerg 
50f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__ledf2(fp_t a,fp_t b)51f7f78b33Sjoerg __ledf2(fp_t a, fp_t b) {
52156cd587Sjoerg 
53156cd587Sjoerg     const srep_t aInt = toRep(a);
54156cd587Sjoerg     const srep_t bInt = toRep(b);
55156cd587Sjoerg     const rep_t aAbs = aInt & absMask;
56156cd587Sjoerg     const rep_t bAbs = bInt & absMask;
57156cd587Sjoerg 
58156cd587Sjoerg     // If either a or b is NaN, they are unordered.
59156cd587Sjoerg     if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
60156cd587Sjoerg 
61156cd587Sjoerg     // If a and b are both zeros, they are equal.
62156cd587Sjoerg     if ((aAbs | bAbs) == 0) return LE_EQUAL;
63156cd587Sjoerg 
64156cd587Sjoerg     // If at least one of a and b is positive, we get the same result comparing
65156cd587Sjoerg     // a and b as signed integers as we would with a floating-point compare.
66156cd587Sjoerg     if ((aInt & bInt) >= 0) {
67156cd587Sjoerg         if (aInt < bInt) return LE_LESS;
68156cd587Sjoerg         else if (aInt == bInt) return LE_EQUAL;
69156cd587Sjoerg         else return LE_GREATER;
70156cd587Sjoerg     }
71156cd587Sjoerg 
72156cd587Sjoerg     // Otherwise, both are negative, so we need to flip the sense of the
73156cd587Sjoerg     // comparison to get the correct result.  (This assumes a twos- or ones-
74156cd587Sjoerg     // complement integer representation; if integers are represented in a
75156cd587Sjoerg     // sign-magnitude representation, then this flip is incorrect).
76156cd587Sjoerg     else {
77156cd587Sjoerg         if (aInt > bInt) return LE_LESS;
78156cd587Sjoerg         else if (aInt == bInt) return LE_EQUAL;
79156cd587Sjoerg         else return LE_GREATER;
80156cd587Sjoerg     }
81156cd587Sjoerg }
82156cd587Sjoerg 
83ef84fd3bSjoerg #if defined(__ELF__)
84ef84fd3bSjoerg // Alias for libgcc compatibility
85ef84fd3bSjoerg FNALIAS(__cmpdf2, __ledf2);
86ef84fd3bSjoerg #endif
87ef84fd3bSjoerg 
88156cd587Sjoerg enum GE_RESULT {
89156cd587Sjoerg     GE_LESS      = -1,
90156cd587Sjoerg     GE_EQUAL     =  0,
91156cd587Sjoerg     GE_GREATER   =  1,
92156cd587Sjoerg     GE_UNORDERED = -1   // Note: different from LE_UNORDERED
93156cd587Sjoerg };
94156cd587Sjoerg 
95f7f78b33Sjoerg COMPILER_RT_ABI enum GE_RESULT
__gedf2(fp_t a,fp_t b)96f7f78b33Sjoerg __gedf2(fp_t a, fp_t b) {
97156cd587Sjoerg 
98156cd587Sjoerg     const srep_t aInt = toRep(a);
99156cd587Sjoerg     const srep_t bInt = toRep(b);
100156cd587Sjoerg     const rep_t aAbs = aInt & absMask;
101156cd587Sjoerg     const rep_t bAbs = bInt & absMask;
102156cd587Sjoerg 
103156cd587Sjoerg     if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
104156cd587Sjoerg     if ((aAbs | bAbs) == 0) return GE_EQUAL;
105156cd587Sjoerg     if ((aInt & bInt) >= 0) {
106156cd587Sjoerg         if (aInt < bInt) return GE_LESS;
107156cd587Sjoerg         else if (aInt == bInt) return GE_EQUAL;
108156cd587Sjoerg         else return GE_GREATER;
109156cd587Sjoerg     } else {
110156cd587Sjoerg         if (aInt > bInt) return GE_LESS;
111156cd587Sjoerg         else if (aInt == bInt) return GE_EQUAL;
112156cd587Sjoerg         else return GE_GREATER;
113156cd587Sjoerg     }
114156cd587Sjoerg }
115156cd587Sjoerg 
116f7f78b33Sjoerg COMPILER_RT_ABI int
__unorddf2(fp_t a,fp_t b)117f7f78b33Sjoerg __unorddf2(fp_t a, fp_t b) {
118156cd587Sjoerg     const rep_t aAbs = toRep(a) & absMask;
119156cd587Sjoerg     const rep_t bAbs = toRep(b) & absMask;
120156cd587Sjoerg     return aAbs > infRep || bAbs > infRep;
121156cd587Sjoerg }
122156cd587Sjoerg 
12330308f42Sjoerg // The following are alternative names for the preceding routines.
124156cd587Sjoerg 
125f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__eqdf2(fp_t a,fp_t b)126f7f78b33Sjoerg __eqdf2(fp_t a, fp_t b) {
127156cd587Sjoerg     return __ledf2(a, b);
128156cd587Sjoerg }
129156cd587Sjoerg 
130f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__ltdf2(fp_t a,fp_t b)131f7f78b33Sjoerg __ltdf2(fp_t a, fp_t b) {
132156cd587Sjoerg     return __ledf2(a, b);
133156cd587Sjoerg }
134156cd587Sjoerg 
135f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__nedf2(fp_t a,fp_t b)136f7f78b33Sjoerg __nedf2(fp_t a, fp_t b) {
137156cd587Sjoerg     return __ledf2(a, b);
138156cd587Sjoerg }
139156cd587Sjoerg 
140f7f78b33Sjoerg COMPILER_RT_ABI enum GE_RESULT
__gtdf2(fp_t a,fp_t b)141f7f78b33Sjoerg __gtdf2(fp_t a, fp_t b) {
142156cd587Sjoerg     return __gedf2(a, b);
143156cd587Sjoerg }
144156cd587Sjoerg 
1453044ee7eSrin #if defined(__ARM_EABI__)
146*d3143459Srin #if defined(COMPILER_RT_ARMHF_TARGET)
__aeabi_dcmpun(fp_t a,fp_t b)1473044ee7eSrin AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) {
1483044ee7eSrin   return __unorddf2(a, b);
1493044ee7eSrin }
150*d3143459Srin #else
151*d3143459Srin AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unorddf2);
1523044ee7eSrin #endif
153*d3143459Srin #endif
154