1 /* ieee754-df.S double-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
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, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, 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.
43 @ This selects the minimum architecture level required.
45 #define __ARM_ARCH__ 3
47 #if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
48 || defined(__ARM_ARCH_4T__)
50 /* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
51 long multiply instructions. That includes v3M. */
52 #define __ARM_ARCH__ 4
55 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
56 || defined(__ARM_ARCH_5TE__)
58 #define __ARM_ARCH__ 5
61 #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
65 #define RETc(x) bx##x lr
66 #if (__ARM_ARCH__ == 4) && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
67 #define __FP_INTERWORKING__
71 @ For FPA, float words are always big-endian.
72 @ For VFP, floats words follow the memory system mode.
73 #if defined(__VFP_FP__) && !defined(__ARMEB__)
86 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
87 .macro ARM_FUNC_START name
94 .macro ARM_FUNC_START name
101 eor xh, xh, #0x80000000
104 ARM_FUNC_START subdf3
105 @ flip sign bit of second arg
106 eor yh, yh, #0x80000000
107 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
108 b 1f @ Skip Thumb-code prologue
111 ARM_FUNC_START adddf3
113 1: @ Compare both args, return zero if equal but the sign.
116 teqeq ip, #0x80000000
119 @ If first arg is 0 or -0, return second arg.
120 @ If second arg is 0 or -0, return first arg.
121 orrs ip, xl, xh, lsl #1
124 orrnes ip, yl, yh, lsl #1
127 stmfd sp!, {r4, r5, lr}
129 @ Mask out exponents.
131 orr ip, ip, #0x00f00000
135 @ If either of them is 0x7ff, result will be INF or NAN
140 @ Compute exponent difference. Make largest exponent in r4,
141 @ corresponding arg in xh-xl, and positive exponent difference in r5.
154 @ If exponent difference is too large, return largest argument
155 @ already in xh-xl. We need up to 54 bit to handle proper rounding
158 #ifdef __FP_INTERWORKING__
159 ldmhifd sp!, {r4, r5, lr}
162 ldmhifd sp!, {r4, r5, pc}RETCOND
165 @ Convert mantissa to signed integer.
167 bic xh, xh, ip, lsl #1
168 orr xh, xh, #0x00100000
174 bic yh, yh, ip, lsl #1
175 orr yh, yh, #0x00100000
180 @ If exponent == difference, one or both args were denormalized.
181 @ Since this is not common case, rescale them off line.
185 @ Scale down second arg with exponent difference.
186 @ Apply shift one bit left to first arg and the rest to second arg
187 @ to simplify things later, but only if exponent does not become 0.
194 adc xh, ip, xh, lsl #1
195 sub r4, r4, #(1 << 20)
199 @ Shift yh-yl right per r5, keep leftover bits into ip.
204 orr yl, yl, yh, lsl lr
210 adc ip, ip, yh, lsl lr
214 @ the actual addition
218 @ We now have a result in xh-xl-ip.
219 @ Keep absolute value in xh-xl-ip, sign in r5.
220 ands r5, xh, #0x80000000
226 @ Determine how to normalize the result.
235 @ Result needs to be shifted right.
240 add r4, r4, #(1 << 20)
246 add r4, r4, #(1 << 20)
248 @ Our result is now properly aligned into xh-xl, remaining bits in ip.
249 @ Round with MSB of ip. If halfway between two numbers, round towards
252 adds xl, xl, ip, lsr #31
257 @ One extreme rounding case may add a new MSB. Adjust exponent.
258 @ That MSB will be cleared when exponent is merged below.
260 addne r4, r4, #(1 << 20)
262 @ Make sure we did not bust our exponent.
263 adds ip, r4, #(1 << 20)
266 @ Pack final result together.
268 bic xh, xh, #0x00300000
271 #ifdef __FP_INTERWORKING__
272 ldmfd sp!, {r4, r5, lr}
275 ldmfd sp!, {r4, r5, pc}RETCOND
278 LSYM(Lad_l): @ Result must be shifted left and exponent adjusted.
279 @ No rounding necessary since ip will always be 0.
289 moveq r2, r2, lsl #16
314 @ determine how to shift the value.
320 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
321 @ since a register switch happened above.
328 @ actually shift value left 1 to 20 bits, which might also represent
329 @ 32 to 52 bits if counting the register switch that happened earlier.
333 orrle xh, xh, xl, lsr ip
336 @ adjust exponent accordingly.
337 3: subs r4, r4, r3, lsl #20
340 @ Exponent too small, denormalize result.
341 @ Find out proper shift value.
348 @ shift result right of 1 to 20 bits, sign is in r5.
352 orr xl, xl, xh, lsl r2
353 orr xh, r5, xh, lsr r4
354 #ifdef __FP_INTERWORKING
355 ldmfd sp!, {r4, r5, lr}
358 ldmfd sp!, {r4, r5, pc}RETCOND
361 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
362 @ a register switch from xh to xl.
366 orr xl, xl, xh, lsl r4
368 #ifdef __FP_INTERWORKING__
369 ldmfd sp!, {r4, r5, lr}
372 ldmfd sp!, {r4, r5, pc}RETCOND
375 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
377 2: mov xl, xh, lsr r4
379 #ifdef __FP_INTERWORKING__
380 ldmfd sp!, {r4, r5, lr}
383 ldmfd sp!, {r4, r5, pc}RETCOND
386 @ Adjust exponents for denormalized arguments.
389 eoreq xh, xh, #0x00100000
390 addeq r4, r4, #(1 << 20)
391 eor yh, yh, #0x00100000
392 subne r5, r5, #(1 << 20)
395 @ Result is x - x = 0, unless x = INF or NAN.
397 sub ip, ip, #0x00100000 @ ip becomes 0x7ff00000
400 orreq xh, ip, #0x00080000
405 @ Overflow: return INF.
407 orr xh, r5, #0x7f000000
408 orr xh, xh, #0x00f00000
410 #ifdef __FP_INTERWORKING__
411 ldmfd sp!, {r4, r5, lr}
414 ldmfd sp!, {r4, r5, pc}RETCOND
417 @ At least one of x or y is INF/NAN.
418 @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
419 @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
420 @ if either is NAN: return NAN
421 @ if opposite sign: return NAN
422 @ return xh-xl (which is INF or -INF)
428 #ifdef __FP_INTERWORKING__
429 ldmnefd sp!, {r4, r5, lr}
432 ldmnefd sp!, {r4, r5, pc}RETCOND
434 orrs r4, xl, xh, lsl #12
435 orreqs r4, yl, yh, lsl #12
437 orrne xh, r5, #0x00080000
439 #ifdef __FP_INTERWORKING__
440 ldmfd sp!, {r4, r5, lr}
443 ldmfd sp!, {r4, r5, pc}RETCOND
447 ARM_FUNC_START floatunsidf
451 stmfd sp!, {r4, r5, lr}
452 mov r4, #(0x400 << 20) @ initial exponent
453 add r4, r4, #((52-1) << 20)
454 mov r5, #0 @ sign bit is 0
460 ARM_FUNC_START floatsidf
464 stmfd sp!, {r4, r5, lr}
465 mov r4, #(0x400 << 20) @ initial exponent
466 add r4, r4, #((52-1) << 20)
467 ands r5, r0, #0x80000000 @ sign bit in r5
468 rsbmi r0, r0, #0 @ absolute value
474 ARM_FUNC_START extendsfdf2
476 beq 1f @ value is 0.0 or -0.0
477 mov xh, r2, asr #3 @ stretch exponent
478 mov xh, xh, rrx @ retrieve sign bit
479 mov xl, r2, lsl #28 @ retrieve remaining bits
480 ands r2, r2, #0xff000000 @ isolate exponent
481 beq 2f @ exponent was 0 but not mantissa
482 teq r2, #0xff000000 @ check if INF or NAN
483 eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
490 2: @ value was denormalized. We can normalize it now.
491 stmfd sp!, {r4, r5, lr}
492 mov r4, #(0x380 << 20) @ setup corresponding exponent
493 add r4, r4, #(1 << 20)
494 and r5, xh, #0x80000000 @ move sign bit in r5
495 bic xh, xh, #0x80000000
499 ARM_FUNC_START muldf3
501 stmfd sp!, {r4, r5, r6, lr}
503 @ Mask out exponents.
505 orr ip, ip, #0x00f00000
514 @ Trap any multiplication by 0.
515 orrs r6, xl, xh, lsl #1
516 orrnes r6, yl, yh, lsl #1
519 @ Shift exponents right one bit to make room for overflow bit.
520 @ If either of them is 0, scale denormalized arguments off line.
521 @ Then add both exponents together.
526 add r4, r4, r5, asr #1
528 @ Preserve final sign in r4 along with exponent for now.
530 orrmi r4, r4, #0x8000
532 @ Convert mantissa to unsigned integer.
533 bic xh, xh, ip, lsl #1
534 bic yh, yh, ip, lsl #1
535 orr xh, xh, #0x00100000
536 orr yh, yh, #0x00100000
540 @ Well, no way to make it shorter without the umull instruction.
541 @ We must perform that 53 x 53 bit multiplication by hand.
542 stmfd sp!, {r7, r8, r9, sl, fp}
547 bic xl, xl, r7, lsl #16
548 bic yl, yl, r8, lsl #16
549 bic xh, xh, r9, lsl #16
550 bic yh, yh, sl, lsl #16
554 adds ip, ip, fp, lsl #16
555 adc lr, lr, fp, lsr #16
557 adds ip, ip, fp, lsl #16
558 adc lr, lr, fp, lsr #16
561 adds lr, lr, fp, lsl #16
562 adc r5, r5, fp, lsr #16
564 adds lr, lr, fp, lsl #16
565 adc r5, r5, fp, lsr #16
567 adds lr, lr, fp, lsl #16
568 adc r5, r5, fp, lsr #16
570 adds lr, lr, fp, lsl #16
571 adc r5, r5, fp, lsr #16
574 adds r5, r5, fp, lsl #16
575 adc r6, r6, fp, lsr #16
577 adds r5, r5, fp, lsl #16
578 adc r6, r6, fp, lsr #16
594 ldmfd sp!, {r7, r8, r9, sl, fp}
598 @ Here is the actual multiplication: 53 bits * 53 bits -> 106 bits.
608 @ The LSBs in ip are only significant for the final rounding.
609 @ Fold them into one bit of lr.
613 @ Put final sign in xh.
617 @ Adjust result if one extra MSB appeared (one of four times).
620 add r4, r4, #(1 << 19)
626 @ Scale back to 53 bits.
627 @ xh contains sign bit already.
628 orr xh, xh, r6, lsl #12
629 orr xh, xh, r5, lsr #20
631 orr xl, xl, lr, lsr #20
633 @ Apply exponent bias, check range for underflow.
634 sub r4, r4, #0x00f80000
635 subs r4, r4, #0x1f000000
646 @ Rounding may have produced an extra MSB here.
647 @ The extra bit is cleared before merging the exponent below.
649 addne r4, r4, #(1 << 19)
651 @ Check exponent for overflow.
652 adds ip, r4, #(1 << 19)
656 @ Add final exponent.
657 bic xh, xh, #0x00300000
658 orr xh, xh, r4, lsl #1
659 #ifdef __FP_INTERWORKING__
660 ldmfd sp!, {r4, r5, r6, lr}
663 ldmfd sp!, {r4, r5, r6, pc}RETCOND
666 @ Result is 0, but determine sign anyway.
670 bic xh, xh, #0x7fffffff
672 #ifdef __FP_INTERWORKING__
673 ldmfd sp!, {r4, r5, r6, lr}
676 ldmfd sp!, {r4, r5, r6, pc}RETCOND
679 @ Check if denormalized result is possible, otherwise return signed 0.
683 #ifdef __FP_INTERWORKING__
684 ldmlefd sp!, {r4, r5, r6, lr}
687 ldmlefd sp!, {r4, r5, r6, pc}RETCOND
690 @ Find out proper shift value.
698 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
703 orr xl, xl, xh, lsl r5
707 adds xl, xl, r3, lsr #31
710 teqeq r3, #0x80000000
712 #ifdef __FP_INTERWORKING__
713 ldmfd sp!, {r4, r5, r6, lr}
716 ldmfd sp!, {r4, r5, r6, pc}RETCOND
719 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
720 @ a register switch from xh to xl. Then round.
725 orr xl, xl, xh, lsl r4
726 bic xh, xh, #0x7fffffff
727 adds xl, xl, r3, lsr #31
730 teqeq r3, #0x80000000
732 #ifdef __FP_INTERWORKING__
733 ldmfd sp!, {r4, r5, r6, lr}
736 ldmfd sp!, {r4, r5, r6, pc}RETCOND
739 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
740 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
744 orr r3, r3, xh, lsl r5
746 bic xh, xh, #0x7fffffff
747 adds xl, xl, r3, lsr #31
750 teqeq r3, #0x80000000
752 #ifdef __FP_INTERWORKING__
753 ldmfd sp!, {r4, r5, r6, lr}
756 ldmfd sp!, {r4, r5, r6, pc}RETCOND
759 @ One or both arguments are denormalized.
760 @ Scale them leftwards and preserve sign bit.
765 and r6, xh, #0x80000000
766 1: movs xl, xl, lsl #1
767 adc xh, lr, xh, lsl #1
769 subeq r4, r4, #(1 << 19)
774 2: and r6, yh, #0x80000000
775 3: movs yl, yl, lsl #1
776 adc yh, lr, yh, lsl #1
778 subeq r5, r5, #(1 << 20)
783 @ One or both args are INF or NAN.
785 orrs r6, xl, xh, lsl #1
786 orrnes r6, yl, yh, lsl #1
787 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
790 orrs r6, xl, xh, lsl #12
791 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
794 orrs r6, yl, yh, lsl #12
795 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
797 @ Result is INF, but we need to determine its sign.
801 @ Overflow: return INF (sign already in xh).
803 and xh, xh, #0x80000000
804 orr xh, xh, #0x7f000000
805 orr xh, xh, #0x00f00000
807 #ifdef __FP_INTERWORKING__
808 ldmfd sp!, {r4, r5, r6, lr}
811 ldmfd sp!, {r4, r5, r6, pc}RETCOND
817 orr xh, xh, #0x00f80000
818 #ifdef __FP_INTERWORKING__
819 ldmfd sp!, {r4, r5, r6, lr}
822 ldmfd sp!, {r4, r5, r6, pc}RETCOND
826 ARM_FUNC_START divdf3
828 stmfd sp!, {r4, r5, r6, lr}
830 @ Mask out exponents.
832 orr ip, ip, #0x00f00000
836 @ Trap any INF/NAN or zeroes.
839 orrnes r6, xl, xh, lsl #1
840 orrnes r6, yl, yh, lsl #1
843 @ Shift exponents right one bit to make room for overflow bit.
844 @ If either of them is 0, scale denormalized arguments off line.
845 @ Then substract divisor exponent from dividend''s.
850 sub r4, r4, r5, asr #1
852 @ Preserve final sign into lr.
855 @ Convert mantissa to unsigned integer.
856 @ Dividend -> r5-r6, divisor -> yh-yl.
859 orr yh, r5, yh, lsr #4
860 orr yh, yh, yl, lsr #24
865 orr r5, r5, xh, lsr #4
866 orr r5, r5, xl, lsr #24
869 @ Initialize xh with final sign bit.
870 and xh, lr, #0x80000000
872 @ Ensure result will land to known bit position.
876 sub r4, r4, #(1 << 19)
880 @ Apply exponent bias, check range for over/underflow.
881 add r4, r4, #0x1f000000
882 add r4, r4, #0x00f80000
888 @ Perform first substraction to align result to a nibble.
896 @ The actual division loop.
908 orrcs xl, xl, ip, lsr #1
915 orrcs xl, xl, ip, lsr #2
922 orrcs xl, xl, ip, lsr #3
927 orr r5, r5, r6, lsr #28
930 orr yh, yh, yl, lsr #29
935 @ We are done with a word of the result.
936 @ Loop again for the low word if this pass was for the high word.
944 @ Be sure result starts in the high word.
949 @ Check if denormalized result is needed.
953 @ Apply proper rounding.
961 @ Add exponent to result.
962 bic xh, xh, #0x00100000
963 orr xh, xh, r4, lsl #1
964 #ifdef __FP_INTERWORKING__
965 ldmfd sp!, {r4, r5, r6, lr}
968 ldmfd sp!, {r4, r5, r6, pc}RETCOND
971 @ Division by 0x1p*: shortcut a lot of code.
973 and lr, lr, #0x80000000
974 orr xh, lr, xh, lsr #12
975 add r4, r4, #0x1f000000
976 add r4, r4, #0x00f80000
980 orrgt xh, xh, r4, lsl #1
981 #ifdef __FP_INTERWORKING__
982 ldmgtfd sp!, {r4, r5, r6, lr}
985 ldmgtfd sp!, {r4, r5, r6, pc}RETCOND
989 orr xh, xh, #0x00100000
993 @ Result must be denormalized: put remainder in lr for
994 @ rounding considerations.
999 @ One or both arguments are denormalized.
1000 @ Scale them leftwards and preserve sign bit.
1005 and r6, xh, #0x80000000
1006 1: movs xl, xl, lsl #1
1007 adc xh, lr, xh, lsl #1
1009 subeq r4, r4, #(1 << 19)
1014 2: and r6, yh, #0x80000000
1015 3: movs yl, yl, lsl #1
1016 adc yh, lr, yh, lsl #1
1018 subeq r5, r5, #(1 << 20)
1023 @ One or both arguments is either INF, NAN or zero.
1027 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1030 orrs r4, xl, xh, lsl #12
1031 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1032 b LSYM(Lml_i) @ INF / <anything> -> INF
1035 orrs r5, yl, yh, lsl #12
1036 bne LSYM(Lml_n) @ <anything> / NAN -> NAN
1037 b LSYM(Lml_z) @ <anything> / INF -> 0
1038 2: @ One or both arguments are 0.
1039 orrs r4, xl, xh, lsl #1
1040 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1041 orrs r5, yl, yh, lsl #1
1042 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1043 b LSYM(Lml_n) @ 0 / 0 -> NAN
1047 ARM_FUNC_START gtdf2
1052 ARM_FUNC_START ltdf2
1058 ARM_FUNC_START cmpdf2
1059 mov ip, #1 @ how should we specify unordered here?
1061 1: stmfd sp!, {r4, r5, lr}
1063 @ Trap any INF/NAN first.
1065 orr lr, lr, #0x00f00000
1072 @ Test for equality.
1073 @ Note that 0.0 is equal to -0.0.
1074 2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1075 orreqs ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1076 teqne xh, yh @ or xh == yh
1077 teqeq xl, yl @ and xl == yl
1078 moveq r0, #0 @ then equal.
1079 #ifdef __FP_INTERWORKING__
1080 ldmeqfd sp!, {r4, r5, lr}
1083 ldmeqfd sp!, {r4, r5, pc}RETCOND
1086 @ Check for sign difference.
1088 movmi r0, xh, asr #31
1090 #ifdef __FP_INTERWORKING__
1091 ldmmifd sp!, {r4, r5, lr}
1094 ldmmifd sp!, {r4, r5, pc}RETCOND
1097 @ Compare exponents.
1100 @ Compare mantissa if exponents are equal.
1101 moveq xh, xh, lsl #12
1102 cmpeq xh, yh, lsl #12
1104 movcs r0, yh, asr #31
1105 mvncc r0, yh, asr #31
1107 #ifdef __FP_INTERWORKING__
1108 ldmfd sp!, {r4, r5, lr}
1111 ldmfd sp!, {r4, r5, pc}RETCOND
1117 orrs xl, xl, xh, lsl #12
1121 orrs yl, yl, yh, lsl #12
1122 beq 2b @ y is not NAN
1123 5: mov r0, ip @ return unordered code from ip
1124 #ifdef __FP_INTERWORKING__
1125 ldmfd sp!, {r4, r5, lr}
1128 ldmfd sp!, {r4, r5, pc}RETCOND
1132 ARM_FUNC_START unorddf2
1135 orr ip, ip, #0x00f00000
1139 orrs xl, xl, xh, lsl #12
1144 orrs yl, yl, yh, lsl #12
1146 2: mov r0, #0 @ arguments are ordered.
1147 #ifdef __FP_INTERWORKING__
1150 #elif defined (__APCS_26__)
1155 3: mov r0, #1 @ arguments are unordered.
1156 #ifdef __FP_INTERWORKING__
1159 #elif defined (__APCS_26__)
1166 ARM_FUNC_START fixdfsi
1167 orrs ip, xl, xh, lsl #1
1168 beq 1f @ value is 0.
1170 @ preserve C flag (the actual sign)
1177 @ check exponent range.
1179 orr ip, ip, #0x00f00000
1182 beq 2f @ value is INF or NAN
1183 bic ip, ip, #0x40000000
1185 bcc 1f @ value is too small
1186 add ip, ip, #(31 << 20)
1188 bcs 3f @ value is too large
1192 orr ip, ip, #0x80000000
1193 orr ip, ip, xl, lsr #21
1196 tst r3, #0x20000000 @ the sign bit
1203 2: orrs xl, xl, xh, lsl #12
1205 3: tst r3, #0x20000000 @ the sign bit
1206 moveq r0, #0x7fffffff @ maximum signed positive si
1207 movne r0, #0x80000000 @ maximum signed negative si
1210 4: mov r0, #0 @ How should we convert NAN?
1213 ARM_FUNC_START fixunsdfsi
1214 orrs ip, xl, xh, lsl #1
1216 bcs 1b @ value is negative
1218 @ check exponent range.
1220 orr ip, ip, #0x00f00000
1223 beq 1f @ value is INF or NAN
1224 bic ip, ip, #0x40000000
1226 bcc 1b @ value is too small
1227 add ip, ip, #(31 << 20)
1229 bhi 2f @ value is too large
1233 orr ip, ip, #0x80000000
1234 orr ip, ip, xl, lsr #21
1239 1: orrs xl, xl, xh, lsl #12
1240 bne 4b @ value is NAN.
1241 2: mov r0, #0xffffffff @ maximum unsigned si
1245 ARM_FUNC_START truncdfsf2
1246 orrs r2, xl, xh, lsl #1
1248 RETc(eq) @ value is 0.0 or -0.0
1250 @ check exponent range.
1252 orr ip, ip, #0x00f00000
1255 beq 2f @ value is INF or NAN
1257 cmp r2, #(0x380 << 20)
1258 bls 4f @ value is too small
1260 @ shift and round mantissa
1261 1: movs r3, xl, lsr #29
1262 adc r3, r3, xh, lsl #3
1264 @ if halfway between two numbers, round towards LSB = 0.
1269 @ rounding might have created an extra MSB. If so adjust exponent.
1271 addne r2, r2, #(1 << 20)
1272 bicne r3, r3, #0x00800000
1274 @ check exponent for overflow
1275 mov ip, #(0x400 << 20)
1276 orr ip, ip, #(0x07f << 20)
1280 @ adjust exponent, merge with sign bit and mantissa.
1284 eor r0, r0, #0x40000000
1288 orrs xl, xl, xh, lsl #12
1289 movne r0, #0x7f000000
1290 orrne r0, r0, #0x00c00000
1291 RETc(ne) @ return NAN
1293 3: @ return INF with sign
1294 and r0, xh, #0x80000000
1295 orr r0, r0, #0x7f000000
1296 orr r0, r0, #0x00800000
1299 4: @ check if denormalized value is possible
1300 subs r2, r2, #((0x380 - 24) << 20)
1301 andle r0, xh, #0x80000000 @ too small, return signed 0.
1304 @ denormalize value so we can resume with the code above afterwards.
1305 orr xh, xh, #0x00100000
1314 orr xl, xl, xh, lsl ip
1318 5: teq r3, #0 @ fold r3 bits into the LSB
1319 orrne xl, xl, #1 @ for rounding considerations.
1320 mov r2, #(0x380 << 20) @ equivalent to the 0 float exponent
1323 6: rsb r2, r2, #(12 + 20)
1327 orr xl, xl, xh, lsl r2
1328 and xh, xh, #0x80000000