Update copyright in libgcc.
[official-gcc.git] / libgcc / config / arm / ieee754-sf.S
blobb5432523a8eba048ad102e14f94d1775a2910b12
1 /* ieee754-sf.S single-precision floating point support for ARM
3    Copyright (C) 2003-2013 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  */
36 #ifdef L_arm_negsf2
37         
38 ARM_FUNC_START negsf2
39 ARM_FUNC_ALIAS aeabi_fneg negsf2
41         eor     r0, r0, #0x80000000     @ flip sign bit
42         RET
44         FUNC_END aeabi_fneg
45         FUNC_END negsf2
47 #endif
49 #ifdef L_arm_addsubsf3
51 ARM_FUNC_START aeabi_frsub
53         eor     r0, r0, #0x80000000     @ flip sign bit of first arg
54         b       1f
56 ARM_FUNC_START subsf3
57 ARM_FUNC_ALIAS aeabi_fsub subsf3
59         eor     r1, r1, #0x80000000     @ flip sign bit of second arg
60 #if defined(__INTERWORKING_STUBS__)
61         b       1f                      @ Skip Thumb-code prologue
62 #endif
64 ARM_FUNC_START addsf3
65 ARM_FUNC_ALIAS aeabi_fadd addsf3
67 1:      @ Look for zeroes, equal values, INF, or NAN.
68         movs    r2, r0, lsl #1
69         do_it   ne, ttt
70         COND(mov,s,ne)  r3, r1, lsl #1
71         teqne   r2, r3
72         COND(mvn,s,ne)  ip, r2, asr #24
73         COND(mvn,s,ne)  ip, r3, asr #24
74         beq     LSYM(Lad_s)
76         @ Compute exponent difference.  Make largest exponent in r2,
77         @ corresponding arg in r0, and positive exponent difference in r3.
78         mov     r2, r2, lsr #24
79         rsbs    r3, r2, r3, lsr #24
80         do_it   gt, ttt
81         addgt   r2, r2, r3
82         eorgt   r1, r0, r1
83         eorgt   r0, r1, r0
84         eorgt   r1, r0, r1
85         do_it   lt
86         rsblt   r3, r3, #0
88         @ If exponent difference is too large, return largest argument
89         @ already in r0.  We need up to 25 bit to handle proper rounding
90         @ of 0x1p25 - 1.1.
91         cmp     r3, #25
92         do_it   hi
93         RETc(hi)
95         @ Convert mantissa to signed integer.
96         tst     r0, #0x80000000
97         orr     r0, r0, #0x00800000
98         bic     r0, r0, #0xff000000
99         do_it   ne
100         rsbne   r0, r0, #0
101         tst     r1, #0x80000000
102         orr     r1, r1, #0x00800000
103         bic     r1, r1, #0xff000000
104         do_it   ne
105         rsbne   r1, r1, #0
107         @ If exponent == difference, one or both args were denormalized.
108         @ Since this is not common case, rescale them off line.
109         teq     r2, r3
110         beq     LSYM(Lad_d)
111 LSYM(Lad_x):
113         @ Compensate for the exponent overlapping the mantissa MSB added later
114         sub     r2, r2, #1
116         @ Shift and add second arg to first arg in r0.
117         @ Keep leftover bits into r1.
118         shiftop adds r0 r0 r1 asr r3 ip
119         rsb     r3, r3, #32
120         shift1  lsl, r1, r1, r3
122         @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
123         and     r3, r0, #0x80000000
124         bpl     LSYM(Lad_p)
125 #if defined(__thumb2__)
126         negs    r1, r1
127         sbc     r0, r0, r0, lsl #1
128 #else
129         rsbs    r1, r1, #0
130         rsc     r0, r0, #0
131 #endif
133         @ Determine how to normalize the result.
134 LSYM(Lad_p):
135         cmp     r0, #0x00800000
136         bcc     LSYM(Lad_a)
137         cmp     r0, #0x01000000
138         bcc     LSYM(Lad_e)
140         @ Result needs to be shifted right.
141         movs    r0, r0, lsr #1
142         mov     r1, r1, rrx
143         add     r2, r2, #1
145         @ Make sure we did not bust our exponent.
146         cmp     r2, #254
147         bhs     LSYM(Lad_o)
149         @ Our result is now properly aligned into r0, remaining bits in r1.
150         @ Pack final result together.
151         @ Round with MSB of r1. If halfway between two numbers, round towards
152         @ LSB of r0 = 0. 
153 LSYM(Lad_e):
154         cmp     r1, #0x80000000
155         adc     r0, r0, r2, lsl #23
156         do_it   eq
157         biceq   r0, r0, #1
158         orr     r0, r0, r3
159         RET
161         @ Result must be shifted left and exponent adjusted.
162 LSYM(Lad_a):
163         movs    r1, r1, lsl #1
164         adc     r0, r0, r0
165         tst     r0, #0x00800000
166         sub     r2, r2, #1
167         bne     LSYM(Lad_e)
168         
169         @ No rounding necessary since r1 will always be 0 at this point.
170 LSYM(Lad_l):
172 #if __ARM_ARCH__ < 5
174         movs    ip, r0, lsr #12
175         moveq   r0, r0, lsl #12
176         subeq   r2, r2, #12
177         tst     r0, #0x00ff0000
178         moveq   r0, r0, lsl #8
179         subeq   r2, r2, #8
180         tst     r0, #0x00f00000
181         moveq   r0, r0, lsl #4
182         subeq   r2, r2, #4
183         tst     r0, #0x00c00000
184         moveq   r0, r0, lsl #2
185         subeq   r2, r2, #2
186         cmp     r0, #0x00800000
187         movcc   r0, r0, lsl #1
188         sbcs    r2, r2, #0
190 #else
192         clz     ip, r0
193         sub     ip, ip, #8
194         subs    r2, r2, ip
195         shift1  lsl, r0, r0, ip
197 #endif
199         @ Final result with sign
200         @ If exponent negative, denormalize result.
201         do_it   ge, et
202         addge   r0, r0, r2, lsl #23
203         rsblt   r2, r2, #0
204         orrge   r0, r0, r3
205 #if defined(__thumb2__)
206         do_it   lt, t
207         lsrlt   r0, r0, r2
208         orrlt   r0, r3, r0
209 #else
210         orrlt   r0, r3, r0, lsr r2
211 #endif
212         RET
214         @ Fixup and adjust bit position for denormalized arguments.
215         @ Note that r2 must not remain equal to 0.
216 LSYM(Lad_d):
217         teq     r2, #0
218         eor     r1, r1, #0x00800000
219         do_it   eq, te
220         eoreq   r0, r0, #0x00800000
221         addeq   r2, r2, #1
222         subne   r3, r3, #1
223         b       LSYM(Lad_x)
225 LSYM(Lad_s):
226         mov     r3, r1, lsl #1
228         mvns    ip, r2, asr #24
229         do_it   ne
230         COND(mvn,s,ne)  ip, r3, asr #24
231         beq     LSYM(Lad_i)
233         teq     r2, r3
234         beq     1f
236         @ Result is x + 0.0 = x or 0.0 + y = y.
237         teq     r2, #0
238         do_it   eq
239         moveq   r0, r1
240         RET
242 1:      teq     r0, r1
244         @ Result is x - x = 0.
245         do_it   ne, t
246         movne   r0, #0
247         RETc(ne)
249         @ Result is x + x = 2x.
250         tst     r2, #0xff000000
251         bne     2f
252         movs    r0, r0, lsl #1
253         do_it   cs
254         orrcs   r0, r0, #0x80000000
255         RET
256 2:      adds    r2, r2, #(2 << 24)
257         do_it   cc, t
258         addcc   r0, r0, #(1 << 23)
259         RETc(cc)
260         and     r3, r0, #0x80000000
262         @ Overflow: return INF.
263 LSYM(Lad_o):
264         orr     r0, r3, #0x7f000000
265         orr     r0, r0, #0x00800000
266         RET
268         @ At least one of r0/r1 is INF/NAN.
269         @   if r0 != INF/NAN: return r1 (which is INF/NAN)
270         @   if r1 != INF/NAN: return r0 (which is INF/NAN)
271         @   if r0 or r1 is NAN: return NAN
272         @   if opposite sign: return NAN
273         @   otherwise return r0 (which is INF or -INF)
274 LSYM(Lad_i):
275         mvns    r2, r2, asr #24
276         do_it   ne, et
277         movne   r0, r1
278         COND(mvn,s,eq)  r3, r3, asr #24
279         movne   r1, r0
280         movs    r2, r0, lsl #9
281         do_it   eq, te
282         COND(mov,s,eq)  r3, r1, lsl #9
283         teqeq   r0, r1
284         orrne   r0, r0, #0x00400000     @ quiet NAN
285         RET
287         FUNC_END aeabi_frsub
288         FUNC_END aeabi_fadd
289         FUNC_END addsf3
290         FUNC_END aeabi_fsub
291         FUNC_END subsf3
293 ARM_FUNC_START floatunsisf
294 ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
295                 
296         mov     r3, #0
297         b       1f
299 ARM_FUNC_START floatsisf
300 ARM_FUNC_ALIAS aeabi_i2f floatsisf
301         
302         ands    r3, r0, #0x80000000
303         do_it   mi
304         rsbmi   r0, r0, #0
306 1:      movs    ip, r0
307         do_it   eq
308         RETc(eq)
310         @ Add initial exponent to sign
311         orr     r3, r3, #((127 + 23) << 23)
313         .ifnc   ah, r0
314         mov     ah, r0
315         .endif
316         mov     al, #0
317         b       2f
319         FUNC_END aeabi_i2f
320         FUNC_END floatsisf
321         FUNC_END aeabi_ui2f
322         FUNC_END floatunsisf
324 ARM_FUNC_START floatundisf
325 ARM_FUNC_ALIAS aeabi_ul2f floatundisf
327         orrs    r2, r0, r1
328         do_it   eq
329         RETc(eq)
331         mov     r3, #0
332         b       1f
334 ARM_FUNC_START floatdisf
335 ARM_FUNC_ALIAS aeabi_l2f floatdisf
337         orrs    r2, r0, r1
338         do_it   eq
339         RETc(eq)
341         ands    r3, ah, #0x80000000     @ sign bit in r3
342         bpl     1f
343 #if defined(__thumb2__)
344         negs    al, al
345         sbc     ah, ah, ah, lsl #1
346 #else
347         rsbs    al, al, #0
348         rsc     ah, ah, #0
349 #endif
351         movs    ip, ah
352         do_it   eq, tt
353         moveq   ip, al
354         moveq   ah, al
355         moveq   al, #0
357         @ Add initial exponent to sign
358         orr     r3, r3, #((127 + 23 + 32) << 23)
359         do_it   eq
360         subeq   r3, r3, #(32 << 23)
361 2:      sub     r3, r3, #(1 << 23)
363 #if __ARM_ARCH__ < 5
365         mov     r2, #23
366         cmp     ip, #(1 << 16)
367         do_it   hs, t
368         movhs   ip, ip, lsr #16
369         subhs   r2, r2, #16
370         cmp     ip, #(1 << 8)
371         do_it   hs, t
372         movhs   ip, ip, lsr #8
373         subhs   r2, r2, #8
374         cmp     ip, #(1 << 4)
375         do_it   hs, t
376         movhs   ip, ip, lsr #4
377         subhs   r2, r2, #4
378         cmp     ip, #(1 << 2)
379         do_it   hs, e
380         subhs   r2, r2, #2
381         sublo   r2, r2, ip, lsr #1
382         subs    r2, r2, ip, lsr #3
384 #else
386         clz     r2, ip
387         subs    r2, r2, #8
389 #endif
391         sub     r3, r3, r2, lsl #23
392         blt     3f
394         shiftop add r3 r3 ah lsl r2 ip
395         shift1  lsl, ip, al, r2
396         rsb     r2, r2, #32
397         cmp     ip, #0x80000000
398         shiftop adc r0 r3 al lsr r2 r2
399         do_it   eq
400         biceq   r0, r0, #1
401         RET
403 3:      add     r2, r2, #32
404         shift1  lsl, ip, ah, r2
405         rsb     r2, r2, #32
406         orrs    al, al, ip, lsl #1
407         shiftop adc r0 r3 ah lsr r2 r2
408         do_it   eq
409         biceq   r0, r0, ip, lsr #31
410         RET
412         FUNC_END floatdisf
413         FUNC_END aeabi_l2f
414         FUNC_END floatundisf
415         FUNC_END aeabi_ul2f
417 #endif /* L_addsubsf3 */
419 #ifdef L_arm_muldivsf3
421 ARM_FUNC_START mulsf3
422 ARM_FUNC_ALIAS aeabi_fmul mulsf3
424         @ Mask out exponents, trap any zero/denormal/INF/NAN.
425         mov     ip, #0xff
426         ands    r2, ip, r0, lsr #23
427         do_it   ne, tt
428         COND(and,s,ne)  r3, ip, r1, lsr #23
429         teqne   r2, ip
430         teqne   r3, ip
431         beq     LSYM(Lml_s)
432 LSYM(Lml_x):
434         @ Add exponents together
435         add     r2, r2, r3
437         @ Determine final sign.
438         eor     ip, r0, r1
440         @ Convert mantissa to unsigned integer.
441         @ If power of two, branch to a separate path.
442         @ Make up for final alignment.
443         movs    r0, r0, lsl #9
444         do_it   ne
445         COND(mov,s,ne)  r1, r1, lsl #9
446         beq     LSYM(Lml_1)
447         mov     r3, #0x08000000
448         orr     r0, r3, r0, lsr #5
449         orr     r1, r3, r1, lsr #5
451 #if __ARM_ARCH__ < 4
453         @ Put sign bit in r3, which will be restored into r0 later.
454         and     r3, ip, #0x80000000
456         @ Well, no way to make it shorter without the umull instruction.
457         do_push {r3, r4, r5}
458         mov     r4, r0, lsr #16
459         mov     r5, r1, lsr #16
460         bic     r0, r0, r4, lsl #16
461         bic     r1, r1, r5, lsl #16
462         mul     ip, r4, r5
463         mul     r3, r0, r1
464         mul     r0, r5, r0
465         mla     r0, r4, r1, r0
466         adds    r3, r3, r0, lsl #16
467         adc     r1, ip, r0, lsr #16
468         do_pop  {r0, r4, r5}
470 #else
472         @ The actual multiplication.
473         umull   r3, r1, r0, r1
475         @ Put final sign in r0.
476         and     r0, ip, #0x80000000
478 #endif
480         @ Adjust result upon the MSB position.
481         cmp     r1, #(1 << 23)
482         do_it   cc, tt
483         movcc   r1, r1, lsl #1
484         orrcc   r1, r1, r3, lsr #31
485         movcc   r3, r3, lsl #1
487         @ Add sign to result.
488         orr     r0, r0, r1
490         @ Apply exponent bias, check for under/overflow.
491         sbc     r2, r2, #127
492         cmp     r2, #(254 - 1)
493         bhi     LSYM(Lml_u)
495         @ Round the result, merge final exponent.
496         cmp     r3, #0x80000000
497         adc     r0, r0, r2, lsl #23
498         do_it   eq
499         biceq   r0, r0, #1
500         RET
502         @ Multiplication by 0x1p*: let''s shortcut a lot of code.
503 LSYM(Lml_1):
504         teq     r0, #0
505         and     ip, ip, #0x80000000
506         do_it   eq
507         moveq   r1, r1, lsl #9
508         orr     r0, ip, r0, lsr #9
509         orr     r0, r0, r1, lsr #9
510         subs    r2, r2, #127
511         do_it   gt, tt
512         COND(rsb,s,gt)  r3, r2, #255
513         orrgt   r0, r0, r2, lsl #23
514         RETc(gt)
516         @ Under/overflow: fix things up for the code below.
517         orr     r0, r0, #0x00800000
518         mov     r3, #0
519         subs    r2, r2, #1
521 LSYM(Lml_u):
522         @ Overflow?
523         bgt     LSYM(Lml_o)
525         @ Check if denormalized result is possible, otherwise return signed 0.
526         cmn     r2, #(24 + 1)
527         do_it   le, t
528         bicle   r0, r0, #0x7fffffff
529         RETc(le)
531         @ Shift value right, round, etc.
532         rsb     r2, r2, #0
533         movs    r1, r0, lsl #1
534         shift1  lsr, r1, r1, r2
535         rsb     r2, r2, #32
536         shift1  lsl, ip, r0, r2
537         movs    r0, r1, rrx
538         adc     r0, r0, #0
539         orrs    r3, r3, ip, lsl #1
540         do_it   eq
541         biceq   r0, r0, ip, lsr #31
542         RET
544         @ One or both arguments are denormalized.
545         @ Scale them leftwards and preserve sign bit.
546 LSYM(Lml_d):
547         teq     r2, #0
548         and     ip, r0, #0x80000000
549 1:      do_it   eq, tt
550         moveq   r0, r0, lsl #1
551         tsteq   r0, #0x00800000
552         subeq   r2, r2, #1
553         beq     1b
554         orr     r0, r0, ip
555         teq     r3, #0
556         and     ip, r1, #0x80000000
557 2:      do_it   eq, tt
558         moveq   r1, r1, lsl #1
559         tsteq   r1, #0x00800000
560         subeq   r3, r3, #1
561         beq     2b
562         orr     r1, r1, ip
563         b       LSYM(Lml_x)
565 LSYM(Lml_s):
566         @ Isolate the INF and NAN cases away
567         and     r3, ip, r1, lsr #23
568         teq     r2, ip
569         do_it   ne
570         teqne   r3, ip
571         beq     1f
573         @ Here, one or more arguments are either denormalized or zero.
574         bics    ip, r0, #0x80000000
575         do_it   ne
576         COND(bic,s,ne)  ip, r1, #0x80000000
577         bne     LSYM(Lml_d)
579         @ Result is 0, but determine sign anyway.
580 LSYM(Lml_z):
581         eor     r0, r0, r1
582         bic     r0, r0, #0x7fffffff
583         RET
585 1:      @ One or both args are INF or NAN.
586         teq     r0, #0x0
587         do_it   ne, ett
588         teqne   r0, #0x80000000
589         moveq   r0, r1
590         teqne   r1, #0x0
591         teqne   r1, #0x80000000
592         beq     LSYM(Lml_n)             @ 0 * INF or INF * 0 -> NAN
593         teq     r2, ip
594         bne     1f
595         movs    r2, r0, lsl #9
596         bne     LSYM(Lml_n)             @ NAN * <anything> -> NAN
597 1:      teq     r3, ip
598         bne     LSYM(Lml_i)
599         movs    r3, r1, lsl #9
600         do_it   ne
601         movne   r0, r1
602         bne     LSYM(Lml_n)             @ <anything> * NAN -> NAN
604         @ Result is INF, but we need to determine its sign.
605 LSYM(Lml_i):
606         eor     r0, r0, r1
608         @ Overflow: return INF (sign already in r0).
609 LSYM(Lml_o):
610         and     r0, r0, #0x80000000
611         orr     r0, r0, #0x7f000000
612         orr     r0, r0, #0x00800000
613         RET
615         @ Return a quiet NAN.
616 LSYM(Lml_n):
617         orr     r0, r0, #0x7f000000
618         orr     r0, r0, #0x00c00000
619         RET
621         FUNC_END aeabi_fmul
622         FUNC_END mulsf3
624 ARM_FUNC_START divsf3
625 ARM_FUNC_ALIAS aeabi_fdiv divsf3
627         @ Mask out exponents, trap any zero/denormal/INF/NAN.
628         mov     ip, #0xff
629         ands    r2, ip, r0, lsr #23
630         do_it   ne, tt
631         COND(and,s,ne)  r3, ip, r1, lsr #23
632         teqne   r2, ip
633         teqne   r3, ip
634         beq     LSYM(Ldv_s)
635 LSYM(Ldv_x):
637         @ Subtract divisor exponent from dividend''s
638         sub     r2, r2, r3
640         @ Preserve final sign into ip.
641         eor     ip, r0, r1
643         @ Convert mantissa to unsigned integer.
644         @ Dividend -> r3, divisor -> r1.
645         movs    r1, r1, lsl #9
646         mov     r0, r0, lsl #9
647         beq     LSYM(Ldv_1)
648         mov     r3, #0x10000000
649         orr     r1, r3, r1, lsr #4
650         orr     r3, r3, r0, lsr #4
652         @ Initialize r0 (result) with final sign bit.
653         and     r0, ip, #0x80000000
655         @ Ensure result will land to known bit position.
656         @ Apply exponent bias accordingly.
657         cmp     r3, r1
658         do_it   cc
659         movcc   r3, r3, lsl #1
660         adc     r2, r2, #(127 - 2)
662         @ The actual division loop.
663         mov     ip, #0x00800000
664 1:      cmp     r3, r1
665         do_it   cs, t
666         subcs   r3, r3, r1
667         orrcs   r0, r0, ip
668         cmp     r3, r1, lsr #1
669         do_it   cs, t
670         subcs   r3, r3, r1, lsr #1
671         orrcs   r0, r0, ip, lsr #1
672         cmp     r3, r1, lsr #2
673         do_it   cs, t
674         subcs   r3, r3, r1, lsr #2
675         orrcs   r0, r0, ip, lsr #2
676         cmp     r3, r1, lsr #3
677         do_it   cs, t
678         subcs   r3, r3, r1, lsr #3
679         orrcs   r0, r0, ip, lsr #3
680         movs    r3, r3, lsl #4
681         do_it   ne
682         COND(mov,s,ne)  ip, ip, lsr #4
683         bne     1b
685         @ Check exponent for under/overflow.
686         cmp     r2, #(254 - 1)
687         bhi     LSYM(Lml_u)
689         @ Round the result, merge final exponent.
690         cmp     r3, r1
691         adc     r0, r0, r2, lsl #23
692         do_it   eq
693         biceq   r0, r0, #1
694         RET
696         @ Division by 0x1p*: let''s shortcut a lot of code.
697 LSYM(Ldv_1):
698         and     ip, ip, #0x80000000
699         orr     r0, ip, r0, lsr #9
700         adds    r2, r2, #127
701         do_it   gt, tt
702         COND(rsb,s,gt)  r3, r2, #255
703         orrgt   r0, r0, r2, lsl #23
704         RETc(gt)
706         orr     r0, r0, #0x00800000
707         mov     r3, #0
708         subs    r2, r2, #1
709         b       LSYM(Lml_u)
711         @ One or both arguments are denormalized.
712         @ Scale them leftwards and preserve sign bit.
713 LSYM(Ldv_d):
714         teq     r2, #0
715         and     ip, r0, #0x80000000
716 1:      do_it   eq, tt
717         moveq   r0, r0, lsl #1
718         tsteq   r0, #0x00800000
719         subeq   r2, r2, #1
720         beq     1b
721         orr     r0, r0, ip
722         teq     r3, #0
723         and     ip, r1, #0x80000000
724 2:      do_it   eq, tt
725         moveq   r1, r1, lsl #1
726         tsteq   r1, #0x00800000
727         subeq   r3, r3, #1
728         beq     2b
729         orr     r1, r1, ip
730         b       LSYM(Ldv_x)
732         @ One or both arguments are either INF, NAN, zero or denormalized.
733 LSYM(Ldv_s):
734         and     r3, ip, r1, lsr #23
735         teq     r2, ip
736         bne     1f
737         movs    r2, r0, lsl #9
738         bne     LSYM(Lml_n)             @ NAN / <anything> -> NAN
739         teq     r3, ip
740         bne     LSYM(Lml_i)             @ INF / <anything> -> INF
741         mov     r0, r1
742         b       LSYM(Lml_n)             @ INF / (INF or NAN) -> NAN
743 1:      teq     r3, ip
744         bne     2f
745         movs    r3, r1, lsl #9
746         beq     LSYM(Lml_z)             @ <anything> / INF -> 0
747         mov     r0, r1
748         b       LSYM(Lml_n)             @ <anything> / NAN -> NAN
749 2:      @ If both are nonzero, we need to normalize and resume above.
750         bics    ip, r0, #0x80000000
751         do_it   ne
752         COND(bic,s,ne)  ip, r1, #0x80000000
753         bne     LSYM(Ldv_d)
754         @ One or both arguments are zero.
755         bics    r2, r0, #0x80000000
756         bne     LSYM(Lml_i)             @ <non_zero> / 0 -> INF
757         bics    r3, r1, #0x80000000
758         bne     LSYM(Lml_z)             @ 0 / <non_zero> -> 0
759         b       LSYM(Lml_n)             @ 0 / 0 -> NAN
761         FUNC_END aeabi_fdiv
762         FUNC_END divsf3
764 #endif /* L_muldivsf3 */
766 #ifdef L_arm_cmpsf2
768         @ The return value in r0 is
769         @
770         @   0  if the operands are equal
771         @   1  if the first operand is greater than the second, or
772         @      the operands are unordered and the operation is
773         @      CMP, LT, LE, NE, or EQ.
774         @   -1 if the first operand is less than the second, or
775         @      the operands are unordered and the operation is GT
776         @      or GE.
777         @
778         @ The Z flag will be set iff the operands are equal.
779         @
780         @ The following registers are clobbered by this function:
781         @   ip, r0, r1, r2, r3
783 ARM_FUNC_START gtsf2
784 ARM_FUNC_ALIAS gesf2 gtsf2
785         mov     ip, #-1
786         b       1f
788 ARM_FUNC_START ltsf2
789 ARM_FUNC_ALIAS lesf2 ltsf2
790         mov     ip, #1
791         b       1f
793 ARM_FUNC_START cmpsf2
794 ARM_FUNC_ALIAS nesf2 cmpsf2
795 ARM_FUNC_ALIAS eqsf2 cmpsf2
796         mov     ip, #1                  @ how should we specify unordered here?
798 1:      str     ip, [sp, #-4]!
800         @ Trap any INF/NAN first.
801         mov     r2, r0, lsl #1
802         mov     r3, r1, lsl #1
803         mvns    ip, r2, asr #24
804         do_it   ne
805         COND(mvn,s,ne)  ip, r3, asr #24
806         beq     3f
808         @ Compare values.
809         @ Note that 0.0 is equal to -0.0.
810 2:      add     sp, sp, #4
811         orrs    ip, r2, r3, lsr #1      @ test if both are 0, clear C flag
812         do_it   ne
813         teqne   r0, r1                  @ if not 0 compare sign
814         do_it   pl
815         COND(sub,s,pl)  r0, r2, r3              @ if same sign compare values, set r0
817         @ Result:
818         do_it   hi
819         movhi   r0, r1, asr #31
820         do_it   lo
821         mvnlo   r0, r1, asr #31
822         do_it   ne
823         orrne   r0, r0, #1
824         RET
826         @ Look for a NAN. 
827 3:      mvns    ip, r2, asr #24
828         bne     4f
829         movs    ip, r0, lsl #9
830         bne     5f                      @ r0 is NAN
831 4:      mvns    ip, r3, asr #24
832         bne     2b
833         movs    ip, r1, lsl #9
834         beq     2b                      @ r1 is not NAN
835 5:      ldr     r0, [sp], #4            @ return unordered code.
836         RET
838         FUNC_END gesf2
839         FUNC_END gtsf2
840         FUNC_END lesf2
841         FUNC_END ltsf2
842         FUNC_END nesf2
843         FUNC_END eqsf2
844         FUNC_END cmpsf2
846 ARM_FUNC_START aeabi_cfrcmple
848         mov     ip, r0
849         mov     r0, r1
850         mov     r1, ip
851         b       6f
853 ARM_FUNC_START aeabi_cfcmpeq
854 ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
856         @ The status-returning routines are required to preserve all
857         @ registers except ip, lr, and cpsr.
858 6:      do_push {r0, r1, r2, r3, lr}
859         ARM_CALL cmpsf2
860         @ Set the Z flag correctly, and the C flag unconditionally.
861         cmp     r0, #0
862         @ Clear the C flag if the return value was -1, indicating
863         @ that the first operand was smaller than the second.
864         do_it   mi
865         cmnmi   r0, #0
866         RETLDM  "r0, r1, r2, r3"
868         FUNC_END aeabi_cfcmple
869         FUNC_END aeabi_cfcmpeq
870         FUNC_END aeabi_cfrcmple
872 ARM_FUNC_START  aeabi_fcmpeq
874         str     lr, [sp, #-8]!
875         ARM_CALL aeabi_cfcmple
876         do_it   eq, e
877         moveq   r0, #1  @ Equal to.
878         movne   r0, #0  @ Less than, greater than, or unordered.
879         RETLDM
881         FUNC_END aeabi_fcmpeq
883 ARM_FUNC_START  aeabi_fcmplt
885         str     lr, [sp, #-8]!
886         ARM_CALL aeabi_cfcmple
887         do_it   cc, e
888         movcc   r0, #1  @ Less than.
889         movcs   r0, #0  @ Equal to, greater than, or unordered.
890         RETLDM
892         FUNC_END aeabi_fcmplt
894 ARM_FUNC_START  aeabi_fcmple
896         str     lr, [sp, #-8]!
897         ARM_CALL aeabi_cfcmple
898         do_it   ls, e
899         movls   r0, #1  @ Less than or equal to.
900         movhi   r0, #0  @ Greater than or unordered.
901         RETLDM
903         FUNC_END aeabi_fcmple
905 ARM_FUNC_START  aeabi_fcmpge
907         str     lr, [sp, #-8]!
908         ARM_CALL aeabi_cfrcmple
909         do_it   ls, e
910         movls   r0, #1  @ Operand 2 is less than or equal to operand 1.
911         movhi   r0, #0  @ Operand 2 greater than operand 1, or unordered.
912         RETLDM
914         FUNC_END aeabi_fcmpge
916 ARM_FUNC_START  aeabi_fcmpgt
918         str     lr, [sp, #-8]!
919         ARM_CALL aeabi_cfrcmple
920         do_it   cc, e
921         movcc   r0, #1  @ Operand 2 is less than operand 1.
922         movcs   r0, #0  @ Operand 2 is greater than or equal to operand 1,
923                         @ or they are unordered.
924         RETLDM
926         FUNC_END aeabi_fcmpgt
928 #endif /* L_cmpsf2 */
930 #ifdef L_arm_unordsf2
932 ARM_FUNC_START unordsf2
933 ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
935         mov     r2, r0, lsl #1
936         mov     r3, r1, lsl #1
937         mvns    ip, r2, asr #24
938         bne     1f
939         movs    ip, r0, lsl #9
940         bne     3f                      @ r0 is NAN
941 1:      mvns    ip, r3, asr #24
942         bne     2f
943         movs    ip, r1, lsl #9
944         bne     3f                      @ r1 is NAN
945 2:      mov     r0, #0                  @ arguments are ordered.
946         RET
947 3:      mov     r0, #1                  @ arguments are unordered.
948         RET
950         FUNC_END aeabi_fcmpun
951         FUNC_END unordsf2
953 #endif /* L_unordsf2 */
955 #ifdef L_arm_fixsfsi
957 ARM_FUNC_START fixsfsi
958 ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
960         @ check exponent range.
961         mov     r2, r0, lsl #1
962         cmp     r2, #(127 << 24)
963         bcc     1f                      @ value is too small
964         mov     r3, #(127 + 31)
965         subs    r2, r3, r2, lsr #24
966         bls     2f                      @ value is too large
968         @ scale value
969         mov     r3, r0, lsl #8
970         orr     r3, r3, #0x80000000
971         tst     r0, #0x80000000         @ the sign bit
972         shift1  lsr, r0, r3, r2
973         do_it   ne
974         rsbne   r0, r0, #0
975         RET
977 1:      mov     r0, #0
978         RET
980 2:      cmp     r2, #(127 + 31 - 0xff)
981         bne     3f
982         movs    r2, r0, lsl #9
983         bne     4f                      @ r0 is NAN.
984 3:      ands    r0, r0, #0x80000000     @ the sign bit
985         do_it   eq
986         moveq   r0, #0x7fffffff         @ the maximum signed positive si
987         RET
989 4:      mov     r0, #0                  @ What should we convert NAN to?
990         RET
992         FUNC_END aeabi_f2iz
993         FUNC_END fixsfsi
995 #endif /* L_fixsfsi */
997 #ifdef L_arm_fixunssfsi
999 ARM_FUNC_START fixunssfsi
1000 ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
1002         @ check exponent range.
1003         movs    r2, r0, lsl #1
1004         bcs     1f                      @ value is negative
1005         cmp     r2, #(127 << 24)
1006         bcc     1f                      @ value is too small
1007         mov     r3, #(127 + 31)
1008         subs    r2, r3, r2, lsr #24
1009         bmi     2f                      @ value is too large
1011         @ scale the value
1012         mov     r3, r0, lsl #8
1013         orr     r3, r3, #0x80000000
1014         shift1  lsr, r0, r3, r2
1015         RET
1017 1:      mov     r0, #0
1018         RET
1020 2:      cmp     r2, #(127 + 31 - 0xff)
1021         bne     3f
1022         movs    r2, r0, lsl #9
1023         bne     4f                      @ r0 is NAN.
1024 3:      mov     r0, #0xffffffff         @ maximum unsigned si
1025         RET
1027 4:      mov     r0, #0                  @ What should we convert NAN to?
1028         RET
1030         FUNC_END aeabi_f2uiz
1031         FUNC_END fixunssfsi
1033 #endif /* L_fixunssfsi */