]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/arm/ieee754-df.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / ieee754-df.S
1 /* ieee754-df.S double-precision floating point support for ARM
2
3 Copyright (C) 2003-2020 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 * For slightly simpler code please see the single precision version
31 * of this file.
32 *
33 * Only the default rounding mode is intended for best performances.
34 * Exceptions aren't supported yet, but that can be added quite easily
35 * if necessary without impacting performances.
36 *
37 * In the CFI related comments, 'previousOffset' refers to the previous offset
38 * from sp used to compute the CFA.
39 */
40
41 .cfi_sections .debug_frame
42
43 #ifndef __ARMEB__
44 #define xl r0
45 #define xh r1
46 #define yl r2
47 #define yh r3
48 #else
49 #define xh r0
50 #define xl r1
51 #define yh r2
52 #define yl r3
53 #endif
54
55
56 #ifdef L_arm_negdf2
57
58 ARM_FUNC_START negdf2
59 ARM_FUNC_ALIAS aeabi_dneg negdf2
60 CFI_START_FUNCTION
61
62 @ flip sign bit
63 eor xh, xh, #0x80000000
64 RET
65
66 CFI_END_FUNCTION
67 FUNC_END aeabi_dneg
68 FUNC_END negdf2
69
70 #endif
71
72 #ifdef L_arm_addsubdf3
73
74 ARM_FUNC_START aeabi_drsub
75 CFI_START_FUNCTION
76
77 eor xh, xh, #0x80000000 @ flip sign bit of first arg
78 b 1f
79
80 ARM_FUNC_START subdf3
81 ARM_FUNC_ALIAS aeabi_dsub subdf3
82
83 eor yh, yh, #0x80000000 @ flip sign bit of second arg
84 #if defined(__INTERWORKING_STUBS__)
85 b 1f @ Skip Thumb-code prologue
86 #endif
87
88 ARM_FUNC_START adddf3
89 ARM_FUNC_ALIAS aeabi_dadd adddf3
90
91 1: do_push {r4, r5, lr} @ sp -= 12
92 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
93 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 8
94 .cfi_rel_offset r5, 4
95 .cfi_rel_offset lr, 8
96
97 @ Look for zeroes, equal values, INF, or NAN.
98 shift1 lsl, r4, xh, #1
99 shift1 lsl, r5, yh, #1
100 teq r4, r5
101 do_it eq
102 teqeq xl, yl
103 do_it ne, ttt
104 COND(orr,s,ne) ip, r4, xl
105 COND(orr,s,ne) ip, r5, yl
106 COND(mvn,s,ne) ip, r4, asr #21
107 COND(mvn,s,ne) ip, r5, asr #21
108 beq LSYM(Lad_s)
109
110 @ Compute exponent difference. Make largest exponent in r4,
111 @ corresponding arg in xh-xl, and positive exponent difference in r5.
112 shift1 lsr, r4, r4, #21
113 rsbs r5, r4, r5, lsr #21
114 do_it lt
115 rsblt r5, r5, #0
116 ble 1f
117 add r4, r4, r5
118 eor yl, xl, yl
119 eor yh, xh, yh
120 eor xl, yl, xl
121 eor xh, yh, xh
122 eor yl, xl, yl
123 eor yh, xh, yh
124 1:
125 @ If exponent difference is too large, return largest argument
126 @ already in xh-xl. We need up to 54 bit to handle proper rounding
127 @ of 0x1p54 - 1.1.
128 cmp r5, #54
129 do_it hi
130 RETLDM "r4, r5" hi
131
132 @ Convert mantissa to signed integer.
133 tst xh, #0x80000000
134 mov xh, xh, lsl #12
135 mov ip, #0x00100000
136 orr xh, ip, xh, lsr #12
137 beq 1f
138 #if defined(__thumb2__)
139 negs xl, xl
140 sbc xh, xh, xh, lsl #1
141 #else
142 rsbs xl, xl, #0
143 rsc xh, xh, #0
144 #endif
145 1:
146 tst yh, #0x80000000
147 mov yh, yh, lsl #12
148 orr yh, ip, yh, lsr #12
149 beq 1f
150 #if defined(__thumb2__)
151 negs yl, yl
152 sbc yh, yh, yh, lsl #1
153 #else
154 rsbs yl, yl, #0
155 rsc yh, yh, #0
156 #endif
157 1:
158 @ If exponent == difference, one or both args were denormalized.
159 @ Since this is not common case, rescale them off line.
160 teq r4, r5
161 beq LSYM(Lad_d)
162
163 @ CFI note: we're lucky that the branches to Lad_* that appear after this
164 @ function have a CFI state that's exactly the same as the one we're in at this
165 @ point. Otherwise the CFI would change to a different state after the branch,
166 @ which would be disastrous for backtracing.
167 LSYM(Lad_x):
168
169 @ Compensate for the exponent overlapping the mantissa MSB added later
170 sub r4, r4, #1
171
172 @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
173 rsbs lr, r5, #32
174 blt 1f
175 shift1 lsl, ip, yl, lr
176 shiftop adds xl xl yl lsr r5 yl
177 adc xh, xh, #0
178 shiftop adds xl xl yh lsl lr yl
179 shiftop adcs xh xh yh asr r5 yh
180 b 2f
181 1: sub r5, r5, #32
182 add lr, lr, #32
183 cmp yl, #1
184 shift1 lsl,ip, yh, lr
185 do_it cs
186 orrcs ip, ip, #2 @ 2 not 1, to allow lsr #1 later
187 shiftop adds xl xl yh asr r5 yh
188 adcs xh, xh, yh, asr #31
189 2:
190 @ We now have a result in xh-xl-ip.
191 @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
192 and r5, xh, #0x80000000
193 bpl LSYM(Lad_p)
194 #if defined(__thumb2__)
195 mov lr, #0
196 negs ip, ip
197 sbcs xl, lr, xl
198 sbc xh, lr, xh
199 #else
200 rsbs ip, ip, #0
201 rscs xl, xl, #0
202 rsc xh, xh, #0
203 #endif
204
205 @ Determine how to normalize the result.
206 LSYM(Lad_p):
207 cmp xh, #0x00100000
208 bcc LSYM(Lad_a)
209 cmp xh, #0x00200000
210 bcc LSYM(Lad_e)
211
212 @ Result needs to be shifted right.
213 movs xh, xh, lsr #1
214 movs xl, xl, rrx
215 mov ip, ip, rrx
216 add r4, r4, #1
217
218 @ Make sure we did not bust our exponent.
219 mov r2, r4, lsl #21
220 cmn r2, #(2 << 21)
221 bcs LSYM(Lad_o)
222
223 @ Our result is now properly aligned into xh-xl, remaining bits in ip.
224 @ Round with MSB of ip. If halfway between two numbers, round towards
225 @ LSB of xl = 0.
226 @ Pack final result together.
227 LSYM(Lad_e):
228 cmp ip, #0x80000000
229 do_it eq
230 COND(mov,s,eq) ip, xl, lsr #1
231 adcs xl, xl, #0
232 adc xh, xh, r4, lsl #20
233 orr xh, xh, r5
234 RETLDM "r4, r5"
235
236 @ Result must be shifted left and exponent adjusted.
237 LSYM(Lad_a):
238 movs ip, ip, lsl #1
239 adcs xl, xl, xl
240 adc xh, xh, xh
241 subs r4, r4, #1
242 do_it hs
243 cmphs xh, #0x00100000
244 bhs LSYM(Lad_e)
245
246 @ No rounding necessary since ip will always be 0 at this point.
247 LSYM(Lad_l):
248
249 #if !defined (__ARM_FEATURE_CLZ)
250
251 teq xh, #0
252 movne r3, #20
253 moveq r3, #52
254 moveq xh, xl
255 moveq xl, #0
256 mov r2, xh
257 cmp r2, #(1 << 16)
258 movhs r2, r2, lsr #16
259 subhs r3, r3, #16
260 cmp r2, #(1 << 8)
261 movhs r2, r2, lsr #8
262 subhs r3, r3, #8
263 cmp r2, #(1 << 4)
264 movhs r2, r2, lsr #4
265 subhs r3, r3, #4
266 cmp r2, #(1 << 2)
267 subhs r3, r3, #2
268 sublo r3, r3, r2, lsr #1
269 sub r3, r3, r2, lsr #3
270
271 #else
272
273 teq xh, #0
274 do_it eq, t
275 moveq xh, xl
276 moveq xl, #0
277 clz r3, xh
278 do_it eq
279 addeq r3, r3, #32
280 sub r3, r3, #11
281
282 #endif
283
284 @ determine how to shift the value.
285 subs r2, r3, #32
286 bge 2f
287 adds r2, r2, #12
288 ble 1f
289
290 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
291 @ since a register switch happened above.
292 add ip, r2, #20
293 rsb r2, r2, #12
294 shift1 lsl, xl, xh, ip
295 shift1 lsr, xh, xh, r2
296 b 3f
297
298 @ actually shift value left 1 to 20 bits, which might also represent
299 @ 32 to 52 bits if counting the register switch that happened earlier.
300 1: add r2, r2, #20
301 2: do_it le
302 rsble ip, r2, #32
303 shift1 lsl, xh, xh, r2
304 #if defined(__thumb2__)
305 lsr ip, xl, ip
306 itt le
307 orrle xh, xh, ip
308 lslle xl, xl, r2
309 #else
310 orrle xh, xh, xl, lsr ip
311 movle xl, xl, lsl r2
312 #endif
313
314 @ adjust exponent accordingly.
315 3: subs r4, r4, r3
316 do_it ge, tt
317 addge xh, xh, r4, lsl #20
318 orrge xh, xh, r5
319 RETLDM "r4, r5" ge
320
321 @ Exponent too small, denormalize result.
322 @ Find out proper shift value.
323 mvn r4, r4
324 subs r4, r4, #31
325 bge 2f
326 adds r4, r4, #12
327 bgt 1f
328
329 @ shift result right of 1 to 20 bits, sign is in r5.
330 add r4, r4, #20
331 rsb r2, r4, #32
332 shift1 lsr, xl, xl, r4
333 shiftop orr xl xl xh lsl r2 yh
334 shiftop orr xh r5 xh lsr r4 yh
335 RETLDM "r4, r5"
336
337 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
338 @ a register switch from xh to xl.
339 1: rsb r4, r4, #12
340 rsb r2, r4, #32
341 shift1 lsr, xl, xl, r2
342 shiftop orr xl xl xh lsl r4 yh
343 mov xh, r5
344 RETLDM "r4, r5"
345
346 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
347 @ from xh to xl.
348 2: shift1 lsr, xl, xh, r4
349 mov xh, r5
350 RETLDM "r4, r5"
351
352 @ Adjust exponents for denormalized arguments.
353 @ Note that r4 must not remain equal to 0.
354 LSYM(Lad_d):
355 teq r4, #0
356 eor yh, yh, #0x00100000
357 do_it eq, te
358 eoreq xh, xh, #0x00100000
359 addeq r4, r4, #1
360 subne r5, r5, #1
361 b LSYM(Lad_x)
362
363
364 LSYM(Lad_s):
365 mvns ip, r4, asr #21
366 do_it ne
367 COND(mvn,s,ne) ip, r5, asr #21
368 beq LSYM(Lad_i)
369
370 teq r4, r5
371 do_it eq
372 teqeq xl, yl
373 beq 1f
374
375 @ Result is x + 0.0 = x or 0.0 + y = y.
376 orrs ip, r4, xl
377 do_it eq, t
378 moveq xh, yh
379 moveq xl, yl
380 RETLDM "r4, r5"
381
382 1: teq xh, yh
383
384 @ Result is x - x = 0.
385 do_it ne, tt
386 movne xh, #0
387 movne xl, #0
388 RETLDM "r4, r5" ne
389
390 @ Result is x + x = 2x.
391 movs ip, r4, lsr #21
392 bne 2f
393 movs xl, xl, lsl #1
394 adcs xh, xh, xh
395 do_it cs
396 orrcs xh, xh, #0x80000000
397 RETLDM "r4, r5"
398 2: adds r4, r4, #(2 << 21)
399 do_it cc, t
400 addcc xh, xh, #(1 << 20)
401 RETLDM "r4, r5" cc
402 and r5, xh, #0x80000000
403
404 @ Overflow: return INF.
405 LSYM(Lad_o):
406 orr xh, r5, #0x7f000000
407 orr xh, xh, #0x00f00000
408 mov xl, #0
409 RETLDM "r4, r5"
410
411 @ At least one of x or y is INF/NAN.
412 @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
413 @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
414 @ if either is NAN: return NAN
415 @ if opposite sign: return NAN
416 @ otherwise return xh-xl (which is INF or -INF)
417 LSYM(Lad_i):
418 mvns ip, r4, asr #21
419 do_it ne, te
420 movne xh, yh
421 movne xl, yl
422 COND(mvn,s,eq) ip, r5, asr #21
423 do_it ne, t
424 movne yh, xh
425 movne yl, xl
426 orrs r4, xl, xh, lsl #12
427 do_it eq, te
428 COND(orr,s,eq) r5, yl, yh, lsl #12
429 teqeq xh, yh
430 orrne xh, xh, #0x00080000 @ quiet NAN
431 RETLDM "r4, r5"
432
433 CFI_END_FUNCTION
434 FUNC_END aeabi_dsub
435 FUNC_END subdf3
436 FUNC_END aeabi_dadd
437 FUNC_END adddf3
438
439 ARM_FUNC_START floatunsidf
440 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
441 CFI_START_FUNCTION
442
443 teq r0, #0
444 do_it eq, t
445 moveq r1, #0
446 RETc(eq)
447
448 do_push {r4, r5, lr} @ sp -= 12
449 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
450 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
451 .cfi_rel_offset r5, 4
452 .cfi_rel_offset lr, 8
453
454 mov r4, #0x400 @ initial exponent
455 add r4, r4, #(52-1 - 1)
456 mov r5, #0 @ sign bit is 0
457 .ifnc xl, r0
458 mov xl, r0
459 .endif
460 mov xh, #0
461 b LSYM(Lad_l)
462
463 CFI_END_FUNCTION
464 FUNC_END aeabi_ui2d
465 FUNC_END floatunsidf
466
467 ARM_FUNC_START floatsidf
468 ARM_FUNC_ALIAS aeabi_i2d floatsidf
469 CFI_START_FUNCTION
470
471 teq r0, #0
472 do_it eq, t
473 moveq r1, #0
474 RETc(eq)
475
476 do_push {r4, r5, lr} @ sp -= 12
477 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
478 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
479 .cfi_rel_offset r5, 4
480 .cfi_rel_offset lr, 8
481
482 mov r4, #0x400 @ initial exponent
483 add r4, r4, #(52-1 - 1)
484 ands r5, r0, #0x80000000 @ sign bit in r5
485 do_it mi
486 rsbmi r0, r0, #0 @ absolute value
487 .ifnc xl, r0
488 mov xl, r0
489 .endif
490 mov xh, #0
491 b LSYM(Lad_l)
492
493 CFI_END_FUNCTION
494 FUNC_END aeabi_i2d
495 FUNC_END floatsidf
496
497 ARM_FUNC_START extendsfdf2
498 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
499 CFI_START_FUNCTION
500
501 movs r2, r0, lsl #1 @ toss sign bit
502 mov xh, r2, asr #3 @ stretch exponent
503 mov xh, xh, rrx @ retrieve sign bit
504 mov xl, r2, lsl #28 @ retrieve remaining bits
505 do_it ne, ttt
506 COND(and,s,ne) r3, r2, #0xff000000 @ isolate exponent
507 teqne r3, #0xff000000 @ if not 0, check if INF or NAN
508 eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
509 RETc(ne) @ and return it.
510
511 bics r2, r2, #0xff000000 @ isolate mantissa
512 do_it eq @ if 0, that is ZERO or INF,
513 RETc(eq) @ we are done already.
514
515 teq r3, #0xff000000 @ check for NAN
516 do_it eq, t
517 orreq xh, xh, #0x00080000 @ change to quiet NAN
518 RETc(eq) @ and return it.
519
520 @ value was denormalized. We can normalize it now.
521 do_push {r4, r5, lr}
522 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
523 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
524 .cfi_rel_offset r5, 4
525 .cfi_rel_offset lr, 8
526
527 mov r4, #0x380 @ setup corresponding exponent
528 and r5, xh, #0x80000000 @ move sign bit in r5
529 bic xh, xh, #0x80000000
530 b LSYM(Lad_l)
531
532 CFI_END_FUNCTION
533 FUNC_END aeabi_f2d
534 FUNC_END extendsfdf2
535
536 ARM_FUNC_START floatundidf
537 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
538 CFI_START_FUNCTION
539 .cfi_remember_state @ Save the current CFA state.
540
541 orrs r2, r0, r1
542 do_it eq
543 RETc(eq)
544
545 do_push {r4, r5, lr} @ sp -= 12
546 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
547 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8
548 .cfi_rel_offset r5, 4
549 .cfi_rel_offset lr, 8
550
551 mov r5, #0
552 b 2f
553
554 ARM_FUNC_START floatdidf
555 ARM_FUNC_ALIAS aeabi_l2d floatdidf
556 .cfi_restore_state
557 @ Restore the CFI state we saved above. If we didn't do this then the
558 @ following instructions would have the CFI state that was set by the
559 @ offset adjustments made in floatundidf.
560
561 orrs r2, r0, r1
562 do_it eq
563 RETc(eq)
564
565 do_push {r4, r5, lr} @ sp -= 12
566 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
567 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 8
568 .cfi_rel_offset r5, 4
569 .cfi_rel_offset lr, 8
570
571 ands r5, ah, #0x80000000 @ sign bit in r5
572 bpl 2f
573 #if defined(__thumb2__)
574 negs al, al
575 sbc ah, ah, ah, lsl #1
576 #else
577 rsbs al, al, #0
578 rsc ah, ah, #0
579 #endif
580 2:
581 mov r4, #0x400 @ initial exponent
582 add r4, r4, #(52-1 - 1)
583
584 @ If FP word order does not match integer word order, swap the words.
585 .ifnc xh, ah
586 mov ip, al
587 mov xh, ah
588 mov xl, ip
589 .endif
590
591 movs ip, xh, lsr #22
592 beq LSYM(Lad_p)
593
594 @ The value is too big. Scale it down a bit...
595 mov r2, #3
596 movs ip, ip, lsr #3
597 do_it ne
598 addne r2, r2, #3
599 movs ip, ip, lsr #3
600 do_it ne
601 addne r2, r2, #3
602 add r2, r2, ip, lsr #3
603
604 rsb r3, r2, #32
605 shift1 lsl, ip, xl, r3
606 shift1 lsr, xl, xl, r2
607 shiftop orr xl xl xh lsl r3 lr
608 shift1 lsr, xh, xh, r2
609 add r4, r4, r2
610 b LSYM(Lad_p)
611
612 CFI_END_FUNCTION
613 FUNC_END floatdidf
614 FUNC_END aeabi_l2d
615 FUNC_END floatundidf
616 FUNC_END aeabi_ul2d
617
618 #endif /* L_addsubdf3 */
619
620 #if defined(L_arm_muldf3) || defined(L_arm_muldivdf3)
621
622 @ Define multiplication as weak in _arm_muldf3.o so that it can be overriden
623 @ by the global definition in _arm_muldivdf3.o. This allows a program only
624 @ using multiplication to take the weak definition which does not contain the
625 @ division code. Programs using only division or both division and
626 @ multiplication will pull _arm_muldivdf3.o from which both the multiplication
627 @ and division are taken thanks to the override.
628 #ifdef L_arm_muldf3
629 WEAK muldf3
630 WEAK aeabi_dmul
631 #endif
632
633 ARM_FUNC_START muldf3
634 ARM_FUNC_ALIAS aeabi_dmul muldf3
635 CFI_START_FUNCTION
636
637 do_push {r4, r5, r6, lr} @ sp -= 16
638 .cfi_adjust_cfa_offset 16 @ CFA is now sp + previousOffset + 16
639 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 12.
640 .cfi_rel_offset r5, 4
641 .cfi_rel_offset r6, 8
642 .cfi_rel_offset lr, 12
643
644 @ Mask out exponents, trap any zero/denormal/INF/NAN.
645 mov ip, #0xff
646 orr ip, ip, #0x700
647 ands r4, ip, xh, lsr #20
648 do_it ne, tte
649 COND(and,s,ne) r5, ip, yh, lsr #20
650 teqne r4, ip
651 teqne r5, ip
652 bleq LSYM(Lml_s)
653
654 @ Add exponents together
655 add r4, r4, r5
656
657 @ Determine final sign.
658 eor r6, xh, yh
659
660 @ Convert mantissa to unsigned integer.
661 @ If power of two, branch to a separate path.
662 bic xh, xh, ip, lsl #21
663 bic yh, yh, ip, lsl #21
664 orrs r5, xl, xh, lsl #12
665 do_it ne
666 COND(orr,s,ne) r5, yl, yh, lsl #12
667 orr xh, xh, #0x00100000
668 orr yh, yh, #0x00100000
669 beq LSYM(Lml_1)
670
671 @ Here is the actual multiplication.
672 @ This code works on architecture versions >= 4
673 umull ip, lr, xl, yl
674 mov r5, #0
675 umlal lr, r5, xh, yl
676 and yl, r6, #0x80000000
677 umlal lr, r5, xl, yh
678 mov r6, #0
679 umlal r5, r6, xh, yh
680
681 @ The LSBs in ip are only significant for the final rounding.
682 @ Fold them into lr.
683 teq ip, #0
684 do_it ne
685 orrne lr, lr, #1
686
687 @ Adjust result upon the MSB position.
688 sub r4, r4, #0xff
689 cmp r6, #(1 << (20-11))
690 sbc r4, r4, #0x300
691 bcs 1f
692 movs lr, lr, lsl #1
693 adcs r5, r5, r5
694 adc r6, r6, r6
695 1:
696 @ Shift to final position, add sign to result.
697 orr xh, yl, r6, lsl #11
698 orr xh, xh, r5, lsr #21
699 mov xl, r5, lsl #11
700 orr xl, xl, lr, lsr #21
701 mov lr, lr, lsl #11
702
703 @ Check exponent range for under/overflow.
704 subs ip, r4, #(254 - 1)
705 do_it hi
706 cmphi ip, #0x700
707 bhi LSYM(Lml_u)
708
709 @ Round the result, merge final exponent.
710 cmp lr, #0x80000000
711 do_it eq
712 COND(mov,s,eq) lr, xl, lsr #1
713 adcs xl, xl, #0
714 adc xh, xh, r4, lsl #20
715 RETLDM "r4, r5, r6"
716
717 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
718 LSYM(Lml_1):
719 and r6, r6, #0x80000000
720 orr xh, r6, xh
721 orr xl, xl, yl
722 eor xh, xh, yh
723 subs r4, r4, ip, lsr #1
724 do_it gt, tt
725 COND(rsb,s,gt) r5, r4, ip
726 orrgt xh, xh, r4, lsl #20
727 RETLDM "r4, r5, r6" gt
728
729 @ Under/overflow: fix things up for the code below.
730 orr xh, xh, #0x00100000
731 mov lr, #0
732 subs r4, r4, #1
733 LSYM(Lml_u):
734 @ Overflow?
735 bgt LSYM(Lml_o)
736
737 @ Check if denormalized result is possible, otherwise return signed 0.
738 cmn r4, #(53 + 1)
739 do_it le, tt
740 movle xl, #0
741 bicle xh, xh, #0x7fffffff
742 RETLDM "r4, r5, r6" le
743
744 @ Find out proper shift value.
745 rsb r4, r4, #0
746 subs r4, r4, #32
747 bge 2f
748 adds r4, r4, #12
749 bgt 1f
750
751 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
752 add r4, r4, #20
753 rsb r5, r4, #32
754 shift1 lsl, r3, xl, r5
755 shift1 lsr, xl, xl, r4
756 shiftop orr xl xl xh lsl r5 r2
757 and r2, xh, #0x80000000
758 bic xh, xh, #0x80000000
759 adds xl, xl, r3, lsr #31
760 shiftop adc xh r2 xh lsr r4 r6
761 orrs lr, lr, r3, lsl #1
762 do_it eq
763 biceq xl, xl, r3, lsr #31
764 RETLDM "r4, r5, r6"
765
766 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
767 @ a register switch from xh to xl. Then round.
768 1: rsb r4, r4, #12
769 rsb r5, r4, #32
770 shift1 lsl, r3, xl, r4
771 shift1 lsr, xl, xl, r5
772 shiftop orr xl xl xh lsl r4 r2
773 bic xh, xh, #0x7fffffff
774 adds xl, xl, r3, lsr #31
775 adc xh, xh, #0
776 orrs lr, lr, r3, lsl #1
777 do_it eq
778 biceq xl, xl, r3, lsr #31
779 RETLDM "r4, r5, r6"
780
781 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
782 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
783 2: rsb r5, r4, #32
784 shiftop orr lr lr xl lsl r5 r2
785 shift1 lsr, r3, xl, r4
786 shiftop orr r3 r3 xh lsl r5 r2
787 shift1 lsr, xl, xh, r4
788 bic xh, xh, #0x7fffffff
789 shiftop bic xl xl xh lsr r4 r2
790 add xl, xl, r3, lsr #31
791 orrs lr, lr, r3, lsl #1
792 do_it eq
793 biceq xl, xl, r3, lsr #31
794 RETLDM "r4, r5, r6"
795
796 @ One or both arguments are denormalized.
797 @ Scale them leftwards and preserve sign bit.
798 LSYM(Lml_d):
799 teq r4, #0
800 bne 2f
801 and r6, xh, #0x80000000
802 1: movs xl, xl, lsl #1
803 adc xh, xh, xh
804 tst xh, #0x00100000
805 do_it eq
806 subeq r4, r4, #1
807 beq 1b
808 orr xh, xh, r6
809 teq r5, #0
810 do_it ne
811 RETc(ne)
812 2: and r6, yh, #0x80000000
813 3: movs yl, yl, lsl #1
814 adc yh, yh, yh
815 tst yh, #0x00100000
816 do_it eq
817 subeq r5, r5, #1
818 beq 3b
819 orr yh, yh, r6
820 RET
821
822 LSYM(Lml_s):
823 @ Isolate the INF and NAN cases away
824 teq r4, ip
825 and r5, ip, yh, lsr #20
826 do_it ne
827 teqne r5, ip
828 beq 1f
829
830 @ Here, one or more arguments are either denormalized or zero.
831 orrs r6, xl, xh, lsl #1
832 do_it ne
833 COND(orr,s,ne) r6, yl, yh, lsl #1
834 bne LSYM(Lml_d)
835
836 @ Result is 0, but determine sign anyway.
837 LSYM(Lml_z):
838 eor xh, xh, yh
839 and xh, xh, #0x80000000
840 mov xl, #0
841 RETLDM "r4, r5, r6"
842
843 1: @ One or both args are INF or NAN.
844 orrs r6, xl, xh, lsl #1
845 do_it eq, te
846 moveq xl, yl
847 moveq xh, yh
848 COND(orr,s,ne) r6, yl, yh, lsl #1
849 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
850 teq r4, ip
851 bne 1f
852 orrs r6, xl, xh, lsl #12
853 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
854 1: teq r5, ip
855 bne LSYM(Lml_i)
856 orrs r6, yl, yh, lsl #12
857 do_it ne, t
858 movne xl, yl
859 movne xh, yh
860 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
861
862 @ Result is INF, but we need to determine its sign.
863 LSYM(Lml_i):
864 eor xh, xh, yh
865
866 @ Overflow: return INF (sign already in xh).
867 LSYM(Lml_o):
868 and xh, xh, #0x80000000
869 orr xh, xh, #0x7f000000
870 orr xh, xh, #0x00f00000
871 mov xl, #0
872 RETLDM "r4, r5, r6"
873
874 @ Return a quiet NAN.
875 LSYM(Lml_n):
876 orr xh, xh, #0x7f000000
877 orr xh, xh, #0x00f80000
878 RETLDM "r4, r5, r6"
879
880 CFI_END_FUNCTION
881 FUNC_END aeabi_dmul
882 FUNC_END muldf3
883
884 #ifdef L_arm_muldivdf3
885
886 ARM_FUNC_START divdf3
887 ARM_FUNC_ALIAS aeabi_ddiv divdf3
888 CFI_START_FUNCTION
889
890 do_push {r4, r5, r6, lr}
891 .cfi_adjust_cfa_offset 16
892 .cfi_rel_offset r4, 0
893 .cfi_rel_offset r5, 4
894 .cfi_rel_offset r6, 8
895 .cfi_rel_offset lr, 12
896
897 @ Mask out exponents, trap any zero/denormal/INF/NAN.
898 mov ip, #0xff
899 orr ip, ip, #0x700
900 ands r4, ip, xh, lsr #20
901 do_it ne, tte
902 COND(and,s,ne) r5, ip, yh, lsr #20
903 teqne r4, ip
904 teqne r5, ip
905 bleq LSYM(Ldv_s)
906
907 @ Subtract divisor exponent from dividend''s.
908 sub r4, r4, r5
909
910 @ Preserve final sign into lr.
911 eor lr, xh, yh
912
913 @ Convert mantissa to unsigned integer.
914 @ Dividend -> r5-r6, divisor -> yh-yl.
915 orrs r5, yl, yh, lsl #12
916 mov xh, xh, lsl #12
917 beq LSYM(Ldv_1)
918 mov yh, yh, lsl #12
919 mov r5, #0x10000000
920 orr yh, r5, yh, lsr #4
921 orr yh, yh, yl, lsr #24
922 mov yl, yl, lsl #8
923 orr r5, r5, xh, lsr #4
924 orr r5, r5, xl, lsr #24
925 mov r6, xl, lsl #8
926
927 @ Initialize xh with final sign bit.
928 and xh, lr, #0x80000000
929
930 @ Ensure result will land to known bit position.
931 @ Apply exponent bias accordingly.
932 cmp r5, yh
933 do_it eq
934 cmpeq r6, yl
935 adc r4, r4, #(255 - 2)
936 add r4, r4, #0x300
937 bcs 1f
938 movs yh, yh, lsr #1
939 mov yl, yl, rrx
940 1:
941 @ Perform first subtraction to align result to a nibble.
942 subs r6, r6, yl
943 sbc r5, r5, yh
944 movs yh, yh, lsr #1
945 mov yl, yl, rrx
946 mov xl, #0x00100000
947 mov ip, #0x00080000
948
949 @ The actual division loop.
950 1: subs lr, r6, yl
951 sbcs lr, r5, yh
952 do_it cs, tt
953 subcs r6, r6, yl
954 movcs r5, lr
955 orrcs xl, xl, ip
956 movs yh, yh, lsr #1
957 mov yl, yl, rrx
958 subs lr, r6, yl
959 sbcs lr, r5, yh
960 do_it cs, tt
961 subcs r6, r6, yl
962 movcs r5, lr
963 orrcs xl, xl, ip, lsr #1
964 movs yh, yh, lsr #1
965 mov yl, yl, rrx
966 subs lr, r6, yl
967 sbcs lr, r5, yh
968 do_it cs, tt
969 subcs r6, r6, yl
970 movcs r5, lr
971 orrcs xl, xl, ip, lsr #2
972 movs yh, yh, lsr #1
973 mov yl, yl, rrx
974 subs lr, r6, yl
975 sbcs lr, r5, yh
976 do_it cs, tt
977 subcs r6, r6, yl
978 movcs r5, lr
979 orrcs xl, xl, ip, lsr #3
980
981 orrs lr, r5, r6
982 beq 2f
983 mov r5, r5, lsl #4
984 orr r5, r5, r6, lsr #28
985 mov r6, r6, lsl #4
986 mov yh, yh, lsl #3
987 orr yh, yh, yl, lsr #29
988 mov yl, yl, lsl #3
989 movs ip, ip, lsr #4
990 bne 1b
991
992 @ We are done with a word of the result.
993 @ Loop again for the low word if this pass was for the high word.
994 tst xh, #0x00100000
995 bne 3f
996 orr xh, xh, xl
997 mov xl, #0
998 mov ip, #0x80000000
999 b 1b
1000 2:
1001 @ Be sure result starts in the high word.
1002 tst xh, #0x00100000
1003 do_it eq, t
1004 orreq xh, xh, xl
1005 moveq xl, #0
1006 3:
1007 @ Check exponent range for under/overflow.
1008 subs ip, r4, #(254 - 1)
1009 do_it hi
1010 cmphi ip, #0x700
1011 bhi LSYM(Lml_u)
1012
1013 @ Round the result, merge final exponent.
1014 subs ip, r5, yh
1015 do_it eq, t
1016 COND(sub,s,eq) ip, r6, yl
1017 COND(mov,s,eq) ip, xl, lsr #1
1018 adcs xl, xl, #0
1019 adc xh, xh, r4, lsl #20
1020 RETLDM "r4, r5, r6"
1021
1022 @ Division by 0x1p*: shortcut a lot of code.
1023 LSYM(Ldv_1):
1024 and lr, lr, #0x80000000
1025 orr xh, lr, xh, lsr #12
1026 adds r4, r4, ip, lsr #1
1027 do_it gt, tt
1028 COND(rsb,s,gt) r5, r4, ip
1029 orrgt xh, xh, r4, lsl #20
1030 RETLDM "r4, r5, r6" gt
1031
1032 orr xh, xh, #0x00100000
1033 mov lr, #0
1034 subs r4, r4, #1
1035 b LSYM(Lml_u)
1036
1037 @ Result mightt need to be denormalized: put remainder bits
1038 @ in lr for rounding considerations.
1039 LSYM(Ldv_u):
1040 orr lr, r5, r6
1041 b LSYM(Lml_u)
1042
1043 @ One or both arguments is either INF, NAN or zero.
1044 LSYM(Ldv_s):
1045 and r5, ip, yh, lsr #20
1046 teq r4, ip
1047 do_it eq
1048 teqeq r5, ip
1049 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1050 teq r4, ip
1051 bne 1f
1052 orrs r4, xl, xh, lsl #12
1053 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1054 teq r5, ip
1055 bne LSYM(Lml_i) @ INF / <anything> -> INF
1056 mov xl, yl
1057 mov xh, yh
1058 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1059 1: teq r5, ip
1060 bne 2f
1061 orrs r5, yl, yh, lsl #12
1062 beq LSYM(Lml_z) @ <anything> / INF -> 0
1063 mov xl, yl
1064 mov xh, yh
1065 b LSYM(Lml_n) @ <anything> / NAN -> NAN
1066 2: @ If both are nonzero, we need to normalize and resume above.
1067 orrs r6, xl, xh, lsl #1
1068 do_it ne
1069 COND(orr,s,ne) r6, yl, yh, lsl #1
1070 bne LSYM(Lml_d)
1071 @ One or both arguments are 0.
1072 orrs r4, xl, xh, lsl #1
1073 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1074 orrs r5, yl, yh, lsl #1
1075 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1076 b LSYM(Lml_n) @ 0 / 0 -> NAN
1077
1078 CFI_END_FUNCTION
1079 FUNC_END aeabi_ddiv
1080 FUNC_END divdf3
1081
1082 #endif /* L_muldivdf3 */
1083 #endif /* L_arm_muldf3 || L_arm_muldivdf3 */
1084
1085 #ifdef L_arm_cmpdf2
1086
1087 @ Note: only r0 (return value) and ip are clobbered here.
1088
1089 ARM_FUNC_START gtdf2
1090 ARM_FUNC_ALIAS gedf2 gtdf2
1091 CFI_START_FUNCTION
1092 mov ip, #-1
1093 b 1f
1094
1095 ARM_FUNC_START ltdf2
1096 ARM_FUNC_ALIAS ledf2 ltdf2
1097 mov ip, #1
1098 b 1f
1099
1100 ARM_FUNC_START cmpdf2
1101 ARM_FUNC_ALIAS nedf2 cmpdf2
1102 ARM_FUNC_ALIAS eqdf2 cmpdf2
1103 mov ip, #1 @ how should we specify unordered here?
1104
1105 1: str ip, [sp, #-4]!
1106 .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4.
1107 @ We're not adding CFI for ip as it's pushed into the stack
1108 @ only because it may be popped off later as a return value
1109 @ (i.e. we're not preserving it anyways).
1110
1111 @ Trap any INF/NAN first.
1112 mov ip, xh, lsl #1
1113 mvns ip, ip, asr #21
1114 mov ip, yh, lsl #1
1115 do_it ne
1116 COND(mvn,s,ne) ip, ip, asr #21
1117 beq 3f
1118 .cfi_remember_state
1119 @ Save the current CFI state. This is done because the branch
1120 @ is conditional, and if we don't take it we'll issue a
1121 @ .cfi_adjust_cfa_offset and return. If we do take it,
1122 @ however, the .cfi_adjust_cfa_offset from the non-branch code
1123 @ will affect the branch code as well. To avoid this we'll
1124 @ restore the current state before executing the branch code.
1125
1126 @ Test for equality. Note that 0.0 is equal to -0.0.
1127 2: add sp, sp, #4
1128 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1129
1130 orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1131 do_it eq, e
1132 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1133 teqne xh, yh @ or xh == yh
1134 do_it eq, tt
1135 teqeq xl, yl @ and xl == yl
1136 moveq r0, #0 @ then equal.
1137 RETc(eq)
1138
1139 @ Clear C flag
1140 cmn r0, #0
1141
1142 @ Compare sign,
1143 teq xh, yh
1144
1145 @ Compare values if same sign
1146 do_it pl
1147 cmppl xh, yh
1148 do_it eq
1149 cmpeq xl, yl
1150
1151 @ Result:
1152 do_it cs, e
1153 movcs r0, yh, asr #31
1154 mvncc r0, yh, asr #31
1155 orr r0, r0, #1
1156 RET
1157
1158 3: @ Look for a NAN.
1159
1160 @ Restore the previous CFI state (i.e. keep the CFI state as it was
1161 @ before the branch).
1162 .cfi_restore_state
1163
1164 mov ip, xh, lsl #1
1165 mvns ip, ip, asr #21
1166 bne 4f
1167 orrs ip, xl, xh, lsl #12
1168 bne 5f @ x is NAN
1169 4: mov ip, yh, lsl #1
1170 mvns ip, ip, asr #21
1171 bne 2b
1172 orrs ip, yl, yh, lsl #12
1173 beq 2b @ y is not NAN
1174
1175 5: ldr r0, [sp], #4 @ unordered return code
1176 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1177
1178 RET
1179
1180 CFI_END_FUNCTION
1181 FUNC_END gedf2
1182 FUNC_END gtdf2
1183 FUNC_END ledf2
1184 FUNC_END ltdf2
1185 FUNC_END nedf2
1186 FUNC_END eqdf2
1187 FUNC_END cmpdf2
1188
1189 ARM_FUNC_START aeabi_cdrcmple
1190 CFI_START_FUNCTION
1191
1192 mov ip, r0
1193 mov r0, r2
1194 mov r2, ip
1195 mov ip, r1
1196 mov r1, r3
1197 mov r3, ip
1198 b 6f
1199
1200 ARM_FUNC_START aeabi_cdcmpeq
1201 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1202
1203 @ The status-returning routines are required to preserve all
1204 @ registers except ip, lr, and cpsr.
1205 6: do_push {r0, lr}
1206 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8.
1207 .cfi_rel_offset r0, 0 @ Previous r0 is saved at sp.
1208 .cfi_rel_offset lr, 4 @ Previous lr is saved at sp + 4.
1209
1210 ARM_CALL cmpdf2
1211 @ Set the Z flag correctly, and the C flag unconditionally.
1212 cmp r0, #0
1213 @ Clear the C flag if the return value was -1, indicating
1214 @ that the first operand was smaller than the second.
1215 do_it mi
1216 cmnmi r0, #0
1217
1218 RETLDM "r0"
1219
1220 CFI_END_FUNCTION
1221 FUNC_END aeabi_cdcmple
1222 FUNC_END aeabi_cdcmpeq
1223 FUNC_END aeabi_cdrcmple
1224
1225 ARM_FUNC_START aeabi_dcmpeq
1226 CFI_START_FUNCTION
1227
1228 str lr, [sp, #-8]! @ sp -= 8
1229 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1230 .cfi_rel_offset lr, 0 @ lr is at sp
1231
1232 ARM_CALL aeabi_cdcmple
1233 do_it eq, e
1234 moveq r0, #1 @ Equal to.
1235 movne r0, #0 @ Less than, greater than, or unordered.
1236
1237 RETLDM
1238
1239 CFI_END_FUNCTION
1240 FUNC_END aeabi_dcmpeq
1241
1242 ARM_FUNC_START aeabi_dcmplt
1243 CFI_START_FUNCTION
1244
1245 str lr, [sp, #-8]! @ sp -= 8
1246 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1247 .cfi_rel_offset lr, 0 @ lr is at sp
1248
1249 ARM_CALL aeabi_cdcmple
1250 do_it cc, e
1251 movcc r0, #1 @ Less than.
1252 movcs r0, #0 @ Equal to, greater than, or unordered.
1253 RETLDM
1254
1255 CFI_END_FUNCTION
1256 FUNC_END aeabi_dcmplt
1257
1258 ARM_FUNC_START aeabi_dcmple
1259 CFI_START_FUNCTION
1260
1261 str lr, [sp, #-8]! @ sp -= 8
1262 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1263 .cfi_rel_offset lr, 0 @ lr is at sp
1264
1265 ARM_CALL aeabi_cdcmple
1266 do_it ls, e
1267 movls r0, #1 @ Less than or equal to.
1268 movhi r0, #0 @ Greater than or unordered.
1269 RETLDM
1270
1271 CFI_END_FUNCTION
1272 FUNC_END aeabi_dcmple
1273
1274 ARM_FUNC_START aeabi_dcmpge
1275 CFI_START_FUNCTION
1276
1277 str lr, [sp, #-8]! @ sp -= 8
1278 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1279 .cfi_rel_offset lr, 0 @ lr is at sp
1280
1281 ARM_CALL aeabi_cdrcmple
1282 do_it ls, e
1283 movls r0, #1 @ Operand 2 is less than or equal to operand 1.
1284 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
1285 RETLDM
1286
1287 CFI_END_FUNCTION
1288 FUNC_END aeabi_dcmpge
1289
1290 ARM_FUNC_START aeabi_dcmpgt
1291 CFI_START_FUNCTION
1292
1293 str lr, [sp, #-8]! @ sp -= 8
1294 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1295 .cfi_rel_offset lr, 0 @ lr is at sp
1296
1297 ARM_CALL aeabi_cdrcmple
1298 do_it cc, e
1299 movcc r0, #1 @ Operand 2 is less than operand 1.
1300 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
1301 @ or they are unordered.
1302 RETLDM
1303
1304 CFI_END_FUNCTION
1305 FUNC_END aeabi_dcmpgt
1306
1307 #endif /* L_cmpdf2 */
1308
1309 #ifdef L_arm_unorddf2
1310
1311 ARM_FUNC_START unorddf2
1312 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1313 .cfi_startproc
1314
1315 mov ip, xh, lsl #1
1316 mvns ip, ip, asr #21
1317 bne 1f
1318 orrs ip, xl, xh, lsl #12
1319 bne 3f @ x is NAN
1320 1: mov ip, yh, lsl #1
1321 mvns ip, ip, asr #21
1322 bne 2f
1323 orrs ip, yl, yh, lsl #12
1324 bne 3f @ y is NAN
1325 2: mov r0, #0 @ arguments are ordered.
1326 RET
1327
1328 3: mov r0, #1 @ arguments are unordered.
1329 RET
1330
1331 .cfi_endproc
1332 FUNC_END aeabi_dcmpun
1333 FUNC_END unorddf2
1334
1335 #endif /* L_unorddf2 */
1336
1337 #ifdef L_arm_fixdfsi
1338
1339 ARM_FUNC_START fixdfsi
1340 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1341 CFI_START_FUNCTION
1342
1343 @ check exponent range.
1344 mov r2, xh, lsl #1
1345 adds r2, r2, #(1 << 21)
1346 bcs 2f @ value is INF or NAN
1347 bpl 1f @ value is too small
1348 mov r3, #(0xfffffc00 + 31)
1349 subs r2, r3, r2, asr #21
1350 bls 3f @ value is too large
1351
1352 @ scale value
1353 mov r3, xh, lsl #11
1354 orr r3, r3, #0x80000000
1355 orr r3, r3, xl, lsr #21
1356 tst xh, #0x80000000 @ the sign bit
1357 shift1 lsr, r0, r3, r2
1358 do_it ne
1359 rsbne r0, r0, #0
1360 RET
1361
1362 1: mov r0, #0
1363 RET
1364
1365 2: orrs xl, xl, xh, lsl #12
1366 bne 4f @ x is NAN.
1367 3: ands r0, xh, #0x80000000 @ the sign bit
1368 do_it eq
1369 moveq r0, #0x7fffffff @ maximum signed positive si
1370 RET
1371
1372 4: mov r0, #0 @ How should we convert NAN?
1373 RET
1374
1375 CFI_END_FUNCTION
1376 FUNC_END aeabi_d2iz
1377 FUNC_END fixdfsi
1378
1379 #endif /* L_fixdfsi */
1380
1381 #ifdef L_arm_fixunsdfsi
1382
1383 ARM_FUNC_START fixunsdfsi
1384 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1385 CFI_START_FUNCTION
1386
1387 @ check exponent range.
1388 movs r2, xh, lsl #1
1389 bcs 1f @ value is negative
1390 adds r2, r2, #(1 << 21)
1391 bcs 2f @ value is INF or NAN
1392 bpl 1f @ value is too small
1393 mov r3, #(0xfffffc00 + 31)
1394 subs r2, r3, r2, asr #21
1395 bmi 3f @ value is too large
1396
1397 @ scale value
1398 mov r3, xh, lsl #11
1399 orr r3, r3, #0x80000000
1400 orr r3, r3, xl, lsr #21
1401 shift1 lsr, r0, r3, r2
1402 RET
1403
1404 1: mov r0, #0
1405 RET
1406
1407 2: orrs xl, xl, xh, lsl #12
1408 bne 4f @ value is NAN.
1409 3: mov r0, #0xffffffff @ maximum unsigned si
1410 RET
1411
1412 4: mov r0, #0 @ How should we convert NAN?
1413 RET
1414
1415 CFI_END_FUNCTION
1416 FUNC_END aeabi_d2uiz
1417 FUNC_END fixunsdfsi
1418
1419 #endif /* L_fixunsdfsi */
1420
1421 #ifdef L_arm_truncdfsf2
1422
1423 ARM_FUNC_START truncdfsf2
1424 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1425 CFI_START_FUNCTION
1426
1427 @ check exponent range.
1428 mov r2, xh, lsl #1
1429 subs r3, r2, #((1023 - 127) << 21)
1430 do_it cs, t
1431 COND(sub,s,cs) ip, r3, #(1 << 21)
1432 COND(rsb,s,cs) ip, ip, #(254 << 21)
1433 bls 2f @ value is out of range
1434
1435 1: @ shift and round mantissa
1436 and ip, xh, #0x80000000
1437 mov r2, xl, lsl #3
1438 orr xl, ip, xl, lsr #29
1439 cmp r2, #0x80000000
1440 adc r0, xl, r3, lsl #2
1441 do_it eq
1442 biceq r0, r0, #1
1443 RET
1444
1445 2: @ either overflow or underflow
1446 tst xh, #0x40000000
1447 bne 3f @ overflow
1448
1449 @ check if denormalized value is possible
1450 adds r2, r3, #(23 << 21)
1451 do_it lt, t
1452 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1453 RETc(lt)
1454
1455 @ denormalize value so we can resume with the code above afterwards.
1456 orr xh, xh, #0x00100000
1457 mov r2, r2, lsr #21
1458 rsb r2, r2, #24
1459 rsb ip, r2, #32
1460 #if defined(__thumb2__)
1461 lsls r3, xl, ip
1462 #else
1463 movs r3, xl, lsl ip
1464 #endif
1465 shift1 lsr, xl, xl, r2
1466 do_it ne
1467 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1468 mov r3, xh, lsl #11
1469 mov r3, r3, lsr #11
1470 shiftop orr xl xl r3 lsl ip ip
1471 shift1 lsr, r3, r3, r2
1472 mov r3, r3, lsl #1
1473 b 1b
1474
1475 3: @ chech for NAN
1476 mvns r3, r2, asr #21
1477 bne 5f @ simple overflow
1478 orrs r3, xl, xh, lsl #12
1479 do_it ne, tt
1480 movne r0, #0x7f000000
1481 orrne r0, r0, #0x00c00000
1482 RETc(ne) @ return NAN
1483
1484 5: @ return INF with sign
1485 and r0, xh, #0x80000000
1486 orr r0, r0, #0x7f000000
1487 orr r0, r0, #0x00800000
1488 RET
1489
1490 CFI_END_FUNCTION
1491 FUNC_END aeabi_d2f
1492 FUNC_END truncdfsf2
1493
1494 #endif /* L_truncdfsf2 */