Home | History | Annotate | Line # | Download | only in arm
ieee754-df.S revision 1.1.1.4
      1 /* ieee754-df.S double-precision floating point support for ARM
      2 
      3    Copyright (C) 2003-2017 Free Software Foundation, Inc.
      4    Contributed by Nicolas Pitre (nico (at) cam.org)
      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 	tst	xh, #0x00100000
    242 	sub	r4, r4, #1
    243 	bne	LSYM(Lad_e)
    244 
    245 	@ No rounding necessary since ip will always be 0 at this point.
    246 LSYM(Lad_l):
    247 
    248 #if __ARM_ARCH__ < 5
    249 
    250 	teq	xh, #0
    251 	movne	r3, #20
    252 	moveq	r3, #52
    253 	moveq	xh, xl
    254 	moveq	xl, #0
    255 	mov	r2, xh
    256 	cmp	r2, #(1 << 16)
    257 	movhs	r2, r2, lsr #16
    258 	subhs	r3, r3, #16
    259 	cmp	r2, #(1 << 8)
    260 	movhs	r2, r2, lsr #8
    261 	subhs	r3, r3, #8
    262 	cmp	r2, #(1 << 4)
    263 	movhs	r2, r2, lsr #4
    264 	subhs	r3, r3, #4
    265 	cmp	r2, #(1 << 2)
    266 	subhs	r3, r3, #2
    267 	sublo	r3, r3, r2, lsr #1
    268 	sub	r3, r3, r2, lsr #3
    269 
    270 #else
    271 
    272 	teq	xh, #0
    273 	do_it	eq, t
    274 	moveq	xh, xl
    275 	moveq	xl, #0
    276 	clz	r3, xh
    277 	do_it	eq
    278 	addeq	r3, r3, #32
    279 	sub	r3, r3, #11
    280 
    281 #endif
    282 
    283 	@ determine how to shift the value.
    284 	subs	r2, r3, #32
    285 	bge	2f
    286 	adds	r2, r2, #12
    287 	ble	1f
    288 
    289 	@ shift value left 21 to 31 bits, or actually right 11 to 1 bits
    290 	@ since a register switch happened above.
    291 	add	ip, r2, #20
    292 	rsb	r2, r2, #12
    293 	shift1	lsl, xl, xh, ip
    294 	shift1	lsr, xh, xh, r2
    295 	b	3f
    296 
    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.
    299 1:	add	r2, r2, #20
    300 2:	do_it	le
    301 	rsble	ip, r2, #32
    302 	shift1	lsl, xh, xh, r2
    303 #if defined(__thumb2__)
    304 	lsr	ip, xl, ip
    305 	itt	le
    306 	orrle	xh, xh, ip
    307 	lslle	xl, xl, r2
    308 #else
    309 	orrle	xh, xh, xl, lsr ip
    310 	movle	xl, xl, lsl r2
    311 #endif
    312 
    313 	@ adjust exponent accordingly.
    314 3:	subs	r4, r4, r3
    315 	do_it	ge, tt
    316 	addge	xh, xh, r4, lsl #20
    317 	orrge	xh, xh, r5
    318 	RETLDM	"r4, r5" ge
    319 
    320 	@ Exponent too small, denormalize result.
    321 	@ Find out proper shift value.
    322 	mvn	r4, r4
    323 	subs	r4, r4, #31
    324 	bge	2f
    325 	adds	r4, r4, #12
    326 	bgt	1f
    327 
    328 	@ shift result right of 1 to 20 bits, sign is in r5.
    329 	add	r4, r4, #20
    330 	rsb	r2, r4, #32
    331 	shift1	lsr, xl, xl, r4
    332 	shiftop orr xl xl xh lsl r2 yh
    333 	shiftop orr xh r5 xh lsr r4 yh
    334 	RETLDM	"r4, r5"
    335 
    336 	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
    337 	@ a register switch from xh to xl.
    338 1:	rsb	r4, r4, #12
    339 	rsb	r2, r4, #32
    340 	shift1	lsr, xl, xl, r2
    341 	shiftop orr xl xl xh lsl r4 yh
    342 	mov	xh, r5
    343 	RETLDM	"r4, r5"
    344 
    345 	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
    346 	@ from xh to xl.
    347 2:	shift1	lsr, xl, xh, r4
    348 	mov	xh, r5
    349 	RETLDM	"r4, r5"
    350 
    351 	@ Adjust exponents for denormalized arguments.
    352 	@ Note that r4 must not remain equal to 0.
    353 LSYM(Lad_d):
    354 	teq	r4, #0
    355 	eor	yh, yh, #0x00100000
    356 	do_it	eq, te
    357 	eoreq	xh, xh, #0x00100000
    358 	addeq	r4, r4, #1
    359 	subne	r5, r5, #1
    360 	b	LSYM(Lad_x)
    361 
    362 
    363 LSYM(Lad_s):
    364 	mvns	ip, r4, asr #21
    365 	do_it	ne
    366 	COND(mvn,s,ne)	ip, r5, asr #21
    367 	beq	LSYM(Lad_i)
    368 
    369 	teq	r4, r5
    370 	do_it	eq
    371 	teqeq	xl, yl
    372 	beq	1f
    373 
    374 	@ Result is x + 0.0 = x or 0.0 + y = y.
    375 	orrs	ip, r4, xl
    376 	do_it	eq, t
    377 	moveq	xh, yh
    378 	moveq	xl, yl
    379 	RETLDM	"r4, r5"
    380 
    381 1:	teq	xh, yh
    382 
    383 	@ Result is x - x = 0.
    384 	do_it	ne, tt
    385 	movne	xh, #0
    386 	movne	xl, #0
    387 	RETLDM	"r4, r5" ne
    388 
    389 	@ Result is x + x = 2x.
    390 	movs	ip, r4, lsr #21
    391 	bne	2f
    392 	movs	xl, xl, lsl #1
    393 	adcs	xh, xh, xh
    394 	do_it	cs
    395 	orrcs	xh, xh, #0x80000000
    396 	RETLDM	"r4, r5"
    397 2:	adds	r4, r4, #(2 << 21)
    398 	do_it	cc, t
    399 	addcc	xh, xh, #(1 << 20)
    400 	RETLDM	"r4, r5" cc
    401 	and	r5, xh, #0x80000000
    402 
    403 	@ Overflow: return INF.
    404 LSYM(Lad_o):
    405 	orr	xh, r5, #0x7f000000
    406 	orr	xh, xh, #0x00f00000
    407 	mov	xl, #0
    408 	RETLDM	"r4, r5"
    409 
    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)
    416 LSYM(Lad_i):
    417 	mvns	ip, r4, asr #21
    418 	do_it	ne, te
    419 	movne	xh, yh
    420 	movne	xl, yl
    421 	COND(mvn,s,eq)	ip, r5, asr #21
    422 	do_it	ne, t
    423 	movne	yh, xh
    424 	movne	yl, xl
    425 	orrs	r4, xl, xh, lsl #12
    426 	do_it	eq, te
    427 	COND(orr,s,eq)	r5, yl, yh, lsl #12
    428 	teqeq	xh, yh
    429 	orrne	xh, xh, #0x00080000	@ quiet NAN
    430 	RETLDM	"r4, r5"
    431 
    432 	CFI_END_FUNCTION
    433 	FUNC_END aeabi_dsub
    434 	FUNC_END subdf3
    435 	FUNC_END aeabi_dadd
    436 	FUNC_END adddf3
    437 
    438 ARM_FUNC_START floatunsidf
    439 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
    440 	CFI_START_FUNCTION
    441 
    442 	teq	r0, #0
    443 	do_it	eq, t
    444 	moveq	r1, #0
    445 	RETc(eq)
    446 
    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
    452 
    453 	mov	r4, #0x400		@ initial exponent
    454 	add	r4, r4, #(52-1 - 1)
    455 	mov	r5, #0			@ sign bit is 0
    456 	.ifnc	xl, r0
    457 	mov	xl, r0
    458 	.endif
    459 	mov	xh, #0
    460 	b	LSYM(Lad_l)
    461 
    462 	CFI_END_FUNCTION
    463 	FUNC_END aeabi_ui2d
    464 	FUNC_END floatunsidf
    465 
    466 ARM_FUNC_START floatsidf
    467 ARM_FUNC_ALIAS aeabi_i2d floatsidf
    468 	CFI_START_FUNCTION
    469 
    470 	teq	r0, #0
    471 	do_it	eq, t
    472 	moveq	r1, #0
    473 	RETc(eq)
    474 
    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
    480 
    481 	mov	r4, #0x400		@ initial exponent
    482 	add	r4, r4, #(52-1 - 1)
    483 	ands	r5, r0, #0x80000000	@ sign bit in r5
    484 	do_it	mi
    485 	rsbmi	r0, r0, #0		@ absolute value
    486 	.ifnc	xl, r0
    487 	mov	xl, r0
    488 	.endif
    489 	mov	xh, #0
    490 	b	LSYM(Lad_l)
    491 
    492 	CFI_END_FUNCTION
    493 	FUNC_END aeabi_i2d
    494 	FUNC_END floatsidf
    495 
    496 ARM_FUNC_START extendsfdf2
    497 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
    498 	CFI_START_FUNCTION
    499 
    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
    504 	do_it	ne, ttt
    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.
    509 
    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.
    513 
    514 	teq	r3, #0xff000000		@ check for NAN
    515 	do_it	eq, t
    516 	orreq	xh, xh, #0x00080000	@ change to quiet NAN
    517 	RETc(eq)			@ and return it.
    518 
    519 	@ value was denormalized.  We can normalize it now.
    520 	do_push	{r4, r5, lr}
    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
    525 
    526 	mov	r4, #0x380		@ setup corresponding exponent
    527 	and	r5, xh, #0x80000000	@ move sign bit in r5
    528 	bic	xh, xh, #0x80000000
    529 	b	LSYM(Lad_l)
    530 
    531 	CFI_END_FUNCTION
    532 	FUNC_END aeabi_f2d
    533 	FUNC_END extendsfdf2
    534 
    535 ARM_FUNC_START floatundidf
    536 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
    537 	CFI_START_FUNCTION
    538 	.cfi_remember_state        @ Save the current CFA state.
    539 
    540 	orrs	r2, r0, r1
    541 	do_it	eq
    542 	RETc(eq)
    543 
    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
    549 
    550 	mov	r5, #0
    551 	b	2f
    552 
    553 ARM_FUNC_START floatdidf
    554 ARM_FUNC_ALIAS aeabi_l2d floatdidf
    555 	.cfi_restore_state
    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.
    559 
    560 	orrs	r2, r0, r1
    561 	do_it	eq
    562 	RETc(eq)
    563 
    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
    569 
    570 	ands	r5, ah, #0x80000000	@ sign bit in r5
    571 	bpl	2f
    572 #if defined(__thumb2__)
    573 	negs	al, al
    574 	sbc	ah, ah, ah, lsl #1
    575 #else
    576 	rsbs	al, al, #0
    577 	rsc	ah, ah, #0
    578 #endif
    579 2:
    580 	mov	r4, #0x400		@ initial exponent
    581 	add	r4, r4, #(52-1 - 1)
    582 
    583 	@ If FP word order does not match integer word order, swap the words.
    584 	.ifnc	xh, ah
    585 	mov	ip, al
    586 	mov	xh, ah
    587 	mov	xl, ip
    588 	.endif
    589 
    590 	movs	ip, xh, lsr #22
    591 	beq	LSYM(Lad_p)
    592 
    593 	@ The value is too big.  Scale it down a bit...
    594 	mov	r2, #3
    595 	movs	ip, ip, lsr #3
    596 	do_it	ne
    597 	addne	r2, r2, #3
    598 	movs	ip, ip, lsr #3
    599 	do_it	ne
    600 	addne	r2, r2, #3
    601 	add	r2, r2, ip, lsr #3
    602 
    603 	rsb	r3, r2, #32
    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
    608 	add	r4, r4, r2
    609 	b	LSYM(Lad_p)
    610 
    611 	CFI_END_FUNCTION
    612 	FUNC_END floatdidf
    613 	FUNC_END aeabi_l2d
    614 	FUNC_END floatundidf
    615 	FUNC_END aeabi_ul2d
    616 
    617 #endif /* L_addsubdf3 */
    618 
    619 #ifdef L_arm_muldivdf3
    620 
    621 ARM_FUNC_START muldf3
    622 ARM_FUNC_ALIAS aeabi_dmul muldf3
    623 	CFI_START_FUNCTION
    624 
    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
    631 
    632 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    633 	mov	ip, #0xff
    634 	orr	ip, ip, #0x700
    635 	ands	r4, ip, xh, lsr #20
    636 	do_it	ne, tte
    637 	COND(and,s,ne)	r5, ip, yh, lsr #20
    638 	teqne	r4, ip
    639 	teqne	r5, ip
    640 	bleq	LSYM(Lml_s)
    641 
    642 	@ Add exponents together
    643 	add	r4, r4, r5
    644 
    645 	@ Determine final sign.
    646 	eor	r6, xh, yh
    647 
    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
    653 	do_it	ne
    654 	COND(orr,s,ne)	r5, yl, yh, lsl #12
    655 	orr	xh, xh, #0x00100000
    656 	orr	yh, yh, #0x00100000
    657 	beq	LSYM(Lml_1)
    658 
    659 #if __ARM_ARCH__ < 4
    660 
    661 	@ Put sign bit in r6, which will be restored in yl later.
    662 	and   r6, r6, #0x80000000
    663 
    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
    674 
    675 	mov	r7, xl, lsr #16
    676 	mov	r8, yl, lsr #16
    677 	mov	r9, xh, lsr #16
    678 	mov	sl, yh, lsr #16
    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
    683 	mul	ip, xl, yl
    684 	mul	fp, xl, r8
    685 	mov	lr, #0
    686 	adds	ip, ip, fp, lsl #16
    687 	adc	lr, lr, fp, lsr #16
    688 	mul	fp, r7, yl
    689 	adds	ip, ip, fp, lsl #16
    690 	adc	lr, lr, fp, lsr #16
    691 	mul	fp, xl, sl
    692 	mov	r5, #0
    693 	adds	lr, lr, fp, lsl #16
    694 	adc	r5, r5, fp, lsr #16
    695 	mul	fp, r7, yh
    696 	adds	lr, lr, fp, lsl #16
    697 	adc	r5, r5, fp, lsr #16
    698 	mul	fp, xh, r8
    699 	adds	lr, lr, fp, lsl #16
    700 	adc	r5, r5, fp, lsr #16
    701 	mul	fp, r9, yl
    702 	adds	lr, lr, fp, lsl #16
    703 	adc	r5, r5, fp, lsr #16
    704 	mul	fp, xh, sl
    705 	mul	r6, r9, sl
    706 	adds	r5, r5, fp, lsl #16
    707 	adc	r6, r6, fp, lsr #16
    708 	mul	fp, r9, yh
    709 	adds	r5, r5, fp, lsl #16
    710 	adc	r6, r6, fp, lsr #16
    711 	mul	fp, xl, yh
    712 	adds	lr, lr, fp
    713 	mul	fp, r7, sl
    714 	adcs	r5, r5, fp
    715 	mul	fp, xh, yl
    716 	adc	r6, r6, #0
    717 	adds	lr, lr, fp
    718 	mul	fp, r9, r8
    719 	adcs	r5, r5, fp
    720 	mul	fp, r7, r8
    721 	adc	r6, r6, #0
    722 	adds	lr, lr, fp
    723 	mul	fp, xh, yh
    724 	adcs	r5, r5, fp
    725 	adc	r6, r6, #0
    726 	ldmfd   sp!, {yl, r7, r8, r9, sl, fp}   @ sp += 24
    727 	.cfi_restore_state   @ Restore the previous CFI state.
    728 #else
    729 
    730 	@ Here is the actual multiplication.
    731 	umull	ip, lr, xl, yl
    732 	mov	r5, #0
    733 	umlal	lr, r5, xh, yl
    734 	and	yl, r6, #0x80000000
    735 	umlal	lr, r5, xl, yh
    736 	mov	r6, #0
    737 	umlal	r5, r6, xh, yh
    738 
    739 #endif
    740 
    741 	@ The LSBs in ip are only significant for the final rounding.
    742 	@ Fold them into lr.
    743 	teq	ip, #0
    744 	do_it	ne
    745 	orrne	lr, lr, #1
    746 
    747 	@ Adjust result upon the MSB position.
    748 	sub	r4, r4, #0xff
    749 	cmp	r6, #(1 << (20-11))
    750 	sbc	r4, r4, #0x300
    751 	bcs	1f
    752 	movs	lr, lr, lsl #1
    753 	adcs	r5, r5, r5
    754 	adc	r6, r6, r6
    755 1:
    756 	@ Shift to final position, add sign to result.
    757 	orr	xh, yl, r6, lsl #11
    758 	orr	xh, xh, r5, lsr #21
    759 	mov	xl, r5, lsl #11
    760 	orr	xl, xl, lr, lsr #21
    761 	mov	lr, lr, lsl #11
    762 
    763 	@ Check exponent range for under/overflow.
    764 	subs	ip, r4, #(254 - 1)
    765 	do_it	hi
    766 	cmphi	ip, #0x700
    767 	bhi	LSYM(Lml_u)
    768 
    769 	@ Round the result, merge final exponent.
    770 	cmp	lr, #0x80000000
    771 	do_it	eq
    772 	COND(mov,s,eq)	lr, xl, lsr #1
    773 	adcs	xl, xl, #0
    774 	adc	xh, xh, r4, lsl #20
    775 	RETLDM	"r4, r5, r6"
    776 
    777 	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
    778 LSYM(Lml_1):
    779 	and	r6, r6, #0x80000000
    780 	orr	xh, r6, xh
    781 	orr	xl, xl, yl
    782 	eor	xh, xh, yh
    783 	subs	r4, r4, ip, lsr #1
    784 	do_it	gt, tt
    785 	COND(rsb,s,gt)	r5, r4, ip
    786 	orrgt	xh, xh, r4, lsl #20
    787 	RETLDM	"r4, r5, r6" gt
    788 
    789 	@ Under/overflow: fix things up for the code below.
    790 	orr	xh, xh, #0x00100000
    791 	mov	lr, #0
    792 	subs	r4, r4, #1
    793 LSYM(Lml_u):
    794 	@ Overflow?
    795 	bgt	LSYM(Lml_o)
    796 
    797 	@ Check if denormalized result is possible, otherwise return signed 0.
    798 	cmn	r4, #(53 + 1)
    799 	do_it	le, tt
    800 	movle	xl, #0
    801 	bicle	xh, xh, #0x7fffffff
    802 	RETLDM	"r4, r5, r6" le
    803 
    804 	@ Find out proper shift value.
    805 	rsb	r4, r4, #0
    806 	subs	r4, r4, #32
    807 	bge	2f
    808 	adds	r4, r4, #12
    809 	bgt	1f
    810 
    811 	@ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
    812 	add	r4, r4, #20
    813 	rsb	r5, r4, #32
    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
    822 	do_it	eq
    823 	biceq	xl, xl, r3, lsr #31
    824 	RETLDM	"r4, r5, r6"
    825 
    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.
    828 1:	rsb	r4, r4, #12
    829 	rsb	r5, r4, #32
    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
    835 	adc	xh, xh, #0
    836 	orrs	lr, lr, r3, lsl #1
    837 	do_it	eq
    838 	biceq	xl, xl, r3, lsr #31
    839 	RETLDM	"r4, r5, r6"
    840 
    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.
    843 2:	rsb	r5, r4, #32
    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
    852 	do_it	eq
    853 	biceq	xl, xl, r3, lsr #31
    854 	RETLDM	"r4, r5, r6"
    855 
    856 	@ One or both arguments are denormalized.
    857 	@ Scale them leftwards and preserve sign bit.
    858 LSYM(Lml_d):
    859 	teq	r4, #0
    860 	bne	2f
    861 	and	r6, xh, #0x80000000
    862 1:	movs	xl, xl, lsl #1
    863 	adc	xh, xh, xh
    864 	tst	xh, #0x00100000
    865 	do_it	eq
    866 	subeq	r4, r4, #1
    867 	beq	1b
    868 	orr	xh, xh, r6
    869 	teq	r5, #0
    870 	do_it	ne
    871 	RETc(ne)
    872 2:	and	r6, yh, #0x80000000
    873 3:	movs	yl, yl, lsl #1
    874 	adc	yh, yh, yh
    875 	tst	yh, #0x00100000
    876 	do_it	eq
    877 	subeq	r5, r5, #1
    878 	beq	3b
    879 	orr	yh, yh, r6
    880 	RET
    881 
    882 LSYM(Lml_s):
    883 	@ Isolate the INF and NAN cases away
    884 	teq	r4, ip
    885 	and	r5, ip, yh, lsr #20
    886 	do_it	ne
    887 	teqne	r5, ip
    888 	beq	1f
    889 
    890 	@ Here, one or more arguments are either denormalized or zero.
    891 	orrs	r6, xl, xh, lsl #1
    892 	do_it	ne
    893 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    894 	bne	LSYM(Lml_d)
    895 
    896 	@ Result is 0, but determine sign anyway.
    897 LSYM(Lml_z):
    898 	eor	xh, xh, yh
    899 	and	xh, xh, #0x80000000
    900 	mov	xl, #0
    901 	RETLDM	"r4, r5, r6"
    902 
    903 1:	@ One or both args are INF or NAN.
    904 	orrs	r6, xl, xh, lsl #1
    905 	do_it	eq, te
    906 	moveq	xl, yl
    907 	moveq	xh, yh
    908 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    909 	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
    910 	teq	r4, ip
    911 	bne	1f
    912 	orrs	r6, xl, xh, lsl #12
    913 	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
    914 1:	teq	r5, ip
    915 	bne	LSYM(Lml_i)
    916 	orrs	r6, yl, yh, lsl #12
    917 	do_it	ne, t
    918 	movne	xl, yl
    919 	movne	xh, yh
    920 	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
    921 
    922 	@ Result is INF, but we need to determine its sign.
    923 LSYM(Lml_i):
    924 	eor	xh, xh, yh
    925 
    926 	@ Overflow: return INF (sign already in xh).
    927 LSYM(Lml_o):
    928 	and	xh, xh, #0x80000000
    929 	orr	xh, xh, #0x7f000000
    930 	orr	xh, xh, #0x00f00000
    931 	mov	xl, #0
    932 	RETLDM	"r4, r5, r6"
    933 
    934 	@ Return a quiet NAN.
    935 LSYM(Lml_n):
    936 	orr	xh, xh, #0x7f000000
    937 	orr	xh, xh, #0x00f80000
    938 	RETLDM	"r4, r5, r6"
    939 
    940 	CFI_END_FUNCTION
    941 	FUNC_END aeabi_dmul
    942 	FUNC_END muldf3
    943 
    944 ARM_FUNC_START divdf3
    945 ARM_FUNC_ALIAS aeabi_ddiv divdf3
    946 	CFI_START_FUNCTION
    947 
    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
    954 
    955 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    956 	mov	ip, #0xff
    957 	orr	ip, ip, #0x700
    958 	ands	r4, ip, xh, lsr #20
    959 	do_it	ne, tte
    960 	COND(and,s,ne)	r5, ip, yh, lsr #20
    961 	teqne	r4, ip
    962 	teqne	r5, ip
    963 	bleq	LSYM(Ldv_s)
    964 
    965 	@ Subtract divisor exponent from dividend''s.
    966 	sub	r4, r4, r5
    967 
    968 	@ Preserve final sign into lr.
    969 	eor	lr, xh, yh
    970 
    971 	@ Convert mantissa to unsigned integer.
    972 	@ Dividend -> r5-r6, divisor -> yh-yl.
    973 	orrs	r5, yl, yh, lsl #12
    974 	mov	xh, xh, lsl #12
    975 	beq	LSYM(Ldv_1)
    976 	mov	yh, yh, lsl #12
    977 	mov	r5, #0x10000000
    978 	orr	yh, r5, yh, lsr #4
    979 	orr	yh, yh, yl, lsr #24
    980 	mov	yl, yl, lsl #8
    981 	orr	r5, r5, xh, lsr #4
    982 	orr	r5, r5, xl, lsr #24
    983 	mov	r6, xl, lsl #8
    984 
    985 	@ Initialize xh with final sign bit.
    986 	and	xh, lr, #0x80000000
    987 
    988 	@ Ensure result will land to known bit position.
    989 	@ Apply exponent bias accordingly.
    990 	cmp	r5, yh
    991 	do_it	eq
    992 	cmpeq	r6, yl
    993 	adc	r4, r4, #(255 - 2)
    994 	add	r4, r4, #0x300
    995 	bcs	1f
    996 	movs	yh, yh, lsr #1
    997 	mov	yl, yl, rrx
    998 1:
    999 	@ Perform first subtraction to align result to a nibble.
   1000 	subs	r6, r6, yl
   1001 	sbc	r5, r5, yh
   1002 	movs	yh, yh, lsr #1
   1003 	mov	yl, yl, rrx
   1004 	mov	xl, #0x00100000
   1005 	mov	ip, #0x00080000
   1006 
   1007 	@ The actual division loop.
   1008 1:	subs	lr, r6, yl
   1009 	sbcs	lr, r5, yh
   1010 	do_it	cs, tt
   1011 	subcs	r6, r6, yl
   1012 	movcs	r5, lr
   1013 	orrcs	xl, xl, ip
   1014 	movs	yh, yh, lsr #1
   1015 	mov	yl, yl, rrx
   1016 	subs	lr, r6, yl
   1017 	sbcs	lr, r5, yh
   1018 	do_it	cs, tt
   1019 	subcs	r6, r6, yl
   1020 	movcs	r5, lr
   1021 	orrcs	xl, xl, ip, lsr #1
   1022 	movs	yh, yh, lsr #1
   1023 	mov	yl, yl, rrx
   1024 	subs	lr, r6, yl
   1025 	sbcs	lr, r5, yh
   1026 	do_it	cs, tt
   1027 	subcs	r6, r6, yl
   1028 	movcs	r5, lr
   1029 	orrcs	xl, xl, ip, lsr #2
   1030 	movs	yh, yh, lsr #1
   1031 	mov	yl, yl, rrx
   1032 	subs	lr, r6, yl
   1033 	sbcs	lr, r5, yh
   1034 	do_it	cs, tt
   1035 	subcs	r6, r6, yl
   1036 	movcs	r5, lr
   1037 	orrcs	xl, xl, ip, lsr #3
   1038 
   1039 	orrs	lr, r5, r6
   1040 	beq	2f
   1041 	mov	r5, r5, lsl #4
   1042 	orr	r5, r5, r6, lsr #28
   1043 	mov	r6, r6, lsl #4
   1044 	mov	yh, yh, lsl #3
   1045 	orr	yh, yh, yl, lsr #29
   1046 	mov	yl, yl, lsl #3
   1047 	movs	ip, ip, lsr #4
   1048 	bne	1b
   1049 
   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.
   1052 	tst	xh, #0x00100000
   1053 	bne	3f
   1054 	orr	xh, xh, xl
   1055 	mov	xl, #0
   1056 	mov	ip, #0x80000000
   1057 	b	1b
   1058 2:
   1059 	@ Be sure result starts in the high word.
   1060 	tst	xh, #0x00100000
   1061 	do_it	eq, t
   1062 	orreq	xh, xh, xl
   1063 	moveq	xl, #0
   1064 3:
   1065 	@ Check exponent range for under/overflow.
   1066 	subs	ip, r4, #(254 - 1)
   1067 	do_it	hi
   1068 	cmphi	ip, #0x700
   1069 	bhi	LSYM(Lml_u)
   1070 
   1071 	@ Round the result, merge final exponent.
   1072 	subs	ip, r5, yh
   1073 	do_it	eq, t
   1074 	COND(sub,s,eq)	ip, r6, yl
   1075 	COND(mov,s,eq)	ip, xl, lsr #1
   1076 	adcs	xl, xl, #0
   1077 	adc	xh, xh, r4, lsl #20
   1078 	RETLDM	"r4, r5, r6"
   1079 
   1080 	@ Division by 0x1p*: shortcut a lot of code.
   1081 LSYM(Ldv_1):
   1082 	and	lr, lr, #0x80000000
   1083 	orr	xh, lr, xh, lsr #12
   1084 	adds	r4, r4, ip, lsr #1
   1085 	do_it	gt, tt
   1086 	COND(rsb,s,gt)	r5, r4, ip
   1087 	orrgt	xh, xh, r4, lsl #20
   1088 	RETLDM	"r4, r5, r6" gt
   1089 
   1090 	orr	xh, xh, #0x00100000
   1091 	mov	lr, #0
   1092 	subs	r4, r4, #1
   1093 	b	LSYM(Lml_u)
   1094 
   1095 	@ Result mightt need to be denormalized: put remainder bits
   1096 	@ in lr for rounding considerations.
   1097 LSYM(Ldv_u):
   1098 	orr	lr, r5, r6
   1099 	b	LSYM(Lml_u)
   1100 
   1101 	@ One or both arguments is either INF, NAN or zero.
   1102 LSYM(Ldv_s):
   1103 	and	r5, ip, yh, lsr #20
   1104 	teq	r4, ip
   1105 	do_it	eq
   1106 	teqeq	r5, ip
   1107 	beq	LSYM(Lml_n)		@ INF/NAN / INF/NAN -> NAN
   1108 	teq	r4, ip
   1109 	bne	1f
   1110 	orrs	r4, xl, xh, lsl #12
   1111 	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
   1112 	teq	r5, ip
   1113 	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
   1114 	mov	xl, yl
   1115 	mov	xh, yh
   1116 	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
   1117 1:	teq	r5, ip
   1118 	bne	2f
   1119 	orrs	r5, yl, yh, lsl #12
   1120 	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
   1121 	mov	xl, yl
   1122 	mov	xh, yh
   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
   1126 	do_it	ne
   1127 	COND(orr,s,ne)	r6, yl, yh, lsl #1
   1128 	bne	LSYM(Lml_d)
   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
   1135 
   1136 	CFI_END_FUNCTION
   1137 	FUNC_END aeabi_ddiv
   1138 	FUNC_END divdf3
   1139 
   1140 #endif /* L_muldivdf3 */
   1141 
   1142 #ifdef L_arm_cmpdf2
   1143 
   1144 @ Note: only r0 (return value) and ip are clobbered here.
   1145 
   1146 ARM_FUNC_START gtdf2
   1147 ARM_FUNC_ALIAS gedf2 gtdf2
   1148 	CFI_START_FUNCTION
   1149 	mov	ip, #-1
   1150 	b	1f
   1151 
   1152 ARM_FUNC_START ltdf2
   1153 ARM_FUNC_ALIAS ledf2 ltdf2
   1154 	mov	ip, #1
   1155 	b	1f
   1156 
   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?
   1161 
   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).
   1167 
   1168 	@ Trap any INF/NAN first.
   1169 	mov	ip, xh, lsl #1
   1170 	mvns	ip, ip, asr #21
   1171 	mov	ip, yh, lsl #1
   1172 	do_it	ne
   1173 	COND(mvn,s,ne)	ip, ip, asr #21
   1174 	beq	3f
   1175 	.cfi_remember_state
   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.
   1182 
   1183 	@ Test for equality.  Note that 0.0 is equal to -0.0.
   1184 2:	add	sp, sp, #4
   1185 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1186 
   1187 	orrs	ip, xl, xh, lsl #1	@ if x == 0.0 or -0.0
   1188 	do_it	eq, e
   1189 	COND(orr,s,eq)	ip, yl, yh, lsl #1	@ and y == 0.0 or -0.0
   1190 	teqne	xh, yh			@ or xh == yh
   1191 	do_it	eq, tt
   1192 	teqeq	xl, yl			@ and xl == yl
   1193 	moveq	r0, #0			@ then equal.
   1194 	RETc(eq)
   1195 
   1196 	@ Clear C flag
   1197 	cmn	r0, #0
   1198 
   1199 	@ Compare sign,
   1200 	teq	xh, yh
   1201 
   1202 	@ Compare values if same sign
   1203 	do_it	pl
   1204 	cmppl	xh, yh
   1205 	do_it	eq
   1206 	cmpeq	xl, yl
   1207 
   1208 	@ Result:
   1209 	do_it	cs, e
   1210 	movcs	r0, yh, asr #31
   1211 	mvncc	r0, yh, asr #31
   1212 	orr	r0, r0, #1
   1213 	RET
   1214 
   1215 3:  @ Look for a NAN.
   1216 
   1217 	@ Restore the previous CFI state (i.e. keep the CFI state as it was
   1218 	@ before the branch).
   1219 	.cfi_restore_state
   1220 
   1221 	mov ip, xh, lsl #1
   1222 	mvns	ip, ip, asr #21
   1223 	bne	4f
   1224 	orrs	ip, xl, xh, lsl #12
   1225 	bne	5f			@ x is NAN
   1226 4:	mov	ip, yh, lsl #1
   1227 	mvns	ip, ip, asr #21
   1228 	bne	2b
   1229 	orrs	ip, yl, yh, lsl #12
   1230 	beq	2b			@ y is not NAN
   1231 
   1232 5:	ldr	r0, [sp], #4		@ unordered return code
   1233 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1234 
   1235 	RET
   1236 
   1237 	CFI_END_FUNCTION
   1238 	FUNC_END gedf2
   1239 	FUNC_END gtdf2
   1240 	FUNC_END ledf2
   1241 	FUNC_END ltdf2
   1242 	FUNC_END nedf2
   1243 	FUNC_END eqdf2
   1244 	FUNC_END cmpdf2
   1245 
   1246 ARM_FUNC_START aeabi_cdrcmple
   1247 	CFI_START_FUNCTION
   1248 
   1249 	mov	ip, r0
   1250 	mov	r0, r2
   1251 	mov	r2, ip
   1252 	mov	ip, r1
   1253 	mov	r1, r3
   1254 	mov	r3, ip
   1255 	b	6f
   1256 
   1257 ARM_FUNC_START aeabi_cdcmpeq
   1258 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
   1259 
   1260 	@ The status-returning routines are required to preserve all
   1261 	@ registers except ip, lr, and cpsr.
   1262 6:	do_push	{r0, lr}
   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.
   1266 
   1267 	ARM_CALL cmpdf2
   1268 	@ Set the Z flag correctly, and the C flag unconditionally.
   1269 	cmp	r0, #0
   1270 	@ Clear the C flag if the return value was -1, indicating
   1271 	@ that the first operand was smaller than the second.
   1272 	do_it	mi
   1273 	cmnmi	r0, #0
   1274 
   1275 	RETLDM	"r0"
   1276 
   1277 	CFI_END_FUNCTION
   1278 	FUNC_END aeabi_cdcmple
   1279 	FUNC_END aeabi_cdcmpeq
   1280 	FUNC_END aeabi_cdrcmple
   1281 
   1282 ARM_FUNC_START	aeabi_dcmpeq
   1283 	CFI_START_FUNCTION
   1284 
   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
   1288 
   1289 	ARM_CALL aeabi_cdcmple
   1290 	do_it	eq, e
   1291 	moveq	r0, #1	@ Equal to.
   1292 	movne	r0, #0	@ Less than, greater than, or unordered.
   1293 
   1294 	RETLDM
   1295 
   1296 	CFI_END_FUNCTION
   1297 	FUNC_END aeabi_dcmpeq
   1298 
   1299 ARM_FUNC_START	aeabi_dcmplt
   1300 	CFI_START_FUNCTION
   1301 
   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
   1305 
   1306 	ARM_CALL aeabi_cdcmple
   1307 	do_it	cc, e
   1308 	movcc	r0, #1	@ Less than.
   1309 	movcs	r0, #0	@ Equal to, greater than, or unordered.
   1310 	RETLDM
   1311 
   1312 	CFI_END_FUNCTION
   1313 	FUNC_END aeabi_dcmplt
   1314 
   1315 ARM_FUNC_START	aeabi_dcmple
   1316 	CFI_START_FUNCTION
   1317 
   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
   1321 
   1322 	ARM_CALL aeabi_cdcmple
   1323 	do_it	ls, e
   1324 	movls	r0, #1  @ Less than or equal to.
   1325 	movhi	r0, #0	@ Greater than or unordered.
   1326 	RETLDM
   1327 
   1328 	CFI_END_FUNCTION
   1329 	FUNC_END aeabi_dcmple
   1330 
   1331 ARM_FUNC_START	aeabi_dcmpge
   1332 	CFI_START_FUNCTION
   1333 
   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
   1337 
   1338 	ARM_CALL aeabi_cdrcmple
   1339 	do_it	ls, e
   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.
   1342 	RETLDM
   1343 
   1344 	CFI_END_FUNCTION
   1345 	FUNC_END aeabi_dcmpge
   1346 
   1347 ARM_FUNC_START	aeabi_dcmpgt
   1348 	CFI_START_FUNCTION
   1349 
   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
   1353 
   1354 	ARM_CALL aeabi_cdrcmple
   1355 	do_it	cc, e
   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.
   1359 	RETLDM
   1360 
   1361 	CFI_END_FUNCTION
   1362 	FUNC_END aeabi_dcmpgt
   1363 
   1364 #endif /* L_cmpdf2 */
   1365 
   1366 #ifdef L_arm_unorddf2
   1367 
   1368 ARM_FUNC_START unorddf2
   1369 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
   1370 	.cfi_startproc
   1371 
   1372 	mov	ip, xh, lsl #1
   1373 	mvns	ip, ip, asr #21
   1374 	bne	1f
   1375 	orrs	ip, xl, xh, lsl #12
   1376 	bne	3f			@ x is NAN
   1377 1:	mov	ip, yh, lsl #1
   1378 	mvns	ip, ip, asr #21
   1379 	bne	2f
   1380 	orrs	ip, yl, yh, lsl #12
   1381 	bne	3f			@ y is NAN
   1382 2:	mov	r0, #0			@ arguments are ordered.
   1383 	RET
   1384 
   1385 3:	mov	r0, #1			@ arguments are unordered.
   1386 	RET
   1387 
   1388 	.cfi_endproc
   1389 	FUNC_END aeabi_dcmpun
   1390 	FUNC_END unorddf2
   1391 
   1392 #endif /* L_unorddf2 */
   1393 
   1394 #ifdef L_arm_fixdfsi
   1395 
   1396 ARM_FUNC_START fixdfsi
   1397 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
   1398 	CFI_START_FUNCTION
   1399 
   1400 	@ check exponent range.
   1401 	mov	r2, xh, lsl #1
   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
   1408 
   1409 	@ scale value
   1410 	mov	r3, xh, lsl #11
   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
   1415 	do_it	ne
   1416 	rsbne	r0, r0, #0
   1417 	RET
   1418 
   1419 1:	mov	r0, #0
   1420 	RET
   1421 
   1422 2:	orrs	xl, xl, xh, lsl #12
   1423 	bne	4f			@ x is NAN.
   1424 3:	ands	r0, xh, #0x80000000	@ the sign bit
   1425 	do_it	eq
   1426 	moveq	r0, #0x7fffffff		@ maximum signed positive si
   1427 	RET
   1428 
   1429 4:	mov	r0, #0			@ How should we convert NAN?
   1430 	RET
   1431 
   1432 	CFI_END_FUNCTION
   1433 	FUNC_END aeabi_d2iz
   1434 	FUNC_END fixdfsi
   1435 
   1436 #endif /* L_fixdfsi */
   1437 
   1438 #ifdef L_arm_fixunsdfsi
   1439 
   1440 ARM_FUNC_START fixunsdfsi
   1441 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
   1442 	CFI_START_FUNCTION
   1443 
   1444 	@ check exponent range.
   1445 	movs	r2, xh, lsl #1
   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
   1453 
   1454 	@ scale value
   1455 	mov	r3, xh, lsl #11
   1456 	orr	r3, r3, #0x80000000
   1457 	orr	r3, r3, xl, lsr #21
   1458 	shift1	lsr, r0, r3, r2
   1459 	RET
   1460 
   1461 1:	mov	r0, #0
   1462 	RET
   1463 
   1464 2:	orrs	xl, xl, xh, lsl #12
   1465 	bne	4f			@ value is NAN.
   1466 3:	mov	r0, #0xffffffff		@ maximum unsigned si
   1467 	RET
   1468 
   1469 4:	mov	r0, #0			@ How should we convert NAN?
   1470 	RET
   1471 
   1472 	CFI_END_FUNCTION
   1473 	FUNC_END aeabi_d2uiz
   1474 	FUNC_END fixunsdfsi
   1475 
   1476 #endif /* L_fixunsdfsi */
   1477 
   1478 #ifdef L_arm_truncdfsf2
   1479 
   1480 ARM_FUNC_START truncdfsf2
   1481 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
   1482 	CFI_START_FUNCTION
   1483 
   1484 	@ check exponent range.
   1485 	mov	r2, xh, lsl #1
   1486 	subs	r3, r2, #((1023 - 127) << 21)
   1487 	do_it	cs, t
   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
   1491 
   1492 1:	@ shift and round mantissa
   1493 	and	ip, xh, #0x80000000
   1494 	mov	r2, xl, lsl #3
   1495 	orr	xl, ip, xl, lsr #29
   1496 	cmp	r2, #0x80000000
   1497 	adc	r0, xl, r3, lsl #2
   1498 	do_it	eq
   1499 	biceq	r0, r0, #1
   1500 	RET
   1501 
   1502 2:	@ either overflow or underflow
   1503 	tst	xh, #0x40000000
   1504 	bne	3f			@ overflow
   1505 
   1506 	@ check if denormalized value is possible
   1507 	adds	r2, r3, #(23 << 21)
   1508 	do_it	lt, t
   1509 	andlt	r0, xh, #0x80000000	@ too small, return signed 0.
   1510 	RETc(lt)
   1511 
   1512 	@ denormalize value so we can resume with the code above afterwards.
   1513 	orr	xh, xh, #0x00100000
   1514 	mov	r2, r2, lsr #21
   1515 	rsb	r2, r2, #24
   1516 	rsb	ip, r2, #32
   1517 #if defined(__thumb2__)
   1518 	lsls	r3, xl, ip
   1519 #else
   1520 	movs	r3, xl, lsl ip
   1521 #endif
   1522 	shift1	lsr, xl, xl, r2
   1523 	do_it	ne
   1524 	orrne	xl, xl, #1		@ fold r3 for rounding considerations.
   1525 	mov	r3, xh, lsl #11
   1526 	mov	r3, r3, lsr #11
   1527 	shiftop orr xl xl r3 lsl ip ip
   1528 	shift1	lsr, r3, r3, r2
   1529 	mov	r3, r3, lsl #1
   1530 	b	1b
   1531 
   1532 3:	@ chech for NAN
   1533 	mvns	r3, r2, asr #21
   1534 	bne	5f			@ simple overflow
   1535 	orrs	r3, xl, xh, lsl #12
   1536 	do_it	ne, tt
   1537 	movne	r0, #0x7f000000
   1538 	orrne	r0, r0, #0x00c00000
   1539 	RETc(ne)			@ return NAN
   1540 
   1541 5:	@ return INF with sign
   1542 	and	r0, xh, #0x80000000
   1543 	orr	r0, r0, #0x7f000000
   1544 	orr	r0, r0, #0x00800000
   1545 	RET
   1546 
   1547 	CFI_END_FUNCTION
   1548 	FUNC_END aeabi_d2f
   1549 	FUNC_END truncdfsf2
   1550 
   1551 #endif /* L_truncdfsf2 */
   1552