]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/arm/ieee754-df.S
[ARM] Fix PR target/59833
[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-2016 Free Software Foundation, Inc.
4 Contributed by Nicolas Pitre (nico@cam.org)
5
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
11 This file is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 /*
26 * Notes:
27 *
28 * The goal of this code is to be as fast as possible. This is
29 * not meant to be easy to understand for the casual reader.
30 * 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 tst xh, #0x00100000
242 sub r4, r4, #1
243 bne LSYM(Lad_e)
244
245 @ No rounding necessary since ip will always be 0 at this point.
246 LSYM(Lad_l):
247
248 #if __ARM_ARCH__ < 5
249
250 teq xh, #0
251 movne r3, #20
252 moveq r3, #52
253 moveq xh, xl
254 moveq xl, #0
255 mov r2, xh
256 cmp r2, #(1 << 16)
257 movhs r2, r2, lsr #16
258 subhs r3, r3, #16
259 cmp r2, #(1 << 8)
260 movhs r2, r2, lsr #8
261 subhs r3, r3, #8
262 cmp r2, #(1 << 4)
263 movhs r2, r2, lsr #4
264 subhs r3, r3, #4
265 cmp r2, #(1 << 2)
266 subhs r3, r3, #2
267 sublo r3, r3, r2, lsr #1
268 sub r3, r3, r2, lsr #3
269
270 #else
271
272 teq xh, #0
273 do_it eq, t
274 moveq xh, xl
275 moveq xl, #0
276 clz r3, xh
277 do_it eq
278 addeq r3, r3, #32
279 sub r3, r3, #11
280
281 #endif
282
283 @ determine how to shift the value.
284 subs r2, r3, #32
285 bge 2f
286 adds r2, r2, #12
287 ble 1f
288
289 @ shift value left 21 to 31 bits, or actually right 11 to 1 bits
290 @ since a register switch happened above.
291 add ip, r2, #20
292 rsb r2, r2, #12
293 shift1 lsl, xl, xh, ip
294 shift1 lsr, xh, xh, r2
295 b 3f
296
297 @ actually shift value left 1 to 20 bits, which might also represent
298 @ 32 to 52 bits if counting the register switch that happened earlier.
299 1: add r2, r2, #20
300 2: do_it le
301 rsble ip, r2, #32
302 shift1 lsl, xh, xh, r2
303 #if defined(__thumb2__)
304 lsr ip, xl, ip
305 itt le
306 orrle xh, xh, ip
307 lslle xl, xl, r2
308 #else
309 orrle xh, xh, xl, lsr ip
310 movle xl, xl, lsl r2
311 #endif
312
313 @ adjust exponent accordingly.
314 3: subs r4, r4, r3
315 do_it ge, tt
316 addge xh, xh, r4, lsl #20
317 orrge xh, xh, r5
318 RETLDM "r4, r5" ge
319
320 @ Exponent too small, denormalize result.
321 @ Find out proper shift value.
322 mvn r4, r4
323 subs r4, r4, #31
324 bge 2f
325 adds r4, r4, #12
326 bgt 1f
327
328 @ shift result right of 1 to 20 bits, sign is in r5.
329 add r4, r4, #20
330 rsb r2, r4, #32
331 shift1 lsr, xl, xl, r4
332 shiftop orr xl xl xh lsl r2 yh
333 shiftop orr xh r5 xh lsr r4 yh
334 RETLDM "r4, r5"
335
336 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
337 @ a register switch from xh to xl.
338 1: rsb r4, r4, #12
339 rsb r2, r4, #32
340 shift1 lsr, xl, xl, r2
341 shiftop orr xl xl xh lsl r4 yh
342 mov xh, r5
343 RETLDM "r4, r5"
344
345 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
346 @ from xh to xl.
347 2: shift1 lsr, xl, xh, r4
348 mov xh, r5
349 RETLDM "r4, r5"
350
351 @ Adjust exponents for denormalized arguments.
352 @ Note that r4 must not remain equal to 0.
353 LSYM(Lad_d):
354 teq r4, #0
355 eor yh, yh, #0x00100000
356 do_it eq, te
357 eoreq xh, xh, #0x00100000
358 addeq r4, r4, #1
359 subne r5, r5, #1
360 b LSYM(Lad_x)
361
362
363 LSYM(Lad_s):
364 mvns ip, r4, asr #21
365 do_it ne
366 COND(mvn,s,ne) ip, r5, asr #21
367 beq LSYM(Lad_i)
368
369 teq r4, r5
370 do_it eq
371 teqeq xl, yl
372 beq 1f
373
374 @ Result is x + 0.0 = x or 0.0 + y = y.
375 orrs ip, r4, xl
376 do_it eq, t
377 moveq xh, yh
378 moveq xl, yl
379 RETLDM "r4, r5"
380
381 1: teq xh, yh
382
383 @ Result is x - x = 0.
384 do_it ne, tt
385 movne xh, #0
386 movne xl, #0
387 RETLDM "r4, r5" ne
388
389 @ Result is x + x = 2x.
390 movs ip, r4, lsr #21
391 bne 2f
392 movs xl, xl, lsl #1
393 adcs xh, xh, xh
394 do_it cs
395 orrcs xh, xh, #0x80000000
396 RETLDM "r4, r5"
397 2: adds r4, r4, #(2 << 21)
398 do_it cc, t
399 addcc xh, xh, #(1 << 20)
400 RETLDM "r4, r5" cc
401 and r5, xh, #0x80000000
402
403 @ Overflow: return INF.
404 LSYM(Lad_o):
405 orr xh, r5, #0x7f000000
406 orr xh, xh, #0x00f00000
407 mov xl, #0
408 RETLDM "r4, r5"
409
410 @ At least one of x or y is INF/NAN.
411 @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
412 @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
413 @ if either is NAN: return NAN
414 @ if opposite sign: return NAN
415 @ otherwise return xh-xl (which is INF or -INF)
416 LSYM(Lad_i):
417 mvns ip, r4, asr #21
418 do_it ne, te
419 movne xh, yh
420 movne xl, yl
421 COND(mvn,s,eq) ip, r5, asr #21
422 do_it ne, t
423 movne yh, xh
424 movne yl, xl
425 orrs r4, xl, xh, lsl #12
426 do_it eq, te
427 COND(orr,s,eq) r5, yl, yh, lsl #12
428 teqeq xh, yh
429 orrne xh, xh, #0x00080000 @ quiet NAN
430 RETLDM "r4, r5"
431
432 CFI_END_FUNCTION
433 FUNC_END aeabi_dsub
434 FUNC_END subdf3
435 FUNC_END aeabi_dadd
436 FUNC_END adddf3
437
438 ARM_FUNC_START floatunsidf
439 ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
440 CFI_START_FUNCTION
441
442 teq r0, #0
443 do_it eq, t
444 moveq r1, #0
445 RETc(eq)
446
447 do_push {r4, r5, lr} @ sp -= 12
448 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
449 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
450 .cfi_rel_offset r5, 4
451 .cfi_rel_offset lr, 8
452
453 mov r4, #0x400 @ initial exponent
454 add r4, r4, #(52-1 - 1)
455 mov r5, #0 @ sign bit is 0
456 .ifnc xl, r0
457 mov xl, r0
458 .endif
459 mov xh, #0
460 b LSYM(Lad_l)
461
462 CFI_END_FUNCTION
463 FUNC_END aeabi_ui2d
464 FUNC_END floatunsidf
465
466 ARM_FUNC_START floatsidf
467 ARM_FUNC_ALIAS aeabi_i2d floatsidf
468 CFI_START_FUNCTION
469
470 teq r0, #0
471 do_it eq, t
472 moveq r1, #0
473 RETc(eq)
474
475 do_push {r4, r5, lr} @ sp -= 12
476 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
477 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
478 .cfi_rel_offset r5, 4
479 .cfi_rel_offset lr, 8
480
481 mov r4, #0x400 @ initial exponent
482 add r4, r4, #(52-1 - 1)
483 ands r5, r0, #0x80000000 @ sign bit in r5
484 do_it mi
485 rsbmi r0, r0, #0 @ absolute value
486 .ifnc xl, r0
487 mov xl, r0
488 .endif
489 mov xh, #0
490 b LSYM(Lad_l)
491
492 CFI_END_FUNCTION
493 FUNC_END aeabi_i2d
494 FUNC_END floatsidf
495
496 ARM_FUNC_START extendsfdf2
497 ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
498 CFI_START_FUNCTION
499
500 movs r2, r0, lsl #1 @ toss sign bit
501 mov xh, r2, asr #3 @ stretch exponent
502 mov xh, xh, rrx @ retrieve sign bit
503 mov xl, r2, lsl #28 @ retrieve remaining bits
504 do_it ne, ttt
505 COND(and,s,ne) r3, r2, #0xff000000 @ isolate exponent
506 teqne r3, #0xff000000 @ if not 0, check if INF or NAN
507 eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
508 RETc(ne) @ and return it.
509
510 bics r2, r2, #0xff000000 @ isolate mantissa
511 do_it eq @ if 0, that is ZERO or INF,
512 RETc(eq) @ we are done already.
513
514 teq r3, #0xff000000 @ check for NAN
515 do_it eq, t
516 orreq xh, xh, #0x00080000 @ change to quiet NAN
517 RETc(eq) @ and return it.
518
519 @ value was denormalized. We can normalize it now.
520 do_push {r4, r5, lr}
521 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
522 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
523 .cfi_rel_offset r5, 4
524 .cfi_rel_offset lr, 8
525
526 mov r4, #0x380 @ setup corresponding exponent
527 and r5, xh, #0x80000000 @ move sign bit in r5
528 bic xh, xh, #0x80000000
529 b LSYM(Lad_l)
530
531 CFI_END_FUNCTION
532 FUNC_END aeabi_f2d
533 FUNC_END extendsfdf2
534
535 ARM_FUNC_START floatundidf
536 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
537 CFI_START_FUNCTION
538 .cfi_remember_state @ Save the current CFA state.
539
540 orrs r2, r0, r1
541 do_it eq
542 RETc(eq)
543
544 do_push {r4, r5, lr} @ sp -= 12
545 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
546 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8
547 .cfi_rel_offset r5, 4
548 .cfi_rel_offset lr, 8
549
550 mov r5, #0
551 b 2f
552
553 ARM_FUNC_START floatdidf
554 ARM_FUNC_ALIAS aeabi_l2d floatdidf
555 .cfi_restore_state
556 @ Restore the CFI state we saved above. If we didn't do this then the
557 @ following instructions would have the CFI state that was set by the
558 @ offset adjustments made in floatundidf.
559
560 orrs r2, r0, r1
561 do_it eq
562 RETc(eq)
563
564 do_push {r4, r5, lr} @ sp -= 12
565 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
566 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 8
567 .cfi_rel_offset r5, 4
568 .cfi_rel_offset lr, 8
569
570 ands r5, ah, #0x80000000 @ sign bit in r5
571 bpl 2f
572 #if defined(__thumb2__)
573 negs al, al
574 sbc ah, ah, ah, lsl #1
575 #else
576 rsbs al, al, #0
577 rsc ah, ah, #0
578 #endif
579 2:
580 mov r4, #0x400 @ initial exponent
581 add r4, r4, #(52-1 - 1)
582
583 @ If FP word order does not match integer word order, swap the words.
584 .ifnc xh, ah
585 mov ip, al
586 mov xh, ah
587 mov xl, ip
588 .endif
589
590 movs ip, xh, lsr #22
591 beq LSYM(Lad_p)
592
593 @ The value is too big. Scale it down a bit...
594 mov r2, #3
595 movs ip, ip, lsr #3
596 do_it ne
597 addne r2, r2, #3
598 movs ip, ip, lsr #3
599 do_it ne
600 addne r2, r2, #3
601 add r2, r2, ip, lsr #3
602
603 rsb r3, r2, #32
604 shift1 lsl, ip, xl, r3
605 shift1 lsr, xl, xl, r2
606 shiftop orr xl xl xh lsl r3 lr
607 shift1 lsr, xh, xh, r2
608 add r4, r4, r2
609 b LSYM(Lad_p)
610
611 CFI_END_FUNCTION
612 FUNC_END floatdidf
613 FUNC_END aeabi_l2d
614 FUNC_END floatundidf
615 FUNC_END aeabi_ul2d
616
617 #endif /* L_addsubdf3 */
618
619 #ifdef L_arm_muldivdf3
620
621 ARM_FUNC_START muldf3
622 ARM_FUNC_ALIAS aeabi_dmul muldf3
623 CFI_START_FUNCTION
624
625 do_push {r4, r5, r6, lr} @ sp -= 16
626 .cfi_adjust_cfa_offset 16 @ CFA is now sp + previousOffset + 16
627 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 12.
628 .cfi_rel_offset r5, 4
629 .cfi_rel_offset r6, 8
630 .cfi_rel_offset lr, 12
631
632 @ Mask out exponents, trap any zero/denormal/INF/NAN.
633 mov ip, #0xff
634 orr ip, ip, #0x700
635 ands r4, ip, xh, lsr #20
636 do_it ne, tte
637 COND(and,s,ne) r5, ip, yh, lsr #20
638 teqne r4, ip
639 teqne r5, ip
640 bleq LSYM(Lml_s)
641
642 @ Add exponents together
643 add r4, r4, r5
644
645 @ Determine final sign.
646 eor r6, xh, yh
647
648 @ Convert mantissa to unsigned integer.
649 @ If power of two, branch to a separate path.
650 bic xh, xh, ip, lsl #21
651 bic yh, yh, ip, lsl #21
652 orrs r5, xl, xh, lsl #12
653 do_it ne
654 COND(orr,s,ne) r5, yl, yh, lsl #12
655 orr xh, xh, #0x00100000
656 orr yh, yh, #0x00100000
657 beq LSYM(Lml_1)
658
659 #if __ARM_ARCH__ < 4
660
661 @ Put sign bit in r6, which will be restored in yl later.
662 and r6, r6, #0x80000000
663
664 @ Well, no way to make it shorter without the umull instruction.
665 stmfd sp!, {r6, r7, r8, r9, sl, fp} @ sp -= 24
666 .cfi_remember_state @ Save the current CFI state.
667 .cfi_adjust_cfa_offset 24 @ CFA is now sp + previousOffset + 24.
668 .cfi_rel_offset r6, 0 @ Registers are saved from sp to sp + 20.
669 .cfi_rel_offset r7, 4
670 .cfi_rel_offset r8, 8
671 .cfi_rel_offset r9, 12
672 .cfi_rel_offset sl, 16
673 .cfi_rel_offset fp, 20
674
675 mov r7, xl, lsr #16
676 mov r8, yl, lsr #16
677 mov r9, xh, lsr #16
678 mov sl, yh, lsr #16
679 bic xl, xl, r7, lsl #16
680 bic yl, yl, r8, lsl #16
681 bic xh, xh, r9, lsl #16
682 bic yh, yh, sl, lsl #16
683 mul ip, xl, yl
684 mul fp, xl, r8
685 mov lr, #0
686 adds ip, ip, fp, lsl #16
687 adc lr, lr, fp, lsr #16
688 mul fp, r7, yl
689 adds ip, ip, fp, lsl #16
690 adc lr, lr, fp, lsr #16
691 mul fp, xl, sl
692 mov r5, #0
693 adds lr, lr, fp, lsl #16
694 adc r5, r5, fp, lsr #16
695 mul fp, r7, yh
696 adds lr, lr, fp, lsl #16
697 adc r5, r5, fp, lsr #16
698 mul fp, xh, r8
699 adds lr, lr, fp, lsl #16
700 adc r5, r5, fp, lsr #16
701 mul fp, r9, yl
702 adds lr, lr, fp, lsl #16
703 adc r5, r5, fp, lsr #16
704 mul fp, xh, sl
705 mul r6, r9, sl
706 adds r5, r5, fp, lsl #16
707 adc r6, r6, fp, lsr #16
708 mul fp, r9, yh
709 adds r5, r5, fp, lsl #16
710 adc r6, r6, fp, lsr #16
711 mul fp, xl, yh
712 adds lr, lr, fp
713 mul fp, r7, sl
714 adcs r5, r5, fp
715 mul fp, xh, yl
716 adc r6, r6, #0
717 adds lr, lr, fp
718 mul fp, r9, r8
719 adcs r5, r5, fp
720 mul fp, r7, r8
721 adc r6, r6, #0
722 adds lr, lr, fp
723 mul fp, xh, yh
724 adcs r5, r5, fp
725 adc r6, r6, #0
726 ldmfd sp!, {yl, r7, r8, r9, sl, fp} @ sp += 24
727 .cfi_restore_state @ Restore the previous CFI state.
728 #else
729
730 @ Here is the actual multiplication.
731 umull ip, lr, xl, yl
732 mov r5, #0
733 umlal lr, r5, xh, yl
734 and yl, r6, #0x80000000
735 umlal lr, r5, xl, yh
736 mov r6, #0
737 umlal r5, r6, xh, yh
738
739 #endif
740
741 @ The LSBs in ip are only significant for the final rounding.
742 @ Fold them into lr.
743 teq ip, #0
744 do_it ne
745 orrne lr, lr, #1
746
747 @ Adjust result upon the MSB position.
748 sub r4, r4, #0xff
749 cmp r6, #(1 << (20-11))
750 sbc r4, r4, #0x300
751 bcs 1f
752 movs lr, lr, lsl #1
753 adcs r5, r5, r5
754 adc r6, r6, r6
755 1:
756 @ Shift to final position, add sign to result.
757 orr xh, yl, r6, lsl #11
758 orr xh, xh, r5, lsr #21
759 mov xl, r5, lsl #11
760 orr xl, xl, lr, lsr #21
761 mov lr, lr, lsl #11
762
763 @ Check exponent range for under/overflow.
764 subs ip, r4, #(254 - 1)
765 do_it hi
766 cmphi ip, #0x700
767 bhi LSYM(Lml_u)
768
769 @ Round the result, merge final exponent.
770 cmp lr, #0x80000000
771 do_it eq
772 COND(mov,s,eq) lr, xl, lsr #1
773 adcs xl, xl, #0
774 adc xh, xh, r4, lsl #20
775 RETLDM "r4, r5, r6"
776
777 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
778 LSYM(Lml_1):
779 and r6, r6, #0x80000000
780 orr xh, r6, xh
781 orr xl, xl, yl
782 eor xh, xh, yh
783 subs r4, r4, ip, lsr #1
784 do_it gt, tt
785 COND(rsb,s,gt) r5, r4, ip
786 orrgt xh, xh, r4, lsl #20
787 RETLDM "r4, r5, r6" gt
788
789 @ Under/overflow: fix things up for the code below.
790 orr xh, xh, #0x00100000
791 mov lr, #0
792 subs r4, r4, #1
793 LSYM(Lml_u):
794 @ Overflow?
795 bgt LSYM(Lml_o)
796
797 @ Check if denormalized result is possible, otherwise return signed 0.
798 cmn r4, #(53 + 1)
799 do_it le, tt
800 movle xl, #0
801 bicle xh, xh, #0x7fffffff
802 RETLDM "r4, r5, r6" le
803
804 @ Find out proper shift value.
805 rsb r4, r4, #0
806 subs r4, r4, #32
807 bge 2f
808 adds r4, r4, #12
809 bgt 1f
810
811 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
812 add r4, r4, #20
813 rsb r5, r4, #32
814 shift1 lsl, r3, xl, r5
815 shift1 lsr, xl, xl, r4
816 shiftop orr xl xl xh lsl r5 r2
817 and r2, xh, #0x80000000
818 bic xh, xh, #0x80000000
819 adds xl, xl, r3, lsr #31
820 shiftop adc xh r2 xh lsr r4 r6
821 orrs lr, lr, r3, lsl #1
822 do_it eq
823 biceq xl, xl, r3, lsr #31
824 RETLDM "r4, r5, r6"
825
826 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
827 @ a register switch from xh to xl. Then round.
828 1: rsb r4, r4, #12
829 rsb r5, r4, #32
830 shift1 lsl, r3, xl, r4
831 shift1 lsr, xl, xl, r5
832 shiftop orr xl xl xh lsl r4 r2
833 bic xh, xh, #0x7fffffff
834 adds xl, xl, r3, lsr #31
835 adc xh, xh, #0
836 orrs lr, lr, r3, lsl #1
837 do_it eq
838 biceq xl, xl, r3, lsr #31
839 RETLDM "r4, r5, r6"
840
841 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
842 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
843 2: rsb r5, r4, #32
844 shiftop orr lr lr xl lsl r5 r2
845 shift1 lsr, r3, xl, r4
846 shiftop orr r3 r3 xh lsl r5 r2
847 shift1 lsr, xl, xh, r4
848 bic xh, xh, #0x7fffffff
849 shiftop bic xl xl xh lsr r4 r2
850 add xl, xl, r3, lsr #31
851 orrs lr, lr, r3, lsl #1
852 do_it eq
853 biceq xl, xl, r3, lsr #31
854 RETLDM "r4, r5, r6"
855
856 @ One or both arguments are denormalized.
857 @ Scale them leftwards and preserve sign bit.
858 LSYM(Lml_d):
859 teq r4, #0
860 bne 2f
861 and r6, xh, #0x80000000
862 1: movs xl, xl, lsl #1
863 adc xh, xh, xh
864 tst xh, #0x00100000
865 do_it eq
866 subeq r4, r4, #1
867 beq 1b
868 orr xh, xh, r6
869 teq r5, #0
870 do_it ne
871 RETc(ne)
872 2: and r6, yh, #0x80000000
873 3: movs yl, yl, lsl #1
874 adc yh, yh, yh
875 tst yh, #0x00100000
876 do_it eq
877 subeq r5, r5, #1
878 beq 3b
879 orr yh, yh, r6
880 RET
881
882 LSYM(Lml_s):
883 @ Isolate the INF and NAN cases away
884 teq r4, ip
885 and r5, ip, yh, lsr #20
886 do_it ne
887 teqne r5, ip
888 beq 1f
889
890 @ Here, one or more arguments are either denormalized or zero.
891 orrs r6, xl, xh, lsl #1
892 do_it ne
893 COND(orr,s,ne) r6, yl, yh, lsl #1
894 bne LSYM(Lml_d)
895
896 @ Result is 0, but determine sign anyway.
897 LSYM(Lml_z):
898 eor xh, xh, yh
899 and xh, xh, #0x80000000
900 mov xl, #0
901 RETLDM "r4, r5, r6"
902
903 1: @ One or both args are INF or NAN.
904 orrs r6, xl, xh, lsl #1
905 do_it eq, te
906 moveq xl, yl
907 moveq xh, yh
908 COND(orr,s,ne) r6, yl, yh, lsl #1
909 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
910 teq r4, ip
911 bne 1f
912 orrs r6, xl, xh, lsl #12
913 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
914 1: teq r5, ip
915 bne LSYM(Lml_i)
916 orrs r6, yl, yh, lsl #12
917 do_it ne, t
918 movne xl, yl
919 movne xh, yh
920 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
921
922 @ Result is INF, but we need to determine its sign.
923 LSYM(Lml_i):
924 eor xh, xh, yh
925
926 @ Overflow: return INF (sign already in xh).
927 LSYM(Lml_o):
928 and xh, xh, #0x80000000
929 orr xh, xh, #0x7f000000
930 orr xh, xh, #0x00f00000
931 mov xl, #0
932 RETLDM "r4, r5, r6"
933
934 @ Return a quiet NAN.
935 LSYM(Lml_n):
936 orr xh, xh, #0x7f000000
937 orr xh, xh, #0x00f80000
938 RETLDM "r4, r5, r6"
939
940 CFI_END_FUNCTION
941 FUNC_END aeabi_dmul
942 FUNC_END muldf3
943
944 ARM_FUNC_START divdf3
945 ARM_FUNC_ALIAS aeabi_ddiv divdf3
946 CFI_START_FUNCTION
947
948 do_push {r4, r5, r6, lr}
949 .cfi_adjust_cfa_offset 16
950 .cfi_rel_offset r4, 0
951 .cfi_rel_offset r5, 4
952 .cfi_rel_offset r6, 8
953 .cfi_rel_offset lr, 12
954
955 @ Mask out exponents, trap any zero/denormal/INF/NAN.
956 mov ip, #0xff
957 orr ip, ip, #0x700
958 ands r4, ip, xh, lsr #20
959 do_it ne, tte
960 COND(and,s,ne) r5, ip, yh, lsr #20
961 teqne r4, ip
962 teqne r5, ip
963 bleq LSYM(Ldv_s)
964
965 @ Subtract divisor exponent from dividend''s.
966 sub r4, r4, r5
967
968 @ Preserve final sign into lr.
969 eor lr, xh, yh
970
971 @ Convert mantissa to unsigned integer.
972 @ Dividend -> r5-r6, divisor -> yh-yl.
973 orrs r5, yl, yh, lsl #12
974 mov xh, xh, lsl #12
975 beq LSYM(Ldv_1)
976 mov yh, yh, lsl #12
977 mov r5, #0x10000000
978 orr yh, r5, yh, lsr #4
979 orr yh, yh, yl, lsr #24
980 mov yl, yl, lsl #8
981 orr r5, r5, xh, lsr #4
982 orr r5, r5, xl, lsr #24
983 mov r6, xl, lsl #8
984
985 @ Initialize xh with final sign bit.
986 and xh, lr, #0x80000000
987
988 @ Ensure result will land to known bit position.
989 @ Apply exponent bias accordingly.
990 cmp r5, yh
991 do_it eq
992 cmpeq r6, yl
993 adc r4, r4, #(255 - 2)
994 add r4, r4, #0x300
995 bcs 1f
996 movs yh, yh, lsr #1
997 mov yl, yl, rrx
998 1:
999 @ Perform first subtraction to align result to a nibble.
1000 subs r6, r6, yl
1001 sbc r5, r5, yh
1002 movs yh, yh, lsr #1
1003 mov yl, yl, rrx
1004 mov xl, #0x00100000
1005 mov ip, #0x00080000
1006
1007 @ The actual division loop.
1008 1: subs lr, r6, yl
1009 sbcs lr, r5, yh
1010 do_it cs, tt
1011 subcs r6, r6, yl
1012 movcs r5, lr
1013 orrcs xl, xl, ip
1014 movs yh, yh, lsr #1
1015 mov yl, yl, rrx
1016 subs lr, r6, yl
1017 sbcs lr, r5, yh
1018 do_it cs, tt
1019 subcs r6, r6, yl
1020 movcs r5, lr
1021 orrcs xl, xl, ip, lsr #1
1022 movs yh, yh, lsr #1
1023 mov yl, yl, rrx
1024 subs lr, r6, yl
1025 sbcs lr, r5, yh
1026 do_it cs, tt
1027 subcs r6, r6, yl
1028 movcs r5, lr
1029 orrcs xl, xl, ip, lsr #2
1030 movs yh, yh, lsr #1
1031 mov yl, yl, rrx
1032 subs lr, r6, yl
1033 sbcs lr, r5, yh
1034 do_it cs, tt
1035 subcs r6, r6, yl
1036 movcs r5, lr
1037 orrcs xl, xl, ip, lsr #3
1038
1039 orrs lr, r5, r6
1040 beq 2f
1041 mov r5, r5, lsl #4
1042 orr r5, r5, r6, lsr #28
1043 mov r6, r6, lsl #4
1044 mov yh, yh, lsl #3
1045 orr yh, yh, yl, lsr #29
1046 mov yl, yl, lsl #3
1047 movs ip, ip, lsr #4
1048 bne 1b
1049
1050 @ We are done with a word of the result.
1051 @ Loop again for the low word if this pass was for the high word.
1052 tst xh, #0x00100000
1053 bne 3f
1054 orr xh, xh, xl
1055 mov xl, #0
1056 mov ip, #0x80000000
1057 b 1b
1058 2:
1059 @ Be sure result starts in the high word.
1060 tst xh, #0x00100000
1061 do_it eq, t
1062 orreq xh, xh, xl
1063 moveq xl, #0
1064 3:
1065 @ Check exponent range for under/overflow.
1066 subs ip, r4, #(254 - 1)
1067 do_it hi
1068 cmphi ip, #0x700
1069 bhi LSYM(Lml_u)
1070
1071 @ Round the result, merge final exponent.
1072 subs ip, r5, yh
1073 do_it eq, t
1074 COND(sub,s,eq) ip, r6, yl
1075 COND(mov,s,eq) ip, xl, lsr #1
1076 adcs xl, xl, #0
1077 adc xh, xh, r4, lsl #20
1078 RETLDM "r4, r5, r6"
1079
1080 @ Division by 0x1p*: shortcut a lot of code.
1081 LSYM(Ldv_1):
1082 and lr, lr, #0x80000000
1083 orr xh, lr, xh, lsr #12
1084 adds r4, r4, ip, lsr #1
1085 do_it gt, tt
1086 COND(rsb,s,gt) r5, r4, ip
1087 orrgt xh, xh, r4, lsl #20
1088 RETLDM "r4, r5, r6" gt
1089
1090 orr xh, xh, #0x00100000
1091 mov lr, #0
1092 subs r4, r4, #1
1093 b LSYM(Lml_u)
1094
1095 @ Result mightt need to be denormalized: put remainder bits
1096 @ in lr for rounding considerations.
1097 LSYM(Ldv_u):
1098 orr lr, r5, r6
1099 b LSYM(Lml_u)
1100
1101 @ One or both arguments is either INF, NAN or zero.
1102 LSYM(Ldv_s):
1103 and r5, ip, yh, lsr #20
1104 teq r4, ip
1105 do_it eq
1106 teqeq r5, ip
1107 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1108 teq r4, ip
1109 bne 1f
1110 orrs r4, xl, xh, lsl #12
1111 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1112 teq r5, ip
1113 bne LSYM(Lml_i) @ INF / <anything> -> INF
1114 mov xl, yl
1115 mov xh, yh
1116 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1117 1: teq r5, ip
1118 bne 2f
1119 orrs r5, yl, yh, lsl #12
1120 beq LSYM(Lml_z) @ <anything> / INF -> 0
1121 mov xl, yl
1122 mov xh, yh
1123 b LSYM(Lml_n) @ <anything> / NAN -> NAN
1124 2: @ If both are nonzero, we need to normalize and resume above.
1125 orrs r6, xl, xh, lsl #1
1126 do_it ne
1127 COND(orr,s,ne) r6, yl, yh, lsl #1
1128 bne LSYM(Lml_d)
1129 @ One or both arguments are 0.
1130 orrs r4, xl, xh, lsl #1
1131 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1132 orrs r5, yl, yh, lsl #1
1133 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1134 b LSYM(Lml_n) @ 0 / 0 -> NAN
1135
1136 CFI_END_FUNCTION
1137 FUNC_END aeabi_ddiv
1138 FUNC_END divdf3
1139
1140 #endif /* L_muldivdf3 */
1141
1142 #ifdef L_arm_cmpdf2
1143
1144 @ Note: only r0 (return value) and ip are clobbered here.
1145
1146 ARM_FUNC_START gtdf2
1147 ARM_FUNC_ALIAS gedf2 gtdf2
1148 CFI_START_FUNCTION
1149 mov ip, #-1
1150 b 1f
1151
1152 ARM_FUNC_START ltdf2
1153 ARM_FUNC_ALIAS ledf2 ltdf2
1154 mov ip, #1
1155 b 1f
1156
1157 ARM_FUNC_START cmpdf2
1158 ARM_FUNC_ALIAS nedf2 cmpdf2
1159 ARM_FUNC_ALIAS eqdf2 cmpdf2
1160 mov ip, #1 @ how should we specify unordered here?
1161
1162 1: str ip, [sp, #-4]!
1163 .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4.
1164 @ We're not adding CFI for ip as it's pushed into the stack
1165 @ only because it may be popped off later as a return value
1166 @ (i.e. we're not preserving it anyways).
1167
1168 @ Trap any INF/NAN first.
1169 mov ip, xh, lsl #1
1170 mvns ip, ip, asr #21
1171 mov ip, yh, lsl #1
1172 do_it ne
1173 COND(mvn,s,ne) ip, ip, asr #21
1174 beq 3f
1175 .cfi_remember_state
1176 @ Save the current CFI state. This is done because the branch
1177 @ is conditional, and if we don't take it we'll issue a
1178 @ .cfi_adjust_cfa_offset and return. If we do take it,
1179 @ however, the .cfi_adjust_cfa_offset from the non-branch code
1180 @ will affect the branch code as well. To avoid this we'll
1181 @ restore the current state before executing the branch code.
1182
1183 @ Test for equality. Note that 0.0 is equal to -0.0.
1184 2: add sp, sp, #4
1185 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1186
1187 orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1188 do_it eq, e
1189 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1190 teqne xh, yh @ or xh == yh
1191 do_it eq, tt
1192 teqeq xl, yl @ and xl == yl
1193 moveq r0, #0 @ then equal.
1194 RETc(eq)
1195
1196 @ Clear C flag
1197 cmn r0, #0
1198
1199 @ Compare sign,
1200 teq xh, yh
1201
1202 @ Compare values if same sign
1203 do_it pl
1204 cmppl xh, yh
1205 do_it eq
1206 cmpeq xl, yl
1207
1208 @ Result:
1209 do_it cs, e
1210 movcs r0, yh, asr #31
1211 mvncc r0, yh, asr #31
1212 orr r0, r0, #1
1213 RET
1214
1215 3: @ Look for a NAN.
1216
1217 @ Restore the previous CFI state (i.e. keep the CFI state as it was
1218 @ before the branch).
1219 .cfi_restore_state
1220
1221 mov ip, xh, lsl #1
1222 mvns ip, ip, asr #21
1223 bne 4f
1224 orrs ip, xl, xh, lsl #12
1225 bne 5f @ x is NAN
1226 4: mov ip, yh, lsl #1
1227 mvns ip, ip, asr #21
1228 bne 2b
1229 orrs ip, yl, yh, lsl #12
1230 beq 2b @ y is not NAN
1231
1232 5: ldr r0, [sp], #4 @ unordered return code
1233 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1234
1235 RET
1236
1237 CFI_END_FUNCTION
1238 FUNC_END gedf2
1239 FUNC_END gtdf2
1240 FUNC_END ledf2
1241 FUNC_END ltdf2
1242 FUNC_END nedf2
1243 FUNC_END eqdf2
1244 FUNC_END cmpdf2
1245
1246 ARM_FUNC_START aeabi_cdrcmple
1247 CFI_START_FUNCTION
1248
1249 mov ip, r0
1250 mov r0, r2
1251 mov r2, ip
1252 mov ip, r1
1253 mov r1, r3
1254 mov r3, ip
1255 b 6f
1256
1257 ARM_FUNC_START aeabi_cdcmpeq
1258 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1259
1260 @ The status-returning routines are required to preserve all
1261 @ registers except ip, lr, and cpsr.
1262 6: do_push {r0, lr}
1263 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8.
1264 .cfi_rel_offset r0, 0 @ Previous r0 is saved at sp.
1265 .cfi_rel_offset lr, 4 @ Previous lr is saved at sp + 4.
1266
1267 ARM_CALL cmpdf2
1268 @ Set the Z flag correctly, and the C flag unconditionally.
1269 cmp r0, #0
1270 @ Clear the C flag if the return value was -1, indicating
1271 @ that the first operand was smaller than the second.
1272 do_it mi
1273 cmnmi r0, #0
1274
1275 RETLDM "r0"
1276
1277 CFI_END_FUNCTION
1278 FUNC_END aeabi_cdcmple
1279 FUNC_END aeabi_cdcmpeq
1280 FUNC_END aeabi_cdrcmple
1281
1282 ARM_FUNC_START aeabi_dcmpeq
1283 CFI_START_FUNCTION
1284
1285 str lr, [sp, #-8]! @ sp -= 8
1286 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1287 .cfi_rel_offset lr, 0 @ lr is at sp
1288
1289 ARM_CALL aeabi_cdcmple
1290 do_it eq, e
1291 moveq r0, #1 @ Equal to.
1292 movne r0, #0 @ Less than, greater than, or unordered.
1293
1294 RETLDM
1295
1296 CFI_END_FUNCTION
1297 FUNC_END aeabi_dcmpeq
1298
1299 ARM_FUNC_START aeabi_dcmplt
1300 CFI_START_FUNCTION
1301
1302 str lr, [sp, #-8]! @ sp -= 8
1303 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1304 .cfi_rel_offset lr, 0 @ lr is at sp
1305
1306 ARM_CALL aeabi_cdcmple
1307 do_it cc, e
1308 movcc r0, #1 @ Less than.
1309 movcs r0, #0 @ Equal to, greater than, or unordered.
1310 RETLDM
1311
1312 CFI_END_FUNCTION
1313 FUNC_END aeabi_dcmplt
1314
1315 ARM_FUNC_START aeabi_dcmple
1316 CFI_START_FUNCTION
1317
1318 str lr, [sp, #-8]! @ sp -= 8
1319 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1320 .cfi_rel_offset lr, 0 @ lr is at sp
1321
1322 ARM_CALL aeabi_cdcmple
1323 do_it ls, e
1324 movls r0, #1 @ Less than or equal to.
1325 movhi r0, #0 @ Greater than or unordered.
1326 RETLDM
1327
1328 CFI_END_FUNCTION
1329 FUNC_END aeabi_dcmple
1330
1331 ARM_FUNC_START aeabi_dcmpge
1332 CFI_START_FUNCTION
1333
1334 str lr, [sp, #-8]! @ sp -= 8
1335 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1336 .cfi_rel_offset lr, 0 @ lr is at sp
1337
1338 ARM_CALL aeabi_cdrcmple
1339 do_it ls, e
1340 movls r0, #1 @ Operand 2 is less than or equal to operand 1.
1341 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
1342 RETLDM
1343
1344 CFI_END_FUNCTION
1345 FUNC_END aeabi_dcmpge
1346
1347 ARM_FUNC_START aeabi_dcmpgt
1348 CFI_START_FUNCTION
1349
1350 str lr, [sp, #-8]! @ sp -= 8
1351 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1352 .cfi_rel_offset lr, 0 @ lr is at sp
1353
1354 ARM_CALL aeabi_cdrcmple
1355 do_it cc, e
1356 movcc r0, #1 @ Operand 2 is less than operand 1.
1357 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
1358 @ or they are unordered.
1359 RETLDM
1360
1361 CFI_END_FUNCTION
1362 FUNC_END aeabi_dcmpgt
1363
1364 #endif /* L_cmpdf2 */
1365
1366 #ifdef L_arm_unorddf2
1367
1368 ARM_FUNC_START unorddf2
1369 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1370 .cfi_startproc
1371
1372 mov ip, xh, lsl #1
1373 mvns ip, ip, asr #21
1374 bne 1f
1375 orrs ip, xl, xh, lsl #12
1376 bne 3f @ x is NAN
1377 1: mov ip, yh, lsl #1
1378 mvns ip, ip, asr #21
1379 bne 2f
1380 orrs ip, yl, yh, lsl #12
1381 bne 3f @ y is NAN
1382 2: mov r0, #0 @ arguments are ordered.
1383 RET
1384
1385 3: mov r0, #1 @ arguments are unordered.
1386 RET
1387
1388 .cfi_endproc
1389 FUNC_END aeabi_dcmpun
1390 FUNC_END unorddf2
1391
1392 #endif /* L_unorddf2 */
1393
1394 #ifdef L_arm_fixdfsi
1395
1396 ARM_FUNC_START fixdfsi
1397 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1398 CFI_START_FUNCTION
1399
1400 @ check exponent range.
1401 mov r2, xh, lsl #1
1402 adds r2, r2, #(1 << 21)
1403 bcs 2f @ value is INF or NAN
1404 bpl 1f @ value is too small
1405 mov r3, #(0xfffffc00 + 31)
1406 subs r2, r3, r2, asr #21
1407 bls 3f @ value is too large
1408
1409 @ scale value
1410 mov r3, xh, lsl #11
1411 orr r3, r3, #0x80000000
1412 orr r3, r3, xl, lsr #21
1413 tst xh, #0x80000000 @ the sign bit
1414 shift1 lsr, r0, r3, r2
1415 do_it ne
1416 rsbne r0, r0, #0
1417 RET
1418
1419 1: mov r0, #0
1420 RET
1421
1422 2: orrs xl, xl, xh, lsl #12
1423 bne 4f @ x is NAN.
1424 3: ands r0, xh, #0x80000000 @ the sign bit
1425 do_it eq
1426 moveq r0, #0x7fffffff @ maximum signed positive si
1427 RET
1428
1429 4: mov r0, #0 @ How should we convert NAN?
1430 RET
1431
1432 CFI_END_FUNCTION
1433 FUNC_END aeabi_d2iz
1434 FUNC_END fixdfsi
1435
1436 #endif /* L_fixdfsi */
1437
1438 #ifdef L_arm_fixunsdfsi
1439
1440 ARM_FUNC_START fixunsdfsi
1441 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1442 CFI_START_FUNCTION
1443
1444 @ check exponent range.
1445 movs r2, xh, lsl #1
1446 bcs 1f @ value is negative
1447 adds r2, r2, #(1 << 21)
1448 bcs 2f @ value is INF or NAN
1449 bpl 1f @ value is too small
1450 mov r3, #(0xfffffc00 + 31)
1451 subs r2, r3, r2, asr #21
1452 bmi 3f @ value is too large
1453
1454 @ scale value
1455 mov r3, xh, lsl #11
1456 orr r3, r3, #0x80000000
1457 orr r3, r3, xl, lsr #21
1458 shift1 lsr, r0, r3, r2
1459 RET
1460
1461 1: mov r0, #0
1462 RET
1463
1464 2: orrs xl, xl, xh, lsl #12
1465 bne 4f @ value is NAN.
1466 3: mov r0, #0xffffffff @ maximum unsigned si
1467 RET
1468
1469 4: mov r0, #0 @ How should we convert NAN?
1470 RET
1471
1472 CFI_END_FUNCTION
1473 FUNC_END aeabi_d2uiz
1474 FUNC_END fixunsdfsi
1475
1476 #endif /* L_fixunsdfsi */
1477
1478 #ifdef L_arm_truncdfsf2
1479
1480 ARM_FUNC_START truncdfsf2
1481 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1482 CFI_START_FUNCTION
1483
1484 @ check exponent range.
1485 mov r2, xh, lsl #1
1486 subs r3, r2, #((1023 - 127) << 21)
1487 do_it cs, t
1488 COND(sub,s,cs) ip, r3, #(1 << 21)
1489 COND(rsb,s,cs) ip, ip, #(254 << 21)
1490 bls 2f @ value is out of range
1491
1492 1: @ shift and round mantissa
1493 and ip, xh, #0x80000000
1494 mov r2, xl, lsl #3
1495 orr xl, ip, xl, lsr #29
1496 cmp r2, #0x80000000
1497 adc r0, xl, r3, lsl #2
1498 do_it eq
1499 biceq r0, r0, #1
1500 RET
1501
1502 2: @ either overflow or underflow
1503 tst xh, #0x40000000
1504 bne 3f @ overflow
1505
1506 @ check if denormalized value is possible
1507 adds r2, r3, #(23 << 21)
1508 do_it lt, t
1509 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1510 RETc(lt)
1511
1512 @ denormalize value so we can resume with the code above afterwards.
1513 orr xh, xh, #0x00100000
1514 mov r2, r2, lsr #21
1515 rsb r2, r2, #24
1516 rsb ip, r2, #32
1517 #if defined(__thumb2__)
1518 lsls r3, xl, ip
1519 #else
1520 movs r3, xl, lsl ip
1521 #endif
1522 shift1 lsr, xl, xl, r2
1523 do_it ne
1524 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1525 mov r3, xh, lsl #11
1526 mov r3, r3, lsr #11
1527 shiftop orr xl xl r3 lsl ip ip
1528 shift1 lsr, r3, r3, r2
1529 mov r3, r3, lsl #1
1530 b 1b
1531
1532 3: @ chech for NAN
1533 mvns r3, r2, asr #21
1534 bne 5f @ simple overflow
1535 orrs r3, xl, xh, lsl #12
1536 do_it ne, tt
1537 movne r0, #0x7f000000
1538 orrne r0, r0, #0x00c00000
1539 RETc(ne) @ return NAN
1540
1541 5: @ return INF with sign
1542 and r0, xh, #0x80000000
1543 orr r0, r0, #0x7f000000
1544 orr r0, r0, #0x00800000
1545 RET
1546
1547 CFI_END_FUNCTION
1548 FUNC_END aeabi_d2f
1549 FUNC_END truncdfsf2
1550
1551 #endif /* L_truncdfsf2 */