]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/arm/ieee754-sf.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / ieee754-sf.S
CommitLineData
4202ce82
RE
1/* ieee754-sf.S single-precision floating point support for ARM
2
83ffe9cd 3 Copyright (C) 2003-2023 Free Software Foundation, Inc.
89fff9cc 4 Contributed by Nicolas Pitre (nico@fluxnic.net)
4202ce82
RE
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
748086b7 8 Free Software Foundation; either version 3, or (at your option) any
4202ce82
RE
9 later version.
10
4202ce82
RE
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
748086b7
JJ
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/>. */
4202ce82
RE
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.
ff935d0c
MG
34 *
35 * In the CFI related comments, 'previousOffset' refers to the previous offset
36 * from sp used to compute the CFA.
4202ce82
RE
37 */
38
bf98ec6c 39#ifdef L_arm_negsf2
4202ce82 40
496b84c8 41ARM_FUNC_START negsf2
b3f8d95d 42ARM_FUNC_ALIAS aeabi_fneg negsf2
ff935d0c 43 CFI_START_FUNCTION
6883a666 44
496b84c8
RE
45 eor r0, r0, #0x80000000 @ flip sign bit
46 RET
4202ce82 47
ff935d0c 48 CFI_END_FUNCTION
b3f8d95d 49 FUNC_END aeabi_fneg
496b84c8 50 FUNC_END negsf2
4202ce82 51
4202ce82
RE
52#endif
53
bf98ec6c 54#ifdef L_arm_addsubsf3
4202ce82 55
b3f8d95d 56ARM_FUNC_START aeabi_frsub
ff935d0c 57 CFI_START_FUNCTION
b3f8d95d
MM
58
59 eor r0, r0, #0x80000000 @ flip sign bit of first arg
6883a666
NP
60 b 1f
61
4202ce82 62ARM_FUNC_START subsf3
b3f8d95d 63ARM_FUNC_ALIAS aeabi_fsub subsf3
6883a666 64
4202ce82 65 eor r1, r1, #0x80000000 @ flip sign bit of second arg
4c5f9898 66#if defined(__INTERWORKING_STUBS__)
4202ce82
RE
67 b 1f @ Skip Thumb-code prologue
68#endif
69
70ARM_FUNC_START addsf3
b3f8d95d 71ARM_FUNC_ALIAS aeabi_fadd addsf3
4202ce82 72
6883a666
NP
731: @ Look for zeroes, equal values, INF, or NAN.
74 movs r2, r0, lsl #1
5b3e6663
PB
75 do_it ne, ttt
76 COND(mov,s,ne) r3, r1, lsl #1
6883a666 77 teqne r2, r3
5b3e6663
PB
78 COND(mvn,s,ne) ip, r2, asr #24
79 COND(mvn,s,ne) ip, r3, asr #24
6883a666 80 beq LSYM(Lad_s)
4202ce82
RE
81
82 @ Compute exponent difference. Make largest exponent in r2,
83 @ corresponding arg in r0, and positive exponent difference in r3.
6883a666
NP
84 mov r2, r2, lsr #24
85 rsbs r3, r2, r3, lsr #24
5b3e6663 86 do_it gt, ttt
4202ce82
RE
87 addgt r2, r2, r3
88 eorgt r1, r0, r1
89 eorgt r0, r1, r0
90 eorgt r1, r0, r1
5b3e6663 91 do_it lt
4202ce82
RE
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.
6883a666 97 cmp r3, #25
5b3e6663 98 do_it hi
4202ce82
RE
99 RETc(hi)
100
101 @ Convert mantissa to signed integer.
102 tst r0, #0x80000000
103 orr r0, r0, #0x00800000
104 bic r0, r0, #0xff000000
5b3e6663 105 do_it ne
4202ce82
RE
106 rsbne r0, r0, #0
107 tst r1, #0x80000000
108 orr r1, r1, #0x00800000
109 bic r1, r1, #0xff000000
5b3e6663 110 do_it ne
4202ce82
RE
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
6883a666
NP
119 @ Compensate for the exponent overlapping the mantissa MSB added later
120 sub r2, r2, #1
4202ce82 121
6883a666
NP
122 @ Shift and add second arg to first arg in r0.
123 @ Keep leftover bits into r1.
5b3e6663 124 shiftop adds r0 r0 r1 asr r3 ip
4202ce82 125 rsb r3, r3, #32
5b3e6663 126 shift1 lsl, r1, r1, r3
4202ce82 127
6883a666
NP
128 @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
129 and r3, r0, #0x80000000
4202ce82 130 bpl LSYM(Lad_p)
5b3e6663
PB
131#if defined(__thumb2__)
132 negs r1, r1
133 sbc r0, r0, r0, lsl #1
134#else
4202ce82
RE
135 rsbs r1, r1, #0
136 rsc r0, r0, #0
5b3e6663 137#endif
4202ce82
RE
138
139 @ Determine how to normalize the result.
140LSYM(Lad_p):
141 cmp r0, #0x00800000
6883a666 142 bcc LSYM(Lad_a)
4202ce82 143 cmp r0, #0x01000000
6883a666 144 bcc LSYM(Lad_e)
4202ce82
RE
145
146 @ Result needs to be shifted right.
147 movs r0, r0, lsr #1
148 mov r1, r1, rrx
6883a666 149 add r2, r2, #1
4202ce82
RE
150
151 @ Make sure we did not bust our exponent.
6883a666
NP
152 cmp r2, #254
153 bhs LSYM(Lad_o)
4202ce82 154
6883a666 155 @ Our result is now properly aligned into r0, remaining bits in r1.
4202ce82 156 @ Pack final result together.
6883a666
NP
157 @ Round with MSB of r1. If halfway between two numbers, round towards
158 @ LSB of r0 = 0.
4202ce82 159LSYM(Lad_e):
6883a666
NP
160 cmp r1, #0x80000000
161 adc r0, r0, r2, lsl #23
5b3e6663 162 do_it eq
6883a666 163 biceq r0, r0, #1
4202ce82
RE
164 orr r0, r0, r3
165 RET
166
6883a666
NP
167 @ Result must be shifted left and exponent adjusted.
168LSYM(Lad_a):
169 movs r1, r1, lsl #1
170 adc r0, r0, r0
89fff9cc
NP
171 subs r2, r2, #1
172 do_it hs
173 cmphs r0, #0x00800000
174 bhs LSYM(Lad_e)
175
6883a666 176 @ No rounding necessary since r1 will always be 0 at this point.
4202ce82
RE
177LSYM(Lad_l):
178
9b2e34ef 179#if !defined (__ARM_FEATURE_CLZ)
4202ce82
RE
180
181 movs ip, r0, lsr #12
182 moveq r0, r0, lsl #12
6883a666 183 subeq r2, r2, #12
4202ce82
RE
184 tst r0, #0x00ff0000
185 moveq r0, r0, lsl #8
6883a666 186 subeq r2, r2, #8
4202ce82
RE
187 tst r0, #0x00f00000
188 moveq r0, r0, lsl #4
6883a666 189 subeq r2, r2, #4
4202ce82
RE
190 tst r0, #0x00c00000
191 moveq r0, r0, lsl #2
6883a666
NP
192 subeq r2, r2, #2
193 cmp r0, #0x00800000
194 movcc r0, r0, lsl #1
195 sbcs r2, r2, #0
4202ce82
RE
196
197#else
198
199 clz ip, r0
200 sub ip, ip, #8
6883a666 201 subs r2, r2, ip
5b3e6663 202 shift1 lsl, r0, r0, ip
4202ce82
RE
203
204#endif
205
6883a666
NP
206 @ Final result with sign
207 @ If exponent negative, denormalize result.
5b3e6663 208 do_it ge, et
6883a666
NP
209 addge r0, r0, r2, lsl #23
210 rsblt r2, r2, #0
211 orrge r0, r0, r3
5b3e6663
PB
212#if defined(__thumb2__)
213 do_it lt, t
214 lsrlt r0, r0, r2
215 orrlt r0, r3, r0
216#else
6883a666 217 orrlt r0, r3, r0, lsr r2
5b3e6663 218#endif
4202ce82
RE
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
4202ce82 225 eor r1, r1, #0x00800000
5b3e6663 226 do_it eq, te
6883a666
NP
227 eoreq r0, r0, #0x00800000
228 addeq r2, r2, #1
229 subne r3, r3, #1
4202ce82
RE
230 b LSYM(Lad_x)
231
6883a666
NP
232LSYM(Lad_s):
233 mov r3, r1, lsl #1
234
235 mvns ip, r2, asr #24
5b3e6663
PB
236 do_it ne
237 COND(mvn,s,ne) ip, r3, asr #24
6883a666
NP
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
5b3e6663 245 do_it eq
6883a666
NP
246 moveq r0, r1
247 RET
248
2491: teq r0, r1
250
251 @ Result is x - x = 0.
5b3e6663 252 do_it ne, t
4202ce82 253 movne r0, #0
6883a666
NP
254 RETc(ne)
255
256 @ Result is x + x = 2x.
257 tst r2, #0xff000000
258 bne 2f
259 movs r0, r0, lsl #1
5b3e6663 260 do_it cs
6883a666 261 orrcs r0, r0, #0x80000000
4202ce82 262 RET
6883a666 2632: adds r2, r2, #(2 << 24)
5b3e6663 264 do_it cc, t
6883a666
NP
265 addcc r0, r0, #(1 << 23)
266 RETc(cc)
267 and r3, r0, #0x80000000
4202ce82
RE
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
6883a666 280 @ otherwise return r0 (which is INF or -INF)
4202ce82 281LSYM(Lad_i):
6883a666 282 mvns r2, r2, asr #24
5b3e6663 283 do_it ne, et
4202ce82 284 movne r0, r1
5b3e6663 285 COND(mvn,s,eq) r3, r3, asr #24
6883a666 286 movne r1, r0
4202ce82 287 movs r2, r0, lsl #9
5b3e6663
PB
288 do_it eq, te
289 COND(mov,s,eq) r3, r1, lsl #9
4202ce82 290 teqeq r0, r1
6883a666 291 orrne r0, r0, #0x00400000 @ quiet NAN
4202ce82
RE
292 RET
293
ff935d0c 294 CFI_END_FUNCTION
b3f8d95d
MM
295 FUNC_END aeabi_frsub
296 FUNC_END aeabi_fadd
496b84c8 297 FUNC_END addsf3
b3f8d95d 298 FUNC_END aeabi_fsub
496b84c8 299 FUNC_END subsf3
4202ce82
RE
300
301ARM_FUNC_START floatunsisf
b3f8d95d 302ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
ff935d0c 303 CFI_START_FUNCTION
b3f8d95d 304
4202ce82
RE
305 mov r3, #0
306 b 1f
307
308ARM_FUNC_START floatsisf
b3f8d95d
MM
309ARM_FUNC_ALIAS aeabi_i2f floatsisf
310
4202ce82 311 ands r3, r0, #0x80000000
5b3e6663 312 do_it mi
4202ce82
RE
313 rsbmi r0, r0, #0
314
6883a666 3151: movs ip, r0
5b3e6663 316 do_it eq
4202ce82
RE
317 RETc(eq)
318
6883a666
NP
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
4202ce82 327
ff935d0c 328 CFI_END_FUNCTION
b3f8d95d 329 FUNC_END aeabi_i2f
496b84c8 330 FUNC_END floatsisf
b3f8d95d 331 FUNC_END aeabi_ui2f
496b84c8
RE
332 FUNC_END floatunsisf
333
0a1aa867
RE
334ARM_FUNC_START floatundisf
335ARM_FUNC_ALIAS aeabi_ul2f floatundisf
ff935d0c 336 CFI_START_FUNCTION
6883a666 337
0a1aa867 338 orrs r2, r0, r1
5b3e6663 339 do_it eq
0a1aa867 340 RETc(eq)
0a1aa867
RE
341
342 mov r3, #0
6883a666 343 b 1f
0a1aa867
RE
344
345ARM_FUNC_START floatdisf
346ARM_FUNC_ALIAS aeabi_l2f floatdisf
347
348 orrs r2, r0, r1
5b3e6663 349 do_it eq
0a1aa867 350 RETc(eq)
6883a666
NP
351
352 ands r3, ah, #0x80000000 @ sign bit in r3
353 bpl 1f
5b3e6663
PB
354#if defined(__thumb2__)
355 negs al, al
356 sbc ah, ah, ah, lsl #1
357#else
6883a666
NP
358 rsbs al, al, #0
359 rsc ah, ah, #0
5b3e6663 360#endif
6883a666 3611:
0a1aa867 362 movs ip, ah
5b3e6663 363 do_it eq, tt
6883a666 364 moveq ip, al
3188a512
NP
365 moveq ah, al
366 moveq al, #0
6883a666
NP
367
368 @ Add initial exponent to sign
369 orr r3, r3, #((127 + 23 + 32) << 23)
5b3e6663 370 do_it eq
6883a666
NP
371 subeq r3, r3, #(32 << 23)
3722: sub r3, r3, #(1 << 23)
0a1aa867 373
9b2e34ef 374#if !defined (__ARM_FEATURE_CLZ)
6883a666
NP
375
376 mov r2, #23
377 cmp ip, #(1 << 16)
5b3e6663 378 do_it hs, t
6883a666
NP
379 movhs ip, ip, lsr #16
380 subhs r2, r2, #16
381 cmp ip, #(1 << 8)
5b3e6663 382 do_it hs, t
6883a666
NP
383 movhs ip, ip, lsr #8
384 subhs r2, r2, #8
385 cmp ip, #(1 << 4)
5b3e6663 386 do_it hs, t
6883a666
NP
387 movhs ip, ip, lsr #4
388 subhs r2, r2, #4
389 cmp ip, #(1 << 2)
5b3e6663 390 do_it hs, e
6883a666
NP
391 subhs r2, r2, #2
392 sublo r2, r2, ip, lsr #1
393 subs r2, r2, ip, lsr #3
394
0a1aa867 395#else
6883a666
NP
396
397 clz r2, ip
398 subs r2, r2, #8
399
0a1aa867 400#endif
6883a666
NP
401
402 sub r3, r3, r2, lsl #23
403 blt 3f
404
5b3e6663
PB
405 shiftop add r3 r3 ah lsl r2 ip
406 shift1 lsl, ip, al, r2
6883a666
NP
407 rsb r2, r2, #32
408 cmp ip, #0x80000000
5b3e6663
PB
409 shiftop adc r0 r3 al lsr r2 r2
410 do_it eq
6883a666
NP
411 biceq r0, r0, #1
412 RET
413
4143: add r2, r2, #32
5b3e6663 415 shift1 lsl, ip, ah, r2
6883a666
NP
416 rsb r2, r2, #32
417 orrs al, al, ip, lsl #1
5b3e6663
PB
418 shiftop adc r0 r3 ah lsr r2 r2
419 do_it eq
6883a666
NP
420 biceq r0, r0, ip, lsr #31
421 RET
422
ff935d0c 423 CFI_END_FUNCTION
0a1aa867
RE
424 FUNC_END floatdisf
425 FUNC_END aeabi_l2f
426 FUNC_END floatundisf
427 FUNC_END aeabi_ul2f
428
496b84c8
RE
429#endif /* L_addsubsf3 */
430
72e3a529
TP
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
4202ce82
RE
443
444ARM_FUNC_START mulsf3
b3f8d95d 445ARM_FUNC_ALIAS aeabi_fmul mulsf3
ff935d0c 446 CFI_START_FUNCTION
4202ce82 447
6883a666
NP
448 @ Mask out exponents, trap any zero/denormal/INF/NAN.
449 mov ip, #0xff
450 ands r2, ip, r0, lsr #23
5b3e6663
PB
451 do_it ne, tt
452 COND(and,s,ne) r3, ip, r1, lsr #23
6883a666
NP
453 teqne r2, ip
454 teqne r3, ip
455 beq LSYM(Lml_s)
4202ce82 456LSYM(Lml_x):
4202ce82 457
6883a666
NP
458 @ Add exponents together
459 add r2, r2, r3
460
461 @ Determine final sign.
462 eor ip, r0, r1
4202ce82
RE
463
464 @ Convert mantissa to unsigned integer.
6883a666
NP
465 @ If power of two, branch to a separate path.
466 @ Make up for final alignment.
467 movs r0, r0, lsl #9
5b3e6663
PB
468 do_it ne
469 COND(mov,s,ne) r1, r1, lsl #9
6883a666
NP
470 beq LSYM(Lml_1)
471 mov r3, #0x08000000
472 orr r0, r3, r0, lsr #5
473 orr r1, r3, r1, lsr #5
4202ce82 474
6883a666 475 @ The actual multiplication.
b7415975 476 @ This code works on architecture versions >= 4
6883a666
NP
477 umull r3, r1, r0, r1
478
479 @ Put final sign in r0.
480 and r0, ip, #0x80000000
4202ce82 481
6883a666
NP
482 @ Adjust result upon the MSB position.
483 cmp r1, #(1 << 23)
5b3e6663 484 do_it cc, tt
6883a666
NP
485 movcc r1, r1, lsl #1
486 orrcc r1, r1, r3, lsr #31
487 movcc r3, r3, lsl #1
4202ce82 488
6883a666
NP
489 @ Add sign to result.
490 orr r0, r0, r1
4202ce82 491
6883a666
NP
492 @ Apply exponent bias, check for under/overflow.
493 sbc r2, r2, #127
494 cmp r2, #(254 - 1)
495 bhi LSYM(Lml_u)
4202ce82 496
6883a666
NP
497 @ Round the result, merge final exponent.
498 cmp r3, #0x80000000
499 adc r0, r0, r2, lsl #23
5b3e6663 500 do_it eq
6883a666 501 biceq r0, r0, #1
4202ce82
RE
502 RET
503
6883a666
NP
504 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
505LSYM(Lml_1):
506 teq r0, #0
507 and ip, ip, #0x80000000
5b3e6663 508 do_it eq
6883a666
NP
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
5b3e6663
PB
513 do_it gt, tt
514 COND(rsb,s,gt) r3, r2, #255
6883a666
NP
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
4202ce82 522
4202ce82 523LSYM(Lml_u):
6883a666
NP
524 @ Overflow?
525 bgt LSYM(Lml_o)
4202ce82 526
6883a666
NP
527 @ Check if denormalized result is possible, otherwise return signed 0.
528 cmn r2, #(24 + 1)
5b3e6663 529 do_it le, t
6883a666
NP
530 bicle r0, r0, #0x7fffffff
531 RETc(le)
4202ce82
RE
532
533 @ Shift value right, round, etc.
6883a666
NP
534 rsb r2, r2, #0
535 movs r1, r0, lsl #1
5b3e6663 536 shift1 lsr, r1, r1, r2
6883a666 537 rsb r2, r2, #32
5b3e6663 538 shift1 lsl, ip, r0, r2
6883a666 539 movs r0, r1, rrx
4202ce82 540 adc r0, r0, #0
6883a666 541 orrs r3, r3, ip, lsl #1
5b3e6663 542 do_it eq
6883a666 543 biceq r0, r0, ip, lsr #31
4202ce82
RE
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
5b3e6663
PB
5511: do_it eq, tt
552 moveq r0, r0, lsl #1
4202ce82 553 tsteq r0, #0x00800000
6883a666 554 subeq r2, r2, #1
4202ce82
RE
555 beq 1b
556 orr r0, r0, ip
557 teq r3, #0
558 and ip, r1, #0x80000000
5b3e6663
PB
5592: do_it eq, tt
560 moveq r1, r1, lsl #1
4202ce82 561 tsteq r1, #0x00800000
6883a666 562 subeq r3, r3, #1
4202ce82
RE
563 beq 2b
564 orr r1, r1, ip
565 b LSYM(Lml_x)
566
4202ce82 567LSYM(Lml_s):
6883a666
NP
568 @ Isolate the INF and NAN cases away
569 and r3, ip, r1, lsr #23
570 teq r2, ip
5b3e6663 571 do_it ne
6883a666
NP
572 teqne r3, ip
573 beq 1f
574
575 @ Here, one or more arguments are either denormalized or zero.
576 bics ip, r0, #0x80000000
5b3e6663
PB
577 do_it ne
578 COND(bic,s,ne) ip, r1, #0x80000000
6883a666
NP
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.
4202ce82 588 teq r0, #0x0
5b3e6663 589 do_it ne, ett
4202ce82 590 teqne r0, #0x80000000
6883a666
NP
591 moveq r0, r1
592 teqne r1, #0x0
4202ce82
RE
593 teqne r1, #0x80000000
594 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
6883a666 595 teq r2, ip
4202ce82
RE
596 bne 1f
597 movs r2, r0, lsl #9
598 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
6883a666 5991: teq r3, ip
4202ce82
RE
600 bne LSYM(Lml_i)
601 movs r3, r1, lsl #9
5b3e6663 602 do_it ne
6883a666 603 movne r0, r1
4202ce82
RE
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
6883a666 617 @ Return a quiet NAN.
4202ce82 618LSYM(Lml_n):
6883a666 619 orr r0, r0, #0x7f000000
4202ce82
RE
620 orr r0, r0, #0x00c00000
621 RET
622
ff935d0c 623 CFI_END_FUNCTION
b3f8d95d 624 FUNC_END aeabi_fmul
496b84c8 625 FUNC_END mulsf3
4202ce82 626
72e3a529
TP
627#ifdef L_arm_muldivsf3
628
4202ce82 629ARM_FUNC_START divsf3
b3f8d95d 630ARM_FUNC_ALIAS aeabi_fdiv divsf3
ff935d0c 631 CFI_START_FUNCTION
4202ce82 632
6883a666
NP
633 @ Mask out exponents, trap any zero/denormal/INF/NAN.
634 mov ip, #0xff
635 ands r2, ip, r0, lsr #23
5b3e6663
PB
636 do_it ne, tt
637 COND(and,s,ne) r3, ip, r1, lsr #23
6883a666
NP
638 teqne r2, ip
639 teqne r3, ip
640 beq LSYM(Ldv_s)
4202ce82 641LSYM(Ldv_x):
6883a666 642
d8c9d391 643 @ Subtract divisor exponent from dividend''s
6883a666 644 sub r2, r2, r3
4202ce82
RE
645
646 @ Preserve final sign into ip.
647 eor ip, r0, r1
648
649 @ Convert mantissa to unsigned integer.
650 @ Dividend -> r3, divisor -> r1.
4202ce82
RE
651 movs r1, r1, lsl #9
652 mov r0, r0, lsl #9
653 beq LSYM(Ldv_1)
6883a666 654 mov r3, #0x10000000
4202ce82
RE
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.
6883a666 662 @ Apply exponent bias accordingly.
4202ce82 663 cmp r3, r1
5b3e6663 664 do_it cc
4202ce82 665 movcc r3, r3, lsl #1
6883a666 666 adc r2, r2, #(127 - 2)
4202ce82
RE
667
668 @ The actual division loop.
669 mov ip, #0x00800000
6701: cmp r3, r1
5b3e6663 671 do_it cs, t
4202ce82
RE
672 subcs r3, r3, r1
673 orrcs r0, r0, ip
674 cmp r3, r1, lsr #1
5b3e6663 675 do_it cs, t
4202ce82
RE
676 subcs r3, r3, r1, lsr #1
677 orrcs r0, r0, ip, lsr #1
678 cmp r3, r1, lsr #2
5b3e6663 679 do_it cs, t
4202ce82
RE
680 subcs r3, r3, r1, lsr #2
681 orrcs r0, r0, ip, lsr #2
682 cmp r3, r1, lsr #3
5b3e6663 683 do_it cs, t
4202ce82
RE
684 subcs r3, r3, r1, lsr #3
685 orrcs r0, r0, ip, lsr #3
686 movs r3, r3, lsl #4
5b3e6663
PB
687 do_it ne
688 COND(mov,s,ne) ip, ip, lsr #4
4202ce82
RE
689 bne 1b
690
6883a666
NP
691 @ Check exponent for under/overflow.
692 cmp r2, #(254 - 1)
693 bhi LSYM(Lml_u)
4202ce82 694
6883a666 695 @ Round the result, merge final exponent.
4202ce82 696 cmp r3, r1
6883a666 697 adc r0, r0, r2, lsl #23
5b3e6663 698 do_it eq
4202ce82 699 biceq r0, r0, #1
4202ce82
RE
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
6883a666 706 adds r2, r2, #127
5b3e6663
PB
707 do_it gt, tt
708 COND(rsb,s,gt) r3, r2, #255
6883a666 709 orrgt r0, r0, r2, lsl #23
4202ce82 710 RETc(gt)
6883a666 711
4202ce82
RE
712 orr r0, r0, #0x00800000
713 mov r3, #0
6883a666
NP
714 subs r2, r2, #1
715 b LSYM(Lml_u)
4202ce82
RE
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
5b3e6663
PB
7221: do_it eq, tt
723 moveq r0, r0, lsl #1
4202ce82 724 tsteq r0, #0x00800000
6883a666 725 subeq r2, r2, #1
4202ce82
RE
726 beq 1b
727 orr r0, r0, ip
728 teq r3, #0
729 and ip, r1, #0x80000000
5b3e6663
PB
7302: do_it eq, tt
731 moveq r1, r1, lsl #1
4202ce82 732 tsteq r1, #0x00800000
6883a666 733 subeq r3, r3, #1
4202ce82
RE
734 beq 2b
735 orr r1, r1, ip
736 b LSYM(Ldv_x)
737
6883a666 738 @ One or both arguments are either INF, NAN, zero or denormalized.
4202ce82 739LSYM(Ldv_s):
6883a666
NP
740 and r3, ip, r1, lsr #23
741 teq r2, ip
4202ce82
RE
742 bne 1f
743 movs r2, r0, lsl #9
744 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
6883a666
NP
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
4202ce82
RE
750 bne 2f
751 movs r3, r1, lsl #9
6883a666
NP
752 beq LSYM(Lml_z) @ <anything> / INF -> 0
753 mov r0, r1
754 b LSYM(Lml_n) @ <anything> / NAN -> NAN
a4d05547 7552: @ If both are nonzero, we need to normalize and resume above.
6883a666 756 bics ip, r0, #0x80000000
5b3e6663
PB
757 do_it ne
758 COND(bic,s,ne) ip, r1, #0x80000000
6883a666
NP
759 bne LSYM(Ldv_d)
760 @ One or both arguments are zero.
4202ce82
RE
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
ff935d0c 767 CFI_END_FUNCTION
b3f8d95d 768 FUNC_END aeabi_fdiv
496b84c8
RE
769 FUNC_END divsf3
770
771#endif /* L_muldivsf3 */
72e3a529 772#endif /* L_arm_mulsf3 || L_arm_muldivsf3 */
496b84c8 773
bf98ec6c 774#ifdef L_arm_cmpsf2
4202ce82 775
b3f8d95d
MM
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
4202ce82 791ARM_FUNC_START gtsf2
46049cff 792ARM_FUNC_ALIAS gesf2 gtsf2
ff935d0c 793 CFI_START_FUNCTION
6883a666 794 mov ip, #-1
4202ce82
RE
795 b 1f
796
4202ce82 797ARM_FUNC_START ltsf2
46049cff 798ARM_FUNC_ALIAS lesf2 ltsf2
6883a666 799 mov ip, #1
4202ce82
RE
800 b 1f
801
4202ce82 802ARM_FUNC_START cmpsf2
46049cff
RE
803ARM_FUNC_ALIAS nesf2 cmpsf2
804ARM_FUNC_ALIAS eqsf2 cmpsf2
6883a666
NP
805 mov ip, #1 @ how should we specify unordered here?
806
b89f8e3c 8071: str ip, [sp, #-4]!
ff935d0c
MG
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).
6883a666
NP
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
5b3e6663
PB
817 do_it ne
818 COND(mvn,s,ne) ip, r3, asr #24
4202ce82 819 beq 3f
ff935d0c
MG
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.
4202ce82 826
6883a666
NP
827 @ Compare values.
828 @ Note that 0.0 is equal to -0.0.
b89f8e3c 8292: add sp, sp, #4
ff935d0c
MG
830 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
831
b89f8e3c 832 orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag
5b3e6663 833 do_it ne
6883a666 834 teqne r0, r1 @ if not 0 compare sign
5b3e6663
PB
835 do_it pl
836 COND(sub,s,pl) r0, r2, r3 @ if same sign compare values, set r0
4202ce82 837
6883a666 838 @ Result:
5b3e6663 839 do_it hi
6883a666 840 movhi r0, r1, asr #31
5b3e6663 841 do_it lo
6883a666 842 mvnlo r0, r1, asr #31
5b3e6663 843 do_it ne
6883a666 844 orrne r0, r0, #1
4202ce82
RE
845 RET
846
ff935d0c
MG
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
4202ce82 854 bne 4f
4202ce82 855 movs ip, r0, lsl #9
6883a666
NP
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
ff935d0c 861
b89f8e3c 8625: ldr r0, [sp], #4 @ return unordered code.
ff935d0c 863 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
4202ce82
RE
864 RET
865
ff935d0c 866 CFI_END_FUNCTION
496b84c8
RE
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
b3f8d95d 875ARM_FUNC_START aeabi_cfrcmple
ff935d0c 876 CFI_START_FUNCTION
6883a666 877
b3f8d95d
MM
878 mov ip, r0
879 mov r0, r1
880 mov r1, ip
881 b 6f
6883a666 882
b3f8d95d
MM
883ARM_FUNC_START aeabi_cfcmpeq
884ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
6883a666 885
b3f8d95d
MM
886 @ The status-returning routines are required to preserve all
887 @ registers except ip, lr, and cpsr.
5b3e6663 8886: do_push {r0, r1, r2, r3, lr}
ff935d0c
MG
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
b3f8d95d
MM
896 ARM_CALL cmpsf2
897 @ Set the Z flag correctly, and the C flag unconditionally.
5b3e6663 898 cmp r0, #0
b3f8d95d
MM
899 @ Clear the C flag if the return value was -1, indicating
900 @ that the first operand was smaller than the second.
5b3e6663
PB
901 do_it mi
902 cmnmi r0, #0
903 RETLDM "r0, r1, r2, r3"
6883a666 904
ff935d0c 905 CFI_END_FUNCTION
b3f8d95d
MM
906 FUNC_END aeabi_cfcmple
907 FUNC_END aeabi_cfcmpeq
6883a666
NP
908 FUNC_END aeabi_cfrcmple
909
b3f8d95d 910ARM_FUNC_START aeabi_fcmpeq
ff935d0c
MG
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
6883a666 916
b3f8d95d 917 ARM_CALL aeabi_cfcmple
5b3e6663 918 do_it eq, e
b3f8d95d
MM
919 moveq r0, #1 @ Equal to.
920 movne r0, #0 @ Less than, greater than, or unordered.
921 RETLDM
6883a666 922
ff935d0c 923 CFI_END_FUNCTION
b3f8d95d
MM
924 FUNC_END aeabi_fcmpeq
925
926ARM_FUNC_START aeabi_fcmplt
ff935d0c
MG
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
6883a666 932
b3f8d95d 933 ARM_CALL aeabi_cfcmple
5b3e6663 934 do_it cc, e
b3f8d95d
MM
935 movcc r0, #1 @ Less than.
936 movcs r0, #0 @ Equal to, greater than, or unordered.
937 RETLDM
6883a666 938
ff935d0c 939 CFI_END_FUNCTION
b3f8d95d
MM
940 FUNC_END aeabi_fcmplt
941
942ARM_FUNC_START aeabi_fcmple
ff935d0c
MG
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
6883a666 948
b3f8d95d 949 ARM_CALL aeabi_cfcmple
5b3e6663 950 do_it ls, e
b3f8d95d
MM
951 movls r0, #1 @ Less than or equal to.
952 movhi r0, #0 @ Greater than or unordered.
953 RETLDM
6883a666 954
ff935d0c 955 CFI_END_FUNCTION
b3f8d95d
MM
956 FUNC_END aeabi_fcmple
957
958ARM_FUNC_START aeabi_fcmpge
ff935d0c
MG
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
6883a666 964
b3f8d95d 965 ARM_CALL aeabi_cfrcmple
5b3e6663 966 do_it ls, e
b3f8d95d
MM
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
6883a666 970
ff935d0c 971 CFI_END_FUNCTION
b3f8d95d
MM
972 FUNC_END aeabi_fcmpge
973
974ARM_FUNC_START aeabi_fcmpgt
ff935d0c
MG
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
6883a666 980
b3f8d95d 981 ARM_CALL aeabi_cfrcmple
5b3e6663 982 do_it cc, e
b3f8d95d
MM
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
6883a666 987
ff935d0c 988 CFI_END_FUNCTION
b3f8d95d 989 FUNC_END aeabi_fcmpgt
6883a666 990
496b84c8
RE
991#endif /* L_cmpsf2 */
992
bf98ec6c 993#ifdef L_arm_unordsf2
4202ce82
RE
994
995ARM_FUNC_START unordsf2
b3f8d95d 996ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
ff935d0c 997 CFI_START_FUNCTION
6883a666
NP
998
999 mov r2, r0, lsl #1
1000 mov r3, r1, lsl #1
1001 mvns ip, r2, asr #24
4202ce82 1002 bne 1f
6883a666 1003 movs ip, r0, lsl #9
4202ce82 1004 bne 3f @ r0 is NAN
6883a666
NP
10051: mvns ip, r3, asr #24
1006 bne 2f
1007 movs ip, r1, lsl #9
1008 bne 3f @ r1 is NAN
4202ce82
RE
10092: mov r0, #0 @ arguments are ordered.
1010 RET
10113: mov r0, #1 @ arguments are unordered.
1012 RET
1013
ff935d0c 1014 CFI_END_FUNCTION
b3f8d95d 1015 FUNC_END aeabi_fcmpun
496b84c8
RE
1016 FUNC_END unordsf2
1017
1018#endif /* L_unordsf2 */
1019
bf98ec6c 1020#ifdef L_arm_fixsfsi
4202ce82
RE
1021
1022ARM_FUNC_START fixsfsi
b3f8d95d 1023ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
ff935d0c 1024 CFI_START_FUNCTION
4202ce82
RE
1025
1026 @ check exponent range.
6883a666 1027 mov r2, r0, lsl #1
4202ce82 1028 cmp r2, #(127 << 24)
6883a666
NP
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
5b3e6663
PB
1038 shift1 lsr, r0, r3, r2
1039 do_it ne
4202ce82
RE
1040 rsbne r0, r0, #0
1041 RET
1042
6883a666
NP
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
5b3e6663 1051 do_it eq
4202ce82 1052 moveq r0, #0x7fffffff @ the maximum signed positive si
4202ce82
RE
1053 RET
1054
6883a666 10554: mov r0, #0 @ What should we convert NAN to?
4202ce82
RE
1056 RET
1057
ff935d0c 1058 CFI_END_FUNCTION
b3f8d95d 1059 FUNC_END aeabi_f2iz
496b84c8
RE
1060 FUNC_END fixsfsi
1061
1062#endif /* L_fixsfsi */
1063
bf98ec6c 1064#ifdef L_arm_fixunssfsi
4202ce82
RE
1065
1066ARM_FUNC_START fixunssfsi
b3f8d95d 1067ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
ff935d0c 1068 CFI_START_FUNCTION
4202ce82
RE
1069
1070 @ check exponent range.
6883a666
NP
1071 movs r2, r0, lsl #1
1072 bcs 1f @ value is negative
4202ce82 1073 cmp r2, #(127 << 24)
6883a666
NP
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
5b3e6663 1082 shift1 lsr, r0, r3, r2
6883a666 1083 RET
4202ce82 1084
6883a666 10851: mov r0, #0
4202ce82
RE
1086 RET
1087
6883a666
NP
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
4202ce82
RE
1093 RET
1094
6883a666 10954: mov r0, #0 @ What should we convert NAN to?
496b84c8
RE
1096 RET
1097
ff935d0c 1098 CFI_END_FUNCTION
b3f8d95d 1099 FUNC_END aeabi_f2uiz
496b84c8 1100 FUNC_END fixunssfsi
4202ce82 1101
496b84c8 1102#endif /* L_fixunssfsi */