1/* ieee754-df.S double-precision floating point support for ARM
2
3   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009  Free Software Foundation, Inc.
4   Contributed by Nicolas Pitre (nico@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
38
39@ For FPA, float words are always big-endian.
40@ For VFP, floats words follow the memory system mode.
41#if defined(__VFP_FP__) && !defined(__ARMEB__)
42#define xl r0
43#define xh r1
44#define yl r2
45#define yh r3
46#else
47#define xh r0
48#define xl r1
49#define yh r2
50#define yl r3
51#endif
52
53
54#ifdef L_arm_negdf2
55
56ARM_FUNC_START negdf2
57ARM_FUNC_ALIAS aeabi_dneg negdf2
58
59	@ flip sign bit
60	eor	xh, xh, #0x80000000
61	RET
62
63	FUNC_END aeabi_dneg
64	FUNC_END negdf2
65
66#endif
67
68#ifdef L_arm_addsubdf3
69
70ARM_FUNC_START aeabi_drsub
71
72	eor	xh, xh, #0x80000000	@ flip sign bit of first arg
73	b	1f
74
75ARM_FUNC_START subdf3
76ARM_FUNC_ALIAS aeabi_dsub subdf3
77
78	eor	yh, yh, #0x80000000	@ flip sign bit of second arg
79#if defined(__INTERWORKING_STUBS__)
80	b	1f			@ Skip Thumb-code prologue
81#endif
82
83ARM_FUNC_START adddf3
84ARM_FUNC_ALIAS aeabi_dadd adddf3
85
861:	do_push	{r4, r5, lr}
87
88	@ Look for zeroes, equal values, INF, or NAN.
89	shift1	lsl, r4, xh, #1
90	shift1	lsl, r5, yh, #1
91	teq	r4, r5
92	do_it	eq
93	teqeq	xl, yl
94	do_it	ne, ttt
95	COND(orr,s,ne)	ip, r4, xl
96	COND(orr,s,ne)	ip, r5, yl
97	COND(mvn,s,ne)	ip, r4, asr #21
98	COND(mvn,s,ne)	ip, r5, asr #21
99	beq	LSYM(Lad_s)
100
101	@ Compute exponent difference.  Make largest exponent in r4,
102	@ corresponding arg in xh-xl, and positive exponent difference in r5.
103	shift1	lsr, r4, r4, #21
104	rsbs	r5, r4, r5, lsr #21
105	do_it	lt
106	rsblt	r5, r5, #0
107	ble	1f
108	add	r4, r4, r5
109	eor	yl, xl, yl
110	eor	yh, xh, yh
111	eor	xl, yl, xl
112	eor	xh, yh, xh
113	eor	yl, xl, yl
114	eor	yh, xh, yh
1151:
116	@ If exponent difference is too large, return largest argument
117	@ already in xh-xl.  We need up to 54 bit to handle proper rounding
118	@ of 0x1p54 - 1.1.
119	cmp	r5, #54
120	do_it	hi
121	RETLDM	"r4, r5" hi
122
123	@ Convert mantissa to signed integer.
124	tst	xh, #0x80000000
125	mov	xh, xh, lsl #12
126	mov	ip, #0x00100000
127	orr	xh, ip, xh, lsr #12
128	beq	1f
129#if defined(__thumb2__)
130	negs	xl, xl
131	sbc	xh, xh, xh, lsl #1
132#else
133	rsbs	xl, xl, #0
134	rsc	xh, xh, #0
135#endif
1361:
137	tst	yh, #0x80000000
138	mov	yh, yh, lsl #12
139	orr	yh, ip, yh, lsr #12
140	beq	1f
141#if defined(__thumb2__)
142	negs	yl, yl
143	sbc	yh, yh, yh, lsl #1
144#else
145	rsbs	yl, yl, #0
146	rsc	yh, yh, #0
147#endif
1481:
149	@ If exponent == difference, one or both args were denormalized.
150	@ Since this is not common case, rescale them off line.
151	teq	r4, r5
152	beq	LSYM(Lad_d)
153LSYM(Lad_x):
154
155	@ Compensate for the exponent overlapping the mantissa MSB added later
156	sub	r4, r4, #1
157
158	@ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
159	rsbs	lr, r5, #32
160	blt	1f
161	shift1	lsl, ip, yl, lr
162	shiftop adds xl xl yl lsr r5 yl
163	adc	xh, xh, #0
164	shiftop adds xl xl yh lsl lr yl
165	shiftop adcs xh xh yh asr r5 yh
166	b	2f
1671:	sub	r5, r5, #32
168	add	lr, lr, #32
169	cmp	yl, #1
170	shift1	lsl,ip, yh, lr
171	do_it	cs
172	orrcs	ip, ip, #2		@ 2 not 1, to allow lsr #1 later
173	shiftop adds xl xl yh asr r5 yh
174	adcs	xh, xh, yh, asr #31
1752:
176	@ We now have a result in xh-xl-ip.
177	@ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
178	and	r5, xh, #0x80000000
179	bpl	LSYM(Lad_p)
180#if defined(__thumb2__)
181	mov	lr, #0
182	negs	ip, ip
183	sbcs	xl, lr, xl
184	sbc	xh, lr, xh
185#else
186	rsbs	ip, ip, #0
187	rscs	xl, xl, #0
188	rsc	xh, xh, #0
189#endif
190
191	@ Determine how to normalize the result.
192LSYM(Lad_p):
193	cmp	xh, #0x00100000
194	bcc	LSYM(Lad_a)
195	cmp	xh, #0x00200000
196	bcc	LSYM(Lad_e)
197
198	@ Result needs to be shifted right.
199	movs	xh, xh, lsr #1
200	movs	xl, xl, rrx
201	mov	ip, ip, rrx
202	add	r4, r4, #1
203
204	@ Make sure we did not bust our exponent.
205	mov	r2, r4, lsl #21
206	cmn	r2, #(2 << 21)
207	bcs	LSYM(Lad_o)
208
209	@ Our result is now properly aligned into xh-xl, remaining bits in ip.
210	@ Round with MSB of ip. If halfway between two numbers, round towards
211	@ LSB of xl = 0.
212	@ Pack final result together.
213LSYM(Lad_e):
214	cmp	ip, #0x80000000
215	do_it	eq
216	COND(mov,s,eq)	ip, xl, lsr #1
217	adcs	xl, xl, #0
218	adc	xh, xh, r4, lsl #20
219	orr	xh, xh, r5
220	RETLDM	"r4, r5"
221
222	@ Result must be shifted left and exponent adjusted.
223LSYM(Lad_a):
224	movs	ip, ip, lsl #1
225	adcs	xl, xl, xl
226	adc	xh, xh, xh
227	tst	xh, #0x00100000
228	sub	r4, r4, #1
229	bne	LSYM(Lad_e)
230
231	@ No rounding necessary since ip will always be 0 at this point.
232LSYM(Lad_l):
233
234#if __ARM_ARCH__ < 5
235
236	teq	xh, #0
237	movne	r3, #20
238	moveq	r3, #52
239	moveq	xh, xl
240	moveq	xl, #0
241	mov	r2, xh
242	cmp	r2, #(1 << 16)
243	movhs	r2, r2, lsr #16
244	subhs	r3, r3, #16
245	cmp	r2, #(1 << 8)
246	movhs	r2, r2, lsr #8
247	subhs	r3, r3, #8
248	cmp	r2, #(1 << 4)
249	movhs	r2, r2, lsr #4
250	subhs	r3, r3, #4
251	cmp	r2, #(1 << 2)
252	subhs	r3, r3, #2
253	sublo	r3, r3, r2, lsr #1
254	sub	r3, r3, r2, lsr #3
255
256#else
257
258	teq	xh, #0
259	do_it	eq, t
260	moveq	xh, xl
261	moveq	xl, #0
262	clz	r3, xh
263	do_it	eq
264	addeq	r3, r3, #32
265	sub	r3, r3, #11
266
267#endif
268
269	@ determine how to shift the value.
270	subs	r2, r3, #32
271	bge	2f
272	adds	r2, r2, #12
273	ble	1f
274
275	@ shift value left 21 to 31 bits, or actually right 11 to 1 bits
276	@ since a register switch happened above.
277	add	ip, r2, #20
278	rsb	r2, r2, #12
279	shift1	lsl, xl, xh, ip
280	shift1	lsr, xh, xh, r2
281	b	3f
282
283	@ actually shift value left 1 to 20 bits, which might also represent
284	@ 32 to 52 bits if counting the register switch that happened earlier.
2851:	add	r2, r2, #20
2862:	do_it	le
287	rsble	ip, r2, #32
288	shift1	lsl, xh, xh, r2
289#if defined(__thumb2__)
290	lsr	ip, xl, ip
291	itt	le
292	orrle	xh, xh, ip
293	lslle	xl, xl, r2
294#else
295	orrle	xh, xh, xl, lsr ip
296	movle	xl, xl, lsl r2
297#endif
298
299	@ adjust exponent accordingly.
3003:	subs	r4, r4, r3
301	do_it	ge, tt
302	addge	xh, xh, r4, lsl #20
303	orrge	xh, xh, r5
304	RETLDM	"r4, r5" ge
305
306	@ Exponent too small, denormalize result.
307	@ Find out proper shift value.
308	mvn	r4, r4
309	subs	r4, r4, #31
310	bge	2f
311	adds	r4, r4, #12
312	bgt	1f
313
314	@ shift result right of 1 to 20 bits, sign is in r5.
315	add	r4, r4, #20
316	rsb	r2, r4, #32
317	shift1	lsr, xl, xl, r4
318	shiftop orr xl xl xh lsl r2 yh
319	shiftop orr xh r5 xh lsr r4 yh
320	RETLDM	"r4, r5"
321
322	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
323	@ a register switch from xh to xl.
3241:	rsb	r4, r4, #12
325	rsb	r2, r4, #32
326	shift1	lsr, xl, xl, r2
327	shiftop orr xl xl xh lsl r4 yh
328	mov	xh, r5
329	RETLDM	"r4, r5"
330
331	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
332	@ from xh to xl.
3332:	shift1	lsr, xl, xh, r4
334	mov	xh, r5
335	RETLDM	"r4, r5"
336
337	@ Adjust exponents for denormalized arguments.
338	@ Note that r4 must not remain equal to 0.
339LSYM(Lad_d):
340	teq	r4, #0
341	eor	yh, yh, #0x00100000
342	do_it	eq, te
343	eoreq	xh, xh, #0x00100000
344	addeq	r4, r4, #1
345	subne	r5, r5, #1
346	b	LSYM(Lad_x)
347
348
349LSYM(Lad_s):
350	mvns	ip, r4, asr #21
351	do_it	ne
352	COND(mvn,s,ne)	ip, r5, asr #21
353	beq	LSYM(Lad_i)
354
355	teq	r4, r5
356	do_it	eq
357	teqeq	xl, yl
358	beq	1f
359
360	@ Result is x + 0.0 = x or 0.0 + y = y.
361	orrs	ip, r4, xl
362	do_it	eq, t
363	moveq	xh, yh
364	moveq	xl, yl
365	RETLDM	"r4, r5"
366
3671:	teq	xh, yh
368
369	@ Result is x - x = 0.
370	do_it	ne, tt
371	movne	xh, #0
372	movne	xl, #0
373	RETLDM	"r4, r5" ne
374
375	@ Result is x + x = 2x.
376	movs	ip, r4, lsr #21
377	bne	2f
378	movs	xl, xl, lsl #1
379	adcs	xh, xh, xh
380	do_it	cs
381	orrcs	xh, xh, #0x80000000
382	RETLDM	"r4, r5"
3832:	adds	r4, r4, #(2 << 21)
384	do_it	cc, t
385	addcc	xh, xh, #(1 << 20)
386	RETLDM	"r4, r5" cc
387	and	r5, xh, #0x80000000
388
389	@ Overflow: return INF.
390LSYM(Lad_o):
391	orr	xh, r5, #0x7f000000
392	orr	xh, xh, #0x00f00000
393	mov	xl, #0
394	RETLDM	"r4, r5"
395
396	@ At least one of x or y is INF/NAN.
397	@   if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
398	@   if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
399	@   if either is NAN: return NAN
400	@   if opposite sign: return NAN
401	@   otherwise return xh-xl (which is INF or -INF)
402LSYM(Lad_i):
403	mvns	ip, r4, asr #21
404	do_it	ne, te
405	movne	xh, yh
406	movne	xl, yl
407	COND(mvn,s,eq)	ip, r5, asr #21
408	do_it	ne, t
409	movne	yh, xh
410	movne	yl, xl
411	orrs	r4, xl, xh, lsl #12
412	do_it	eq, te
413	COND(orr,s,eq)	r5, yl, yh, lsl #12
414	teqeq	xh, yh
415	orrne	xh, xh, #0x00080000	@ quiet NAN
416	RETLDM	"r4, r5"
417
418	FUNC_END aeabi_dsub
419	FUNC_END subdf3
420	FUNC_END aeabi_dadd
421	FUNC_END adddf3
422
423ARM_FUNC_START floatunsidf
424ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
425
426	teq	r0, #0
427	do_it	eq, t
428	moveq	r1, #0
429	RETc(eq)
430	do_push	{r4, r5, lr}
431	mov	r4, #0x400		@ initial exponent
432	add	r4, r4, #(52-1 - 1)
433	mov	r5, #0			@ sign bit is 0
434	.ifnc	xl, r0
435	mov	xl, r0
436	.endif
437	mov	xh, #0
438	b	LSYM(Lad_l)
439
440	FUNC_END aeabi_ui2d
441	FUNC_END floatunsidf
442
443ARM_FUNC_START floatsidf
444ARM_FUNC_ALIAS aeabi_i2d floatsidf
445
446	teq	r0, #0
447	do_it	eq, t
448	moveq	r1, #0
449	RETc(eq)
450	do_push	{r4, r5, lr}
451	mov	r4, #0x400		@ initial exponent
452	add	r4, r4, #(52-1 - 1)
453	ands	r5, r0, #0x80000000	@ sign bit in r5
454	do_it	mi
455	rsbmi	r0, r0, #0		@ absolute value
456	.ifnc	xl, r0
457	mov	xl, r0
458	.endif
459	mov	xh, #0
460	b	LSYM(Lad_l)
461
462	FUNC_END aeabi_i2d
463	FUNC_END floatsidf
464
465ARM_FUNC_START extendsfdf2
466ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
467
468	movs	r2, r0, lsl #1		@ toss sign bit
469	mov	xh, r2, asr #3		@ stretch exponent
470	mov	xh, xh, rrx		@ retrieve sign bit
471	mov	xl, r2, lsl #28		@ retrieve remaining bits
472	do_it	ne, ttt
473	COND(and,s,ne)	r3, r2, #0xff000000	@ isolate exponent
474	teqne	r3, #0xff000000		@ if not 0, check if INF or NAN
475	eorne	xh, xh, #0x38000000	@ fixup exponent otherwise.
476	RETc(ne)			@ and return it.
477
478	teq	r2, #0			@ if actually 0
479	do_it	ne, e
480	teqne	r3, #0xff000000		@ or INF or NAN
481	RETc(eq)			@ we are done already.
482
483	@ value was denormalized.  We can normalize it now.
484	do_push	{r4, r5, lr}
485	mov	r4, #0x380		@ setup corresponding exponent
486	and	r5, xh, #0x80000000	@ move sign bit in r5
487	bic	xh, xh, #0x80000000
488	b	LSYM(Lad_l)
489
490	FUNC_END aeabi_f2d
491	FUNC_END extendsfdf2
492
493ARM_FUNC_START floatundidf
494ARM_FUNC_ALIAS aeabi_ul2d floatundidf
495
496	orrs	r2, r0, r1
497#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
498	do_it	eq, t
499	mvfeqd	f0, #0.0
500#else
501	do_it	eq
502#endif
503	RETc(eq)
504
505#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
506	@ For hard FPA code we want to return via the tail below so that
507	@ we can return the result in f0 as well as in r0/r1 for backwards
508	@ compatibility.
509	adr	ip, LSYM(f0_ret)
510	@ Push pc as well so that RETLDM works correctly.
511	do_push	{r4, r5, ip, lr, pc}
512#else
513	do_push	{r4, r5, lr}
514#endif
515
516	mov	r5, #0
517	b	2f
518
519ARM_FUNC_START floatdidf
520ARM_FUNC_ALIAS aeabi_l2d floatdidf
521
522	orrs	r2, r0, r1
523#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
524	do_it	eq, t
525	mvfeqd	f0, #0.0
526#else
527	do_it	eq
528#endif
529	RETc(eq)
530
531#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
532	@ For hard FPA code we want to return via the tail below so that
533	@ we can return the result in f0 as well as in r0/r1 for backwards
534	@ compatibility.
535	adr	ip, LSYM(f0_ret)
536	@ Push pc as well so that RETLDM works correctly.
537	do_push	{r4, r5, ip, lr, pc}
538#else
539	do_push	{r4, r5, lr}
540#endif
541
542	ands	r5, ah, #0x80000000	@ sign bit in r5
543	bpl	2f
544#if defined(__thumb2__)
545	negs	al, al
546	sbc	ah, ah, ah, lsl #1
547#else
548	rsbs	al, al, #0
549	rsc	ah, ah, #0
550#endif
5512:
552	mov	r4, #0x400		@ initial exponent
553	add	r4, r4, #(52-1 - 1)
554
555	@ FPA little-endian: must swap the word order.
556	.ifnc	xh, ah
557	mov	ip, al
558	mov	xh, ah
559	mov	xl, ip
560	.endif
561
562	movs	ip, xh, lsr #22
563	beq	LSYM(Lad_p)
564
565	@ The value is too big.  Scale it down a bit...
566	mov	r2, #3
567	movs	ip, ip, lsr #3
568	do_it	ne
569	addne	r2, r2, #3
570	movs	ip, ip, lsr #3
571	do_it	ne
572	addne	r2, r2, #3
573	add	r2, r2, ip, lsr #3
574
575	rsb	r3, r2, #32
576	shift1	lsl, ip, xl, r3
577	shift1	lsr, xl, xl, r2
578	shiftop orr xl xl xh lsl r3 lr
579	shift1	lsr, xh, xh, r2
580	add	r4, r4, r2
581	b	LSYM(Lad_p)
582
583#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
584
585	@ Legacy code expects the result to be returned in f0.  Copy it
586	@ there as well.
587LSYM(f0_ret):
588	do_push	{r0, r1}
589	ldfd	f0, [sp], #8
590	RETLDM
591
592#endif
593
594	FUNC_END floatdidf
595	FUNC_END aeabi_l2d
596	FUNC_END floatundidf
597	FUNC_END aeabi_ul2d
598
599#endif /* L_addsubdf3 */
600
601#ifdef L_arm_muldivdf3
602
603ARM_FUNC_START muldf3
604ARM_FUNC_ALIAS aeabi_dmul muldf3
605	do_push	{r4, r5, r6, lr}
606
607	@ Mask out exponents, trap any zero/denormal/INF/NAN.
608	mov	ip, #0xff
609	orr	ip, ip, #0x700
610	ands	r4, ip, xh, lsr #20
611	do_it	ne, tte
612	COND(and,s,ne)	r5, ip, yh, lsr #20
613	teqne	r4, ip
614	teqne	r5, ip
615	bleq	LSYM(Lml_s)
616
617	@ Add exponents together
618	add	r4, r4, r5
619
620	@ Determine final sign.
621	eor	r6, xh, yh
622
623	@ Convert mantissa to unsigned integer.
624	@ If power of two, branch to a separate path.
625	bic	xh, xh, ip, lsl #21
626	bic	yh, yh, ip, lsl #21
627	orrs	r5, xl, xh, lsl #12
628	do_it	ne
629	COND(orr,s,ne)	r5, yl, yh, lsl #12
630	orr	xh, xh, #0x00100000
631	orr	yh, yh, #0x00100000
632	beq	LSYM(Lml_1)
633
634#if __ARM_ARCH__ < 4
635
636	@ Put sign bit in r6, which will be restored in yl later.
637	and   r6, r6, #0x80000000
638
639	@ Well, no way to make it shorter without the umull instruction.
640	stmfd	sp!, {r6, r7, r8, r9, sl, fp}
641	mov	r7, xl, lsr #16
642	mov	r8, yl, lsr #16
643	mov	r9, xh, lsr #16
644	mov	sl, yh, lsr #16
645	bic	xl, xl, r7, lsl #16
646	bic	yl, yl, r8, lsl #16
647	bic	xh, xh, r9, lsl #16
648	bic	yh, yh, sl, lsl #16
649	mul	ip, xl, yl
650	mul	fp, xl, r8
651	mov	lr, #0
652	adds	ip, ip, fp, lsl #16
653	adc	lr, lr, fp, lsr #16
654	mul	fp, r7, yl
655	adds	ip, ip, fp, lsl #16
656	adc	lr, lr, fp, lsr #16
657	mul	fp, xl, sl
658	mov	r5, #0
659	adds	lr, lr, fp, lsl #16
660	adc	r5, r5, fp, lsr #16
661	mul	fp, r7, yh
662	adds	lr, lr, fp, lsl #16
663	adc	r5, r5, fp, lsr #16
664	mul	fp, xh, r8
665	adds	lr, lr, fp, lsl #16
666	adc	r5, r5, fp, lsr #16
667	mul	fp, r9, yl
668	adds	lr, lr, fp, lsl #16
669	adc	r5, r5, fp, lsr #16
670	mul	fp, xh, sl
671	mul	r6, r9, sl
672	adds	r5, r5, fp, lsl #16
673	adc	r6, r6, fp, lsr #16
674	mul	fp, r9, yh
675	adds	r5, r5, fp, lsl #16
676	adc	r6, r6, fp, lsr #16
677	mul	fp, xl, yh
678	adds	lr, lr, fp
679	mul	fp, r7, sl
680	adcs	r5, r5, fp
681	mul	fp, xh, yl
682	adc	r6, r6, #0
683	adds	lr, lr, fp
684	mul	fp, r9, r8
685	adcs	r5, r5, fp
686	mul	fp, r7, r8
687	adc	r6, r6, #0
688	adds	lr, lr, fp
689	mul	fp, xh, yh
690	adcs	r5, r5, fp
691	adc	r6, r6, #0
692	ldmfd	sp!, {yl, r7, r8, r9, sl, fp}
693
694#else
695
696	@ Here is the actual multiplication.
697	umull	ip, lr, xl, yl
698	mov	r5, #0
699	umlal	lr, r5, xh, yl
700	and	yl, r6, #0x80000000
701	umlal	lr, r5, xl, yh
702	mov	r6, #0
703	umlal	r5, r6, xh, yh
704
705#endif
706
707	@ The LSBs in ip are only significant for the final rounding.
708	@ Fold them into lr.
709	teq	ip, #0
710	do_it	ne
711	orrne	lr, lr, #1
712
713	@ Adjust result upon the MSB position.
714	sub	r4, r4, #0xff
715	cmp	r6, #(1 << (20-11))
716	sbc	r4, r4, #0x300
717	bcs	1f
718	movs	lr, lr, lsl #1
719	adcs	r5, r5, r5
720	adc	r6, r6, r6
7211:
722	@ Shift to final position, add sign to result.
723	orr	xh, yl, r6, lsl #11
724	orr	xh, xh, r5, lsr #21
725	mov	xl, r5, lsl #11
726	orr	xl, xl, lr, lsr #21
727	mov	lr, lr, lsl #11
728
729	@ Check exponent range for under/overflow.
730	subs	ip, r4, #(254 - 1)
731	do_it	hi
732	cmphi	ip, #0x700
733	bhi	LSYM(Lml_u)
734
735	@ Round the result, merge final exponent.
736	cmp	lr, #0x80000000
737	do_it	eq
738	COND(mov,s,eq)	lr, xl, lsr #1
739	adcs	xl, xl, #0
740	adc	xh, xh, r4, lsl #20
741	RETLDM	"r4, r5, r6"
742
743	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
744LSYM(Lml_1):
745	and	r6, r6, #0x80000000
746	orr	xh, r6, xh
747	orr	xl, xl, yl
748	eor	xh, xh, yh
749	subs	r4, r4, ip, lsr #1
750	do_it	gt, tt
751	COND(rsb,s,gt)	r5, r4, ip
752	orrgt	xh, xh, r4, lsl #20
753	RETLDM	"r4, r5, r6" gt
754
755	@ Under/overflow: fix things up for the code below.
756	orr	xh, xh, #0x00100000
757	mov	lr, #0
758	subs	r4, r4, #1
759
760LSYM(Lml_u):
761	@ Overflow?
762	bgt	LSYM(Lml_o)
763
764	@ Check if denormalized result is possible, otherwise return signed 0.
765	cmn	r4, #(53 + 1)
766	do_it	le, tt
767	movle	xl, #0
768	bicle	xh, xh, #0x7fffffff
769	RETLDM	"r4, r5, r6" le
770
771	@ Find out proper shift value.
772	rsb	r4, r4, #0
773	subs	r4, r4, #32
774	bge	2f
775	adds	r4, r4, #12
776	bgt	1f
777
778	@ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
779	add	r4, r4, #20
780	rsb	r5, r4, #32
781	shift1	lsl, r3, xl, r5
782	shift1	lsr, xl, xl, r4
783	shiftop orr xl xl xh lsl r5 r2
784	and	r2, xh, #0x80000000
785	bic	xh, xh, #0x80000000
786	adds	xl, xl, r3, lsr #31
787	shiftop adc xh r2 xh lsr r4 r6
788	orrs	lr, lr, r3, lsl #1
789	do_it	eq
790	biceq	xl, xl, r3, lsr #31
791	RETLDM	"r4, r5, r6"
792
793	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
794	@ a register switch from xh to xl. Then round.
7951:	rsb	r4, r4, #12
796	rsb	r5, r4, #32
797	shift1	lsl, r3, xl, r4
798	shift1	lsr, xl, xl, r5
799	shiftop orr xl xl xh lsl r4 r2
800	bic	xh, xh, #0x7fffffff
801	adds	xl, xl, r3, lsr #31
802	adc	xh, xh, #0
803	orrs	lr, lr, r3, lsl #1
804	do_it	eq
805	biceq	xl, xl, r3, lsr #31
806	RETLDM	"r4, r5, r6"
807
808	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
809	@ from xh to xl.  Leftover bits are in r3-r6-lr for rounding.
8102:	rsb	r5, r4, #32
811	shiftop orr lr lr xl lsl r5 r2
812	shift1	lsr, r3, xl, r4
813	shiftop orr r3 r3 xh lsl r5 r2
814	shift1	lsr, xl, xh, r4
815	bic	xh, xh, #0x7fffffff
816	shiftop bic xl xl xh lsr r4 r2
817	add	xl, xl, r3, lsr #31
818	orrs	lr, lr, r3, lsl #1
819	do_it	eq
820	biceq	xl, xl, r3, lsr #31
821	RETLDM	"r4, r5, r6"
822
823	@ One or both arguments are denormalized.
824	@ Scale them leftwards and preserve sign bit.
825LSYM(Lml_d):
826	teq	r4, #0
827	bne	2f
828	and	r6, xh, #0x80000000
8291:	movs	xl, xl, lsl #1
830	adc	xh, xh, xh
831	tst	xh, #0x00100000
832	do_it	eq
833	subeq	r4, r4, #1
834	beq	1b
835	orr	xh, xh, r6
836	teq	r5, #0
837	do_it	ne
838	RETc(ne)
8392:	and	r6, yh, #0x80000000
8403:	movs	yl, yl, lsl #1
841	adc	yh, yh, yh
842	tst	yh, #0x00100000
843	do_it	eq
844	subeq	r5, r5, #1
845	beq	3b
846	orr	yh, yh, r6
847	RET
848
849LSYM(Lml_s):
850	@ Isolate the INF and NAN cases away
851	teq	r4, ip
852	and	r5, ip, yh, lsr #20
853	do_it	ne
854	teqne	r5, ip
855	beq	1f
856
857	@ Here, one or more arguments are either denormalized or zero.
858	orrs	r6, xl, xh, lsl #1
859	do_it	ne
860	COND(orr,s,ne)	r6, yl, yh, lsl #1
861	bne	LSYM(Lml_d)
862
863	@ Result is 0, but determine sign anyway.
864LSYM(Lml_z):
865	eor	xh, xh, yh
866	and	xh, xh, #0x80000000
867	mov	xl, #0
868	RETLDM	"r4, r5, r6"
869
8701:	@ One or both args are INF or NAN.
871	orrs	r6, xl, xh, lsl #1
872	do_it	eq, te
873	moveq	xl, yl
874	moveq	xh, yh
875	COND(orr,s,ne)	r6, yl, yh, lsl #1
876	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
877	teq	r4, ip
878	bne	1f
879	orrs	r6, xl, xh, lsl #12
880	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
8811:	teq	r5, ip
882	bne	LSYM(Lml_i)
883	orrs	r6, yl, yh, lsl #12
884	do_it	ne, t
885	movne	xl, yl
886	movne	xh, yh
887	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
888
889	@ Result is INF, but we need to determine its sign.
890LSYM(Lml_i):
891	eor	xh, xh, yh
892
893	@ Overflow: return INF (sign already in xh).
894LSYM(Lml_o):
895	and	xh, xh, #0x80000000
896	orr	xh, xh, #0x7f000000
897	orr	xh, xh, #0x00f00000
898	mov	xl, #0
899	RETLDM	"r4, r5, r6"
900
901	@ Return a quiet NAN.
902LSYM(Lml_n):
903	orr	xh, xh, #0x7f000000
904	orr	xh, xh, #0x00f80000
905	RETLDM	"r4, r5, r6"
906
907	FUNC_END aeabi_dmul
908	FUNC_END muldf3
909
910ARM_FUNC_START divdf3
911ARM_FUNC_ALIAS aeabi_ddiv divdf3
912
913	do_push	{r4, r5, r6, lr}
914
915	@ Mask out exponents, trap any zero/denormal/INF/NAN.
916	mov	ip, #0xff
917	orr	ip, ip, #0x700
918	ands	r4, ip, xh, lsr #20
919	do_it	ne, tte
920	COND(and,s,ne)	r5, ip, yh, lsr #20
921	teqne	r4, ip
922	teqne	r5, ip
923	bleq	LSYM(Ldv_s)
924
925	@ Substract divisor exponent from dividend''s.
926	sub	r4, r4, r5
927
928	@ Preserve final sign into lr.
929	eor	lr, xh, yh
930
931	@ Convert mantissa to unsigned integer.
932	@ Dividend -> r5-r6, divisor -> yh-yl.
933	orrs	r5, yl, yh, lsl #12
934	mov	xh, xh, lsl #12
935	beq	LSYM(Ldv_1)
936	mov	yh, yh, lsl #12
937	mov	r5, #0x10000000
938	orr	yh, r5, yh, lsr #4
939	orr	yh, yh, yl, lsr #24
940	mov	yl, yl, lsl #8
941	orr	r5, r5, xh, lsr #4
942	orr	r5, r5, xl, lsr #24
943	mov	r6, xl, lsl #8
944
945	@ Initialize xh with final sign bit.
946	and	xh, lr, #0x80000000
947
948	@ Ensure result will land to known bit position.
949	@ Apply exponent bias accordingly.
950	cmp	r5, yh
951	do_it	eq
952	cmpeq	r6, yl
953	adc	r4, r4, #(255 - 2)
954	add	r4, r4, #0x300
955	bcs	1f
956	movs	yh, yh, lsr #1
957	mov	yl, yl, rrx
9581:
959	@ Perform first substraction to align result to a nibble.
960	subs	r6, r6, yl
961	sbc	r5, r5, yh
962	movs	yh, yh, lsr #1
963	mov	yl, yl, rrx
964	mov	xl, #0x00100000
965	mov	ip, #0x00080000
966
967	@ The actual division loop.
9681:	subs	lr, r6, yl
969	sbcs	lr, r5, yh
970	do_it	cs, tt
971	subcs	r6, r6, yl
972	movcs	r5, lr
973	orrcs	xl, xl, ip
974	movs	yh, yh, lsr #1
975	mov	yl, yl, rrx
976	subs	lr, r6, yl
977	sbcs	lr, r5, yh
978	do_it	cs, tt
979	subcs	r6, r6, yl
980	movcs	r5, lr
981	orrcs	xl, xl, ip, lsr #1
982	movs	yh, yh, lsr #1
983	mov	yl, yl, rrx
984	subs	lr, r6, yl
985	sbcs	lr, r5, yh
986	do_it	cs, tt
987	subcs	r6, r6, yl
988	movcs	r5, lr
989	orrcs	xl, xl, ip, lsr #2
990	movs	yh, yh, lsr #1
991	mov	yl, yl, rrx
992	subs	lr, r6, yl
993	sbcs	lr, r5, yh
994	do_it	cs, tt
995	subcs	r6, r6, yl
996	movcs	r5, lr
997	orrcs	xl, xl, ip, lsr #3
998
999	orrs	lr, r5, r6
1000	beq	2f
1001	mov	r5, r5, lsl #4
1002	orr	r5, r5, r6, lsr #28
1003	mov	r6, r6, lsl #4
1004	mov	yh, yh, lsl #3
1005	orr	yh, yh, yl, lsr #29
1006	mov	yl, yl, lsl #3
1007	movs	ip, ip, lsr #4
1008	bne	1b
1009
1010	@ We are done with a word of the result.
1011	@ Loop again for the low word if this pass was for the high word.
1012	tst	xh, #0x00100000
1013	bne	3f
1014	orr	xh, xh, xl
1015	mov	xl, #0
1016	mov	ip, #0x80000000
1017	b	1b
10182:
1019	@ Be sure result starts in the high word.
1020	tst	xh, #0x00100000
1021	do_it	eq, t
1022	orreq	xh, xh, xl
1023	moveq	xl, #0
10243:
1025	@ Check exponent range for under/overflow.
1026	subs	ip, r4, #(254 - 1)
1027	do_it	hi
1028	cmphi	ip, #0x700
1029	bhi	LSYM(Lml_u)
1030
1031	@ Round the result, merge final exponent.
1032	subs	ip, r5, yh
1033	do_it	eq, t
1034	COND(sub,s,eq)	ip, r6, yl
1035	COND(mov,s,eq)	ip, xl, lsr #1
1036	adcs	xl, xl, #0
1037	adc	xh, xh, r4, lsl #20
1038	RETLDM	"r4, r5, r6"
1039
1040	@ Division by 0x1p*: shortcut a lot of code.
1041LSYM(Ldv_1):
1042	and	lr, lr, #0x80000000
1043	orr	xh, lr, xh, lsr #12
1044	adds	r4, r4, ip, lsr #1
1045	do_it	gt, tt
1046	COND(rsb,s,gt)	r5, r4, ip
1047	orrgt	xh, xh, r4, lsl #20
1048	RETLDM	"r4, r5, r6" gt
1049
1050	orr	xh, xh, #0x00100000
1051	mov	lr, #0
1052	subs	r4, r4, #1
1053	b	LSYM(Lml_u)
1054
1055	@ Result mightt need to be denormalized: put remainder bits
1056	@ in lr for rounding considerations.
1057LSYM(Ldv_u):
1058	orr	lr, r5, r6
1059	b	LSYM(Lml_u)
1060
1061	@ One or both arguments is either INF, NAN or zero.
1062LSYM(Ldv_s):
1063	and	r5, ip, yh, lsr #20
1064	teq	r4, ip
1065	do_it	eq
1066	teqeq	r5, ip
1067	beq	LSYM(Lml_n)		@ INF/NAN / INF/NAN -> NAN
1068	teq	r4, ip
1069	bne	1f
1070	orrs	r4, xl, xh, lsl #12
1071	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
1072	teq	r5, ip
1073	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
1074	mov	xl, yl
1075	mov	xh, yh
1076	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
10771:	teq	r5, ip
1078	bne	2f
1079	orrs	r5, yl, yh, lsl #12
1080	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
1081	mov	xl, yl
1082	mov	xh, yh
1083	b	LSYM(Lml_n)		@ <anything> / NAN -> NAN
10842:	@ If both are nonzero, we need to normalize and resume above.
1085	orrs	r6, xl, xh, lsl #1
1086	do_it	ne
1087	COND(orr,s,ne)	r6, yl, yh, lsl #1
1088	bne	LSYM(Lml_d)
1089	@ One or both arguments are 0.
1090	orrs	r4, xl, xh, lsl #1
1091	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
1092	orrs	r5, yl, yh, lsl #1
1093	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
1094	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
1095
1096	FUNC_END aeabi_ddiv
1097	FUNC_END divdf3
1098
1099#endif /* L_muldivdf3 */
1100
1101#ifdef L_arm_cmpdf2
1102
1103@ Note: only r0 (return value) and ip are clobbered here.
1104
1105ARM_FUNC_START gtdf2
1106ARM_FUNC_ALIAS gedf2 gtdf2
1107	mov	ip, #-1
1108	b	1f
1109
1110ARM_FUNC_START ltdf2
1111ARM_FUNC_ALIAS ledf2 ltdf2
1112	mov	ip, #1
1113	b	1f
1114
1115ARM_FUNC_START cmpdf2
1116ARM_FUNC_ALIAS nedf2 cmpdf2
1117ARM_FUNC_ALIAS eqdf2 cmpdf2
1118	mov	ip, #1			@ how should we specify unordered here?
1119
11201:	str	ip, [sp, #-4]!
1121
1122	@ Trap any INF/NAN first.
1123	mov	ip, xh, lsl #1
1124	mvns	ip, ip, asr #21
1125	mov	ip, yh, lsl #1
1126	do_it	ne
1127	COND(mvn,s,ne)	ip, ip, asr #21
1128	beq	3f
1129
1130	@ Test for equality.
1131	@ Note that 0.0 is equal to -0.0.
11322:	add	sp, sp, #4
1133	orrs	ip, xl, xh, lsl #1	@ if x == 0.0 or -0.0
1134	do_it	eq, e
1135	COND(orr,s,eq)	ip, yl, yh, lsl #1	@ and y == 0.0 or -0.0
1136	teqne	xh, yh			@ or xh == yh
1137	do_it	eq, tt
1138	teqeq	xl, yl			@ and xl == yl
1139	moveq	r0, #0			@ then equal.
1140	RETc(eq)
1141
1142	@ Clear C flag
1143	cmn	r0, #0
1144
1145	@ Compare sign,
1146	teq	xh, yh
1147
1148	@ Compare values if same sign
1149	do_it	pl
1150	cmppl	xh, yh
1151	do_it	eq
1152	cmpeq	xl, yl
1153
1154	@ Result:
1155	do_it	cs, e
1156	movcs	r0, yh, asr #31
1157	mvncc	r0, yh, asr #31
1158	orr	r0, r0, #1
1159	RET
1160
1161	@ Look for a NAN.
11623:	mov	ip, xh, lsl #1
1163	mvns	ip, ip, asr #21
1164	bne	4f
1165	orrs	ip, xl, xh, lsl #12
1166	bne	5f			@ x is NAN
11674:	mov	ip, yh, lsl #1
1168	mvns	ip, ip, asr #21
1169	bne	2b
1170	orrs	ip, yl, yh, lsl #12
1171	beq	2b			@ y is not NAN
11725:	ldr	r0, [sp], #4		@ unordered return code
1173	RET
1174
1175	FUNC_END gedf2
1176	FUNC_END gtdf2
1177	FUNC_END ledf2
1178	FUNC_END ltdf2
1179	FUNC_END nedf2
1180	FUNC_END eqdf2
1181	FUNC_END cmpdf2
1182
1183ARM_FUNC_START aeabi_cdrcmple
1184
1185	mov	ip, r0
1186	mov	r0, r2
1187	mov	r2, ip
1188	mov	ip, r1
1189	mov	r1, r3
1190	mov	r3, ip
1191	b	6f
1192
1193ARM_FUNC_START aeabi_cdcmpeq
1194ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1195
1196	@ The status-returning routines are required to preserve all
1197	@ registers except ip, lr, and cpsr.
11986:	do_push	{r0, lr}
1199	ARM_CALL cmpdf2
1200	@ Set the Z flag correctly, and the C flag unconditionally.
1201	cmp	r0, #0
1202	@ Clear the C flag if the return value was -1, indicating
1203	@ that the first operand was smaller than the second.
1204	do_it	mi
1205	cmnmi	r0, #0
1206	RETLDM	"r0"
1207
1208	FUNC_END aeabi_cdcmple
1209	FUNC_END aeabi_cdcmpeq
1210	FUNC_END aeabi_cdrcmple
1211
1212ARM_FUNC_START	aeabi_dcmpeq
1213
1214	str	lr, [sp, #-8]!
1215	ARM_CALL aeabi_cdcmple
1216	do_it	eq, e
1217	moveq	r0, #1	@ Equal to.
1218	movne	r0, #0	@ Less than, greater than, or unordered.
1219	RETLDM
1220
1221	FUNC_END aeabi_dcmpeq
1222
1223ARM_FUNC_START	aeabi_dcmplt
1224
1225	str	lr, [sp, #-8]!
1226	ARM_CALL aeabi_cdcmple
1227	do_it	cc, e
1228	movcc	r0, #1	@ Less than.
1229	movcs	r0, #0	@ Equal to, greater than, or unordered.
1230	RETLDM
1231
1232	FUNC_END aeabi_dcmplt
1233
1234ARM_FUNC_START	aeabi_dcmple
1235
1236	str	lr, [sp, #-8]!
1237	ARM_CALL aeabi_cdcmple
1238	do_it	ls, e
1239	movls	r0, #1  @ Less than or equal to.
1240	movhi	r0, #0	@ Greater than or unordered.
1241	RETLDM
1242
1243	FUNC_END aeabi_dcmple
1244
1245ARM_FUNC_START	aeabi_dcmpge
1246
1247	str	lr, [sp, #-8]!
1248	ARM_CALL aeabi_cdrcmple
1249	do_it	ls, e
1250	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
1251	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
1252	RETLDM
1253
1254	FUNC_END aeabi_dcmpge
1255
1256ARM_FUNC_START	aeabi_dcmpgt
1257
1258	str	lr, [sp, #-8]!
1259	ARM_CALL aeabi_cdrcmple
1260	do_it	cc, e
1261	movcc	r0, #1	@ Operand 2 is less than operand 1.
1262	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
1263			@ or they are unordered.
1264	RETLDM
1265
1266	FUNC_END aeabi_dcmpgt
1267
1268#endif /* L_cmpdf2 */
1269
1270#ifdef L_arm_unorddf2
1271
1272ARM_FUNC_START unorddf2
1273ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1274
1275	mov	ip, xh, lsl #1
1276	mvns	ip, ip, asr #21
1277	bne	1f
1278	orrs	ip, xl, xh, lsl #12
1279	bne	3f			@ x is NAN
12801:	mov	ip, yh, lsl #1
1281	mvns	ip, ip, asr #21
1282	bne	2f
1283	orrs	ip, yl, yh, lsl #12
1284	bne	3f			@ y is NAN
12852:	mov	r0, #0			@ arguments are ordered.
1286	RET
1287
12883:	mov	r0, #1			@ arguments are unordered.
1289	RET
1290
1291	FUNC_END aeabi_dcmpun
1292	FUNC_END unorddf2
1293
1294#endif /* L_unorddf2 */
1295
1296#ifdef L_arm_fixdfsi
1297
1298ARM_FUNC_START fixdfsi
1299ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1300
1301	@ check exponent range.
1302	mov	r2, xh, lsl #1
1303	adds	r2, r2, #(1 << 21)
1304	bcs	2f			@ value is INF or NAN
1305	bpl	1f			@ value is too small
1306	mov	r3, #(0xfffffc00 + 31)
1307	subs	r2, r3, r2, asr #21
1308	bls	3f			@ value is too large
1309
1310	@ scale value
1311	mov	r3, xh, lsl #11
1312	orr	r3, r3, #0x80000000
1313	orr	r3, r3, xl, lsr #21
1314	tst	xh, #0x80000000		@ the sign bit
1315	shift1	lsr, r0, r3, r2
1316	do_it	ne
1317	rsbne	r0, r0, #0
1318	RET
1319
13201:	mov	r0, #0
1321	RET
1322
13232:	orrs	xl, xl, xh, lsl #12
1324	bne	4f			@ x is NAN.
13253:	ands	r0, xh, #0x80000000	@ the sign bit
1326	do_it	eq
1327	moveq	r0, #0x7fffffff		@ maximum signed positive si
1328	RET
1329
13304:	mov	r0, #0			@ How should we convert NAN?
1331	RET
1332
1333	FUNC_END aeabi_d2iz
1334	FUNC_END fixdfsi
1335
1336#endif /* L_fixdfsi */
1337
1338#ifdef L_arm_fixunsdfsi
1339
1340ARM_FUNC_START fixunsdfsi
1341ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1342
1343	@ check exponent range.
1344	movs	r2, xh, lsl #1
1345	bcs	1f			@ value is negative
1346	adds	r2, r2, #(1 << 21)
1347	bcs	2f			@ value is INF or NAN
1348	bpl	1f			@ value is too small
1349	mov	r3, #(0xfffffc00 + 31)
1350	subs	r2, r3, r2, asr #21
1351	bmi	3f			@ value is too large
1352
1353	@ scale value
1354	mov	r3, xh, lsl #11
1355	orr	r3, r3, #0x80000000
1356	orr	r3, r3, xl, lsr #21
1357	shift1	lsr, r0, r3, r2
1358	RET
1359
13601:	mov	r0, #0
1361	RET
1362
13632:	orrs	xl, xl, xh, lsl #12
1364	bne	4f			@ value is NAN.
13653:	mov	r0, #0xffffffff		@ maximum unsigned si
1366	RET
1367
13684:	mov	r0, #0			@ How should we convert NAN?
1369	RET
1370
1371	FUNC_END aeabi_d2uiz
1372	FUNC_END fixunsdfsi
1373
1374#endif /* L_fixunsdfsi */
1375
1376#ifdef L_arm_truncdfsf2
1377
1378ARM_FUNC_START truncdfsf2
1379ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1380
1381	@ check exponent range.
1382	mov	r2, xh, lsl #1
1383	subs	r3, r2, #((1023 - 127) << 21)
1384	do_it	cs, t
1385	COND(sub,s,cs)	ip, r3, #(1 << 21)
1386	COND(rsb,s,cs)	ip, ip, #(254 << 21)
1387	bls	2f			@ value is out of range
1388
13891:	@ shift and round mantissa
1390	and	ip, xh, #0x80000000
1391	mov	r2, xl, lsl #3
1392	orr	xl, ip, xl, lsr #29
1393	cmp	r2, #0x80000000
1394	adc	r0, xl, r3, lsl #2
1395	do_it	eq
1396	biceq	r0, r0, #1
1397	RET
1398
13992:	@ either overflow or underflow
1400	tst	xh, #0x40000000
1401	bne	3f			@ overflow
1402
1403	@ check if denormalized value is possible
1404	adds	r2, r3, #(23 << 21)
1405	do_it	lt, t
1406	andlt	r0, xh, #0x80000000	@ too small, return signed 0.
1407	RETc(lt)
1408
1409	@ denormalize value so we can resume with the code above afterwards.
1410	orr	xh, xh, #0x00100000
1411	mov	r2, r2, lsr #21
1412	rsb	r2, r2, #24
1413	rsb	ip, r2, #32
1414#if defined(__thumb2__)
1415	lsls	r3, xl, ip
1416#else
1417	movs	r3, xl, lsl ip
1418#endif
1419	shift1	lsr, xl, xl, r2
1420	do_it	ne
1421	orrne	xl, xl, #1		@ fold r3 for rounding considerations.
1422	mov	r3, xh, lsl #11
1423	mov	r3, r3, lsr #11
1424	shiftop orr xl xl r3 lsl ip ip
1425	shift1	lsr, r3, r3, r2
1426	mov	r3, r3, lsl #1
1427	b	1b
1428
14293:	@ chech for NAN
1430	mvns	r3, r2, asr #21
1431	bne	5f			@ simple overflow
1432	orrs	r3, xl, xh, lsl #12
1433	do_it	ne, tt
1434	movne	r0, #0x7f000000
1435	orrne	r0, r0, #0x00c00000
1436	RETc(ne)			@ return NAN
1437
14385:	@ return INF with sign
1439	and	r0, xh, #0x80000000
1440	orr	r0, r0, #0x7f000000
1441	orr	r0, r0, #0x00800000
1442	RET
1443
1444	FUNC_END aeabi_d2f
1445	FUNC_END truncdfsf2
1446
1447#endif /* L_truncdfsf2 */
1448