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