1/* ieee754-sf.S single-precision floating point support for ARM
2
3   Copyright (C) 2003-2019 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 *
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	subs	r2, r2, #1
172	do_it	hs
173	cmphs	r0, #0x00800000
174	bhs	LSYM(Lad_e)
175
176	@ No rounding necessary since r1 will always be 0 at this point.
177LSYM(Lad_l):
178
179#if !defined (__ARM_FEATURE_CLZ)
180
181	movs	ip, r0, lsr #12
182	moveq	r0, r0, lsl #12
183	subeq	r2, r2, #12
184	tst	r0, #0x00ff0000
185	moveq	r0, r0, lsl #8
186	subeq	r2, r2, #8
187	tst	r0, #0x00f00000
188	moveq	r0, r0, lsl #4
189	subeq	r2, r2, #4
190	tst	r0, #0x00c00000
191	moveq	r0, r0, lsl #2
192	subeq	r2, r2, #2
193	cmp	r0, #0x00800000
194	movcc	r0, r0, lsl #1
195	sbcs	r2, r2, #0
196
197#else
198
199	clz	ip, r0
200	sub	ip, ip, #8
201	subs	r2, r2, ip
202	shift1	lsl, r0, r0, ip
203
204#endif
205
206	@ Final result with sign
207	@ If exponent negative, denormalize result.
208	do_it	ge, et
209	addge	r0, r0, r2, lsl #23
210	rsblt	r2, r2, #0
211	orrge	r0, r0, r3
212#if defined(__thumb2__)
213	do_it	lt, t
214	lsrlt	r0, r0, r2
215	orrlt	r0, r3, r0
216#else
217	orrlt	r0, r3, r0, lsr r2
218#endif
219	RET
220
221	@ Fixup and adjust bit position for denormalized arguments.
222	@ Note that r2 must not remain equal to 0.
223LSYM(Lad_d):
224	teq	r2, #0
225	eor	r1, r1, #0x00800000
226	do_it	eq, te
227	eoreq	r0, r0, #0x00800000
228	addeq	r2, r2, #1
229	subne	r3, r3, #1
230	b	LSYM(Lad_x)
231
232LSYM(Lad_s):
233	mov	r3, r1, lsl #1
234
235	mvns	ip, r2, asr #24
236	do_it	ne
237	COND(mvn,s,ne)	ip, r3, asr #24
238	beq	LSYM(Lad_i)
239
240	teq	r2, r3
241	beq	1f
242
243	@ Result is x + 0.0 = x or 0.0 + y = y.
244	teq	r2, #0
245	do_it	eq
246	moveq	r0, r1
247	RET
248
2491:	teq	r0, r1
250
251	@ Result is x - x = 0.
252	do_it	ne, t
253	movne	r0, #0
254	RETc(ne)
255
256	@ Result is x + x = 2x.
257	tst	r2, #0xff000000
258	bne	2f
259	movs	r0, r0, lsl #1
260	do_it	cs
261	orrcs	r0, r0, #0x80000000
262	RET
2632:	adds	r2, r2, #(2 << 24)
264	do_it	cc, t
265	addcc	r0, r0, #(1 << 23)
266	RETc(cc)
267	and	r3, r0, #0x80000000
268
269	@ Overflow: return INF.
270LSYM(Lad_o):
271	orr	r0, r3, #0x7f000000
272	orr	r0, r0, #0x00800000
273	RET
274
275	@ At least one of r0/r1 is INF/NAN.
276	@   if r0 != INF/NAN: return r1 (which is INF/NAN)
277	@   if r1 != INF/NAN: return r0 (which is INF/NAN)
278	@   if r0 or r1 is NAN: return NAN
279	@   if opposite sign: return NAN
280	@   otherwise return r0 (which is INF or -INF)
281LSYM(Lad_i):
282	mvns	r2, r2, asr #24
283	do_it	ne, et
284	movne	r0, r1
285	COND(mvn,s,eq)	r3, r3, asr #24
286	movne	r1, r0
287	movs	r2, r0, lsl #9
288	do_it	eq, te
289	COND(mov,s,eq)	r3, r1, lsl #9
290	teqeq	r0, r1
291	orrne	r0, r0, #0x00400000	@ quiet NAN
292	RET
293
294	CFI_END_FUNCTION
295	FUNC_END aeabi_frsub
296	FUNC_END aeabi_fadd
297	FUNC_END addsf3
298	FUNC_END aeabi_fsub
299	FUNC_END subsf3
300
301ARM_FUNC_START floatunsisf
302ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
303	CFI_START_FUNCTION
304
305	mov	r3, #0
306	b	1f
307
308ARM_FUNC_START floatsisf
309ARM_FUNC_ALIAS aeabi_i2f floatsisf
310
311	ands	r3, r0, #0x80000000
312	do_it	mi
313	rsbmi	r0, r0, #0
314
3151:	movs	ip, r0
316	do_it	eq
317	RETc(eq)
318
319	@ Add initial exponent to sign
320	orr	r3, r3, #((127 + 23) << 23)
321
322	.ifnc	ah, r0
323	mov	ah, r0
324	.endif
325	mov	al, #0
326	b	2f
327
328	CFI_END_FUNCTION
329	FUNC_END aeabi_i2f
330	FUNC_END floatsisf
331	FUNC_END aeabi_ui2f
332	FUNC_END floatunsisf
333
334ARM_FUNC_START floatundisf
335ARM_FUNC_ALIAS aeabi_ul2f floatundisf
336	CFI_START_FUNCTION
337
338	orrs	r2, r0, r1
339	do_it	eq
340	RETc(eq)
341
342	mov	r3, #0
343	b	1f
344
345ARM_FUNC_START floatdisf
346ARM_FUNC_ALIAS aeabi_l2f floatdisf
347
348	orrs	r2, r0, r1
349	do_it	eq
350	RETc(eq)
351
352	ands	r3, ah, #0x80000000	@ sign bit in r3
353	bpl	1f
354#if defined(__thumb2__)
355	negs	al, al
356	sbc	ah, ah, ah, lsl #1
357#else
358	rsbs	al, al, #0
359	rsc	ah, ah, #0
360#endif
3611:
362	movs	ip, ah
363	do_it	eq, tt
364	moveq	ip, al
365	moveq	ah, al
366	moveq	al, #0
367
368	@ Add initial exponent to sign
369	orr	r3, r3, #((127 + 23 + 32) << 23)
370	do_it	eq
371	subeq	r3, r3, #(32 << 23)
3722:	sub	r3, r3, #(1 << 23)
373
374#if !defined (__ARM_FEATURE_CLZ)
375
376	mov	r2, #23
377	cmp	ip, #(1 << 16)
378	do_it	hs, t
379	movhs	ip, ip, lsr #16
380	subhs	r2, r2, #16
381	cmp	ip, #(1 << 8)
382	do_it	hs, t
383	movhs	ip, ip, lsr #8
384	subhs	r2, r2, #8
385	cmp	ip, #(1 << 4)
386	do_it	hs, t
387	movhs	ip, ip, lsr #4
388	subhs	r2, r2, #4
389	cmp	ip, #(1 << 2)
390	do_it	hs, e
391	subhs	r2, r2, #2
392	sublo	r2, r2, ip, lsr #1
393	subs	r2, r2, ip, lsr #3
394
395#else
396
397	clz	r2, ip
398	subs	r2, r2, #8
399
400#endif
401
402	sub	r3, r3, r2, lsl #23
403	blt	3f
404
405	shiftop add r3 r3 ah lsl r2 ip
406	shift1	lsl, ip, al, r2
407	rsb	r2, r2, #32
408	cmp	ip, #0x80000000
409	shiftop adc r0 r3 al lsr r2 r2
410	do_it	eq
411	biceq	r0, r0, #1
412	RET
413
4143:	add	r2, r2, #32
415	shift1	lsl, ip, ah, r2
416	rsb	r2, r2, #32
417	orrs	al, al, ip, lsl #1
418	shiftop adc r0 r3 ah lsr r2 r2
419	do_it	eq
420	biceq	r0, r0, ip, lsr #31
421	RET
422
423	CFI_END_FUNCTION
424	FUNC_END floatdisf
425	FUNC_END aeabi_l2f
426	FUNC_END floatundisf
427	FUNC_END aeabi_ul2f
428
429#endif /* L_addsubsf3 */
430
431#if defined(L_arm_mulsf3) || defined(L_arm_muldivsf3)
432
433@ Define multiplication as weak in _arm_mulsf3.o so that it can be overriden
434@ by the global definition in _arm_muldivsf3.o.  This allows a program only
435@ using multiplication to take the weak definition which does not contain the
436@ division code. Programs using only division or both division and
437@ multiplication will pull _arm_muldivsf3.o from which both the multiplication
438@ and division are taken thanks to the override.
439#ifdef L_arm_mulsf3
440WEAK mulsf3
441WEAK aeabi_fmul
442#endif
443
444ARM_FUNC_START mulsf3
445ARM_FUNC_ALIAS aeabi_fmul mulsf3
446	CFI_START_FUNCTION
447
448	@ Mask out exponents, trap any zero/denormal/INF/NAN.
449	mov	ip, #0xff
450	ands	r2, ip, r0, lsr #23
451	do_it	ne, tt
452	COND(and,s,ne)	r3, ip, r1, lsr #23
453	teqne	r2, ip
454	teqne	r3, ip
455	beq	LSYM(Lml_s)
456LSYM(Lml_x):
457
458	@ Add exponents together
459	add	r2, r2, r3
460
461	@ Determine final sign.
462	eor	ip, r0, r1
463
464	@ Convert mantissa to unsigned integer.
465	@ If power of two, branch to a separate path.
466	@ Make up for final alignment.
467	movs	r0, r0, lsl #9
468	do_it	ne
469	COND(mov,s,ne)	r1, r1, lsl #9
470	beq	LSYM(Lml_1)
471	mov	r3, #0x08000000
472	orr	r0, r3, r0, lsr #5
473	orr	r1, r3, r1, lsr #5
474
475	@ The actual multiplication.
476	@ This code works on architecture versions >= 4
477	umull	r3, r1, r0, r1
478
479	@ Put final sign in r0.
480	and	r0, ip, #0x80000000
481
482	@ Adjust result upon the MSB position.
483	cmp	r1, #(1 << 23)
484	do_it	cc, tt
485	movcc	r1, r1, lsl #1
486	orrcc	r1, r1, r3, lsr #31
487	movcc	r3, r3, lsl #1
488
489	@ Add sign to result.
490	orr	r0, r0, r1
491
492	@ Apply exponent bias, check for under/overflow.
493	sbc	r2, r2, #127
494	cmp	r2, #(254 - 1)
495	bhi	LSYM(Lml_u)
496
497	@ Round the result, merge final exponent.
498	cmp	r3, #0x80000000
499	adc	r0, r0, r2, lsl #23
500	do_it	eq
501	biceq	r0, r0, #1
502	RET
503
504	@ Multiplication by 0x1p*: let''s shortcut a lot of code.
505LSYM(Lml_1):
506	teq	r0, #0
507	and	ip, ip, #0x80000000
508	do_it	eq
509	moveq	r1, r1, lsl #9
510	orr	r0, ip, r0, lsr #9
511	orr	r0, r0, r1, lsr #9
512	subs	r2, r2, #127
513	do_it	gt, tt
514	COND(rsb,s,gt)	r3, r2, #255
515	orrgt	r0, r0, r2, lsl #23
516	RETc(gt)
517
518	@ Under/overflow: fix things up for the code below.
519	orr	r0, r0, #0x00800000
520	mov	r3, #0
521	subs	r2, r2, #1
522
523LSYM(Lml_u):
524	@ Overflow?
525	bgt	LSYM(Lml_o)
526
527	@ Check if denormalized result is possible, otherwise return signed 0.
528	cmn	r2, #(24 + 1)
529	do_it	le, t
530	bicle	r0, r0, #0x7fffffff
531	RETc(le)
532
533	@ Shift value right, round, etc.
534	rsb	r2, r2, #0
535	movs	r1, r0, lsl #1
536	shift1	lsr, r1, r1, r2
537	rsb	r2, r2, #32
538	shift1	lsl, ip, r0, r2
539	movs	r0, r1, rrx
540	adc	r0, r0, #0
541	orrs	r3, r3, ip, lsl #1
542	do_it	eq
543	biceq	r0, r0, ip, lsr #31
544	RET
545
546	@ One or both arguments are denormalized.
547	@ Scale them leftwards and preserve sign bit.
548LSYM(Lml_d):
549	teq	r2, #0
550	and	ip, r0, #0x80000000
5511:	do_it	eq, tt
552	moveq	r0, r0, lsl #1
553	tsteq	r0, #0x00800000
554	subeq	r2, r2, #1
555	beq	1b
556	orr	r0, r0, ip
557	teq	r3, #0
558	and	ip, r1, #0x80000000
5592:	do_it	eq, tt
560	moveq	r1, r1, lsl #1
561	tsteq	r1, #0x00800000
562	subeq	r3, r3, #1
563	beq	2b
564	orr	r1, r1, ip
565	b	LSYM(Lml_x)
566
567LSYM(Lml_s):
568	@ Isolate the INF and NAN cases away
569	and	r3, ip, r1, lsr #23
570	teq	r2, ip
571	do_it	ne
572	teqne	r3, ip
573	beq	1f
574
575	@ Here, one or more arguments are either denormalized or zero.
576	bics	ip, r0, #0x80000000
577	do_it	ne
578	COND(bic,s,ne)	ip, r1, #0x80000000
579	bne	LSYM(Lml_d)
580
581	@ Result is 0, but determine sign anyway.
582LSYM(Lml_z):
583	eor	r0, r0, r1
584	bic	r0, r0, #0x7fffffff
585	RET
586
5871:	@ One or both args are INF or NAN.
588	teq	r0, #0x0
589	do_it	ne, ett
590	teqne	r0, #0x80000000
591	moveq	r0, r1
592	teqne	r1, #0x0
593	teqne	r1, #0x80000000
594	beq	LSYM(Lml_n)		@ 0 * INF or INF * 0 -> NAN
595	teq	r2, ip
596	bne	1f
597	movs	r2, r0, lsl #9
598	bne	LSYM(Lml_n)		@ NAN * <anything> -> NAN
5991:	teq	r3, ip
600	bne	LSYM(Lml_i)
601	movs	r3, r1, lsl #9
602	do_it	ne
603	movne	r0, r1
604	bne	LSYM(Lml_n)		@ <anything> * NAN -> NAN
605
606	@ Result is INF, but we need to determine its sign.
607LSYM(Lml_i):
608	eor	r0, r0, r1
609
610	@ Overflow: return INF (sign already in r0).
611LSYM(Lml_o):
612	and	r0, r0, #0x80000000
613	orr	r0, r0, #0x7f000000
614	orr	r0, r0, #0x00800000
615	RET
616
617	@ Return a quiet NAN.
618LSYM(Lml_n):
619	orr	r0, r0, #0x7f000000
620	orr	r0, r0, #0x00c00000
621	RET
622
623	CFI_END_FUNCTION
624	FUNC_END aeabi_fmul
625	FUNC_END mulsf3
626
627#ifdef L_arm_muldivsf3
628
629ARM_FUNC_START divsf3
630ARM_FUNC_ALIAS aeabi_fdiv divsf3
631	CFI_START_FUNCTION
632
633	@ Mask out exponents, trap any zero/denormal/INF/NAN.
634	mov	ip, #0xff
635	ands	r2, ip, r0, lsr #23
636	do_it	ne, tt
637	COND(and,s,ne)	r3, ip, r1, lsr #23
638	teqne	r2, ip
639	teqne	r3, ip
640	beq	LSYM(Ldv_s)
641LSYM(Ldv_x):
642
643	@ Subtract divisor exponent from dividend''s
644	sub	r2, r2, r3
645
646	@ Preserve final sign into ip.
647	eor	ip, r0, r1
648
649	@ Convert mantissa to unsigned integer.
650	@ Dividend -> r3, divisor -> r1.
651	movs	r1, r1, lsl #9
652	mov	r0, r0, lsl #9
653	beq	LSYM(Ldv_1)
654	mov	r3, #0x10000000
655	orr	r1, r3, r1, lsr #4
656	orr	r3, r3, r0, lsr #4
657
658	@ Initialize r0 (result) with final sign bit.
659	and	r0, ip, #0x80000000
660
661	@ Ensure result will land to known bit position.
662	@ Apply exponent bias accordingly.
663	cmp	r3, r1
664	do_it	cc
665	movcc	r3, r3, lsl #1
666	adc	r2, r2, #(127 - 2)
667
668	@ The actual division loop.
669	mov	ip, #0x00800000
6701:	cmp	r3, r1
671	do_it	cs, t
672	subcs	r3, r3, r1
673	orrcs	r0, r0, ip
674	cmp	r3, r1, lsr #1
675	do_it	cs, t
676	subcs	r3, r3, r1, lsr #1
677	orrcs	r0, r0, ip, lsr #1
678	cmp	r3, r1, lsr #2
679	do_it	cs, t
680	subcs	r3, r3, r1, lsr #2
681	orrcs	r0, r0, ip, lsr #2
682	cmp	r3, r1, lsr #3
683	do_it	cs, t
684	subcs	r3, r3, r1, lsr #3
685	orrcs	r0, r0, ip, lsr #3
686	movs	r3, r3, lsl #4
687	do_it	ne
688	COND(mov,s,ne)	ip, ip, lsr #4
689	bne	1b
690
691	@ Check exponent for under/overflow.
692	cmp	r2, #(254 - 1)
693	bhi	LSYM(Lml_u)
694
695	@ Round the result, merge final exponent.
696	cmp	r3, r1
697	adc	r0, r0, r2, lsl #23
698	do_it	eq
699	biceq	r0, r0, #1
700	RET
701
702	@ Division by 0x1p*: let''s shortcut a lot of code.
703LSYM(Ldv_1):
704	and	ip, ip, #0x80000000
705	orr	r0, ip, r0, lsr #9
706	adds	r2, r2, #127
707	do_it	gt, tt
708	COND(rsb,s,gt)	r3, r2, #255
709	orrgt	r0, r0, r2, lsl #23
710	RETc(gt)
711
712	orr	r0, r0, #0x00800000
713	mov	r3, #0
714	subs	r2, r2, #1
715	b	LSYM(Lml_u)
716
717	@ One or both arguments are denormalized.
718	@ Scale them leftwards and preserve sign bit.
719LSYM(Ldv_d):
720	teq	r2, #0
721	and	ip, r0, #0x80000000
7221:	do_it	eq, tt
723	moveq	r0, r0, lsl #1
724	tsteq	r0, #0x00800000
725	subeq	r2, r2, #1
726	beq	1b
727	orr	r0, r0, ip
728	teq	r3, #0
729	and	ip, r1, #0x80000000
7302:	do_it	eq, tt
731	moveq	r1, r1, lsl #1
732	tsteq	r1, #0x00800000
733	subeq	r3, r3, #1
734	beq	2b
735	orr	r1, r1, ip
736	b	LSYM(Ldv_x)
737
738	@ One or both arguments are either INF, NAN, zero or denormalized.
739LSYM(Ldv_s):
740	and	r3, ip, r1, lsr #23
741	teq	r2, ip
742	bne	1f
743	movs	r2, r0, lsl #9
744	bne	LSYM(Lml_n)		@ NAN / <anything> -> NAN
745	teq	r3, ip
746	bne	LSYM(Lml_i)		@ INF / <anything> -> INF
747	mov	r0, r1
748	b	LSYM(Lml_n)		@ INF / (INF or NAN) -> NAN
7491:	teq	r3, ip
750	bne	2f
751	movs	r3, r1, lsl #9
752	beq	LSYM(Lml_z)		@ <anything> / INF -> 0
753	mov	r0, r1
754	b	LSYM(Lml_n)		@ <anything> / NAN -> NAN
7552:	@ If both are nonzero, we need to normalize and resume above.
756	bics	ip, r0, #0x80000000
757	do_it	ne
758	COND(bic,s,ne)	ip, r1, #0x80000000
759	bne	LSYM(Ldv_d)
760	@ One or both arguments are zero.
761	bics	r2, r0, #0x80000000
762	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
763	bics	r3, r1, #0x80000000
764	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
765	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
766
767	CFI_END_FUNCTION
768	FUNC_END aeabi_fdiv
769	FUNC_END divsf3
770
771#endif /* L_muldivsf3 */
772#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */
773
774#ifdef L_arm_cmpsf2
775
776	@ The return value in r0 is
777	@
778	@   0  if the operands are equal
779	@   1  if the first operand is greater than the second, or
780	@      the operands are unordered and the operation is
781	@      CMP, LT, LE, NE, or EQ.
782	@   -1 if the first operand is less than the second, or
783	@      the operands are unordered and the operation is GT
784	@      or GE.
785	@
786	@ The Z flag will be set iff the operands are equal.
787	@
788	@ The following registers are clobbered by this function:
789	@   ip, r0, r1, r2, r3
790
791ARM_FUNC_START gtsf2
792ARM_FUNC_ALIAS gesf2 gtsf2
793	CFI_START_FUNCTION
794	mov	ip, #-1
795	b	1f
796
797ARM_FUNC_START ltsf2
798ARM_FUNC_ALIAS lesf2 ltsf2
799	mov	ip, #1
800	b	1f
801
802ARM_FUNC_START cmpsf2
803ARM_FUNC_ALIAS nesf2 cmpsf2
804ARM_FUNC_ALIAS eqsf2 cmpsf2
805	mov	ip, #1			@ how should we specify unordered here?
806
8071:	str	ip, [sp, #-4]!
808	.cfi_adjust_cfa_offset 4  @ CFA is now sp + previousOffset + 4.
809	@ We're not adding CFI for ip as it's pushed into the stack only because
810	@ it may be popped off later as a return value (i.e. we're not preserving
811	@ it anyways).
812
813	@ Trap any INF/NAN first.
814	mov	r2, r0, lsl #1
815	mov	r3, r1, lsl #1
816	mvns	ip, r2, asr #24
817	do_it	ne
818	COND(mvn,s,ne)	ip, r3, asr #24
819	beq	3f
820	.cfi_remember_state
821	@ Save the current CFI state. This is done because the branch is conditional,
822	@ and if we don't take it we'll issue a .cfi_adjust_cfa_offset and return.
823	@ If we do take it, however, the .cfi_adjust_cfa_offset from the non-branch
824	@ code will affect the branch code as well. To avoid this we'll restore
825	@ the current state before executing the branch code.
826
827	@ Compare values.
828	@ Note that 0.0 is equal to -0.0.
8292:	add	sp, sp, #4
830	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
831
832	orrs	ip, r2, r3, lsr #1	@ test if both are 0, clear C flag
833	do_it	ne
834	teqne	r0, r1			@ if not 0 compare sign
835	do_it	pl
836	COND(sub,s,pl)	r0, r2, r3		@ if same sign compare values, set r0
837
838	@ Result:
839	do_it	hi
840	movhi	r0, r1, asr #31
841	do_it	lo
842	mvnlo	r0, r1, asr #31
843	do_it	ne
844	orrne	r0, r0, #1
845	RET
846
8473:	@ Look for a NAN.
848
849	@ Restore the previous CFI state (i.e. keep the CFI state as it was
850	@ before the branch).
851	.cfi_restore_state
852
853	mvns	ip, r2, asr #24
854	bne	4f
855	movs	ip, r0, lsl #9
856	bne	5f			@ r0 is NAN
8574:	mvns	ip, r3, asr #24
858	bne	2b
859	movs	ip, r1, lsl #9
860	beq	2b			@ r1 is not NAN
861
8625:	ldr	r0, [sp], #4		@ return unordered code.
863	.cfi_adjust_cfa_offset -4       @ CFA is now sp + previousOffset.
864	RET
865
866	CFI_END_FUNCTION
867	FUNC_END gesf2
868	FUNC_END gtsf2
869	FUNC_END lesf2
870	FUNC_END ltsf2
871	FUNC_END nesf2
872	FUNC_END eqsf2
873	FUNC_END cmpsf2
874
875ARM_FUNC_START aeabi_cfrcmple
876	CFI_START_FUNCTION
877
878	mov	ip, r0
879	mov	r0, r1
880	mov	r1, ip
881	b	6f
882
883ARM_FUNC_START aeabi_cfcmpeq
884ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
885
886	@ The status-returning routines are required to preserve all
887	@ registers except ip, lr, and cpsr.
8886:	do_push	{r0, r1, r2, r3, lr}
889	.cfi_adjust_cfa_offset 20  @ CFA is at sp + previousOffset + 20
890	.cfi_rel_offset r0, 0      @ Registers are saved from sp to sp + 16
891	.cfi_rel_offset r1, 4
892	.cfi_rel_offset r2, 8
893	.cfi_rel_offset r3, 12
894	.cfi_rel_offset lr, 16
895
896	ARM_CALL cmpsf2
897	@ Set the Z flag correctly, and the C flag unconditionally.
898	cmp	r0, #0
899	@ Clear the C flag if the return value was -1, indicating
900	@ that the first operand was smaller than the second.
901	do_it	mi
902	cmnmi	r0, #0
903	RETLDM	"r0, r1, r2, r3"
904
905	CFI_END_FUNCTION
906	FUNC_END aeabi_cfcmple
907	FUNC_END aeabi_cfcmpeq
908	FUNC_END aeabi_cfrcmple
909
910ARM_FUNC_START	aeabi_fcmpeq
911	CFI_START_FUNCTION
912
913	str	lr, [sp, #-8]!    @ sp -= 8
914	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
915	.cfi_rel_offset lr, 0     @ lr is at sp
916
917	ARM_CALL aeabi_cfcmple
918	do_it	eq, e
919	moveq	r0, #1	@ Equal to.
920	movne	r0, #0	@ Less than, greater than, or unordered.
921	RETLDM
922
923	CFI_END_FUNCTION
924	FUNC_END aeabi_fcmpeq
925
926ARM_FUNC_START	aeabi_fcmplt
927	CFI_START_FUNCTION
928
929	str	lr, [sp, #-8]!    @ sp -= 8
930	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
931	.cfi_rel_offset lr, 0     @ lr is at sp
932
933	ARM_CALL aeabi_cfcmple
934	do_it	cc, e
935	movcc	r0, #1	@ Less than.
936	movcs	r0, #0	@ Equal to, greater than, or unordered.
937	RETLDM
938
939	CFI_END_FUNCTION
940	FUNC_END aeabi_fcmplt
941
942ARM_FUNC_START	aeabi_fcmple
943	CFI_START_FUNCTION
944
945	str	lr, [sp, #-8]!    @ sp -= 8
946	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
947	.cfi_rel_offset lr, 0     @ lr is at sp
948
949	ARM_CALL aeabi_cfcmple
950	do_it	ls, e
951	movls	r0, #1  @ Less than or equal to.
952	movhi	r0, #0	@ Greater than or unordered.
953	RETLDM
954
955	CFI_END_FUNCTION
956	FUNC_END aeabi_fcmple
957
958ARM_FUNC_START	aeabi_fcmpge
959	CFI_START_FUNCTION
960
961	str	lr, [sp, #-8]!    @ sp -= 8
962	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
963	.cfi_rel_offset lr, 0     @ lr is at sp
964
965	ARM_CALL aeabi_cfrcmple
966	do_it	ls, e
967	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
968	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
969	RETLDM
970
971	CFI_END_FUNCTION
972	FUNC_END aeabi_fcmpge
973
974ARM_FUNC_START	aeabi_fcmpgt
975	CFI_START_FUNCTION
976
977	str	lr, [sp, #-8]!    @ sp -= 8
978	.cfi_adjust_cfa_offset 8  @ CFA is now sp + previousOffset + 8
979	.cfi_rel_offset lr, 0     @ lr is at sp
980
981	ARM_CALL aeabi_cfrcmple
982	do_it	cc, e
983	movcc	r0, #1	@ Operand 2 is less than operand 1.
984	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
985			@ or they are unordered.
986	RETLDM
987
988	CFI_END_FUNCTION
989	FUNC_END aeabi_fcmpgt
990
991#endif /* L_cmpsf2 */
992
993#ifdef L_arm_unordsf2
994
995ARM_FUNC_START unordsf2
996ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
997	CFI_START_FUNCTION
998
999	mov	r2, r0, lsl #1
1000	mov	r3, r1, lsl #1
1001	mvns	ip, r2, asr #24
1002	bne	1f
1003	movs	ip, r0, lsl #9
1004	bne	3f			@ r0 is NAN
10051:	mvns	ip, r3, asr #24
1006	bne	2f
1007	movs	ip, r1, lsl #9
1008	bne	3f			@ r1 is NAN
10092:	mov	r0, #0			@ arguments are ordered.
1010	RET
10113:	mov	r0, #1			@ arguments are unordered.
1012	RET
1013
1014	CFI_END_FUNCTION
1015	FUNC_END aeabi_fcmpun
1016	FUNC_END unordsf2
1017
1018#endif /* L_unordsf2 */
1019
1020#ifdef L_arm_fixsfsi
1021
1022ARM_FUNC_START fixsfsi
1023ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
1024	CFI_START_FUNCTION
1025
1026	@ check exponent range.
1027	mov	r2, r0, lsl #1
1028	cmp	r2, #(127 << 24)
1029	bcc	1f			@ value is too small
1030	mov	r3, #(127 + 31)
1031	subs	r2, r3, r2, lsr #24
1032	bls	2f			@ value is too large
1033
1034	@ scale value
1035	mov	r3, r0, lsl #8
1036	orr	r3, r3, #0x80000000
1037	tst	r0, #0x80000000		@ the sign bit
1038	shift1	lsr, r0, r3, r2
1039	do_it	ne
1040	rsbne	r0, r0, #0
1041	RET
1042
10431:	mov	r0, #0
1044	RET
1045
10462:	cmp	r2, #(127 + 31 - 0xff)
1047	bne	3f
1048	movs	r2, r0, lsl #9
1049	bne	4f			@ r0 is NAN.
10503:	ands	r0, r0, #0x80000000	@ the sign bit
1051	do_it	eq
1052	moveq	r0, #0x7fffffff		@ the maximum signed positive si
1053	RET
1054
10554:	mov	r0, #0			@ What should we convert NAN to?
1056	RET
1057
1058	CFI_END_FUNCTION
1059	FUNC_END aeabi_f2iz
1060	FUNC_END fixsfsi
1061
1062#endif /* L_fixsfsi */
1063
1064#ifdef L_arm_fixunssfsi
1065
1066ARM_FUNC_START fixunssfsi
1067ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
1068	CFI_START_FUNCTION
1069
1070	@ check exponent range.
1071	movs	r2, r0, lsl #1
1072	bcs	1f			@ value is negative
1073	cmp	r2, #(127 << 24)
1074	bcc	1f			@ value is too small
1075	mov	r3, #(127 + 31)
1076	subs	r2, r3, r2, lsr #24
1077	bmi	2f			@ value is too large
1078
1079	@ scale the value
1080	mov	r3, r0, lsl #8
1081	orr	r3, r3, #0x80000000
1082	shift1	lsr, r0, r3, r2
1083	RET
1084
10851:	mov	r0, #0
1086	RET
1087
10882:	cmp	r2, #(127 + 31 - 0xff)
1089	bne	3f
1090	movs	r2, r0, lsl #9
1091	bne	4f			@ r0 is NAN.
10923:	mov	r0, #0xffffffff		@ maximum unsigned si
1093	RET
1094
10954:	mov	r0, #0			@ What should we convert NAN to?
1096	RET
1097
1098	CFI_END_FUNCTION
1099	FUNC_END aeabi_f2uiz
1100	FUNC_END fixunssfsi
1101
1102#endif /* L_fixunssfsi */
1103