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