]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/builtins/arm/comparesf2.S
Merge llvm, clang, lld and lldb release_40 branch r292009. Also update
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / builtins / arm / comparesf2.S
1 //===-- comparesf2.S - Implement single-precision soft-float comparisons --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the following soft-fp_t comparison routines:
11 //
12 //   __eqsf2   __gesf2   __unordsf2
13 //   __lesf2   __gtsf2
14 //   __ltsf2
15 //   __nesf2
16 //
17 // The semantics of the routines grouped in each column are identical, so there
18 // is a single implementation for each, with multiple names.
19 //
20 // The routines behave as follows:
21 //
22 //   __lesf2(a,b) returns -1 if a < b
23 //                         0 if a == b
24 //                         1 if a > b
25 //                         1 if either a or b is NaN
26 //
27 //   __gesf2(a,b) returns -1 if a < b
28 //                         0 if a == b
29 //                         1 if a > b
30 //                        -1 if either a or b is NaN
31 //
32 //   __unordsf2(a,b) returns 0 if both a and b are numbers
33 //                           1 if either a or b is NaN
34 //
35 // Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
36 // NaN values.
37 //
38 //===----------------------------------------------------------------------===//
39
40 #include "../assembly.h"
41 .syntax unified
42 #if __ARM_ARCH_ISA_THUMB == 2
43 .thumb
44 #endif
45
46 .p2align 2
47 DEFINE_COMPILERRT_FUNCTION(__eqsf2)
48     // Make copies of a and b with the sign bit shifted off the top.  These will
49     // be used to detect zeros and NaNs.
50 #if __ARM_ARCH_ISA_THUMB == 1
51     push    {r6, lr}
52     lsls    r2,         r0, #1
53     lsls    r3,         r1, #1
54 #else
55     mov     r2,         r0, lsl #1
56     mov     r3,         r1, lsl #1
57 #endif
58
59     // We do the comparison in three stages (ignoring NaN values for the time
60     // being).  First, we orr the absolute values of a and b; this sets the Z
61     // flag if both a and b are zero (of either sign).  The shift of r3 doesn't
62     // effect this at all, but it *does* make sure that the C flag is clear for
63     // the subsequent operations.
64 #if __ARM_ARCH_ISA_THUMB == 1
65     lsrs    r6,     r3, #1
66     orrs    r6,     r2, r6
67 #else
68     orrs    r12,    r2, r3, lsr #1
69 #endif
70     // Next, we check if a and b have the same or different signs.  If they have
71     // opposite signs, this eor will set the N flag.
72 #if __ARM_ARCH_ISA_THUMB == 1
73     beq     1f
74     movs    r6,     r0
75     eors    r6,     r1
76 1:
77 #else
78     it ne
79     eorsne  r12,    r0, r1
80 #endif
81
82     // If a and b are equal (either both zeros or bit identical; again, we're
83     // ignoring NaNs for now), this subtract will zero out r0.  If they have the
84     // same sign, the flags are updated as they would be for a comparison of the
85     // absolute values of a and b.
86 #if __ARM_ARCH_ISA_THUMB == 1
87     bmi     1f
88     subs    r0,     r2, r3
89 1:
90 #else
91     it pl
92     subspl  r0,     r2, r3
93 #endif
94
95     // If a is smaller in magnitude than b and both have the same sign, place
96     // the negation of the sign of b in r0.  Thus, if both are negative and
97     // a > b, this sets r0 to 0; if both are positive and a < b, this sets
98     // r0 to -1.
99     //
100     // This is also done if a and b have opposite signs and are not both zero,
101     // because in that case the subtract was not performed and the C flag is
102     // still clear from the shift argument in orrs; if a is positive and b
103     // negative, this places 0 in r0; if a is negative and b positive, -1 is
104     // placed in r0.
105 #if __ARM_ARCH_ISA_THUMB == 1
106     bhs     1f
107     // Here if a and b have the same sign and absA < absB, the result is thus
108     // b < 0 ? 1 : -1. Same if a and b have the opposite sign (ignoring Nan).
109     movs    r0,         #1
110     lsrs    r1,         #31
111     bne     LOCAL_LABEL(CHECK_NAN)
112     negs    r0,         r0
113     b       LOCAL_LABEL(CHECK_NAN)
114 1:
115 #else
116     it lo
117     mvnlo   r0,         r1, asr #31
118 #endif
119
120     // If a is greater in magnitude than b and both have the same sign, place
121     // the sign of b in r0.  Thus, if both are negative and a < b, -1 is placed
122     // in r0, which is the desired result.  Conversely, if both are positive
123     // and a > b, zero is placed in r0.
124 #if __ARM_ARCH_ISA_THUMB == 1
125     bls     1f
126     // Here both have the same sign and absA > absB.
127     movs    r0,         #1
128     lsrs    r1,         #31
129     beq     LOCAL_LABEL(CHECK_NAN)
130     negs    r0, r0
131 1:
132 #else
133     it hi
134     movhi   r0,         r1, asr #31
135 #endif
136
137     // If you've been keeping track, at this point r0 contains -1 if a < b and
138     // 0 if a >= b.  All that remains to be done is to set it to 1 if a > b.
139     // If a == b, then the Z flag is set, so we can get the correct final value
140     // into r0 by simply or'ing with 1 if Z is clear.
141     // For Thumb-1, r0 contains -1 if a < b, 0 if a > b and 0 if a == b.
142 #if __ARM_ARCH_ISA_THUMB != 1
143     it ne
144     orrne   r0,     r0, #1
145 #endif
146
147     // Finally, we need to deal with NaNs.  If either argument is NaN, replace
148     // the value in r0 with 1.
149 #if __ARM_ARCH_ISA_THUMB == 1
150 LOCAL_LABEL(CHECK_NAN):
151     movs    r6,         #0xff
152     lsls    r6,         #24
153     cmp     r2,         r6
154     bhi     1f
155     cmp     r3,         r6
156 1:
157     bls     2f
158     movs    r0,         #1
159 2:
160     pop     {r6, pc}
161 #else
162     cmp     r2,         #0xff000000
163     ite ls
164     cmpls   r3,         #0xff000000
165     movhi   r0,         #1
166     JMP(lr)
167 #endif
168 END_COMPILERRT_FUNCTION(__eqsf2)
169 DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2)
170 DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2)
171 DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2)
172
173 .p2align 2
174 DEFINE_COMPILERRT_FUNCTION(__gtsf2)
175     // Identical to the preceding except in that we return -1 for NaN values.
176     // Given that the two paths share so much code, one might be tempted to
177     // unify them; however, the extra code needed to do so makes the code size
178     // to performance tradeoff very hard to justify for such small functions.
179 #if __ARM_ARCH_ISA_THUMB == 1
180     push    {r6, lr}
181     lsls    r2,        r0, #1
182     lsls    r3,        r1, #1
183     lsrs    r6,        r3, #1
184     orrs    r6,        r2, r6
185     beq     1f
186     movs    r6,        r0
187     eors    r6,        r1
188 1:
189     bmi     2f
190     subs    r0,        r2, r3
191 2:
192     bhs     3f
193     movs    r0,        #1
194     lsrs    r1,        #31
195     bne     LOCAL_LABEL(CHECK_NAN_2)
196     negs    r0, r0
197     b       LOCAL_LABEL(CHECK_NAN_2)
198 3:
199     bls     4f
200     movs    r0,         #1
201     lsrs    r1,         #31
202     beq     LOCAL_LABEL(CHECK_NAN_2)
203     negs    r0, r0
204 4:
205 LOCAL_LABEL(CHECK_NAN_2):
206     movs    r6,         #0xff
207     lsls    r6,         #24
208     cmp     r2,         r6
209     bhi     5f
210     cmp     r3,         r6
211 5:
212     bls     6f
213     movs    r0,         #1
214     negs    r0,         r0
215 6:
216     pop     {r6, pc}
217 #else
218     orrs    r12,    r2, r3, lsr #1
219     it ne
220     eorsne  r12,    r0, r1
221     it pl
222     subspl  r0,     r2, r3
223     it lo
224     mvnlo   r0,         r1, asr #31
225     it hi
226     movhi   r0,         r1, asr #31
227     it ne
228     orrne   r0,     r0, #1
229     cmp     r2,         #0xff000000
230     ite ls
231     cmpls   r3,         #0xff000000
232     movhi   r0,         #-1
233     JMP(lr)
234 #endif
235 END_COMPILERRT_FUNCTION(__gtsf2)
236 DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2)
237
238 .p2align 2
239 DEFINE_COMPILERRT_FUNCTION(__unordsf2)
240     // Return 1 for NaN values, 0 otherwise.
241     lsls    r2,         r0, #1
242     lsls    r3,         r1, #1
243     movs    r0,         #0
244 #if __ARM_ARCH_ISA_THUMB == 1
245     movs    r1,         #0xff
246     lsls    r1,         #24
247     cmp     r2,         r1
248     bhi     1f
249     cmp     r3,         r1
250 1:
251     bls     2f
252     movs    r0,         #1
253 2:
254 #else
255     cmp     r2,         #0xff000000
256     ite ls
257     cmpls   r3,         #0xff000000
258     movhi   r0,         #1
259 #endif
260     JMP(lr)
261 END_COMPILERRT_FUNCTION(__unordsf2)
262
263 DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fcmpun, __unordsf2)
264
265 NO_EXEC_STACK_DIRECTIVE
266