1 //===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the following soft-fp_t comparison routines:
10 //
11 // __eqsf2 __gesf2 __unordsf2
12 // __lesf2 __gtsf2
13 // __ltsf2
14 // __nesf2
15 //
16 // The semantics of the routines grouped in each column are identical, so there
17 // is a single implementation for each, and wrappers to provide the other names.
18 //
19 // The main routines behave as follows:
20 //
21 // __lesf2(a,b) returns -1 if a < b
22 // 0 if a == b
23 // 1 if a > b
24 // 1 if either a or b is NaN
25 //
26 // __gesf2(a,b) returns -1 if a < b
27 // 0 if a == b
28 // 1 if a > b
29 // -1 if either a or b is NaN
30 //
31 // __unordsf2(a,b) returns 0 if both a and b are numbers
32 // 1 if either a or b is NaN
33 //
34 // Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
35 // NaN values.
36 //
37 //===----------------------------------------------------------------------===//
38
39 #define SINGLE_PRECISION
40 #include "fp_lib.h"
41
42 enum LE_RESULT { LE_LESS = -1, LE_EQUAL = 0, LE_GREATER = 1, LE_UNORDERED = 1 };
43
__lesf2(fp_t a,fp_t b)44 COMPILER_RT_ABI enum LE_RESULT __lesf2(fp_t a, fp_t b) {
45
46 const srep_t aInt = toRep(a);
47 const srep_t bInt = toRep(b);
48 const rep_t aAbs = aInt & absMask;
49 const rep_t bAbs = bInt & absMask;
50
51 // If either a or b is NaN, they are unordered.
52 if (aAbs > infRep || bAbs > infRep)
53 return LE_UNORDERED;
54
55 // If a and b are both zeros, they are equal.
56 if ((aAbs | bAbs) == 0)
57 return LE_EQUAL;
58
59 // If at least one of a and b is positive, we get the same result comparing
60 // a and b as signed integers as we would with a fp_ting-point compare.
61 if ((aInt & bInt) >= 0) {
62 if (aInt < bInt)
63 return LE_LESS;
64 else if (aInt == bInt)
65 return LE_EQUAL;
66 else
67 return LE_GREATER;
68 }
69
70 // Otherwise, both are negative, so we need to flip the sense of the
71 // comparison to get the correct result. (This assumes a twos- or ones-
72 // complement integer representation; if integers are represented in a
73 // sign-magnitude representation, then this flip is incorrect).
74 else {
75 if (aInt > bInt)
76 return LE_LESS;
77 else if (aInt == bInt)
78 return LE_EQUAL;
79 else
80 return LE_GREATER;
81 }
82 }
83
84 #if defined(__ELF__)
85 // Alias for libgcc compatibility
86 COMPILER_RT_ALIAS(__lesf2, __cmpsf2)
87 #endif
88 COMPILER_RT_ALIAS(__lesf2, __eqsf2)
89 COMPILER_RT_ALIAS(__lesf2, __ltsf2)
90 COMPILER_RT_ALIAS(__lesf2, __nesf2)
91
92 enum GE_RESULT {
93 GE_LESS = -1,
94 GE_EQUAL = 0,
95 GE_GREATER = 1,
96 GE_UNORDERED = -1 // Note: different from LE_UNORDERED
97 };
98
__gesf2(fp_t a,fp_t b)99 COMPILER_RT_ABI enum GE_RESULT __gesf2(fp_t a, fp_t b) {
100
101 const srep_t aInt = toRep(a);
102 const srep_t bInt = toRep(b);
103 const rep_t aAbs = aInt & absMask;
104 const rep_t bAbs = bInt & absMask;
105
106 if (aAbs > infRep || bAbs > infRep)
107 return GE_UNORDERED;
108 if ((aAbs | bAbs) == 0)
109 return GE_EQUAL;
110 if ((aInt & bInt) >= 0) {
111 if (aInt < bInt)
112 return GE_LESS;
113 else if (aInt == bInt)
114 return GE_EQUAL;
115 else
116 return GE_GREATER;
117 } else {
118 if (aInt > bInt)
119 return GE_LESS;
120 else if (aInt == bInt)
121 return GE_EQUAL;
122 else
123 return GE_GREATER;
124 }
125 }
126
COMPILER_RT_ALIAS(__gesf2,__gtsf2)127 COMPILER_RT_ALIAS(__gesf2, __gtsf2)
128
129 COMPILER_RT_ABI int
130 __unordsf2(fp_t a, fp_t b) {
131 const rep_t aAbs = toRep(a) & absMask;
132 const rep_t bAbs = toRep(b) & absMask;
133 return aAbs > infRep || bAbs > infRep;
134 }
135
136 #if defined(__ARM_EABI__)
137 #if defined(COMPILER_RT_ARMHF_TARGET)
__aeabi_fcmpun(fp_t a,fp_t b)138 AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) { return __unordsf2(a, b); }
139 #else
COMPILER_RT_ALIAS(__unordsf2,__aeabi_fcmpun)140 COMPILER_RT_ALIAS(__unordsf2, __aeabi_fcmpun)
141 #endif
142 #endif
143
144 #if defined(_WIN32) && !defined(__MINGW32__)
145 // The alias mechanism doesn't work on Windows except for MinGW, so emit
146 // wrapper functions.
147 int __eqsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
__ltsf2(fp_t a,fp_t b)148 int __ltsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
__nesf2(fp_t a,fp_t b)149 int __nesf2(fp_t a, fp_t b) { return __lesf2(a, b); }
__gtsf2(fp_t a,fp_t b)150 int __gtsf2(fp_t a, fp_t b) { return __gesf2(a, b); }
151 #endif
152