2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / config / arm / ieee754-sf.S
blob73c598b763987d736d1d821c9d0adaec95caecf3
1 /* ieee754-sf.S single-precision floating point support for ARM
3    Copyright (C) 2003  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 2, or (at your option) any
9    later version.
11    In addition to the permissions in the GNU General Public License, the
12    Free Software Foundation gives you unlimited permission to link the
13    compiled version of this file into combinations with other programs,
14    and to distribute those combinations without any restriction coming
15    from the use of this file.  (The General Public License restrictions
16    do apply in other respects; for example, they cover modification of
17    the file, and distribution when not linked into a combine
18    executable.)
20    This file is distributed in the hope that it will be useful, but
21    WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23    General Public License for more details.
25    You should have received a copy of the GNU General Public License
26    along with this program; see the file COPYING.  If not, write to
27    the Free Software Foundation, 59 Temple Place - Suite 330,
28    Boston, MA 02111-1307, USA.  */
31  * Notes:
32  *
33  * The goal of this code is to be as fast as possible.  This is
34  * not meant to be easy to understand for the casual reader.
35  *
36  * Only the default rounding mode is intended for best performances.
37  * Exceptions aren't supported yet, but that can be added quite easily
38  * if necessary without impacting performances.
39  */
41 #ifdef L_negsf2
42         
43 ARM_FUNC_START negsf2
44         eor     r0, r0, #0x80000000     @ flip sign bit
45         RET
47         FUNC_END negsf2
49 #endif
51 #ifdef L_addsubsf3
53 ARM_FUNC_START subsf3
54         eor     r1, r1, #0x80000000     @ flip sign bit of second arg
55 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
56         b       1f                      @ Skip Thumb-code prologue
57 #endif
59 ARM_FUNC_START addsf3
61 1:      @ Compare both args, return zero if equal but the sign.
62         eor     r2, r0, r1
63         teq     r2, #0x80000000
64         beq     LSYM(Lad_z)
66         @ If first arg is 0 or -0, return second arg.
67         @ If second arg is 0 or -0, return first arg.
68         bics    r2, r0, #0x80000000
69         moveq   r0, r1
70         bicnes  r2, r1, #0x80000000
71         RETc(eq)
73         @ Mask out exponents.
74         mov     ip, #0xff000000
75         and     r2, r0, ip, lsr #1
76         and     r3, r1, ip, lsr #1
78         @ If either of them is 255, result will be INF or NAN
79         teq     r2, ip, lsr #1
80         teqne   r3, ip, lsr #1
81         beq     LSYM(Lad_i)
83         @ Compute exponent difference.  Make largest exponent in r2,
84         @ corresponding arg in r0, and positive exponent difference in r3.
85         subs    r3, r3, r2
86         addgt   r2, r2, r3
87         eorgt   r1, r0, r1
88         eorgt   r0, r1, r0
89         eorgt   r1, r0, r1
90         rsblt   r3, r3, #0
92         @ If exponent difference is too large, return largest argument
93         @ already in r0.  We need up to 25 bit to handle proper rounding
94         @ of 0x1p25 - 1.1.
95         cmp     r3, #(25 << 23)
96         RETc(hi)
98         @ Convert mantissa to signed integer.
99         tst     r0, #0x80000000
100         orr     r0, r0, #0x00800000
101         bic     r0, r0, #0xff000000
102         rsbne   r0, r0, #0
103         tst     r1, #0x80000000
104         orr     r1, r1, #0x00800000
105         bic     r1, r1, #0xff000000
106         rsbne   r1, r1, #0
108         @ If exponent == difference, one or both args were denormalized.
109         @ Since this is not common case, rescale them off line.
110         teq     r2, r3
111         beq     LSYM(Lad_d)
112 LSYM(Lad_x):
114         @ Scale down second arg with exponent difference.
115         @ Apply shift one bit left to first arg and the rest to second arg
116         @ to simplify things later, but only if exponent does not become 0.
117         movs    r3, r3, lsr #23
118         teqne   r2, #(1 << 23)
119         movne   r0, r0, lsl #1
120         subne   r2, r2, #(1 << 23)
121         subne   r3, r3, #1
123         @ Shift second arg into ip, keep leftover bits into r1.
124         mov     ip, r1, asr r3
125         rsb     r3, r3, #32
126         mov     r1, r1, lsl r3
128         add     r0, r0, ip              @ the actual addition
130         @ We now have a 64 bit result in r0-r1.
131         @ Keep absolute value in r0-r1, sign in r3.
132         ands    r3, r0, #0x80000000
133         bpl     LSYM(Lad_p)
134         rsbs    r1, r1, #0
135         rsc     r0, r0, #0
137         @ Determine how to normalize the result.
138 LSYM(Lad_p):
139         cmp     r0, #0x00800000
140         bcc     LSYM(Lad_l)
141         cmp     r0, #0x01000000
142         bcc     LSYM(Lad_r0)
143         cmp     r0, #0x02000000
144         bcc     LSYM(Lad_r1)
146         @ Result needs to be shifted right.
147         movs    r0, r0, lsr #1
148         mov     r1, r1, rrx
149         add     r2, r2, #(1 << 23)
150 LSYM(Lad_r1):
151         movs    r0, r0, lsr #1
152         mov     r1, r1, rrx
153         add     r2, r2, #(1 << 23)
155         @ Our result is now properly aligned into r0, remaining bits in r1.
156         @ Round with MSB of r1. If halfway between two numbers, round towards
157         @ LSB of r0 = 0. 
158 LSYM(Lad_r0):
159         add     r0, r0, r1, lsr #31
160         teq     r1, #0x80000000
161         biceq   r0, r0, #1
163         @ Rounding may have added a new MSB.  Adjust exponent.
164         @ That MSB will be cleared when exponent is merged below.
165         tst     r0, #0x01000000
166         addne   r2, r2, #(1 << 23)
168         @ Make sure we did not bust our exponent.
169         cmp     r2, #(254 << 23)
170         bhi     LSYM(Lad_o)
172         @ Pack final result together.
173 LSYM(Lad_e):
174         bic     r0, r0, #0x01800000
175         orr     r0, r0, r2
176         orr     r0, r0, r3
177         RET
179         @ Result must be shifted left.
180         @ No rounding necessary since r1 will always be 0.
181 LSYM(Lad_l):
183 #if __ARM_ARCH__ < 5
185         movs    ip, r0, lsr #12
186         moveq   r0, r0, lsl #12
187         subeq   r2, r2, #(12 << 23)
188         tst     r0, #0x00ff0000
189         moveq   r0, r0, lsl #8
190         subeq   r2, r2, #(8 << 23)
191         tst     r0, #0x00f00000
192         moveq   r0, r0, lsl #4
193         subeq   r2, r2, #(4 << 23)
194         tst     r0, #0x00c00000
195         moveq   r0, r0, lsl #2
196         subeq   r2, r2, #(2 << 23)
197         tst     r0, #0x00800000
198         moveq   r0, r0, lsl #1
199         subeq   r2, r2, #(1 << 23)
200         cmp     r2, #0
201         bgt     LSYM(Lad_e)
203 #else
205         clz     ip, r0
206         sub     ip, ip, #8
207         mov     r0, r0, lsl ip
208         subs    r2, r2, ip, lsl #23
209         bgt     LSYM(Lad_e)
211 #endif
213         @ Exponent too small, denormalize result.
214         mvn     r2, r2, asr #23
215         add     r2, r2, #2
216         orr     r0, r3, r0, lsr r2
217         RET
219         @ Fixup and adjust bit position for denormalized arguments.
220         @ Note that r2 must not remain equal to 0.
221 LSYM(Lad_d):
222         teq     r2, #0
223         eoreq   r0, r0, #0x00800000
224         addeq   r2, r2, #(1 << 23)
225         eor     r1, r1, #0x00800000
226         subne   r3, r3, #(1 << 23)
227         b       LSYM(Lad_x)
229         @ Result is x - x = 0, unless x is INF or NAN.
230 LSYM(Lad_z):
231         mov     ip, #0xff000000
232         and     r2, r0, ip, lsr #1
233         teq     r2, ip, lsr #1
234         moveq   r0, ip, asr #2
235         movne   r0, #0
236         RET
238         @ Overflow: return INF.
239 LSYM(Lad_o):
240         orr     r0, r3, #0x7f000000
241         orr     r0, r0, #0x00800000
242         RET
244         @ At least one of r0/r1 is INF/NAN.
245         @   if r0 != INF/NAN: return r1 (which is INF/NAN)
246         @   if r1 != INF/NAN: return r0 (which is INF/NAN)
247         @   if r0 or r1 is NAN: return NAN
248         @   if opposite sign: return NAN
249         @   return r0 (which is INF or -INF)
250 LSYM(Lad_i):
251         teq     r2, ip, lsr #1
252         movne   r0, r1
253         teqeq   r3, ip, lsr #1
254         RETc(ne)
255         movs    r2, r0, lsl #9
256         moveqs  r2, r1, lsl #9
257         teqeq   r0, r1
258         orrne   r0, r3, #0x00400000     @ NAN
259         RET
261         FUNC_END addsf3
262         FUNC_END subsf3
264 ARM_FUNC_START floatunsisf
265         mov     r3, #0
266         b       1f
268 ARM_FUNC_START floatsisf
269         ands    r3, r0, #0x80000000
270         rsbmi   r0, r0, #0
272 1:      teq     r0, #0
273         RETc(eq)
275         mov     r1, #0
276         mov     r2, #((127 + 23) << 23)
277         tst     r0, #0xfc000000
278         beq     LSYM(Lad_p)
280         @ We need to scale the value a little before branching to code above.
281         tst     r0, #0xf0000000
282         movne   r1, r0, lsl #28
283         movne   r0, r0, lsr #4
284         addne   r2, r2, #(4 << 23)
285         tst     r0, #0x0c000000
286         beq     LSYM(Lad_p)
287         mov     r1, r1, lsr #2
288         orr     r1, r1, r0, lsl #30
289         mov     r0, r0, lsr #2
290         add     r2, r2, #(2 << 23)
291         b       LSYM(Lad_p)
293         FUNC_END floatsisf
294         FUNC_END floatunsisf
296 #endif /* L_addsubsf3 */
298 #ifdef L_muldivsf3
300 ARM_FUNC_START mulsf3
302         @ Mask out exponents.
303         mov     ip, #0xff000000
304         and     r2, r0, ip, lsr #1
305         and     r3, r1, ip, lsr #1
307         @ Trap any INF/NAN.
308         teq     r2, ip, lsr #1
309         teqne   r3, ip, lsr #1
310         beq     LSYM(Lml_s)
312         @ Trap any multiplication by 0.
313         bics    ip, r0, #0x80000000
314         bicnes  ip, r1, #0x80000000
315         beq     LSYM(Lml_z)
317         @ Shift exponents right one bit to make room for overflow bit.
318         @ If either of them is 0, scale denormalized arguments off line.
319         @ Then add both exponents together.
320         movs    r2, r2, lsr #1
321         teqne   r3, #0
322         beq     LSYM(Lml_d)
323 LSYM(Lml_x):
324         add     r2, r2, r3, asr #1
326         @ Preserve final sign in r2 along with exponent for now.
327         teq     r0, r1
328         orrmi   r2, r2, #0x8000
330         @ Convert mantissa to unsigned integer.
331         bic     r0, r0, #0xff000000
332         bic     r1, r1, #0xff000000
333         orr     r0, r0, #0x00800000
334         orr     r1, r1, #0x00800000
336 #if __ARM_ARCH__ < 4
338         @ Well, no way to make it shorter without the umull instruction.
339         @ We must perform that 24 x 24 -> 48 bit multiplication by hand.
340         stmfd   sp!, {r4, r5}
341         mov     r4, r0, lsr #16
342         mov     r5, r1, lsr #16
343         bic     r0, r0, #0x00ff0000
344         bic     r1, r1, #0x00ff0000
345         mul     ip, r4, r5
346         mul     r3, r0, r1
347         mul     r0, r5, r0
348         mla     r0, r4, r1, r0
349         adds    r3, r3, r0, lsl #16
350         adc     ip, ip, r0, lsr #16
351         ldmfd   sp!, {r4, r5}
353 #else
355         umull   r3, ip, r0, r1          @ The actual multiplication.
357 #endif
359         @ Put final sign in r0.
360         mov     r0, r2, lsl #16
361         bic     r2, r2, #0x8000
363         @ Adjust result if one extra MSB appeared.
364         @ The LSB may be lost but this never changes the result in this case.
365         tst     ip, #(1 << 15)
366         addne   r2, r2, #(1 << 22)
367         movnes  ip, ip, lsr #1
368         movne   r3, r3, rrx
370         @ Apply exponent bias, check range for underflow.
371         subs    r2, r2, #(127 << 22)
372         ble     LSYM(Lml_u)
374         @ Scale back to 24 bits with rounding.
375         @ r0 contains sign bit already.
376         orrs    r0, r0, r3, lsr #23
377         adc     r0, r0, ip, lsl #9
379         @ If halfway between two numbers, rounding should be towards LSB = 0.
380         mov     r3, r3, lsl #9
381         teq     r3, #0x80000000
382         biceq   r0, r0, #1
384         @ Note: rounding may have produced an extra MSB here.
385         @ The extra bit is cleared before merging the exponent below.
386         tst     r0, #0x01000000
387         addne   r2, r2, #(1 << 22)
389         @ Check for exponent overflow
390         cmp     r2, #(255 << 22)
391         bge     LSYM(Lml_o)
393         @ Add final exponent.
394         bic     r0, r0, #0x01800000
395         orr     r0, r0, r2, lsl #1
396         RET
398         @ Result is 0, but determine sign anyway.
399 LSYM(Lml_z):
400         eor     r0, r0, r1
401         bic     r0, r0, #0x7fffffff
402         RET
404         @ Check if denormalized result is possible, otherwise return signed 0.
405 LSYM(Lml_u):
406         cmn     r2, #(24 << 22)
407         RETc(le)
409         @ Find out proper shift value.
410         mvn     r1, r2, asr #22
411         subs    r1, r1, #7
412         bgt     LSYM(Lml_ur)
414         @ Shift value left, round, etc.
415         add     r1, r1, #32
416         orrs    r0, r0, r3, lsr r1
417         rsb     r1, r1, #32
418         adc     r0, r0, ip, lsl r1
419         mov     ip, r3, lsl r1
420         teq     ip, #0x80000000
421         biceq   r0, r0, #1
422         RET
424         @ Shift value right, round, etc.
425         @ Note: r1 must not be 0 otherwise carry does not get set.
426 LSYM(Lml_ur):
427         orrs    r0, r0, ip, lsr r1
428         adc     r0, r0, #0
429         rsb     r1, r1, #32
430         mov     ip, ip, lsl r1
431         teq     r3, #0
432         teqeq   ip, #0x80000000
433         biceq   r0, r0, #1
434         RET
436         @ One or both arguments are denormalized.
437         @ Scale them leftwards and preserve sign bit.
438 LSYM(Lml_d):
439         teq     r2, #0
440         and     ip, r0, #0x80000000
441 1:      moveq   r0, r0, lsl #1
442         tsteq   r0, #0x00800000
443         subeq   r2, r2, #(1 << 22)
444         beq     1b
445         orr     r0, r0, ip
446         teq     r3, #0
447         and     ip, r1, #0x80000000
448 2:      moveq   r1, r1, lsl #1
449         tsteq   r1, #0x00800000
450         subeq   r3, r3, #(1 << 23)
451         beq     2b
452         orr     r1, r1, ip
453         b       LSYM(Lml_x)
455         @ One or both args are INF or NAN.
456 LSYM(Lml_s):
457         teq     r0, #0x0
458         teqne   r1, #0x0
459         teqne   r0, #0x80000000
460         teqne   r1, #0x80000000
461         beq     LSYM(Lml_n)             @ 0 * INF or INF * 0 -> NAN
462         teq     r2, ip, lsr #1
463         bne     1f
464         movs    r2, r0, lsl #9
465         bne     LSYM(Lml_n)             @ NAN * <anything> -> NAN
466 1:      teq     r3, ip, lsr #1
467         bne     LSYM(Lml_i)
468         movs    r3, r1, lsl #9
469         bne     LSYM(Lml_n)             @ <anything> * NAN -> NAN
471         @ Result is INF, but we need to determine its sign.
472 LSYM(Lml_i):
473         eor     r0, r0, r1
475         @ Overflow: return INF (sign already in r0).
476 LSYM(Lml_o):
477         and     r0, r0, #0x80000000
478         orr     r0, r0, #0x7f000000
479         orr     r0, r0, #0x00800000
480         RET
482         @ Return NAN.
483 LSYM(Lml_n):
484         mov     r0, #0x7f000000
485         orr     r0, r0, #0x00c00000
486         RET
488         FUNC_END mulsf3
490 ARM_FUNC_START divsf3
492         @ Mask out exponents.
493         mov     ip, #0xff000000
494         and     r2, r0, ip, lsr #1
495         and     r3, r1, ip, lsr #1
497         @ Trap any INF/NAN or zeroes.
498         teq     r2, ip, lsr #1
499         teqne   r3, ip, lsr #1
500         bicnes  ip, r0, #0x80000000
501         bicnes  ip, r1, #0x80000000
502         beq     LSYM(Ldv_s)
504         @ Shift exponents right one bit to make room for overflow bit.
505         @ If either of them is 0, scale denormalized arguments off line.
506         @ Then substract divisor exponent from dividend''s.
507         movs    r2, r2, lsr #1
508         teqne   r3, #0
509         beq     LSYM(Ldv_d)
510 LSYM(Ldv_x):
511         sub     r2, r2, r3, asr #1
513         @ Preserve final sign into ip.
514         eor     ip, r0, r1
516         @ Convert mantissa to unsigned integer.
517         @ Dividend -> r3, divisor -> r1.
518         mov     r3, #0x10000000
519         movs    r1, r1, lsl #9
520         mov     r0, r0, lsl #9
521         beq     LSYM(Ldv_1)
522         orr     r1, r3, r1, lsr #4
523         orr     r3, r3, r0, lsr #4
525         @ Initialize r0 (result) with final sign bit.
526         and     r0, ip, #0x80000000
528         @ Ensure result will land to known bit position.
529         cmp     r3, r1
530         subcc   r2, r2, #(1 << 22)
531         movcc   r3, r3, lsl #1
533         @ Apply exponent bias, check range for over/underflow.
534         add     r2, r2, #(127 << 22)
535         cmn     r2, #(24 << 22)
536         RETc(le)
537         cmp     r2, #(255 << 22)
538         bge     LSYM(Lml_o)
540         @ The actual division loop.
541         mov     ip, #0x00800000
542 1:      cmp     r3, r1
543         subcs   r3, r3, r1
544         orrcs   r0, r0, ip
545         cmp     r3, r1, lsr #1
546         subcs   r3, r3, r1, lsr #1
547         orrcs   r0, r0, ip, lsr #1
548         cmp     r3, r1, lsr #2
549         subcs   r3, r3, r1, lsr #2
550         orrcs   r0, r0, ip, lsr #2
551         cmp     r3, r1, lsr #3
552         subcs   r3, r3, r1, lsr #3
553         orrcs   r0, r0, ip, lsr #3
554         movs    r3, r3, lsl #4
555         movnes  ip, ip, lsr #4
556         bne     1b
558         @ Check if denormalized result is needed.
559         cmp     r2, #0
560         ble     LSYM(Ldv_u)
562         @ Apply proper rounding.
563         cmp     r3, r1
564         addcs   r0, r0, #1
565         biceq   r0, r0, #1
567         @ Add exponent to result.
568         bic     r0, r0, #0x00800000
569         orr     r0, r0, r2, lsl #1
570         RET
572         @ Division by 0x1p*: let''s shortcut a lot of code.
573 LSYM(Ldv_1):
574         and     ip, ip, #0x80000000
575         orr     r0, ip, r0, lsr #9
576         add     r2, r2, #(127 << 22)
577         cmp     r2, #(255 << 22)
578         bge     LSYM(Lml_o)
579         cmp     r2, #0
580         orrgt   r0, r0, r2, lsl #1
581         RETc(gt)
582         cmn     r2, #(24 << 22)
583         movle   r0, ip
584         RETc(le)
585         orr     r0, r0, #0x00800000
586         mov     r3, #0
588         @ Result must be denormalized: prepare parameters to use code above.
589         @ r3 already contains remainder for rounding considerations.
590 LSYM(Ldv_u):
591         bic     ip, r0, #0x80000000
592         and     r0, r0, #0x80000000
593         mvn     r1, r2, asr #22
594         add     r1, r1, #2
595         b       LSYM(Lml_ur)
597         @ One or both arguments are denormalized.
598         @ Scale them leftwards and preserve sign bit.
599 LSYM(Ldv_d):
600         teq     r2, #0
601         and     ip, r0, #0x80000000
602 1:      moveq   r0, r0, lsl #1
603         tsteq   r0, #0x00800000
604         subeq   r2, r2, #(1 << 22)
605         beq     1b
606         orr     r0, r0, ip
607         teq     r3, #0
608         and     ip, r1, #0x80000000
609 2:      moveq   r1, r1, lsl #1
610         tsteq   r1, #0x00800000
611         subeq   r3, r3, #(1 << 23)
612         beq     2b
613         orr     r1, r1, ip
614         b       LSYM(Ldv_x)
616         @ One or both arguments is either INF, NAN or zero.
617 LSYM(Ldv_s):
618         mov     ip, #0xff000000
619         teq     r2, ip, lsr #1
620         teqeq   r3, ip, lsr #1
621         beq     LSYM(Lml_n)             @ INF/NAN / INF/NAN -> NAN
622         teq     r2, ip, lsr #1
623         bne     1f
624         movs    r2, r0, lsl #9
625         bne     LSYM(Lml_n)             @ NAN / <anything> -> NAN
626         b       LSYM(Lml_i)             @ INF / <anything> -> INF
627 1:      teq     r3, ip, lsr #1
628         bne     2f
629         movs    r3, r1, lsl #9
630         bne     LSYM(Lml_n)             @ <anything> / NAN -> NAN
631         b       LSYM(Lml_z)             @ <anything> / INF -> 0
632 2:      @ One or both arguments are 0.
633         bics    r2, r0, #0x80000000
634         bne     LSYM(Lml_i)             @ <non_zero> / 0 -> INF
635         bics    r3, r1, #0x80000000
636         bne     LSYM(Lml_z)             @ 0 / <non_zero> -> 0
637         b       LSYM(Lml_n)             @ 0 / 0 -> NAN
639         FUNC_END divsf3
641 #endif /* L_muldivsf3 */
643 #ifdef L_cmpsf2
645 FUNC_START gesf2
646 ARM_FUNC_START gtsf2
647         mov     r3, #-1
648         b       1f
650 FUNC_START lesf2
651 ARM_FUNC_START ltsf2
652         mov     r3, #1
653         b       1f
655 FUNC_START nesf2
656 FUNC_START eqsf2
657 ARM_FUNC_START cmpsf2
658         mov     r3, #1                  @ how should we specify unordered here?
660 1:      @ Trap any INF/NAN first.
661         mov     ip, #0xff000000
662         and     r2, r1, ip, lsr #1
663         teq     r2, ip, lsr #1
664         and     r2, r0, ip, lsr #1
665         teqne   r2, ip, lsr #1
666         beq     3f
668         @ Test for equality.
669         @ Note that 0.0 is equal to -0.0.
670 2:      orr     r3, r0, r1
671         bics    r3, r3, #0x80000000     @ either 0.0 or -0.0
672         teqne   r0, r1                  @ or both the same
673         moveq   r0, #0
674         RETc(eq)
676         @ Check for sign difference.  The N flag is set if it is the case.
677         @ If so, return sign of r0.
678         movmi   r0, r0, asr #31
679         orrmi   r0, r0, #1
680         RETc(mi)
682         @ Compare exponents.
683         and     r3, r1, ip, lsr #1
684         cmp     r2, r3
686         @ Compare mantissa if exponents are equal
687         moveq   r0, r0, lsl #9
688         cmpeq   r0, r1, lsl #9
689         movcs   r0, r1, asr #31
690         mvncc   r0, r1, asr #31
691         orr     r0, r0, #1
692         RET
694         @ Look for a NAN. 
695 3:      and     r2, r1, ip, lsr #1
696         teq     r2, ip, lsr #1
697         bne     4f
698         movs    r2, r1, lsl #9
699         bne     5f                      @ r1 is NAN
700 4:      and     r2, r0, ip, lsr #1
701         teq     r2, ip, lsr #1
702         bne     2b
703         movs    ip, r0, lsl #9
704         beq     2b                      @ r0 is not NAN
705 5:      mov     r0, r3                  @ return unordered code from r3.
706         RET
708         FUNC_END gesf2
709         FUNC_END gtsf2
710         FUNC_END lesf2
711         FUNC_END ltsf2
712         FUNC_END nesf2
713         FUNC_END eqsf2
714         FUNC_END cmpsf2
716 #endif /* L_cmpsf2 */
718 #ifdef L_unordsf2
720 ARM_FUNC_START unordsf2
721         mov     ip, #0xff000000
722         and     r2, r1, ip, lsr #1
723         teq     r2, ip, lsr #1
724         bne     1f
725         movs    r2, r1, lsl #9
726         bne     3f                      @ r1 is NAN
727 1:      and     r2, r0, ip, lsr #1
728         teq     r2, ip, lsr #1
729         bne     2f
730         movs    r2, r0, lsl #9
731         bne     3f                      @ r0 is NAN
732 2:      mov     r0, #0                  @ arguments are ordered.
733         RET
734 3:      mov     r0, #1                  @ arguments are unordered.
735         RET
737         FUNC_END unordsf2
739 #endif /* L_unordsf2 */
741 #ifdef L_fixsfsi
743 ARM_FUNC_START fixsfsi
744         movs    r0, r0, lsl #1
745         RETc(eq)                        @ value is 0.
747         mov     r1, r1, rrx             @ preserve C flag (the actual sign)
749         @ check exponent range.
750         and     r2, r0, #0xff000000
751         cmp     r2, #(127 << 24)
752         movcc   r0, #0                  @ value is too small
753         RETc(cc)
754         cmp     r2, #((127 + 31) << 24)
755         bcs     1f                      @ value is too large
757         mov     r0, r0, lsl #7
758         orr     r0, r0, #0x80000000
759         mov     r2, r2, lsr #24
760         rsb     r2, r2, #(127 + 31)
761         tst     r1, #0x80000000         @ the sign bit
762         mov     r0, r0, lsr r2
763         rsbne   r0, r0, #0
764         RET
766 1:      teq     r2, #0xff000000
767         bne     2f
768         movs    r0, r0, lsl #8
769         bne     3f                      @ r0 is NAN.
770 2:      ands    r0, r1, #0x80000000     @ the sign bit
771         moveq   r0, #0x7fffffff         @ the maximum signed positive si
772         RET
774 3:      mov     r0, #0                  @ What should we convert NAN to?
775         RET
777         FUNC_END fixsfsi
779 #endif /* L_fixsfsi */
781 #ifdef L_fixunssfsi
783 ARM_FUNC_START fixunssfsi
784         movs    r0, r0, lsl #1
785         movcss  r0, #0                  @ value is negative...
786         RETc(eq)                        @ ... or 0.
789         @ check exponent range.
790         and     r2, r0, #0xff000000
791         cmp     r2, #(127 << 24)
792         movcc   r0, #0                  @ value is too small
793         RETc(cc)
794         cmp     r2, #((127 + 32) << 24)
795         bcs     1f                      @ value is too large
797         mov     r0, r0, lsl #7
798         orr     r0, r0, #0x80000000
799         mov     r2, r2, lsr #24
800         rsb     r2, r2, #(127 + 31)
801         mov     r0, r0, lsr r2
802         RET
804 1:      teq     r2, #0xff000000
805         bne     2f
806         movs    r0, r0, lsl #8
807         bne     3f                      @ r0 is NAN.
808 2:      mov     r0, #0xffffffff         @ maximum unsigned si
809         RET
811 3:      mov     r0, #0                  @ What should we convert NAN to?
812         RET
814         FUNC_END fixunssfsi
816 #endif /* L_fixunssfsi */