Home | History | Annotate | Line # | Download | only in arm
ieee754-df.S revision 1.8
      1 /* ieee754-df.S double-precision floating point support for ARM
      2 
      3    Copyright (C) 2003-2019 Free Software Foundation, Inc.
      4    Contributed by Nicolas Pitre (nico (at) fluxnic.net)
      5 
      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.
     10 
     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.
     15 
     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.
     19 
     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/>.  */
     24 
     25 /*
     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  */
     40 
     41 	.cfi_sections .debug_frame
     42 
     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
     54 
     55 
     56 #ifdef L_arm_negdf2
     57 
     58 ARM_FUNC_START negdf2
     59 ARM_FUNC_ALIAS aeabi_dneg negdf2
     60 	CFI_START_FUNCTION
     61 
     62 	@ flip sign bit
     63 	eor	xh, xh, #0x80000000
     64 	RET
     65 
     66 	CFI_END_FUNCTION
     67 	FUNC_END aeabi_dneg
     68 	FUNC_END negdf2
     69 
     70 #endif
     71 
     72 #ifdef L_arm_addsubdf3
     73 
     74 ARM_FUNC_START aeabi_drsub
     75 	CFI_START_FUNCTION
     76 
     77 	eor	xh, xh, #0x80000000	@ flip sign bit of first arg
     78 	b	1f
     79 
     80 ARM_FUNC_START subdf3
     81 ARM_FUNC_ALIAS aeabi_dsub subdf3
     82 
     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
     87 
     88 ARM_FUNC_START adddf3
     89 ARM_FUNC_ALIAS aeabi_dadd adddf3
     90 
     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
     96 
     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)
    109 
    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
    124 1:
    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
    131 
    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
    145 1:
    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
    157 1:
    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)
    162 
    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):
    168 
    169 	@ Compensate for the exponent overlapping the mantissa MSB added later
    170 	sub	r4, r4, #1
    171 
    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
    189 2:
    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
    204 
    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)
    211 
    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
    217 
    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)
    222 
    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"
    235 
    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 	subs	r4, r4, #1
    242 	do_it	hs
    243 	cmphs	xh, #0x00100000
    244 	bhs	LSYM(Lad_e)
    245 
    246 	@ No rounding necessary since ip will always be 0 at this point.
    247 LSYM(Lad_l):
    248 
    249 #if !defined (__ARM_FEATURE_CLZ)
    250 
    251 	teq	xh, #0
    252 	movne	r3, #20
    253 	moveq	r3, #52
    254 	moveq	xh, xl
    255 	moveq	xl, #0
    256 	mov	r2, xh
    257 	cmp	r2, #(1 << 16)
    258 	movhs	r2, r2, lsr #16
    259 	subhs	r3, r3, #16
    260 	cmp	r2, #(1 << 8)
    261 	movhs	r2, r2, lsr #8
    262 	subhs	r3, r3, #8
    263 	cmp	r2, #(1 << 4)
    264 	movhs	r2, r2, lsr #4
    265 	subhs	r3, r3, #4
    266 	cmp	r2, #(1 << 2)
    267 	subhs	r3, r3, #2
    268 	sublo	r3, r3, r2, lsr #1
    269 	sub	r3, r3, r2, lsr #3
    270 
    271 #else
    272 
    273 	teq	xh, #0
    274 	do_it	eq, t
    275 	moveq	xh, xl
    276 	moveq	xl, #0
    277 	clz	r3, xh
    278 	do_it	eq
    279 	addeq	r3, r3, #32
    280 	sub	r3, r3, #11
    281 
    282 #endif
    283 
    284 	@ determine how to shift the value.
    285 	subs	r2, r3, #32
    286 	bge	2f
    287 	adds	r2, r2, #12
    288 	ble	1f
    289 
    290 	@ shift value left 21 to 31 bits, or actually right 11 to 1 bits
    291 	@ since a register switch happened above.
    292 	add	ip, r2, #20
    293 	rsb	r2, r2, #12
    294 	shift1	lsl, xl, xh, ip
    295 	shift1	lsr, xh, xh, r2
    296 	b	3f
    297 
    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.
    300 1:	add	r2, r2, #20
    301 2:	do_it	le
    302 	rsble	ip, r2, #32
    303 	shift1	lsl, xh, xh, r2
    304 #if defined(__thumb2__)
    305 	lsr	ip, xl, ip
    306 	itt	le
    307 	orrle	xh, xh, ip
    308 	lslle	xl, xl, r2
    309 #else
    310 	orrle	xh, xh, xl, lsr ip
    311 	movle	xl, xl, lsl r2
    312 #endif
    313 
    314 	@ adjust exponent accordingly.
    315 3:	subs	r4, r4, r3
    316 	do_it	ge, tt
    317 	addge	xh, xh, r4, lsl #20
    318 	orrge	xh, xh, r5
    319 	RETLDM	"r4, r5" ge
    320 
    321 	@ Exponent too small, denormalize result.
    322 	@ Find out proper shift value.
    323 	mvn	r4, r4
    324 	subs	r4, r4, #31
    325 	bge	2f
    326 	adds	r4, r4, #12
    327 	bgt	1f
    328 
    329 	@ shift result right of 1 to 20 bits, sign is in r5.
    330 	add	r4, r4, #20
    331 	rsb	r2, r4, #32
    332 	shift1	lsr, xl, xl, r4
    333 	shiftop orr xl xl xh lsl r2 yh
    334 	shiftop orr xh r5 xh lsr r4 yh
    335 	RETLDM	"r4, r5"
    336 
    337 	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
    338 	@ a register switch from xh to xl.
    339 1:	rsb	r4, r4, #12
    340 	rsb	r2, r4, #32
    341 	shift1	lsr, xl, xl, r2
    342 	shiftop orr xl xl xh lsl r4 yh
    343 	mov	xh, r5
    344 	RETLDM	"r4, r5"
    345 
    346 	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
    347 	@ from xh to xl.
    348 2:	shift1	lsr, xl, xh, r4
    349 	mov	xh, r5
    350 	RETLDM	"r4, r5"
    351 
    352 	@ Adjust exponents for denormalized arguments.
    353 	@ Note that r4 must not remain equal to 0.
    354 LSYM(Lad_d):
    355 	teq	r4, #0
    356 	eor	yh, yh, #0x00100000
    357 	do_it	eq, te
    358 	eoreq	xh, xh, #0x00100000
    359 	addeq	r4, r4, #1
    360 	subne	r5, r5, #1
    361 	b	LSYM(Lad_x)
    362 
    363 
    364 LSYM(Lad_s):
    365 	mvns	ip, r4, asr #21
    366 	do_it	ne
    367 	COND(mvn,s,ne)	ip, r5, asr #21
    368 	beq	LSYM(Lad_i)
    369 
    370 	teq	r4, r5
    371 	do_it	eq
    372 	teqeq	xl, yl
    373 	beq	1f
    374 
    375 	@ Result is x + 0.0 = x or 0.0 + y = y.
    376 	orrs	ip, r4, xl
    377 	do_it	eq, t
    378 	moveq	xh, yh
    379 	moveq	xl, yl
    380 	RETLDM	"r4, r5"
    381 
    382 1:	teq	xh, yh
    383 
    384 	@ Result is x - x = 0.
    385 	do_it	ne, tt
    386 	movne	xh, #0
    387 	movne	xl, #0
    388 	RETLDM	"r4, r5" ne
    389 
    390 	@ Result is x + x = 2x.
    391 	movs	ip, r4, lsr #21
    392 	bne	2f
    393 	movs	xl, xl, lsl #1
    394 	adcs	xh, xh, xh
    395 	do_it	cs
    396 	orrcs	xh, xh, #0x80000000
    397 	RETLDM	"r4, r5"
    398 2:	adds	r4, r4, #(2 << 21)
    399 	do_it	cc, t
    400 	addcc	xh, xh, #(1 << 20)
    401 	RETLDM	"r4, r5" cc
    402 	and	r5, xh, #0x80000000
    403 
    404 	@ Overflow: return INF.
    405 LSYM(Lad_o):
    406 	orr	xh, r5, #0x7f000000
    407 	orr	xh, xh, #0x00f00000
    408 	mov	xl, #0
    409 	RETLDM	"r4, r5"
    410 
    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)
    417 LSYM(Lad_i):
    418 	mvns	ip, r4, asr #21
    419 	do_it	ne, te
    420 	movne	xh, yh
    421 	movne	xl, yl
    422 	COND(mvn,s,eq)	ip, r5, asr #21
    423 	do_it	ne, t
    424 	movne	yh, xh
    425 	movne	yl, xl
    426 	orrs	r4, xl, xh, lsl #12
    427 	do_it	eq, te
    428 	COND(orr,s,eq)	r5, yl, yh, lsl #12
    429 	teqeq	xh, yh
    430 	orrne	xh, xh, #0x00080000	@ quiet NAN
    431 	RETLDM	"r4, r5"
    432 
    433 	CFI_END_FUNCTION
    434 	FUNC_END aeabi_dsub
    435 	FUNC_END subdf3
    436 	FUNC_END aeabi_dadd
    437 	FUNC_END adddf3
    438 
    439 ARM_FUNC_START floatunsidf
    440 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
    441 	CFI_START_FUNCTION
    442 
    443 	teq	r0, #0
    444 	do_it	eq, t
    445 	moveq	r1, #0
    446 	RETc(eq)
    447 
    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
    453 
    454 	mov	r4, #0x400		@ initial exponent
    455 	add	r4, r4, #(52-1 - 1)
    456 	mov	r5, #0			@ sign bit is 0
    457 	.ifnc	xl, r0
    458 	mov	xl, r0
    459 	.endif
    460 	mov	xh, #0
    461 	b	LSYM(Lad_l)
    462 
    463 	CFI_END_FUNCTION
    464 	FUNC_END aeabi_ui2d
    465 	FUNC_END floatunsidf
    466 
    467 ARM_FUNC_START floatsidf
    468 ARM_FUNC_ALIAS aeabi_i2d floatsidf
    469 	CFI_START_FUNCTION
    470 
    471 	teq	r0, #0
    472 	do_it	eq, t
    473 	moveq	r1, #0
    474 	RETc(eq)
    475 
    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
    481 
    482 	mov	r4, #0x400		@ initial exponent
    483 	add	r4, r4, #(52-1 - 1)
    484 	ands	r5, r0, #0x80000000	@ sign bit in r5
    485 	do_it	mi
    486 	rsbmi	r0, r0, #0		@ absolute value
    487 	.ifnc	xl, r0
    488 	mov	xl, r0
    489 	.endif
    490 	mov	xh, #0
    491 	b	LSYM(Lad_l)
    492 
    493 	CFI_END_FUNCTION
    494 	FUNC_END aeabi_i2d
    495 	FUNC_END floatsidf
    496 
    497 ARM_FUNC_START extendsfdf2
    498 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
    499 	CFI_START_FUNCTION
    500 
    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
    505 	do_it	ne, ttt
    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.
    510 
    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.
    514 
    515 	teq	r3, #0xff000000		@ check for NAN
    516 	do_it	eq, t
    517 	orreq	xh, xh, #0x00080000	@ change to quiet NAN
    518 	RETc(eq)			@ and return it.
    519 
    520 	@ value was denormalized.  We can normalize it now.
    521 	do_push	{r4, r5, lr}
    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
    526 
    527 	mov	r4, #0x380		@ setup corresponding exponent
    528 	and	r5, xh, #0x80000000	@ move sign bit in r5
    529 	bic	xh, xh, #0x80000000
    530 	b	LSYM(Lad_l)
    531 
    532 	CFI_END_FUNCTION
    533 	FUNC_END aeabi_f2d
    534 	FUNC_END extendsfdf2
    535 
    536 ARM_FUNC_START floatundidf
    537 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
    538 	CFI_START_FUNCTION
    539 	.cfi_remember_state        @ Save the current CFA state.
    540 
    541 	orrs	r2, r0, r1
    542 	do_it	eq
    543 	RETc(eq)
    544 
    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
    550 
    551 	mov	r5, #0
    552 	b	2f
    553 
    554 ARM_FUNC_START floatdidf
    555 ARM_FUNC_ALIAS aeabi_l2d floatdidf
    556 	.cfi_restore_state
    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.
    560 
    561 	orrs	r2, r0, r1
    562 	do_it	eq
    563 	RETc(eq)
    564 
    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
    570 
    571 	ands	r5, ah, #0x80000000	@ sign bit in r5
    572 	bpl	2f
    573 #if defined(__thumb2__)
    574 	negs	al, al
    575 	sbc	ah, ah, ah, lsl #1
    576 #else
    577 	rsbs	al, al, #0
    578 	rsc	ah, ah, #0
    579 #endif
    580 2:
    581 	mov	r4, #0x400		@ initial exponent
    582 	add	r4, r4, #(52-1 - 1)
    583 
    584 	@ If FP word order does not match integer word order, swap the words.
    585 	.ifnc	xh, ah
    586 	mov	ip, al
    587 	mov	xh, ah
    588 	mov	xl, ip
    589 	.endif
    590 
    591 	movs	ip, xh, lsr #22
    592 	beq	LSYM(Lad_p)
    593 
    594 	@ The value is too big.  Scale it down a bit...
    595 	mov	r2, #3
    596 	movs	ip, ip, lsr #3
    597 	do_it	ne
    598 	addne	r2, r2, #3
    599 	movs	ip, ip, lsr #3
    600 	do_it	ne
    601 	addne	r2, r2, #3
    602 	add	r2, r2, ip, lsr #3
    603 
    604 	rsb	r3, r2, #32
    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
    609 	add	r4, r4, r2
    610 	b	LSYM(Lad_p)
    611 
    612 	CFI_END_FUNCTION
    613 	FUNC_END floatdidf
    614 	FUNC_END aeabi_l2d
    615 	FUNC_END floatundidf
    616 	FUNC_END aeabi_ul2d
    617 
    618 #endif /* L_addsubdf3 */
    619 
    620 #if defined(L_arm_muldf3) || defined(L_arm_muldivdf3)
    621 
    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.
    628 #ifdef L_arm_muldf3
    629 WEAK muldf3
    630 WEAK aeabi_dmul
    631 #endif
    632 
    633 ARM_FUNC_START muldf3
    634 ARM_FUNC_ALIAS aeabi_dmul muldf3
    635 	CFI_START_FUNCTION
    636 
    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
    643 
    644 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    645 	mov	ip, #0xff
    646 	orr	ip, ip, #0x700
    647 	ands	r4, ip, xh, lsr #20
    648 	do_it	ne, tte
    649 	COND(and,s,ne)	r5, ip, yh, lsr #20
    650 	teqne	r4, ip
    651 	teqne	r5, ip
    652 	bleq	LSYM(Lml_s)
    653 
    654 	@ Add exponents together
    655 	add	r4, r4, r5
    656 
    657 	@ Determine final sign.
    658 	eor	r6, xh, yh
    659 
    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
    665 	do_it	ne
    666 	COND(orr,s,ne)	r5, yl, yh, lsl #12
    667 	orr	xh, xh, #0x00100000
    668 	orr	yh, yh, #0x00100000
    669 	beq	LSYM(Lml_1)
    670 
    671 	@ Here is the actual multiplication.
    672 	@ This code works on architecture versions >= 4
    673 	umull	ip, lr, xl, yl
    674 	mov	r5, #0
    675 	umlal	lr, r5, xh, yl
    676 	and	yl, r6, #0x80000000
    677 	umlal	lr, r5, xl, yh
    678 	mov	r6, #0
    679 	umlal	r5, r6, xh, yh
    680 
    681 	@ The LSBs in ip are only significant for the final rounding.
    682 	@ Fold them into lr.
    683 	teq	ip, #0
    684 	do_it	ne
    685 	orrne	lr, lr, #1
    686 
    687 	@ Adjust result upon the MSB position.
    688 	sub	r4, r4, #0xff
    689 	cmp	r6, #(1 << (20-11))
    690 	sbc	r4, r4, #0x300
    691 	bcs	1f
    692 	movs	lr, lr, lsl #1
    693 	adcs	r5, r5, r5
    694 	adc	r6, r6, r6
    695 1:
    696 	@ Shift to final position, add sign to result.
    697 	orr	xh, yl, r6, lsl #11
    698 	orr	xh, xh, r5, lsr #21
    699 	mov	xl, r5, lsl #11
    700 	orr	xl, xl, lr, lsr #21
    701 	mov	lr, lr, lsl #11
    702 
    703 	@ Check exponent range for under/overflow.
    704 	subs	ip, r4, #(254 - 1)
    705 	do_it	hi
    706 	cmphi	ip, #0x700
    707 	bhi	LSYM(Lml_u)
    708 
    709 	@ Round the result, merge final exponent.
    710 	cmp	lr, #0x80000000
    711 	do_it	eq
    712 	COND(mov,s,eq)	lr, xl, lsr #1
    713 	adcs	xl, xl, #0
    714 	adc	xh, xh, r4, lsl #20
    715 	RETLDM	"r4, r5, r6"
    716 
    717 	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
    718 LSYM(Lml_1):
    719 	and	r6, r6, #0x80000000
    720 	orr	xh, r6, xh
    721 	orr	xl, xl, yl
    722 	eor	xh, xh, yh
    723 	subs	r4, r4, ip, lsr #1
    724 	do_it	gt, tt
    725 	COND(rsb,s,gt)	r5, r4, ip
    726 	orrgt	xh, xh, r4, lsl #20
    727 	RETLDM	"r4, r5, r6" gt
    728 
    729 	@ Under/overflow: fix things up for the code below.
    730 	orr	xh, xh, #0x00100000
    731 	mov	lr, #0
    732 	subs	r4, r4, #1
    733 LSYM(Lml_u):
    734 	@ Overflow?
    735 	bgt	LSYM(Lml_o)
    736 
    737 	@ Check if denormalized result is possible, otherwise return signed 0.
    738 	cmn	r4, #(53 + 1)
    739 	do_it	le, tt
    740 	movle	xl, #0
    741 	bicle	xh, xh, #0x7fffffff
    742 	RETLDM	"r4, r5, r6" le
    743 
    744 	@ Find out proper shift value.
    745 	rsb	r4, r4, #0
    746 	subs	r4, r4, #32
    747 	bge	2f
    748 	adds	r4, r4, #12
    749 	bgt	1f
    750 
    751 	@ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
    752 	add	r4, r4, #20
    753 	rsb	r5, r4, #32
    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
    762 	do_it	eq
    763 	biceq	xl, xl, r3, lsr #31
    764 	RETLDM	"r4, r5, r6"
    765 
    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.
    768 1:	rsb	r4, r4, #12
    769 	rsb	r5, r4, #32
    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
    775 	adc	xh, xh, #0
    776 	orrs	lr, lr, r3, lsl #1
    777 	do_it	eq
    778 	biceq	xl, xl, r3, lsr #31
    779 	RETLDM	"r4, r5, r6"
    780 
    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.
    783 2:	rsb	r5, r4, #32
    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
    792 	do_it	eq
    793 	biceq	xl, xl, r3, lsr #31
    794 	RETLDM	"r4, r5, r6"
    795 
    796 	@ One or both arguments are denormalized.
    797 	@ Scale them leftwards and preserve sign bit.
    798 LSYM(Lml_d):
    799 	teq	r4, #0
    800 	bne	2f
    801 	and	r6, xh, #0x80000000
    802 1:	movs	xl, xl, lsl #1
    803 	adc	xh, xh, xh
    804 	tst	xh, #0x00100000
    805 	do_it	eq
    806 	subeq	r4, r4, #1
    807 	beq	1b
    808 	orr	xh, xh, r6
    809 	teq	r5, #0
    810 	do_it	ne
    811 	RETc(ne)
    812 2:	and	r6, yh, #0x80000000
    813 3:	movs	yl, yl, lsl #1
    814 	adc	yh, yh, yh
    815 	tst	yh, #0x00100000
    816 	do_it	eq
    817 	subeq	r5, r5, #1
    818 	beq	3b
    819 	orr	yh, yh, r6
    820 	RET
    821 
    822 LSYM(Lml_s):
    823 	@ Isolate the INF and NAN cases away
    824 	teq	r4, ip
    825 	and	r5, ip, yh, lsr #20
    826 	do_it	ne
    827 	teqne	r5, ip
    828 	beq	1f
    829 
    830 	@ Here, one or more arguments are either denormalized or zero.
    831 	orrs	r6, xl, xh, lsl #1
    832 	do_it	ne
    833 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    834 	bne	LSYM(Lml_d)
    835 
    836 	@ Result is 0, but determine sign anyway.
    837 LSYM(Lml_z):
    838 	eor	xh, xh, yh
    839 	and	xh, xh, #0x80000000
    840 	mov	xl, #0
    841 	RETLDM	"r4, r5, r6"
    842 
    843 1:	@ One or both args are INF or NAN.
    844 	orrs	r6, xl, xh, lsl #1
    845 	do_it	eq, te
    846 	moveq	xl, yl
    847 	moveq	xh, yh
    848 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    849 	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
    850 	teq	r4, ip
    851 	bne	1f
    852 	orrs	r6, xl, xh, lsl #12
    853 	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
    854 1:	teq	r5, ip
    855 	bne	LSYM(Lml_i)
    856 	orrs	r6, yl, yh, lsl #12
    857 	do_it	ne, t
    858 	movne	xl, yl
    859 	movne	xh, yh
    860 	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
    861 
    862 	@ Result is INF, but we need to determine its sign.
    863 LSYM(Lml_i):
    864 	eor	xh, xh, yh
    865 
    866 	@ Overflow: return INF (sign already in xh).
    867 LSYM(Lml_o):
    868 	and	xh, xh, #0x80000000
    869 	orr	xh, xh, #0x7f000000
    870 	orr	xh, xh, #0x00f00000
    871 	mov	xl, #0
    872 	RETLDM	"r4, r5, r6"
    873 
    874 	@ Return a quiet NAN.
    875 LSYM(Lml_n):
    876 	orr	xh, xh, #0x7f000000
    877 	orr	xh, xh, #0x00f80000
    878 	RETLDM	"r4, r5, r6"
    879 
    880 	CFI_END_FUNCTION
    881 	FUNC_END aeabi_dmul
    882 	FUNC_END muldf3
    883 
    884 #ifdef L_arm_muldivdf3
    885 
    886 ARM_FUNC_START divdf3
    887 ARM_FUNC_ALIAS aeabi_ddiv divdf3
    888 	CFI_START_FUNCTION
    889 
    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
    896 
    897 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    898 	mov	ip, #0xff
    899 	orr	ip, ip, #0x700
    900 	ands	r4, ip, xh, lsr #20
    901 	do_it	ne, tte
    902 	COND(and,s,ne)	r5, ip, yh, lsr #20
    903 	teqne	r4, ip
    904 	teqne	r5, ip
    905 	bleq	LSYM(Ldv_s)
    906 
    907 	@ Subtract divisor exponent from dividend''s.
    908 	sub	r4, r4, r5
    909 
    910 	@ Preserve final sign into lr.
    911 	eor	lr, xh, yh
    912 
    913 	@ Convert mantissa to unsigned integer.
    914 	@ Dividend -> r5-r6, divisor -> yh-yl.
    915 	orrs	r5, yl, yh, lsl #12
    916 	mov	xh, xh, lsl #12
    917 	beq	LSYM(Ldv_1)
    918 	mov	yh, yh, lsl #12
    919 	mov	r5, #0x10000000
    920 	orr	yh, r5, yh, lsr #4
    921 	orr	yh, yh, yl, lsr #24
    922 	mov	yl, yl, lsl #8
    923 	orr	r5, r5, xh, lsr #4
    924 	orr	r5, r5, xl, lsr #24
    925 	mov	r6, xl, lsl #8
    926 
    927 	@ Initialize xh with final sign bit.
    928 	and	xh, lr, #0x80000000
    929 
    930 	@ Ensure result will land to known bit position.
    931 	@ Apply exponent bias accordingly.
    932 	cmp	r5, yh
    933 	do_it	eq
    934 	cmpeq	r6, yl
    935 	adc	r4, r4, #(255 - 2)
    936 	add	r4, r4, #0x300
    937 	bcs	1f
    938 	movs	yh, yh, lsr #1
    939 	mov	yl, yl, rrx
    940 1:
    941 	@ Perform first subtraction to align result to a nibble.
    942 	subs	r6, r6, yl
    943 	sbc	r5, r5, yh
    944 	movs	yh, yh, lsr #1
    945 	mov	yl, yl, rrx
    946 	mov	xl, #0x00100000
    947 	mov	ip, #0x00080000
    948 
    949 	@ The actual division loop.
    950 1:	subs	lr, r6, yl
    951 	sbcs	lr, r5, yh
    952 	do_it	cs, tt
    953 	subcs	r6, r6, yl
    954 	movcs	r5, lr
    955 	orrcs	xl, xl, ip
    956 	movs	yh, yh, lsr #1
    957 	mov	yl, yl, rrx
    958 	subs	lr, r6, yl
    959 	sbcs	lr, r5, yh
    960 	do_it	cs, tt
    961 	subcs	r6, r6, yl
    962 	movcs	r5, lr
    963 	orrcs	xl, xl, ip, lsr #1
    964 	movs	yh, yh, lsr #1
    965 	mov	yl, yl, rrx
    966 	subs	lr, r6, yl
    967 	sbcs	lr, r5, yh
    968 	do_it	cs, tt
    969 	subcs	r6, r6, yl
    970 	movcs	r5, lr
    971 	orrcs	xl, xl, ip, lsr #2
    972 	movs	yh, yh, lsr #1
    973 	mov	yl, yl, rrx
    974 	subs	lr, r6, yl
    975 	sbcs	lr, r5, yh
    976 	do_it	cs, tt
    977 	subcs	r6, r6, yl
    978 	movcs	r5, lr
    979 	orrcs	xl, xl, ip, lsr #3
    980 
    981 	orrs	lr, r5, r6
    982 	beq	2f
    983 	mov	r5, r5, lsl #4
    984 	orr	r5, r5, r6, lsr #28
    985 	mov	r6, r6, lsl #4
    986 	mov	yh, yh, lsl #3
    987 	orr	yh, yh, yl, lsr #29
    988 	mov	yl, yl, lsl #3
    989 	movs	ip, ip, lsr #4
    990 	bne	1b
    991 
    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.
    994 	tst	xh, #0x00100000
    995 	bne	3f
    996 	orr	xh, xh, xl
    997 	mov	xl, #0
    998 	mov	ip, #0x80000000
    999 	b	1b
   1000 2:
   1001 	@ Be sure result starts in the high word.
   1002 	tst	xh, #0x00100000
   1003 	do_it	eq, t
   1004 	orreq	xh, xh, xl
   1005 	moveq	xl, #0
   1006 3:
   1007 	@ Check exponent range for under/overflow.
   1008 	subs	ip, r4, #(254 - 1)
   1009 	do_it	hi
   1010 	cmphi	ip, #0x700
   1011 	bhi	LSYM(Lml_u)
   1012 
   1013 	@ Round the result, merge final exponent.
   1014 	subs	ip, r5, yh
   1015 	do_it	eq, t
   1016 	COND(sub,s,eq)	ip, r6, yl
   1017 	COND(mov,s,eq)	ip, xl, lsr #1
   1018 	adcs	xl, xl, #0
   1019 	adc	xh, xh, r4, lsl #20
   1020 	RETLDM	"r4, r5, r6"
   1021 
   1022 	@ Division by 0x1p*: shortcut a lot of code.
   1023 LSYM(Ldv_1):
   1024 	and	lr, lr, #0x80000000
   1025 	orr	xh, lr, xh, lsr #12
   1026 	adds	r4, r4, ip, lsr #1
   1027 	do_it	gt, tt
   1028 	COND(rsb,s,gt)	r5, r4, ip
   1029 	orrgt	xh, xh, r4, lsl #20
   1030 	RETLDM	"r4, r5, r6" gt
   1031 
   1032 	orr	xh, xh, #0x00100000
   1033 	mov	lr, #0
   1034 	subs	r4, r4, #1
   1035 	b	LSYM(Lml_u)
   1036 
   1037 	@ Result mightt need to be denormalized: put remainder bits
   1038 	@ in lr for rounding considerations.
   1039 LSYM(Ldv_u):
   1040 	orr	lr, r5, r6
   1041 	b	LSYM(Lml_u)
   1042 
   1043 	@ One or both arguments is either INF, NAN or zero.
   1044 LSYM(Ldv_s):
   1045 	and	r5, ip, yh, lsr #20
   1046 	teq	r4, ip
   1047 	do_it	eq
   1048 	teqeq	r5, ip
   1049 	beq	LSYM(Lml_n)		@ INF/NAN / INF/NAN -> NAN
   1050 	teq	r4, ip
   1051 	bne	1f
   1052 	orrs	r4, xl, xh, lsl #12
   1053 	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
   1054 	teq	r5, ip
   1055 	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
   1056 	mov	xl, yl
   1057 	mov	xh, yh
   1058 	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
   1059 1:	teq	r5, ip
   1060 	bne	2f
   1061 	orrs	r5, yl, yh, lsl #12
   1062 	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
   1063 	mov	xl, yl
   1064 	mov	xh, yh
   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
   1068 	do_it	ne
   1069 	COND(orr,s,ne)	r6, yl, yh, lsl #1
   1070 	bne	LSYM(Lml_d)
   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
   1077 
   1078 	CFI_END_FUNCTION
   1079 	FUNC_END aeabi_ddiv
   1080 	FUNC_END divdf3
   1081 
   1082 #endif /* L_muldivdf3 */
   1083 #endif /* L_arm_muldf3 || L_arm_muldivdf3 */
   1084 
   1085 #ifdef L_arm_cmpdf2
   1086 
   1087 @ Note: only r0 (return value) and ip are clobbered here.
   1088 
   1089 ARM_FUNC_START gtdf2
   1090 ARM_FUNC_ALIAS gedf2 gtdf2
   1091 	CFI_START_FUNCTION
   1092 	mov	ip, #-1
   1093 	b	1f
   1094 
   1095 ARM_FUNC_START ltdf2
   1096 ARM_FUNC_ALIAS ledf2 ltdf2
   1097 	mov	ip, #1
   1098 	b	1f
   1099 
   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?
   1104 
   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).
   1110 
   1111 	@ Trap any INF/NAN first.
   1112 	mov	ip, xh, lsl #1
   1113 	mvns	ip, ip, asr #21
   1114 	mov	ip, yh, lsl #1
   1115 	do_it	ne
   1116 	COND(mvn,s,ne)	ip, ip, asr #21
   1117 	beq	3f
   1118 	.cfi_remember_state
   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.
   1125 
   1126 	@ Test for equality.  Note that 0.0 is equal to -0.0.
   1127 2:	add	sp, sp, #4
   1128 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1129 
   1130 	orrs	ip, xl, xh, lsl #1	@ if x == 0.0 or -0.0
   1131 	do_it	eq, e
   1132 	COND(orr,s,eq)	ip, yl, yh, lsl #1	@ and y == 0.0 or -0.0
   1133 	teqne	xh, yh			@ or xh == yh
   1134 	do_it	eq, tt
   1135 	teqeq	xl, yl			@ and xl == yl
   1136 	moveq	r0, #0			@ then equal.
   1137 	RETc(eq)
   1138 
   1139 	@ Clear C flag
   1140 	cmn	r0, #0
   1141 
   1142 	@ Compare sign,
   1143 	teq	xh, yh
   1144 
   1145 	@ Compare values if same sign
   1146 	do_it	pl
   1147 	cmppl	xh, yh
   1148 	do_it	eq
   1149 	cmpeq	xl, yl
   1150 
   1151 	@ Result:
   1152 	do_it	cs, e
   1153 	movcs	r0, yh, asr #31
   1154 	mvncc	r0, yh, asr #31
   1155 	orr	r0, r0, #1
   1156 	RET
   1157 
   1158 3:  @ Look for a NAN.
   1159 
   1160 	@ Restore the previous CFI state (i.e. keep the CFI state as it was
   1161 	@ before the branch).
   1162 	.cfi_restore_state
   1163 
   1164 	mov ip, xh, lsl #1
   1165 	mvns	ip, ip, asr #21
   1166 	bne	4f
   1167 	orrs	ip, xl, xh, lsl #12
   1168 	bne	5f			@ x is NAN
   1169 4:	mov	ip, yh, lsl #1
   1170 	mvns	ip, ip, asr #21
   1171 	bne	2b
   1172 	orrs	ip, yl, yh, lsl #12
   1173 	beq	2b			@ y is not NAN
   1174 
   1175 5:	ldr	r0, [sp], #4		@ unordered return code
   1176 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1177 
   1178 	RET
   1179 
   1180 	CFI_END_FUNCTION
   1181 	FUNC_END gedf2
   1182 	FUNC_END gtdf2
   1183 	FUNC_END ledf2
   1184 	FUNC_END ltdf2
   1185 	FUNC_END nedf2
   1186 	FUNC_END eqdf2
   1187 	FUNC_END cmpdf2
   1188 
   1189 ARM_FUNC_START aeabi_cdrcmple
   1190 	CFI_START_FUNCTION
   1191 
   1192 	mov	ip, r0
   1193 	mov	r0, r2
   1194 	mov	r2, ip
   1195 	mov	ip, r1
   1196 	mov	r1, r3
   1197 	mov	r3, ip
   1198 	b	6f
   1199 
   1200 ARM_FUNC_START aeabi_cdcmpeq
   1201 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
   1202 
   1203 	@ The status-returning routines are required to preserve all
   1204 	@ registers except ip, lr, and cpsr.
   1205 6:	do_push	{r0, lr}
   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.
   1209 
   1210 	ARM_CALL cmpdf2
   1211 	@ Set the Z flag correctly, and the C flag unconditionally.
   1212 	cmp	r0, #0
   1213 	@ Clear the C flag if the return value was -1, indicating
   1214 	@ that the first operand was smaller than the second.
   1215 	do_it	mi
   1216 	cmnmi	r0, #0
   1217 
   1218 	RETLDM	"r0"
   1219 
   1220 	CFI_END_FUNCTION
   1221 	FUNC_END aeabi_cdcmple
   1222 	FUNC_END aeabi_cdcmpeq
   1223 	FUNC_END aeabi_cdrcmple
   1224 
   1225 ARM_FUNC_START	aeabi_dcmpeq
   1226 	CFI_START_FUNCTION
   1227 
   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
   1231 
   1232 	ARM_CALL aeabi_cdcmple
   1233 	do_it	eq, e
   1234 	moveq	r0, #1	@ Equal to.
   1235 	movne	r0, #0	@ Less than, greater than, or unordered.
   1236 
   1237 	RETLDM
   1238 
   1239 	CFI_END_FUNCTION
   1240 	FUNC_END aeabi_dcmpeq
   1241 
   1242 ARM_FUNC_START	aeabi_dcmplt
   1243 	CFI_START_FUNCTION
   1244 
   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
   1248 
   1249 	ARM_CALL aeabi_cdcmple
   1250 	do_it	cc, e
   1251 	movcc	r0, #1	@ Less than.
   1252 	movcs	r0, #0	@ Equal to, greater than, or unordered.
   1253 	RETLDM
   1254 
   1255 	CFI_END_FUNCTION
   1256 	FUNC_END aeabi_dcmplt
   1257 
   1258 ARM_FUNC_START	aeabi_dcmple
   1259 	CFI_START_FUNCTION
   1260 
   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
   1264 
   1265 	ARM_CALL aeabi_cdcmple
   1266 	do_it	ls, e
   1267 	movls	r0, #1  @ Less than or equal to.
   1268 	movhi	r0, #0	@ Greater than or unordered.
   1269 	RETLDM
   1270 
   1271 	CFI_END_FUNCTION
   1272 	FUNC_END aeabi_dcmple
   1273 
   1274 ARM_FUNC_START	aeabi_dcmpge
   1275 	CFI_START_FUNCTION
   1276 
   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
   1280 
   1281 	ARM_CALL aeabi_cdrcmple
   1282 	do_it	ls, e
   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.
   1285 	RETLDM
   1286 
   1287 	CFI_END_FUNCTION
   1288 	FUNC_END aeabi_dcmpge
   1289 
   1290 ARM_FUNC_START	aeabi_dcmpgt
   1291 	CFI_START_FUNCTION
   1292 
   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
   1296 
   1297 	ARM_CALL aeabi_cdrcmple
   1298 	do_it	cc, e
   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.
   1302 	RETLDM
   1303 
   1304 	CFI_END_FUNCTION
   1305 	FUNC_END aeabi_dcmpgt
   1306 
   1307 #endif /* L_cmpdf2 */
   1308 
   1309 #ifdef L_arm_unorddf2
   1310 
   1311 ARM_FUNC_START unorddf2
   1312 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
   1313 	.cfi_startproc
   1314 
   1315 	mov	ip, xh, lsl #1
   1316 	mvns	ip, ip, asr #21
   1317 	bne	1f
   1318 	orrs	ip, xl, xh, lsl #12
   1319 	bne	3f			@ x is NAN
   1320 1:	mov	ip, yh, lsl #1
   1321 	mvns	ip, ip, asr #21
   1322 	bne	2f
   1323 	orrs	ip, yl, yh, lsl #12
   1324 	bne	3f			@ y is NAN
   1325 2:	mov	r0, #0			@ arguments are ordered.
   1326 	RET
   1327 
   1328 3:	mov	r0, #1			@ arguments are unordered.
   1329 	RET
   1330 
   1331 	.cfi_endproc
   1332 	FUNC_END aeabi_dcmpun
   1333 	FUNC_END unorddf2
   1334 
   1335 #endif /* L_unorddf2 */
   1336 
   1337 #ifdef L_arm_fixdfsi
   1338 
   1339 ARM_FUNC_START fixdfsi
   1340 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
   1341 	CFI_START_FUNCTION
   1342 
   1343 	@ check exponent range.
   1344 	mov	r2, xh, lsl #1
   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
   1351 
   1352 	@ scale value
   1353 	mov	r3, xh, lsl #11
   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
   1358 	do_it	ne
   1359 	rsbne	r0, r0, #0
   1360 	RET
   1361 
   1362 1:	mov	r0, #0
   1363 	RET
   1364 
   1365 2:	orrs	xl, xl, xh, lsl #12
   1366 	bne	4f			@ x is NAN.
   1367 3:	ands	r0, xh, #0x80000000	@ the sign bit
   1368 	do_it	eq
   1369 	moveq	r0, #0x7fffffff		@ maximum signed positive si
   1370 	RET
   1371 
   1372 4:	mov	r0, #0			@ How should we convert NAN?
   1373 	RET
   1374 
   1375 	CFI_END_FUNCTION
   1376 	FUNC_END aeabi_d2iz
   1377 	FUNC_END fixdfsi
   1378 
   1379 #endif /* L_fixdfsi */
   1380 
   1381 #ifdef L_arm_fixunsdfsi
   1382 
   1383 ARM_FUNC_START fixunsdfsi
   1384 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
   1385 	CFI_START_FUNCTION
   1386 
   1387 	@ check exponent range.
   1388 	movs	r2, xh, lsl #1
   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
   1396 
   1397 	@ scale value
   1398 	mov	r3, xh, lsl #11
   1399 	orr	r3, r3, #0x80000000
   1400 	orr	r3, r3, xl, lsr #21
   1401 	shift1	lsr, r0, r3, r2
   1402 	RET
   1403 
   1404 1:	mov	r0, #0
   1405 	RET
   1406 
   1407 2:	orrs	xl, xl, xh, lsl #12
   1408 	bne	4f			@ value is NAN.
   1409 3:	mov	r0, #0xffffffff		@ maximum unsigned si
   1410 	RET
   1411 
   1412 4:	mov	r0, #0			@ How should we convert NAN?
   1413 	RET
   1414 
   1415 	CFI_END_FUNCTION
   1416 	FUNC_END aeabi_d2uiz
   1417 	FUNC_END fixunsdfsi
   1418 
   1419 #endif /* L_fixunsdfsi */
   1420 
   1421 #ifdef L_arm_truncdfsf2
   1422 
   1423 ARM_FUNC_START truncdfsf2
   1424 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
   1425 	CFI_START_FUNCTION
   1426 
   1427 	@ check exponent range.
   1428 	mov	r2, xh, lsl #1
   1429 	subs	r3, r2, #((1023 - 127) << 21)
   1430 	do_it	cs, t
   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
   1434 
   1435 1:	@ shift and round mantissa
   1436 	and	ip, xh, #0x80000000
   1437 	mov	r2, xl, lsl #3
   1438 	orr	xl, ip, xl, lsr #29
   1439 	cmp	r2, #0x80000000
   1440 	adc	r0, xl, r3, lsl #2
   1441 	do_it	eq
   1442 	biceq	r0, r0, #1
   1443 	RET
   1444 
   1445 2:	@ either overflow or underflow
   1446 	tst	xh, #0x40000000
   1447 	bne	3f			@ overflow
   1448 
   1449 	@ check if denormalized value is possible
   1450 	adds	r2, r3, #(23 << 21)
   1451 	do_it	lt, t
   1452 	andlt	r0, xh, #0x80000000	@ too small, return signed 0.
   1453 	RETc(lt)
   1454 
   1455 	@ denormalize value so we can resume with the code above afterwards.
   1456 	orr	xh, xh, #0x00100000
   1457 	mov	r2, r2, lsr #21
   1458 	rsb	r2, r2, #24
   1459 	rsb	ip, r2, #32
   1460 #if defined(__thumb2__)
   1461 	lsls	r3, xl, ip
   1462 #else
   1463 	movs	r3, xl, lsl ip
   1464 #endif
   1465 	shift1	lsr, xl, xl, r2
   1466 	do_it	ne
   1467 	orrne	xl, xl, #1		@ fold r3 for rounding considerations.
   1468 	mov	r3, xh, lsl #11
   1469 	mov	r3, r3, lsr #11
   1470 	shiftop orr xl xl r3 lsl ip ip
   1471 	shift1	lsr, r3, r3, r2
   1472 	mov	r3, r3, lsl #1
   1473 	b	1b
   1474 
   1475 3:	@ chech for NAN
   1476 	mvns	r3, r2, asr #21
   1477 	bne	5f			@ simple overflow
   1478 	orrs	r3, xl, xh, lsl #12
   1479 	do_it	ne, tt
   1480 	movne	r0, #0x7f000000
   1481 	orrne	r0, r0, #0x00c00000
   1482 	RETc(ne)			@ return NAN
   1483 
   1484 5:	@ return INF with sign
   1485 	and	r0, xh, #0x80000000
   1486 	orr	r0, r0, #0x7f000000
   1487 	orr	r0, r0, #0x00800000
   1488 	RET
   1489 
   1490 	CFI_END_FUNCTION
   1491 	FUNC_END aeabi_d2f
   1492 	FUNC_END truncdfsf2
   1493 
   1494 #endif /* L_truncdfsf2 */
   1495