1/* ieee754-sf.S single-precision floating point support for ARM
2
3   Copyright (C) 2003-2015 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 *
31 * Only the default rounding mode is intended for best performances.
32 * Exceptions aren't supported yet, but that can be added quite easily
33 * if necessary without impacting performances.
34 */
35
36#ifdef L_arm_negsf2
37
38ARM_FUNC_START negsf2
39ARM_FUNC_ALIAS aeabi_fneg negsf2
40
41	eor	r0, r0, #0x80000000	@ flip sign bit
42	RET
43
44	FUNC_END aeabi_fneg
45	FUNC_END negsf2
46
47#endif
48
49#ifdef L_arm_addsubsf3
50
51ARM_FUNC_START aeabi_frsub
52
53	eor	r0, r0, #0x80000000	@ flip sign bit of first arg
54	b	1f
55
56ARM_FUNC_START subsf3
57ARM_FUNC_ALIAS aeabi_fsub subsf3
58
59	eor	r1, r1, #0x80000000	@ flip sign bit of second arg
60#if defined(__INTERWORKING_STUBS__)
61	b	1f			@ Skip Thumb-code prologue
62#endif
63
64ARM_FUNC_START addsf3
65ARM_FUNC_ALIAS aeabi_fadd addsf3
66
671:	@ Look for zeroes, equal values, INF, or NAN.
68	movs	r2, r0, lsl #1
69	do_it	ne, ttt
70	COND(mov,s,ne)	r3, r1, lsl #1
71	teqne	r2, r3
72	COND(mvn,s,ne)	ip, r2, asr #24
73	COND(mvn,s,ne)	ip, r3, asr #24
74	beq	LSYM(Lad_s)
75
76	@ Compute exponent difference.  Make largest exponent in r2,
77	@ corresponding arg in r0, and positive exponent difference in r3.
78	mov	r2, r2, lsr #24
79	rsbs	r3, r2, r3, lsr #24
80	do_it	gt, ttt
81	addgt	r2, r2, r3
82	eorgt	r1, r0, r1
83	eorgt	r0, r1, r0
84	eorgt	r1, r0, r1
85	do_it	lt
86	rsblt	r3, r3, #0
87
88	@ If exponent difference is too large, return largest argument
89	@ already in r0.  We need up to 25 bit to handle proper rounding
90	@ of 0x1p25 - 1.1.
91	cmp	r3, #25
92	do_it	hi
93	RETc(hi)
94
95	@ Convert mantissa to signed integer.
96	tst	r0, #0x80000000
97	orr	r0, r0, #0x00800000
98	bic	r0, r0, #0xff000000
99	do_it	ne
100	rsbne	r0, r0, #0
101	tst	r1, #0x80000000
102	orr	r1, r1, #0x00800000
103	bic	r1, r1, #0xff000000
104	do_it	ne
105	rsbne	r1, r1, #0
106
107	@ If exponent == difference, one or both args were denormalized.
108	@ Since this is not common case, rescale them off line.
109	teq	r2, r3
110	beq	LSYM(Lad_d)
111LSYM(Lad_x):
112
113	@ Compensate for the exponent overlapping the mantissa MSB added later
114	sub	r2, r2, #1
115
116	@ Shift and add second arg to first arg in r0.
117	@ Keep leftover bits into r1.
118	shiftop adds r0 r0 r1 asr r3 ip
119	rsb	r3, r3, #32
120	shift1	lsl, r1, r1, r3
121
122	@ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
123	and	r3, r0, #0x80000000
124	bpl	LSYM(Lad_p)
125#if defined(__thumb2__)
126	negs	r1, r1
127	sbc	r0, r0, r0, lsl #1
128#else
129	rsbs	r1, r1, #0
130	rsc	r0, r0, #0
131#endif
132
133	@ Determine how to normalize the result.
134LSYM(Lad_p):
135	cmp	r0, #0x00800000
136	bcc	LSYM(Lad_a)
137	cmp	r0, #0x01000000
138	bcc	LSYM(Lad_e)
139
140	@ Result needs to be shifted right.
141	movs	r0, r0, lsr #1
142	mov	r1, r1, rrx
143	add	r2, r2, #1
144
145	@ Make sure we did not bust our exponent.
146	cmp	r2, #254
147	bhs	LSYM(Lad_o)
148
149	@ Our result is now properly aligned into r0, remaining bits in r1.
150	@ Pack final result together.
151	@ Round with MSB of r1. If halfway between two numbers, round towards
152	@ LSB of r0 = 0.
153LSYM(Lad_e):
154	cmp	r1, #0x80000000
155	adc	r0, r0, r2, lsl #23
156	do_it	eq
157	biceq	r0, r0, #1
158	orr	r0, r0, r3
159	RET
160
161	@ Result must be shifted left and exponent adjusted.
162LSYM(Lad_a):
163	movs	r1, r1, lsl #1
164	adc	r0, r0, r0
165	tst	r0, #0x00800000
166	sub	r2, r2, #1
167	bne	LSYM(Lad_e)
168
169	@ No rounding necessary since r1 will always be 0 at this point.
170LSYM(Lad_l):
171
172#if __ARM_ARCH__ < 5
173
174	movs	ip, r0, lsr #12
175	moveq	r0, r0, lsl #12
176	subeq	r2, r2, #12
177	tst	r0, #0x00ff0000
178	moveq	r0, r0, lsl #8
179	subeq	r2, r2, #8
180	tst	r0, #0x00f00000
181	moveq	r0, r0, lsl #4
182	subeq	r2, r2, #4
183	tst	r0, #0x00c00000
184	moveq	r0, r0, lsl #2
185	subeq	r2, r2, #2
186	cmp	r0, #0x00800000
187	movcc	r0, r0, lsl #1
188	sbcs	r2, r2, #0
189
190#else
191
192	clz	ip, r0
193	sub	ip, ip, #8
194	subs	r2, r2, ip
195	shift1	lsl, r0, r0, ip
196
197#endif
198
199	@ Final result with sign
200	@ If exponent negative, denormalize result.
201	do_it	ge, et
202	addge	r0, r0, r2, lsl #23
203	rsblt	r2, r2, #0
204	orrge	r0, r0, r3
205#if defined(__thumb2__)
206	do_it	lt, t
207	lsrlt	r0, r0, r2
208	orrlt	r0, r3, r0
209#else
210	orrlt	r0, r3, r0, lsr r2
211#endif
212	RET
213
214	@ Fixup and adjust bit position for denormalized arguments.
215	@ Note that r2 must not remain equal to 0.
216LSYM(Lad_d):
217	teq	r2, #0
218	eor	r1, r1, #0x00800000
219	do_it	eq, te
220	eoreq	r0, r0, #0x00800000
221	addeq	r2, r2, #1
222	subne	r3, r3, #1
223	b	LSYM(Lad_x)
224
225LSYM(Lad_s):
226	mov	r3, r1, lsl #1
227
228	mvns	ip, r2, asr #24
229	do_it	ne
230	COND(mvn,s,ne)	ip, r3, asr #24
231	beq	LSYM(Lad_i)
232
233	teq	r2, r3
234	beq	1f
235
236	@ Result is x + 0.0 = x or 0.0 + y = y.
237	teq	r2, #0
238	do_it	eq
239	moveq	r0, r1
240	RET
241
2421:	teq	r0, r1
243
244	@ Result is x - x = 0.
245	do_it	ne, t
246	movne	r0, #0
247	RETc(ne)
248
249	@ Result is x + x = 2x.
250	tst	r2, #0xff000000
251	bne	2f
252	movs	r0, r0, lsl #1
253	do_it	cs
254	orrcs	r0, r0, #0x80000000
255	RET
2562:	adds	r2, r2, #(2 << 24)
257	do_it	cc, t
258	addcc	r0, r0, #(1 << 23)
259	RETc(cc)
260	and	r3, r0, #0x80000000
261
262	@ Overflow: return INF.
263LSYM(Lad_o):
264	orr	r0, r3, #0x7f000000
265	orr	r0, r0, #0x00800000
266	RET
267
268	@ At least one of r0/r1 is INF/NAN.
269	@   if r0 != INF/NAN: return r1 (which is INF/NAN)
270	@   if r1 != INF/NAN: return r0 (which is INF/NAN)
271	@   if r0 or r1 is NAN: return NAN
272	@   if opposite sign: return NAN
273	@   otherwise return r0 (which is INF or -INF)
274LSYM(Lad_i):
275	mvns	r2, r2, asr #24
276	do_it	ne, et
277	movne	r0, r1
278	COND(mvn,s,eq)	r3, r3, asr #24
279	movne	r1, r0
280	movs	r2, r0, lsl #9
281	do_it	eq, te
282	COND(mov,s,eq)	r3, r1, lsl #9
283	teqeq	r0, r1
284	orrne	r0, r0, #0x00400000	@ quiet NAN
285	RET
286
287	FUNC_END aeabi_frsub
288	FUNC_END aeabi_fadd
289	FUNC_END addsf3
290	FUNC_END aeabi_fsub
291	FUNC_END subsf3
292
293ARM_FUNC_START floatunsisf
294ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
295
296	mov	r3, #0
297	b	1f
298
299ARM_FUNC_START floatsisf
300ARM_FUNC_ALIAS aeabi_i2f floatsisf
301
302	ands	r3, r0, #0x80000000
303	do_it	mi
304	rsbmi	r0, r0, #0
305
3061:	movs	ip, r0
307	do_it	eq
308	RETc(eq)
309
310	@ Add initial exponent to sign
311	orr	r3, r3, #((127 + 23) << 23)
312
313	.ifnc	ah, r0
314	mov	ah, r0
315	.endif
316	mov	al, #0
317	b	2f
318
319	FUNC_END aeabi_i2f
320	FUNC_END floatsisf
321	FUNC_END aeabi_ui2f
322	FUNC_END floatunsisf
323
324ARM_FUNC_START floatundisf
325ARM_FUNC_ALIAS aeabi_ul2f floatundisf
326
327	orrs	r2, r0, r1
328	do_it	eq
329	RETc(eq)
330
331	mov	r3, #0
332	b	1f
333
334ARM_FUNC_START floatdisf
335ARM_FUNC_ALIAS aeabi_l2f floatdisf
336
337	orrs	r2, r0, r1
338	do_it	eq
339	RETc(eq)
340
341	ands	r3, ah, #0x80000000	@ sign bit in r3
342	bpl	1f
343#if defined(__thumb2__)
344	negs	al, al
345	sbc	ah, ah, ah, lsl #1
346#else
347	rsbs	al, al, #0
348	rsc	ah, ah, #0
349#endif
3501:
351	movs	ip, ah
352	do_it	eq, tt
353	moveq	ip, al
354	moveq	ah, al
355	moveq	al, #0
356
357	@ Add initial exponent to sign
358	orr	r3, r3, #((127 + 23 + 32) << 23)
359	do_it	eq
360	subeq	r3, r3, #(32 << 23)
3612:	sub	r3, r3, #(1 << 23)
362
363#if __ARM_ARCH__ < 5
364
365	mov	r2, #23
366	cmp	ip, #(1 << 16)
367	do_it	hs, t
368	movhs	ip, ip, lsr #16
369	subhs	r2, r2, #16
370	cmp	ip, #(1 << 8)
371	do_it	hs, t
372	movhs	ip, ip, lsr #8
373	subhs	r2, r2, #8
374	cmp	ip, #(1 << 4)
375	do_it	hs, t
376	movhs	ip, ip, lsr #4
377	subhs	r2, r2, #4
378	cmp	ip, #(1 << 2)
379	do_it	hs, e
380	subhs	r2, r2, #2
381	sublo	r2, r2, ip, lsr #1
382	subs	r2, r2, ip, lsr #3
383
384#else
385
386	clz	r2, ip
387	subs	r2, r2, #8
388
389#endif
390
391	sub	r3, r3, r2, lsl #23
392	blt	3f
393
394	shiftop add r3 r3 ah lsl r2 ip
395	shift1	lsl, ip, al, r2
396	rsb	r2, r2, #32
397	cmp	ip, #0x80000000
398	shiftop adc r0 r3 al lsr r2 r2
399	do_it	eq
400	biceq	r0, r0, #1
401	RET
402
4033:	add	r2, r2, #32
404	shift1	lsl, ip, ah, r2
405	rsb	r2, r2, #32
406	orrs	al, al, ip, lsl #1
407	shiftop adc r0 r3 ah lsr r2 r2
408	do_it	eq
409	biceq	r0, r0, ip, lsr #31
410	RET
411
412	FUNC_END floatdisf
413	FUNC_END aeabi_l2f
414	FUNC_END floatundisf
415	FUNC_END aeabi_ul2f
416
417#endif /* L_addsubsf3 */
418
419#ifdef L_arm_muldivsf3
420
421ARM_FUNC_START mulsf3
422ARM_FUNC_ALIAS aeabi_fmul mulsf3
423
424	@ Mask out exponents, trap any zero/denormal/INF/NAN.
425	mov	ip, #0xff
426	ands	r2, ip, r0, lsr #23
427	do_it	ne, tt
428	COND(and,s,ne)	r3, ip, r1, lsr #23
429	teqne	r2, ip
430	teqne	r3, ip
431	beq	LSYM(Lml_s)
432LSYM(Lml_x):
433
434	@ Add exponents together
435	add	r2, r2, r3
436
437	@ Determine final sign.
438	eor	ip, r0, r1
439
440	@ Convert mantissa to unsigned integer.
441	@ If power of two, branch to a separate path.
442	@ Make up for final alignment.
443	movs	r0, r0, lsl #9
444	do_it	ne
445	COND(mov,s,ne)	r1, r1, lsl #9
446	beq	LSYM(Lml_1)
447	mov	r3, #0x08000000
448	orr	r0, r3, r0, lsr #5
449	orr	r1, r3, r1, lsr #5
450
451#if __ARM_ARCH__ < 4
452
453	@ Put sign bit in r3, which will be restored into r0 later.
454	and	r3, ip, #0x80000000
455
456	@ Well, no way to make it shorter without the umull instruction.
457	do_push	{r3, r4, r5}
458	mov	r4, r0, lsr #16
459	mov	r5, r1, lsr #16
460	bic	r0, r0, r4, lsl #16
461	bic	r1, r1, r5, lsl #16
462	mul	ip, r4, r5
463	mul	r3, r0, r1
464	mul	r0, r5, r0
465	mla	r0, r4, r1, r0
466	adds	r3, r3, r0, lsl #16
467	adc	r1, ip, r0, lsr #16
468	do_pop	{r0, r4, r5}
469
470#else
471
472	@ The actual multiplication.
473	umull	r3, r1, r0, r1
474
475	@ Put final sign in r0.
476	and	r0, ip, #0x80000000
477
478#endif
479
480	@ Adjust result upon the MSB position.
481	cmp	r1, #(1 << 23)
482	do_it	cc, tt
483	movcc	r1, r1, lsl #1
484	orrcc	r1, r1, r3, lsr #31
485	movcc	r3, r3, lsl #1
486
487	@ Add sign to result.
488	orr	r0, r0, r1
489
490	@ Apply exponent bias, check for under/overflow.
491	sbc	r2, r2, #127
492	cmp	r2, #(254 - 1)
493	bhi	LSYM(Lml_u)
494
495	@ Round the result, merge final exponent.
496	cmp	r3, #0x80000000
497	adc	r0, r0, r2, lsl #23
498	do_it	eq
499	biceq	r0, r0, #1
500	RET
501
502	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
503LSYM(Lml_1):
504	teq	r0, #0
505	and	ip, ip, #0x80000000
506	do_it	eq
507	moveq	r1, r1, lsl #9
508	orr	r0, ip, r0, lsr #9
509	orr	r0, r0, r1, lsr #9
510	subs	r2, r2, #127
511	do_it	gt, tt
512	COND(rsb,s,gt)	r3, r2, #255
513	orrgt	r0, r0, r2, lsl #23
514	RETc(gt)
515
516	@ Under/overflow: fix things up for the code below.
517	orr	r0, r0, #0x00800000
518	mov	r3, #0
519	subs	r2, r2, #1
520
521LSYM(Lml_u):
522	@ Overflow?
523	bgt	LSYM(Lml_o)
524
525	@ Check if denormalized result is possible, otherwise return signed 0.
526	cmn	r2, #(24 + 1)
527	do_it	le, t
528	bicle	r0, r0, #0x7fffffff
529	RETc(le)
530
531	@ Shift value right, round, etc.
532	rsb	r2, r2, #0
533	movs	r1, r0, lsl #1
534	shift1	lsr, r1, r1, r2
535	rsb	r2, r2, #32
536	shift1	lsl, ip, r0, r2
537	movs	r0, r1, rrx
538	adc	r0, r0, #0
539	orrs	r3, r3, ip, lsl #1
540	do_it	eq
541	biceq	r0, r0, ip, lsr #31
542	RET
543
544	@ One or both arguments are denormalized.
545	@ Scale them leftwards and preserve sign bit.
546LSYM(Lml_d):
547	teq	r2, #0
548	and	ip, r0, #0x80000000
5491:	do_it	eq, tt
550	moveq	r0, r0, lsl #1
551	tsteq	r0, #0x00800000
552	subeq	r2, r2, #1
553	beq	1b
554	orr	r0, r0, ip
555	teq	r3, #0
556	and	ip, r1, #0x80000000
5572:	do_it	eq, tt
558	moveq	r1, r1, lsl #1
559	tsteq	r1, #0x00800000
560	subeq	r3, r3, #1
561	beq	2b
562	orr	r1, r1, ip
563	b	LSYM(Lml_x)
564
565LSYM(Lml_s):
566	@ Isolate the INF and NAN cases away
567	and	r3, ip, r1, lsr #23
568	teq	r2, ip
569	do_it	ne
570	teqne	r3, ip
571	beq	1f
572
573	@ Here, one or more arguments are either denormalized or zero.
574	bics	ip, r0, #0x80000000
575	do_it	ne
576	COND(bic,s,ne)	ip, r1, #0x80000000
577	bne	LSYM(Lml_d)
578
579	@ Result is 0, but determine sign anyway.
580LSYM(Lml_z):
581	eor	r0, r0, r1
582	bic	r0, r0, #0x7fffffff
583	RET
584
5851:	@ One or both args are INF or NAN.
586	teq	r0, #0x0
587	do_it	ne, ett
588	teqne	r0, #0x80000000
589	moveq	r0, r1
590	teqne	r1, #0x0
591	teqne	r1, #0x80000000
592	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
593	teq	r2, ip
594	bne	1f
595	movs	r2, r0, lsl #9
596	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
5971:	teq	r3, ip
598	bne	LSYM(Lml_i)
599	movs	r3, r1, lsl #9
600	do_it	ne
601	movne	r0, r1
602	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
603
604	@ Result is INF, but we need to determine its sign.
605LSYM(Lml_i):
606	eor	r0, r0, r1
607
608	@ Overflow: return INF (sign already in r0).
609LSYM(Lml_o):
610	and	r0, r0, #0x80000000
611	orr	r0, r0, #0x7f000000
612	orr	r0, r0, #0x00800000
613	RET
614
615	@ Return a quiet NAN.
616LSYM(Lml_n):
617	orr	r0, r0, #0x7f000000
618	orr	r0, r0, #0x00c00000
619	RET
620
621	FUNC_END aeabi_fmul
622	FUNC_END mulsf3
623
624ARM_FUNC_START divsf3
625ARM_FUNC_ALIAS aeabi_fdiv divsf3
626
627	@ Mask out exponents, trap any zero/denormal/INF/NAN.
628	mov	ip, #0xff
629	ands	r2, ip, r0, lsr #23
630	do_it	ne, tt
631	COND(and,s,ne)	r3, ip, r1, lsr #23
632	teqne	r2, ip
633	teqne	r3, ip
634	beq	LSYM(Ldv_s)
635LSYM(Ldv_x):
636
637	@ Subtract divisor exponent from dividend''s
638	sub	r2, r2, r3
639
640	@ Preserve final sign into ip.
641	eor	ip, r0, r1
642
643	@ Convert mantissa to unsigned integer.
644	@ Dividend -> r3, divisor -> r1.
645	movs	r1, r1, lsl #9
646	mov	r0, r0, lsl #9
647	beq	LSYM(Ldv_1)
648	mov	r3, #0x10000000
649	orr	r1, r3, r1, lsr #4
650	orr	r3, r3, r0, lsr #4
651
652	@ Initialize r0 (result) with final sign bit.
653	and	r0, ip, #0x80000000
654
655	@ Ensure result will land to known bit position.
656	@ Apply exponent bias accordingly.
657	cmp	r3, r1
658	do_it	cc
659	movcc	r3, r3, lsl #1
660	adc	r2, r2, #(127 - 2)
661
662	@ The actual division loop.
663	mov	ip, #0x00800000
6641:	cmp	r3, r1
665	do_it	cs, t
666	subcs	r3, r3, r1
667	orrcs	r0, r0, ip
668	cmp	r3, r1, lsr #1
669	do_it	cs, t
670	subcs	r3, r3, r1, lsr #1
671	orrcs	r0, r0, ip, lsr #1
672	cmp	r3, r1, lsr #2
673	do_it	cs, t
674	subcs	r3, r3, r1, lsr #2
675	orrcs	r0, r0, ip, lsr #2
676	cmp	r3, r1, lsr #3
677	do_it	cs, t
678	subcs	r3, r3, r1, lsr #3
679	orrcs	r0, r0, ip, lsr #3
680	movs	r3, r3, lsl #4
681	do_it	ne
682	COND(mov,s,ne)	ip, ip, lsr #4
683	bne	1b
684
685	@ Check exponent for under/overflow.
686	cmp	r2, #(254 - 1)
687	bhi	LSYM(Lml_u)
688
689	@ Round the result, merge final exponent.
690	cmp	r3, r1
691	adc	r0, r0, r2, lsl #23
692	do_it	eq
693	biceq	r0, r0, #1
694	RET
695
696	@ Division by 0x1p*: let''s shortcut a lot of code.
697LSYM(Ldv_1):
698	and	ip, ip, #0x80000000
699	orr	r0, ip, r0, lsr #9
700	adds	r2, r2, #127
701	do_it	gt, tt
702	COND(rsb,s,gt)	r3, r2, #255
703	orrgt	r0, r0, r2, lsl #23
704	RETc(gt)
705
706	orr	r0, r0, #0x00800000
707	mov	r3, #0
708	subs	r2, r2, #1
709	b	LSYM(Lml_u)
710
711	@ One or both arguments are denormalized.
712	@ Scale them leftwards and preserve sign bit.
713LSYM(Ldv_d):
714	teq	r2, #0
715	and	ip, r0, #0x80000000
7161:	do_it	eq, tt
717	moveq	r0, r0, lsl #1
718	tsteq	r0, #0x00800000
719	subeq	r2, r2, #1
720	beq	1b
721	orr	r0, r0, ip
722	teq	r3, #0
723	and	ip, r1, #0x80000000
7242:	do_it	eq, tt
725	moveq	r1, r1, lsl #1
726	tsteq	r1, #0x00800000
727	subeq	r3, r3, #1
728	beq	2b
729	orr	r1, r1, ip
730	b	LSYM(Ldv_x)
731
732	@ One or both arguments are either INF, NAN, zero or denormalized.
733LSYM(Ldv_s):
734	and	r3, ip, r1, lsr #23
735	teq	r2, ip
736	bne	1f
737	movs	r2, r0, lsl #9
738	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
739	teq	r3, ip
740	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
741	mov	r0, r1
742	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
7431:	teq	r3, ip
744	bne	2f
745	movs	r3, r1, lsl #9
746	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
747	mov	r0, r1
748	b	LSYM(Lml_n)		@ <anything> / NAN -> NAN
7492:	@ If both are nonzero, we need to normalize and resume above.
750	bics	ip, r0, #0x80000000
751	do_it	ne
752	COND(bic,s,ne)	ip, r1, #0x80000000
753	bne	LSYM(Ldv_d)
754	@ One or both arguments are zero.
755	bics	r2, r0, #0x80000000
756	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
757	bics	r3, r1, #0x80000000
758	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
759	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
760
761	FUNC_END aeabi_fdiv
762	FUNC_END divsf3
763
764#endif /* L_muldivsf3 */
765
766#ifdef L_arm_cmpsf2
767
768	@ The return value in r0 is
769	@
770	@   0  if the operands are equal
771	@   1  if the first operand is greater than the second, or
772	@      the operands are unordered and the operation is
773	@      CMP, LT, LE, NE, or EQ.
774	@   -1 if the first operand is less than the second, or
775	@      the operands are unordered and the operation is GT
776	@      or GE.
777	@
778	@ The Z flag will be set iff the operands are equal.
779	@
780	@ The following registers are clobbered by this function:
781	@   ip, r0, r1, r2, r3
782
783ARM_FUNC_START gtsf2
784ARM_FUNC_ALIAS gesf2 gtsf2
785	mov	ip, #-1
786	b	1f
787
788ARM_FUNC_START ltsf2
789ARM_FUNC_ALIAS lesf2 ltsf2
790	mov	ip, #1
791	b	1f
792
793ARM_FUNC_START cmpsf2
794ARM_FUNC_ALIAS nesf2 cmpsf2
795ARM_FUNC_ALIAS eqsf2 cmpsf2
796	mov	ip, #1			@ how should we specify unordered here?
797
7981:	str	ip, [sp, #-4]!
799
800	@ Trap any INF/NAN first.
801	mov	r2, r0, lsl #1
802	mov	r3, r1, lsl #1
803	mvns	ip, r2, asr #24
804	do_it	ne
805	COND(mvn,s,ne)	ip, r3, asr #24
806	beq	3f
807
808	@ Compare values.
809	@ Note that 0.0 is equal to -0.0.
8102:	add	sp, sp, #4
811	orrs	ip, r2, r3, lsr #1	@ test if both are 0, clear C flag
812	do_it	ne
813	teqne	r0, r1			@ if not 0 compare sign
814	do_it	pl
815	COND(sub,s,pl)	r0, r2, r3		@ if same sign compare values, set r0
816
817	@ Result:
818	do_it	hi
819	movhi	r0, r1, asr #31
820	do_it	lo
821	mvnlo	r0, r1, asr #31
822	do_it	ne
823	orrne	r0, r0, #1
824	RET
825
826	@ Look for a NAN.
8273:	mvns	ip, r2, asr #24
828	bne	4f
829	movs	ip, r0, lsl #9
830	bne	5f			@ r0 is NAN
8314:	mvns	ip, r3, asr #24
832	bne	2b
833	movs	ip, r1, lsl #9
834	beq	2b			@ r1 is not NAN
8355:	ldr	r0, [sp], #4		@ return unordered code.
836	RET
837
838	FUNC_END gesf2
839	FUNC_END gtsf2
840	FUNC_END lesf2
841	FUNC_END ltsf2
842	FUNC_END nesf2
843	FUNC_END eqsf2
844	FUNC_END cmpsf2
845
846ARM_FUNC_START aeabi_cfrcmple
847
848	mov	ip, r0
849	mov	r0, r1
850	mov	r1, ip
851	b	6f
852
853ARM_FUNC_START aeabi_cfcmpeq
854ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
855
856	@ The status-returning routines are required to preserve all
857	@ registers except ip, lr, and cpsr.
8586:	do_push	{r0, r1, r2, r3, lr}
859	ARM_CALL cmpsf2
860	@ Set the Z flag correctly, and the C flag unconditionally.
861	cmp	r0, #0
862	@ Clear the C flag if the return value was -1, indicating
863	@ that the first operand was smaller than the second.
864	do_it	mi
865	cmnmi	r0, #0
866	RETLDM	"r0, r1, r2, r3"
867
868	FUNC_END aeabi_cfcmple
869	FUNC_END aeabi_cfcmpeq
870	FUNC_END aeabi_cfrcmple
871
872ARM_FUNC_START	aeabi_fcmpeq
873
874	str	lr, [sp, #-8]!
875	ARM_CALL aeabi_cfcmple
876	do_it	eq, e
877	moveq	r0, #1	@ Equal to.
878	movne	r0, #0	@ Less than, greater than, or unordered.
879	RETLDM
880
881	FUNC_END aeabi_fcmpeq
882
883ARM_FUNC_START	aeabi_fcmplt
884
885	str	lr, [sp, #-8]!
886	ARM_CALL aeabi_cfcmple
887	do_it	cc, e
888	movcc	r0, #1	@ Less than.
889	movcs	r0, #0	@ Equal to, greater than, or unordered.
890	RETLDM
891
892	FUNC_END aeabi_fcmplt
893
894ARM_FUNC_START	aeabi_fcmple
895
896	str	lr, [sp, #-8]!
897	ARM_CALL aeabi_cfcmple
898	do_it	ls, e
899	movls	r0, #1  @ Less than or equal to.
900	movhi	r0, #0	@ Greater than or unordered.
901	RETLDM
902
903	FUNC_END aeabi_fcmple
904
905ARM_FUNC_START	aeabi_fcmpge
906
907	str	lr, [sp, #-8]!
908	ARM_CALL aeabi_cfrcmple
909	do_it	ls, e
910	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
911	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
912	RETLDM
913
914	FUNC_END aeabi_fcmpge
915
916ARM_FUNC_START	aeabi_fcmpgt
917
918	str	lr, [sp, #-8]!
919	ARM_CALL aeabi_cfrcmple
920	do_it	cc, e
921	movcc	r0, #1	@ Operand 2 is less than operand 1.
922	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
923			@ or they are unordered.
924	RETLDM
925
926	FUNC_END aeabi_fcmpgt
927
928#endif /* L_cmpsf2 */
929
930#ifdef L_arm_unordsf2
931
932ARM_FUNC_START unordsf2
933ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
934
935	mov	r2, r0, lsl #1
936	mov	r3, r1, lsl #1
937	mvns	ip, r2, asr #24
938	bne	1f
939	movs	ip, r0, lsl #9
940	bne	3f			@ r0 is NAN
9411:	mvns	ip, r3, asr #24
942	bne	2f
943	movs	ip, r1, lsl #9
944	bne	3f			@ r1 is NAN
9452:	mov	r0, #0			@ arguments are ordered.
946	RET
9473:	mov	r0, #1			@ arguments are unordered.
948	RET
949
950	FUNC_END aeabi_fcmpun
951	FUNC_END unordsf2
952
953#endif /* L_unordsf2 */
954
955#ifdef L_arm_fixsfsi
956
957ARM_FUNC_START fixsfsi
958ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
959
960	@ check exponent range.
961	mov	r2, r0, lsl #1
962	cmp	r2, #(127 << 24)
963	bcc	1f			@ value is too small
964	mov	r3, #(127 + 31)
965	subs	r2, r3, r2, lsr #24
966	bls	2f			@ value is too large
967
968	@ scale value
969	mov	r3, r0, lsl #8
970	orr	r3, r3, #0x80000000
971	tst	r0, #0x80000000		@ the sign bit
972	shift1	lsr, r0, r3, r2
973	do_it	ne
974	rsbne	r0, r0, #0
975	RET
976
9771:	mov	r0, #0
978	RET
979
9802:	cmp	r2, #(127 + 31 - 0xff)
981	bne	3f
982	movs	r2, r0, lsl #9
983	bne	4f			@ r0 is NAN.
9843:	ands	r0, r0, #0x80000000	@ the sign bit
985	do_it	eq
986	moveq	r0, #0x7fffffff		@ the maximum signed positive si
987	RET
988
9894:	mov	r0, #0			@ What should we convert NAN to?
990	RET
991
992	FUNC_END aeabi_f2iz
993	FUNC_END fixsfsi
994
995#endif /* L_fixsfsi */
996
997#ifdef L_arm_fixunssfsi
998
999ARM_FUNC_START fixunssfsi
1000ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
1001
1002	@ check exponent range.
1003	movs	r2, r0, lsl #1
1004	bcs	1f			@ value is negative
1005	cmp	r2, #(127 << 24)
1006	bcc	1f			@ value is too small
1007	mov	r3, #(127 + 31)
1008	subs	r2, r3, r2, lsr #24
1009	bmi	2f			@ value is too large
1010
1011	@ scale the value
1012	mov	r3, r0, lsl #8
1013	orr	r3, r3, #0x80000000
1014	shift1	lsr, r0, r3, r2
1015	RET
1016
10171:	mov	r0, #0
1018	RET
1019
10202:	cmp	r2, #(127 + 31 - 0xff)
1021	bne	3f
1022	movs	r2, r0, lsl #9
1023	bne	4f			@ r0 is NAN.
10243:	mov	r0, #0xffffffff		@ maximum unsigned si
1025	RET
1026
10274:	mov	r0, #0			@ What should we convert NAN to?
1028	RET
1029
1030	FUNC_END aeabi_f2uiz
1031	FUNC_END fixunssfsi
1032
1033#endif /* L_fixunssfsi */
1034