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
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.
245 @ No rounding necessary since ip will always be 0 at this point.
257 movhs r2, r2, lsr #16
267 sublo r3, r3, r2, lsr #1
268 sub r3, r3, r2, lsr #3
283 @ determine how to shift the value.
289 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
290 @ since a register switch happened above.
293 shift1 lsl, xl, xh, ip
294 shift1 lsr, xh, xh, r2
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.
302 shift1 lsl, xh, xh, r2
303 #if defined(__thumb2__)
309 orrle xh, xh, xl, lsr ip
313 @ adjust exponent accordingly.
316 addge xh, xh, r4, lsl #20
320 @ Exponent too small, denormalize result.
321 @ Find out proper shift value.
328 @ shift result right of 1 to 20 bits, sign is in r5.
331 shift1 lsr, xl, xl, r4
332 shiftop orr xl xl xh lsl r2 yh
333 shiftop orr xh r5 xh lsr r4 yh
336 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
337 @ a register switch from xh to xl.
340 shift1 lsr, xl, xl, r2
341 shiftop orr xl xl xh lsl r4 yh
345 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
347 2: shift1 lsr, xl, xh, r4
351 @ Adjust exponents for denormalized arguments.
352 @ Note that r4 must not remain equal to 0.
355 eor yh, yh, #0x00100000
357 eoreq xh, xh, #0x00100000
366 COND(mvn,s,ne) ip, r5, asr #21
374 @ Result is x + 0.0 = x or 0.0 + y = y.
383 @ Result is x - x = 0.
389 @ Result is x + x = 2x.
395 orrcs xh, xh, #0x80000000
397 2: adds r4, r4, #(2 << 21)
399 addcc xh, xh, #(1 << 20)
401 and r5, xh, #0x80000000
403 @ Overflow: return INF.
405 orr xh, r5, #0x7f000000
406 orr xh, xh, #0x00f00000
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)
421 COND(mvn,s,eq) ip, r5, asr #21
425 orrs r4, xl, xh, lsl #12
427 COND(orr,s,eq) r5, yl, yh, lsl #12
429 orrne xh, xh, #0x00080000 @ quiet NAN
438 ARM_FUNC_START floatunsidf
439 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
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
466 ARM_FUNC_START floatsidf
467 ARM_FUNC_ALIAS aeabi_i2d floatsidf
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
485 rsbmi r0, r0, #0 @ absolute value
496 ARM_FUNC_START extendsfdf2
497 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
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
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
516 orreq xh, xh, #0x00080000 @ change to quiet NAN
517 RETc(eq) @ and return it.
519 @ value was denormalized. We can normalize it now.
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
535 ARM_FUNC_START floatundidf
536 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
538 .cfi_remember_state @ Save the current CFA state.
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
553 ARM_FUNC_START floatdidf
554 ARM_FUNC_ALIAS aeabi_l2d floatdidf
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.
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
572 #if defined(__thumb2__)
574 sbc ah, ah, ah, lsl #1
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.
593 @ The value is too big. Scale it down a bit...
601 add r2, r2, ip, lsr #3
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
617 #endif /* L_addsubdf3 */
619 #ifdef L_arm_muldivdf3
621 ARM_FUNC_START muldf3
622 ARM_FUNC_ALIAS aeabi_dmul muldf3
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.
635 ands r4, ip, xh, lsr #20
637 COND(and,s,ne) r5, ip, yh, lsr #20
642 @ Add exponents together
645 @ Determine final sign.
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
654 COND(orr,s,ne) r5, yl, yh, lsl #12
655 orr xh, xh, #0x00100000
656 orr yh, yh, #0x00100000
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
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
686 adds ip, ip, fp, lsl #16
687 adc lr, lr, fp, lsr #16
689 adds ip, ip, fp, lsl #16
690 adc lr, lr, fp, lsr #16
693 adds lr, lr, fp, lsl #16
694 adc r5, r5, fp, lsr #16
696 adds lr, lr, fp, lsl #16
697 adc r5, r5, fp, lsr #16
699 adds lr, lr, fp, lsl #16
700 adc r5, r5, fp, lsr #16
702 adds lr, lr, fp, lsl #16
703 adc r5, r5, fp, lsr #16
706 adds r5, r5, fp, lsl #16
707 adc r6, r6, fp, lsr #16
709 adds r5, r5, fp, lsl #16
710 adc r6, r6, fp, lsr #16
726 ldmfd sp!, {yl, r7, r8, r9, sl, fp} @ sp += 24
727 .cfi_restore_state @ Restore the previous CFI state.
730 @ Here is the actual multiplication.
734 and yl, r6, #0x80000000
741 @ The LSBs in ip are only significant for the final rounding.
747 @ Adjust result upon the MSB position.
749 cmp r6, #(1 << (20-11))
756 @ Shift to final position, add sign to result.
757 orr xh, yl, r6, lsl #11
758 orr xh, xh, r5, lsr #21
760 orr xl, xl, lr, lsr #21
763 @ Check exponent range for under/overflow.
764 subs ip, r4, #(254 - 1)
769 @ Round the result, merge final exponent.
772 COND(mov,s,eq) lr, xl, lsr #1
774 adc xh, xh, r4, lsl #20
777 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
779 and r6, r6, #0x80000000
783 subs r4, r4, ip, lsr #1
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
797 @ Check if denormalized result is possible, otherwise return signed 0.
801 bicle xh, xh, #0x7fffffff
802 RETLDM "r4, r5, r6" le
804 @ Find out proper shift value.
811 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
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
823 biceq xl, xl, r3, lsr #31
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.
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
836 orrs lr, lr, r3, lsl #1
838 biceq xl, xl, r3, lsr #31
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.
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
853 biceq xl, xl, r3, lsr #31
856 @ One or both arguments are denormalized.
857 @ Scale them leftwards and preserve sign bit.
861 and r6, xh, #0x80000000
862 1: movs xl, xl, lsl #1
872 2: and r6, yh, #0x80000000
873 3: movs yl, yl, lsl #1
883 @ Isolate the INF and NAN cases away
885 and r5, ip, yh, lsr #20
890 @ Here, one or more arguments are either denormalized or zero.
891 orrs r6, xl, xh, lsl #1
893 COND(orr,s,ne) r6, yl, yh, lsl #1
896 @ Result is 0, but determine sign anyway.
899 and xh, xh, #0x80000000
903 1: @ One or both args are INF or NAN.
904 orrs r6, xl, xh, lsl #1
908 COND(orr,s,ne) r6, yl, yh, lsl #1
909 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
912 orrs r6, xl, xh, lsl #12
913 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
916 orrs r6, yl, yh, lsl #12
920 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
922 @ Result is INF, but we need to determine its sign.
926 @ Overflow: return INF (sign already in xh).
928 and xh, xh, #0x80000000
929 orr xh, xh, #0x7f000000
930 orr xh, xh, #0x00f00000
934 @ Return a quiet NAN.
936 orr xh, xh, #0x7f000000
937 orr xh, xh, #0x00f80000
944 ARM_FUNC_START divdf3
945 ARM_FUNC_ALIAS aeabi_ddiv divdf3
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.
958 ands r4, ip, xh, lsr #20
960 COND(and,s,ne) r5, ip, yh, lsr #20
965 @ Subtract divisor exponent from dividend''s.
968 @ Preserve final sign into lr.
971 @ Convert mantissa to unsigned integer.
972 @ Dividend -> r5-r6, divisor -> yh-yl.
973 orrs r5, yl, yh, lsl #12
978 orr yh, r5, yh, lsr #4
979 orr yh, yh, yl, lsr #24
981 orr r5, r5, xh, lsr #4
982 orr r5, r5, xl, lsr #24
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.
993 adc r4, r4, #(255 - 2)
999 @ Perform first subtraction to align result to a nibble.
1007 @ The actual division loop.
1021 orrcs xl, xl, ip, lsr #1
1029 orrcs xl, xl, ip, lsr #2
1037 orrcs xl, xl, ip, lsr #3
1042 orr r5, r5, r6, lsr #28
1045 orr yh, yh, yl, lsr #29
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.
1059 @ Be sure result starts in the high word.
1065 @ Check exponent range for under/overflow.
1066 subs ip, r4, #(254 - 1)
1071 @ Round the result, merge final exponent.
1074 COND(sub,s,eq) ip, r6, yl
1075 COND(mov,s,eq) ip, xl, lsr #1
1077 adc xh, xh, r4, lsl #20
1080 @ Division by 0x1p*: shortcut a lot of code.
1082 and lr, lr, #0x80000000
1083 orr xh, lr, xh, lsr #12
1084 adds r4, r4, ip, lsr #1
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
1095 @ Result mightt need to be denormalized: put remainder bits
1096 @ in lr for rounding considerations.
1101 @ One or both arguments is either INF, NAN or zero.
1103 and r5, ip, yh, lsr #20
1107 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1110 orrs r4, xl, xh, lsl #12
1111 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1113 bne LSYM(Lml_i) @ INF / <anything> -> INF
1116 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1119 orrs r5, yl, yh, lsl #12
1120 beq LSYM(Lml_z) @ <anything> / INF -> 0
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
1127 COND(orr,s,ne) r6, yl, yh, lsl #1
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
1140 #endif /* L_muldivdf3 */
1144 @ Note: only r0 (return value) and ip are clobbered here.
1146 ARM_FUNC_START gtdf2
1147 ARM_FUNC_ALIAS gedf2 gtdf2
1152 ARM_FUNC_START ltdf2
1153 ARM_FUNC_ALIAS ledf2 ltdf2
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.
1170 mvns ip, ip, asr #21
1173 COND(mvn,s,ne) ip, ip, asr #21
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.
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
1189 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1190 teqne xh, yh @ or xh == yh
1192 teqeq xl, yl @ and xl == yl
1193 moveq r0, #0 @ then equal.
1202 @ Compare values if same sign
1210 movcs r0, yh, asr #31
1211 mvncc r0, yh, asr #31
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).
1222 mvns ip, ip, asr #21
1224 orrs ip, xl, xh, lsl #12
1226 4: mov ip, yh, lsl #1
1227 mvns ip, ip, asr #21
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.
1246 ARM_FUNC_START aeabi_cdrcmple
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.
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.
1268 @ Set the Z flag correctly, and the C flag unconditionally.
1270 @ Clear the C flag if the return value was -1, indicating
1271 @ that the first operand was smaller than the second.
1278 FUNC_END aeabi_cdcmple
1279 FUNC_END aeabi_cdcmpeq
1280 FUNC_END aeabi_cdrcmple
1282 ARM_FUNC_START aeabi_dcmpeq
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
1291 moveq r0, #1 @ Equal to.
1292 movne r0, #0 @ Less than, greater than, or unordered.
1297 FUNC_END aeabi_dcmpeq
1299 ARM_FUNC_START aeabi_dcmplt
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
1308 movcc r0, #1 @ Less than.
1309 movcs r0, #0 @ Equal to, greater than, or unordered.
1313 FUNC_END aeabi_dcmplt
1315 ARM_FUNC_START aeabi_dcmple
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
1324 movls r0, #1 @ Less than or equal to.
1325 movhi r0, #0 @ Greater than or unordered.
1329 FUNC_END aeabi_dcmple
1331 ARM_FUNC_START aeabi_dcmpge
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
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.
1345 FUNC_END aeabi_dcmpge
1347 ARM_FUNC_START aeabi_dcmpgt
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
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.
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
1373 mvns ip, ip, asr #21
1375 orrs ip, xl, xh, lsl #12
1377 1: mov ip, yh, lsl #1
1378 mvns ip, ip, asr #21
1380 orrs ip, yl, yh, lsl #12
1382 2: mov r0, #0 @ arguments are ordered.
1385 3: mov r0, #1 @ arguments are unordered.
1389 FUNC_END aeabi_dcmpun
1392 #endif /* L_unorddf2 */
1394 #ifdef L_arm_fixdfsi
1396 ARM_FUNC_START fixdfsi
1397 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1400 @ check exponent range.
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
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
1422 2: orrs xl, xl, xh, lsl #12
1424 3: ands r0, xh, #0x80000000 @ the sign bit
1426 moveq r0, #0x7fffffff @ maximum signed positive si
1429 4: mov r0, #0 @ How should we convert NAN?
1436 #endif /* L_fixdfsi */
1438 #ifdef L_arm_fixunsdfsi
1440 ARM_FUNC_START fixunsdfsi
1441 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1444 @ check exponent range.
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
1456 orr r3, r3, #0x80000000
1457 orr r3, r3, xl, lsr #21
1458 shift1 lsr, r0, r3, r2
1464 2: orrs xl, xl, xh, lsl #12
1465 bne 4f @ value is NAN.
1466 3: mov r0, #0xffffffff @ maximum unsigned si
1469 4: mov r0, #0 @ How should we convert NAN?
1473 FUNC_END aeabi_d2uiz
1476 #endif /* L_fixunsdfsi */
1478 #ifdef L_arm_truncdfsf2
1480 ARM_FUNC_START truncdfsf2
1481 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1484 @ check exponent range.
1486 subs r3, r2, #((1023 - 127) << 21)
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
1495 orr xl, ip, xl, lsr #29
1497 adc r0, xl, r3, lsl #2
1502 2: @ either overflow or underflow
1506 @ check if denormalized value is possible
1507 adds r2, r3, #(23 << 21)
1509 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1512 @ denormalize value so we can resume with the code above afterwards.
1513 orr xh, xh, #0x00100000
1517 #if defined(__thumb2__)
1522 shift1 lsr, xl, xl, r2
1524 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1527 shiftop orr xl xl r3 lsl ip ip
1528 shift1 lsr, r3, r3, r2
1533 mvns r3, r2, asr #21
1534 bne 5f @ simple overflow
1535 orrs r3, xl, xh, lsl #12
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
1551 #endif /* L_truncdfsf2 */