1/* ieee754-df.S double-precision floating point support for ARM
2
3   Copyright (C) 2003-2020 Free Software Foundation, Inc.
4   Contributed by Nicolas Pitre (nico@fluxnic.net)
5
6   This file is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 3, or (at your option) any
9   later version.
10
11   This file is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15
16   Under Section 7 of GPL version 3, you are granted additional
17   permissions described in the GCC Runtime Library Exception, version
18   3.1, as published by the Free Software Foundation.
19
20   You should have received a copy of the GNU General Public License and
21   a copy of the GCC Runtime Library Exception along with this program;
22   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23   <http://www.gnu.org/licenses/>.  */
24
25/*
26 * Notes:
27 *
28 * The goal of this code is to be as fast as possible.  This is
29 * not meant to be easy to understand for the casual reader.
30 * For slightly simpler code please see the single precision version
31 * of this file.
32 *
33 * Only the default rounding mode is intended for best performances.
34 * Exceptions aren't supported yet, but that can be added quite easily
35 * if necessary without impacting performances.
36 *
37 * In the CFI related comments, 'previousOffset' refers to the previous offset
38 * from sp used to compute the CFA.
39 */
40
41	.cfi_sections .debug_frame
42
43#ifndef __ARMEB__
44#define xl r0
45#define xh r1
46#define yl r2
47#define yh r3
48#else
49#define xh r0
50#define xl r1
51#define yh r2
52#define yl r3
53#endif
54
55
56#ifdef L_arm_negdf2
57
58ARM_FUNC_START negdf2
59ARM_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
74ARM_FUNC_START aeabi_drsub
75	CFI_START_FUNCTION
76
77	eor	xh, xh, #0x80000000	@ flip sign bit of first arg
78	b	1f
79
80ARM_FUNC_START subdf3
81ARM_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
88ARM_FUNC_START adddf3
89ARM_FUNC_ALIAS aeabi_dadd adddf3
90
911:  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
1241:
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
1451:
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
1571:
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.
167LSYM(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
1811:	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
1892:
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.
206LSYM(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.
227LSYM(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.
237LSYM(Lad_a):
238	movs	ip, ip, lsl #1
239	adcs	xl, xl, xl
240	adc	xh, xh, xh
241	subs	r4, r4, #1
242	do_it	hs
243	cmphs	xh, #0x00100000
244	bhs	LSYM(Lad_e)
245
246	@ No rounding necessary since ip will always be 0 at this point.
247LSYM(Lad_l):
248
249#if !defined (__ARM_FEATURE_CLZ)
250
251	teq	xh, #0
252	movne	r3, #20
253	moveq	r3, #52
254	moveq	xh, xl
255	moveq	xl, #0
256	mov	r2, xh
257	cmp	r2, #(1 << 16)
258	movhs	r2, r2, lsr #16
259	subhs	r3, r3, #16
260	cmp	r2, #(1 << 8)
261	movhs	r2, r2, lsr #8
262	subhs	r3, r3, #8
263	cmp	r2, #(1 << 4)
264	movhs	r2, r2, lsr #4
265	subhs	r3, r3, #4
266	cmp	r2, #(1 << 2)
267	subhs	r3, r3, #2
268	sublo	r3, r3, r2, lsr #1
269	sub	r3, r3, r2, lsr #3
270
271#else
272
273	teq	xh, #0
274	do_it	eq, t
275	moveq	xh, xl
276	moveq	xl, #0
277	clz	r3, xh
278	do_it	eq
279	addeq	r3, r3, #32
280	sub	r3, r3, #11
281
282#endif
283
284	@ determine how to shift the value.
285	subs	r2, r3, #32
286	bge	2f
287	adds	r2, r2, #12
288	ble	1f
289
290	@ shift value left 21 to 31 bits, or actually right 11 to 1 bits
291	@ since a register switch happened above.
292	add	ip, r2, #20
293	rsb	r2, r2, #12
294	shift1	lsl, xl, xh, ip
295	shift1	lsr, xh, xh, r2
296	b	3f
297
298	@ actually shift value left 1 to 20 bits, which might also represent
299	@ 32 to 52 bits if counting the register switch that happened earlier.
3001:	add	r2, r2, #20
3012:	do_it	le
302	rsble	ip, r2, #32
303	shift1	lsl, xh, xh, r2
304#if defined(__thumb2__)
305	lsr	ip, xl, ip
306	itt	le
307	orrle	xh, xh, ip
308	lslle	xl, xl, r2
309#else
310	orrle	xh, xh, xl, lsr ip
311	movle	xl, xl, lsl r2
312#endif
313
314	@ adjust exponent accordingly.
3153:	subs	r4, r4, r3
316	do_it	ge, tt
317	addge	xh, xh, r4, lsl #20
318	orrge	xh, xh, r5
319	RETLDM	"r4, r5" ge
320
321	@ Exponent too small, denormalize result.
322	@ Find out proper shift value.
323	mvn	r4, r4
324	subs	r4, r4, #31
325	bge	2f
326	adds	r4, r4, #12
327	bgt	1f
328
329	@ shift result right of 1 to 20 bits, sign is in r5.
330	add	r4, r4, #20
331	rsb	r2, r4, #32
332	shift1	lsr, xl, xl, r4
333	shiftop orr xl xl xh lsl r2 yh
334	shiftop orr xh r5 xh lsr r4 yh
335	RETLDM	"r4, r5"
336
337	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
338	@ a register switch from xh to xl.
3391:	rsb	r4, r4, #12
340	rsb	r2, r4, #32
341	shift1	lsr, xl, xl, r2
342	shiftop orr xl xl xh lsl r4 yh
343	mov	xh, r5
344	RETLDM	"r4, r5"
345
346	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
347	@ from xh to xl.
3482:	shift1	lsr, xl, xh, r4
349	mov	xh, r5
350	RETLDM	"r4, r5"
351
352	@ Adjust exponents for denormalized arguments.
353	@ Note that r4 must not remain equal to 0.
354LSYM(Lad_d):
355	teq	r4, #0
356	eor	yh, yh, #0x00100000
357	do_it	eq, te
358	eoreq	xh, xh, #0x00100000
359	addeq	r4, r4, #1
360	subne	r5, r5, #1
361	b	LSYM(Lad_x)
362
363
364LSYM(Lad_s):
365	mvns	ip, r4, asr #21
366	do_it	ne
367	COND(mvn,s,ne)	ip, r5, asr #21
368	beq	LSYM(Lad_i)
369
370	teq	r4, r5
371	do_it	eq
372	teqeq	xl, yl
373	beq	1f
374
375	@ Result is x + 0.0 = x or 0.0 + y = y.
376	orrs	ip, r4, xl
377	do_it	eq, t
378	moveq	xh, yh
379	moveq	xl, yl
380	RETLDM	"r4, r5"
381
3821:	teq	xh, yh
383
384	@ Result is x - x = 0.
385	do_it	ne, tt
386	movne	xh, #0
387	movne	xl, #0
388	RETLDM	"r4, r5" ne
389
390	@ Result is x + x = 2x.
391	movs	ip, r4, lsr #21
392	bne	2f
393	movs	xl, xl, lsl #1
394	adcs	xh, xh, xh
395	do_it	cs
396	orrcs	xh, xh, #0x80000000
397	RETLDM	"r4, r5"
3982:	adds	r4, r4, #(2 << 21)
399	do_it	cc, t
400	addcc	xh, xh, #(1 << 20)
401	RETLDM	"r4, r5" cc
402	and	r5, xh, #0x80000000
403
404	@ Overflow: return INF.
405LSYM(Lad_o):
406	orr	xh, r5, #0x7f000000
407	orr	xh, xh, #0x00f00000
408	mov	xl, #0
409	RETLDM	"r4, r5"
410
411	@ At least one of x or y is INF/NAN.
412	@   if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
413	@   if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
414	@   if either is NAN: return NAN
415	@   if opposite sign: return NAN
416	@   otherwise return xh-xl (which is INF or -INF)
417LSYM(Lad_i):
418	mvns	ip, r4, asr #21
419	do_it	ne, te
420	movne	xh, yh
421	movne	xl, yl
422	COND(mvn,s,eq)	ip, r5, asr #21
423	do_it	ne, t
424	movne	yh, xh
425	movne	yl, xl
426	orrs	r4, xl, xh, lsl #12
427	do_it	eq, te
428	COND(orr,s,eq)	r5, yl, yh, lsl #12
429	teqeq	xh, yh
430	orrne	xh, xh, #0x00080000	@ quiet NAN
431	RETLDM	"r4, r5"
432
433	CFI_END_FUNCTION
434	FUNC_END aeabi_dsub
435	FUNC_END subdf3
436	FUNC_END aeabi_dadd
437	FUNC_END adddf3
438
439ARM_FUNC_START floatunsidf
440ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
441	CFI_START_FUNCTION
442
443	teq	r0, #0
444	do_it	eq, t
445	moveq	r1, #0
446	RETc(eq)
447
448	do_push {r4, r5, lr}        @ sp -= 12
449	.cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
450	.cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
451	.cfi_rel_offset r5, 4
452	.cfi_rel_offset lr, 8
453
454	mov	r4, #0x400		@ initial exponent
455	add	r4, r4, #(52-1 - 1)
456	mov	r5, #0			@ sign bit is 0
457	.ifnc	xl, r0
458	mov	xl, r0
459	.endif
460	mov	xh, #0
461	b	LSYM(Lad_l)
462
463	CFI_END_FUNCTION
464	FUNC_END aeabi_ui2d
465	FUNC_END floatunsidf
466
467ARM_FUNC_START floatsidf
468ARM_FUNC_ALIAS aeabi_i2d floatsidf
469	CFI_START_FUNCTION
470
471	teq	r0, #0
472	do_it	eq, t
473	moveq	r1, #0
474	RETc(eq)
475
476	do_push {r4, r5, lr}        @ sp -= 12
477	.cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
478	.cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
479	.cfi_rel_offset r5, 4
480	.cfi_rel_offset lr, 8
481
482	mov	r4, #0x400		@ initial exponent
483	add	r4, r4, #(52-1 - 1)
484	ands	r5, r0, #0x80000000	@ sign bit in r5
485	do_it	mi
486	rsbmi	r0, r0, #0		@ absolute value
487	.ifnc	xl, r0
488	mov	xl, r0
489	.endif
490	mov	xh, #0
491	b	LSYM(Lad_l)
492
493	CFI_END_FUNCTION
494	FUNC_END aeabi_i2d
495	FUNC_END floatsidf
496
497ARM_FUNC_START extendsfdf2
498ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
499	CFI_START_FUNCTION
500
501	movs	r2, r0, lsl #1		@ toss sign bit
502	mov	xh, r2, asr #3		@ stretch exponent
503	mov	xh, xh, rrx		@ retrieve sign bit
504	mov	xl, r2, lsl #28		@ retrieve remaining bits
505	do_it	ne, ttt
506	COND(and,s,ne)	r3, r2, #0xff000000	@ isolate exponent
507	teqne	r3, #0xff000000		@ if not 0, check if INF or NAN
508	eorne	xh, xh, #0x38000000	@ fixup exponent otherwise.
509	RETc(ne)			@ and return it.
510
511	bics	r2, r2, #0xff000000	@ isolate mantissa
512	do_it	eq			@ if 0, that is ZERO or INF,
513	RETc(eq)			@ we are done already.
514
515	teq	r3, #0xff000000		@ check for NAN
516	do_it	eq, t
517	orreq	xh, xh, #0x00080000	@ change to quiet NAN
518	RETc(eq)			@ and return it.
519
520	@ value was denormalized.  We can normalize it now.
521	do_push	{r4, r5, lr}
522	.cfi_adjust_cfa_offset 12   @ CFA is now sp + previousOffset + 12
523	.cfi_rel_offset r4, 0       @ Registers are saved from sp + 0 to sp + 8.
524	.cfi_rel_offset r5, 4
525	.cfi_rel_offset lr, 8
526
527	mov	r4, #0x380		@ setup corresponding exponent
528	and	r5, xh, #0x80000000	@ move sign bit in r5
529	bic	xh, xh, #0x80000000
530	b	LSYM(Lad_l)
531
532	CFI_END_FUNCTION
533	FUNC_END aeabi_f2d
534	FUNC_END extendsfdf2
535
536ARM_FUNC_START floatundidf
537ARM_FUNC_ALIAS aeabi_ul2d floatundidf
538	CFI_START_FUNCTION
539	.cfi_remember_state        @ Save the current CFA state.
540
541	orrs	r2, r0, r1
542	do_it	eq
543	RETc(eq)
544
545	do_push {r4, r5, lr}       @ sp -= 12
546	.cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
547	.cfi_rel_offset r4, 0      @ Registers are saved from sp + 0 to sp + 8
548	.cfi_rel_offset r5, 4
549	.cfi_rel_offset lr, 8
550
551	mov	r5, #0
552	b	2f
553
554ARM_FUNC_START floatdidf
555ARM_FUNC_ALIAS aeabi_l2d floatdidf
556	.cfi_restore_state
557	@ Restore the CFI state we saved above. If we didn't do this then the
558	@ following instructions would have the CFI state that was set by the
559	@ offset adjustments made in floatundidf.
560
561	orrs	r2, r0, r1
562	do_it	eq
563	RETc(eq)
564
565	do_push {r4, r5, lr}       @ sp -= 12
566	.cfi_adjust_cfa_offset 12  @ CFA is now sp + previousOffset + 12
567	.cfi_rel_offset r4, 0      @ Registers are saved from sp to sp + 8
568	.cfi_rel_offset r5, 4
569	.cfi_rel_offset lr, 8
570
571	ands	r5, ah, #0x80000000	@ sign bit in r5
572	bpl	2f
573#if defined(__thumb2__)
574	negs	al, al
575	sbc	ah, ah, ah, lsl #1
576#else
577	rsbs	al, al, #0
578	rsc	ah, ah, #0
579#endif
5802:
581	mov	r4, #0x400		@ initial exponent
582	add	r4, r4, #(52-1 - 1)
583
584	@ If FP word order does not match integer word order, swap the words.
585	.ifnc	xh, ah
586	mov	ip, al
587	mov	xh, ah
588	mov	xl, ip
589	.endif
590
591	movs	ip, xh, lsr #22
592	beq	LSYM(Lad_p)
593
594	@ The value is too big.  Scale it down a bit...
595	mov	r2, #3
596	movs	ip, ip, lsr #3
597	do_it	ne
598	addne	r2, r2, #3
599	movs	ip, ip, lsr #3
600	do_it	ne
601	addne	r2, r2, #3
602	add	r2, r2, ip, lsr #3
603
604	rsb	r3, r2, #32
605	shift1	lsl, ip, xl, r3
606	shift1	lsr, xl, xl, r2
607	shiftop orr xl xl xh lsl r3 lr
608	shift1	lsr, xh, xh, r2
609	add	r4, r4, r2
610	b	LSYM(Lad_p)
611
612	CFI_END_FUNCTION
613	FUNC_END floatdidf
614	FUNC_END aeabi_l2d
615	FUNC_END floatundidf
616	FUNC_END aeabi_ul2d
617
618#endif /* L_addsubdf3 */
619
620#if defined(L_arm_muldf3) || defined(L_arm_muldivdf3)
621
622@ Define multiplication as weak in _arm_muldf3.o so that it can be overriden
623@ by the global definition in _arm_muldivdf3.o.  This allows a program only
624@ using multiplication to take the weak definition which does not contain the
625@ division code. Programs using only division or both division and
626@ multiplication will pull _arm_muldivdf3.o from which both the multiplication
627@ and division are taken thanks to the override.
628#ifdef L_arm_muldf3
629WEAK muldf3
630WEAK aeabi_dmul
631#endif
632
633ARM_FUNC_START muldf3
634ARM_FUNC_ALIAS aeabi_dmul muldf3
635	CFI_START_FUNCTION
636
637	do_push {r4, r5, r6, lr}    @ sp -= 16
638	.cfi_adjust_cfa_offset 16   @ CFA is now sp + previousOffset + 16
639	.cfi_rel_offset r4, 0       @ Registers are saved from sp to sp + 12.
640	.cfi_rel_offset r5, 4
641	.cfi_rel_offset r6, 8
642	.cfi_rel_offset lr, 12
643
644	@ Mask out exponents, trap any zero/denormal/INF/NAN.
645	mov	ip, #0xff
646	orr	ip, ip, #0x700
647	ands	r4, ip, xh, lsr #20
648	do_it	ne, tte
649	COND(and,s,ne)	r5, ip, yh, lsr #20
650	teqne	r4, ip
651	teqne	r5, ip
652	bleq	LSYM(Lml_s)
653
654	@ Add exponents together
655	add	r4, r4, r5
656
657	@ Determine final sign.
658	eor	r6, xh, yh
659
660	@ Convert mantissa to unsigned integer.
661	@ If power of two, branch to a separate path.
662	bic	xh, xh, ip, lsl #21
663	bic	yh, yh, ip, lsl #21
664	orrs	r5, xl, xh, lsl #12
665	do_it	ne
666	COND(orr,s,ne)	r5, yl, yh, lsl #12
667	orr	xh, xh, #0x00100000
668	orr	yh, yh, #0x00100000
669	beq	LSYM(Lml_1)
670
671	@ Here is the actual multiplication.
672	@ This code works on architecture versions >= 4
673	umull	ip, lr, xl, yl
674	mov	r5, #0
675	umlal	lr, r5, xh, yl
676	and	yl, r6, #0x80000000
677	umlal	lr, r5, xl, yh
678	mov	r6, #0
679	umlal	r5, r6, xh, yh
680
681	@ The LSBs in ip are only significant for the final rounding.
682	@ Fold them into lr.
683	teq	ip, #0
684	do_it	ne
685	orrne	lr, lr, #1
686
687	@ Adjust result upon the MSB position.
688	sub	r4, r4, #0xff
689	cmp	r6, #(1 << (20-11))
690	sbc	r4, r4, #0x300
691	bcs	1f
692	movs	lr, lr, lsl #1
693	adcs	r5, r5, r5
694	adc	r6, r6, r6
6951:
696	@ Shift to final position, add sign to result.
697	orr	xh, yl, r6, lsl #11
698	orr	xh, xh, r5, lsr #21
699	mov	xl, r5, lsl #11
700	orr	xl, xl, lr, lsr #21
701	mov	lr, lr, lsl #11
702
703	@ Check exponent range for under/overflow.
704	subs	ip, r4, #(254 - 1)
705	do_it	hi
706	cmphi	ip, #0x700
707	bhi	LSYM(Lml_u)
708
709	@ Round the result, merge final exponent.
710	cmp	lr, #0x80000000
711	do_it	eq
712	COND(mov,s,eq)	lr, xl, lsr #1
713	adcs	xl, xl, #0
714	adc	xh, xh, r4, lsl #20
715	RETLDM	"r4, r5, r6"
716
717	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
718LSYM(Lml_1):
719	and	r6, r6, #0x80000000
720	orr	xh, r6, xh
721	orr	xl, xl, yl
722	eor	xh, xh, yh
723	subs	r4, r4, ip, lsr #1
724	do_it	gt, tt
725	COND(rsb,s,gt)	r5, r4, ip
726	orrgt	xh, xh, r4, lsl #20
727	RETLDM	"r4, r5, r6" gt
728
729	@ Under/overflow: fix things up for the code below.
730	orr	xh, xh, #0x00100000
731	mov	lr, #0
732	subs	r4, r4, #1
733LSYM(Lml_u):
734	@ Overflow?
735	bgt	LSYM(Lml_o)
736
737	@ Check if denormalized result is possible, otherwise return signed 0.
738	cmn	r4, #(53 + 1)
739	do_it	le, tt
740	movle	xl, #0
741	bicle	xh, xh, #0x7fffffff
742	RETLDM	"r4, r5, r6" le
743
744	@ Find out proper shift value.
745	rsb	r4, r4, #0
746	subs	r4, r4, #32
747	bge	2f
748	adds	r4, r4, #12
749	bgt	1f
750
751	@ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
752	add	r4, r4, #20
753	rsb	r5, r4, #32
754	shift1	lsl, r3, xl, r5
755	shift1	lsr, xl, xl, r4
756	shiftop orr xl xl xh lsl r5 r2
757	and	r2, xh, #0x80000000
758	bic	xh, xh, #0x80000000
759	adds	xl, xl, r3, lsr #31
760	shiftop adc xh r2 xh lsr r4 r6
761	orrs	lr, lr, r3, lsl #1
762	do_it	eq
763	biceq	xl, xl, r3, lsr #31
764	RETLDM	"r4, r5, r6"
765
766	@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
767	@ a register switch from xh to xl. Then round.
7681:	rsb	r4, r4, #12
769	rsb	r5, r4, #32
770	shift1	lsl, r3, xl, r4
771	shift1	lsr, xl, xl, r5
772	shiftop orr xl xl xh lsl r4 r2
773	bic	xh, xh, #0x7fffffff
774	adds	xl, xl, r3, lsr #31
775	adc	xh, xh, #0
776	orrs	lr, lr, r3, lsl #1
777	do_it	eq
778	biceq	xl, xl, r3, lsr #31
779	RETLDM	"r4, r5, r6"
780
781	@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
782	@ from xh to xl.  Leftover bits are in r3-r6-lr for rounding.
7832:	rsb	r5, r4, #32
784	shiftop orr lr lr xl lsl r5 r2
785	shift1	lsr, r3, xl, r4
786	shiftop orr r3 r3 xh lsl r5 r2
787	shift1	lsr, xl, xh, r4
788	bic	xh, xh, #0x7fffffff
789	shiftop bic xl xl xh lsr r4 r2
790	add	xl, xl, r3, lsr #31
791	orrs	lr, lr, r3, lsl #1
792	do_it	eq
793	biceq	xl, xl, r3, lsr #31
794	RETLDM	"r4, r5, r6"
795
796	@ One or both arguments are denormalized.
797	@ Scale them leftwards and preserve sign bit.
798LSYM(Lml_d):
799	teq	r4, #0
800	bne	2f
801	and	r6, xh, #0x80000000
8021:	movs	xl, xl, lsl #1
803	adc	xh, xh, xh
804	tst	xh, #0x00100000
805	do_it	eq
806	subeq	r4, r4, #1
807	beq	1b
808	orr	xh, xh, r6
809	teq	r5, #0
810	do_it	ne
811	RETc(ne)
8122:	and	r6, yh, #0x80000000
8133:	movs	yl, yl, lsl #1
814	adc	yh, yh, yh
815	tst	yh, #0x00100000
816	do_it	eq
817	subeq	r5, r5, #1
818	beq	3b
819	orr	yh, yh, r6
820	RET
821
822LSYM(Lml_s):
823	@ Isolate the INF and NAN cases away
824	teq	r4, ip
825	and	r5, ip, yh, lsr #20
826	do_it	ne
827	teqne	r5, ip
828	beq	1f
829
830	@ Here, one or more arguments are either denormalized or zero.
831	orrs	r6, xl, xh, lsl #1
832	do_it	ne
833	COND(orr,s,ne)	r6, yl, yh, lsl #1
834	bne	LSYM(Lml_d)
835
836	@ Result is 0, but determine sign anyway.
837LSYM(Lml_z):
838	eor	xh, xh, yh
839	and	xh, xh, #0x80000000
840	mov	xl, #0
841	RETLDM	"r4, r5, r6"
842
8431:	@ One or both args are INF or NAN.
844	orrs	r6, xl, xh, lsl #1
845	do_it	eq, te
846	moveq	xl, yl
847	moveq	xh, yh
848	COND(orr,s,ne)	r6, yl, yh, lsl #1
849	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
850	teq	r4, ip
851	bne	1f
852	orrs	r6, xl, xh, lsl #12
853	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
8541:	teq	r5, ip
855	bne	LSYM(Lml_i)
856	orrs	r6, yl, yh, lsl #12
857	do_it	ne, t
858	movne	xl, yl
859	movne	xh, yh
860	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
861
862	@ Result is INF, but we need to determine its sign.
863LSYM(Lml_i):
864	eor	xh, xh, yh
865
866	@ Overflow: return INF (sign already in xh).
867LSYM(Lml_o):
868	and	xh, xh, #0x80000000
869	orr	xh, xh, #0x7f000000
870	orr	xh, xh, #0x00f00000
871	mov	xl, #0
872	RETLDM	"r4, r5, r6"
873
874	@ Return a quiet NAN.
875LSYM(Lml_n):
876	orr	xh, xh, #0x7f000000
877	orr	xh, xh, #0x00f80000
878	RETLDM	"r4, r5, r6"
879
880	CFI_END_FUNCTION
881	FUNC_END aeabi_dmul
882	FUNC_END muldf3
883
884#ifdef L_arm_muldivdf3
885
886ARM_FUNC_START divdf3
887ARM_FUNC_ALIAS aeabi_ddiv divdf3
888	CFI_START_FUNCTION
889
890	do_push	{r4, r5, r6, lr}
891	.cfi_adjust_cfa_offset 16
892	.cfi_rel_offset r4, 0
893	.cfi_rel_offset r5, 4
894	.cfi_rel_offset r6, 8
895	.cfi_rel_offset lr, 12
896
897	@ Mask out exponents, trap any zero/denormal/INF/NAN.
898	mov	ip, #0xff
899	orr	ip, ip, #0x700
900	ands	r4, ip, xh, lsr #20
901	do_it	ne, tte
902	COND(and,s,ne)	r5, ip, yh, lsr #20
903	teqne	r4, ip
904	teqne	r5, ip
905	bleq	LSYM(Ldv_s)
906
907	@ Subtract divisor exponent from dividend''s.
908	sub	r4, r4, r5
909
910	@ Preserve final sign into lr.
911	eor	lr, xh, yh
912
913	@ Convert mantissa to unsigned integer.
914	@ Dividend -> r5-r6, divisor -> yh-yl.
915	orrs	r5, yl, yh, lsl #12
916	mov	xh, xh, lsl #12
917	beq	LSYM(Ldv_1)
918	mov	yh, yh, lsl #12
919	mov	r5, #0x10000000
920	orr	yh, r5, yh, lsr #4
921	orr	yh, yh, yl, lsr #24
922	mov	yl, yl, lsl #8
923	orr	r5, r5, xh, lsr #4
924	orr	r5, r5, xl, lsr #24
925	mov	r6, xl, lsl #8
926
927	@ Initialize xh with final sign bit.
928	and	xh, lr, #0x80000000
929
930	@ Ensure result will land to known bit position.
931	@ Apply exponent bias accordingly.
932	cmp	r5, yh
933	do_it	eq
934	cmpeq	r6, yl
935	adc	r4, r4, #(255 - 2)
936	add	r4, r4, #0x300
937	bcs	1f
938	movs	yh, yh, lsr #1
939	mov	yl, yl, rrx
9401:
941	@ Perform first subtraction to align result to a nibble.
942	subs	r6, r6, yl
943	sbc	r5, r5, yh
944	movs	yh, yh, lsr #1
945	mov	yl, yl, rrx
946	mov	xl, #0x00100000
947	mov	ip, #0x00080000
948
949	@ The actual division loop.
9501:	subs	lr, r6, yl
951	sbcs	lr, r5, yh
952	do_it	cs, tt
953	subcs	r6, r6, yl
954	movcs	r5, lr
955	orrcs	xl, xl, ip
956	movs	yh, yh, lsr #1
957	mov	yl, yl, rrx
958	subs	lr, r6, yl
959	sbcs	lr, r5, yh
960	do_it	cs, tt
961	subcs	r6, r6, yl
962	movcs	r5, lr
963	orrcs	xl, xl, ip, lsr #1
964	movs	yh, yh, lsr #1
965	mov	yl, yl, rrx
966	subs	lr, r6, yl
967	sbcs	lr, r5, yh
968	do_it	cs, tt
969	subcs	r6, r6, yl
970	movcs	r5, lr
971	orrcs	xl, xl, ip, lsr #2
972	movs	yh, yh, lsr #1
973	mov	yl, yl, rrx
974	subs	lr, r6, yl
975	sbcs	lr, r5, yh
976	do_it	cs, tt
977	subcs	r6, r6, yl
978	movcs	r5, lr
979	orrcs	xl, xl, ip, lsr #3
980
981	orrs	lr, r5, r6
982	beq	2f
983	mov	r5, r5, lsl #4
984	orr	r5, r5, r6, lsr #28
985	mov	r6, r6, lsl #4
986	mov	yh, yh, lsl #3
987	orr	yh, yh, yl, lsr #29
988	mov	yl, yl, lsl #3
989	movs	ip, ip, lsr #4
990	bne	1b
991
992	@ We are done with a word of the result.
993	@ Loop again for the low word if this pass was for the high word.
994	tst	xh, #0x00100000
995	bne	3f
996	orr	xh, xh, xl
997	mov	xl, #0
998	mov	ip, #0x80000000
999	b	1b
10002:
1001	@ Be sure result starts in the high word.
1002	tst	xh, #0x00100000
1003	do_it	eq, t
1004	orreq	xh, xh, xl
1005	moveq	xl, #0
10063:
1007	@ Check exponent range for under/overflow.
1008	subs	ip, r4, #(254 - 1)
1009	do_it	hi
1010	cmphi	ip, #0x700
1011	bhi	LSYM(Lml_u)
1012
1013	@ Round the result, merge final exponent.
1014	subs	ip, r5, yh
1015	do_it	eq, t
1016	COND(sub,s,eq)	ip, r6, yl
1017	COND(mov,s,eq)	ip, xl, lsr #1
1018	adcs	xl, xl, #0
1019	adc	xh, xh, r4, lsl #20
1020	RETLDM	"r4, r5, r6"
1021
1022	@ Division by 0x1p*: shortcut a lot of code.
1023LSYM(Ldv_1):
1024	and	lr, lr, #0x80000000
1025	orr	xh, lr, xh, lsr #12
1026	adds	r4, r4, ip, lsr #1
1027	do_it	gt, tt
1028	COND(rsb,s,gt)	r5, r4, ip
1029	orrgt	xh, xh, r4, lsl #20
1030	RETLDM	"r4, r5, r6" gt
1031
1032	orr	xh, xh, #0x00100000
1033	mov	lr, #0
1034	subs	r4, r4, #1
1035	b	LSYM(Lml_u)
1036
1037	@ Result mightt need to be denormalized: put remainder bits
1038	@ in lr for rounding considerations.
1039LSYM(Ldv_u):
1040	orr	lr, r5, r6
1041	b	LSYM(Lml_u)
1042
1043	@ One or both arguments is either INF, NAN or zero.
1044LSYM(Ldv_s):
1045	and	r5, ip, yh, lsr #20
1046	teq	r4, ip
1047	do_it	eq
1048	teqeq	r5, ip
1049	beq	LSYM(Lml_n)		@ INF/NAN / INF/NAN -> NAN
1050	teq	r4, ip
1051	bne	1f
1052	orrs	r4, xl, xh, lsl #12
1053	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
1054	teq	r5, ip
1055	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
1056	mov	xl, yl
1057	mov	xh, yh
1058	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
10591:	teq	r5, ip
1060	bne	2f
1061	orrs	r5, yl, yh, lsl #12
1062	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
1063	mov	xl, yl
1064	mov	xh, yh
1065	b	LSYM(Lml_n)		@ <anything> / NAN -> NAN
10662:	@ If both are nonzero, we need to normalize and resume above.
1067	orrs	r6, xl, xh, lsl #1
1068	do_it	ne
1069	COND(orr,s,ne)	r6, yl, yh, lsl #1
1070	bne	LSYM(Lml_d)
1071	@ One or both arguments are 0.
1072	orrs	r4, xl, xh, lsl #1
1073	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
1074	orrs	r5, yl, yh, lsl #1
1075	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
1076	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
1077
1078	CFI_END_FUNCTION
1079	FUNC_END aeabi_ddiv
1080	FUNC_END divdf3
1081
1082#endif /* L_muldivdf3 */
1083#endif /* L_arm_muldf3 || L_arm_muldivdf3 */
1084
1085#ifdef L_arm_cmpdf2
1086
1087@ Note: only r0 (return value) and ip are clobbered here.
1088
1089ARM_FUNC_START gtdf2
1090ARM_FUNC_ALIAS gedf2 gtdf2
1091	CFI_START_FUNCTION
1092	mov	ip, #-1
1093	b	1f
1094
1095ARM_FUNC_START ltdf2
1096ARM_FUNC_ALIAS ledf2 ltdf2
1097	mov	ip, #1
1098	b	1f
1099
1100ARM_FUNC_START cmpdf2
1101ARM_FUNC_ALIAS nedf2 cmpdf2
1102ARM_FUNC_ALIAS eqdf2 cmpdf2
1103	mov	ip, #1			@ how should we specify unordered here?
1104
11051:	str	ip, [sp, #-4]!
1106	.cfi_adjust_cfa_offset 4        @ CFA is now sp + previousOffset + 4.
1107	@ We're not adding CFI for ip as it's pushed into the stack
1108	@ only because it may be popped off later as a return value
1109	@ (i.e. we're not preserving it anyways).
1110
1111	@ Trap any INF/NAN first.
1112	mov	ip, xh, lsl #1
1113	mvns	ip, ip, asr #21
1114	mov	ip, yh, lsl #1
1115	do_it	ne
1116	COND(mvn,s,ne)	ip, ip, asr #21
1117	beq	3f
1118	.cfi_remember_state
1119	@ Save the current CFI state.  This is done because the branch
1120	@ is conditional, and if we don't take it we'll issue a
1121	@ .cfi_adjust_cfa_offset and return.  If we do take it,
1122	@ however, the .cfi_adjust_cfa_offset from the non-branch code
1123	@ will affect the branch code as well.  To avoid this we'll
1124	@ restore the current state before executing the branch code.
1125
1126	@ Test for equality.  Note that 0.0 is equal to -0.0.
11272:	add	sp, sp, #4
1128	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
1129
1130	orrs	ip, xl, xh, lsl #1	@ if x == 0.0 or -0.0
1131	do_it	eq, e
1132	COND(orr,s,eq)	ip, yl, yh, lsl #1	@ and y == 0.0 or -0.0
1133	teqne	xh, yh			@ or xh == yh
1134	do_it	eq, tt
1135	teqeq	xl, yl			@ and xl == yl
1136	moveq	r0, #0			@ then equal.
1137	RETc(eq)
1138
1139	@ Clear C flag
1140	cmn	r0, #0
1141
1142	@ Compare sign,
1143	teq	xh, yh
1144
1145	@ Compare values if same sign
1146	do_it	pl
1147	cmppl	xh, yh
1148	do_it	eq
1149	cmpeq	xl, yl
1150
1151	@ Result:
1152	do_it	cs, e
1153	movcs	r0, yh, asr #31
1154	mvncc	r0, yh, asr #31
1155	orr	r0, r0, #1
1156	RET
1157
11583:  @ Look for a NAN.
1159
1160	@ Restore the previous CFI state (i.e. keep the CFI state as it was
1161	@ before the branch).
1162	.cfi_restore_state
1163
1164	mov ip, xh, lsl #1
1165	mvns	ip, ip, asr #21
1166	bne	4f
1167	orrs	ip, xl, xh, lsl #12
1168	bne	5f			@ x is NAN
11694:	mov	ip, yh, lsl #1
1170	mvns	ip, ip, asr #21
1171	bne	2b
1172	orrs	ip, yl, yh, lsl #12
1173	beq	2b			@ y is not NAN
1174
11755:	ldr	r0, [sp], #4		@ unordered return code
1176	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
1177
1178	RET
1179
1180	CFI_END_FUNCTION
1181	FUNC_END gedf2
1182	FUNC_END gtdf2
1183	FUNC_END ledf2
1184	FUNC_END ltdf2
1185	FUNC_END nedf2
1186	FUNC_END eqdf2
1187	FUNC_END cmpdf2
1188
1189ARM_FUNC_START aeabi_cdrcmple
1190	CFI_START_FUNCTION
1191
1192	mov	ip, r0
1193	mov	r0, r2
1194	mov	r2, ip
1195	mov	ip, r1
1196	mov	r1, r3
1197	mov	r3, ip
1198	b	6f
1199
1200ARM_FUNC_START aeabi_cdcmpeq
1201ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1202
1203	@ The status-returning routines are required to preserve all
1204	@ registers except ip, lr, and cpsr.
12056:	do_push	{r0, lr}
1206	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8.
1207	.cfi_rel_offset r0, 0     @ Previous r0 is saved at sp.
1208	.cfi_rel_offset lr, 4     @ Previous lr is saved at sp + 4.
1209
1210	ARM_CALL cmpdf2
1211	@ Set the Z flag correctly, and the C flag unconditionally.
1212	cmp	r0, #0
1213	@ Clear the C flag if the return value was -1, indicating
1214	@ that the first operand was smaller than the second.
1215	do_it	mi
1216	cmnmi	r0, #0
1217
1218	RETLDM	"r0"
1219
1220	CFI_END_FUNCTION
1221	FUNC_END aeabi_cdcmple
1222	FUNC_END aeabi_cdcmpeq
1223	FUNC_END aeabi_cdrcmple
1224
1225ARM_FUNC_START	aeabi_dcmpeq
1226	CFI_START_FUNCTION
1227
1228	str lr, [sp, #-8]!        @ sp -= 8
1229	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1230	.cfi_rel_offset lr, 0     @ lr is at sp
1231
1232	ARM_CALL aeabi_cdcmple
1233	do_it	eq, e
1234	moveq	r0, #1	@ Equal to.
1235	movne	r0, #0	@ Less than, greater than, or unordered.
1236
1237	RETLDM
1238
1239	CFI_END_FUNCTION
1240	FUNC_END aeabi_dcmpeq
1241
1242ARM_FUNC_START	aeabi_dcmplt
1243	CFI_START_FUNCTION
1244
1245	str lr, [sp, #-8]!        @ sp -= 8
1246	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1247	.cfi_rel_offset lr, 0     @ lr is at sp
1248
1249	ARM_CALL aeabi_cdcmple
1250	do_it	cc, e
1251	movcc	r0, #1	@ Less than.
1252	movcs	r0, #0	@ Equal to, greater than, or unordered.
1253	RETLDM
1254
1255	CFI_END_FUNCTION
1256	FUNC_END aeabi_dcmplt
1257
1258ARM_FUNC_START	aeabi_dcmple
1259	CFI_START_FUNCTION
1260
1261	str lr, [sp, #-8]!        @ sp -= 8
1262	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1263	.cfi_rel_offset lr, 0     @ lr is at sp
1264
1265	ARM_CALL aeabi_cdcmple
1266	do_it	ls, e
1267	movls	r0, #1  @ Less than or equal to.
1268	movhi	r0, #0	@ Greater than or unordered.
1269	RETLDM
1270
1271	CFI_END_FUNCTION
1272	FUNC_END aeabi_dcmple
1273
1274ARM_FUNC_START	aeabi_dcmpge
1275	CFI_START_FUNCTION
1276
1277	str lr, [sp, #-8]!        @ sp -= 8
1278	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1279	.cfi_rel_offset lr, 0     @ lr is at sp
1280
1281	ARM_CALL aeabi_cdrcmple
1282	do_it	ls, e
1283	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
1284	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
1285	RETLDM
1286
1287	CFI_END_FUNCTION
1288	FUNC_END aeabi_dcmpge
1289
1290ARM_FUNC_START	aeabi_dcmpgt
1291	CFI_START_FUNCTION
1292
1293	str lr, [sp, #-8]!        @ sp -= 8
1294	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
1295	.cfi_rel_offset lr, 0     @ lr is at sp
1296
1297	ARM_CALL aeabi_cdrcmple
1298	do_it	cc, e
1299	movcc	r0, #1	@ Operand 2 is less than operand 1.
1300	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
1301			@ or they are unordered.
1302	RETLDM
1303
1304	CFI_END_FUNCTION
1305	FUNC_END aeabi_dcmpgt
1306
1307#endif /* L_cmpdf2 */
1308
1309#ifdef L_arm_unorddf2
1310
1311ARM_FUNC_START unorddf2
1312ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1313	.cfi_startproc
1314
1315	mov	ip, xh, lsl #1
1316	mvns	ip, ip, asr #21
1317	bne	1f
1318	orrs	ip, xl, xh, lsl #12
1319	bne	3f			@ x is NAN
13201:	mov	ip, yh, lsl #1
1321	mvns	ip, ip, asr #21
1322	bne	2f
1323	orrs	ip, yl, yh, lsl #12
1324	bne	3f			@ y is NAN
13252:	mov	r0, #0			@ arguments are ordered.
1326	RET
1327
13283:	mov	r0, #1			@ arguments are unordered.
1329	RET
1330
1331	.cfi_endproc
1332	FUNC_END aeabi_dcmpun
1333	FUNC_END unorddf2
1334
1335#endif /* L_unorddf2 */
1336
1337#ifdef L_arm_fixdfsi
1338
1339ARM_FUNC_START fixdfsi
1340ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1341	CFI_START_FUNCTION
1342
1343	@ check exponent range.
1344	mov	r2, xh, lsl #1
1345	adds	r2, r2, #(1 << 21)
1346	bcs	2f			@ value is INF or NAN
1347	bpl	1f			@ value is too small
1348	mov	r3, #(0xfffffc00 + 31)
1349	subs	r2, r3, r2, asr #21
1350	bls	3f			@ value is too large
1351
1352	@ scale value
1353	mov	r3, xh, lsl #11
1354	orr	r3, r3, #0x80000000
1355	orr	r3, r3, xl, lsr #21
1356	tst	xh, #0x80000000		@ the sign bit
1357	shift1	lsr, r0, r3, r2
1358	do_it	ne
1359	rsbne	r0, r0, #0
1360	RET
1361
13621:	mov	r0, #0
1363	RET
1364
13652:	orrs	xl, xl, xh, lsl #12
1366	bne	4f			@ x is NAN.
13673:	ands	r0, xh, #0x80000000	@ the sign bit
1368	do_it	eq
1369	moveq	r0, #0x7fffffff		@ maximum signed positive si
1370	RET
1371
13724:	mov	r0, #0			@ How should we convert NAN?
1373	RET
1374
1375	CFI_END_FUNCTION
1376	FUNC_END aeabi_d2iz
1377	FUNC_END fixdfsi
1378
1379#endif /* L_fixdfsi */
1380
1381#ifdef L_arm_fixunsdfsi
1382
1383ARM_FUNC_START fixunsdfsi
1384ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1385	CFI_START_FUNCTION
1386
1387	@ check exponent range.
1388	movs	r2, xh, lsl #1
1389	bcs	1f			@ value is negative
1390	adds	r2, r2, #(1 << 21)
1391	bcs	2f			@ value is INF or NAN
1392	bpl	1f			@ value is too small
1393	mov	r3, #(0xfffffc00 + 31)
1394	subs	r2, r3, r2, asr #21
1395	bmi	3f			@ value is too large
1396
1397	@ scale value
1398	mov	r3, xh, lsl #11
1399	orr	r3, r3, #0x80000000
1400	orr	r3, r3, xl, lsr #21
1401	shift1	lsr, r0, r3, r2
1402	RET
1403
14041:	mov	r0, #0
1405	RET
1406
14072:	orrs	xl, xl, xh, lsl #12
1408	bne	4f			@ value is NAN.
14093:	mov	r0, #0xffffffff		@ maximum unsigned si
1410	RET
1411
14124:	mov	r0, #0			@ How should we convert NAN?
1413	RET
1414
1415	CFI_END_FUNCTION
1416	FUNC_END aeabi_d2uiz
1417	FUNC_END fixunsdfsi
1418
1419#endif /* L_fixunsdfsi */
1420
1421#ifdef L_arm_truncdfsf2
1422
1423ARM_FUNC_START truncdfsf2
1424ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1425	CFI_START_FUNCTION
1426
1427	@ check exponent range.
1428	mov	r2, xh, lsl #1
1429	subs	r3, r2, #((1023 - 127) << 21)
1430	do_it	cs, t
1431	COND(sub,s,cs)	ip, r3, #(1 << 21)
1432	COND(rsb,s,cs)	ip, ip, #(254 << 21)
1433	bls	2f			@ value is out of range
1434
14351:	@ shift and round mantissa
1436	and	ip, xh, #0x80000000
1437	mov	r2, xl, lsl #3
1438	orr	xl, ip, xl, lsr #29
1439	cmp	r2, #0x80000000
1440	adc	r0, xl, r3, lsl #2
1441	do_it	eq
1442	biceq	r0, r0, #1
1443	RET
1444
14452:	@ either overflow or underflow
1446	tst	xh, #0x40000000
1447	bne	3f			@ overflow
1448
1449	@ check if denormalized value is possible
1450	adds	r2, r3, #(23 << 21)
1451	do_it	lt, t
1452	andlt	r0, xh, #0x80000000	@ too small, return signed 0.
1453	RETc(lt)
1454
1455	@ denormalize value so we can resume with the code above afterwards.
1456	orr	xh, xh, #0x00100000
1457	mov	r2, r2, lsr #21
1458	rsb	r2, r2, #24
1459	rsb	ip, r2, #32
1460#if defined(__thumb2__)
1461	lsls	r3, xl, ip
1462#else
1463	movs	r3, xl, lsl ip
1464#endif
1465	shift1	lsr, xl, xl, r2
1466	do_it	ne
1467	orrne	xl, xl, #1		@ fold r3 for rounding considerations.
1468	mov	r3, xh, lsl #11
1469	mov	r3, r3, lsr #11
1470	shiftop orr xl xl r3 lsl ip ip
1471	shift1	lsr, r3, r3, r2
1472	mov	r3, r3, lsl #1
1473	b	1b
1474
14753:	@ chech for NAN
1476	mvns	r3, r2, asr #21
1477	bne	5f			@ simple overflow
1478	orrs	r3, xl, xh, lsl #12
1479	do_it	ne, tt
1480	movne	r0, #0x7f000000
1481	orrne	r0, r0, #0x00c00000
1482	RETc(ne)			@ return NAN
1483
14845:	@ return INF with sign
1485	and	r0, xh, #0x80000000
1486	orr	r0, r0, #0x7f000000
1487	orr	r0, r0, #0x00800000
1488	RET
1489
1490	CFI_END_FUNCTION
1491	FUNC_END aeabi_d2f
1492	FUNC_END truncdfsf2
1493
1494#endif /* L_truncdfsf2 */
1495