]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/arm/ieee754-sf.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / ieee754-sf.S
1 /* ieee754-sf.S single-precision floating point support for ARM
2
3 Copyright (C) 2003-2016 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
41 ARM_FUNC_START negsf2
42 ARM_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
56 ARM_FUNC_START aeabi_frsub
57 CFI_START_FUNCTION
58
59 eor r0, r0, #0x80000000 @ flip sign bit of first arg
60 b 1f
61
62 ARM_FUNC_START subsf3
63 ARM_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
70 ARM_FUNC_START addsf3
71 ARM_FUNC_ALIAS aeabi_fadd addsf3
72
73 1: @ 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)
117 LSYM(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.
140 LSYM(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.
159 LSYM(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.
168 LSYM(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.
176 LSYM(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.
222 LSYM(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
231 LSYM(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
248 1: 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
262 2: 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.
269 LSYM(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)
280 LSYM(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
300 ARM_FUNC_START floatunsisf
301 ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
302 CFI_START_FUNCTION
303
304 mov r3, #0
305 b 1f
306
307 ARM_FUNC_START floatsisf
308 ARM_FUNC_ALIAS aeabi_i2f floatsisf
309
310 ands r3, r0, #0x80000000
311 do_it mi
312 rsbmi r0, r0, #0
313
314 1: 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
333 ARM_FUNC_START floatundisf
334 ARM_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
344 ARM_FUNC_START floatdisf
345 ARM_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
360 1:
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)
371 2: 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
413 3: 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
432 ARM_FUNC_START mulsf3
433 ARM_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)
444 LSYM(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.
522 LSYM(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
540 LSYM(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.
565 LSYM(Lml_d):
566 teq r2, #0
567 and ip, r0, #0x80000000
568 1: 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
576 2: 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
584 LSYM(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.
599 LSYM(Lml_z):
600 eor r0, r0, r1
601 bic r0, r0, #0x7fffffff
602 RET
603
604 1: @ 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
616 1: 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.
624 LSYM(Lml_i):
625 eor r0, r0, r1
626
627 @ Overflow: return INF (sign already in r0).
628 LSYM(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.
635 LSYM(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
644 ARM_FUNC_START divsf3
645 ARM_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)
656 LSYM(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
685 1: 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.
718 LSYM(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.
734 LSYM(Ldv_d):
735 teq r2, #0
736 and ip, r0, #0x80000000
737 1: 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
745 2: 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.
754 LSYM(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
764 1: 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
770 2: @ 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
805 ARM_FUNC_START gtsf2
806 ARM_FUNC_ALIAS gesf2 gtsf2
807 CFI_START_FUNCTION
808 mov ip, #-1
809 b 1f
810
811 ARM_FUNC_START ltsf2
812 ARM_FUNC_ALIAS lesf2 ltsf2
813 mov ip, #1
814 b 1f
815
816 ARM_FUNC_START cmpsf2
817 ARM_FUNC_ALIAS nesf2 cmpsf2
818 ARM_FUNC_ALIAS eqsf2 cmpsf2
819 mov ip, #1 @ how should we specify unordered here?
820
821 1: 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.
843 2: 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
861 3: @ 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
871 4: mvns ip, r3, asr #24
872 bne 2b
873 movs ip, r1, lsl #9
874 beq 2b @ r1 is not NAN
875
876 5: 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
889 ARM_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
897 ARM_FUNC_START aeabi_cfcmpeq
898 ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
899
900 @ The status-returning routines are required to preserve all
901 @ registers except ip, lr, and cpsr.
902 6: 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
924 ARM_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
940 ARM_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
956 ARM_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
972 ARM_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
988 ARM_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
1009 ARM_FUNC_START unordsf2
1010 ARM_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
1019 1: mvns ip, r3, asr #24
1020 bne 2f
1021 movs ip, r1, lsl #9
1022 bne 3f @ r1 is NAN
1023 2: mov r0, #0 @ arguments are ordered.
1024 RET
1025 3: 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
1036 ARM_FUNC_START fixsfsi
1037 ARM_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
1057 1: mov r0, #0
1058 RET
1059
1060 2: cmp r2, #(127 + 31 - 0xff)
1061 bne 3f
1062 movs r2, r0, lsl #9
1063 bne 4f @ r0 is NAN.
1064 3: ands r0, r0, #0x80000000 @ the sign bit
1065 do_it eq
1066 moveq r0, #0x7fffffff @ the maximum signed positive si
1067 RET
1068
1069 4: 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
1080 ARM_FUNC_START fixunssfsi
1081 ARM_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
1099 1: mov r0, #0
1100 RET
1101
1102 2: cmp r2, #(127 + 31 - 0xff)
1103 bne 3f
1104 movs r2, r0, lsl #9
1105 bne 4f @ r0 is NAN.
1106 3: mov r0, #0xffffffff @ maximum unsigned si
1107 RET
1108
1109 4: 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 */