xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/comparesf2.c (revision d31434597b255f3fd7646698e04170d148f1de49)
1156cd587Sjoerg //===-- lib/comparesf2.c - Single-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-fp_t comparison routines:
11156cd587Sjoerg //
12156cd587Sjoerg //   __eqsf2   __gesf2   __unordsf2
13156cd587Sjoerg //   __lesf2   __gtsf2
14156cd587Sjoerg //   __ltsf2
15156cd587Sjoerg //   __nesf2
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 //   __lesf2(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 //   __gesf2(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 //   __unordsf2(a,b) returns 0 if both a and b are numbers
33156cd587Sjoerg //                           1 if either a or b is NaN
34156cd587Sjoerg //
35156cd587Sjoerg // Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
36156cd587Sjoerg // NaN values.
37156cd587Sjoerg //
38156cd587Sjoerg //===----------------------------------------------------------------------===//
39156cd587Sjoerg 
40156cd587Sjoerg #define SINGLE_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
__lesf2(fp_t a,fp_t b)51f7f78b33Sjoerg __lesf2(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 fp_ting-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(__cmpsf2, __lesf2);
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
__gesf2(fp_t a,fp_t b)96f7f78b33Sjoerg __gesf2(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
__unordsf2(fp_t a,fp_t b)117f7f78b33Sjoerg __unordsf2(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
__eqsf2(fp_t a,fp_t b)126f7f78b33Sjoerg __eqsf2(fp_t a, fp_t b) {
127156cd587Sjoerg     return __lesf2(a, b);
128156cd587Sjoerg }
129156cd587Sjoerg 
130f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__ltsf2(fp_t a,fp_t b)131f7f78b33Sjoerg __ltsf2(fp_t a, fp_t b) {
132156cd587Sjoerg     return __lesf2(a, b);
133156cd587Sjoerg }
134156cd587Sjoerg 
135f7f78b33Sjoerg COMPILER_RT_ABI enum LE_RESULT
__nesf2(fp_t a,fp_t b)136f7f78b33Sjoerg __nesf2(fp_t a, fp_t b) {
137156cd587Sjoerg     return __lesf2(a, b);
138156cd587Sjoerg }
139156cd587Sjoerg 
140f7f78b33Sjoerg COMPILER_RT_ABI enum GE_RESULT
__gtsf2(fp_t a,fp_t b)141f7f78b33Sjoerg __gtsf2(fp_t a, fp_t b) {
142156cd587Sjoerg     return __gesf2(a, b);
143156cd587Sjoerg }
1443044ee7eSrin 
1453044ee7eSrin #if defined(__ARM_EABI__)
146*d3143459Srin #if defined(COMPILER_RT_ARMHF_TARGET)
__aeabi_fcmpun(fp_t a,fp_t b)1473044ee7eSrin AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) {
1483044ee7eSrin   return __unordsf2(a, b);
1493044ee7eSrin }
150*d3143459Srin #else
151*d3143459Srin AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unordsf2);
1523044ee7eSrin #endif
153*d3143459Srin #endif
154