1 /* ieee754-df.S double-precision floating point support for ARM
3 Copyright (C) 2003-2020 Free Software Foundation, Inc.
4 Contributed by Nicolas Pitre (nico@fluxnic.net)
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
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/>. */
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
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.
37 * In the CFI related comments, 'previousOffset' refers to the previous offset
38 * from sp used to compute the CFA.
41 .cfi_sections .debug_frame
59 ARM_FUNC_ALIAS aeabi_dneg negdf2
63 eor xh, xh, #0x80000000
72 #ifdef L_arm_addsubdf3
74 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} @ 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
97 @ Look for zeroes, equal values, INF, or NAN.
98 shift1 lsl, r4, xh, #1
99 shift1 lsl, r5, yh, #1
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
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
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
132 @ Convert mantissa to signed integer.
136 orr xh, ip, xh, lsr #12
138 #if defined(__thumb2__)
140 sbc xh, xh, xh, lsl #1
148 orr yh, ip, yh, lsr #12
150 #if defined(__thumb2__)
152 sbc yh, yh, yh, lsl #1
158 @ If exponent == difference, one or both args were denormalized.
159 @ Since this is not common case, rescale them off line.
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.
169 @ Compensate for the exponent overlapping the mantissa MSB added later
172 @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
175 shift1 lsl, ip, yl, lr
176 shiftop adds xl xl yl lsr r5 yl
178 shiftop adds xl xl yh lsl lr yl
179 shiftop adcs xh xh yh asr r5 yh
184 shift1 lsl,ip, yh, lr
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
194 #if defined(__thumb2__)
205 @ Determine how to normalize the result.
212 @ Result needs to be shifted right.
218 @ Make sure we did not bust our exponent.
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
226 @ Pack final result together.
230 COND(mov,s,eq) ip, xl, lsr #1
232 adc xh, xh, r4, lsl #20
236 @ Result must be shifted left and exponent adjusted.
243 cmphs xh, #0x00100000
246 @ No rounding necessary since ip will always be 0 at this point.
249 #if !defined (__ARM_FEATURE_CLZ)
258 movhs r2, r2, lsr #16
268 sublo r3, r3, r2, lsr #1
269 sub r3, r3, r2, lsr #3
284 @ determine how to shift the value.
290 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
291 @ since a register switch happened above.
294 shift1 lsl, xl, xh, ip
295 shift1 lsr, xh, xh, r2
298 @ actually shift value left 1 to 20 bits, which might also represent
299 @ 32 to 52 bits if counting the register switch that happened earlier.
303 shift1 lsl, xh, xh, r2
304 #if defined(__thumb2__)
310 orrle xh, xh, xl, lsr ip
314 @ adjust exponent accordingly.
317 addge xh, xh, r4, lsl #20
321 @ Exponent too small, denormalize result.
322 @ Find out proper shift value.
329 @ shift result right of 1 to 20 bits, sign is in r5.
332 shift1 lsr, xl, xl, r4
333 shiftop orr xl xl xh lsl r2 yh
334 shiftop orr xh r5 xh lsr r4 yh
337 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
338 @ a register switch from xh to xl.
341 shift1 lsr, xl, xl, r2
342 shiftop orr xl xl xh lsl r4 yh
346 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
348 2: shift1 lsr, xl, xh, r4
352 @ Adjust exponents for denormalized arguments.
353 @ Note that r4 must not remain equal to 0.
356 eor yh, yh, #0x00100000
358 eoreq xh, xh, #0x00100000
367 COND(mvn,s,ne) ip, r5, asr #21
375 @ Result is x + 0.0 = x or 0.0 + y = y.
384 @ Result is x - x = 0.
390 @ Result is x + x = 2x.
396 orrcs xh, xh, #0x80000000
398 2: adds r4, r4, #(2 << 21)
400 addcc xh, xh, #(1 << 20)
402 and r5, xh, #0x80000000
404 @ Overflow: return INF.
406 orr xh, r5, #0x7f000000
407 orr xh, xh, #0x00f00000
411 @ At least one of x or y is INF/NAN.
412 @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
413 @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
414 @ if either is NAN: return NAN
415 @ if opposite sign: return NAN
416 @ otherwise return xh-xl (which is INF or -INF)
422 COND(mvn,s,eq) ip, r5, asr #21
426 orrs r4, xl, xh, lsl #12
428 COND(orr,s,eq) r5, yl, yh, lsl #12
430 orrne xh, xh, #0x00080000 @ quiet NAN
439 ARM_FUNC_START floatunsidf
440 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
448 do_push {r4, r5, lr} @ sp -= 12
449 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
450 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
451 .cfi_rel_offset r5, 4
452 .cfi_rel_offset lr, 8
454 mov r4, #0x400 @ initial exponent
455 add r4, r4, #(52-1 - 1)
456 mov r5, #0 @ sign bit is 0
467 ARM_FUNC_START floatsidf
468 ARM_FUNC_ALIAS aeabi_i2d floatsidf
476 do_push {r4, r5, lr} @ sp -= 12
477 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
478 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
479 .cfi_rel_offset r5, 4
480 .cfi_rel_offset lr, 8
482 mov r4, #0x400 @ initial exponent
483 add r4, r4, #(52-1 - 1)
484 ands r5, r0, #0x80000000 @ sign bit in r5
486 rsbmi r0, r0, #0 @ absolute value
497 ARM_FUNC_START extendsfdf2
498 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
501 movs r2, r0, lsl #1 @ toss sign bit
502 mov xh, r2, asr #3 @ stretch exponent
503 mov xh, xh, rrx @ retrieve sign bit
504 mov xl, r2, lsl #28 @ retrieve remaining bits
506 COND(and,s,ne) r3, r2, #0xff000000 @ isolate exponent
507 teqne r3, #0xff000000 @ if not 0, check if INF or NAN
508 eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
509 RETc(ne) @ and return it.
511 bics r2, r2, #0xff000000 @ isolate mantissa
512 do_it eq @ if 0, that is ZERO or INF,
513 RETc(eq) @ we are done already.
515 teq r3, #0xff000000 @ check for NAN
517 orreq xh, xh, #0x00080000 @ change to quiet NAN
518 RETc(eq) @ and return it.
520 @ value was denormalized. We can normalize it now.
522 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
523 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
524 .cfi_rel_offset r5, 4
525 .cfi_rel_offset lr, 8
527 mov r4, #0x380 @ setup corresponding exponent
528 and r5, xh, #0x80000000 @ move sign bit in r5
529 bic xh, xh, #0x80000000
536 ARM_FUNC_START floatundidf
537 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
539 .cfi_remember_state @ Save the current CFA state.
545 do_push {r4, r5, lr} @ sp -= 12
546 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
547 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8
548 .cfi_rel_offset r5, 4
549 .cfi_rel_offset lr, 8
554 ARM_FUNC_START floatdidf
555 ARM_FUNC_ALIAS aeabi_l2d floatdidf
557 @ Restore the CFI state we saved above. If we didn't do this then the
558 @ following instructions would have the CFI state that was set by the
559 @ offset adjustments made in floatundidf.
565 do_push {r4, r5, lr} @ sp -= 12
566 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
567 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 8
568 .cfi_rel_offset r5, 4
569 .cfi_rel_offset lr, 8
571 ands r5, ah, #0x80000000 @ sign bit in r5
573 #if defined(__thumb2__)
575 sbc ah, ah, ah, lsl #1
581 mov r4, #0x400 @ initial exponent
582 add r4, r4, #(52-1 - 1)
584 @ If FP word order does not match integer word order, swap the words.
594 @ The value is too big. Scale it down a bit...
602 add r2, r2, ip, lsr #3
605 shift1 lsl, ip, xl, r3
606 shift1 lsr, xl, xl, r2
607 shiftop orr xl xl xh lsl r3 lr
608 shift1 lsr, xh, xh, r2
618 #endif /* L_addsubdf3 */
620 #if defined(L_arm_muldf3) || defined(L_arm_muldivdf3)
622 @ Define multiplication as weak in _arm_muldf3.o so that it can be overriden
623 @ by the global definition in _arm_muldivdf3.o. This allows a program only
624 @ using multiplication to take the weak definition which does not contain the
625 @ division code. Programs using only division or both division and
626 @ multiplication will pull _arm_muldivdf3.o from which both the multiplication
627 @ and division are taken thanks to the override.
633 ARM_FUNC_START muldf3
634 ARM_FUNC_ALIAS aeabi_dmul muldf3
637 do_push {r4, r5, r6, lr} @ sp -= 16
638 .cfi_adjust_cfa_offset 16 @ CFA is now sp + previousOffset + 16
639 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 12.
640 .cfi_rel_offset r5, 4
641 .cfi_rel_offset r6, 8
642 .cfi_rel_offset lr, 12
644 @ Mask out exponents, trap any zero/denormal/INF/NAN.
647 ands r4, ip, xh, lsr #20
649 COND(and,s,ne) r5, ip, yh, lsr #20
654 @ Add exponents together
657 @ Determine final sign.
660 @ Convert mantissa to unsigned integer.
661 @ If power of two, branch to a separate path.
662 bic xh, xh, ip, lsl #21
663 bic yh, yh, ip, lsl #21
664 orrs r5, xl, xh, lsl #12
666 COND(orr,s,ne) r5, yl, yh, lsl #12
667 orr xh, xh, #0x00100000
668 orr yh, yh, #0x00100000
671 @ Here is the actual multiplication.
672 @ This code works on architecture versions >= 4
676 and yl, r6, #0x80000000
681 @ The LSBs in ip are only significant for the final rounding.
687 @ Adjust result upon the MSB position.
689 cmp r6, #(1 << (20-11))
696 @ Shift to final position, add sign to result.
697 orr xh, yl, r6, lsl #11
698 orr xh, xh, r5, lsr #21
700 orr xl, xl, lr, lsr #21
703 @ Check exponent range for under/overflow.
704 subs ip, r4, #(254 - 1)
709 @ Round the result, merge final exponent.
712 COND(mov,s,eq) lr, xl, lsr #1
714 adc xh, xh, r4, lsl #20
717 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
719 and r6, r6, #0x80000000
723 subs r4, r4, ip, lsr #1
725 COND(rsb,s,gt) r5, r4, ip
726 orrgt xh, xh, r4, lsl #20
727 RETLDM "r4, r5, r6" gt
729 @ Under/overflow: fix things up for the code below.
730 orr xh, xh, #0x00100000
737 @ Check if denormalized result is possible, otherwise return signed 0.
741 bicle xh, xh, #0x7fffffff
742 RETLDM "r4, r5, r6" le
744 @ Find out proper shift value.
751 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
754 shift1 lsl, r3, xl, r5
755 shift1 lsr, xl, xl, r4
756 shiftop orr xl xl xh lsl r5 r2
757 and r2, xh, #0x80000000
758 bic xh, xh, #0x80000000
759 adds xl, xl, r3, lsr #31
760 shiftop adc xh r2 xh lsr r4 r6
761 orrs lr, lr, r3, lsl #1
763 biceq xl, xl, r3, lsr #31
766 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
767 @ a register switch from xh to xl. Then round.
770 shift1 lsl, r3, xl, r4
771 shift1 lsr, xl, xl, r5
772 shiftop orr xl xl xh lsl r4 r2
773 bic xh, xh, #0x7fffffff
774 adds xl, xl, r3, lsr #31
776 orrs lr, lr, r3, lsl #1
778 biceq xl, xl, r3, lsr #31
781 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
782 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
784 shiftop orr lr lr xl lsl r5 r2
785 shift1 lsr, r3, xl, r4
786 shiftop orr r3 r3 xh lsl r5 r2
787 shift1 lsr, xl, xh, r4
788 bic xh, xh, #0x7fffffff
789 shiftop bic xl xl xh lsr r4 r2
790 add xl, xl, r3, lsr #31
791 orrs lr, lr, r3, lsl #1
793 biceq xl, xl, r3, lsr #31
796 @ One or both arguments are denormalized.
797 @ Scale them leftwards and preserve sign bit.
801 and r6, xh, #0x80000000
802 1: movs xl, xl, lsl #1
812 2: and r6, yh, #0x80000000
813 3: movs yl, yl, lsl #1
823 @ Isolate the INF and NAN cases away
825 and r5, ip, yh, lsr #20
830 @ Here, one or more arguments are either denormalized or zero.
831 orrs r6, xl, xh, lsl #1
833 COND(orr,s,ne) r6, yl, yh, lsl #1
836 @ Result is 0, but determine sign anyway.
839 and xh, xh, #0x80000000
843 1: @ One or both args are INF or NAN.
844 orrs r6, xl, xh, lsl #1
848 COND(orr,s,ne) r6, yl, yh, lsl #1
849 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
852 orrs r6, xl, xh, lsl #12
853 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
856 orrs r6, yl, yh, lsl #12
860 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
862 @ Result is INF, but we need to determine its sign.
866 @ Overflow: return INF (sign already in xh).
868 and xh, xh, #0x80000000
869 orr xh, xh, #0x7f000000
870 orr xh, xh, #0x00f00000
874 @ Return a quiet NAN.
876 orr xh, xh, #0x7f000000
877 orr xh, xh, #0x00f80000
884 #ifdef L_arm_muldivdf3
886 ARM_FUNC_START divdf3
887 ARM_FUNC_ALIAS aeabi_ddiv divdf3
890 do_push {r4, r5, r6, lr}
891 .cfi_adjust_cfa_offset 16
892 .cfi_rel_offset r4, 0
893 .cfi_rel_offset r5, 4
894 .cfi_rel_offset r6, 8
895 .cfi_rel_offset lr, 12
897 @ Mask out exponents, trap any zero/denormal/INF/NAN.
900 ands r4, ip, xh, lsr #20
902 COND(and,s,ne) r5, ip, yh, lsr #20
907 @ Subtract divisor exponent from dividend''s.
910 @ Preserve final sign into lr.
913 @ Convert mantissa to unsigned integer.
914 @ Dividend -> r5-r6, divisor -> yh-yl.
915 orrs r5, yl, yh, lsl #12
920 orr yh, r5, yh, lsr #4
921 orr yh, yh, yl, lsr #24
923 orr r5, r5, xh, lsr #4
924 orr r5, r5, xl, lsr #24
927 @ Initialize xh with final sign bit.
928 and xh, lr, #0x80000000
930 @ Ensure result will land to known bit position.
931 @ Apply exponent bias accordingly.
935 adc r4, r4, #(255 - 2)
941 @ Perform first subtraction to align result to a nibble.
949 @ The actual division loop.
963 orrcs xl, xl, ip, lsr #1
971 orrcs xl, xl, ip, lsr #2
979 orrcs xl, xl, ip, lsr #3
984 orr r5, r5, r6, lsr #28
987 orr yh, yh, yl, lsr #29
992 @ We are done with a word of the result.
993 @ Loop again for the low word if this pass was for the high word.
1001 @ Be sure result starts in the high word.
1007 @ Check exponent range for under/overflow.
1008 subs ip, r4, #(254 - 1)
1013 @ Round the result, merge final exponent.
1016 COND(sub,s,eq) ip, r6, yl
1017 COND(mov,s,eq) ip, xl, lsr #1
1019 adc xh, xh, r4, lsl #20
1022 @ Division by 0x1p*: shortcut a lot of code.
1024 and lr, lr, #0x80000000
1025 orr xh, lr, xh, lsr #12
1026 adds r4, r4, ip, lsr #1
1028 COND(rsb,s,gt) r5, r4, ip
1029 orrgt xh, xh, r4, lsl #20
1030 RETLDM "r4, r5, r6" gt
1032 orr xh, xh, #0x00100000
1037 @ Result mightt need to be denormalized: put remainder bits
1038 @ in lr for rounding considerations.
1043 @ One or both arguments is either INF, NAN or zero.
1045 and r5, ip, yh, lsr #20
1049 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1052 orrs r4, xl, xh, lsl #12
1053 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1055 bne LSYM(Lml_i) @ INF / <anything> -> INF
1058 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1061 orrs r5, yl, yh, lsl #12
1062 beq LSYM(Lml_z) @ <anything> / INF -> 0
1065 b LSYM(Lml_n) @ <anything> / NAN -> NAN
1066 2: @ If both are nonzero, we need to normalize and resume above.
1067 orrs r6, xl, xh, lsl #1
1069 COND(orr,s,ne) r6, yl, yh, lsl #1
1071 @ One or both arguments are 0.
1072 orrs r4, xl, xh, lsl #1
1073 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1074 orrs r5, yl, yh, lsl #1
1075 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1076 b LSYM(Lml_n) @ 0 / 0 -> NAN
1082 #endif /* L_muldivdf3 */
1083 #endif /* L_arm_muldf3 || L_arm_muldivdf3 */
1087 @ Note: only r0 (return value) and ip are clobbered here.
1089 ARM_FUNC_START gtdf2
1090 ARM_FUNC_ALIAS gedf2 gtdf2
1095 ARM_FUNC_START ltdf2
1096 ARM_FUNC_ALIAS ledf2 ltdf2
1100 ARM_FUNC_START cmpdf2
1101 ARM_FUNC_ALIAS nedf2 cmpdf2
1102 ARM_FUNC_ALIAS eqdf2 cmpdf2
1103 mov ip, #1 @ how should we specify unordered here?
1105 1: str ip, [sp, #-4]!
1106 .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4.
1107 @ We're not adding CFI for ip as it's pushed into the stack
1108 @ only because it may be popped off later as a return value
1109 @ (i.e. we're not preserving it anyways).
1111 @ Trap any INF/NAN first.
1113 mvns ip, ip, asr #21
1116 COND(mvn,s,ne) ip, ip, asr #21
1119 @ Save the current CFI state. This is done because the branch
1120 @ is conditional, and if we don't take it we'll issue a
1121 @ .cfi_adjust_cfa_offset and return. If we do take it,
1122 @ however, the .cfi_adjust_cfa_offset from the non-branch code
1123 @ will affect the branch code as well. To avoid this we'll
1124 @ restore the current state before executing the branch code.
1126 @ Test for equality. Note that 0.0 is equal to -0.0.
1128 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1130 orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1132 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1133 teqne xh, yh @ or xh == yh
1135 teqeq xl, yl @ and xl == yl
1136 moveq r0, #0 @ then equal.
1145 @ Compare values if same sign
1153 movcs r0, yh, asr #31
1154 mvncc r0, yh, asr #31
1158 3: @ Look for a NAN.
1160 @ Restore the previous CFI state (i.e. keep the CFI state as it was
1161 @ before the branch).
1165 mvns ip, ip, asr #21
1167 orrs ip, xl, xh, lsl #12
1169 4: mov ip, yh, lsl #1
1170 mvns ip, ip, asr #21
1172 orrs ip, yl, yh, lsl #12
1173 beq 2b @ y is not NAN
1175 5: ldr r0, [sp], #4 @ unordered return code
1176 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1189 ARM_FUNC_START aeabi_cdrcmple
1200 ARM_FUNC_START aeabi_cdcmpeq
1201 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1203 @ The status-returning routines are required to preserve all
1204 @ registers except ip, lr, and cpsr.
1206 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8.
1207 .cfi_rel_offset r0, 0 @ Previous r0 is saved at sp.
1208 .cfi_rel_offset lr, 4 @ Previous lr is saved at sp + 4.
1211 @ Set the Z flag correctly, and the C flag unconditionally.
1213 @ Clear the C flag if the return value was -1, indicating
1214 @ that the first operand was smaller than the second.
1221 FUNC_END aeabi_cdcmple
1222 FUNC_END aeabi_cdcmpeq
1223 FUNC_END aeabi_cdrcmple
1225 ARM_FUNC_START aeabi_dcmpeq
1228 str lr, [sp, #-8]! @ sp -= 8
1229 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1230 .cfi_rel_offset lr, 0 @ lr is at sp
1232 ARM_CALL aeabi_cdcmple
1234 moveq r0, #1 @ Equal to.
1235 movne r0, #0 @ Less than, greater than, or unordered.
1240 FUNC_END aeabi_dcmpeq
1242 ARM_FUNC_START aeabi_dcmplt
1245 str lr, [sp, #-8]! @ sp -= 8
1246 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1247 .cfi_rel_offset lr, 0 @ lr is at sp
1249 ARM_CALL aeabi_cdcmple
1251 movcc r0, #1 @ Less than.
1252 movcs r0, #0 @ Equal to, greater than, or unordered.
1256 FUNC_END aeabi_dcmplt
1258 ARM_FUNC_START aeabi_dcmple
1261 str lr, [sp, #-8]! @ sp -= 8
1262 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1263 .cfi_rel_offset lr, 0 @ lr is at sp
1265 ARM_CALL aeabi_cdcmple
1267 movls r0, #1 @ Less than or equal to.
1268 movhi r0, #0 @ Greater than or unordered.
1272 FUNC_END aeabi_dcmple
1274 ARM_FUNC_START aeabi_dcmpge
1277 str lr, [sp, #-8]! @ sp -= 8
1278 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1279 .cfi_rel_offset lr, 0 @ lr is at sp
1281 ARM_CALL aeabi_cdrcmple
1283 movls r0, #1 @ Operand 2 is less than or equal to operand 1.
1284 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
1288 FUNC_END aeabi_dcmpge
1290 ARM_FUNC_START aeabi_dcmpgt
1293 str lr, [sp, #-8]! @ sp -= 8
1294 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1295 .cfi_rel_offset lr, 0 @ lr is at sp
1297 ARM_CALL aeabi_cdrcmple
1299 movcc r0, #1 @ Operand 2 is less than operand 1.
1300 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
1301 @ or they are unordered.
1305 FUNC_END aeabi_dcmpgt
1307 #endif /* L_cmpdf2 */
1309 #ifdef L_arm_unorddf2
1311 ARM_FUNC_START unorddf2
1312 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1316 mvns ip, ip, asr #21
1318 orrs ip, xl, xh, lsl #12
1320 1: mov ip, yh, lsl #1
1321 mvns ip, ip, asr #21
1323 orrs ip, yl, yh, lsl #12
1325 2: mov r0, #0 @ arguments are ordered.
1328 3: mov r0, #1 @ arguments are unordered.
1332 FUNC_END aeabi_dcmpun
1335 #endif /* L_unorddf2 */
1337 #ifdef L_arm_fixdfsi
1339 ARM_FUNC_START fixdfsi
1340 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1343 @ check exponent range.
1345 adds r2, r2, #(1 << 21)
1346 bcs 2f @ value is INF or NAN
1347 bpl 1f @ value is too small
1348 mov r3, #(0xfffffc00 + 31)
1349 subs r2, r3, r2, asr #21
1350 bls 3f @ value is too large
1354 orr r3, r3, #0x80000000
1355 orr r3, r3, xl, lsr #21
1356 tst xh, #0x80000000 @ the sign bit
1357 shift1 lsr, r0, r3, r2
1365 2: orrs xl, xl, xh, lsl #12
1367 3: ands r0, xh, #0x80000000 @ the sign bit
1369 moveq r0, #0x7fffffff @ maximum signed positive si
1372 4: mov r0, #0 @ How should we convert NAN?
1379 #endif /* L_fixdfsi */
1381 #ifdef L_arm_fixunsdfsi
1383 ARM_FUNC_START fixunsdfsi
1384 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1387 @ check exponent range.
1389 bcs 1f @ value is negative
1390 adds r2, r2, #(1 << 21)
1391 bcs 2f @ value is INF or NAN
1392 bpl 1f @ value is too small
1393 mov r3, #(0xfffffc00 + 31)
1394 subs r2, r3, r2, asr #21
1395 bmi 3f @ value is too large
1399 orr r3, r3, #0x80000000
1400 orr r3, r3, xl, lsr #21
1401 shift1 lsr, r0, r3, r2
1407 2: orrs xl, xl, xh, lsl #12
1408 bne 4f @ value is NAN.
1409 3: mov r0, #0xffffffff @ maximum unsigned si
1412 4: mov r0, #0 @ How should we convert NAN?
1416 FUNC_END aeabi_d2uiz
1419 #endif /* L_fixunsdfsi */
1421 #ifdef L_arm_truncdfsf2
1423 ARM_FUNC_START truncdfsf2
1424 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1427 @ check exponent range.
1429 subs r3, r2, #((1023 - 127) << 21)
1431 COND(sub,s,cs) ip, r3, #(1 << 21)
1432 COND(rsb,s,cs) ip, ip, #(254 << 21)
1433 bls 2f @ value is out of range
1435 1: @ shift and round mantissa
1436 and ip, xh, #0x80000000
1438 orr xl, ip, xl, lsr #29
1440 adc r0, xl, r3, lsl #2
1445 2: @ either overflow or underflow
1449 @ check if denormalized value is possible
1450 adds r2, r3, #(23 << 21)
1452 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1455 @ denormalize value so we can resume with the code above afterwards.
1456 orr xh, xh, #0x00100000
1460 #if defined(__thumb2__)
1465 shift1 lsr, xl, xl, r2
1467 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1470 shiftop orr xl xl r3 lsl ip ip
1471 shift1 lsr, r3, r3, r2
1476 mvns r3, r2, asr #21
1477 bne 5f @ simple overflow
1478 orrs r3, xl, xh, lsl #12
1480 movne r0, #0x7f000000
1481 orrne r0, r0, #0x00c00000
1482 RETc(ne) @ return NAN
1484 5: @ return INF with sign
1485 and r0, xh, #0x80000000
1486 orr r0, r0, #0x7f000000
1487 orr r0, r0, #0x00800000
1494 #endif /* L_truncdfsf2 */