]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/arm/ieee754-sf.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / ieee754-sf.S
1 /* ieee754-sf.S single-precision floating point support for ARM
2
3 Copyright (C) 2003-2021 Free Software Foundation, Inc.
4 Contributed by Nicolas Pitre (nico@fluxnic.net)
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
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
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
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/>. */
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.
34 *
35 * In the CFI related comments, 'previousOffset' refers to the previous offset
36 * from sp used to compute the CFA.
37 */
38
39 #ifdef L_arm_negsf2
40
41 ARM_FUNC_START negsf2
42 ARM_FUNC_ALIAS aeabi_fneg negsf2
43 CFI_START_FUNCTION
44
45 eor r0, r0, #0x80000000 @ flip sign bit
46 RET
47
48 CFI_END_FUNCTION
49 FUNC_END aeabi_fneg
50 FUNC_END negsf2
51
52 #endif
53
54 #ifdef L_arm_addsubsf3
55
56 ARM_FUNC_START aeabi_frsub
57 CFI_START_FUNCTION
58
59 eor r0, r0, #0x80000000 @ flip sign bit of first arg
60 b 1f
61
62 ARM_FUNC_START subsf3
63 ARM_FUNC_ALIAS aeabi_fsub subsf3
64
65 eor r1, r1, #0x80000000 @ flip sign bit of second arg
66 #if defined(__INTERWORKING_STUBS__)
67 b 1f @ Skip Thumb-code prologue
68 #endif
69
70 ARM_FUNC_START addsf3
71 ARM_FUNC_ALIAS aeabi_fadd addsf3
72
73 1: @ Look for zeroes, equal values, INF, or NAN.
74 movs r2, r0, lsl #1
75 do_it ne, ttt
76 COND(mov,s,ne) r3, r1, lsl #1
77 teqne r2, r3
78 COND(mvn,s,ne) ip, r2, asr #24
79 COND(mvn,s,ne) ip, r3, asr #24
80 beq LSYM(Lad_s)
81
82 @ Compute exponent difference. Make largest exponent in r2,
83 @ corresponding arg in r0, and positive exponent difference in r3.
84 mov r2, r2, lsr #24
85 rsbs r3, r2, r3, lsr #24
86 do_it gt, ttt
87 addgt r2, r2, r3
88 eorgt r1, r0, r1
89 eorgt r0, r1, r0
90 eorgt r1, r0, r1
91 do_it lt
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.
97 cmp r3, #25
98 do_it hi
99 RETc(hi)
100
101 @ Convert mantissa to signed integer.
102 tst r0, #0x80000000
103 orr r0, r0, #0x00800000
104 bic r0, r0, #0xff000000
105 do_it ne
106 rsbne r0, r0, #0
107 tst r1, #0x80000000
108 orr r1, r1, #0x00800000
109 bic r1, r1, #0xff000000
110 do_it ne
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
119 @ Compensate for the exponent overlapping the mantissa MSB added later
120 sub r2, r2, #1
121
122 @ Shift and add second arg to first arg in r0.
123 @ Keep leftover bits into r1.
124 shiftop adds r0 r0 r1 asr r3 ip
125 rsb r3, r3, #32
126 shift1 lsl, r1, r1, r3
127
128 @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
129 and r3, r0, #0x80000000
130 bpl LSYM(Lad_p)
131 #if defined(__thumb2__)
132 negs r1, r1
133 sbc r0, r0, r0, lsl #1
134 #else
135 rsbs r1, r1, #0
136 rsc r0, r0, #0
137 #endif
138
139 @ Determine how to normalize the result.
140 LSYM(Lad_p):
141 cmp r0, #0x00800000
142 bcc LSYM(Lad_a)
143 cmp r0, #0x01000000
144 bcc LSYM(Lad_e)
145
146 @ Result needs to be shifted right.
147 movs r0, r0, lsr #1
148 mov r1, r1, rrx
149 add r2, r2, #1
150
151 @ Make sure we did not bust our exponent.
152 cmp r2, #254
153 bhs LSYM(Lad_o)
154
155 @ Our result is now properly aligned into r0, remaining bits in r1.
156 @ Pack final result together.
157 @ Round with MSB of r1. If halfway between two numbers, round towards
158 @ LSB of r0 = 0.
159 LSYM(Lad_e):
160 cmp r1, #0x80000000
161 adc r0, r0, r2, lsl #23
162 do_it eq
163 biceq r0, r0, #1
164 orr r0, r0, r3
165 RET
166
167 @ Result must be shifted left and exponent adjusted.
168 LSYM(Lad_a):
169 movs r1, r1, lsl #1
170 adc r0, r0, r0
171 subs r2, r2, #1
172 do_it hs
173 cmphs r0, #0x00800000
174 bhs LSYM(Lad_e)
175
176 @ No rounding necessary since r1 will always be 0 at this point.
177 LSYM(Lad_l):
178
179 #if !defined (__ARM_FEATURE_CLZ)
180
181 movs ip, r0, lsr #12
182 moveq r0, r0, lsl #12
183 subeq r2, r2, #12
184 tst r0, #0x00ff0000
185 moveq r0, r0, lsl #8
186 subeq r2, r2, #8
187 tst r0, #0x00f00000
188 moveq r0, r0, lsl #4
189 subeq r2, r2, #4
190 tst r0, #0x00c00000
191 moveq r0, r0, lsl #2
192 subeq r2, r2, #2
193 cmp r0, #0x00800000
194 movcc r0, r0, lsl #1
195 sbcs r2, r2, #0
196
197 #else
198
199 clz ip, r0
200 sub ip, ip, #8
201 subs r2, r2, ip
202 shift1 lsl, r0, r0, ip
203
204 #endif
205
206 @ Final result with sign
207 @ If exponent negative, denormalize result.
208 do_it ge, et
209 addge r0, r0, r2, lsl #23
210 rsblt r2, r2, #0
211 orrge r0, r0, r3
212 #if defined(__thumb2__)
213 do_it lt, t
214 lsrlt r0, r0, r2
215 orrlt r0, r3, r0
216 #else
217 orrlt r0, r3, r0, lsr r2
218 #endif
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
225 eor r1, r1, #0x00800000
226 do_it eq, te
227 eoreq r0, r0, #0x00800000
228 addeq r2, r2, #1
229 subne r3, r3, #1
230 b LSYM(Lad_x)
231
232 LSYM(Lad_s):
233 mov r3, r1, lsl #1
234
235 mvns ip, r2, asr #24
236 do_it ne
237 COND(mvn,s,ne) ip, r3, asr #24
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
245 do_it eq
246 moveq r0, r1
247 RET
248
249 1: teq r0, r1
250
251 @ Result is x - x = 0.
252 do_it ne, t
253 movne r0, #0
254 RETc(ne)
255
256 @ Result is x + x = 2x.
257 tst r2, #0xff000000
258 bne 2f
259 movs r0, r0, lsl #1
260 do_it cs
261 orrcs r0, r0, #0x80000000
262 RET
263 2: adds r2, r2, #(2 << 24)
264 do_it cc, t
265 addcc r0, r0, #(1 << 23)
266 RETc(cc)
267 and r3, r0, #0x80000000
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
280 @ otherwise return r0 (which is INF or -INF)
281 LSYM(Lad_i):
282 mvns r2, r2, asr #24
283 do_it ne, et
284 movne r0, r1
285 COND(mvn,s,eq) r3, r3, asr #24
286 movne r1, r0
287 movs r2, r0, lsl #9
288 do_it eq, te
289 COND(mov,s,eq) r3, r1, lsl #9
290 teqeq r0, r1
291 orrne r0, r0, #0x00400000 @ quiet NAN
292 RET
293
294 CFI_END_FUNCTION
295 FUNC_END aeabi_frsub
296 FUNC_END aeabi_fadd
297 FUNC_END addsf3
298 FUNC_END aeabi_fsub
299 FUNC_END subsf3
300
301 ARM_FUNC_START floatunsisf
302 ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
303 CFI_START_FUNCTION
304
305 mov r3, #0
306 b 1f
307
308 ARM_FUNC_START floatsisf
309 ARM_FUNC_ALIAS aeabi_i2f floatsisf
310
311 ands r3, r0, #0x80000000
312 do_it mi
313 rsbmi r0, r0, #0
314
315 1: movs ip, r0
316 do_it eq
317 RETc(eq)
318
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
327
328 CFI_END_FUNCTION
329 FUNC_END aeabi_i2f
330 FUNC_END floatsisf
331 FUNC_END aeabi_ui2f
332 FUNC_END floatunsisf
333
334 ARM_FUNC_START floatundisf
335 ARM_FUNC_ALIAS aeabi_ul2f floatundisf
336 CFI_START_FUNCTION
337
338 orrs r2, r0, r1
339 do_it eq
340 RETc(eq)
341
342 mov r3, #0
343 b 1f
344
345 ARM_FUNC_START floatdisf
346 ARM_FUNC_ALIAS aeabi_l2f floatdisf
347
348 orrs r2, r0, r1
349 do_it eq
350 RETc(eq)
351
352 ands r3, ah, #0x80000000 @ sign bit in r3
353 bpl 1f
354 #if defined(__thumb2__)
355 negs al, al
356 sbc ah, ah, ah, lsl #1
357 #else
358 rsbs al, al, #0
359 rsc ah, ah, #0
360 #endif
361 1:
362 movs ip, ah
363 do_it eq, tt
364 moveq ip, al
365 moveq ah, al
366 moveq al, #0
367
368 @ Add initial exponent to sign
369 orr r3, r3, #((127 + 23 + 32) << 23)
370 do_it eq
371 subeq r3, r3, #(32 << 23)
372 2: sub r3, r3, #(1 << 23)
373
374 #if !defined (__ARM_FEATURE_CLZ)
375
376 mov r2, #23
377 cmp ip, #(1 << 16)
378 do_it hs, t
379 movhs ip, ip, lsr #16
380 subhs r2, r2, #16
381 cmp ip, #(1 << 8)
382 do_it hs, t
383 movhs ip, ip, lsr #8
384 subhs r2, r2, #8
385 cmp ip, #(1 << 4)
386 do_it hs, t
387 movhs ip, ip, lsr #4
388 subhs r2, r2, #4
389 cmp ip, #(1 << 2)
390 do_it hs, e
391 subhs r2, r2, #2
392 sublo r2, r2, ip, lsr #1
393 subs r2, r2, ip, lsr #3
394
395 #else
396
397 clz r2, ip
398 subs r2, r2, #8
399
400 #endif
401
402 sub r3, r3, r2, lsl #23
403 blt 3f
404
405 shiftop add r3 r3 ah lsl r2 ip
406 shift1 lsl, ip, al, r2
407 rsb r2, r2, #32
408 cmp ip, #0x80000000
409 shiftop adc r0 r3 al lsr r2 r2
410 do_it eq
411 biceq r0, r0, #1
412 RET
413
414 3: add r2, r2, #32
415 shift1 lsl, ip, ah, r2
416 rsb r2, r2, #32
417 orrs al, al, ip, lsl #1
418 shiftop adc r0 r3 ah lsr r2 r2
419 do_it eq
420 biceq r0, r0, ip, lsr #31
421 RET
422
423 CFI_END_FUNCTION
424 FUNC_END floatdisf
425 FUNC_END aeabi_l2f
426 FUNC_END floatundisf
427 FUNC_END aeabi_ul2f
428
429 #endif /* L_addsubsf3 */
430
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
443
444 ARM_FUNC_START mulsf3
445 ARM_FUNC_ALIAS aeabi_fmul mulsf3
446 CFI_START_FUNCTION
447
448 @ Mask out exponents, trap any zero/denormal/INF/NAN.
449 mov ip, #0xff
450 ands r2, ip, r0, lsr #23
451 do_it ne, tt
452 COND(and,s,ne) r3, ip, r1, lsr #23
453 teqne r2, ip
454 teqne r3, ip
455 beq LSYM(Lml_s)
456 LSYM(Lml_x):
457
458 @ Add exponents together
459 add r2, r2, r3
460
461 @ Determine final sign.
462 eor ip, r0, r1
463
464 @ Convert mantissa to unsigned integer.
465 @ If power of two, branch to a separate path.
466 @ Make up for final alignment.
467 movs r0, r0, lsl #9
468 do_it ne
469 COND(mov,s,ne) r1, r1, lsl #9
470 beq LSYM(Lml_1)
471 mov r3, #0x08000000
472 orr r0, r3, r0, lsr #5
473 orr r1, r3, r1, lsr #5
474
475 @ The actual multiplication.
476 @ This code works on architecture versions >= 4
477 umull r3, r1, r0, r1
478
479 @ Put final sign in r0.
480 and r0, ip, #0x80000000
481
482 @ Adjust result upon the MSB position.
483 cmp r1, #(1 << 23)
484 do_it cc, tt
485 movcc r1, r1, lsl #1
486 orrcc r1, r1, r3, lsr #31
487 movcc r3, r3, lsl #1
488
489 @ Add sign to result.
490 orr r0, r0, r1
491
492 @ Apply exponent bias, check for under/overflow.
493 sbc r2, r2, #127
494 cmp r2, #(254 - 1)
495 bhi LSYM(Lml_u)
496
497 @ Round the result, merge final exponent.
498 cmp r3, #0x80000000
499 adc r0, r0, r2, lsl #23
500 do_it eq
501 biceq r0, r0, #1
502 RET
503
504 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
505 LSYM(Lml_1):
506 teq r0, #0
507 and ip, ip, #0x80000000
508 do_it eq
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
513 do_it gt, tt
514 COND(rsb,s,gt) r3, r2, #255
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
522
523 LSYM(Lml_u):
524 @ Overflow?
525 bgt LSYM(Lml_o)
526
527 @ Check if denormalized result is possible, otherwise return signed 0.
528 cmn r2, #(24 + 1)
529 do_it le, t
530 bicle r0, r0, #0x7fffffff
531 RETc(le)
532
533 @ Shift value right, round, etc.
534 rsb r2, r2, #0
535 movs r1, r0, lsl #1
536 shift1 lsr, r1, r1, r2
537 rsb r2, r2, #32
538 shift1 lsl, ip, r0, r2
539 movs r0, r1, rrx
540 adc r0, r0, #0
541 orrs r3, r3, ip, lsl #1
542 do_it eq
543 biceq r0, r0, ip, lsr #31
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
551 1: do_it eq, tt
552 moveq r0, r0, lsl #1
553 tsteq r0, #0x00800000
554 subeq r2, r2, #1
555 beq 1b
556 orr r0, r0, ip
557 teq r3, #0
558 and ip, r1, #0x80000000
559 2: do_it eq, tt
560 moveq r1, r1, lsl #1
561 tsteq r1, #0x00800000
562 subeq r3, r3, #1
563 beq 2b
564 orr r1, r1, ip
565 b LSYM(Lml_x)
566
567 LSYM(Lml_s):
568 @ Isolate the INF and NAN cases away
569 and r3, ip, r1, lsr #23
570 teq r2, ip
571 do_it ne
572 teqne r3, ip
573 beq 1f
574
575 @ Here, one or more arguments are either denormalized or zero.
576 bics ip, r0, #0x80000000
577 do_it ne
578 COND(bic,s,ne) ip, r1, #0x80000000
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.
588 teq r0, #0x0
589 do_it ne, ett
590 teqne r0, #0x80000000
591 moveq r0, r1
592 teqne r1, #0x0
593 teqne r1, #0x80000000
594 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
595 teq r2, ip
596 bne 1f
597 movs r2, r0, lsl #9
598 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
599 1: teq r3, ip
600 bne LSYM(Lml_i)
601 movs r3, r1, lsl #9
602 do_it ne
603 movne r0, r1
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
617 @ Return a quiet NAN.
618 LSYM(Lml_n):
619 orr r0, r0, #0x7f000000
620 orr r0, r0, #0x00c00000
621 RET
622
623 CFI_END_FUNCTION
624 FUNC_END aeabi_fmul
625 FUNC_END mulsf3
626
627 #ifdef L_arm_muldivsf3
628
629 ARM_FUNC_START divsf3
630 ARM_FUNC_ALIAS aeabi_fdiv divsf3
631 CFI_START_FUNCTION
632
633 @ Mask out exponents, trap any zero/denormal/INF/NAN.
634 mov ip, #0xff
635 ands r2, ip, r0, lsr #23
636 do_it ne, tt
637 COND(and,s,ne) r3, ip, r1, lsr #23
638 teqne r2, ip
639 teqne r3, ip
640 beq LSYM(Ldv_s)
641 LSYM(Ldv_x):
642
643 @ Subtract divisor exponent from dividend''s
644 sub r2, r2, r3
645
646 @ Preserve final sign into ip.
647 eor ip, r0, r1
648
649 @ Convert mantissa to unsigned integer.
650 @ Dividend -> r3, divisor -> r1.
651 movs r1, r1, lsl #9
652 mov r0, r0, lsl #9
653 beq LSYM(Ldv_1)
654 mov r3, #0x10000000
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.
662 @ Apply exponent bias accordingly.
663 cmp r3, r1
664 do_it cc
665 movcc r3, r3, lsl #1
666 adc r2, r2, #(127 - 2)
667
668 @ The actual division loop.
669 mov ip, #0x00800000
670 1: cmp r3, r1
671 do_it cs, t
672 subcs r3, r3, r1
673 orrcs r0, r0, ip
674 cmp r3, r1, lsr #1
675 do_it cs, t
676 subcs r3, r3, r1, lsr #1
677 orrcs r0, r0, ip, lsr #1
678 cmp r3, r1, lsr #2
679 do_it cs, t
680 subcs r3, r3, r1, lsr #2
681 orrcs r0, r0, ip, lsr #2
682 cmp r3, r1, lsr #3
683 do_it cs, t
684 subcs r3, r3, r1, lsr #3
685 orrcs r0, r0, ip, lsr #3
686 movs r3, r3, lsl #4
687 do_it ne
688 COND(mov,s,ne) ip, ip, lsr #4
689 bne 1b
690
691 @ Check exponent for under/overflow.
692 cmp r2, #(254 - 1)
693 bhi LSYM(Lml_u)
694
695 @ Round the result, merge final exponent.
696 cmp r3, r1
697 adc r0, r0, r2, lsl #23
698 do_it eq
699 biceq r0, r0, #1
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
706 adds r2, r2, #127
707 do_it gt, tt
708 COND(rsb,s,gt) r3, r2, #255
709 orrgt r0, r0, r2, lsl #23
710 RETc(gt)
711
712 orr r0, r0, #0x00800000
713 mov r3, #0
714 subs r2, r2, #1
715 b LSYM(Lml_u)
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
722 1: do_it eq, tt
723 moveq r0, r0, lsl #1
724 tsteq r0, #0x00800000
725 subeq r2, r2, #1
726 beq 1b
727 orr r0, r0, ip
728 teq r3, #0
729 and ip, r1, #0x80000000
730 2: do_it eq, tt
731 moveq r1, r1, lsl #1
732 tsteq r1, #0x00800000
733 subeq r3, r3, #1
734 beq 2b
735 orr r1, r1, ip
736 b LSYM(Ldv_x)
737
738 @ One or both arguments are either INF, NAN, zero or denormalized.
739 LSYM(Ldv_s):
740 and r3, ip, r1, lsr #23
741 teq r2, ip
742 bne 1f
743 movs r2, r0, lsl #9
744 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
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
750 bne 2f
751 movs r3, r1, lsl #9
752 beq LSYM(Lml_z) @ <anything> / INF -> 0
753 mov r0, r1
754 b LSYM(Lml_n) @ <anything> / NAN -> NAN
755 2: @ If both are nonzero, we need to normalize and resume above.
756 bics ip, r0, #0x80000000
757 do_it ne
758 COND(bic,s,ne) ip, r1, #0x80000000
759 bne LSYM(Ldv_d)
760 @ One or both arguments are zero.
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
767 CFI_END_FUNCTION
768 FUNC_END aeabi_fdiv
769 FUNC_END divsf3
770
771 #endif /* L_muldivsf3 */
772 #endif /* L_arm_mulsf3 || L_arm_muldivsf3 */
773
774 #ifdef L_arm_cmpsf2
775
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
791 ARM_FUNC_START gtsf2
792 ARM_FUNC_ALIAS gesf2 gtsf2
793 CFI_START_FUNCTION
794 mov ip, #-1
795 b 1f
796
797 ARM_FUNC_START ltsf2
798 ARM_FUNC_ALIAS lesf2 ltsf2
799 mov ip, #1
800 b 1f
801
802 ARM_FUNC_START cmpsf2
803 ARM_FUNC_ALIAS nesf2 cmpsf2
804 ARM_FUNC_ALIAS eqsf2 cmpsf2
805 mov ip, #1 @ how should we specify unordered here?
806
807 1: str ip, [sp, #-4]!
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).
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
817 do_it ne
818 COND(mvn,s,ne) ip, r3, asr #24
819 beq 3f
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.
826
827 @ Compare values.
828 @ Note that 0.0 is equal to -0.0.
829 2: add sp, sp, #4
830 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
831
832 orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag
833 do_it ne
834 teqne r0, r1 @ if not 0 compare sign
835 do_it pl
836 COND(sub,s,pl) r0, r2, r3 @ if same sign compare values, set r0
837
838 @ Result:
839 do_it hi
840 movhi r0, r1, asr #31
841 do_it lo
842 mvnlo r0, r1, asr #31
843 do_it ne
844 orrne r0, r0, #1
845 RET
846
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
854 bne 4f
855 movs ip, r0, lsl #9
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
861
862 5: ldr r0, [sp], #4 @ return unordered code.
863 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
864 RET
865
866 CFI_END_FUNCTION
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
875 ARM_FUNC_START aeabi_cfrcmple
876 CFI_START_FUNCTION
877
878 mov ip, r0
879 mov r0, r1
880 mov r1, ip
881 b 6f
882
883 ARM_FUNC_START aeabi_cfcmpeq
884 ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
885
886 @ The status-returning routines are required to preserve all
887 @ registers except ip, lr, and cpsr.
888 6: do_push {r0, r1, r2, r3, lr}
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
896 ARM_CALL cmpsf2
897 @ Set the Z flag correctly, and the C flag unconditionally.
898 cmp r0, #0
899 @ Clear the C flag if the return value was -1, indicating
900 @ that the first operand was smaller than the second.
901 do_it mi
902 cmnmi r0, #0
903 RETLDM "r0, r1, r2, r3"
904
905 CFI_END_FUNCTION
906 FUNC_END aeabi_cfcmple
907 FUNC_END aeabi_cfcmpeq
908 FUNC_END aeabi_cfrcmple
909
910 ARM_FUNC_START aeabi_fcmpeq
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
916
917 ARM_CALL aeabi_cfcmple
918 do_it eq, e
919 moveq r0, #1 @ Equal to.
920 movne r0, #0 @ Less than, greater than, or unordered.
921 RETLDM
922
923 CFI_END_FUNCTION
924 FUNC_END aeabi_fcmpeq
925
926 ARM_FUNC_START aeabi_fcmplt
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
932
933 ARM_CALL aeabi_cfcmple
934 do_it cc, e
935 movcc r0, #1 @ Less than.
936 movcs r0, #0 @ Equal to, greater than, or unordered.
937 RETLDM
938
939 CFI_END_FUNCTION
940 FUNC_END aeabi_fcmplt
941
942 ARM_FUNC_START aeabi_fcmple
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
948
949 ARM_CALL aeabi_cfcmple
950 do_it ls, e
951 movls r0, #1 @ Less than or equal to.
952 movhi r0, #0 @ Greater than or unordered.
953 RETLDM
954
955 CFI_END_FUNCTION
956 FUNC_END aeabi_fcmple
957
958 ARM_FUNC_START aeabi_fcmpge
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
964
965 ARM_CALL aeabi_cfrcmple
966 do_it ls, e
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
970
971 CFI_END_FUNCTION
972 FUNC_END aeabi_fcmpge
973
974 ARM_FUNC_START aeabi_fcmpgt
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
980
981 ARM_CALL aeabi_cfrcmple
982 do_it cc, e
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
987
988 CFI_END_FUNCTION
989 FUNC_END aeabi_fcmpgt
990
991 #endif /* L_cmpsf2 */
992
993 #ifdef L_arm_unordsf2
994
995 ARM_FUNC_START unordsf2
996 ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
997 CFI_START_FUNCTION
998
999 mov r2, r0, lsl #1
1000 mov r3, r1, lsl #1
1001 mvns ip, r2, asr #24
1002 bne 1f
1003 movs ip, r0, lsl #9
1004 bne 3f @ r0 is NAN
1005 1: mvns ip, r3, asr #24
1006 bne 2f
1007 movs ip, r1, lsl #9
1008 bne 3f @ r1 is NAN
1009 2: mov r0, #0 @ arguments are ordered.
1010 RET
1011 3: mov r0, #1 @ arguments are unordered.
1012 RET
1013
1014 CFI_END_FUNCTION
1015 FUNC_END aeabi_fcmpun
1016 FUNC_END unordsf2
1017
1018 #endif /* L_unordsf2 */
1019
1020 #ifdef L_arm_fixsfsi
1021
1022 ARM_FUNC_START fixsfsi
1023 ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
1024 CFI_START_FUNCTION
1025
1026 @ check exponent range.
1027 mov r2, r0, lsl #1
1028 cmp r2, #(127 << 24)
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
1038 shift1 lsr, r0, r3, r2
1039 do_it ne
1040 rsbne r0, r0, #0
1041 RET
1042
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
1051 do_it eq
1052 moveq r0, #0x7fffffff @ the maximum signed positive si
1053 RET
1054
1055 4: mov r0, #0 @ What should we convert NAN to?
1056 RET
1057
1058 CFI_END_FUNCTION
1059 FUNC_END aeabi_f2iz
1060 FUNC_END fixsfsi
1061
1062 #endif /* L_fixsfsi */
1063
1064 #ifdef L_arm_fixunssfsi
1065
1066 ARM_FUNC_START fixunssfsi
1067 ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
1068 CFI_START_FUNCTION
1069
1070 @ check exponent range.
1071 movs r2, r0, lsl #1
1072 bcs 1f @ value is negative
1073 cmp r2, #(127 << 24)
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
1082 shift1 lsr, r0, r3, r2
1083 RET
1084
1085 1: mov r0, #0
1086 RET
1087
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
1093 RET
1094
1095 4: mov r0, #0 @ What should we convert NAN to?
1096 RET
1097
1098 CFI_END_FUNCTION
1099 FUNC_END aeabi_f2uiz
1100 FUNC_END fixunssfsi
1101
1102 #endif /* L_fixunssfsi */