1 /* ieee754-df.S double-precision floating point support for ARM
3 Copyright (C) 2003, 2004, 2005, 2007 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
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
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, 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301, USA. */
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 * For slightly simpler code please see the single precision version
38 * Only the default rounding mode is intended for best performances.
39 * Exceptions aren't supported yet, but that can be added quite easily
40 * if necessary without impacting performances.
44 @ For FPA, float words are always big-endian.
45 @ For VFP, floats words follow the memory system mode.
46 #if defined(__VFP_FP__) && !defined(__ARMEB__)
62 ARM_FUNC_ALIAS aeabi_dneg negdf2
65 eor xh, xh, #0x80000000
75 ARM_FUNC_START aeabi_drsub
77 eor xh, xh, #0x80000000 @ flip sign bit of first arg
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
89 ARM_FUNC_ALIAS aeabi_dadd adddf3
91 1: do_push {r4, r5, lr}
93 @ Look for zeroes, equal values, INF, or NAN.
94 shift1 lsl, r4, xh, #1
95 shift1 lsl, r5, yh, #1
100 COND(orr,s,ne) ip, r4, xl
101 COND(orr,s,ne) ip, r5, yl
102 COND(mvn,s,ne) ip, r4, asr #21
103 COND(mvn,s,ne) ip, r5, asr #21
106 @ Compute exponent difference. Make largest exponent in r4,
107 @ corresponding arg in xh-xl, and positive exponent difference in r5.
108 shift1 lsr, r4, r4, #21
109 rsbs r5, r4, r5, lsr #21
121 @ If exponent difference is too large, return largest argument
122 @ already in xh-xl. We need up to 54 bit to handle proper rounding
128 @ Convert mantissa to signed integer.
132 orr xh, ip, xh, lsr #12
134 #if defined(__thumb2__)
136 sbc xh, xh, xh, lsl #1
144 orr yh, ip, yh, lsr #12
146 #if defined(__thumb2__)
148 sbc yh, yh, yh, lsl #1
154 @ If exponent == difference, one or both args were denormalized.
155 @ Since this is not common case, rescale them off line.
160 @ Compensate for the exponent overlapping the mantissa MSB added later
163 @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
166 shift1 lsl, ip, yl, lr
167 shiftop adds xl xl yl lsr r5 yl
169 shiftop adds xl xl yh lsl lr yl
170 shiftop adcs xh xh yh asr r5 yh
175 shift1 lsl,ip, yh, lr
177 orrcs ip, ip, #2 @ 2 not 1, to allow lsr #1 later
178 shiftop adds xl xl yh asr r5 yh
179 adcs xh, xh, yh, asr #31
181 @ We now have a result in xh-xl-ip.
182 @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
183 and r5, xh, #0x80000000
185 #if defined(__thumb2__)
196 @ Determine how to normalize the result.
203 @ Result needs to be shifted right.
209 @ Make sure we did not bust our exponent.
214 @ Our result is now properly aligned into xh-xl, remaining bits in ip.
215 @ Round with MSB of ip. If halfway between two numbers, round towards
217 @ Pack final result together.
221 COND(mov,s,eq) ip, xl, lsr #1
223 adc xh, xh, r4, lsl #20
227 @ Result must be shifted left and exponent adjusted.
236 @ No rounding necessary since ip will always be 0 at this point.
248 movhs r2, r2, lsr #16
258 sublo r3, r3, r2, lsr #1
259 sub r3, r3, r2, lsr #3
274 @ determine how to shift the value.
280 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
281 @ since a register switch happened above.
284 shift1 lsl, xl, xh, ip
285 shift1 lsr, xh, xh, r2
288 @ actually shift value left 1 to 20 bits, which might also represent
289 @ 32 to 52 bits if counting the register switch that happened earlier.
293 shift1 lsl, xh, xh, r2
294 #if defined(__thumb2__)
300 orrle xh, xh, xl, lsr ip
304 @ adjust exponent accordingly.
307 addge xh, xh, r4, lsl #20
311 @ Exponent too small, denormalize result.
312 @ Find out proper shift value.
319 @ shift result right of 1 to 20 bits, sign is in r5.
322 shift1 lsr, xl, xl, r4
323 shiftop orr xl xl xh lsl r2 yh
324 shiftop orr xh r5 xh lsr r4 yh
327 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
328 @ a register switch from xh to xl.
331 shift1 lsr, xl, xl, r2
332 shiftop orr xl xl xh lsl r4 yh
336 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
338 2: shift1 lsr, xl, xh, r4
342 @ Adjust exponents for denormalized arguments.
343 @ Note that r4 must not remain equal to 0.
346 eor yh, yh, #0x00100000
348 eoreq xh, xh, #0x00100000
357 COND(mvn,s,ne) ip, r5, asr #21
365 @ Result is x + 0.0 = x or 0.0 + y = y.
374 @ Result is x - x = 0.
380 @ Result is x + x = 2x.
386 orrcs xh, xh, #0x80000000
388 2: adds r4, r4, #(2 << 21)
390 addcc xh, xh, #(1 << 20)
392 and r5, xh, #0x80000000
394 @ Overflow: return INF.
396 orr xh, r5, #0x7f000000
397 orr xh, xh, #0x00f00000
401 @ At least one of x or y is INF/NAN.
402 @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
403 @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
404 @ if either is NAN: return NAN
405 @ if opposite sign: return NAN
406 @ otherwise return xh-xl (which is INF or -INF)
412 COND(mvn,s,eq) ip, r5, asr #21
416 orrs r4, xl, xh, lsl #12
418 COND(orr,s,eq) r5, yl, yh, lsl #12
420 orrne xh, xh, #0x00080000 @ quiet NAN
428 ARM_FUNC_START floatunsidf
429 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
436 mov r4, #0x400 @ initial exponent
437 add r4, r4, #(52-1 - 1)
438 mov r5, #0 @ sign bit is 0
448 ARM_FUNC_START floatsidf
449 ARM_FUNC_ALIAS aeabi_i2d floatsidf
456 mov r4, #0x400 @ initial exponent
457 add r4, r4, #(52-1 - 1)
458 ands r5, r0, #0x80000000 @ sign bit in r5
460 rsbmi r0, r0, #0 @ absolute value
470 ARM_FUNC_START extendsfdf2
471 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
473 movs r2, r0, lsl #1 @ toss sign bit
474 mov xh, r2, asr #3 @ stretch exponent
475 mov xh, xh, rrx @ retrieve sign bit
476 mov xl, r2, lsl #28 @ retrieve remaining bits
478 COND(and,s,ne) r3, r2, #0xff000000 @ isolate exponent
479 teqne r3, #0xff000000 @ if not 0, check if INF or NAN
480 eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
481 RETc(ne) @ and return it.
483 teq r2, #0 @ if actually 0
485 teqne r3, #0xff000000 @ or INF or NAN
486 RETc(eq) @ we are done already.
488 @ value was denormalized. We can normalize it now.
490 mov r4, #0x380 @ setup corresponding exponent
491 and r5, xh, #0x80000000 @ move sign bit in r5
492 bic xh, xh, #0x80000000
498 ARM_FUNC_START floatundidf
499 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
502 #if !defined (__VFP_FP__) && !defined(__SOFTFP__)
510 #if !defined (__VFP_FP__) && !defined(__SOFTFP__)
511 @ For hard FPA code we want to return via the tail below so that
512 @ we can return the result in f0 as well as in r0/r1 for backwards
515 @ Push pc as well so that RETLDM works correctly.
516 do_push {r4, r5, ip, lr, pc}
524 ARM_FUNC_START floatdidf
525 ARM_FUNC_ALIAS aeabi_l2d floatdidf
528 #if !defined (__VFP_FP__) && !defined(__SOFTFP__)
536 #if !defined (__VFP_FP__) && !defined(__SOFTFP__)
537 @ For hard FPA code we want to return via the tail below so that
538 @ we can return the result in f0 as well as in r0/r1 for backwards
541 @ Push pc as well so that RETLDM works correctly.
542 do_push {r4, r5, ip, lr, pc}
547 ands r5, ah, #0x80000000 @ sign bit in r5
549 #if defined(__thumb2__)
551 sbc ah, ah, ah, lsl #1
557 mov r4, #0x400 @ initial exponent
558 add r4, r4, #(52-1 - 1)
560 @ FPA little-endian: must swap the word order.
570 @ The value is too big. Scale it down a bit...
578 add r2, r2, ip, lsr #3
581 shift1 lsl, ip, xl, r3
582 shift1 lsr, xl, xl, r2
583 shiftop orr xl xl xh lsl r3 lr
584 shift1 lsr, xh, xh, r2
588 #if !defined (__VFP_FP__) && !defined(__SOFTFP__)
590 @ Legacy code expects the result to be returned in f0. Copy it
604 #endif /* L_addsubdf3 */
608 ARM_FUNC_START muldf3
609 ARM_FUNC_ALIAS aeabi_dmul muldf3
610 do_push {r4, r5, r6, lr}
612 @ Mask out exponents, trap any zero/denormal/INF/NAN.
615 ands r4, ip, xh, lsr #20
617 COND(and,s,ne) r5, ip, yh, lsr #20
622 @ Add exponents together
625 @ Determine final sign.
628 @ Convert mantissa to unsigned integer.
629 @ If power of two, branch to a separate path.
630 bic xh, xh, ip, lsl #21
631 bic yh, yh, ip, lsl #21
632 orrs r5, xl, xh, lsl #12
634 COND(orr,s,ne) r5, yl, yh, lsl #12
635 orr xh, xh, #0x00100000
636 orr yh, yh, #0x00100000
641 @ Put sign bit in r6, which will be restored in yl later.
642 and r6, r6, #0x80000000
644 @ Well, no way to make it shorter without the umull instruction.
645 stmfd sp!, {r6, r7, r8, r9, sl, fp}
650 bic xl, xl, r7, lsl #16
651 bic yl, yl, r8, lsl #16
652 bic xh, xh, r9, lsl #16
653 bic yh, yh, sl, lsl #16
657 adds ip, ip, fp, lsl #16
658 adc lr, lr, fp, lsr #16
660 adds ip, ip, fp, lsl #16
661 adc lr, lr, fp, lsr #16
664 adds lr, lr, fp, lsl #16
665 adc r5, r5, fp, lsr #16
667 adds lr, lr, fp, lsl #16
668 adc r5, r5, fp, lsr #16
670 adds lr, lr, fp, lsl #16
671 adc r5, r5, fp, lsr #16
673 adds lr, lr, fp, lsl #16
674 adc r5, r5, fp, lsr #16
677 adds r5, r5, fp, lsl #16
678 adc r6, r6, fp, lsr #16
680 adds r5, r5, fp, lsl #16
681 adc r6, r6, fp, lsr #16
697 ldmfd sp!, {yl, r7, r8, r9, sl, fp}
701 @ Here is the actual multiplication.
705 and yl, r6, #0x80000000
712 @ The LSBs in ip are only significant for the final rounding.
718 @ Adjust result upon the MSB position.
720 cmp r6, #(1 << (20-11))
727 @ Shift to final position, add sign to result.
728 orr xh, yl, r6, lsl #11
729 orr xh, xh, r5, lsr #21
731 orr xl, xl, lr, lsr #21
734 @ Check exponent range for under/overflow.
735 subs ip, r4, #(254 - 1)
740 @ Round the result, merge final exponent.
743 COND(mov,s,eq) lr, xl, lsr #1
745 adc xh, xh, r4, lsl #20
748 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
750 and r6, r6, #0x80000000
754 subs r4, r4, ip, lsr #1
756 COND(rsb,s,gt) r5, r4, ip
757 orrgt xh, xh, r4, lsl #20
758 RETLDM "r4, r5, r6" gt
760 @ Under/overflow: fix things up for the code below.
761 orr xh, xh, #0x00100000
769 @ Check if denormalized result is possible, otherwise return signed 0.
773 bicle xh, xh, #0x7fffffff
774 RETLDM "r4, r5, r6" le
776 @ Find out proper shift value.
783 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
786 shift1 lsl, r3, xl, r5
787 shift1 lsr, xl, xl, r4
788 shiftop orr xl xl xh lsl r5 r2
789 and r2, xh, #0x80000000
790 bic xh, xh, #0x80000000
791 adds xl, xl, r3, lsr #31
792 shiftop adc xh r2 xh lsr r4 r6
793 orrs lr, lr, r3, lsl #1
795 biceq xl, xl, r3, lsr #31
798 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
799 @ a register switch from xh to xl. Then round.
802 shift1 lsl, r3, xl, r4
803 shift1 lsr, xl, xl, r5
804 shiftop orr xl xl xh lsl r4 r2
805 bic xh, xh, #0x7fffffff
806 adds xl, xl, r3, lsr #31
808 orrs lr, lr, r3, lsl #1
810 biceq xl, xl, r3, lsr #31
813 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
814 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
816 shiftop orr lr lr xl lsl r5 r2
817 shift1 lsr, r3, xl, r4
818 shiftop orr r3 r3 xh lsl r5 r2
819 shift1 lsr, xl, xh, r4
820 bic xh, xh, #0x7fffffff
821 shiftop bic xl xl xh lsr r4 r2
822 add xl, xl, r3, lsr #31
823 orrs lr, lr, r3, lsl #1
825 biceq xl, xl, r3, lsr #31
828 @ One or both arguments are denormalized.
829 @ Scale them leftwards and preserve sign bit.
833 and r6, xh, #0x80000000
834 1: movs xl, xl, lsl #1
844 2: and r6, yh, #0x80000000
845 3: movs yl, yl, lsl #1
855 @ Isolate the INF and NAN cases away
857 and r5, ip, yh, lsr #20
862 @ Here, one or more arguments are either denormalized or zero.
863 orrs r6, xl, xh, lsl #1
865 COND(orr,s,ne) r6, yl, yh, lsl #1
868 @ Result is 0, but determine sign anyway.
871 and xh, xh, #0x80000000
875 1: @ One or both args are INF or NAN.
876 orrs r6, xl, xh, lsl #1
880 COND(orr,s,ne) r6, yl, yh, lsl #1
881 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
884 orrs r6, xl, xh, lsl #12
885 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
888 orrs r6, yl, yh, lsl #12
892 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
894 @ Result is INF, but we need to determine its sign.
898 @ Overflow: return INF (sign already in xh).
900 and xh, xh, #0x80000000
901 orr xh, xh, #0x7f000000
902 orr xh, xh, #0x00f00000
906 @ Return a quiet NAN.
908 orr xh, xh, #0x7f000000
909 orr xh, xh, #0x00f80000
915 ARM_FUNC_START divdf3
916 ARM_FUNC_ALIAS aeabi_ddiv divdf3
918 do_push {r4, r5, r6, lr}
920 @ Mask out exponents, trap any zero/denormal/INF/NAN.
923 ands r4, ip, xh, lsr #20
925 COND(and,s,ne) r5, ip, yh, lsr #20
930 @ Substract divisor exponent from dividend''s.
933 @ Preserve final sign into lr.
936 @ Convert mantissa to unsigned integer.
937 @ Dividend -> r5-r6, divisor -> yh-yl.
938 orrs r5, yl, yh, lsl #12
943 orr yh, r5, yh, lsr #4
944 orr yh, yh, yl, lsr #24
946 orr r5, r5, xh, lsr #4
947 orr r5, r5, xl, lsr #24
950 @ Initialize xh with final sign bit.
951 and xh, lr, #0x80000000
953 @ Ensure result will land to known bit position.
954 @ Apply exponent bias accordingly.
958 adc r4, r4, #(255 - 2)
964 @ Perform first substraction to align result to a nibble.
972 @ The actual division loop.
986 orrcs xl, xl, ip, lsr #1
994 orrcs xl, xl, ip, lsr #2
1002 orrcs xl, xl, ip, lsr #3
1007 orr r5, r5, r6, lsr #28
1010 orr yh, yh, yl, lsr #29
1015 @ We are done with a word of the result.
1016 @ Loop again for the low word if this pass was for the high word.
1024 @ Be sure result starts in the high word.
1030 @ Check exponent range for under/overflow.
1031 subs ip, r4, #(254 - 1)
1036 @ Round the result, merge final exponent.
1039 COND(sub,s,eq) ip, r6, yl
1040 COND(mov,s,eq) ip, xl, lsr #1
1042 adc xh, xh, r4, lsl #20
1045 @ Division by 0x1p*: shortcut a lot of code.
1047 and lr, lr, #0x80000000
1048 orr xh, lr, xh, lsr #12
1049 adds r4, r4, ip, lsr #1
1051 COND(rsb,s,gt) r5, r4, ip
1052 orrgt xh, xh, r4, lsl #20
1053 RETLDM "r4, r5, r6" gt
1055 orr xh, xh, #0x00100000
1060 @ Result mightt need to be denormalized: put remainder bits
1061 @ in lr for rounding considerations.
1066 @ One or both arguments is either INF, NAN or zero.
1068 and r5, ip, yh, lsr #20
1072 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1075 orrs r4, xl, xh, lsl #12
1076 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1078 bne LSYM(Lml_i) @ INF / <anything> -> INF
1081 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1084 orrs r5, yl, yh, lsl #12
1085 beq LSYM(Lml_z) @ <anything> / INF -> 0
1088 b LSYM(Lml_n) @ <anything> / NAN -> NAN
1089 2: @ If both are nonzero, we need to normalize and resume above.
1090 orrs r6, xl, xh, lsl #1
1092 COND(orr,s,ne) r6, yl, yh, lsl #1
1094 @ One or both arguments are 0.
1095 orrs r4, xl, xh, lsl #1
1096 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1097 orrs r5, yl, yh, lsl #1
1098 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1099 b LSYM(Lml_n) @ 0 / 0 -> NAN
1104 #endif /* L_muldivdf3 */
1108 @ Note: only r0 (return value) and ip are clobbered here.
1110 ARM_FUNC_START gtdf2
1111 ARM_FUNC_ALIAS gedf2 gtdf2
1115 ARM_FUNC_START ltdf2
1116 ARM_FUNC_ALIAS ledf2 ltdf2
1120 ARM_FUNC_START cmpdf2
1121 ARM_FUNC_ALIAS nedf2 cmpdf2
1122 ARM_FUNC_ALIAS eqdf2 cmpdf2
1123 mov ip, #1 @ how should we specify unordered here?
1125 1: str ip, [sp, #-4]
1127 @ Trap any INF/NAN first.
1129 mvns ip, ip, asr #21
1132 COND(mvn,s,ne) ip, ip, asr #21
1135 @ Test for equality.
1136 @ Note that 0.0 is equal to -0.0.
1137 2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1139 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1140 teqne xh, yh @ or xh == yh
1142 teqeq xl, yl @ and xl == yl
1143 moveq r0, #0 @ then equal.
1152 @ Compare values if same sign
1160 movcs r0, yh, asr #31
1161 mvncc r0, yh, asr #31
1166 3: mov ip, xh, lsl #1
1167 mvns ip, ip, asr #21
1169 orrs ip, xl, xh, lsl #12
1171 4: mov ip, yh, lsl #1
1172 mvns ip, ip, asr #21
1174 orrs ip, yl, yh, lsl #12
1175 beq 2b @ y is not NAN
1176 5: ldr r0, [sp, #-4] @ unordered return code
1187 ARM_FUNC_START aeabi_cdrcmple
1197 ARM_FUNC_START aeabi_cdcmpeq
1198 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1200 @ The status-returning routines are required to preserve all
1201 @ registers except ip, lr, and cpsr.
1204 @ Set the Z flag correctly, and the C flag unconditionally.
1206 @ Clear the C flag if the return value was -1, indicating
1207 @ that the first operand was smaller than the second.
1212 FUNC_END aeabi_cdcmple
1213 FUNC_END aeabi_cdcmpeq
1214 FUNC_END aeabi_cdrcmple
1216 ARM_FUNC_START aeabi_dcmpeq
1219 ARM_CALL aeabi_cdcmple
1221 moveq r0, #1 @ Equal to.
1222 movne r0, #0 @ Less than, greater than, or unordered.
1225 FUNC_END aeabi_dcmpeq
1227 ARM_FUNC_START aeabi_dcmplt
1230 ARM_CALL aeabi_cdcmple
1232 movcc r0, #1 @ Less than.
1233 movcs r0, #0 @ Equal to, greater than, or unordered.
1236 FUNC_END aeabi_dcmplt
1238 ARM_FUNC_START aeabi_dcmple
1241 ARM_CALL aeabi_cdcmple
1243 movls r0, #1 @ Less than or equal to.
1244 movhi r0, #0 @ Greater than or unordered.
1247 FUNC_END aeabi_dcmple
1249 ARM_FUNC_START aeabi_dcmpge
1252 ARM_CALL aeabi_cdrcmple
1254 movls r0, #1 @ Operand 2 is less than or equal to operand 1.
1255 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
1258 FUNC_END aeabi_dcmpge
1260 ARM_FUNC_START aeabi_dcmpgt
1263 ARM_CALL aeabi_cdrcmple
1265 movcc r0, #1 @ Operand 2 is less than operand 1.
1266 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
1267 @ or they are unordered.
1270 FUNC_END aeabi_dcmpgt
1272 #endif /* L_cmpdf2 */
1276 ARM_FUNC_START unorddf2
1277 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1280 mvns ip, ip, asr #21
1282 orrs ip, xl, xh, lsl #12
1284 1: mov ip, yh, lsl #1
1285 mvns ip, ip, asr #21
1287 orrs ip, yl, yh, lsl #12
1289 2: mov r0, #0 @ arguments are ordered.
1292 3: mov r0, #1 @ arguments are unordered.
1295 FUNC_END aeabi_dcmpun
1298 #endif /* L_unorddf2 */
1302 ARM_FUNC_START fixdfsi
1303 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1305 @ check exponent range.
1307 adds r2, r2, #(1 << 21)
1308 bcs 2f @ value is INF or NAN
1309 bpl 1f @ value is too small
1310 mov r3, #(0xfffffc00 + 31)
1311 subs r2, r3, r2, asr #21
1312 bls 3f @ value is too large
1316 orr r3, r3, #0x80000000
1317 orr r3, r3, xl, lsr #21
1318 tst xh, #0x80000000 @ the sign bit
1319 shift1 lsr, r0, r3, r2
1327 2: orrs xl, xl, xh, lsl #12
1329 3: ands r0, xh, #0x80000000 @ the sign bit
1331 moveq r0, #0x7fffffff @ maximum signed positive si
1334 4: mov r0, #0 @ How should we convert NAN?
1340 #endif /* L_fixdfsi */
1344 ARM_FUNC_START fixunsdfsi
1345 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1347 @ check exponent range.
1349 bcs 1f @ value is negative
1350 adds r2, r2, #(1 << 21)
1351 bcs 2f @ value is INF or NAN
1352 bpl 1f @ value is too small
1353 mov r3, #(0xfffffc00 + 31)
1354 subs r2, r3, r2, asr #21
1355 bmi 3f @ value is too large
1359 orr r3, r3, #0x80000000
1360 orr r3, r3, xl, lsr #21
1361 shift1 lsr, r0, r3, r2
1367 2: orrs xl, xl, xh, lsl #12
1368 bne 4f @ value is NAN.
1369 3: mov r0, #0xffffffff @ maximum unsigned si
1372 4: mov r0, #0 @ How should we convert NAN?
1375 FUNC_END aeabi_d2uiz
1378 #endif /* L_fixunsdfsi */
1382 ARM_FUNC_START truncdfsf2
1383 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1385 @ check exponent range.
1387 subs r3, r2, #((1023 - 127) << 21)
1389 COND(sub,s,cs) ip, r3, #(1 << 21)
1390 COND(rsb,s,cs) ip, ip, #(254 << 21)
1391 bls 2f @ value is out of range
1393 1: @ shift and round mantissa
1394 and ip, xh, #0x80000000
1396 orr xl, ip, xl, lsr #29
1398 adc r0, xl, r3, lsl #2
1403 2: @ either overflow or underflow
1407 @ check if denormalized value is possible
1408 adds r2, r3, #(23 << 21)
1410 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1413 @ denormalize value so we can resume with the code above afterwards.
1414 orr xh, xh, #0x00100000
1418 #if defined(__thumb2__)
1423 shift1 lsr, xl, xl, r2
1425 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1428 shiftop orr xl xl r3 lsl ip ip
1429 shift1 lsr, r3, r3, r2
1434 mvns r3, r2, asr #21
1435 bne 5f @ simple overflow
1436 orrs r3, xl, xh, lsl #12
1438 movne r0, #0x7f000000
1439 orrne r0, r0, #0x00c00000
1440 RETc(ne) @ return NAN
1442 5: @ return INF with sign
1443 and r0, xh, #0x80000000
1444 orr r0, r0, #0x7f000000
1445 orr r0, r0, #0x00800000
1451 #endif /* L_truncdfsf2 */