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