[Patch (preapproved)] Guard Copy Header pass on
[official-gcc.git] / libgcc / config / arm / ieee754-df.S
blobf470151cd8f1da3952a05b88d994fb930c6764c2
1 /* ieee754-df.S double-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  * For slightly simpler code please see the single precision version
31  * of this file.
32  * 
33  * Only the default rounding mode is intended for best performances.
34  * Exceptions aren't supported yet, but that can be added quite easily
35  * if necessary without impacting performances.
36  *
37  * In the CFI related comments, 'previousOffset' refers to the previous offset
38  * from sp used to compute the CFA.
39  */
41         .cfi_sections .debug_frame
43 #ifndef __ARMEB__
44 #define xl r0
45 #define xh r1
46 #define yl r2
47 #define yh r3
48 #else
49 #define xh r0
50 #define xl r1
51 #define yh r2
52 #define yl r3
53 #endif
56 #ifdef L_arm_negdf2
58 ARM_FUNC_START negdf2
59 ARM_FUNC_ALIAS aeabi_dneg negdf2
60         CFI_START_FUNCTION
62         @ flip sign bit
63         eor     xh, xh, #0x80000000
64         RET
66         CFI_END_FUNCTION
67         FUNC_END aeabi_dneg
68         FUNC_END negdf2
70 #endif
72 #ifdef L_arm_addsubdf3
74 ARM_FUNC_START aeabi_drsub
75         CFI_START_FUNCTION
77         eor     xh, xh, #0x80000000     @ flip sign bit of first arg
78         b       1f      
80 ARM_FUNC_START subdf3
81 ARM_FUNC_ALIAS aeabi_dsub subdf3
83         eor     yh, yh, #0x80000000     @ flip sign bit of second arg
84 #if defined(__INTERWORKING_STUBS__)
85         b       1f                      @ Skip Thumb-code prologue
86 #endif
88 ARM_FUNC_START adddf3
89 ARM_FUNC_ALIAS aeabi_dadd adddf3
91 1:  do_push {r4, r5, lr}        @ sp -= 12
92         .cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
93         .cfi_rel_offset r4, 0       @ Registers are saved from sp to sp + 8
94         .cfi_rel_offset r5, 4
95         .cfi_rel_offset lr, 8
97         @ Look for zeroes, equal values, INF, or NAN.
98         shift1  lsl, r4, xh, #1
99         shift1  lsl, r5, yh, #1
100         teq     r4, r5
101         do_it   eq
102         teqeq   xl, yl
103         do_it   ne, ttt
104         COND(orr,s,ne)  ip, r4, xl
105         COND(orr,s,ne)  ip, r5, yl
106         COND(mvn,s,ne)  ip, r4, asr #21
107         COND(mvn,s,ne)  ip, r5, asr #21
108         beq     LSYM(Lad_s)
110         @ Compute exponent difference.  Make largest exponent in r4,
111         @ corresponding arg in xh-xl, and positive exponent difference in r5.
112         shift1  lsr, r4, r4, #21
113         rsbs    r5, r4, r5, lsr #21
114         do_it   lt
115         rsblt   r5, r5, #0
116         ble     1f
117         add     r4, r4, r5
118         eor     yl, xl, yl
119         eor     yh, xh, yh
120         eor     xl, yl, xl
121         eor     xh, yh, xh
122         eor     yl, xl, yl
123         eor     yh, xh, yh
125         @ If exponent difference is too large, return largest argument
126         @ already in xh-xl.  We need up to 54 bit to handle proper rounding
127         @ of 0x1p54 - 1.1.
128         cmp     r5, #54
129         do_it   hi
130         RETLDM  "r4, r5" hi
132         @ Convert mantissa to signed integer.
133         tst     xh, #0x80000000
134         mov     xh, xh, lsl #12
135         mov     ip, #0x00100000
136         orr     xh, ip, xh, lsr #12
137         beq     1f
138 #if defined(__thumb2__)
139         negs    xl, xl
140         sbc     xh, xh, xh, lsl #1
141 #else
142         rsbs    xl, xl, #0
143         rsc     xh, xh, #0
144 #endif
146         tst     yh, #0x80000000
147         mov     yh, yh, lsl #12
148         orr     yh, ip, yh, lsr #12
149         beq     1f
150 #if defined(__thumb2__)
151         negs    yl, yl
152         sbc     yh, yh, yh, lsl #1
153 #else
154         rsbs    yl, yl, #0
155         rsc     yh, yh, #0
156 #endif
158         @ If exponent == difference, one or both args were denormalized.
159         @ Since this is not common case, rescale them off line.
160         teq     r4, r5
161         beq     LSYM(Lad_d)
163 @ CFI note: we're lucky that the branches to Lad_* that appear after this
164 @ function have a CFI state that's exactly the same as the one we're in at this
165 @ point. Otherwise the CFI would change to a different state after the branch,
166 @ which would be disastrous for backtracing.
167 LSYM(Lad_x):
169         @ Compensate for the exponent overlapping the mantissa MSB added later
170         sub     r4, r4, #1
172         @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
173         rsbs    lr, r5, #32
174         blt     1f
175         shift1  lsl, ip, yl, lr
176         shiftop adds xl xl yl lsr r5 yl
177         adc     xh, xh, #0
178         shiftop adds xl xl yh lsl lr yl
179         shiftop adcs xh xh yh asr r5 yh
180         b       2f
181 1:      sub     r5, r5, #32
182         add     lr, lr, #32
183         cmp     yl, #1
184         shift1  lsl,ip, yh, lr
185         do_it   cs
186         orrcs   ip, ip, #2              @ 2 not 1, to allow lsr #1 later
187         shiftop adds xl xl yh asr r5 yh
188         adcs    xh, xh, yh, asr #31
190         @ We now have a result in xh-xl-ip.
191         @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
192         and     r5, xh, #0x80000000
193         bpl     LSYM(Lad_p)
194 #if defined(__thumb2__)
195         mov     lr, #0
196         negs    ip, ip
197         sbcs    xl, lr, xl
198         sbc     xh, lr, xh
199 #else
200         rsbs    ip, ip, #0
201         rscs    xl, xl, #0
202         rsc     xh, xh, #0
203 #endif
205         @ Determine how to normalize the result.
206 LSYM(Lad_p):
207         cmp     xh, #0x00100000
208         bcc     LSYM(Lad_a)
209         cmp     xh, #0x00200000
210         bcc     LSYM(Lad_e)
212         @ Result needs to be shifted right.
213         movs    xh, xh, lsr #1
214         movs    xl, xl, rrx
215         mov     ip, ip, rrx
216         add     r4, r4, #1
218         @ Make sure we did not bust our exponent.
219         mov     r2, r4, lsl #21
220         cmn     r2, #(2 << 21)
221         bcs     LSYM(Lad_o)
223         @ Our result is now properly aligned into xh-xl, remaining bits in ip.
224         @ Round with MSB of ip. If halfway between two numbers, round towards
225         @ LSB of xl = 0.
226         @ Pack final result together.
227 LSYM(Lad_e):
228         cmp     ip, #0x80000000
229         do_it   eq
230         COND(mov,s,eq)  ip, xl, lsr #1
231         adcs    xl, xl, #0
232         adc     xh, xh, r4, lsl #20
233         orr     xh, xh, r5
234         RETLDM  "r4, r5"
236         @ Result must be shifted left and exponent adjusted.
237 LSYM(Lad_a):
238         movs    ip, ip, lsl #1
239         adcs    xl, xl, xl
240         adc     xh, xh, xh
241         tst     xh, #0x00100000
242         sub     r4, r4, #1
243         bne     LSYM(Lad_e)
245         @ No rounding necessary since ip will always be 0 at this point.
246 LSYM(Lad_l):
248 #if __ARM_ARCH__ < 5
250         teq     xh, #0
251         movne   r3, #20
252         moveq   r3, #52
253         moveq   xh, xl
254         moveq   xl, #0
255         mov     r2, xh
256         cmp     r2, #(1 << 16)
257         movhs   r2, r2, lsr #16
258         subhs   r3, r3, #16
259         cmp     r2, #(1 << 8)
260         movhs   r2, r2, lsr #8
261         subhs   r3, r3, #8
262         cmp     r2, #(1 << 4)
263         movhs   r2, r2, lsr #4
264         subhs   r3, r3, #4
265         cmp     r2, #(1 << 2)
266         subhs   r3, r3, #2
267         sublo   r3, r3, r2, lsr #1
268         sub     r3, r3, r2, lsr #3
270 #else
272         teq     xh, #0
273         do_it   eq, t
274         moveq   xh, xl
275         moveq   xl, #0
276         clz     r3, xh
277         do_it   eq
278         addeq   r3, r3, #32
279         sub     r3, r3, #11
281 #endif
283         @ determine how to shift the value.
284         subs    r2, r3, #32
285         bge     2f
286         adds    r2, r2, #12
287         ble     1f
289         @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
290         @ since a register switch happened above.
291         add     ip, r2, #20
292         rsb     r2, r2, #12
293         shift1  lsl, xl, xh, ip
294         shift1  lsr, xh, xh, r2
295         b       3f
297         @ actually shift value left 1 to 20 bits, which might also represent
298         @ 32 to 52 bits if counting the register switch that happened earlier.
299 1:      add     r2, r2, #20
300 2:      do_it   le
301         rsble   ip, r2, #32
302         shift1  lsl, xh, xh, r2
303 #if defined(__thumb2__)
304         lsr     ip, xl, ip
305         itt     le
306         orrle   xh, xh, ip
307         lslle   xl, xl, r2
308 #else
309         orrle   xh, xh, xl, lsr ip
310         movle   xl, xl, lsl r2
311 #endif
313         @ adjust exponent accordingly.
314 3:      subs    r4, r4, r3
315         do_it   ge, tt
316         addge   xh, xh, r4, lsl #20
317         orrge   xh, xh, r5
318         RETLDM  "r4, r5" ge
320         @ Exponent too small, denormalize result.
321         @ Find out proper shift value.
322         mvn     r4, r4
323         subs    r4, r4, #31
324         bge     2f
325         adds    r4, r4, #12
326         bgt     1f
328         @ shift result right of 1 to 20 bits, sign is in r5.
329         add     r4, r4, #20
330         rsb     r2, r4, #32
331         shift1  lsr, xl, xl, r4
332         shiftop orr xl xl xh lsl r2 yh
333         shiftop orr xh r5 xh lsr r4 yh
334         RETLDM  "r4, r5"
336         @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
337         @ a register switch from xh to xl.
338 1:      rsb     r4, r4, #12
339         rsb     r2, r4, #32
340         shift1  lsr, xl, xl, r2
341         shiftop orr xl xl xh lsl r4 yh
342         mov     xh, r5
343         RETLDM  "r4, r5"
345         @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
346         @ from xh to xl.
347 2:      shift1  lsr, xl, xh, r4
348         mov     xh, r5
349         RETLDM  "r4, r5"
351         @ Adjust exponents for denormalized arguments.
352         @ Note that r4 must not remain equal to 0.
353 LSYM(Lad_d):
354         teq     r4, #0
355         eor     yh, yh, #0x00100000
356         do_it   eq, te
357         eoreq   xh, xh, #0x00100000
358         addeq   r4, r4, #1
359         subne   r5, r5, #1
360         b       LSYM(Lad_x)
363 LSYM(Lad_s):
364         mvns    ip, r4, asr #21
365         do_it   ne
366         COND(mvn,s,ne)  ip, r5, asr #21
367         beq     LSYM(Lad_i)
369         teq     r4, r5
370         do_it   eq
371         teqeq   xl, yl
372         beq     1f
374         @ Result is x + 0.0 = x or 0.0 + y = y.
375         orrs    ip, r4, xl
376         do_it   eq, t
377         moveq   xh, yh
378         moveq   xl, yl
379         RETLDM  "r4, r5"
381 1:      teq     xh, yh
383         @ Result is x - x = 0.
384         do_it   ne, tt
385         movne   xh, #0
386         movne   xl, #0
387         RETLDM  "r4, r5" ne
389         @ Result is x + x = 2x.
390         movs    ip, r4, lsr #21
391         bne     2f
392         movs    xl, xl, lsl #1
393         adcs    xh, xh, xh
394         do_it   cs
395         orrcs   xh, xh, #0x80000000
396         RETLDM  "r4, r5"
397 2:      adds    r4, r4, #(2 << 21)
398         do_it   cc, t
399         addcc   xh, xh, #(1 << 20)
400         RETLDM  "r4, r5" cc
401         and     r5, xh, #0x80000000
403         @ Overflow: return INF.
404 LSYM(Lad_o):
405         orr     xh, r5, #0x7f000000
406         orr     xh, xh, #0x00f00000
407         mov     xl, #0
408         RETLDM  "r4, r5"
410         @ At least one of x or y is INF/NAN.
411         @   if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
412         @   if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
413         @   if either is NAN: return NAN
414         @   if opposite sign: return NAN
415         @   otherwise return xh-xl (which is INF or -INF)
416 LSYM(Lad_i):
417         mvns    ip, r4, asr #21
418         do_it   ne, te
419         movne   xh, yh
420         movne   xl, yl
421         COND(mvn,s,eq)  ip, r5, asr #21
422         do_it   ne, t
423         movne   yh, xh
424         movne   yl, xl
425         orrs    r4, xl, xh, lsl #12
426         do_it   eq, te
427         COND(orr,s,eq)  r5, yl, yh, lsl #12
428         teqeq   xh, yh
429         orrne   xh, xh, #0x00080000     @ quiet NAN
430         RETLDM  "r4, r5"
432         CFI_END_FUNCTION
433         FUNC_END aeabi_dsub
434         FUNC_END subdf3
435         FUNC_END aeabi_dadd
436         FUNC_END adddf3
438 ARM_FUNC_START floatunsidf
439 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
440         CFI_START_FUNCTION
442         teq     r0, #0
443         do_it   eq, t
444         moveq   r1, #0
445         RETc(eq)
447         do_push {r4, r5, lr}        @ sp -= 12
448         .cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
449         .cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
450         .cfi_rel_offset r5, 4
451         .cfi_rel_offset lr, 8
453         mov     r4, #0x400              @ initial exponent
454         add     r4, r4, #(52-1 - 1)
455         mov     r5, #0                  @ sign bit is 0
456         .ifnc   xl, r0
457         mov     xl, r0
458         .endif
459         mov     xh, #0
460         b       LSYM(Lad_l)
462         CFI_END_FUNCTION
463         FUNC_END aeabi_ui2d
464         FUNC_END floatunsidf
466 ARM_FUNC_START floatsidf
467 ARM_FUNC_ALIAS aeabi_i2d floatsidf
468         CFI_START_FUNCTION
470         teq     r0, #0
471         do_it   eq, t
472         moveq   r1, #0
473         RETc(eq)
475         do_push {r4, r5, lr}        @ sp -= 12
476         .cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
477         .cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
478         .cfi_rel_offset r5, 4
479         .cfi_rel_offset lr, 8
481         mov     r4, #0x400              @ initial exponent
482         add     r4, r4, #(52-1 - 1)
483         ands    r5, r0, #0x80000000     @ sign bit in r5
484         do_it   mi
485         rsbmi   r0, r0, #0              @ absolute value
486         .ifnc   xl, r0
487         mov     xl, r0
488         .endif
489         mov     xh, #0
490         b       LSYM(Lad_l)
492         CFI_END_FUNCTION
493         FUNC_END aeabi_i2d
494         FUNC_END floatsidf
496 ARM_FUNC_START extendsfdf2
497 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
498         CFI_START_FUNCTION
500         movs    r2, r0, lsl #1          @ toss sign bit
501         mov     xh, r2, asr #3          @ stretch exponent
502         mov     xh, xh, rrx             @ retrieve sign bit
503         mov     xl, r2, lsl #28         @ retrieve remaining bits
504         do_it   ne, ttt
505         COND(and,s,ne)  r3, r2, #0xff000000     @ isolate exponent
506         teqne   r3, #0xff000000         @ if not 0, check if INF or NAN
507         eorne   xh, xh, #0x38000000     @ fixup exponent otherwise.
508         RETc(ne)                        @ and return it.
510         bics    r2, r2, #0xff000000     @ isolate mantissa
511         do_it   eq                      @ if 0, that is ZERO or INF,
512         RETc(eq)                        @ we are done already.
514         teq     r3, #0xff000000         @ check for NAN
515         do_it   eq, t
516         orreq   xh, xh, #0x00080000     @ change to quiet NAN
517         RETc(eq)                        @ and return it.
519         @ value was denormalized.  We can normalize it now.
520         do_push {r4, r5, lr}
521         .cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
522         .cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
523         .cfi_rel_offset r5, 4
524         .cfi_rel_offset lr, 8
526         mov     r4, #0x380              @ setup corresponding exponent
527         and     r5, xh, #0x80000000     @ move sign bit in r5
528         bic     xh, xh, #0x80000000
529         b       LSYM(Lad_l)
531         CFI_END_FUNCTION
532         FUNC_END aeabi_f2d
533         FUNC_END extendsfdf2
535 ARM_FUNC_START floatundidf
536 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
537         CFI_START_FUNCTION
538         .cfi_remember_state        @ Save the current CFA state.
540         orrs    r2, r0, r1
541         do_it   eq
542         RETc(eq)
544         do_push {r4, r5, lr}       @ sp -= 12
545         .cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
546         .cfi_rel_offset r4, 0      @ Registers are saved from sp + 0 to sp + 8
547         .cfi_rel_offset r5, 4
548         .cfi_rel_offset lr, 8
550         mov     r5, #0
551         b       2f
553 ARM_FUNC_START floatdidf
554 ARM_FUNC_ALIAS aeabi_l2d floatdidf
555         .cfi_restore_state
556         @ Restore the CFI state we saved above. If we didn't do this then the
557         @ following instructions would have the CFI state that was set by the
558         @ offset adjustments made in floatundidf.
560         orrs    r2, r0, r1
561         do_it   eq
562         RETc(eq)
564         do_push {r4, r5, lr}       @ sp -= 12
565         .cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
566         .cfi_rel_offset r4, 0      @ Registers are saved from sp to sp + 8
567         .cfi_rel_offset r5, 4
568         .cfi_rel_offset lr, 8
570         ands    r5, ah, #0x80000000     @ sign bit in r5
571         bpl     2f
572 #if defined(__thumb2__)
573         negs    al, al
574         sbc     ah, ah, ah, lsl #1
575 #else
576         rsbs    al, al, #0
577         rsc     ah, ah, #0
578 #endif
580         mov     r4, #0x400              @ initial exponent
581         add     r4, r4, #(52-1 - 1)
583         @ If FP word order does not match integer word order, swap the words.
584         .ifnc   xh, ah
585         mov     ip, al
586         mov     xh, ah
587         mov     xl, ip
588         .endif
590         movs    ip, xh, lsr #22
591         beq     LSYM(Lad_p)
593         @ The value is too big.  Scale it down a bit...
594         mov     r2, #3
595         movs    ip, ip, lsr #3
596         do_it   ne
597         addne   r2, r2, #3
598         movs    ip, ip, lsr #3
599         do_it   ne
600         addne   r2, r2, #3
601         add     r2, r2, ip, lsr #3
603         rsb     r3, r2, #32
604         shift1  lsl, ip, xl, r3
605         shift1  lsr, xl, xl, r2
606         shiftop orr xl xl xh lsl r3 lr
607         shift1  lsr, xh, xh, r2
608         add     r4, r4, r2
609         b       LSYM(Lad_p)
611         CFI_END_FUNCTION
612         FUNC_END floatdidf
613         FUNC_END aeabi_l2d
614         FUNC_END floatundidf
615         FUNC_END aeabi_ul2d
617 #endif /* L_addsubdf3 */
619 #ifdef L_arm_muldivdf3
621 ARM_FUNC_START muldf3
622 ARM_FUNC_ALIAS aeabi_dmul muldf3
623         CFI_START_FUNCTION
625         do_push {r4, r5, r6, lr}    @ sp -= 16
626         .cfi_adjust_cfa_offset 16   @ CFA is now sp + previousOffset + 16
627         .cfi_rel_offset r4, 0       @ Registers are saved from sp to sp + 12.
628         .cfi_rel_offset r5, 4
629         .cfi_rel_offset r6, 8
630         .cfi_rel_offset lr, 12
632         @ Mask out exponents, trap any zero/denormal/INF/NAN.
633         mov     ip, #0xff
634         orr     ip, ip, #0x700
635         ands    r4, ip, xh, lsr #20
636         do_it   ne, tte
637         COND(and,s,ne)  r5, ip, yh, lsr #20
638         teqne   r4, ip
639         teqne   r5, ip
640         bleq    LSYM(Lml_s)
642         @ Add exponents together
643         add     r4, r4, r5
645         @ Determine final sign.
646         eor     r6, xh, yh
648         @ Convert mantissa to unsigned integer.
649         @ If power of two, branch to a separate path.
650         bic     xh, xh, ip, lsl #21
651         bic     yh, yh, ip, lsl #21
652         orrs    r5, xl, xh, lsl #12
653         do_it   ne
654         COND(orr,s,ne)  r5, yl, yh, lsl #12
655         orr     xh, xh, #0x00100000
656         orr     yh, yh, #0x00100000
657         beq     LSYM(Lml_1)
659 #if __ARM_ARCH__ < 4
661         @ Put sign bit in r6, which will be restored in yl later.
662         and   r6, r6, #0x80000000
664         @ Well, no way to make it shorter without the umull instruction.
665         stmfd   sp!, {r6, r7, r8, r9, sl, fp}   @ sp -= 24
666         .cfi_remember_state         @ Save the current CFI state.
667         .cfi_adjust_cfa_offset 24   @ CFA is now sp + previousOffset + 24.
668         .cfi_rel_offset r6, 0       @ Registers are saved from sp to sp + 20.
669         .cfi_rel_offset r7, 4
670         .cfi_rel_offset r8, 8
671         .cfi_rel_offset r9, 12
672         .cfi_rel_offset sl, 16
673         .cfi_rel_offset fp, 20
675         mov     r7, xl, lsr #16
676         mov     r8, yl, lsr #16
677         mov     r9, xh, lsr #16
678         mov     sl, yh, lsr #16
679         bic     xl, xl, r7, lsl #16
680         bic     yl, yl, r8, lsl #16
681         bic     xh, xh, r9, lsl #16
682         bic     yh, yh, sl, lsl #16
683         mul     ip, xl, yl
684         mul     fp, xl, r8
685         mov     lr, #0
686         adds    ip, ip, fp, lsl #16
687         adc     lr, lr, fp, lsr #16
688         mul     fp, r7, yl
689         adds    ip, ip, fp, lsl #16
690         adc     lr, lr, fp, lsr #16
691         mul     fp, xl, sl
692         mov     r5, #0
693         adds    lr, lr, fp, lsl #16
694         adc     r5, r5, fp, lsr #16
695         mul     fp, r7, yh
696         adds    lr, lr, fp, lsl #16
697         adc     r5, r5, fp, lsr #16
698         mul     fp, xh, r8
699         adds    lr, lr, fp, lsl #16
700         adc     r5, r5, fp, lsr #16
701         mul     fp, r9, yl
702         adds    lr, lr, fp, lsl #16
703         adc     r5, r5, fp, lsr #16
704         mul     fp, xh, sl
705         mul     r6, r9, sl
706         adds    r5, r5, fp, lsl #16
707         adc     r6, r6, fp, lsr #16
708         mul     fp, r9, yh
709         adds    r5, r5, fp, lsl #16
710         adc     r6, r6, fp, lsr #16
711         mul     fp, xl, yh
712         adds    lr, lr, fp
713         mul     fp, r7, sl
714         adcs    r5, r5, fp
715         mul     fp, xh, yl
716         adc     r6, r6, #0
717         adds    lr, lr, fp
718         mul     fp, r9, r8
719         adcs    r5, r5, fp
720         mul     fp, r7, r8
721         adc     r6, r6, #0
722         adds    lr, lr, fp
723         mul     fp, xh, yh
724         adcs    r5, r5, fp
725         adc     r6, r6, #0
726         ldmfd   sp!, {yl, r7, r8, r9, sl, fp}   @ sp += 24
727         .cfi_restore_state   @ Restore the previous CFI state.
728 #else
730         @ Here is the actual multiplication.
731         umull   ip, lr, xl, yl
732         mov     r5, #0
733         umlal   lr, r5, xh, yl
734         and     yl, r6, #0x80000000
735         umlal   lr, r5, xl, yh
736         mov     r6, #0
737         umlal   r5, r6, xh, yh
739 #endif
741         @ The LSBs in ip are only significant for the final rounding.
742         @ Fold them into lr.
743         teq     ip, #0
744         do_it   ne
745         orrne   lr, lr, #1
747         @ Adjust result upon the MSB position.
748         sub     r4, r4, #0xff
749         cmp     r6, #(1 << (20-11))
750         sbc     r4, r4, #0x300
751         bcs     1f
752         movs    lr, lr, lsl #1
753         adcs    r5, r5, r5
754         adc     r6, r6, r6
756         @ Shift to final position, add sign to result.
757         orr     xh, yl, r6, lsl #11
758         orr     xh, xh, r5, lsr #21
759         mov     xl, r5, lsl #11
760         orr     xl, xl, lr, lsr #21
761         mov     lr, lr, lsl #11
763         @ Check exponent range for under/overflow.
764         subs    ip, r4, #(254 - 1)
765         do_it   hi
766         cmphi   ip, #0x700
767         bhi     LSYM(Lml_u)
769         @ Round the result, merge final exponent.
770         cmp     lr, #0x80000000
771         do_it   eq
772         COND(mov,s,eq)  lr, xl, lsr #1
773         adcs    xl, xl, #0
774         adc     xh, xh, r4, lsl #20
775         RETLDM  "r4, r5, r6"
777         @ Multiplication by 0x1p*: let''s shortcut a lot of code.
778 LSYM(Lml_1):
779         and     r6, r6, #0x80000000
780         orr     xh, r6, xh
781         orr     xl, xl, yl
782         eor     xh, xh, yh
783         subs    r4, r4, ip, lsr #1
784         do_it   gt, tt
785         COND(rsb,s,gt)  r5, r4, ip
786         orrgt   xh, xh, r4, lsl #20
787         RETLDM  "r4, r5, r6" gt
789         @ Under/overflow: fix things up for the code below.
790         orr     xh, xh, #0x00100000
791         mov     lr, #0
792         subs    r4, r4, #1
793 LSYM(Lml_u):
794         @ Overflow?
795         bgt     LSYM(Lml_o)
797         @ Check if denormalized result is possible, otherwise return signed 0.
798         cmn     r4, #(53 + 1)
799         do_it   le, tt
800         movle   xl, #0
801         bicle   xh, xh, #0x7fffffff
802         RETLDM  "r4, r5, r6" le
804         @ Find out proper shift value.
805         rsb     r4, r4, #0
806         subs    r4, r4, #32
807         bge     2f
808         adds    r4, r4, #12
809         bgt     1f
811         @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
812         add     r4, r4, #20
813         rsb     r5, r4, #32
814         shift1  lsl, r3, xl, r5
815         shift1  lsr, xl, xl, r4
816         shiftop orr xl xl xh lsl r5 r2
817         and     r2, xh, #0x80000000
818         bic     xh, xh, #0x80000000
819         adds    xl, xl, r3, lsr #31
820         shiftop adc xh r2 xh lsr r4 r6
821         orrs    lr, lr, r3, lsl #1
822         do_it   eq
823         biceq   xl, xl, r3, lsr #31
824         RETLDM  "r4, r5, r6"
826         @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
827         @ a register switch from xh to xl. Then round.
828 1:      rsb     r4, r4, #12
829         rsb     r5, r4, #32
830         shift1  lsl, r3, xl, r4
831         shift1  lsr, xl, xl, r5
832         shiftop orr xl xl xh lsl r4 r2
833         bic     xh, xh, #0x7fffffff
834         adds    xl, xl, r3, lsr #31
835         adc     xh, xh, #0
836         orrs    lr, lr, r3, lsl #1
837         do_it   eq
838         biceq   xl, xl, r3, lsr #31
839         RETLDM  "r4, r5, r6"
841         @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
842         @ from xh to xl.  Leftover bits are in r3-r6-lr for rounding.
843 2:      rsb     r5, r4, #32
844         shiftop orr lr lr xl lsl r5 r2
845         shift1  lsr, r3, xl, r4
846         shiftop orr r3 r3 xh lsl r5 r2
847         shift1  lsr, xl, xh, r4
848         bic     xh, xh, #0x7fffffff
849         shiftop bic xl xl xh lsr r4 r2
850         add     xl, xl, r3, lsr #31
851         orrs    lr, lr, r3, lsl #1
852         do_it   eq
853         biceq   xl, xl, r3, lsr #31
854         RETLDM  "r4, r5, r6"
856         @ One or both arguments are denormalized.
857         @ Scale them leftwards and preserve sign bit.
858 LSYM(Lml_d):
859         teq     r4, #0
860         bne     2f
861         and     r6, xh, #0x80000000
862 1:      movs    xl, xl, lsl #1
863         adc     xh, xh, xh
864         tst     xh, #0x00100000
865         do_it   eq
866         subeq   r4, r4, #1
867         beq     1b
868         orr     xh, xh, r6
869         teq     r5, #0
870         do_it   ne
871         RETc(ne)
872 2:      and     r6, yh, #0x80000000
873 3:      movs    yl, yl, lsl #1
874         adc     yh, yh, yh
875         tst     yh, #0x00100000
876         do_it   eq
877         subeq   r5, r5, #1
878         beq     3b
879         orr     yh, yh, r6
880         RET
882 LSYM(Lml_s):
883         @ Isolate the INF and NAN cases away
884         teq     r4, ip
885         and     r5, ip, yh, lsr #20
886         do_it   ne
887         teqne   r5, ip
888         beq     1f
890         @ Here, one or more arguments are either denormalized or zero.
891         orrs    r6, xl, xh, lsl #1
892         do_it   ne
893         COND(orr,s,ne)  r6, yl, yh, lsl #1
894         bne     LSYM(Lml_d)
896         @ Result is 0, but determine sign anyway.
897 LSYM(Lml_z):
898         eor     xh, xh, yh
899         and     xh, xh, #0x80000000
900         mov     xl, #0
901         RETLDM  "r4, r5, r6"
903 1:      @ One or both args are INF or NAN.
904         orrs    r6, xl, xh, lsl #1
905         do_it   eq, te
906         moveq   xl, yl
907         moveq   xh, yh
908         COND(orr,s,ne)  r6, yl, yh, lsl #1
909         beq     LSYM(Lml_n)             @ 0 * INF or INF * 0 -> NAN
910         teq     r4, ip
911         bne     1f
912         orrs    r6, xl, xh, lsl #12
913         bne     LSYM(Lml_n)             @ NAN * <anything> -> NAN
914 1:      teq     r5, ip
915         bne     LSYM(Lml_i)
916         orrs    r6, yl, yh, lsl #12
917         do_it   ne, t
918         movne   xl, yl
919         movne   xh, yh
920         bne     LSYM(Lml_n)             @ <anything> * NAN -> NAN
922         @ Result is INF, but we need to determine its sign.
923 LSYM(Lml_i):
924         eor     xh, xh, yh
926         @ Overflow: return INF (sign already in xh).
927 LSYM(Lml_o):
928         and     xh, xh, #0x80000000
929         orr     xh, xh, #0x7f000000
930         orr     xh, xh, #0x00f00000
931         mov     xl, #0
932         RETLDM  "r4, r5, r6"
934         @ Return a quiet NAN.
935 LSYM(Lml_n):
936         orr     xh, xh, #0x7f000000
937         orr     xh, xh, #0x00f80000
938         RETLDM  "r4, r5, r6"
940         CFI_END_FUNCTION
941         FUNC_END aeabi_dmul
942         FUNC_END muldf3
944 ARM_FUNC_START divdf3
945 ARM_FUNC_ALIAS aeabi_ddiv divdf3
946         CFI_START_FUNCTION
947         
948         do_push {r4, r5, r6, lr}
949         .cfi_adjust_cfa_offset 16
950         .cfi_rel_offset r4, 0
951         .cfi_rel_offset r5, 4
952         .cfi_rel_offset r6, 8
953         .cfi_rel_offset lr, 12
955         @ Mask out exponents, trap any zero/denormal/INF/NAN.
956         mov     ip, #0xff
957         orr     ip, ip, #0x700
958         ands    r4, ip, xh, lsr #20
959         do_it   ne, tte
960         COND(and,s,ne)  r5, ip, yh, lsr #20
961         teqne   r4, ip
962         teqne   r5, ip
963         bleq    LSYM(Ldv_s)
965         @ Subtract divisor exponent from dividend''s.
966         sub     r4, r4, r5
968         @ Preserve final sign into lr.
969         eor     lr, xh, yh
971         @ Convert mantissa to unsigned integer.
972         @ Dividend -> r5-r6, divisor -> yh-yl.
973         orrs    r5, yl, yh, lsl #12
974         mov     xh, xh, lsl #12
975         beq     LSYM(Ldv_1)
976         mov     yh, yh, lsl #12
977         mov     r5, #0x10000000
978         orr     yh, r5, yh, lsr #4
979         orr     yh, yh, yl, lsr #24
980         mov     yl, yl, lsl #8
981         orr     r5, r5, xh, lsr #4
982         orr     r5, r5, xl, lsr #24
983         mov     r6, xl, lsl #8
985         @ Initialize xh with final sign bit.
986         and     xh, lr, #0x80000000
988         @ Ensure result will land to known bit position.
989         @ Apply exponent bias accordingly.
990         cmp     r5, yh
991         do_it   eq
992         cmpeq   r6, yl
993         adc     r4, r4, #(255 - 2)
994         add     r4, r4, #0x300
995         bcs     1f
996         movs    yh, yh, lsr #1
997         mov     yl, yl, rrx
999         @ Perform first subtraction to align result to a nibble.
1000         subs    r6, r6, yl
1001         sbc     r5, r5, yh
1002         movs    yh, yh, lsr #1
1003         mov     yl, yl, rrx
1004         mov     xl, #0x00100000
1005         mov     ip, #0x00080000
1007         @ The actual division loop.
1008 1:      subs    lr, r6, yl
1009         sbcs    lr, r5, yh
1010         do_it   cs, tt
1011         subcs   r6, r6, yl
1012         movcs   r5, lr
1013         orrcs   xl, xl, ip
1014         movs    yh, yh, lsr #1
1015         mov     yl, yl, rrx
1016         subs    lr, r6, yl
1017         sbcs    lr, r5, yh
1018         do_it   cs, tt
1019         subcs   r6, r6, yl
1020         movcs   r5, lr
1021         orrcs   xl, xl, ip, lsr #1
1022         movs    yh, yh, lsr #1
1023         mov     yl, yl, rrx
1024         subs    lr, r6, yl
1025         sbcs    lr, r5, yh
1026         do_it   cs, tt
1027         subcs   r6, r6, yl
1028         movcs   r5, lr
1029         orrcs   xl, xl, ip, lsr #2
1030         movs    yh, yh, lsr #1
1031         mov     yl, yl, rrx
1032         subs    lr, r6, yl
1033         sbcs    lr, r5, yh
1034         do_it   cs, tt
1035         subcs   r6, r6, yl
1036         movcs   r5, lr
1037         orrcs   xl, xl, ip, lsr #3
1039         orrs    lr, r5, r6
1040         beq     2f
1041         mov     r5, r5, lsl #4
1042         orr     r5, r5, r6, lsr #28
1043         mov     r6, r6, lsl #4
1044         mov     yh, yh, lsl #3
1045         orr     yh, yh, yl, lsr #29
1046         mov     yl, yl, lsl #3
1047         movs    ip, ip, lsr #4
1048         bne     1b
1050         @ We are done with a word of the result.
1051         @ Loop again for the low word if this pass was for the high word.
1052         tst     xh, #0x00100000
1053         bne     3f
1054         orr     xh, xh, xl
1055         mov     xl, #0
1056         mov     ip, #0x80000000
1057         b       1b
1059         @ Be sure result starts in the high word.
1060         tst     xh, #0x00100000
1061         do_it   eq, t
1062         orreq   xh, xh, xl
1063         moveq   xl, #0
1065         @ Check exponent range for under/overflow.
1066         subs    ip, r4, #(254 - 1)
1067         do_it   hi
1068         cmphi   ip, #0x700
1069         bhi     LSYM(Lml_u)
1071         @ Round the result, merge final exponent.
1072         subs    ip, r5, yh
1073         do_it   eq, t
1074         COND(sub,s,eq)  ip, r6, yl
1075         COND(mov,s,eq)  ip, xl, lsr #1
1076         adcs    xl, xl, #0
1077         adc     xh, xh, r4, lsl #20
1078         RETLDM  "r4, r5, r6"
1080         @ Division by 0x1p*: shortcut a lot of code.
1081 LSYM(Ldv_1):
1082         and     lr, lr, #0x80000000
1083         orr     xh, lr, xh, lsr #12
1084         adds    r4, r4, ip, lsr #1
1085         do_it   gt, tt
1086         COND(rsb,s,gt)  r5, r4, ip
1087         orrgt   xh, xh, r4, lsl #20
1088         RETLDM  "r4, r5, r6" gt
1090         orr     xh, xh, #0x00100000
1091         mov     lr, #0
1092         subs    r4, r4, #1
1093         b       LSYM(Lml_u)
1095         @ Result mightt need to be denormalized: put remainder bits
1096         @ in lr for rounding considerations.
1097 LSYM(Ldv_u):
1098         orr     lr, r5, r6
1099         b       LSYM(Lml_u)
1101         @ One or both arguments is either INF, NAN or zero.
1102 LSYM(Ldv_s):
1103         and     r5, ip, yh, lsr #20
1104         teq     r4, ip
1105         do_it   eq
1106         teqeq   r5, ip
1107         beq     LSYM(Lml_n)             @ INF/NAN / INF/NAN -> NAN
1108         teq     r4, ip
1109         bne     1f
1110         orrs    r4, xl, xh, lsl #12
1111         bne     LSYM(Lml_n)             @ NAN / <anything> -> NAN
1112         teq     r5, ip
1113         bne     LSYM(Lml_i)             @ INF / <anything> -> INF
1114         mov     xl, yl
1115         mov     xh, yh
1116         b       LSYM(Lml_n)             @ INF / (INF or NAN) -> NAN
1117 1:      teq     r5, ip
1118         bne     2f
1119         orrs    r5, yl, yh, lsl #12
1120         beq     LSYM(Lml_z)             @ <anything> / INF -> 0
1121         mov     xl, yl
1122         mov     xh, yh
1123         b       LSYM(Lml_n)             @ <anything> / NAN -> NAN
1124 2:      @ If both are nonzero, we need to normalize and resume above.
1125         orrs    r6, xl, xh, lsl #1
1126         do_it   ne
1127         COND(orr,s,ne)  r6, yl, yh, lsl #1
1128         bne     LSYM(Lml_d)
1129         @ One or both arguments are 0.
1130         orrs    r4, xl, xh, lsl #1
1131         bne     LSYM(Lml_i)             @ <non_zero> / 0 -> INF
1132         orrs    r5, yl, yh, lsl #1
1133         bne     LSYM(Lml_z)             @ 0 / <non_zero> -> 0
1134         b       LSYM(Lml_n)             @ 0 / 0 -> NAN
1136         CFI_END_FUNCTION
1137         FUNC_END aeabi_ddiv
1138         FUNC_END divdf3
1140 #endif /* L_muldivdf3 */
1142 #ifdef L_arm_cmpdf2
1144 @ Note: only r0 (return value) and ip are clobbered here.
1146 ARM_FUNC_START gtdf2
1147 ARM_FUNC_ALIAS gedf2 gtdf2
1148         CFI_START_FUNCTION
1149         mov     ip, #-1
1150         b       1f
1152 ARM_FUNC_START ltdf2
1153 ARM_FUNC_ALIAS ledf2 ltdf2
1154         mov     ip, #1
1155         b       1f
1157 ARM_FUNC_START cmpdf2
1158 ARM_FUNC_ALIAS nedf2 cmpdf2
1159 ARM_FUNC_ALIAS eqdf2 cmpdf2
1160         mov     ip, #1                  @ how should we specify unordered here?
1162 1:      str     ip, [sp, #-4]!
1163         .cfi_adjust_cfa_offset 4        @ CFA is now sp + previousOffset + 4.
1164         @ We're not adding CFI for ip as it's pushed into the stack
1165         @ only because it may be popped off later as a return value
1166         @ (i.e. we're not preserving it anyways).
1168         @ Trap any INF/NAN first.
1169         mov     ip, xh, lsl #1
1170         mvns    ip, ip, asr #21
1171         mov     ip, yh, lsl #1
1172         do_it   ne
1173         COND(mvn,s,ne)  ip, ip, asr #21
1174         beq     3f
1175         .cfi_remember_state
1176         @ Save the current CFI state.  This is done because the branch
1177         @ is conditional, and if we don't take it we'll issue a
1178         @ .cfi_adjust_cfa_offset and return.  If we do take it,
1179         @ however, the .cfi_adjust_cfa_offset from the non-branch code
1180         @ will affect the branch code as well.  To avoid this we'll
1181         @ restore the current state before executing the branch code.
1183         @ Test for equality.  Note that 0.0 is equal to -0.0.
1184 2:      add     sp, sp, #4
1185         .cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
1187         orrs    ip, xl, xh, lsl #1      @ if x == 0.0 or -0.0
1188         do_it   eq, e
1189         COND(orr,s,eq)  ip, yl, yh, lsl #1      @ and y == 0.0 or -0.0
1190         teqne   xh, yh                  @ or xh == yh
1191         do_it   eq, tt
1192         teqeq   xl, yl                  @ and xl == yl
1193         moveq   r0, #0                  @ then equal.
1194         RETc(eq)
1196         @ Clear C flag
1197         cmn     r0, #0
1199         @ Compare sign, 
1200         teq     xh, yh
1202         @ Compare values if same sign
1203         do_it   pl
1204         cmppl   xh, yh
1205         do_it   eq
1206         cmpeq   xl, yl
1208         @ Result:
1209         do_it   cs, e
1210         movcs   r0, yh, asr #31
1211         mvncc   r0, yh, asr #31
1212         orr     r0, r0, #1
1213         RET
1215 3:  @ Look for a NAN.
1217         @ Restore the previous CFI state (i.e. keep the CFI state as it was
1218         @ before the branch).
1219         .cfi_restore_state
1221         mov ip, xh, lsl #1
1222         mvns    ip, ip, asr #21
1223         bne     4f
1224         orrs    ip, xl, xh, lsl #12
1225         bne     5f                      @ x is NAN
1226 4:      mov     ip, yh, lsl #1
1227         mvns    ip, ip, asr #21
1228         bne     2b
1229         orrs    ip, yl, yh, lsl #12
1230         beq     2b                      @ y is not NAN
1232 5:      ldr     r0, [sp], #4            @ unordered return code
1233         .cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
1235         RET
1237         CFI_END_FUNCTION
1238         FUNC_END gedf2
1239         FUNC_END gtdf2
1240         FUNC_END ledf2
1241         FUNC_END ltdf2
1242         FUNC_END nedf2
1243         FUNC_END eqdf2
1244         FUNC_END cmpdf2
1246 ARM_FUNC_START aeabi_cdrcmple
1247         CFI_START_FUNCTION
1249         mov     ip, r0
1250         mov     r0, r2
1251         mov     r2, ip
1252         mov     ip, r1
1253         mov     r1, r3
1254         mov     r3, ip
1255         b       6f
1257 ARM_FUNC_START aeabi_cdcmpeq
1258 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1260         @ The status-returning routines are required to preserve all
1261         @ registers except ip, lr, and cpsr.
1262 6:      do_push {r0, lr}
1263         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8.
1264         .cfi_rel_offset r0, 0     @ Previous r0 is saved at sp.
1265         .cfi_rel_offset lr, 4     @ Previous lr is saved at sp + 4.
1267         ARM_CALL cmpdf2
1268         @ Set the Z flag correctly, and the C flag unconditionally.
1269         cmp     r0, #0
1270         @ Clear the C flag if the return value was -1, indicating
1271         @ that the first operand was smaller than the second.
1272         do_it   mi
1273         cmnmi   r0, #0
1275         RETLDM  "r0"
1277         CFI_END_FUNCTION
1278         FUNC_END aeabi_cdcmple
1279         FUNC_END aeabi_cdcmpeq
1280         FUNC_END aeabi_cdrcmple
1281         
1282 ARM_FUNC_START  aeabi_dcmpeq
1283         CFI_START_FUNCTION
1285         str lr, [sp, #-8]!        @ sp -= 8
1286         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1287         .cfi_rel_offset lr, 0     @ lr is at sp
1289         ARM_CALL aeabi_cdcmple
1290         do_it   eq, e
1291         moveq   r0, #1  @ Equal to.
1292         movne   r0, #0  @ Less than, greater than, or unordered.
1294         RETLDM
1296         CFI_END_FUNCTION
1297         FUNC_END aeabi_dcmpeq
1299 ARM_FUNC_START  aeabi_dcmplt
1300         CFI_START_FUNCTION
1302         str lr, [sp, #-8]!        @ sp -= 8
1303         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1304         .cfi_rel_offset lr, 0     @ lr is at sp
1306         ARM_CALL aeabi_cdcmple
1307         do_it   cc, e
1308         movcc   r0, #1  @ Less than.
1309         movcs   r0, #0  @ Equal to, greater than, or unordered.
1310         RETLDM
1312         CFI_END_FUNCTION
1313         FUNC_END aeabi_dcmplt
1315 ARM_FUNC_START  aeabi_dcmple
1316         CFI_START_FUNCTION
1318         str lr, [sp, #-8]!        @ sp -= 8
1319         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1320         .cfi_rel_offset lr, 0     @ lr is at sp
1322         ARM_CALL aeabi_cdcmple
1323         do_it   ls, e
1324         movls   r0, #1  @ Less than or equal to.
1325         movhi   r0, #0  @ Greater than or unordered.
1326         RETLDM
1328         CFI_END_FUNCTION
1329         FUNC_END aeabi_dcmple
1331 ARM_FUNC_START  aeabi_dcmpge
1332         CFI_START_FUNCTION
1334         str lr, [sp, #-8]!        @ sp -= 8
1335         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1336         .cfi_rel_offset lr, 0     @ lr is at sp
1338         ARM_CALL aeabi_cdrcmple
1339         do_it   ls, e
1340         movls   r0, #1  @ Operand 2 is less than or equal to operand 1.
1341         movhi   r0, #0  @ Operand 2 greater than operand 1, or unordered.
1342         RETLDM
1344         CFI_END_FUNCTION
1345         FUNC_END aeabi_dcmpge
1347 ARM_FUNC_START  aeabi_dcmpgt
1348         CFI_START_FUNCTION
1350         str lr, [sp, #-8]!        @ sp -= 8
1351         .cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1352         .cfi_rel_offset lr, 0     @ lr is at sp
1354         ARM_CALL aeabi_cdrcmple
1355         do_it   cc, e
1356         movcc   r0, #1  @ Operand 2 is less than operand 1.
1357         movcs   r0, #0  @ Operand 2 is greater than or equal to operand 1,
1358                         @ or they are unordered.
1359         RETLDM
1361         CFI_END_FUNCTION
1362         FUNC_END aeabi_dcmpgt
1364 #endif /* L_cmpdf2 */
1366 #ifdef L_arm_unorddf2
1368 ARM_FUNC_START unorddf2
1369 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1370         .cfi_startproc
1372         mov     ip, xh, lsl #1
1373         mvns    ip, ip, asr #21
1374         bne     1f
1375         orrs    ip, xl, xh, lsl #12
1376         bne     3f                      @ x is NAN
1377 1:      mov     ip, yh, lsl #1
1378         mvns    ip, ip, asr #21
1379         bne     2f
1380         orrs    ip, yl, yh, lsl #12
1381         bne     3f                      @ y is NAN
1382 2:      mov     r0, #0                  @ arguments are ordered.
1383         RET
1385 3:      mov     r0, #1                  @ arguments are unordered.
1386         RET
1388         .cfi_endproc
1389         FUNC_END aeabi_dcmpun
1390         FUNC_END unorddf2
1392 #endif /* L_unorddf2 */
1394 #ifdef L_arm_fixdfsi
1396 ARM_FUNC_START fixdfsi
1397 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1398         CFI_START_FUNCTION
1400         @ check exponent range.
1401         mov     r2, xh, lsl #1
1402         adds    r2, r2, #(1 << 21)
1403         bcs     2f                      @ value is INF or NAN
1404         bpl     1f                      @ value is too small
1405         mov     r3, #(0xfffffc00 + 31)
1406         subs    r2, r3, r2, asr #21
1407         bls     3f                      @ value is too large
1409         @ scale value
1410         mov     r3, xh, lsl #11
1411         orr     r3, r3, #0x80000000
1412         orr     r3, r3, xl, lsr #21
1413         tst     xh, #0x80000000         @ the sign bit
1414         shift1  lsr, r0, r3, r2
1415         do_it   ne
1416         rsbne   r0, r0, #0
1417         RET
1419 1:      mov     r0, #0
1420         RET
1422 2:      orrs    xl, xl, xh, lsl #12
1423         bne     4f                      @ x is NAN.
1424 3:      ands    r0, xh, #0x80000000     @ the sign bit
1425         do_it   eq
1426         moveq   r0, #0x7fffffff         @ maximum signed positive si
1427         RET
1429 4:      mov     r0, #0                  @ How should we convert NAN?
1430         RET
1432         CFI_END_FUNCTION
1433         FUNC_END aeabi_d2iz
1434         FUNC_END fixdfsi
1436 #endif /* L_fixdfsi */
1438 #ifdef L_arm_fixunsdfsi
1440 ARM_FUNC_START fixunsdfsi
1441 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1442         CFI_START_FUNCTION
1444         @ check exponent range.
1445         movs    r2, xh, lsl #1
1446         bcs     1f                      @ value is negative
1447         adds    r2, r2, #(1 << 21)
1448         bcs     2f                      @ value is INF or NAN
1449         bpl     1f                      @ value is too small
1450         mov     r3, #(0xfffffc00 + 31)
1451         subs    r2, r3, r2, asr #21
1452         bmi     3f                      @ value is too large
1454         @ scale value
1455         mov     r3, xh, lsl #11
1456         orr     r3, r3, #0x80000000
1457         orr     r3, r3, xl, lsr #21
1458         shift1  lsr, r0, r3, r2
1459         RET
1461 1:      mov     r0, #0
1462         RET
1464 2:      orrs    xl, xl, xh, lsl #12
1465         bne     4f                      @ value is NAN.
1466 3:      mov     r0, #0xffffffff         @ maximum unsigned si
1467         RET
1469 4:      mov     r0, #0                  @ How should we convert NAN?
1470         RET
1472         CFI_END_FUNCTION
1473         FUNC_END aeabi_d2uiz
1474         FUNC_END fixunsdfsi
1476 #endif /* L_fixunsdfsi */
1478 #ifdef L_arm_truncdfsf2
1480 ARM_FUNC_START truncdfsf2
1481 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1482         CFI_START_FUNCTION
1484         @ check exponent range.
1485         mov     r2, xh, lsl #1
1486         subs    r3, r2, #((1023 - 127) << 21)
1487         do_it   cs, t
1488         COND(sub,s,cs)  ip, r3, #(1 << 21)
1489         COND(rsb,s,cs)  ip, ip, #(254 << 21)
1490         bls     2f                      @ value is out of range
1492 1:      @ shift and round mantissa
1493         and     ip, xh, #0x80000000
1494         mov     r2, xl, lsl #3
1495         orr     xl, ip, xl, lsr #29
1496         cmp     r2, #0x80000000
1497         adc     r0, xl, r3, lsl #2
1498         do_it   eq
1499         biceq   r0, r0, #1
1500         RET
1502 2:      @ either overflow or underflow
1503         tst     xh, #0x40000000
1504         bne     3f                      @ overflow
1506         @ check if denormalized value is possible
1507         adds    r2, r3, #(23 << 21)
1508         do_it   lt, t
1509         andlt   r0, xh, #0x80000000     @ too small, return signed 0.
1510         RETc(lt)
1512         @ denormalize value so we can resume with the code above afterwards.
1513         orr     xh, xh, #0x00100000
1514         mov     r2, r2, lsr #21
1515         rsb     r2, r2, #24
1516         rsb     ip, r2, #32
1517 #if defined(__thumb2__)
1518         lsls    r3, xl, ip
1519 #else
1520         movs    r3, xl, lsl ip
1521 #endif
1522         shift1  lsr, xl, xl, r2
1523         do_it   ne
1524         orrne   xl, xl, #1              @ fold r3 for rounding considerations. 
1525         mov     r3, xh, lsl #11
1526         mov     r3, r3, lsr #11
1527         shiftop orr xl xl r3 lsl ip ip
1528         shift1  lsr, r3, r3, r2
1529         mov     r3, r3, lsl #1
1530         b       1b
1532 3:      @ chech for NAN
1533         mvns    r3, r2, asr #21
1534         bne     5f                      @ simple overflow
1535         orrs    r3, xl, xh, lsl #12
1536         do_it   ne, tt
1537         movne   r0, #0x7f000000
1538         orrne   r0, r0, #0x00c00000
1539         RETc(ne)                        @ return NAN
1541 5:      @ return INF with sign
1542         and     r0, xh, #0x80000000
1543         orr     r0, r0, #0x7f000000
1544         orr     r0, r0, #0x00800000
1545         RET
1547         CFI_END_FUNCTION
1548         FUNC_END aeabi_d2f
1549         FUNC_END truncdfsf2
1551 #endif /* L_truncdfsf2 */