ieee754-df.S revision 1.1.1.3 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 (at) 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 function
164 @ 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 teq r2, #0 @ if actually 0
511 do_it ne, e
512 teqne r3, #0xff000000 @ or INF or NAN
513 RETc(eq) @ we are done already.
514
515 @ value was denormalized. We can normalize it now.
516 do_push {r4, r5, lr}
517 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
518 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8.
519 .cfi_rel_offset r5, 4
520 .cfi_rel_offset lr, 8
521
522 mov r4, #0x380 @ setup corresponding exponent
523 and r5, xh, #0x80000000 @ move sign bit in r5
524 bic xh, xh, #0x80000000
525 b LSYM(Lad_l)
526
527 CFI_END_FUNCTION
528 FUNC_END aeabi_f2d
529 FUNC_END extendsfdf2
530
531 ARM_FUNC_START floatundidf
532 ARM_FUNC_ALIAS aeabi_ul2d floatundidf
533 CFI_START_FUNCTION
534 .cfi_remember_state @ Save the current CFA state.
535
536 orrs r2, r0, r1
537 do_it eq
538 RETc(eq)
539
540 do_push {r4, r5, lr} @ sp -= 12
541 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
542 .cfi_rel_offset r4, 0 @ Registers are saved from sp + 0 to sp + 8
543 .cfi_rel_offset r5, 4
544 .cfi_rel_offset lr, 8
545
546 mov r5, #0
547 b 2f
548
549 ARM_FUNC_START floatdidf
550 ARM_FUNC_ALIAS aeabi_l2d floatdidf
551 .cfi_restore_state
552 @ Restore the CFI state we saved above. If we didn't do this then the
553 @ following instructions would have the CFI state that was set by the
554 @ offset adjustments made in floatundidf.
555
556 orrs r2, r0, r1
557 do_it eq
558 RETc(eq)
559
560 do_push {r4, r5, lr} @ sp -= 12
561 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12
562 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 8
563 .cfi_rel_offset r5, 4
564 .cfi_rel_offset lr, 8
565
566 ands r5, ah, #0x80000000 @ sign bit in r5
567 bpl 2f
568 #if defined(__thumb2__)
569 negs al, al
570 sbc ah, ah, ah, lsl #1
571 #else
572 rsbs al, al, #0
573 rsc ah, ah, #0
574 #endif
575 2:
576 mov r4, #0x400 @ initial exponent
577 add r4, r4, #(52-1 - 1)
578
579 @ If FP word order does not match integer word order, swap the words.
580 .ifnc xh, ah
581 mov ip, al
582 mov xh, ah
583 mov xl, ip
584 .endif
585
586 movs ip, xh, lsr #22
587 beq LSYM(Lad_p)
588
589 @ The value is too big. Scale it down a bit...
590 mov r2, #3
591 movs ip, ip, lsr #3
592 do_it ne
593 addne r2, r2, #3
594 movs ip, ip, lsr #3
595 do_it ne
596 addne r2, r2, #3
597 add r2, r2, ip, lsr #3
598
599 rsb r3, r2, #32
600 shift1 lsl, ip, xl, r3
601 shift1 lsr, xl, xl, r2
602 shiftop orr xl xl xh lsl r3 lr
603 shift1 lsr, xh, xh, r2
604 add r4, r4, r2
605 b LSYM(Lad_p)
606
607 CFI_END_FUNCTION
608 FUNC_END floatdidf
609 FUNC_END aeabi_l2d
610 FUNC_END floatundidf
611 FUNC_END aeabi_ul2d
612
613 #endif /* L_addsubdf3 */
614
615 #ifdef L_arm_muldivdf3
616
617 ARM_FUNC_START muldf3
618 ARM_FUNC_ALIAS aeabi_dmul muldf3
619 CFI_START_FUNCTION
620
621 do_push {r4, r5, r6, lr} @ sp -= 16
622 .cfi_adjust_cfa_offset 16 @ CFA is now sp + previousOffset + 16
623 .cfi_rel_offset r4, 0 @ Registers are saved from sp to sp + 12.
624 .cfi_rel_offset r5, 4
625 .cfi_rel_offset r6, 8
626 .cfi_rel_offset lr, 12
627
628 @ Mask out exponents, trap any zero/denormal/INF/NAN.
629 mov ip, #0xff
630 orr ip, ip, #0x700
631 ands r4, ip, xh, lsr #20
632 do_it ne, tte
633 COND(and,s,ne) r5, ip, yh, lsr #20
634 teqne r4, ip
635 teqne r5, ip
636 bleq LSYM(Lml_s)
637
638 @ Add exponents together
639 add r4, r4, r5
640
641 @ Determine final sign.
642 eor r6, xh, yh
643
644 @ Convert mantissa to unsigned integer.
645 @ If power of two, branch to a separate path.
646 bic xh, xh, ip, lsl #21
647 bic yh, yh, ip, lsl #21
648 orrs r5, xl, xh, lsl #12
649 do_it ne
650 COND(orr,s,ne) r5, yl, yh, lsl #12
651 orr xh, xh, #0x00100000
652 orr yh, yh, #0x00100000
653 beq LSYM(Lml_1)
654
655 #if __ARM_ARCH__ < 4
656
657 @ Put sign bit in r6, which will be restored in yl later.
658 and r6, r6, #0x80000000
659
660 @ Well, no way to make it shorter without the umull instruction.
661 stmfd sp!, {r6, r7, r8, r9, sl, fp} @ sp -= 24
662 .cfi_remember_state @ Save the current CFI state.
663 .cfi_adjust_cfa_offset 24 @ CFA is now sp + previousOffset + 24.
664 .cfi_rel_offset r6, 0 @ Registers are saved from sp to sp + 20.
665 .cfi_rel_offset r7, 4
666 .cfi_rel_offset r8, 8
667 .cfi_rel_offset r9, 12
668 .cfi_rel_offset sl, 16
669 .cfi_rel_offset fp, 20
670
671 mov r7, xl, lsr #16
672 mov r8, yl, lsr #16
673 mov r9, xh, lsr #16
674 mov sl, yh, lsr #16
675 bic xl, xl, r7, lsl #16
676 bic yl, yl, r8, lsl #16
677 bic xh, xh, r9, lsl #16
678 bic yh, yh, sl, lsl #16
679 mul ip, xl, yl
680 mul fp, xl, r8
681 mov lr, #0
682 adds ip, ip, fp, lsl #16
683 adc lr, lr, fp, lsr #16
684 mul fp, r7, yl
685 adds ip, ip, fp, lsl #16
686 adc lr, lr, fp, lsr #16
687 mul fp, xl, sl
688 mov r5, #0
689 adds lr, lr, fp, lsl #16
690 adc r5, r5, fp, lsr #16
691 mul fp, r7, yh
692 adds lr, lr, fp, lsl #16
693 adc r5, r5, fp, lsr #16
694 mul fp, xh, r8
695 adds lr, lr, fp, lsl #16
696 adc r5, r5, fp, lsr #16
697 mul fp, r9, yl
698 adds lr, lr, fp, lsl #16
699 adc r5, r5, fp, lsr #16
700 mul fp, xh, sl
701 mul r6, r9, sl
702 adds r5, r5, fp, lsl #16
703 adc r6, r6, fp, lsr #16
704 mul fp, r9, yh
705 adds r5, r5, fp, lsl #16
706 adc r6, r6, fp, lsr #16
707 mul fp, xl, yh
708 adds lr, lr, fp
709 mul fp, r7, sl
710 adcs r5, r5, fp
711 mul fp, xh, yl
712 adc r6, r6, #0
713 adds lr, lr, fp
714 mul fp, r9, r8
715 adcs r5, r5, fp
716 mul fp, r7, r8
717 adc r6, r6, #0
718 adds lr, lr, fp
719 mul fp, xh, yh
720 adcs r5, r5, fp
721 adc r6, r6, #0
722 ldmfd sp!, {yl, r7, r8, r9, sl, fp} @ sp += 24
723 .cfi_restore_state @ Restore the previous CFI state.
724 #else
725
726 @ Here is the actual multiplication.
727 umull ip, lr, xl, yl
728 mov r5, #0
729 umlal lr, r5, xh, yl
730 and yl, r6, #0x80000000
731 umlal lr, r5, xl, yh
732 mov r6, #0
733 umlal r5, r6, xh, yh
734
735 #endif
736
737 @ The LSBs in ip are only significant for the final rounding.
738 @ Fold them into lr.
739 teq ip, #0
740 do_it ne
741 orrne lr, lr, #1
742
743 @ Adjust result upon the MSB position.
744 sub r4, r4, #0xff
745 cmp r6, #(1 << (20-11))
746 sbc r4, r4, #0x300
747 bcs 1f
748 movs lr, lr, lsl #1
749 adcs r5, r5, r5
750 adc r6, r6, r6
751 1:
752 @ Shift to final position, add sign to result.
753 orr xh, yl, r6, lsl #11
754 orr xh, xh, r5, lsr #21
755 mov xl, r5, lsl #11
756 orr xl, xl, lr, lsr #21
757 mov lr, lr, lsl #11
758
759 @ Check exponent range for under/overflow.
760 subs ip, r4, #(254 - 1)
761 do_it hi
762 cmphi ip, #0x700
763 bhi LSYM(Lml_u)
764
765 @ Round the result, merge final exponent.
766 cmp lr, #0x80000000
767 do_it eq
768 COND(mov,s,eq) lr, xl, lsr #1
769 adcs xl, xl, #0
770 adc xh, xh, r4, lsl #20
771 RETLDM "r4, r5, r6"
772
773 @ Multiplication by 0x1p*: let''s shortcut a lot of code.
774 LSYM(Lml_1):
775 and r6, r6, #0x80000000
776 orr xh, r6, xh
777 orr xl, xl, yl
778 eor xh, xh, yh
779 subs r4, r4, ip, lsr #1
780 do_it gt, tt
781 COND(rsb,s,gt) r5, r4, ip
782 orrgt xh, xh, r4, lsl #20
783 RETLDM "r4, r5, r6" gt
784
785 @ Under/overflow: fix things up for the code below.
786 orr xh, xh, #0x00100000
787 mov lr, #0
788 subs r4, r4, #1
789 LSYM(Lml_u):
790 @ Overflow?
791 bgt LSYM(Lml_o)
792
793 @ Check if denormalized result is possible, otherwise return signed 0.
794 cmn r4, #(53 + 1)
795 do_it le, tt
796 movle xl, #0
797 bicle xh, xh, #0x7fffffff
798 RETLDM "r4, r5, r6" le
799
800 @ Find out proper shift value.
801 rsb r4, r4, #0
802 subs r4, r4, #32
803 bge 2f
804 adds r4, r4, #12
805 bgt 1f
806
807 @ shift result right of 1 to 20 bits, preserve sign bit, round, etc.
808 add r4, r4, #20
809 rsb r5, r4, #32
810 shift1 lsl, r3, xl, r5
811 shift1 lsr, xl, xl, r4
812 shiftop orr xl xl xh lsl r5 r2
813 and r2, xh, #0x80000000
814 bic xh, xh, #0x80000000
815 adds xl, xl, r3, lsr #31
816 shiftop adc xh r2 xh lsr r4 r6
817 orrs lr, lr, r3, lsl #1
818 do_it eq
819 biceq xl, xl, r3, lsr #31
820 RETLDM "r4, r5, r6"
821
822 @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
823 @ a register switch from xh to xl. Then round.
824 1: rsb r4, r4, #12
825 rsb r5, r4, #32
826 shift1 lsl, r3, xl, r4
827 shift1 lsr, xl, xl, r5
828 shiftop orr xl xl xh lsl r4 r2
829 bic xh, xh, #0x7fffffff
830 adds xl, xl, r3, lsr #31
831 adc xh, xh, #0
832 orrs lr, lr, r3, lsl #1
833 do_it eq
834 biceq xl, xl, r3, lsr #31
835 RETLDM "r4, r5, r6"
836
837 @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
838 @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
839 2: rsb r5, r4, #32
840 shiftop orr lr lr xl lsl r5 r2
841 shift1 lsr, r3, xl, r4
842 shiftop orr r3 r3 xh lsl r5 r2
843 shift1 lsr, xl, xh, r4
844 bic xh, xh, #0x7fffffff
845 shiftop bic xl xl xh lsr r4 r2
846 add xl, xl, r3, lsr #31
847 orrs lr, lr, r3, lsl #1
848 do_it eq
849 biceq xl, xl, r3, lsr #31
850 RETLDM "r4, r5, r6"
851
852 @ One or both arguments are denormalized.
853 @ Scale them leftwards and preserve sign bit.
854 LSYM(Lml_d):
855 teq r4, #0
856 bne 2f
857 and r6, xh, #0x80000000
858 1: movs xl, xl, lsl #1
859 adc xh, xh, xh
860 tst xh, #0x00100000
861 do_it eq
862 subeq r4, r4, #1
863 beq 1b
864 orr xh, xh, r6
865 teq r5, #0
866 do_it ne
867 RETc(ne)
868 2: and r6, yh, #0x80000000
869 3: movs yl, yl, lsl #1
870 adc yh, yh, yh
871 tst yh, #0x00100000
872 do_it eq
873 subeq r5, r5, #1
874 beq 3b
875 orr yh, yh, r6
876 RET
877
878 LSYM(Lml_s):
879 @ Isolate the INF and NAN cases away
880 teq r4, ip
881 and r5, ip, yh, lsr #20
882 do_it ne
883 teqne r5, ip
884 beq 1f
885
886 @ Here, one or more arguments are either denormalized or zero.
887 orrs r6, xl, xh, lsl #1
888 do_it ne
889 COND(orr,s,ne) r6, yl, yh, lsl #1
890 bne LSYM(Lml_d)
891
892 @ Result is 0, but determine sign anyway.
893 LSYM(Lml_z):
894 eor xh, xh, yh
895 and xh, xh, #0x80000000
896 mov xl, #0
897 RETLDM "r4, r5, r6"
898
899 1: @ One or both args are INF or NAN.
900 orrs r6, xl, xh, lsl #1
901 do_it eq, te
902 moveq xl, yl
903 moveq xh, yh
904 COND(orr,s,ne) r6, yl, yh, lsl #1
905 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
906 teq r4, ip
907 bne 1f
908 orrs r6, xl, xh, lsl #12
909 bne LSYM(Lml_n) @ NAN * <anything> -> NAN
910 1: teq r5, ip
911 bne LSYM(Lml_i)
912 orrs r6, yl, yh, lsl #12
913 do_it ne, t
914 movne xl, yl
915 movne xh, yh
916 bne LSYM(Lml_n) @ <anything> * NAN -> NAN
917
918 @ Result is INF, but we need to determine its sign.
919 LSYM(Lml_i):
920 eor xh, xh, yh
921
922 @ Overflow: return INF (sign already in xh).
923 LSYM(Lml_o):
924 and xh, xh, #0x80000000
925 orr xh, xh, #0x7f000000
926 orr xh, xh, #0x00f00000
927 mov xl, #0
928 RETLDM "r4, r5, r6"
929
930 @ Return a quiet NAN.
931 LSYM(Lml_n):
932 orr xh, xh, #0x7f000000
933 orr xh, xh, #0x00f80000
934 RETLDM "r4, r5, r6"
935
936 CFI_END_FUNCTION
937 FUNC_END aeabi_dmul
938 FUNC_END muldf3
939
940 ARM_FUNC_START divdf3
941 ARM_FUNC_ALIAS aeabi_ddiv divdf3
942 CFI_START_FUNCTION
943
944 do_push {r4, r5, r6, lr}
945 .cfi_adjust_cfa_offset 16
946 .cfi_rel_offset r4, 0
947 .cfi_rel_offset r5, 4
948 .cfi_rel_offset r6, 8
949 .cfi_rel_offset lr, 12
950
951 @ Mask out exponents, trap any zero/denormal/INF/NAN.
952 mov ip, #0xff
953 orr ip, ip, #0x700
954 ands r4, ip, xh, lsr #20
955 do_it ne, tte
956 COND(and,s,ne) r5, ip, yh, lsr #20
957 teqne r4, ip
958 teqne r5, ip
959 bleq LSYM(Ldv_s)
960
961 @ Subtract divisor exponent from dividend''s.
962 sub r4, r4, r5
963
964 @ Preserve final sign into lr.
965 eor lr, xh, yh
966
967 @ Convert mantissa to unsigned integer.
968 @ Dividend -> r5-r6, divisor -> yh-yl.
969 orrs r5, yl, yh, lsl #12
970 mov xh, xh, lsl #12
971 beq LSYM(Ldv_1)
972 mov yh, yh, lsl #12
973 mov r5, #0x10000000
974 orr yh, r5, yh, lsr #4
975 orr yh, yh, yl, lsr #24
976 mov yl, yl, lsl #8
977 orr r5, r5, xh, lsr #4
978 orr r5, r5, xl, lsr #24
979 mov r6, xl, lsl #8
980
981 @ Initialize xh with final sign bit.
982 and xh, lr, #0x80000000
983
984 @ Ensure result will land to known bit position.
985 @ Apply exponent bias accordingly.
986 cmp r5, yh
987 do_it eq
988 cmpeq r6, yl
989 adc r4, r4, #(255 - 2)
990 add r4, r4, #0x300
991 bcs 1f
992 movs yh, yh, lsr #1
993 mov yl, yl, rrx
994 1:
995 @ Perform first subtraction to align result to a nibble.
996 subs r6, r6, yl
997 sbc r5, r5, yh
998 movs yh, yh, lsr #1
999 mov yl, yl, rrx
1000 mov xl, #0x00100000
1001 mov ip, #0x00080000
1002
1003 @ The actual division loop.
1004 1: subs lr, r6, yl
1005 sbcs lr, r5, yh
1006 do_it cs, tt
1007 subcs r6, r6, yl
1008 movcs r5, lr
1009 orrcs xl, xl, ip
1010 movs yh, yh, lsr #1
1011 mov yl, yl, rrx
1012 subs lr, r6, yl
1013 sbcs lr, r5, yh
1014 do_it cs, tt
1015 subcs r6, r6, yl
1016 movcs r5, lr
1017 orrcs xl, xl, ip, lsr #1
1018 movs yh, yh, lsr #1
1019 mov yl, yl, rrx
1020 subs lr, r6, yl
1021 sbcs lr, r5, yh
1022 do_it cs, tt
1023 subcs r6, r6, yl
1024 movcs r5, lr
1025 orrcs xl, xl, ip, lsr #2
1026 movs yh, yh, lsr #1
1027 mov yl, yl, rrx
1028 subs lr, r6, yl
1029 sbcs lr, r5, yh
1030 do_it cs, tt
1031 subcs r6, r6, yl
1032 movcs r5, lr
1033 orrcs xl, xl, ip, lsr #3
1034
1035 orrs lr, r5, r6
1036 beq 2f
1037 mov r5, r5, lsl #4
1038 orr r5, r5, r6, lsr #28
1039 mov r6, r6, lsl #4
1040 mov yh, yh, lsl #3
1041 orr yh, yh, yl, lsr #29
1042 mov yl, yl, lsl #3
1043 movs ip, ip, lsr #4
1044 bne 1b
1045
1046 @ We are done with a word of the result.
1047 @ Loop again for the low word if this pass was for the high word.
1048 tst xh, #0x00100000
1049 bne 3f
1050 orr xh, xh, xl
1051 mov xl, #0
1052 mov ip, #0x80000000
1053 b 1b
1054 2:
1055 @ Be sure result starts in the high word.
1056 tst xh, #0x00100000
1057 do_it eq, t
1058 orreq xh, xh, xl
1059 moveq xl, #0
1060 3:
1061 @ Check exponent range for under/overflow.
1062 subs ip, r4, #(254 - 1)
1063 do_it hi
1064 cmphi ip, #0x700
1065 bhi LSYM(Lml_u)
1066
1067 @ Round the result, merge final exponent.
1068 subs ip, r5, yh
1069 do_it eq, t
1070 COND(sub,s,eq) ip, r6, yl
1071 COND(mov,s,eq) ip, xl, lsr #1
1072 adcs xl, xl, #0
1073 adc xh, xh, r4, lsl #20
1074 RETLDM "r4, r5, r6"
1075
1076 @ Division by 0x1p*: shortcut a lot of code.
1077 LSYM(Ldv_1):
1078 and lr, lr, #0x80000000
1079 orr xh, lr, xh, lsr #12
1080 adds r4, r4, ip, lsr #1
1081 do_it gt, tt
1082 COND(rsb,s,gt) r5, r4, ip
1083 orrgt xh, xh, r4, lsl #20
1084 RETLDM "r4, r5, r6" gt
1085
1086 orr xh, xh, #0x00100000
1087 mov lr, #0
1088 subs r4, r4, #1
1089 b LSYM(Lml_u)
1090
1091 @ Result mightt need to be denormalized: put remainder bits
1092 @ in lr for rounding considerations.
1093 LSYM(Ldv_u):
1094 orr lr, r5, r6
1095 b LSYM(Lml_u)
1096
1097 @ One or both arguments is either INF, NAN or zero.
1098 LSYM(Ldv_s):
1099 and r5, ip, yh, lsr #20
1100 teq r4, ip
1101 do_it eq
1102 teqeq r5, ip
1103 beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
1104 teq r4, ip
1105 bne 1f
1106 orrs r4, xl, xh, lsl #12
1107 bne LSYM(Lml_n) @ NAN / <anything> -> NAN
1108 teq r5, ip
1109 bne LSYM(Lml_i) @ INF / <anything> -> INF
1110 mov xl, yl
1111 mov xh, yh
1112 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1113 1: teq r5, ip
1114 bne 2f
1115 orrs r5, yl, yh, lsl #12
1116 beq LSYM(Lml_z) @ <anything> / INF -> 0
1117 mov xl, yl
1118 mov xh, yh
1119 b LSYM(Lml_n) @ <anything> / NAN -> NAN
1120 2: @ If both are nonzero, we need to normalize and resume above.
1121 orrs r6, xl, xh, lsl #1
1122 do_it ne
1123 COND(orr,s,ne) r6, yl, yh, lsl #1
1124 bne LSYM(Lml_d)
1125 @ One or both arguments are 0.
1126 orrs r4, xl, xh, lsl #1
1127 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
1128 orrs r5, yl, yh, lsl #1
1129 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
1130 b LSYM(Lml_n) @ 0 / 0 -> NAN
1131
1132 CFI_END_FUNCTION
1133 FUNC_END aeabi_ddiv
1134 FUNC_END divdf3
1135
1136 #endif /* L_muldivdf3 */
1137
1138 #ifdef L_arm_cmpdf2
1139
1140 @ Note: only r0 (return value) and ip are clobbered here.
1141
1142 ARM_FUNC_START gtdf2
1143 ARM_FUNC_ALIAS gedf2 gtdf2
1144 CFI_START_FUNCTION
1145 mov ip, #-1
1146 b 1f
1147
1148 ARM_FUNC_START ltdf2
1149 ARM_FUNC_ALIAS ledf2 ltdf2
1150 mov ip, #1
1151 b 1f
1152
1153 ARM_FUNC_START cmpdf2
1154 ARM_FUNC_ALIAS nedf2 cmpdf2
1155 ARM_FUNC_ALIAS eqdf2 cmpdf2
1156 mov ip, #1 @ how should we specify unordered here?
1157
1158 1: str ip, [sp, #-4]!
1159 .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4.
1160 @ We're not adding CFI for ip as it's pushed into the stack
1161 @ only because @ it may be popped off later as a return value
1162 @ (i.e. we're not preserving @ it anyways).
1163
1164 @ Trap any INF/NAN first.
1165 mov ip, xh, lsl #1
1166 mvns ip, ip, asr #21
1167 mov ip, yh, lsl #1
1168 do_it ne
1169 COND(mvn,s,ne) ip, ip, asr #21
1170 beq 3f
1171 .cfi_remember_state
1172 @ Save the current CFI state. This is done because the branch
1173 @ is conditional, @ and if we don't take it we'll issue a
1174 @ .cfi_adjust_cfa_offset and return. @ If we do take it,
1175 @ however, the .cfi_adjust_cfa_offset from the non-branch @ code
1176 @ will affect the branch code as well. To avoid this we'll
1177 @ restore @ the current state before executing the branch code.
1178
1179 @ Test for equality. @ Note that 0.0 is equal to -0.0.
1180 2: add sp, sp, #4
1181 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1182
1183 orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0
1184 do_it eq, e
1185 COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0
1186 teqne xh, yh @ or xh == yh
1187 do_it eq, tt
1188 teqeq xl, yl @ and xl == yl
1189 moveq r0, #0 @ then equal.
1190 RETc(eq)
1191
1192 @ Clear C flag
1193 cmn r0, #0
1194
1195 @ Compare sign,
1196 teq xh, yh
1197
1198 @ Compare values if same sign
1199 do_it pl
1200 cmppl xh, yh
1201 do_it eq
1202 cmpeq xl, yl
1203
1204 @ Result:
1205 do_it cs, e
1206 movcs r0, yh, asr #31
1207 mvncc r0, yh, asr #31
1208 orr r0, r0, #1
1209 RET
1210
1211 3: @ Look for a NAN.
1212
1213 @ Restore the previous CFI state (i.e. keep the CFI state as it was
1214 @ before the branch).
1215 .cfi_restore_state
1216
1217 mov ip, xh, lsl #1
1218 mvns ip, ip, asr #21
1219 bne 4f
1220 orrs ip, xl, xh, lsl #12
1221 bne 5f @ x is NAN
1222 4: mov ip, yh, lsl #1
1223 mvns ip, ip, asr #21
1224 bne 2b
1225 orrs ip, yl, yh, lsl #12
1226 beq 2b @ y is not NAN
1227
1228 5: ldr r0, [sp], #4 @ unordered return code
1229 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset.
1230
1231 RET
1232
1233 CFI_END_FUNCTION
1234 FUNC_END gedf2
1235 FUNC_END gtdf2
1236 FUNC_END ledf2
1237 FUNC_END ltdf2
1238 FUNC_END nedf2
1239 FUNC_END eqdf2
1240 FUNC_END cmpdf2
1241
1242 ARM_FUNC_START aeabi_cdrcmple
1243 CFI_START_FUNCTION
1244
1245 mov ip, r0
1246 mov r0, r2
1247 mov r2, ip
1248 mov ip, r1
1249 mov r1, r3
1250 mov r3, ip
1251 b 6f
1252
1253 ARM_FUNC_START aeabi_cdcmpeq
1254 ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
1255
1256 @ The status-returning routines are required to preserve all
1257 @ registers except ip, lr, and cpsr.
1258 6: do_push {r0, lr}
1259 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8.
1260 .cfi_rel_offset r0, 0 @ Previous r0 is saved at sp.
1261 .cfi_rel_offset lr, 4 @ Previous lr is saved at sp + 4.
1262
1263 ARM_CALL cmpdf2
1264 @ Set the Z flag correctly, and the C flag unconditionally.
1265 cmp r0, #0
1266 @ Clear the C flag if the return value was -1, indicating
1267 @ that the first operand was smaller than the second.
1268 do_it mi
1269 cmnmi r0, #0
1270
1271 RETLDM "r0"
1272
1273 CFI_END_FUNCTION
1274 FUNC_END aeabi_cdcmple
1275 FUNC_END aeabi_cdcmpeq
1276 FUNC_END aeabi_cdrcmple
1277
1278 ARM_FUNC_START aeabi_dcmpeq
1279 CFI_START_FUNCTION
1280
1281 str lr, [sp, #-8]! @ sp -= 8
1282 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1283 .cfi_rel_offset lr, 0 @ lr is at sp
1284
1285 ARM_CALL aeabi_cdcmple
1286 do_it eq, e
1287 moveq r0, #1 @ Equal to.
1288 movne r0, #0 @ Less than, greater than, or unordered.
1289
1290 RETLDM
1291
1292 CFI_END_FUNCTION
1293 FUNC_END aeabi_dcmpeq
1294
1295 ARM_FUNC_START aeabi_dcmplt
1296 CFI_START_FUNCTION
1297
1298 str lr, [sp, #-8]! @ sp -= 8
1299 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1300 .cfi_rel_offset lr, 0 @ lr is at sp
1301
1302 ARM_CALL aeabi_cdcmple
1303 do_it cc, e
1304 movcc r0, #1 @ Less than.
1305 movcs r0, #0 @ Equal to, greater than, or unordered.
1306 RETLDM
1307
1308 CFI_END_FUNCTION
1309 FUNC_END aeabi_dcmplt
1310
1311 ARM_FUNC_START aeabi_dcmple
1312 CFI_START_FUNCTION
1313
1314 str lr, [sp, #-8]! @ sp -= 8
1315 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1316 .cfi_rel_offset lr, 0 @ lr is at sp
1317
1318 ARM_CALL aeabi_cdcmple
1319 do_it ls, e
1320 movls r0, #1 @ Less than or equal to.
1321 movhi r0, #0 @ Greater than or unordered.
1322 RETLDM
1323
1324 CFI_END_FUNCTION
1325 FUNC_END aeabi_dcmple
1326
1327 ARM_FUNC_START aeabi_dcmpge
1328 CFI_START_FUNCTION
1329
1330 str lr, [sp, #-8]! @ sp -= 8
1331 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1332 .cfi_rel_offset lr, 0 @ lr is at sp
1333
1334 ARM_CALL aeabi_cdrcmple
1335 do_it ls, e
1336 movls r0, #1 @ Operand 2 is less than or equal to operand 1.
1337 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
1338 RETLDM
1339
1340 CFI_END_FUNCTION
1341 FUNC_END aeabi_dcmpge
1342
1343 ARM_FUNC_START aeabi_dcmpgt
1344 CFI_START_FUNCTION
1345
1346 str lr, [sp, #-8]! @ sp -= 8
1347 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8
1348 .cfi_rel_offset lr, 0 @ lr is at sp
1349
1350 ARM_CALL aeabi_cdrcmple
1351 do_it cc, e
1352 movcc r0, #1 @ Operand 2 is less than operand 1.
1353 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
1354 @ or they are unordered.
1355 RETLDM
1356
1357 CFI_END_FUNCTION
1358 FUNC_END aeabi_dcmpgt
1359
1360 #endif /* L_cmpdf2 */
1361
1362 #ifdef L_arm_unorddf2
1363
1364 ARM_FUNC_START unorddf2
1365 ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
1366 .cfi_startproc
1367
1368 mov ip, xh, lsl #1
1369 mvns ip, ip, asr #21
1370 bne 1f
1371 orrs ip, xl, xh, lsl #12
1372 bne 3f @ x is NAN
1373 1: mov ip, yh, lsl #1
1374 mvns ip, ip, asr #21
1375 bne 2f
1376 orrs ip, yl, yh, lsl #12
1377 bne 3f @ y is NAN
1378 2: mov r0, #0 @ arguments are ordered.
1379 RET
1380
1381 3: mov r0, #1 @ arguments are unordered.
1382 RET
1383
1384 .cfi_endproc
1385 FUNC_END aeabi_dcmpun
1386 FUNC_END unorddf2
1387
1388 #endif /* L_unorddf2 */
1389
1390 #ifdef L_arm_fixdfsi
1391
1392 ARM_FUNC_START fixdfsi
1393 ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
1394 CFI_START_FUNCTION
1395
1396 @ check exponent range.
1397 mov r2, xh, lsl #1
1398 adds r2, r2, #(1 << 21)
1399 bcs 2f @ value is INF or NAN
1400 bpl 1f @ value is too small
1401 mov r3, #(0xfffffc00 + 31)
1402 subs r2, r3, r2, asr #21
1403 bls 3f @ value is too large
1404
1405 @ scale value
1406 mov r3, xh, lsl #11
1407 orr r3, r3, #0x80000000
1408 orr r3, r3, xl, lsr #21
1409 tst xh, #0x80000000 @ the sign bit
1410 shift1 lsr, r0, r3, r2
1411 do_it ne
1412 rsbne r0, r0, #0
1413 RET
1414
1415 1: mov r0, #0
1416 RET
1417
1418 2: orrs xl, xl, xh, lsl #12
1419 bne 4f @ x is NAN.
1420 3: ands r0, xh, #0x80000000 @ the sign bit
1421 do_it eq
1422 moveq r0, #0x7fffffff @ maximum signed positive si
1423 RET
1424
1425 4: mov r0, #0 @ How should we convert NAN?
1426 RET
1427
1428 CFI_END_FUNCTION
1429 FUNC_END aeabi_d2iz
1430 FUNC_END fixdfsi
1431
1432 #endif /* L_fixdfsi */
1433
1434 #ifdef L_arm_fixunsdfsi
1435
1436 ARM_FUNC_START fixunsdfsi
1437 ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
1438 CFI_START_FUNCTION
1439
1440 @ check exponent range.
1441 movs r2, xh, lsl #1
1442 bcs 1f @ value is negative
1443 adds r2, r2, #(1 << 21)
1444 bcs 2f @ value is INF or NAN
1445 bpl 1f @ value is too small
1446 mov r3, #(0xfffffc00 + 31)
1447 subs r2, r3, r2, asr #21
1448 bmi 3f @ value is too large
1449
1450 @ scale value
1451 mov r3, xh, lsl #11
1452 orr r3, r3, #0x80000000
1453 orr r3, r3, xl, lsr #21
1454 shift1 lsr, r0, r3, r2
1455 RET
1456
1457 1: mov r0, #0
1458 RET
1459
1460 2: orrs xl, xl, xh, lsl #12
1461 bne 4f @ value is NAN.
1462 3: mov r0, #0xffffffff @ maximum unsigned si
1463 RET
1464
1465 4: mov r0, #0 @ How should we convert NAN?
1466 RET
1467
1468 CFI_END_FUNCTION
1469 FUNC_END aeabi_d2uiz
1470 FUNC_END fixunsdfsi
1471
1472 #endif /* L_fixunsdfsi */
1473
1474 #ifdef L_arm_truncdfsf2
1475
1476 ARM_FUNC_START truncdfsf2
1477 ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
1478 CFI_START_FUNCTION
1479
1480 @ check exponent range.
1481 mov r2, xh, lsl #1
1482 subs r3, r2, #((1023 - 127) << 21)
1483 do_it cs, t
1484 COND(sub,s,cs) ip, r3, #(1 << 21)
1485 COND(rsb,s,cs) ip, ip, #(254 << 21)
1486 bls 2f @ value is out of range
1487
1488 1: @ shift and round mantissa
1489 and ip, xh, #0x80000000
1490 mov r2, xl, lsl #3
1491 orr xl, ip, xl, lsr #29
1492 cmp r2, #0x80000000
1493 adc r0, xl, r3, lsl #2
1494 do_it eq
1495 biceq r0, r0, #1
1496 RET
1497
1498 2: @ either overflow or underflow
1499 tst xh, #0x40000000
1500 bne 3f @ overflow
1501
1502 @ check if denormalized value is possible
1503 adds r2, r3, #(23 << 21)
1504 do_it lt, t
1505 andlt r0, xh, #0x80000000 @ too small, return signed 0.
1506 RETc(lt)
1507
1508 @ denormalize value so we can resume with the code above afterwards.
1509 orr xh, xh, #0x00100000
1510 mov r2, r2, lsr #21
1511 rsb r2, r2, #24
1512 rsb ip, r2, #32
1513 #if defined(__thumb2__)
1514 lsls r3, xl, ip
1515 #else
1516 movs r3, xl, lsl ip
1517 #endif
1518 shift1 lsr, xl, xl, r2
1519 do_it ne
1520 orrne xl, xl, #1 @ fold r3 for rounding considerations.
1521 mov r3, xh, lsl #11
1522 mov r3, r3, lsr #11
1523 shiftop orr xl xl r3 lsl ip ip
1524 shift1 lsr, r3, r3, r2
1525 mov r3, r3, lsl #1
1526 b 1b
1527
1528 3: @ chech for NAN
1529 mvns r3, r2, asr #21
1530 bne 5f @ simple overflow
1531 orrs r3, xl, xh, lsl #12
1532 do_it ne, tt
1533 movne r0, #0x7f000000
1534 orrne r0, r0, #0x00c00000
1535 RETc(ne) @ return NAN
1536
1537 5: @ return INF with sign
1538 and r0, xh, #0x80000000
1539 orr r0, r0, #0x7f000000
1540 orr r0, r0, #0x00800000
1541 RET
1542
1543 CFI_END_FUNCTION
1544 FUNC_END aeabi_d2f
1545 FUNC_END truncdfsf2
1546
1547 #endif /* L_truncdfsf2 */
1548