]>
Commit | Line | Data |
---|---|---|
4202ce82 RE |
1 | /* ieee754-sf.S single-precision floating point support for ARM |
2 | ||
7adcbafe | 3 | Copyright (C) 2003-2022 Free Software Foundation, Inc. |
89fff9cc | 4 | Contributed by Nicolas Pitre (nico@fluxnic.net) |
4202ce82 RE |
5 | |
6 | This file is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
748086b7 | 8 | Free Software Foundation; either version 3, or (at your option) any |
4202ce82 RE |
9 | later version. |
10 | ||
4202ce82 RE |
11 | This file is distributed in the hope that it will be useful, but |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
4202ce82 RE |
24 | |
25 | /* | |
26 | * Notes: | |
27 | * | |
28 | * The goal of this code is to be as fast as possible. This is | |
29 | * not meant to be easy to understand for the casual reader. | |
30 | * | |
31 | * Only the default rounding mode is intended for best performances. | |
32 | * Exceptions aren't supported yet, but that can be added quite easily | |
33 | * if necessary without impacting performances. | |
ff935d0c MG |
34 | * |
35 | * In the CFI related comments, 'previousOffset' refers to the previous offset | |
36 | * from sp used to compute the CFA. | |
4202ce82 RE |
37 | */ |
38 | ||
bf98ec6c | 39 | #ifdef L_arm_negsf2 |
4202ce82 | 40 | |
496b84c8 | 41 | ARM_FUNC_START negsf2 |
b3f8d95d | 42 | ARM_FUNC_ALIAS aeabi_fneg negsf2 |
ff935d0c | 43 | CFI_START_FUNCTION |
6883a666 | 44 | |
496b84c8 RE |
45 | eor r0, r0, #0x80000000 @ flip sign bit |
46 | RET | |
4202ce82 | 47 | |
ff935d0c | 48 | CFI_END_FUNCTION |
b3f8d95d | 49 | FUNC_END aeabi_fneg |
496b84c8 | 50 | FUNC_END negsf2 |
4202ce82 | 51 | |
4202ce82 RE |
52 | #endif |
53 | ||
bf98ec6c | 54 | #ifdef L_arm_addsubsf3 |
4202ce82 | 55 | |
b3f8d95d | 56 | ARM_FUNC_START aeabi_frsub |
ff935d0c | 57 | CFI_START_FUNCTION |
b3f8d95d MM |
58 | |
59 | eor r0, r0, #0x80000000 @ flip sign bit of first arg | |
6883a666 NP |
60 | b 1f |
61 | ||
4202ce82 | 62 | ARM_FUNC_START subsf3 |
b3f8d95d | 63 | ARM_FUNC_ALIAS aeabi_fsub subsf3 |
6883a666 | 64 | |
4202ce82 | 65 | eor r1, r1, #0x80000000 @ flip sign bit of second arg |
4c5f9898 | 66 | #if defined(__INTERWORKING_STUBS__) |
4202ce82 RE |
67 | b 1f @ Skip Thumb-code prologue |
68 | #endif | |
69 | ||
70 | ARM_FUNC_START addsf3 | |
b3f8d95d | 71 | ARM_FUNC_ALIAS aeabi_fadd addsf3 |
4202ce82 | 72 | |
6883a666 NP |
73 | 1: @ Look for zeroes, equal values, INF, or NAN. |
74 | movs r2, r0, lsl #1 | |
5b3e6663 PB |
75 | do_it ne, ttt |
76 | COND(mov,s,ne) r3, r1, lsl #1 | |
6883a666 | 77 | teqne r2, r3 |
5b3e6663 PB |
78 | COND(mvn,s,ne) ip, r2, asr #24 |
79 | COND(mvn,s,ne) ip, r3, asr #24 | |
6883a666 | 80 | beq LSYM(Lad_s) |
4202ce82 RE |
81 | |
82 | @ Compute exponent difference. Make largest exponent in r2, | |
83 | @ corresponding arg in r0, and positive exponent difference in r3. | |
6883a666 NP |
84 | mov r2, r2, lsr #24 |
85 | rsbs r3, r2, r3, lsr #24 | |
5b3e6663 | 86 | do_it gt, ttt |
4202ce82 RE |
87 | addgt r2, r2, r3 |
88 | eorgt r1, r0, r1 | |
89 | eorgt r0, r1, r0 | |
90 | eorgt r1, r0, r1 | |
5b3e6663 | 91 | do_it lt |
4202ce82 RE |
92 | rsblt r3, r3, #0 |
93 | ||
94 | @ If exponent difference is too large, return largest argument | |
95 | @ already in r0. We need up to 25 bit to handle proper rounding | |
96 | @ of 0x1p25 - 1.1. | |
6883a666 | 97 | cmp r3, #25 |
5b3e6663 | 98 | do_it hi |
4202ce82 RE |
99 | RETc(hi) |
100 | ||
101 | @ Convert mantissa to signed integer. | |
102 | tst r0, #0x80000000 | |
103 | orr r0, r0, #0x00800000 | |
104 | bic r0, r0, #0xff000000 | |
5b3e6663 | 105 | do_it ne |
4202ce82 RE |
106 | rsbne r0, r0, #0 |
107 | tst r1, #0x80000000 | |
108 | orr r1, r1, #0x00800000 | |
109 | bic r1, r1, #0xff000000 | |
5b3e6663 | 110 | do_it ne |
4202ce82 RE |
111 | rsbne r1, r1, #0 |
112 | ||
113 | @ If exponent == difference, one or both args were denormalized. | |
114 | @ Since this is not common case, rescale them off line. | |
115 | teq r2, r3 | |
116 | beq LSYM(Lad_d) | |
117 | LSYM(Lad_x): | |
118 | ||
6883a666 NP |
119 | @ Compensate for the exponent overlapping the mantissa MSB added later |
120 | sub r2, r2, #1 | |
4202ce82 | 121 | |
6883a666 NP |
122 | @ Shift and add second arg to first arg in r0. |
123 | @ Keep leftover bits into r1. | |
5b3e6663 | 124 | shiftop adds r0 r0 r1 asr r3 ip |
4202ce82 | 125 | rsb r3, r3, #32 |
5b3e6663 | 126 | shift1 lsl, r1, r1, r3 |
4202ce82 | 127 | |
6883a666 NP |
128 | @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above) |
129 | and r3, r0, #0x80000000 | |
4202ce82 | 130 | bpl LSYM(Lad_p) |
5b3e6663 PB |
131 | #if defined(__thumb2__) |
132 | negs r1, r1 | |
133 | sbc r0, r0, r0, lsl #1 | |
134 | #else | |
4202ce82 RE |
135 | rsbs r1, r1, #0 |
136 | rsc r0, r0, #0 | |
5b3e6663 | 137 | #endif |
4202ce82 RE |
138 | |
139 | @ Determine how to normalize the result. | |
140 | LSYM(Lad_p): | |
141 | cmp r0, #0x00800000 | |
6883a666 | 142 | bcc LSYM(Lad_a) |
4202ce82 | 143 | cmp r0, #0x01000000 |
6883a666 | 144 | bcc LSYM(Lad_e) |
4202ce82 RE |
145 | |
146 | @ Result needs to be shifted right. | |
147 | movs r0, r0, lsr #1 | |
148 | mov r1, r1, rrx | |
6883a666 | 149 | add r2, r2, #1 |
4202ce82 RE |
150 | |
151 | @ Make sure we did not bust our exponent. | |
6883a666 NP |
152 | cmp r2, #254 |
153 | bhs LSYM(Lad_o) | |
4202ce82 | 154 | |
6883a666 | 155 | @ Our result is now properly aligned into r0, remaining bits in r1. |
4202ce82 | 156 | @ Pack final result together. |
6883a666 NP |
157 | @ Round with MSB of r1. If halfway between two numbers, round towards |
158 | @ LSB of r0 = 0. | |
4202ce82 | 159 | LSYM(Lad_e): |
6883a666 NP |
160 | cmp r1, #0x80000000 |
161 | adc r0, r0, r2, lsl #23 | |
5b3e6663 | 162 | do_it eq |
6883a666 | 163 | biceq r0, r0, #1 |
4202ce82 RE |
164 | orr r0, r0, r3 |
165 | RET | |
166 | ||
6883a666 NP |
167 | @ Result must be shifted left and exponent adjusted. |
168 | LSYM(Lad_a): | |
169 | movs r1, r1, lsl #1 | |
170 | adc r0, r0, r0 | |
89fff9cc NP |
171 | subs r2, r2, #1 |
172 | do_it hs | |
173 | cmphs r0, #0x00800000 | |
174 | bhs LSYM(Lad_e) | |
175 | ||
6883a666 | 176 | @ No rounding necessary since r1 will always be 0 at this point. |
4202ce82 RE |
177 | LSYM(Lad_l): |
178 | ||
9b2e34ef | 179 | #if !defined (__ARM_FEATURE_CLZ) |
4202ce82 RE |
180 | |
181 | movs ip, r0, lsr #12 | |
182 | moveq r0, r0, lsl #12 | |
6883a666 | 183 | subeq r2, r2, #12 |
4202ce82 RE |
184 | tst r0, #0x00ff0000 |
185 | moveq r0, r0, lsl #8 | |
6883a666 | 186 | subeq r2, r2, #8 |
4202ce82 RE |
187 | tst r0, #0x00f00000 |
188 | moveq r0, r0, lsl #4 | |
6883a666 | 189 | subeq r2, r2, #4 |
4202ce82 RE |
190 | tst r0, #0x00c00000 |
191 | moveq r0, r0, lsl #2 | |
6883a666 NP |
192 | subeq r2, r2, #2 |
193 | cmp r0, #0x00800000 | |
194 | movcc r0, r0, lsl #1 | |
195 | sbcs r2, r2, #0 | |
4202ce82 RE |
196 | |
197 | #else | |
198 | ||
199 | clz ip, r0 | |
200 | sub ip, ip, #8 | |
6883a666 | 201 | subs r2, r2, ip |
5b3e6663 | 202 | shift1 lsl, r0, r0, ip |
4202ce82 RE |
203 | |
204 | #endif | |
205 | ||
6883a666 NP |
206 | @ Final result with sign |
207 | @ If exponent negative, denormalize result. | |
5b3e6663 | 208 | do_it ge, et |
6883a666 NP |
209 | addge r0, r0, r2, lsl #23 |
210 | rsblt r2, r2, #0 | |
211 | orrge r0, r0, r3 | |
5b3e6663 PB |
212 | #if defined(__thumb2__) |
213 | do_it lt, t | |
214 | lsrlt r0, r0, r2 | |
215 | orrlt r0, r3, r0 | |
216 | #else | |
6883a666 | 217 | orrlt r0, r3, r0, lsr r2 |
5b3e6663 | 218 | #endif |
4202ce82 RE |
219 | RET |
220 | ||
221 | @ Fixup and adjust bit position for denormalized arguments. | |
222 | @ Note that r2 must not remain equal to 0. | |
223 | LSYM(Lad_d): | |
224 | teq r2, #0 | |
4202ce82 | 225 | eor r1, r1, #0x00800000 |
5b3e6663 | 226 | do_it eq, te |
6883a666 NP |
227 | eoreq r0, r0, #0x00800000 |
228 | addeq r2, r2, #1 | |
229 | subne r3, r3, #1 | |
4202ce82 RE |
230 | b LSYM(Lad_x) |
231 | ||
6883a666 NP |
232 | LSYM(Lad_s): |
233 | mov r3, r1, lsl #1 | |
234 | ||
235 | mvns ip, r2, asr #24 | |
5b3e6663 PB |
236 | do_it ne |
237 | COND(mvn,s,ne) ip, r3, asr #24 | |
6883a666 NP |
238 | beq LSYM(Lad_i) |
239 | ||
240 | teq r2, r3 | |
241 | beq 1f | |
242 | ||
243 | @ Result is x + 0.0 = x or 0.0 + y = y. | |
244 | teq r2, #0 | |
5b3e6663 | 245 | do_it eq |
6883a666 NP |
246 | moveq r0, r1 |
247 | RET | |
248 | ||
249 | 1: teq r0, r1 | |
250 | ||
251 | @ Result is x - x = 0. | |
5b3e6663 | 252 | do_it ne, t |
4202ce82 | 253 | movne r0, #0 |
6883a666 NP |
254 | RETc(ne) |
255 | ||
256 | @ Result is x + x = 2x. | |
257 | tst r2, #0xff000000 | |
258 | bne 2f | |
259 | movs r0, r0, lsl #1 | |
5b3e6663 | 260 | do_it cs |
6883a666 | 261 | orrcs r0, r0, #0x80000000 |
4202ce82 | 262 | RET |
6883a666 | 263 | 2: adds r2, r2, #(2 << 24) |
5b3e6663 | 264 | do_it cc, t |
6883a666 NP |
265 | addcc r0, r0, #(1 << 23) |
266 | RETc(cc) | |
267 | and r3, r0, #0x80000000 | |
4202ce82 RE |
268 | |
269 | @ Overflow: return INF. | |
270 | LSYM(Lad_o): | |
271 | orr r0, r3, #0x7f000000 | |
272 | orr r0, r0, #0x00800000 | |
273 | RET | |
274 | ||
275 | @ At least one of r0/r1 is INF/NAN. | |
276 | @ if r0 != INF/NAN: return r1 (which is INF/NAN) | |
277 | @ if r1 != INF/NAN: return r0 (which is INF/NAN) | |
278 | @ if r0 or r1 is NAN: return NAN | |
279 | @ if opposite sign: return NAN | |
6883a666 | 280 | @ otherwise return r0 (which is INF or -INF) |
4202ce82 | 281 | LSYM(Lad_i): |
6883a666 | 282 | mvns r2, r2, asr #24 |
5b3e6663 | 283 | do_it ne, et |
4202ce82 | 284 | movne r0, r1 |
5b3e6663 | 285 | COND(mvn,s,eq) r3, r3, asr #24 |
6883a666 | 286 | movne r1, r0 |
4202ce82 | 287 | movs r2, r0, lsl #9 |
5b3e6663 PB |
288 | do_it eq, te |
289 | COND(mov,s,eq) r3, r1, lsl #9 | |
4202ce82 | 290 | teqeq r0, r1 |
6883a666 | 291 | orrne r0, r0, #0x00400000 @ quiet NAN |
4202ce82 RE |
292 | RET |
293 | ||
ff935d0c | 294 | CFI_END_FUNCTION |
b3f8d95d MM |
295 | FUNC_END aeabi_frsub |
296 | FUNC_END aeabi_fadd | |
496b84c8 | 297 | FUNC_END addsf3 |
b3f8d95d | 298 | FUNC_END aeabi_fsub |
496b84c8 | 299 | FUNC_END subsf3 |
4202ce82 RE |
300 | |
301 | ARM_FUNC_START floatunsisf | |
b3f8d95d | 302 | ARM_FUNC_ALIAS aeabi_ui2f floatunsisf |
ff935d0c | 303 | CFI_START_FUNCTION |
b3f8d95d | 304 | |
4202ce82 RE |
305 | mov r3, #0 |
306 | b 1f | |
307 | ||
308 | ARM_FUNC_START floatsisf | |
b3f8d95d MM |
309 | ARM_FUNC_ALIAS aeabi_i2f floatsisf |
310 | ||
4202ce82 | 311 | ands r3, r0, #0x80000000 |
5b3e6663 | 312 | do_it mi |
4202ce82 RE |
313 | rsbmi r0, r0, #0 |
314 | ||
6883a666 | 315 | 1: movs ip, r0 |
5b3e6663 | 316 | do_it eq |
4202ce82 RE |
317 | RETc(eq) |
318 | ||
6883a666 NP |
319 | @ Add initial exponent to sign |
320 | orr r3, r3, #((127 + 23) << 23) | |
321 | ||
322 | .ifnc ah, r0 | |
323 | mov ah, r0 | |
324 | .endif | |
325 | mov al, #0 | |
326 | b 2f | |
4202ce82 | 327 | |
ff935d0c | 328 | CFI_END_FUNCTION |
b3f8d95d | 329 | FUNC_END aeabi_i2f |
496b84c8 | 330 | FUNC_END floatsisf |
b3f8d95d | 331 | FUNC_END aeabi_ui2f |
496b84c8 RE |
332 | FUNC_END floatunsisf |
333 | ||
0a1aa867 RE |
334 | ARM_FUNC_START floatundisf |
335 | ARM_FUNC_ALIAS aeabi_ul2f floatundisf | |
ff935d0c | 336 | CFI_START_FUNCTION |
6883a666 | 337 | |
0a1aa867 | 338 | orrs r2, r0, r1 |
5b3e6663 | 339 | do_it eq |
0a1aa867 | 340 | RETc(eq) |
0a1aa867 RE |
341 | |
342 | mov r3, #0 | |
6883a666 | 343 | b 1f |
0a1aa867 RE |
344 | |
345 | ARM_FUNC_START floatdisf | |
346 | ARM_FUNC_ALIAS aeabi_l2f floatdisf | |
347 | ||
348 | orrs r2, r0, r1 | |
5b3e6663 | 349 | do_it eq |
0a1aa867 | 350 | RETc(eq) |
6883a666 NP |
351 | |
352 | ands r3, ah, #0x80000000 @ sign bit in r3 | |
353 | bpl 1f | |
5b3e6663 PB |
354 | #if defined(__thumb2__) |
355 | negs al, al | |
356 | sbc ah, ah, ah, lsl #1 | |
357 | #else | |
6883a666 NP |
358 | rsbs al, al, #0 |
359 | rsc ah, ah, #0 | |
5b3e6663 | 360 | #endif |
6883a666 | 361 | 1: |
0a1aa867 | 362 | movs ip, ah |
5b3e6663 | 363 | do_it eq, tt |
6883a666 | 364 | moveq ip, al |
3188a512 NP |
365 | moveq ah, al |
366 | moveq al, #0 | |
6883a666 NP |
367 | |
368 | @ Add initial exponent to sign | |
369 | orr r3, r3, #((127 + 23 + 32) << 23) | |
5b3e6663 | 370 | do_it eq |
6883a666 NP |
371 | subeq r3, r3, #(32 << 23) |
372 | 2: sub r3, r3, #(1 << 23) | |
0a1aa867 | 373 | |
9b2e34ef | 374 | #if !defined (__ARM_FEATURE_CLZ) |
6883a666 NP |
375 | |
376 | mov r2, #23 | |
377 | cmp ip, #(1 << 16) | |
5b3e6663 | 378 | do_it hs, t |
6883a666 NP |
379 | movhs ip, ip, lsr #16 |
380 | subhs r2, r2, #16 | |
381 | cmp ip, #(1 << 8) | |
5b3e6663 | 382 | do_it hs, t |
6883a666 NP |
383 | movhs ip, ip, lsr #8 |
384 | subhs r2, r2, #8 | |
385 | cmp ip, #(1 << 4) | |
5b3e6663 | 386 | do_it hs, t |
6883a666 NP |
387 | movhs ip, ip, lsr #4 |
388 | subhs r2, r2, #4 | |
389 | cmp ip, #(1 << 2) | |
5b3e6663 | 390 | do_it hs, e |
6883a666 NP |
391 | subhs r2, r2, #2 |
392 | sublo r2, r2, ip, lsr #1 | |
393 | subs r2, r2, ip, lsr #3 | |
394 | ||
0a1aa867 | 395 | #else |
6883a666 NP |
396 | |
397 | clz r2, ip | |
398 | subs r2, r2, #8 | |
399 | ||
0a1aa867 | 400 | #endif |
6883a666 NP |
401 | |
402 | sub r3, r3, r2, lsl #23 | |
403 | blt 3f | |
404 | ||
5b3e6663 PB |
405 | shiftop add r3 r3 ah lsl r2 ip |
406 | shift1 lsl, ip, al, r2 | |
6883a666 NP |
407 | rsb r2, r2, #32 |
408 | cmp ip, #0x80000000 | |
5b3e6663 PB |
409 | shiftop adc r0 r3 al lsr r2 r2 |
410 | do_it eq | |
6883a666 NP |
411 | biceq r0, r0, #1 |
412 | RET | |
413 | ||
414 | 3: add r2, r2, #32 | |
5b3e6663 | 415 | shift1 lsl, ip, ah, r2 |
6883a666 NP |
416 | rsb r2, r2, #32 |
417 | orrs al, al, ip, lsl #1 | |
5b3e6663 PB |
418 | shiftop adc r0 r3 ah lsr r2 r2 |
419 | do_it eq | |
6883a666 NP |
420 | biceq r0, r0, ip, lsr #31 |
421 | RET | |
422 | ||
ff935d0c | 423 | CFI_END_FUNCTION |
0a1aa867 RE |
424 | FUNC_END floatdisf |
425 | FUNC_END aeabi_l2f | |
426 | FUNC_END floatundisf | |
427 | FUNC_END aeabi_ul2f | |
428 | ||
496b84c8 RE |
429 | #endif /* L_addsubsf3 */ |
430 | ||
72e3a529 TP |
431 | #if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3) |
432 | ||
433 | @ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden | |
434 | @ by the global definition in _arm_muldivsf3.o. This allows a program only | |
435 | @ using multiplication to take the weak definition which does not contain the | |
436 | @ division code. Programs using only division or both division and | |
437 | @ multiplication will pull _arm_muldivsf3.o from which both the multiplication | |
438 | @ and division are taken thanks to the override. | |
439 | #ifdef L_arm_mulsf3 | |
440 | WEAK mulsf3 | |
441 | WEAK aeabi_fmul | |
442 | #endif | |
4202ce82 RE |
443 | |
444 | ARM_FUNC_START mulsf3 | |
b3f8d95d | 445 | ARM_FUNC_ALIAS aeabi_fmul mulsf3 |
ff935d0c | 446 | CFI_START_FUNCTION |
4202ce82 | 447 | |
6883a666 NP |
448 | @ Mask out exponents, trap any zero/denormal/INF/NAN. |
449 | mov ip, #0xff | |
450 | ands r2, ip, r0, lsr #23 | |
5b3e6663 PB |
451 | do_it ne, tt |
452 | COND(and,s,ne) r3, ip, r1, lsr #23 | |
6883a666 NP |
453 | teqne r2, ip |
454 | teqne r3, ip | |
455 | beq LSYM(Lml_s) | |
4202ce82 | 456 | LSYM(Lml_x): |
4202ce82 | 457 | |
6883a666 NP |
458 | @ Add exponents together |
459 | add r2, r2, r3 | |
460 | ||
461 | @ Determine final sign. | |
462 | eor ip, r0, r1 | |
4202ce82 RE |
463 | |
464 | @ Convert mantissa to unsigned integer. | |
6883a666 NP |
465 | @ If power of two, branch to a separate path. |
466 | @ Make up for final alignment. | |
467 | movs r0, r0, lsl #9 | |
5b3e6663 PB |
468 | do_it ne |
469 | COND(mov,s,ne) r1, r1, lsl #9 | |
6883a666 NP |
470 | beq LSYM(Lml_1) |
471 | mov r3, #0x08000000 | |
472 | orr r0, r3, r0, lsr #5 | |
473 | orr r1, r3, r1, lsr #5 | |
4202ce82 | 474 | |
6883a666 | 475 | @ The actual multiplication. |
b7415975 | 476 | @ This code works on architecture versions >= 4 |
6883a666 NP |
477 | umull r3, r1, r0, r1 |
478 | ||
479 | @ Put final sign in r0. | |
480 | and r0, ip, #0x80000000 | |
4202ce82 | 481 | |
6883a666 NP |
482 | @ Adjust result upon the MSB position. |
483 | cmp r1, #(1 << 23) | |
5b3e6663 | 484 | do_it cc, tt |
6883a666 NP |
485 | movcc r1, r1, lsl #1 |
486 | orrcc r1, r1, r3, lsr #31 | |
487 | movcc r3, r3, lsl #1 | |
4202ce82 | 488 | |
6883a666 NP |
489 | @ Add sign to result. |
490 | orr r0, r0, r1 | |
4202ce82 | 491 | |
6883a666 NP |
492 | @ Apply exponent bias, check for under/overflow. |
493 | sbc r2, r2, #127 | |
494 | cmp r2, #(254 - 1) | |
495 | bhi LSYM(Lml_u) | |
4202ce82 | 496 | |
6883a666 NP |
497 | @ Round the result, merge final exponent. |
498 | cmp r3, #0x80000000 | |
499 | adc r0, r0, r2, lsl #23 | |
5b3e6663 | 500 | do_it eq |
6883a666 | 501 | biceq r0, r0, #1 |
4202ce82 RE |
502 | RET |
503 | ||
6883a666 NP |
504 | @ Multiplication by 0x1p*: let''s shortcut a lot of code. |
505 | LSYM(Lml_1): | |
506 | teq r0, #0 | |
507 | and ip, ip, #0x80000000 | |
5b3e6663 | 508 | do_it eq |
6883a666 NP |
509 | moveq r1, r1, lsl #9 |
510 | orr r0, ip, r0, lsr #9 | |
511 | orr r0, r0, r1, lsr #9 | |
512 | subs r2, r2, #127 | |
5b3e6663 PB |
513 | do_it gt, tt |
514 | COND(rsb,s,gt) r3, r2, #255 | |
6883a666 NP |
515 | orrgt r0, r0, r2, lsl #23 |
516 | RETc(gt) | |
517 | ||
518 | @ Under/overflow: fix things up for the code below. | |
519 | orr r0, r0, #0x00800000 | |
520 | mov r3, #0 | |
521 | subs r2, r2, #1 | |
4202ce82 | 522 | |
4202ce82 | 523 | LSYM(Lml_u): |
6883a666 NP |
524 | @ Overflow? |
525 | bgt LSYM(Lml_o) | |
4202ce82 | 526 | |
6883a666 NP |
527 | @ Check if denormalized result is possible, otherwise return signed 0. |
528 | cmn r2, #(24 + 1) | |
5b3e6663 | 529 | do_it le, t |
6883a666 NP |
530 | bicle r0, r0, #0x7fffffff |
531 | RETc(le) | |
4202ce82 RE |
532 | |
533 | @ Shift value right, round, etc. | |
6883a666 NP |
534 | rsb r2, r2, #0 |
535 | movs r1, r0, lsl #1 | |
5b3e6663 | 536 | shift1 lsr, r1, r1, r2 |
6883a666 | 537 | rsb r2, r2, #32 |
5b3e6663 | 538 | shift1 lsl, ip, r0, r2 |
6883a666 | 539 | movs r0, r1, rrx |
4202ce82 | 540 | adc r0, r0, #0 |
6883a666 | 541 | orrs r3, r3, ip, lsl #1 |
5b3e6663 | 542 | do_it eq |
6883a666 | 543 | biceq r0, r0, ip, lsr #31 |
4202ce82 RE |
544 | RET |
545 | ||
546 | @ One or both arguments are denormalized. | |
547 | @ Scale them leftwards and preserve sign bit. | |
548 | LSYM(Lml_d): | |
549 | teq r2, #0 | |
550 | and ip, r0, #0x80000000 | |
5b3e6663 PB |
551 | 1: do_it eq, tt |
552 | moveq r0, r0, lsl #1 | |
4202ce82 | 553 | tsteq r0, #0x00800000 |
6883a666 | 554 | subeq r2, r2, #1 |
4202ce82 RE |
555 | beq 1b |
556 | orr r0, r0, ip | |
557 | teq r3, #0 | |
558 | and ip, r1, #0x80000000 | |
5b3e6663 PB |
559 | 2: do_it eq, tt |
560 | moveq r1, r1, lsl #1 | |
4202ce82 | 561 | tsteq r1, #0x00800000 |
6883a666 | 562 | subeq r3, r3, #1 |
4202ce82 RE |
563 | beq 2b |
564 | orr r1, r1, ip | |
565 | b LSYM(Lml_x) | |
566 | ||
4202ce82 | 567 | LSYM(Lml_s): |
6883a666 NP |
568 | @ Isolate the INF and NAN cases away |
569 | and r3, ip, r1, lsr #23 | |
570 | teq r2, ip | |
5b3e6663 | 571 | do_it ne |
6883a666 NP |
572 | teqne r3, ip |
573 | beq 1f | |
574 | ||
575 | @ Here, one or more arguments are either denormalized or zero. | |
576 | bics ip, r0, #0x80000000 | |
5b3e6663 PB |
577 | do_it ne |
578 | COND(bic,s,ne) ip, r1, #0x80000000 | |
6883a666 NP |
579 | bne LSYM(Lml_d) |
580 | ||
581 | @ Result is 0, but determine sign anyway. | |
582 | LSYM(Lml_z): | |
583 | eor r0, r0, r1 | |
584 | bic r0, r0, #0x7fffffff | |
585 | RET | |
586 | ||
587 | 1: @ One or both args are INF or NAN. | |
4202ce82 | 588 | teq r0, #0x0 |
5b3e6663 | 589 | do_it ne, ett |
4202ce82 | 590 | teqne r0, #0x80000000 |
6883a666 NP |
591 | moveq r0, r1 |
592 | teqne r1, #0x0 | |
4202ce82 RE |
593 | teqne r1, #0x80000000 |
594 | beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN | |
6883a666 | 595 | teq r2, ip |
4202ce82 RE |
596 | bne 1f |
597 | movs r2, r0, lsl #9 | |
598 | bne LSYM(Lml_n) @ NAN * <anything> -> NAN | |
6883a666 | 599 | 1: teq r3, ip |
4202ce82 RE |
600 | bne LSYM(Lml_i) |
601 | movs r3, r1, lsl #9 | |
5b3e6663 | 602 | do_it ne |
6883a666 | 603 | movne r0, r1 |
4202ce82 RE |
604 | bne LSYM(Lml_n) @ <anything> * NAN -> NAN |
605 | ||
606 | @ Result is INF, but we need to determine its sign. | |
607 | LSYM(Lml_i): | |
608 | eor r0, r0, r1 | |
609 | ||
610 | @ Overflow: return INF (sign already in r0). | |
611 | LSYM(Lml_o): | |
612 | and r0, r0, #0x80000000 | |
613 | orr r0, r0, #0x7f000000 | |
614 | orr r0, r0, #0x00800000 | |
615 | RET | |
616 | ||
6883a666 | 617 | @ Return a quiet NAN. |
4202ce82 | 618 | LSYM(Lml_n): |
6883a666 | 619 | orr r0, r0, #0x7f000000 |
4202ce82 RE |
620 | orr r0, r0, #0x00c00000 |
621 | RET | |
622 | ||
ff935d0c | 623 | CFI_END_FUNCTION |
b3f8d95d | 624 | FUNC_END aeabi_fmul |
496b84c8 | 625 | FUNC_END mulsf3 |
4202ce82 | 626 | |
72e3a529 TP |
627 | #ifdef L_arm_muldivsf3 |
628 | ||
4202ce82 | 629 | ARM_FUNC_START divsf3 |
b3f8d95d | 630 | ARM_FUNC_ALIAS aeabi_fdiv divsf3 |
ff935d0c | 631 | CFI_START_FUNCTION |
4202ce82 | 632 | |
6883a666 NP |
633 | @ Mask out exponents, trap any zero/denormal/INF/NAN. |
634 | mov ip, #0xff | |
635 | ands r2, ip, r0, lsr #23 | |
5b3e6663 PB |
636 | do_it ne, tt |
637 | COND(and,s,ne) r3, ip, r1, lsr #23 | |
6883a666 NP |
638 | teqne r2, ip |
639 | teqne r3, ip | |
640 | beq LSYM(Ldv_s) | |
4202ce82 | 641 | LSYM(Ldv_x): |
6883a666 | 642 | |
d8c9d391 | 643 | @ Subtract divisor exponent from dividend''s |
6883a666 | 644 | sub r2, r2, r3 |
4202ce82 RE |
645 | |
646 | @ Preserve final sign into ip. | |
647 | eor ip, r0, r1 | |
648 | ||
649 | @ Convert mantissa to unsigned integer. | |
650 | @ Dividend -> r3, divisor -> r1. | |
4202ce82 RE |
651 | movs r1, r1, lsl #9 |
652 | mov r0, r0, lsl #9 | |
653 | beq LSYM(Ldv_1) | |
6883a666 | 654 | mov r3, #0x10000000 |
4202ce82 RE |
655 | orr r1, r3, r1, lsr #4 |
656 | orr r3, r3, r0, lsr #4 | |
657 | ||
658 | @ Initialize r0 (result) with final sign bit. | |
659 | and r0, ip, #0x80000000 | |
660 | ||
661 | @ Ensure result will land to known bit position. | |
6883a666 | 662 | @ Apply exponent bias accordingly. |
4202ce82 | 663 | cmp r3, r1 |
5b3e6663 | 664 | do_it cc |
4202ce82 | 665 | movcc r3, r3, lsl #1 |
6883a666 | 666 | adc r2, r2, #(127 - 2) |
4202ce82 RE |
667 | |
668 | @ The actual division loop. | |
669 | mov ip, #0x00800000 | |
670 | 1: cmp r3, r1 | |
5b3e6663 | 671 | do_it cs, t |
4202ce82 RE |
672 | subcs r3, r3, r1 |
673 | orrcs r0, r0, ip | |
674 | cmp r3, r1, lsr #1 | |
5b3e6663 | 675 | do_it cs, t |
4202ce82 RE |
676 | subcs r3, r3, r1, lsr #1 |
677 | orrcs r0, r0, ip, lsr #1 | |
678 | cmp r3, r1, lsr #2 | |
5b3e6663 | 679 | do_it cs, t |
4202ce82 RE |
680 | subcs r3, r3, r1, lsr #2 |
681 | orrcs r0, r0, ip, lsr #2 | |
682 | cmp r3, r1, lsr #3 | |
5b3e6663 | 683 | do_it cs, t |
4202ce82 RE |
684 | subcs r3, r3, r1, lsr #3 |
685 | orrcs r0, r0, ip, lsr #3 | |
686 | movs r3, r3, lsl #4 | |
5b3e6663 PB |
687 | do_it ne |
688 | COND(mov,s,ne) ip, ip, lsr #4 | |
4202ce82 RE |
689 | bne 1b |
690 | ||
6883a666 NP |
691 | @ Check exponent for under/overflow. |
692 | cmp r2, #(254 - 1) | |
693 | bhi LSYM(Lml_u) | |
4202ce82 | 694 | |
6883a666 | 695 | @ Round the result, merge final exponent. |
4202ce82 | 696 | cmp r3, r1 |
6883a666 | 697 | adc r0, r0, r2, lsl #23 |
5b3e6663 | 698 | do_it eq |
4202ce82 | 699 | biceq r0, r0, #1 |
4202ce82 RE |
700 | RET |
701 | ||
702 | @ Division by 0x1p*: let''s shortcut a lot of code. | |
703 | LSYM(Ldv_1): | |
704 | and ip, ip, #0x80000000 | |
705 | orr r0, ip, r0, lsr #9 | |
6883a666 | 706 | adds r2, r2, #127 |
5b3e6663 PB |
707 | do_it gt, tt |
708 | COND(rsb,s,gt) r3, r2, #255 | |
6883a666 | 709 | orrgt r0, r0, r2, lsl #23 |
4202ce82 | 710 | RETc(gt) |
6883a666 | 711 | |
4202ce82 RE |
712 | orr r0, r0, #0x00800000 |
713 | mov r3, #0 | |
6883a666 NP |
714 | subs r2, r2, #1 |
715 | b LSYM(Lml_u) | |
4202ce82 RE |
716 | |
717 | @ One or both arguments are denormalized. | |
718 | @ Scale them leftwards and preserve sign bit. | |
719 | LSYM(Ldv_d): | |
720 | teq r2, #0 | |
721 | and ip, r0, #0x80000000 | |
5b3e6663 PB |
722 | 1: do_it eq, tt |
723 | moveq r0, r0, lsl #1 | |
4202ce82 | 724 | tsteq r0, #0x00800000 |
6883a666 | 725 | subeq r2, r2, #1 |
4202ce82 RE |
726 | beq 1b |
727 | orr r0, r0, ip | |
728 | teq r3, #0 | |
729 | and ip, r1, #0x80000000 | |
5b3e6663 PB |
730 | 2: do_it eq, tt |
731 | moveq r1, r1, lsl #1 | |
4202ce82 | 732 | tsteq r1, #0x00800000 |
6883a666 | 733 | subeq r3, r3, #1 |
4202ce82 RE |
734 | beq 2b |
735 | orr r1, r1, ip | |
736 | b LSYM(Ldv_x) | |
737 | ||
6883a666 | 738 | @ One or both arguments are either INF, NAN, zero or denormalized. |
4202ce82 | 739 | LSYM(Ldv_s): |
6883a666 NP |
740 | and r3, ip, r1, lsr #23 |
741 | teq r2, ip | |
4202ce82 RE |
742 | bne 1f |
743 | movs r2, r0, lsl #9 | |
744 | bne LSYM(Lml_n) @ NAN / <anything> -> NAN | |
6883a666 NP |
745 | teq r3, ip |
746 | bne LSYM(Lml_i) @ INF / <anything> -> INF | |
747 | mov r0, r1 | |
748 | b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN | |
749 | 1: teq r3, ip | |
4202ce82 RE |
750 | bne 2f |
751 | movs r3, r1, lsl #9 | |
6883a666 NP |
752 | beq LSYM(Lml_z) @ <anything> / INF -> 0 |
753 | mov r0, r1 | |
754 | b LSYM(Lml_n) @ <anything> / NAN -> NAN | |
a4d05547 | 755 | 2: @ If both are nonzero, we need to normalize and resume above. |
6883a666 | 756 | bics ip, r0, #0x80000000 |
5b3e6663 PB |
757 | do_it ne |
758 | COND(bic,s,ne) ip, r1, #0x80000000 | |
6883a666 NP |
759 | bne LSYM(Ldv_d) |
760 | @ One or both arguments are zero. | |
4202ce82 RE |
761 | bics r2, r0, #0x80000000 |
762 | bne LSYM(Lml_i) @ <non_zero> / 0 -> INF | |
763 | bics r3, r1, #0x80000000 | |
764 | bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 | |
765 | b LSYM(Lml_n) @ 0 / 0 -> NAN | |
766 | ||
ff935d0c | 767 | CFI_END_FUNCTION |
b3f8d95d | 768 | FUNC_END aeabi_fdiv |
496b84c8 RE |
769 | FUNC_END divsf3 |
770 | ||
771 | #endif /* L_muldivsf3 */ | |
72e3a529 | 772 | #endif /* L_arm_mulsf3 || L_arm_muldivsf3 */ |
496b84c8 | 773 | |
bf98ec6c | 774 | #ifdef L_arm_cmpsf2 |
4202ce82 | 775 | |
b3f8d95d MM |
776 | @ The return value in r0 is |
777 | @ | |
778 | @ 0 if the operands are equal | |
779 | @ 1 if the first operand is greater than the second, or | |
780 | @ the operands are unordered and the operation is | |
781 | @ CMP, LT, LE, NE, or EQ. | |
782 | @ -1 if the first operand is less than the second, or | |
783 | @ the operands are unordered and the operation is GT | |
784 | @ or GE. | |
785 | @ | |
786 | @ The Z flag will be set iff the operands are equal. | |
787 | @ | |
788 | @ The following registers are clobbered by this function: | |
789 | @ ip, r0, r1, r2, r3 | |
790 | ||
4202ce82 | 791 | ARM_FUNC_START gtsf2 |
46049cff | 792 | ARM_FUNC_ALIAS gesf2 gtsf2 |
ff935d0c | 793 | CFI_START_FUNCTION |
6883a666 | 794 | mov ip, #-1 |
4202ce82 RE |
795 | b 1f |
796 | ||
4202ce82 | 797 | ARM_FUNC_START ltsf2 |
46049cff | 798 | ARM_FUNC_ALIAS lesf2 ltsf2 |
6883a666 | 799 | mov ip, #1 |
4202ce82 RE |
800 | b 1f |
801 | ||
4202ce82 | 802 | ARM_FUNC_START cmpsf2 |
46049cff RE |
803 | ARM_FUNC_ALIAS nesf2 cmpsf2 |
804 | ARM_FUNC_ALIAS eqsf2 cmpsf2 | |
6883a666 NP |
805 | mov ip, #1 @ how should we specify unordered here? |
806 | ||
b89f8e3c | 807 | 1: str ip, [sp, #-4]! |
ff935d0c MG |
808 | .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4. |
809 | @ We're not adding CFI for ip as it's pushed into the stack only because | |
810 | @ it may be popped off later as a return value (i.e. we're not preserving | |
811 | @ it anyways). | |
6883a666 NP |
812 | |
813 | @ Trap any INF/NAN first. | |
814 | mov r2, r0, lsl #1 | |
815 | mov r3, r1, lsl #1 | |
816 | mvns ip, r2, asr #24 | |
5b3e6663 PB |
817 | do_it ne |
818 | COND(mvn,s,ne) ip, r3, asr #24 | |
4202ce82 | 819 | beq 3f |
ff935d0c MG |
820 | .cfi_remember_state |
821 | @ Save the current CFI state. This is done because the branch is conditional, | |
822 | @ and if we don't take it we'll issue a .cfi_adjust_cfa_offset and return. | |
823 | @ If we do take it, however, the .cfi_adjust_cfa_offset from the non-branch | |
824 | @ code will affect the branch code as well. To avoid this we'll restore | |
825 | @ the current state before executing the branch code. | |
4202ce82 | 826 | |
6883a666 NP |
827 | @ Compare values. |
828 | @ Note that 0.0 is equal to -0.0. | |
b89f8e3c | 829 | 2: add sp, sp, #4 |
ff935d0c MG |
830 | .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset. |
831 | ||
b89f8e3c | 832 | orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag |
5b3e6663 | 833 | do_it ne |
6883a666 | 834 | teqne r0, r1 @ if not 0 compare sign |
5b3e6663 PB |
835 | do_it pl |
836 | COND(sub,s,pl) r0, r2, r3 @ if same sign compare values, set r0 | |
4202ce82 | 837 | |
6883a666 | 838 | @ Result: |
5b3e6663 | 839 | do_it hi |
6883a666 | 840 | movhi r0, r1, asr #31 |
5b3e6663 | 841 | do_it lo |
6883a666 | 842 | mvnlo r0, r1, asr #31 |
5b3e6663 | 843 | do_it ne |
6883a666 | 844 | orrne r0, r0, #1 |
4202ce82 RE |
845 | RET |
846 | ||
ff935d0c MG |
847 | 3: @ Look for a NAN. |
848 | ||
849 | @ Restore the previous CFI state (i.e. keep the CFI state as it was | |
850 | @ before the branch). | |
851 | .cfi_restore_state | |
852 | ||
853 | mvns ip, r2, asr #24 | |
4202ce82 | 854 | bne 4f |
4202ce82 | 855 | movs ip, r0, lsl #9 |
6883a666 NP |
856 | bne 5f @ r0 is NAN |
857 | 4: mvns ip, r3, asr #24 | |
858 | bne 2b | |
859 | movs ip, r1, lsl #9 | |
860 | beq 2b @ r1 is not NAN | |
ff935d0c | 861 | |
b89f8e3c | 862 | 5: ldr r0, [sp], #4 @ return unordered code. |
ff935d0c | 863 | .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset. |
4202ce82 RE |
864 | RET |
865 | ||
ff935d0c | 866 | CFI_END_FUNCTION |
496b84c8 RE |
867 | FUNC_END gesf2 |
868 | FUNC_END gtsf2 | |
869 | FUNC_END lesf2 | |
870 | FUNC_END ltsf2 | |
871 | FUNC_END nesf2 | |
872 | FUNC_END eqsf2 | |
873 | FUNC_END cmpsf2 | |
874 | ||
b3f8d95d | 875 | ARM_FUNC_START aeabi_cfrcmple |
ff935d0c | 876 | CFI_START_FUNCTION |
6883a666 | 877 | |
b3f8d95d MM |
878 | mov ip, r0 |
879 | mov r0, r1 | |
880 | mov r1, ip | |
881 | b 6f | |
6883a666 | 882 | |
b3f8d95d MM |
883 | ARM_FUNC_START aeabi_cfcmpeq |
884 | ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq | |
6883a666 | 885 | |
b3f8d95d MM |
886 | @ The status-returning routines are required to preserve all |
887 | @ registers except ip, lr, and cpsr. | |
5b3e6663 | 888 | 6: do_push {r0, r1, r2, r3, lr} |
ff935d0c MG |
889 | .cfi_adjust_cfa_offset 20 @ CFA is at sp + previousOffset + 20 |
890 | .cfi_rel_offset r0, 0 @ Registers are saved from sp to sp + 16 | |
891 | .cfi_rel_offset r1, 4 | |
892 | .cfi_rel_offset r2, 8 | |
893 | .cfi_rel_offset r3, 12 | |
894 | .cfi_rel_offset lr, 16 | |
895 | ||
b3f8d95d MM |
896 | ARM_CALL cmpsf2 |
897 | @ Set the Z flag correctly, and the C flag unconditionally. | |
5b3e6663 | 898 | cmp r0, #0 |
b3f8d95d MM |
899 | @ Clear the C flag if the return value was -1, indicating |
900 | @ that the first operand was smaller than the second. | |
5b3e6663 PB |
901 | do_it mi |
902 | cmnmi r0, #0 | |
903 | RETLDM "r0, r1, r2, r3" | |
6883a666 | 904 | |
ff935d0c | 905 | CFI_END_FUNCTION |
b3f8d95d MM |
906 | FUNC_END aeabi_cfcmple |
907 | FUNC_END aeabi_cfcmpeq | |
6883a666 NP |
908 | FUNC_END aeabi_cfrcmple |
909 | ||
b3f8d95d | 910 | ARM_FUNC_START aeabi_fcmpeq |
ff935d0c MG |
911 | CFI_START_FUNCTION |
912 | ||
913 | str lr, [sp, #-8]! @ sp -= 8 | |
914 | .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 | |
915 | .cfi_rel_offset lr, 0 @ lr is at sp | |
6883a666 | 916 | |
b3f8d95d | 917 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 918 | do_it eq, e |
b3f8d95d MM |
919 | moveq r0, #1 @ Equal to. |
920 | movne r0, #0 @ Less than, greater than, or unordered. | |
921 | RETLDM | |
6883a666 | 922 | |
ff935d0c | 923 | CFI_END_FUNCTION |
b3f8d95d MM |
924 | FUNC_END aeabi_fcmpeq |
925 | ||
926 | ARM_FUNC_START aeabi_fcmplt | |
ff935d0c MG |
927 | CFI_START_FUNCTION |
928 | ||
929 | str lr, [sp, #-8]! @ sp -= 8 | |
930 | .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 | |
931 | .cfi_rel_offset lr, 0 @ lr is at sp | |
6883a666 | 932 | |
b3f8d95d | 933 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 934 | do_it cc, e |
b3f8d95d MM |
935 | movcc r0, #1 @ Less than. |
936 | movcs r0, #0 @ Equal to, greater than, or unordered. | |
937 | RETLDM | |
6883a666 | 938 | |
ff935d0c | 939 | CFI_END_FUNCTION |
b3f8d95d MM |
940 | FUNC_END aeabi_fcmplt |
941 | ||
942 | ARM_FUNC_START aeabi_fcmple | |
ff935d0c MG |
943 | CFI_START_FUNCTION |
944 | ||
945 | str lr, [sp, #-8]! @ sp -= 8 | |
946 | .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 | |
947 | .cfi_rel_offset lr, 0 @ lr is at sp | |
6883a666 | 948 | |
b3f8d95d | 949 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 950 | do_it ls, e |
b3f8d95d MM |
951 | movls r0, #1 @ Less than or equal to. |
952 | movhi r0, #0 @ Greater than or unordered. | |
953 | RETLDM | |
6883a666 | 954 | |
ff935d0c | 955 | CFI_END_FUNCTION |
b3f8d95d MM |
956 | FUNC_END aeabi_fcmple |
957 | ||
958 | ARM_FUNC_START aeabi_fcmpge | |
ff935d0c MG |
959 | CFI_START_FUNCTION |
960 | ||
961 | str lr, [sp, #-8]! @ sp -= 8 | |
962 | .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 | |
963 | .cfi_rel_offset lr, 0 @ lr is at sp | |
6883a666 | 964 | |
b3f8d95d | 965 | ARM_CALL aeabi_cfrcmple |
5b3e6663 | 966 | do_it ls, e |
b3f8d95d MM |
967 | movls r0, #1 @ Operand 2 is less than or equal to operand 1. |
968 | movhi r0, #0 @ Operand 2 greater than operand 1, or unordered. | |
969 | RETLDM | |
6883a666 | 970 | |
ff935d0c | 971 | CFI_END_FUNCTION |
b3f8d95d MM |
972 | FUNC_END aeabi_fcmpge |
973 | ||
974 | ARM_FUNC_START aeabi_fcmpgt | |
ff935d0c MG |
975 | CFI_START_FUNCTION |
976 | ||
977 | str lr, [sp, #-8]! @ sp -= 8 | |
978 | .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 | |
979 | .cfi_rel_offset lr, 0 @ lr is at sp | |
6883a666 | 980 | |
b3f8d95d | 981 | ARM_CALL aeabi_cfrcmple |
5b3e6663 | 982 | do_it cc, e |
b3f8d95d MM |
983 | movcc r0, #1 @ Operand 2 is less than operand 1. |
984 | movcs r0, #0 @ Operand 2 is greater than or equal to operand 1, | |
985 | @ or they are unordered. | |
986 | RETLDM | |
6883a666 | 987 | |
ff935d0c | 988 | CFI_END_FUNCTION |
b3f8d95d | 989 | FUNC_END aeabi_fcmpgt |
6883a666 | 990 | |
496b84c8 RE |
991 | #endif /* L_cmpsf2 */ |
992 | ||
bf98ec6c | 993 | #ifdef L_arm_unordsf2 |
4202ce82 RE |
994 | |
995 | ARM_FUNC_START unordsf2 | |
b3f8d95d | 996 | ARM_FUNC_ALIAS aeabi_fcmpun unordsf2 |
ff935d0c | 997 | CFI_START_FUNCTION |
6883a666 NP |
998 | |
999 | mov r2, r0, lsl #1 | |
1000 | mov r3, r1, lsl #1 | |
1001 | mvns ip, r2, asr #24 | |
4202ce82 | 1002 | bne 1f |
6883a666 | 1003 | movs ip, r0, lsl #9 |
4202ce82 | 1004 | bne 3f @ r0 is NAN |
6883a666 NP |
1005 | 1: mvns ip, r3, asr #24 |
1006 | bne 2f | |
1007 | movs ip, r1, lsl #9 | |
1008 | bne 3f @ r1 is NAN | |
4202ce82 RE |
1009 | 2: mov r0, #0 @ arguments are ordered. |
1010 | RET | |
1011 | 3: mov r0, #1 @ arguments are unordered. | |
1012 | RET | |
1013 | ||
ff935d0c | 1014 | CFI_END_FUNCTION |
b3f8d95d | 1015 | FUNC_END aeabi_fcmpun |
496b84c8 RE |
1016 | FUNC_END unordsf2 |
1017 | ||
1018 | #endif /* L_unordsf2 */ | |
1019 | ||
bf98ec6c | 1020 | #ifdef L_arm_fixsfsi |
4202ce82 RE |
1021 | |
1022 | ARM_FUNC_START fixsfsi | |
b3f8d95d | 1023 | ARM_FUNC_ALIAS aeabi_f2iz fixsfsi |
ff935d0c | 1024 | CFI_START_FUNCTION |
4202ce82 RE |
1025 | |
1026 | @ check exponent range. | |
6883a666 | 1027 | mov r2, r0, lsl #1 |
4202ce82 | 1028 | cmp r2, #(127 << 24) |
6883a666 NP |
1029 | bcc 1f @ value is too small |
1030 | mov r3, #(127 + 31) | |
1031 | subs r2, r3, r2, lsr #24 | |
1032 | bls 2f @ value is too large | |
1033 | ||
1034 | @ scale value | |
1035 | mov r3, r0, lsl #8 | |
1036 | orr r3, r3, #0x80000000 | |
1037 | tst r0, #0x80000000 @ the sign bit | |
5b3e6663 PB |
1038 | shift1 lsr, r0, r3, r2 |
1039 | do_it ne | |
4202ce82 RE |
1040 | rsbne r0, r0, #0 |
1041 | RET | |
1042 | ||
6883a666 NP |
1043 | 1: mov r0, #0 |
1044 | RET | |
1045 | ||
1046 | 2: cmp r2, #(127 + 31 - 0xff) | |
1047 | bne 3f | |
1048 | movs r2, r0, lsl #9 | |
1049 | bne 4f @ r0 is NAN. | |
1050 | 3: ands r0, r0, #0x80000000 @ the sign bit | |
5b3e6663 | 1051 | do_it eq |
4202ce82 | 1052 | moveq r0, #0x7fffffff @ the maximum signed positive si |
4202ce82 RE |
1053 | RET |
1054 | ||
6883a666 | 1055 | 4: mov r0, #0 @ What should we convert NAN to? |
4202ce82 RE |
1056 | RET |
1057 | ||
ff935d0c | 1058 | CFI_END_FUNCTION |
b3f8d95d | 1059 | FUNC_END aeabi_f2iz |
496b84c8 RE |
1060 | FUNC_END fixsfsi |
1061 | ||
1062 | #endif /* L_fixsfsi */ | |
1063 | ||
bf98ec6c | 1064 | #ifdef L_arm_fixunssfsi |
4202ce82 RE |
1065 | |
1066 | ARM_FUNC_START fixunssfsi | |
b3f8d95d | 1067 | ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi |
ff935d0c | 1068 | CFI_START_FUNCTION |
4202ce82 RE |
1069 | |
1070 | @ check exponent range. | |
6883a666 NP |
1071 | movs r2, r0, lsl #1 |
1072 | bcs 1f @ value is negative | |
4202ce82 | 1073 | cmp r2, #(127 << 24) |
6883a666 NP |
1074 | bcc 1f @ value is too small |
1075 | mov r3, #(127 + 31) | |
1076 | subs r2, r3, r2, lsr #24 | |
1077 | bmi 2f @ value is too large | |
1078 | ||
1079 | @ scale the value | |
1080 | mov r3, r0, lsl #8 | |
1081 | orr r3, r3, #0x80000000 | |
5b3e6663 | 1082 | shift1 lsr, r0, r3, r2 |
6883a666 | 1083 | RET |
4202ce82 | 1084 | |
6883a666 | 1085 | 1: mov r0, #0 |
4202ce82 RE |
1086 | RET |
1087 | ||
6883a666 NP |
1088 | 2: cmp r2, #(127 + 31 - 0xff) |
1089 | bne 3f | |
1090 | movs r2, r0, lsl #9 | |
1091 | bne 4f @ r0 is NAN. | |
1092 | 3: mov r0, #0xffffffff @ maximum unsigned si | |
4202ce82 RE |
1093 | RET |
1094 | ||
6883a666 | 1095 | 4: mov r0, #0 @ What should we convert NAN to? |
496b84c8 RE |
1096 | RET |
1097 | ||
ff935d0c | 1098 | CFI_END_FUNCTION |
b3f8d95d | 1099 | FUNC_END aeabi_f2uiz |
496b84c8 | 1100 | FUNC_END fixunssfsi |
4202ce82 | 1101 | |
496b84c8 | 1102 | #endif /* L_fixunssfsi */ |