Home | History | Annotate | Line # | Download | only in arm
ieee754-df.S revision 1.3.4.1
      1 /* ieee754-df.S double-precision floating point support for ARM
      2 
      3    Copyright (C) 2003-2016 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 function
    164 @ 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 	teq	r2, #0			@ if actually 0
    511 	do_it	ne, e
    512 	teqne	r3, #0xff000000		@ or INF or NAN
    513 	RETc(eq)			@ we are done already.
    514 
    515 	@ value was denormalized.  We can normalize it now.
    516 	do_push	{r4, r5, lr}
    517 	.cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
    518 	.cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
    519 	.cfi_rel_offset r5, 4
    520 	.cfi_rel_offset lr, 8
    521 
    522 	mov	r4, #0x380		@ setup corresponding exponent
    523 	and	r5, xh, #0x80000000	@ move sign bit in r5
    524 	bic	xh, xh, #0x80000000
    525 	b	LSYM(Lad_l)
    526 
    527 	CFI_END_FUNCTION
    528 	FUNC_END aeabi_f2d
    529 	FUNC_END extendsfdf2
    530 
    531 ARM_FUNC_START floatundidf
    532 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
    533 	CFI_START_FUNCTION
    534 	.cfi_remember_state        @ Save the current CFA state.
    535 
    536 	orrs	r2, r0, r1
    537 	do_it	eq
    538 	RETc(eq)
    539 
    540 	do_push {r4, r5, lr}       @ sp -= 12
    541 	.cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
    542 	.cfi_rel_offset r4, 0      @ Registers are saved from sp + 0 to sp + 8
    543 	.cfi_rel_offset r5, 4
    544 	.cfi_rel_offset lr, 8
    545 
    546 	mov	r5, #0
    547 	b	2f
    548 
    549 ARM_FUNC_START floatdidf
    550 ARM_FUNC_ALIAS aeabi_l2d floatdidf
    551 	.cfi_restore_state
    552 	@ Restore the CFI state we saved above. If we didn't do this then the
    553 	@ following instructions would have the CFI state that was set by the
    554 	@ offset adjustments made in floatundidf.
    555 
    556 	orrs	r2, r0, r1
    557 	do_it	eq
    558 	RETc(eq)
    559 
    560 	do_push {r4, r5, lr}       @ sp -= 12
    561 	.cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
    562 	.cfi_rel_offset r4, 0      @ Registers are saved from sp to sp + 8
    563 	.cfi_rel_offset r5, 4
    564 	.cfi_rel_offset lr, 8
    565 
    566 	ands	r5, ah, #0x80000000	@ sign bit in r5
    567 	bpl	2f
    568 #if defined(__thumb2__)
    569 	negs	al, al
    570 	sbc	ah, ah, ah, lsl #1
    571 #else
    572 	rsbs	al, al, #0
    573 	rsc	ah, ah, #0
    574 #endif
    575 2:
    576 	mov	r4, #0x400		@ initial exponent
    577 	add	r4, r4, #(52-1 - 1)
    578 
    579 	@ If FP word order does not match integer word order, swap the words.
    580 	.ifnc	xh, ah
    581 	mov	ip, al
    582 	mov	xh, ah
    583 	mov	xl, ip
    584 	.endif
    585 
    586 	movs	ip, xh, lsr #22
    587 	beq	LSYM(Lad_p)
    588 
    589 	@ The value is too big.  Scale it down a bit...
    590 	mov	r2, #3
    591 	movs	ip, ip, lsr #3
    592 	do_it	ne
    593 	addne	r2, r2, #3
    594 	movs	ip, ip, lsr #3
    595 	do_it	ne
    596 	addne	r2, r2, #3
    597 	add	r2, r2, ip, lsr #3
    598 
    599 	rsb	r3, r2, #32
    600 	shift1	lsl, ip, xl, r3
    601 	shift1	lsr, xl, xl, r2
    602 	shiftop orr xl xl xh lsl r3 lr
    603 	shift1	lsr, xh, xh, r2
    604 	add	r4, r4, r2
    605 	b	LSYM(Lad_p)
    606 
    607 	CFI_END_FUNCTION
    608 	FUNC_END floatdidf
    609 	FUNC_END aeabi_l2d
    610 	FUNC_END floatundidf
    611 	FUNC_END aeabi_ul2d
    612 
    613 #endif /* L_addsubdf3 */
    614 
    615 #ifdef L_arm_muldivdf3
    616 
    617 ARM_FUNC_START muldf3
    618 ARM_FUNC_ALIAS aeabi_dmul muldf3
    619 	CFI_START_FUNCTION
    620 
    621 	do_push {r4, r5, r6, lr}    @ sp -= 16
    622 	.cfi_adjust_cfa_offset 16   @ CFA is now sp + previousOffset + 16
    623 	.cfi_rel_offset r4, 0       @ Registers are saved from sp to sp + 12.
    624 	.cfi_rel_offset r5, 4
    625 	.cfi_rel_offset r6, 8
    626 	.cfi_rel_offset lr, 12
    627 
    628 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    629 	mov	ip, #0xff
    630 	orr	ip, ip, #0x700
    631 	ands	r4, ip, xh, lsr #20
    632 	do_it	ne, tte
    633 	COND(and,s,ne)	r5, ip, yh, lsr #20
    634 	teqne	r4, ip
    635 	teqne	r5, ip
    636 	bleq	LSYM(Lml_s)
    637 
    638 	@ Add exponents together
    639 	add	r4, r4, r5
    640 
    641 	@ Determine final sign.
    642 	eor	r6, xh, yh
    643 
    644 	@ Convert mantissa to unsigned integer.
    645 	@ If power of two, branch to a separate path.
    646 	bic	xh, xh, ip, lsl #21
    647 	bic	yh, yh, ip, lsl #21
    648 	orrs	r5, xl, xh, lsl #12
    649 	do_it	ne
    650 	COND(orr,s,ne)	r5, yl, yh, lsl #12
    651 	orr	xh, xh, #0x00100000
    652 	orr	yh, yh, #0x00100000
    653 	beq	LSYM(Lml_1)
    654 
    655 #if __ARM_ARCH__ < 4
    656 
    657 	@ Put sign bit in r6, which will be restored in yl later.
    658 	and   r6, r6, #0x80000000
    659 
    660 	@ Well, no way to make it shorter without the umull instruction.
    661 	stmfd   sp!, {r6, r7, r8, r9, sl, fp}   @ sp -= 24
    662 	.cfi_remember_state         @ Save the current CFI state.
    663 	.cfi_adjust_cfa_offset 24   @ CFA is now sp + previousOffset + 24.
    664 	.cfi_rel_offset r6, 0       @ Registers are saved from sp to sp + 20.
    665 	.cfi_rel_offset r7, 4
    666 	.cfi_rel_offset r8, 8
    667 	.cfi_rel_offset r9, 12
    668 	.cfi_rel_offset sl, 16
    669 	.cfi_rel_offset fp, 20
    670 
    671 	mov	r7, xl, lsr #16
    672 	mov	r8, yl, lsr #16
    673 	mov	r9, xh, lsr #16
    674 	mov	sl, yh, lsr #16
    675 	bic	xl, xl, r7, lsl #16
    676 	bic	yl, yl, r8, lsl #16
    677 	bic	xh, xh, r9, lsl #16
    678 	bic	yh, yh, sl, lsl #16
    679 	mul	ip, xl, yl
    680 	mul	fp, xl, r8
    681 	mov	lr, #0
    682 	adds	ip, ip, fp, lsl #16
    683 	adc	lr, lr, fp, lsr #16
    684 	mul	fp, r7, yl
    685 	adds	ip, ip, fp, lsl #16
    686 	adc	lr, lr, fp, lsr #16
    687 	mul	fp, xl, sl
    688 	mov	r5, #0
    689 	adds	lr, lr, fp, lsl #16
    690 	adc	r5, r5, fp, lsr #16
    691 	mul	fp, r7, yh
    692 	adds	lr, lr, fp, lsl #16
    693 	adc	r5, r5, fp, lsr #16
    694 	mul	fp, xh, r8
    695 	adds	lr, lr, fp, lsl #16
    696 	adc	r5, r5, fp, lsr #16
    697 	mul	fp, r9, yl
    698 	adds	lr, lr, fp, lsl #16
    699 	adc	r5, r5, fp, lsr #16
    700 	mul	fp, xh, sl
    701 	mul	r6, r9, sl
    702 	adds	r5, r5, fp, lsl #16
    703 	adc	r6, r6, fp, lsr #16
    704 	mul	fp, r9, yh
    705 	adds	r5, r5, fp, lsl #16
    706 	adc	r6, r6, fp, lsr #16
    707 	mul	fp, xl, yh
    708 	adds	lr, lr, fp
    709 	mul	fp, r7, sl
    710 	adcs	r5, r5, fp
    711 	mul	fp, xh, yl
    712 	adc	r6, r6, #0
    713 	adds	lr, lr, fp
    714 	mul	fp, r9, r8
    715 	adcs	r5, r5, fp
    716 	mul	fp, r7, r8
    717 	adc	r6, r6, #0
    718 	adds	lr, lr, fp
    719 	mul	fp, xh, yh
    720 	adcs	r5, r5, fp
    721 	adc	r6, r6, #0
    722 	ldmfd   sp!, {yl, r7, r8, r9, sl, fp}   @ sp += 24
    723 	.cfi_restore_state   @ Restore the previous CFI state.
    724 #else
    725 
    726 	@ Here is the actual multiplication.
    727 	umull	ip, lr, xl, yl
    728 	mov	r5, #0
    729 	umlal	lr, r5, xh, yl
    730 	and	yl, r6, #0x80000000
    731 	umlal	lr, r5, xl, yh
    732 	mov	r6, #0
    733 	umlal	r5, r6, xh, yh
    734 
    735 #endif
    736 
    737 	@ The LSBs in ip are only significant for the final rounding.
    738 	@ Fold them into lr.
    739 	teq	ip, #0
    740 	do_it	ne
    741 	orrne	lr, lr, #1
    742 
    743 	@ Adjust result upon the MSB position.
    744 	sub	r4, r4, #0xff
    745 	cmp	r6, #(1 << (20-11))
    746 	sbc	r4, r4, #0x300
    747 	bcs	1f
    748 	movs	lr, lr, lsl #1
    749 	adcs	r5, r5, r5
    750 	adc	r6, r6, r6
    751 1:
    752 	@ Shift to final position, add sign to result.
    753 	orr	xh, yl, r6, lsl #11
    754 	orr	xh, xh, r5, lsr #21
    755 	mov	xl, r5, lsl #11
    756 	orr	xl, xl, lr, lsr #21
    757 	mov	lr, lr, lsl #11
    758 
    759 	@ Check exponent range for under/overflow.
    760 	subs	ip, r4, #(254 - 1)
    761 	do_it	hi
    762 	cmphi	ip, #0x700
    763 	bhi	LSYM(Lml_u)
    764 
    765 	@ Round the result, merge final exponent.
    766 	cmp	lr, #0x80000000
    767 	do_it	eq
    768 	COND(mov,s,eq)	lr, xl, lsr #1
    769 	adcs	xl, xl, #0
    770 	adc	xh, xh, r4, lsl #20
    771 	RETLDM	"r4, r5, r6"
    772 
    773 	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
    774 LSYM(Lml_1):
    775 	and	r6, r6, #0x80000000
    776 	orr	xh, r6, xh
    777 	orr	xl, xl, yl
    778 	eor	xh, xh, yh
    779 	subs	r4, r4, ip, lsr #1
    780 	do_it	gt, tt
    781 	COND(rsb,s,gt)	r5, r4, ip
    782 	orrgt	xh, xh, r4, lsl #20
    783 	RETLDM	"r4, r5, r6" gt
    784 
    785 	@ Under/overflow: fix things up for the code below.
    786 	orr	xh, xh, #0x00100000
    787 	mov	lr, #0
    788 	subs	r4, r4, #1
    789 LSYM(Lml_u):
    790 	@ Overflow?
    791 	bgt	LSYM(Lml_o)
    792 
    793 	@ Check if denormalized result is possible, otherwise return signed 0.
    794 	cmn	r4, #(53 + 1)
    795 	do_it	le, tt
    796 	movle	xl, #0
    797 	bicle	xh, xh, #0x7fffffff
    798 	RETLDM	"r4, r5, r6" le
    799 
    800 	@ Find out proper shift value.
    801 	rsb	r4, r4, #0
    802 	subs	r4, r4, #32
    803 	bge	2f
    804 	adds	r4, r4, #12
    805 	bgt	1f
    806 
    807 	@ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
    808 	add	r4, r4, #20
    809 	rsb	r5, r4, #32
    810 	shift1	lsl, r3, xl, r5
    811 	shift1	lsr, xl, xl, r4
    812 	shiftop orr xl xl xh lsl r5 r2
    813 	and	r2, xh, #0x80000000
    814 	bic	xh, xh, #0x80000000
    815 	adds	xl, xl, r3, lsr #31
    816 	shiftop adc xh r2 xh lsr r4 r6
    817 	orrs	lr, lr, r3, lsl #1
    818 	do_it	eq
    819 	biceq	xl, xl, r3, lsr #31
    820 	RETLDM	"r4, r5, r6"
    821 
    822 	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
    823 	@ a register switch from xh to xl. Then round.
    824 1:	rsb	r4, r4, #12
    825 	rsb	r5, r4, #32
    826 	shift1	lsl, r3, xl, r4
    827 	shift1	lsr, xl, xl, r5
    828 	shiftop orr xl xl xh lsl r4 r2
    829 	bic	xh, xh, #0x7fffffff
    830 	adds	xl, xl, r3, lsr #31
    831 	adc	xh, xh, #0
    832 	orrs	lr, lr, r3, lsl #1
    833 	do_it	eq
    834 	biceq	xl, xl, r3, lsr #31
    835 	RETLDM	"r4, r5, r6"
    836 
    837 	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
    838 	@ from xh to xl.  Leftover bits are in r3-r6-lr for rounding.
    839 2:	rsb	r5, r4, #32
    840 	shiftop orr lr lr xl lsl r5 r2
    841 	shift1	lsr, r3, xl, r4
    842 	shiftop orr r3 r3 xh lsl r5 r2
    843 	shift1	lsr, xl, xh, r4
    844 	bic	xh, xh, #0x7fffffff
    845 	shiftop bic xl xl xh lsr r4 r2
    846 	add	xl, xl, r3, lsr #31
    847 	orrs	lr, lr, r3, lsl #1
    848 	do_it	eq
    849 	biceq	xl, xl, r3, lsr #31
    850 	RETLDM	"r4, r5, r6"
    851 
    852 	@ One or both arguments are denormalized.
    853 	@ Scale them leftwards and preserve sign bit.
    854 LSYM(Lml_d):
    855 	teq	r4, #0
    856 	bne	2f
    857 	and	r6, xh, #0x80000000
    858 1:	movs	xl, xl, lsl #1
    859 	adc	xh, xh, xh
    860 	tst	xh, #0x00100000
    861 	do_it	eq
    862 	subeq	r4, r4, #1
    863 	beq	1b
    864 	orr	xh, xh, r6
    865 	teq	r5, #0
    866 	do_it	ne
    867 	RETc(ne)
    868 2:	and	r6, yh, #0x80000000
    869 3:	movs	yl, yl, lsl #1
    870 	adc	yh, yh, yh
    871 	tst	yh, #0x00100000
    872 	do_it	eq
    873 	subeq	r5, r5, #1
    874 	beq	3b
    875 	orr	yh, yh, r6
    876 	RET
    877 
    878 LSYM(Lml_s):
    879 	@ Isolate the INF and NAN cases away
    880 	teq	r4, ip
    881 	and	r5, ip, yh, lsr #20
    882 	do_it	ne
    883 	teqne	r5, ip
    884 	beq	1f
    885 
    886 	@ Here, one or more arguments are either denormalized or zero.
    887 	orrs	r6, xl, xh, lsl #1
    888 	do_it	ne
    889 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    890 	bne	LSYM(Lml_d)
    891 
    892 	@ Result is 0, but determine sign anyway.
    893 LSYM(Lml_z):
    894 	eor	xh, xh, yh
    895 	and	xh, xh, #0x80000000
    896 	mov	xl, #0
    897 	RETLDM	"r4, r5, r6"
    898 
    899 1:	@ One or both args are INF or NAN.
    900 	orrs	r6, xl, xh, lsl #1
    901 	do_it	eq, te
    902 	moveq	xl, yl
    903 	moveq	xh, yh
    904 	COND(orr,s,ne)	r6, yl, yh, lsl #1
    905 	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
    906 	teq	r4, ip
    907 	bne	1f
    908 	orrs	r6, xl, xh, lsl #12
    909 	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
    910 1:	teq	r5, ip
    911 	bne	LSYM(Lml_i)
    912 	orrs	r6, yl, yh, lsl #12
    913 	do_it	ne, t
    914 	movne	xl, yl
    915 	movne	xh, yh
    916 	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
    917 
    918 	@ Result is INF, but we need to determine its sign.
    919 LSYM(Lml_i):
    920 	eor	xh, xh, yh
    921 
    922 	@ Overflow: return INF (sign already in xh).
    923 LSYM(Lml_o):
    924 	and	xh, xh, #0x80000000
    925 	orr	xh, xh, #0x7f000000
    926 	orr	xh, xh, #0x00f00000
    927 	mov	xl, #0
    928 	RETLDM	"r4, r5, r6"
    929 
    930 	@ Return a quiet NAN.
    931 LSYM(Lml_n):
    932 	orr	xh, xh, #0x7f000000
    933 	orr	xh, xh, #0x00f80000
    934 	RETLDM	"r4, r5, r6"
    935 
    936 	CFI_END_FUNCTION
    937 	FUNC_END aeabi_dmul
    938 	FUNC_END muldf3
    939 
    940 ARM_FUNC_START divdf3
    941 ARM_FUNC_ALIAS aeabi_ddiv divdf3
    942 	CFI_START_FUNCTION
    943 
    944 	do_push	{r4, r5, r6, lr}
    945 	.cfi_adjust_cfa_offset 16
    946 	.cfi_rel_offset r4, 0
    947 	.cfi_rel_offset r5, 4
    948 	.cfi_rel_offset r6, 8
    949 	.cfi_rel_offset lr, 12
    950 
    951 	@ Mask out exponents, trap any zero/denormal/INF/NAN.
    952 	mov	ip, #0xff
    953 	orr	ip, ip, #0x700
    954 	ands	r4, ip, xh, lsr #20
    955 	do_it	ne, tte
    956 	COND(and,s,ne)	r5, ip, yh, lsr #20
    957 	teqne	r4, ip
    958 	teqne	r5, ip
    959 	bleq	LSYM(Ldv_s)
    960 
    961 	@ Subtract divisor exponent from dividend''s.
    962 	sub	r4, r4, r5
    963 
    964 	@ Preserve final sign into lr.
    965 	eor	lr, xh, yh
    966 
    967 	@ Convert mantissa to unsigned integer.
    968 	@ Dividend -> r5-r6, divisor -> yh-yl.
    969 	orrs	r5, yl, yh, lsl #12
    970 	mov	xh, xh, lsl #12
    971 	beq	LSYM(Ldv_1)
    972 	mov	yh, yh, lsl #12
    973 	mov	r5, #0x10000000
    974 	orr	yh, r5, yh, lsr #4
    975 	orr	yh, yh, yl, lsr #24
    976 	mov	yl, yl, lsl #8
    977 	orr	r5, r5, xh, lsr #4
    978 	orr	r5, r5, xl, lsr #24
    979 	mov	r6, xl, lsl #8
    980 
    981 	@ Initialize xh with final sign bit.
    982 	and	xh, lr, #0x80000000
    983 
    984 	@ Ensure result will land to known bit position.
    985 	@ Apply exponent bias accordingly.
    986 	cmp	r5, yh
    987 	do_it	eq
    988 	cmpeq	r6, yl
    989 	adc	r4, r4, #(255 - 2)
    990 	add	r4, r4, #0x300
    991 	bcs	1f
    992 	movs	yh, yh, lsr #1
    993 	mov	yl, yl, rrx
    994 1:
    995 	@ Perform first subtraction to align result to a nibble.
    996 	subs	r6, r6, yl
    997 	sbc	r5, r5, yh
    998 	movs	yh, yh, lsr #1
    999 	mov	yl, yl, rrx
   1000 	mov	xl, #0x00100000
   1001 	mov	ip, #0x00080000
   1002 
   1003 	@ The actual division loop.
   1004 1:	subs	lr, r6, yl
   1005 	sbcs	lr, r5, yh
   1006 	do_it	cs, tt
   1007 	subcs	r6, r6, yl
   1008 	movcs	r5, lr
   1009 	orrcs	xl, xl, ip
   1010 	movs	yh, yh, lsr #1
   1011 	mov	yl, yl, rrx
   1012 	subs	lr, r6, yl
   1013 	sbcs	lr, r5, yh
   1014 	do_it	cs, tt
   1015 	subcs	r6, r6, yl
   1016 	movcs	r5, lr
   1017 	orrcs	xl, xl, ip, lsr #1
   1018 	movs	yh, yh, lsr #1
   1019 	mov	yl, yl, rrx
   1020 	subs	lr, r6, yl
   1021 	sbcs	lr, r5, yh
   1022 	do_it	cs, tt
   1023 	subcs	r6, r6, yl
   1024 	movcs	r5, lr
   1025 	orrcs	xl, xl, ip, lsr #2
   1026 	movs	yh, yh, lsr #1
   1027 	mov	yl, yl, rrx
   1028 	subs	lr, r6, yl
   1029 	sbcs	lr, r5, yh
   1030 	do_it	cs, tt
   1031 	subcs	r6, r6, yl
   1032 	movcs	r5, lr
   1033 	orrcs	xl, xl, ip, lsr #3
   1034 
   1035 	orrs	lr, r5, r6
   1036 	beq	2f
   1037 	mov	r5, r5, lsl #4
   1038 	orr	r5, r5, r6, lsr #28
   1039 	mov	r6, r6, lsl #4
   1040 	mov	yh, yh, lsl #3
   1041 	orr	yh, yh, yl, lsr #29
   1042 	mov	yl, yl, lsl #3
   1043 	movs	ip, ip, lsr #4
   1044 	bne	1b
   1045 
   1046 	@ We are done with a word of the result.
   1047 	@ Loop again for the low word if this pass was for the high word.
   1048 	tst	xh, #0x00100000
   1049 	bne	3f
   1050 	orr	xh, xh, xl
   1051 	mov	xl, #0
   1052 	mov	ip, #0x80000000
   1053 	b	1b
   1054 2:
   1055 	@ Be sure result starts in the high word.
   1056 	tst	xh, #0x00100000
   1057 	do_it	eq, t
   1058 	orreq	xh, xh, xl
   1059 	moveq	xl, #0
   1060 3:
   1061 	@ Check exponent range for under/overflow.
   1062 	subs	ip, r4, #(254 - 1)
   1063 	do_it	hi
   1064 	cmphi	ip, #0x700
   1065 	bhi	LSYM(Lml_u)
   1066 
   1067 	@ Round the result, merge final exponent.
   1068 	subs	ip, r5, yh
   1069 	do_it	eq, t
   1070 	COND(sub,s,eq)	ip, r6, yl
   1071 	COND(mov,s,eq)	ip, xl, lsr #1
   1072 	adcs	xl, xl, #0
   1073 	adc	xh, xh, r4, lsl #20
   1074 	RETLDM	"r4, r5, r6"
   1075 
   1076 	@ Division by 0x1p*: shortcut a lot of code.
   1077 LSYM(Ldv_1):
   1078 	and	lr, lr, #0x80000000
   1079 	orr	xh, lr, xh, lsr #12
   1080 	adds	r4, r4, ip, lsr #1
   1081 	do_it	gt, tt
   1082 	COND(rsb,s,gt)	r5, r4, ip
   1083 	orrgt	xh, xh, r4, lsl #20
   1084 	RETLDM	"r4, r5, r6" gt
   1085 
   1086 	orr	xh, xh, #0x00100000
   1087 	mov	lr, #0
   1088 	subs	r4, r4, #1
   1089 	b	LSYM(Lml_u)
   1090 
   1091 	@ Result mightt need to be denormalized: put remainder bits
   1092 	@ in lr for rounding considerations.
   1093 LSYM(Ldv_u):
   1094 	orr	lr, r5, r6
   1095 	b	LSYM(Lml_u)
   1096 
   1097 	@ One or both arguments is either INF, NAN or zero.
   1098 LSYM(Ldv_s):
   1099 	and	r5, ip, yh, lsr #20
   1100 	teq	r4, ip
   1101 	do_it	eq
   1102 	teqeq	r5, ip
   1103 	beq	LSYM(Lml_n)		@ INF/NAN / INF/NAN -> NAN
   1104 	teq	r4, ip
   1105 	bne	1f
   1106 	orrs	r4, xl, xh, lsl #12
   1107 	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
   1108 	teq	r5, ip
   1109 	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
   1110 	mov	xl, yl
   1111 	mov	xh, yh
   1112 	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
   1113 1:	teq	r5, ip
   1114 	bne	2f
   1115 	orrs	r5, yl, yh, lsl #12
   1116 	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
   1117 	mov	xl, yl
   1118 	mov	xh, yh
   1119 	b	LSYM(Lml_n)		@ <anything> / NAN -> NAN
   1120 2:	@ If both are nonzero, we need to normalize and resume above.
   1121 	orrs	r6, xl, xh, lsl #1
   1122 	do_it	ne
   1123 	COND(orr,s,ne)	r6, yl, yh, lsl #1
   1124 	bne	LSYM(Lml_d)
   1125 	@ One or both arguments are 0.
   1126 	orrs	r4, xl, xh, lsl #1
   1127 	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
   1128 	orrs	r5, yl, yh, lsl #1
   1129 	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
   1130 	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
   1131 
   1132 	CFI_END_FUNCTION
   1133 	FUNC_END aeabi_ddiv
   1134 	FUNC_END divdf3
   1135 
   1136 #endif /* L_muldivdf3 */
   1137 
   1138 #ifdef L_arm_cmpdf2
   1139 
   1140 @ Note: only r0 (return value) and ip are clobbered here.
   1141 
   1142 ARM_FUNC_START gtdf2
   1143 ARM_FUNC_ALIAS gedf2 gtdf2
   1144 	CFI_START_FUNCTION
   1145 	mov	ip, #-1
   1146 	b	1f
   1147 
   1148 ARM_FUNC_START ltdf2
   1149 ARM_FUNC_ALIAS ledf2 ltdf2
   1150 	mov	ip, #1
   1151 	b	1f
   1152 
   1153 ARM_FUNC_START cmpdf2
   1154 ARM_FUNC_ALIAS nedf2 cmpdf2
   1155 ARM_FUNC_ALIAS eqdf2 cmpdf2
   1156 	mov	ip, #1			@ how should we specify unordered here?
   1157 
   1158 1:	str	ip, [sp, #-4]!
   1159 	.cfi_adjust_cfa_offset 4        @ CFA is now sp + previousOffset + 4.
   1160 	@ We're not adding CFI for ip as it's pushed into the stack
   1161 	@ only because @ it may be popped off later as a return value
   1162 	@ (i.e. we're not preserving @ it anyways).
   1163 
   1164 	@ Trap any INF/NAN first.
   1165 	mov	ip, xh, lsl #1
   1166 	mvns	ip, ip, asr #21
   1167 	mov	ip, yh, lsl #1
   1168 	do_it	ne
   1169 	COND(mvn,s,ne)	ip, ip, asr #21
   1170 	beq	3f
   1171 	.cfi_remember_state
   1172 	@ Save the current CFI state. This is done because the branch
   1173 	@ is conditional, @ and if we don't take it we'll issue a
   1174 	@ .cfi_adjust_cfa_offset and return.  @ If we do take it,
   1175 	@ however, the .cfi_adjust_cfa_offset from the non-branch @ code
   1176 	@ will affect the branch code as well. To avoid this we'll
   1177 	@ restore @ the current state before executing the branch code.
   1178 
   1179 	@ Test for equality.  @ Note that 0.0 is equal to -0.0.
   1180 2:	add	sp, sp, #4
   1181 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1182 
   1183 	orrs	ip, xl, xh, lsl #1	@ if x == 0.0 or -0.0
   1184 	do_it	eq, e
   1185 	COND(orr,s,eq)	ip, yl, yh, lsl #1	@ and y == 0.0 or -0.0
   1186 	teqne	xh, yh			@ or xh == yh
   1187 	do_it	eq, tt
   1188 	teqeq	xl, yl			@ and xl == yl
   1189 	moveq	r0, #0			@ then equal.
   1190 	RETc(eq)
   1191 
   1192 	@ Clear C flag
   1193 	cmn	r0, #0
   1194 
   1195 	@ Compare sign,
   1196 	teq	xh, yh
   1197 
   1198 	@ Compare values if same sign
   1199 	do_it	pl
   1200 	cmppl	xh, yh
   1201 	do_it	eq
   1202 	cmpeq	xl, yl
   1203 
   1204 	@ Result:
   1205 	do_it	cs, e
   1206 	movcs	r0, yh, asr #31
   1207 	mvncc	r0, yh, asr #31
   1208 	orr	r0, r0, #1
   1209 	RET
   1210 
   1211 3:  @ Look for a NAN.
   1212 
   1213 	@ Restore the previous CFI state (i.e. keep the CFI state as it was
   1214 	@ before the branch).
   1215 	.cfi_restore_state
   1216 
   1217 	mov ip, xh, lsl #1
   1218 	mvns	ip, ip, asr #21
   1219 	bne	4f
   1220 	orrs	ip, xl, xh, lsl #12
   1221 	bne	5f			@ x is NAN
   1222 4:	mov	ip, yh, lsl #1
   1223 	mvns	ip, ip, asr #21
   1224 	bne	2b
   1225 	orrs	ip, yl, yh, lsl #12
   1226 	beq	2b			@ y is not NAN
   1227 
   1228 5:	ldr	r0, [sp], #4		@ unordered return code
   1229 	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
   1230 
   1231 	RET
   1232 
   1233 	CFI_END_FUNCTION
   1234 	FUNC_END gedf2
   1235 	FUNC_END gtdf2
   1236 	FUNC_END ledf2
   1237 	FUNC_END ltdf2
   1238 	FUNC_END nedf2
   1239 	FUNC_END eqdf2
   1240 	FUNC_END cmpdf2
   1241 
   1242 ARM_FUNC_START aeabi_cdrcmple
   1243 	CFI_START_FUNCTION
   1244 
   1245 	mov	ip, r0
   1246 	mov	r0, r2
   1247 	mov	r2, ip
   1248 	mov	ip, r1
   1249 	mov	r1, r3
   1250 	mov	r3, ip
   1251 	b	6f
   1252 
   1253 ARM_FUNC_START aeabi_cdcmpeq
   1254 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
   1255 
   1256 	@ The status-returning routines are required to preserve all
   1257 	@ registers except ip, lr, and cpsr.
   1258 6:	do_push	{r0, lr}
   1259 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8.
   1260 	.cfi_rel_offset r0, 0     @ Previous r0 is saved at sp.
   1261 	.cfi_rel_offset lr, 4     @ Previous lr is saved at sp + 4.
   1262 
   1263 	ARM_CALL cmpdf2
   1264 	@ Set the Z flag correctly, and the C flag unconditionally.
   1265 	cmp	r0, #0
   1266 	@ Clear the C flag if the return value was -1, indicating
   1267 	@ that the first operand was smaller than the second.
   1268 	do_it	mi
   1269 	cmnmi	r0, #0
   1270 
   1271 	RETLDM	"r0"
   1272 
   1273 	CFI_END_FUNCTION
   1274 	FUNC_END aeabi_cdcmple
   1275 	FUNC_END aeabi_cdcmpeq
   1276 	FUNC_END aeabi_cdrcmple
   1277 
   1278 ARM_FUNC_START	aeabi_dcmpeq
   1279 	CFI_START_FUNCTION
   1280 
   1281 	str lr, [sp, #-8]!        @ sp -= 8
   1282 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
   1283 	.cfi_rel_offset lr, 0     @ lr is at sp
   1284 
   1285 	ARM_CALL aeabi_cdcmple
   1286 	do_it	eq, e
   1287 	moveq	r0, #1	@ Equal to.
   1288 	movne	r0, #0	@ Less than, greater than, or unordered.
   1289 
   1290 	RETLDM
   1291 
   1292 	CFI_END_FUNCTION
   1293 	FUNC_END aeabi_dcmpeq
   1294 
   1295 ARM_FUNC_START	aeabi_dcmplt
   1296 	CFI_START_FUNCTION
   1297 
   1298 	str lr, [sp, #-8]!        @ sp -= 8
   1299 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
   1300 	.cfi_rel_offset lr, 0     @ lr is at sp
   1301 
   1302 	ARM_CALL aeabi_cdcmple
   1303 	do_it	cc, e
   1304 	movcc	r0, #1	@ Less than.
   1305 	movcs	r0, #0	@ Equal to, greater than, or unordered.
   1306 	RETLDM
   1307 
   1308 	CFI_END_FUNCTION
   1309 	FUNC_END aeabi_dcmplt
   1310 
   1311 ARM_FUNC_START	aeabi_dcmple
   1312 	CFI_START_FUNCTION
   1313 
   1314 	str lr, [sp, #-8]!        @ sp -= 8
   1315 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
   1316 	.cfi_rel_offset lr, 0     @ lr is at sp
   1317 
   1318 	ARM_CALL aeabi_cdcmple
   1319 	do_it	ls, e
   1320 	movls	r0, #1  @ Less than or equal to.
   1321 	movhi	r0, #0	@ Greater than or unordered.
   1322 	RETLDM
   1323 
   1324 	CFI_END_FUNCTION
   1325 	FUNC_END aeabi_dcmple
   1326 
   1327 ARM_FUNC_START	aeabi_dcmpge
   1328 	CFI_START_FUNCTION
   1329 
   1330 	str lr, [sp, #-8]!        @ sp -= 8
   1331 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
   1332 	.cfi_rel_offset lr, 0     @ lr is at sp
   1333 
   1334 	ARM_CALL aeabi_cdrcmple
   1335 	do_it	ls, e
   1336 	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
   1337 	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
   1338 	RETLDM
   1339 
   1340 	CFI_END_FUNCTION
   1341 	FUNC_END aeabi_dcmpge
   1342 
   1343 ARM_FUNC_START	aeabi_dcmpgt
   1344 	CFI_START_FUNCTION
   1345 
   1346 	str lr, [sp, #-8]!        @ sp -= 8
   1347 	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
   1348 	.cfi_rel_offset lr, 0     @ lr is at sp
   1349 
   1350 	ARM_CALL aeabi_cdrcmple
   1351 	do_it	cc, e
   1352 	movcc	r0, #1	@ Operand 2 is less than operand 1.
   1353 	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
   1354 			@ or they are unordered.
   1355 	RETLDM
   1356 
   1357 	CFI_END_FUNCTION
   1358 	FUNC_END aeabi_dcmpgt
   1359 
   1360 #endif /* L_cmpdf2 */
   1361 
   1362 #ifdef L_arm_unorddf2
   1363 
   1364 ARM_FUNC_START unorddf2
   1365 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
   1366 	.cfi_startproc
   1367 
   1368 	mov	ip, xh, lsl #1
   1369 	mvns	ip, ip, asr #21
   1370 	bne	1f
   1371 	orrs	ip, xl, xh, lsl #12
   1372 	bne	3f			@ x is NAN
   1373 1:	mov	ip, yh, lsl #1
   1374 	mvns	ip, ip, asr #21
   1375 	bne	2f
   1376 	orrs	ip, yl, yh, lsl #12
   1377 	bne	3f			@ y is NAN
   1378 2:	mov	r0, #0			@ arguments are ordered.
   1379 	RET
   1380 
   1381 3:	mov	r0, #1			@ arguments are unordered.
   1382 	RET
   1383 
   1384 	.cfi_endproc
   1385 	FUNC_END aeabi_dcmpun
   1386 	FUNC_END unorddf2
   1387 
   1388 #endif /* L_unorddf2 */
   1389 
   1390 #ifdef L_arm_fixdfsi
   1391 
   1392 ARM_FUNC_START fixdfsi
   1393 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
   1394 	CFI_START_FUNCTION
   1395 
   1396 	@ check exponent range.
   1397 	mov	r2, xh, lsl #1
   1398 	adds	r2, r2, #(1 << 21)
   1399 	bcs	2f			@ value is INF or NAN
   1400 	bpl	1f			@ value is too small
   1401 	mov	r3, #(0xfffffc00 + 31)
   1402 	subs	r2, r3, r2, asr #21
   1403 	bls	3f			@ value is too large
   1404 
   1405 	@ scale value
   1406 	mov	r3, xh, lsl #11
   1407 	orr	r3, r3, #0x80000000
   1408 	orr	r3, r3, xl, lsr #21
   1409 	tst	xh, #0x80000000		@ the sign bit
   1410 	shift1	lsr, r0, r3, r2
   1411 	do_it	ne
   1412 	rsbne	r0, r0, #0
   1413 	RET
   1414 
   1415 1:	mov	r0, #0
   1416 	RET
   1417 
   1418 2:	orrs	xl, xl, xh, lsl #12
   1419 	bne	4f			@ x is NAN.
   1420 3:	ands	r0, xh, #0x80000000	@ the sign bit
   1421 	do_it	eq
   1422 	moveq	r0, #0x7fffffff		@ maximum signed positive si
   1423 	RET
   1424 
   1425 4:	mov	r0, #0			@ How should we convert NAN?
   1426 	RET
   1427 
   1428 	CFI_END_FUNCTION
   1429 	FUNC_END aeabi_d2iz
   1430 	FUNC_END fixdfsi
   1431 
   1432 #endif /* L_fixdfsi */
   1433 
   1434 #ifdef L_arm_fixunsdfsi
   1435 
   1436 ARM_FUNC_START fixunsdfsi
   1437 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
   1438 	CFI_START_FUNCTION
   1439 
   1440 	@ check exponent range.
   1441 	movs	r2, xh, lsl #1
   1442 	bcs	1f			@ value is negative
   1443 	adds	r2, r2, #(1 << 21)
   1444 	bcs	2f			@ value is INF or NAN
   1445 	bpl	1f			@ value is too small
   1446 	mov	r3, #(0xfffffc00 + 31)
   1447 	subs	r2, r3, r2, asr #21
   1448 	bmi	3f			@ value is too large
   1449 
   1450 	@ scale value
   1451 	mov	r3, xh, lsl #11
   1452 	orr	r3, r3, #0x80000000
   1453 	orr	r3, r3, xl, lsr #21
   1454 	shift1	lsr, r0, r3, r2
   1455 	RET
   1456 
   1457 1:	mov	r0, #0
   1458 	RET
   1459 
   1460 2:	orrs	xl, xl, xh, lsl #12
   1461 	bne	4f			@ value is NAN.
   1462 3:	mov	r0, #0xffffffff		@ maximum unsigned si
   1463 	RET
   1464 
   1465 4:	mov	r0, #0			@ How should we convert NAN?
   1466 	RET
   1467 
   1468 	CFI_END_FUNCTION
   1469 	FUNC_END aeabi_d2uiz
   1470 	FUNC_END fixunsdfsi
   1471 
   1472 #endif /* L_fixunsdfsi */
   1473 
   1474 #ifdef L_arm_truncdfsf2
   1475 
   1476 ARM_FUNC_START truncdfsf2
   1477 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
   1478 	CFI_START_FUNCTION
   1479 
   1480 	@ check exponent range.
   1481 	mov	r2, xh, lsl #1
   1482 	subs	r3, r2, #((1023 - 127) << 21)
   1483 	do_it	cs, t
   1484 	COND(sub,s,cs)	ip, r3, #(1 << 21)
   1485 	COND(rsb,s,cs)	ip, ip, #(254 << 21)
   1486 	bls	2f			@ value is out of range
   1487 
   1488 1:	@ shift and round mantissa
   1489 	and	ip, xh, #0x80000000
   1490 	mov	r2, xl, lsl #3
   1491 	orr	xl, ip, xl, lsr #29
   1492 	cmp	r2, #0x80000000
   1493 	adc	r0, xl, r3, lsl #2
   1494 	do_it	eq
   1495 	biceq	r0, r0, #1
   1496 	RET
   1497 
   1498 2:	@ either overflow or underflow
   1499 	tst	xh, #0x40000000
   1500 	bne	3f			@ overflow
   1501 
   1502 	@ check if denormalized value is possible
   1503 	adds	r2, r3, #(23 << 21)
   1504 	do_it	lt, t
   1505 	andlt	r0, xh, #0x80000000	@ too small, return signed 0.
   1506 	RETc(lt)
   1507 
   1508 	@ denormalize value so we can resume with the code above afterwards.
   1509 	orr	xh, xh, #0x00100000
   1510 	mov	r2, r2, lsr #21
   1511 	rsb	r2, r2, #24
   1512 	rsb	ip, r2, #32
   1513 #if defined(__thumb2__)
   1514 	lsls	r3, xl, ip
   1515 #else
   1516 	movs	r3, xl, lsl ip
   1517 #endif
   1518 	shift1	lsr, xl, xl, r2
   1519 	do_it	ne
   1520 	orrne	xl, xl, #1		@ fold r3 for rounding considerations.
   1521 	mov	r3, xh, lsl #11
   1522 	mov	r3, r3, lsr #11
   1523 	shiftop orr xl xl r3 lsl ip ip
   1524 	shift1	lsr, r3, r3, r2
   1525 	mov	r3, r3, lsl #1
   1526 	b	1b
   1527 
   1528 3:	@ chech for NAN
   1529 	mvns	r3, r2, asr #21
   1530 	bne	5f			@ simple overflow
   1531 	orrs	r3, xl, xh, lsl #12
   1532 	do_it	ne, tt
   1533 	movne	r0, #0x7f000000
   1534 	orrne	r0, r0, #0x00c00000
   1535 	RETc(ne)			@ return NAN
   1536 
   1537 5:	@ return INF with sign
   1538 	and	r0, xh, #0x80000000
   1539 	orr	r0, r0, #0x7f000000
   1540 	orr	r0, r0, #0x00800000
   1541 	RET
   1542 
   1543 	CFI_END_FUNCTION
   1544 	FUNC_END aeabi_d2f
   1545 	FUNC_END truncdfsf2
   1546 
   1547 #endif /* L_truncdfsf2 */
   1548