PR bootstrap/82916
[official-gcc.git] / libgcc / config / arm / ieee754-sf.S
blob86c3199e019502dd2aa5141d59ef2810f7e26c2e
1 /* ieee754-sf.S single-precision floating point support for ARM
3    Copyright (C) 2003-2017 Free Software Foundation, Inc.
4    Contributed by Nicolas Pitre (nico@cam.org)
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.
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.
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.
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/>.  */
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  */
39 #ifdef L_arm_negsf2
40         
41 ARM_FUNC_START negsf2
42 ARM_FUNC_ALIAS aeabi_fneg negsf2
43         CFI_START_FUNCTION
45         eor     r0, r0, #0x80000000     @ flip sign bit
46         RET
48         CFI_END_FUNCTION
49         FUNC_END aeabi_fneg
50         FUNC_END negsf2
52 #endif
54 #ifdef L_arm_addsubsf3
56 ARM_FUNC_START aeabi_frsub
57         CFI_START_FUNCTION
59         eor     r0, r0, #0x80000000     @ flip sign bit of first arg
60         b       1f
62 ARM_FUNC_START subsf3
63 ARM_FUNC_ALIAS aeabi_fsub subsf3
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
70 ARM_FUNC_START addsf3
71 ARM_FUNC_ALIAS aeabi_fadd addsf3
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)
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
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)
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
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):
119         @ Compensate for the exponent overlapping the mantissa MSB added later
120         sub     r2, r2, #1
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
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
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)
146         @ Result needs to be shifted right.
147         movs    r0, r0, lsr #1
148         mov     r1, r1, rrx
149         add     r2, r2, #1
151         @ Make sure we did not bust our exponent.
152         cmp     r2, #254
153         bhs     LSYM(Lad_o)
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
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         tst     r0, #0x00800000
172         sub     r2, r2, #1
173         bne     LSYM(Lad_e)
174         
175         @ No rounding necessary since r1 will always be 0 at this point.
176 LSYM(Lad_l):
178 #if __ARM_ARCH__ < 5
180         movs    ip, r0, lsr #12
181         moveq   r0, r0, lsl #12
182         subeq   r2, r2, #12
183         tst     r0, #0x00ff0000
184         moveq   r0, r0, lsl #8
185         subeq   r2, r2, #8
186         tst     r0, #0x00f00000
187         moveq   r0, r0, lsl #4
188         subeq   r2, r2, #4
189         tst     r0, #0x00c00000
190         moveq   r0, r0, lsl #2
191         subeq   r2, r2, #2
192         cmp     r0, #0x00800000
193         movcc   r0, r0, lsl #1
194         sbcs    r2, r2, #0
196 #else
198         clz     ip, r0
199         sub     ip, ip, #8
200         subs    r2, r2, ip
201         shift1  lsl, r0, r0, ip
203 #endif
205         @ Final result with sign
206         @ If exponent negative, denormalize result.
207         do_it   ge, et
208         addge   r0, r0, r2, lsl #23
209         rsblt   r2, r2, #0
210         orrge   r0, r0, r3
211 #if defined(__thumb2__)
212         do_it   lt, t
213         lsrlt   r0, r0, r2
214         orrlt   r0, r3, r0
215 #else
216         orrlt   r0, r3, r0, lsr r2
217 #endif
218         RET
220         @ Fixup and adjust bit position for denormalized arguments.
221         @ Note that r2 must not remain equal to 0.
222 LSYM(Lad_d):
223         teq     r2, #0
224         eor     r1, r1, #0x00800000
225         do_it   eq, te
226         eoreq   r0, r0, #0x00800000
227         addeq   r2, r2, #1
228         subne   r3, r3, #1
229         b       LSYM(Lad_x)
231 LSYM(Lad_s):
232         mov     r3, r1, lsl #1
234         mvns    ip, r2, asr #24
235         do_it   ne
236         COND(mvn,s,ne)  ip, r3, asr #24
237         beq     LSYM(Lad_i)
239         teq     r2, r3
240         beq     1f
242         @ Result is x + 0.0 = x or 0.0 + y = y.
243         teq     r2, #0
244         do_it   eq
245         moveq   r0, r1
246         RET
248 1:      teq     r0, r1
250         @ Result is x - x = 0.
251         do_it   ne, t
252         movne   r0, #0
253         RETc(ne)
255         @ Result is x + x = 2x.
256         tst     r2, #0xff000000
257         bne     2f
258         movs    r0, r0, lsl #1
259         do_it   cs
260         orrcs   r0, r0, #0x80000000
261         RET
262 2:      adds    r2, r2, #(2 << 24)
263         do_it   cc, t
264         addcc   r0, r0, #(1 << 23)
265         RETc(cc)
266         and     r3, r0, #0x80000000
268         @ Overflow: return INF.
269 LSYM(Lad_o):
270         orr     r0, r3, #0x7f000000
271         orr     r0, r0, #0x00800000
272         RET
274         @ At least one of r0/r1 is INF/NAN.
275         @   if r0 != INF/NAN: return r1 (which is INF/NAN)
276         @   if r1 != INF/NAN: return r0 (which is INF/NAN)
277         @   if r0 or r1 is NAN: return NAN
278         @   if opposite sign: return NAN
279         @   otherwise return r0 (which is INF or -INF)
280 LSYM(Lad_i):
281         mvns    r2, r2, asr #24
282         do_it   ne, et
283         movne   r0, r1
284         COND(mvn,s,eq)  r3, r3, asr #24
285         movne   r1, r0
286         movs    r2, r0, lsl #9
287         do_it   eq, te
288         COND(mov,s,eq)  r3, r1, lsl #9
289         teqeq   r0, r1
290         orrne   r0, r0, #0x00400000     @ quiet NAN
291         RET
293         CFI_END_FUNCTION
294         FUNC_END aeabi_frsub
295         FUNC_END aeabi_fadd
296         FUNC_END addsf3
297         FUNC_END aeabi_fsub
298         FUNC_END subsf3
300 ARM_FUNC_START floatunsisf
301 ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
302         CFI_START_FUNCTION
303                 
304         mov     r3, #0
305         b       1f
307 ARM_FUNC_START floatsisf
308 ARM_FUNC_ALIAS aeabi_i2f floatsisf
309         
310         ands    r3, r0, #0x80000000
311         do_it   mi
312         rsbmi   r0, r0, #0
314 1:      movs    ip, r0
315         do_it   eq
316         RETc(eq)
318         @ Add initial exponent to sign
319         orr     r3, r3, #((127 + 23) << 23)
321         .ifnc   ah, r0
322         mov     ah, r0
323         .endif
324         mov     al, #0
325         b       2f
327         CFI_END_FUNCTION
328         FUNC_END aeabi_i2f
329         FUNC_END floatsisf
330         FUNC_END aeabi_ui2f
331         FUNC_END floatunsisf
333 ARM_FUNC_START floatundisf
334 ARM_FUNC_ALIAS aeabi_ul2f floatundisf
335         CFI_START_FUNCTION
337         orrs    r2, r0, r1
338         do_it   eq
339         RETc(eq)
341         mov     r3, #0
342         b       1f
344 ARM_FUNC_START floatdisf
345 ARM_FUNC_ALIAS aeabi_l2f floatdisf
347         orrs    r2, r0, r1
348         do_it   eq
349         RETc(eq)
351         ands    r3, ah, #0x80000000     @ sign bit in r3
352         bpl     1f
353 #if defined(__thumb2__)
354         negs    al, al
355         sbc     ah, ah, ah, lsl #1
356 #else
357         rsbs    al, al, #0
358         rsc     ah, ah, #0
359 #endif
361         movs    ip, ah
362         do_it   eq, tt
363         moveq   ip, al
364         moveq   ah, al
365         moveq   al, #0
367         @ Add initial exponent to sign
368         orr     r3, r3, #((127 + 23 + 32) << 23)
369         do_it   eq
370         subeq   r3, r3, #(32 << 23)
371 2:      sub     r3, r3, #(1 << 23)
373 #if __ARM_ARCH__ < 5
375         mov     r2, #23
376         cmp     ip, #(1 << 16)
377         do_it   hs, t
378         movhs   ip, ip, lsr #16
379         subhs   r2, r2, #16
380         cmp     ip, #(1 << 8)
381         do_it   hs, t
382         movhs   ip, ip, lsr #8
383         subhs   r2, r2, #8
384         cmp     ip, #(1 << 4)
385         do_it   hs, t
386         movhs   ip, ip, lsr #4
387         subhs   r2, r2, #4
388         cmp     ip, #(1 << 2)
389         do_it   hs, e
390         subhs   r2, r2, #2
391         sublo   r2, r2, ip, lsr #1
392         subs    r2, r2, ip, lsr #3
394 #else
396         clz     r2, ip
397         subs    r2, r2, #8
399 #endif
401         sub     r3, r3, r2, lsl #23
402         blt     3f
404         shiftop add r3 r3 ah lsl r2 ip
405         shift1  lsl, ip, al, r2
406         rsb     r2, r2, #32
407         cmp     ip, #0x80000000
408         shiftop adc r0 r3 al lsr r2 r2
409         do_it   eq
410         biceq   r0, r0, #1
411         RET
413 3:      add     r2, r2, #32
414         shift1  lsl, ip, ah, r2
415         rsb     r2, r2, #32
416         orrs    al, al, ip, lsl #1
417         shiftop adc r0 r3 ah lsr r2 r2
418         do_it   eq
419         biceq   r0, r0, ip, lsr #31
420         RET
422         CFI_END_FUNCTION
423         FUNC_END floatdisf
424         FUNC_END aeabi_l2f
425         FUNC_END floatundisf
426         FUNC_END aeabi_ul2f
428 #endif /* L_addsubsf3 */
430 #ifdef L_arm_muldivsf3
432 ARM_FUNC_START mulsf3
433 ARM_FUNC_ALIAS aeabi_fmul mulsf3
434         CFI_START_FUNCTION
436         @ Mask out exponents, trap any zero/denormal/INF/NAN.
437         mov     ip, #0xff
438         ands    r2, ip, r0, lsr #23
439         do_it   ne, tt
440         COND(and,s,ne)  r3, ip, r1, lsr #23
441         teqne   r2, ip
442         teqne   r3, ip
443         beq     LSYM(Lml_s)
444 LSYM(Lml_x):
446         @ Add exponents together
447         add     r2, r2, r3
449         @ Determine final sign.
450         eor     ip, r0, r1
452         @ Convert mantissa to unsigned integer.
453         @ If power of two, branch to a separate path.
454         @ Make up for final alignment.
455         movs    r0, r0, lsl #9
456         do_it   ne
457         COND(mov,s,ne)  r1, r1, lsl #9
458         beq     LSYM(Lml_1)
459         mov     r3, #0x08000000
460         orr     r0, r3, r0, lsr #5
461         orr     r1, r3, r1, lsr #5
463 #if __ARM_ARCH__ < 4
465         @ Put sign bit in r3, which will be restored into r0 later.
466         and     r3, ip, #0x80000000
468         @ Well, no way to make it shorter without the umull instruction.
469         do_push {r3, r4, r5}       @ sp -= 12
470         .cfi_remember_state        @ Save the current CFI state
471         .cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
472         .cfi_rel_offset r3, 0      @ Registers are saved from sp to sp + 8
473         .cfi_rel_offset r4, 4
474         .cfi_rel_offset r5, 8
476         mov     r4, r0, lsr #16
477         mov     r5, r1, lsr #16
478         bic     r0, r0, r4, lsl #16
479         bic     r1, r1, r5, lsl #16
480         mul     ip, r4, r5
481         mul     r3, r0, r1
482         mul     r0, r5, r0
483         mla     r0, r4, r1, r0
484         adds    r3, r3, r0, lsl #16
485         adc     r1, ip, r0, lsr #16
486         do_pop  {r0, r4, r5}       @ sp += 12
487         .cfi_restore_state         @ Restore the previous CFI state
489 #else
491         @ The actual multiplication.
492         umull   r3, r1, r0, r1
494         @ Put final sign in r0.
495         and     r0, ip, #0x80000000
497 #endif
499         @ Adjust result upon the MSB position.
500         cmp     r1, #(1 << 23)
501         do_it   cc, tt
502         movcc   r1, r1, lsl #1
503         orrcc   r1, r1, r3, lsr #31
504         movcc   r3, r3, lsl #1
506         @ Add sign to result.
507         orr     r0, r0, r1
509         @ Apply exponent bias, check for under/overflow.
510         sbc     r2, r2, #127
511         cmp     r2, #(254 - 1)
512         bhi     LSYM(Lml_u)
514         @ Round the result, merge final exponent.
515         cmp     r3, #0x80000000
516         adc     r0, r0, r2, lsl #23
517         do_it   eq
518         biceq   r0, r0, #1
519         RET
521         @ Multiplication by 0x1p*: let''s shortcut a lot of code.
522 LSYM(Lml_1):
523         teq     r0, #0
524         and     ip, ip, #0x80000000
525         do_it   eq
526         moveq   r1, r1, lsl #9
527         orr     r0, ip, r0, lsr #9
528         orr     r0, r0, r1, lsr #9
529         subs    r2, r2, #127
530         do_it   gt, tt
531         COND(rsb,s,gt)  r3, r2, #255
532         orrgt   r0, r0, r2, lsl #23
533         RETc(gt)
535         @ Under/overflow: fix things up for the code below.
536         orr     r0, r0, #0x00800000
537         mov     r3, #0
538         subs    r2, r2, #1
540 LSYM(Lml_u):
541         @ Overflow?
542         bgt     LSYM(Lml_o)
544         @ Check if denormalized result is possible, otherwise return signed 0.
545         cmn     r2, #(24 + 1)
546         do_it   le, t
547         bicle   r0, r0, #0x7fffffff
548         RETc(le)
550         @ Shift value right, round, etc.
551         rsb     r2, r2, #0
552         movs    r1, r0, lsl #1
553         shift1  lsr, r1, r1, r2
554         rsb     r2, r2, #32
555         shift1  lsl, ip, r0, r2
556         movs    r0, r1, rrx
557         adc     r0, r0, #0
558         orrs    r3, r3, ip, lsl #1
559         do_it   eq
560         biceq   r0, r0, ip, lsr #31
561         RET
563         @ One or both arguments are denormalized.
564         @ Scale them leftwards and preserve sign bit.
565 LSYM(Lml_d):
566         teq     r2, #0
567         and     ip, r0, #0x80000000
568 1:      do_it   eq, tt
569         moveq   r0, r0, lsl #1
570         tsteq   r0, #0x00800000
571         subeq   r2, r2, #1
572         beq     1b
573         orr     r0, r0, ip
574         teq     r3, #0
575         and     ip, r1, #0x80000000
576 2:      do_it   eq, tt
577         moveq   r1, r1, lsl #1
578         tsteq   r1, #0x00800000
579         subeq   r3, r3, #1
580         beq     2b
581         orr     r1, r1, ip
582         b       LSYM(Lml_x)
584 LSYM(Lml_s):
585         @ Isolate the INF and NAN cases away
586         and     r3, ip, r1, lsr #23
587         teq     r2, ip
588         do_it   ne
589         teqne   r3, ip
590         beq     1f
592         @ Here, one or more arguments are either denormalized or zero.
593         bics    ip, r0, #0x80000000
594         do_it   ne
595         COND(bic,s,ne)  ip, r1, #0x80000000
596         bne     LSYM(Lml_d)
598         @ Result is 0, but determine sign anyway.
599 LSYM(Lml_z):
600         eor     r0, r0, r1
601         bic     r0, r0, #0x7fffffff
602         RET
604 1:      @ One or both args are INF or NAN.
605         teq     r0, #0x0
606         do_it   ne, ett
607         teqne   r0, #0x80000000
608         moveq   r0, r1
609         teqne   r1, #0x0
610         teqne   r1, #0x80000000
611         beq     LSYM(Lml_n)             @ 0 * INF or INF * 0 -> NAN
612         teq     r2, ip
613         bne     1f
614         movs    r2, r0, lsl #9
615         bne     LSYM(Lml_n)             @ NAN * <anything> -> NAN
616 1:      teq     r3, ip
617         bne     LSYM(Lml_i)
618         movs    r3, r1, lsl #9
619         do_it   ne
620         movne   r0, r1
621         bne     LSYM(Lml_n)             @ <anything> * NAN -> NAN
623         @ Result is INF, but we need to determine its sign.
624 LSYM(Lml_i):
625         eor     r0, r0, r1
627         @ Overflow: return INF (sign already in r0).
628 LSYM(Lml_o):
629         and     r0, r0, #0x80000000
630         orr     r0, r0, #0x7f000000
631         orr     r0, r0, #0x00800000
632         RET
634         @ Return a quiet NAN.
635 LSYM(Lml_n):
636         orr     r0, r0, #0x7f000000
637         orr     r0, r0, #0x00c00000
638         RET
640         CFI_END_FUNCTION
641         FUNC_END aeabi_fmul
642         FUNC_END mulsf3
644 ARM_FUNC_START divsf3
645 ARM_FUNC_ALIAS aeabi_fdiv divsf3
646         CFI_START_FUNCTION
648         @ Mask out exponents, trap any zero/denormal/INF/NAN.
649         mov     ip, #0xff
650         ands    r2, ip, r0, lsr #23
651         do_it   ne, tt
652         COND(and,s,ne)  r3, ip, r1, lsr #23
653         teqne   r2, ip
654         teqne   r3, ip
655         beq     LSYM(Ldv_s)
656 LSYM(Ldv_x):
658         @ Subtract divisor exponent from dividend''s
659         sub     r2, r2, r3
661         @ Preserve final sign into ip.
662         eor     ip, r0, r1
664         @ Convert mantissa to unsigned integer.
665         @ Dividend -> r3, divisor -> r1.
666         movs    r1, r1, lsl #9
667         mov     r0, r0, lsl #9
668         beq     LSYM(Ldv_1)
669         mov     r3, #0x10000000
670         orr     r1, r3, r1, lsr #4
671         orr     r3, r3, r0, lsr #4
673         @ Initialize r0 (result) with final sign bit.
674         and     r0, ip, #0x80000000
676         @ Ensure result will land to known bit position.
677         @ Apply exponent bias accordingly.
678         cmp     r3, r1
679         do_it   cc
680         movcc   r3, r3, lsl #1
681         adc     r2, r2, #(127 - 2)
683         @ The actual division loop.
684         mov     ip, #0x00800000
685 1:      cmp     r3, r1
686         do_it   cs, t
687         subcs   r3, r3, r1
688         orrcs   r0, r0, ip
689         cmp     r3, r1, lsr #1
690         do_it   cs, t
691         subcs   r3, r3, r1, lsr #1
692         orrcs   r0, r0, ip, lsr #1
693         cmp     r3, r1, lsr #2
694         do_it   cs, t
695         subcs   r3, r3, r1, lsr #2
696         orrcs   r0, r0, ip, lsr #2
697         cmp     r3, r1, lsr #3
698         do_it   cs, t
699         subcs   r3, r3, r1, lsr #3
700         orrcs   r0, r0, ip, lsr #3
701         movs    r3, r3, lsl #4
702         do_it   ne
703         COND(mov,s,ne)  ip, ip, lsr #4
704         bne     1b
706         @ Check exponent for under/overflow.
707         cmp     r2, #(254 - 1)
708         bhi     LSYM(Lml_u)
710         @ Round the result, merge final exponent.
711         cmp     r3, r1
712         adc     r0, r0, r2, lsl #23
713         do_it   eq
714         biceq   r0, r0, #1
715         RET
717         @ Division by 0x1p*: let''s shortcut a lot of code.
718 LSYM(Ldv_1):
719         and     ip, ip, #0x80000000
720         orr     r0, ip, r0, lsr #9
721         adds    r2, r2, #127
722         do_it   gt, tt
723         COND(rsb,s,gt)  r3, r2, #255
724         orrgt   r0, r0, r2, lsl #23
725         RETc(gt)
727         orr     r0, r0, #0x00800000
728         mov     r3, #0
729         subs    r2, r2, #1
730         b       LSYM(Lml_u)
732         @ One or both arguments are denormalized.
733         @ Scale them leftwards and preserve sign bit.
734 LSYM(Ldv_d):
735         teq     r2, #0
736         and     ip, r0, #0x80000000
737 1:      do_it   eq, tt
738         moveq   r0, r0, lsl #1
739         tsteq   r0, #0x00800000
740         subeq   r2, r2, #1
741         beq     1b
742         orr     r0, r0, ip
743         teq     r3, #0
744         and     ip, r1, #0x80000000
745 2:      do_it   eq, tt
746         moveq   r1, r1, lsl #1
747         tsteq   r1, #0x00800000
748         subeq   r3, r3, #1
749         beq     2b
750         orr     r1, r1, ip
751         b       LSYM(Ldv_x)
753         @ One or both arguments are either INF, NAN, zero or denormalized.
754 LSYM(Ldv_s):
755         and     r3, ip, r1, lsr #23
756         teq     r2, ip
757         bne     1f
758         movs    r2, r0, lsl #9
759         bne     LSYM(Lml_n)             @ NAN / <anything> -> NAN
760         teq     r3, ip
761         bne     LSYM(Lml_i)             @ INF / <anything> -> INF
762         mov     r0, r1
763         b       LSYM(Lml_n)             @ INF / (INF or NAN) -> NAN
764 1:      teq     r3, ip
765         bne     2f
766         movs    r3, r1, lsl #9
767         beq     LSYM(Lml_z)             @ <anything> / INF -> 0
768         mov     r0, r1
769         b       LSYM(Lml_n)             @ <anything> / NAN -> NAN
770 2:      @ If both are nonzero, we need to normalize and resume above.
771         bics    ip, r0, #0x80000000
772         do_it   ne
773         COND(bic,s,ne)  ip, r1, #0x80000000
774         bne     LSYM(Ldv_d)
775         @ One or both arguments are zero.
776         bics    r2, r0, #0x80000000
777         bne     LSYM(Lml_i)             @ <non_zero> / 0 -> INF
778         bics    r3, r1, #0x80000000
779         bne     LSYM(Lml_z)             @ 0 / <non_zero> -> 0
780         b       LSYM(Lml_n)             @ 0 / 0 -> NAN
782         CFI_END_FUNCTION
783         FUNC_END aeabi_fdiv
784         FUNC_END divsf3
786 #endif /* L_muldivsf3 */
788 #ifdef L_arm_cmpsf2
790         @ The return value in r0 is
791         @
792         @   0  if the operands are equal
793         @   1  if the first operand is greater than the second, or
794         @      the operands are unordered and the operation is
795         @      CMP, LT, LE, NE, or EQ.
796         @   -1 if the first operand is less than the second, or
797         @      the operands are unordered and the operation is GT
798         @      or GE.
799         @
800         @ The Z flag will be set iff the operands are equal.
801         @
802         @ The following registers are clobbered by this function:
803         @   ip, r0, r1, r2, r3
805 ARM_FUNC_START gtsf2
806 ARM_FUNC_ALIAS gesf2 gtsf2
807         CFI_START_FUNCTION
808         mov     ip, #-1
809         b       1f
811 ARM_FUNC_START ltsf2
812 ARM_FUNC_ALIAS lesf2 ltsf2
813         mov     ip, #1
814         b       1f
816 ARM_FUNC_START cmpsf2
817 ARM_FUNC_ALIAS nesf2 cmpsf2
818 ARM_FUNC_ALIAS eqsf2 cmpsf2
819         mov     ip, #1                  @ how should we specify unordered here?
821 1:      str     ip, [sp, #-4]!
822         .cfi_adjust_cfa_offset 4  @ CFA is now sp + previousOffset + 4.
823         @ We're not adding CFI for ip as it's pushed into the stack only because
824         @ it may be popped off later as a return value (i.e. we're not preserving
825         @ it anyways).
827         @ Trap any INF/NAN first.
828         mov     r2, r0, lsl #1
829         mov     r3, r1, lsl #1
830         mvns    ip, r2, asr #24
831         do_it   ne
832         COND(mvn,s,ne)  ip, r3, asr #24
833         beq     3f
834         .cfi_remember_state
835         @ Save the current CFI state. This is done because the branch is conditional,
836         @ and if we don't take it we'll issue a .cfi_adjust_cfa_offset and return.
837         @ If we do take it, however, the .cfi_adjust_cfa_offset from the non-branch
838         @ code will affect the branch code as well. To avoid this we'll restore
839         @ the current state before executing the branch code.
841         @ Compare values.
842         @ Note that 0.0 is equal to -0.0.
843 2:      add     sp, sp, #4
844         .cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
846         orrs    ip, r2, r3, lsr #1      @ test if both are 0, clear C flag
847         do_it   ne
848         teqne   r0, r1                  @ if not 0 compare sign
849         do_it   pl
850         COND(sub,s,pl)  r0, r2, r3              @ if same sign compare values, set r0
852         @ Result:
853         do_it   hi
854         movhi   r0, r1, asr #31
855         do_it   lo
856         mvnlo   r0, r1, asr #31
857         do_it   ne
858         orrne   r0, r0, #1
859         RET
861 3:      @ Look for a NAN.
863         @ Restore the previous CFI state (i.e. keep the CFI state as it was
864         @ before the branch).
865         .cfi_restore_state
867         mvns    ip, r2, asr #24
868         bne     4f
869         movs    ip, r0, lsl #9
870         bne     5f                      @ r0 is NAN
871 4:      mvns    ip, r3, asr #24
872         bne     2b
873         movs    ip, r1, lsl #9
874         beq     2b                      @ r1 is not NAN
876 5:      ldr     r0, [sp], #4            @ return unordered code.
877         .cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
878         RET
880         CFI_END_FUNCTION
881         FUNC_END gesf2
882         FUNC_END gtsf2
883         FUNC_END lesf2
884         FUNC_END ltsf2
885         FUNC_END nesf2
886         FUNC_END eqsf2
887         FUNC_END cmpsf2
889 ARM_FUNC_START aeabi_cfrcmple
890         CFI_START_FUNCTION
892         mov     ip, r0
893         mov     r0, r1
894         mov     r1, ip
895         b       6f
897 ARM_FUNC_START aeabi_cfcmpeq
898 ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
900         @ The status-returning routines are required to preserve all
901         @ registers except ip, lr, and cpsr.
902 6:      do_push {r0, r1, r2, r3, lr}
903         .cfi_adjust_cfa_offset 20  @ CFA is at sp + previousOffset + 20
904         .cfi_rel_offset r0, 0      @ Registers are saved from sp to sp + 16
905         .cfi_rel_offset r1, 4
906         .cfi_rel_offset r2, 8
907         .cfi_rel_offset r3, 12
908         .cfi_rel_offset lr, 16
910         ARM_CALL cmpsf2
911         @ Set the Z flag correctly, and the C flag unconditionally.
912         cmp     r0, #0
913         @ Clear the C flag if the return value was -1, indicating
914         @ that the first operand was smaller than the second.
915         do_it   mi
916         cmnmi   r0, #0
917         RETLDM  "r0, r1, r2, r3"
919         CFI_END_FUNCTION
920         FUNC_END aeabi_cfcmple
921         FUNC_END aeabi_cfcmpeq
922         FUNC_END aeabi_cfrcmple
924 ARM_FUNC_START  aeabi_fcmpeq
925         CFI_START_FUNCTION
927         str     lr, [sp, #-8]!    @ sp -= 8
928         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
929         .cfi_rel_offset lr, 0     @ lr is at sp
931         ARM_CALL aeabi_cfcmple
932         do_it   eq, e
933         moveq   r0, #1  @ Equal to.
934         movne   r0, #0  @ Less than, greater than, or unordered.
935         RETLDM
937         CFI_END_FUNCTION
938         FUNC_END aeabi_fcmpeq
940 ARM_FUNC_START  aeabi_fcmplt
941         CFI_START_FUNCTION
943         str     lr, [sp, #-8]!    @ sp -= 8
944         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
945         .cfi_rel_offset lr, 0     @ lr is at sp
947         ARM_CALL aeabi_cfcmple
948         do_it   cc, e
949         movcc   r0, #1  @ Less than.
950         movcs   r0, #0  @ Equal to, greater than, or unordered.
951         RETLDM
953         CFI_END_FUNCTION
954         FUNC_END aeabi_fcmplt
956 ARM_FUNC_START  aeabi_fcmple
957         CFI_START_FUNCTION
959         str     lr, [sp, #-8]!    @ sp -= 8
960         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
961         .cfi_rel_offset lr, 0     @ lr is at sp
963         ARM_CALL aeabi_cfcmple
964         do_it   ls, e
965         movls   r0, #1  @ Less than or equal to.
966         movhi   r0, #0  @ Greater than or unordered.
967         RETLDM
969         CFI_END_FUNCTION
970         FUNC_END aeabi_fcmple
972 ARM_FUNC_START  aeabi_fcmpge
973         CFI_START_FUNCTION
975         str     lr, [sp, #-8]!    @ sp -= 8
976         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
977         .cfi_rel_offset lr, 0     @ lr is at sp
979         ARM_CALL aeabi_cfrcmple
980         do_it   ls, e
981         movls   r0, #1  @ Operand 2 is less than or equal to operand 1.
982         movhi   r0, #0  @ Operand 2 greater than operand 1, or unordered.
983         RETLDM
985         CFI_END_FUNCTION
986         FUNC_END aeabi_fcmpge
988 ARM_FUNC_START  aeabi_fcmpgt
989         CFI_START_FUNCTION
991         str     lr, [sp, #-8]!    @ sp -= 8
992         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
993         .cfi_rel_offset lr, 0     @ lr is at sp
995         ARM_CALL aeabi_cfrcmple
996         do_it   cc, e
997         movcc   r0, #1  @ Operand 2 is less than operand 1.
998         movcs   r0, #0  @ Operand 2 is greater than or equal to operand 1,
999                         @ or they are unordered.
1000         RETLDM
1002         CFI_END_FUNCTION
1003         FUNC_END aeabi_fcmpgt
1005 #endif /* L_cmpsf2 */
1007 #ifdef L_arm_unordsf2
1009 ARM_FUNC_START unordsf2
1010 ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
1011         CFI_START_FUNCTION
1013         mov     r2, r0, lsl #1
1014         mov     r3, r1, lsl #1
1015         mvns    ip, r2, asr #24
1016         bne     1f
1017         movs    ip, r0, lsl #9
1018         bne     3f                      @ r0 is NAN
1019 1:      mvns    ip, r3, asr #24
1020         bne     2f
1021         movs    ip, r1, lsl #9
1022         bne     3f                      @ r1 is NAN
1023 2:      mov     r0, #0                  @ arguments are ordered.
1024         RET
1025 3:      mov     r0, #1                  @ arguments are unordered.
1026         RET
1028         CFI_END_FUNCTION
1029         FUNC_END aeabi_fcmpun
1030         FUNC_END unordsf2
1032 #endif /* L_unordsf2 */
1034 #ifdef L_arm_fixsfsi
1036 ARM_FUNC_START fixsfsi
1037 ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
1038         CFI_START_FUNCTION
1040         @ check exponent range.
1041         mov     r2, r0, lsl #1
1042         cmp     r2, #(127 << 24)
1043         bcc     1f                      @ value is too small
1044         mov     r3, #(127 + 31)
1045         subs    r2, r3, r2, lsr #24
1046         bls     2f                      @ value is too large
1048         @ scale value
1049         mov     r3, r0, lsl #8
1050         orr     r3, r3, #0x80000000
1051         tst     r0, #0x80000000         @ the sign bit
1052         shift1  lsr, r0, r3, r2
1053         do_it   ne
1054         rsbne   r0, r0, #0
1055         RET
1057 1:      mov     r0, #0
1058         RET
1060 2:      cmp     r2, #(127 + 31 - 0xff)
1061         bne     3f
1062         movs    r2, r0, lsl #9
1063         bne     4f                      @ r0 is NAN.
1064 3:      ands    r0, r0, #0x80000000     @ the sign bit
1065         do_it   eq
1066         moveq   r0, #0x7fffffff         @ the maximum signed positive si
1067         RET
1069 4:      mov     r0, #0                  @ What should we convert NAN to?
1070         RET
1072         CFI_END_FUNCTION
1073         FUNC_END aeabi_f2iz
1074         FUNC_END fixsfsi
1076 #endif /* L_fixsfsi */
1078 #ifdef L_arm_fixunssfsi
1080 ARM_FUNC_START fixunssfsi
1081 ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
1082         CFI_START_FUNCTION
1084         @ check exponent range.
1085         movs    r2, r0, lsl #1
1086         bcs     1f                      @ value is negative
1087         cmp     r2, #(127 << 24)
1088         bcc     1f                      @ value is too small
1089         mov     r3, #(127 + 31)
1090         subs    r2, r3, r2, lsr #24
1091         bmi     2f                      @ value is too large
1093         @ scale the value
1094         mov     r3, r0, lsl #8
1095         orr     r3, r3, #0x80000000
1096         shift1  lsr, r0, r3, r2
1097         RET
1099 1:      mov     r0, #0
1100         RET
1102 2:      cmp     r2, #(127 + 31 - 0xff)
1103         bne     3f
1104         movs    r2, r0, lsl #9
1105         bne     4f                      @ r0 is NAN.
1106 3:      mov     r0, #0xffffffff         @ maximum unsigned si
1107         RET
1109 4:      mov     r0, #0                  @ What should we convert NAN to?
1110         RET
1112         CFI_END_FUNCTION
1113         FUNC_END aeabi_f2uiz
1114         FUNC_END fixunssfsi
1116 #endif /* L_fixunssfsi */