1/* ieee754-df.S double-precision floating point support for ARM 2 3 Copyright (C) 2003-2021 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 58ARM_FUNC_START negdf2 59ARM_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 74ARM_FUNC_START aeabi_drsub 75 CFI_START_FUNCTION 76 77 eor xh, xh, #0x80000000 @ flip sign bit of first arg 78 b 1f 79 80ARM_FUNC_START subdf3 81ARM_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 88ARM_FUNC_START adddf3 89ARM_FUNC_ALIAS aeabi_dadd adddf3 90 911: 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 1241: 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 1451: 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 1571: 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. 167LSYM(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 1811: 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 1892: 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. 206LSYM(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. 227LSYM(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. 237LSYM(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. 247LSYM(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. 3001: add r2, r2, #20 3012: 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. 3153: 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. 3391: 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. 3482: 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. 354LSYM(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 364LSYM(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 3821: 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" 3982: 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. 405LSYM(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) 417LSYM(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 439ARM_FUNC_START floatunsidf 440ARM_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 467ARM_FUNC_START floatsidf 468ARM_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 497ARM_FUNC_START extendsfdf2 498ARM_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 536ARM_FUNC_START floatundidf 537ARM_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 554ARM_FUNC_START floatdidf 555ARM_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 5802: 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 629WEAK muldf3 630WEAK aeabi_dmul 631#endif 632 633ARM_FUNC_START muldf3 634ARM_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 6951: 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. 718LSYM(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 733LSYM(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. 7681: 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. 7832: 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. 798LSYM(Lml_d): 799 teq r4, #0 800 bne 2f 801 and r6, xh, #0x80000000 8021: 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) 8122: and r6, yh, #0x80000000 8133: 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 822LSYM(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. 837LSYM(Lml_z): 838 eor xh, xh, yh 839 and xh, xh, #0x80000000 840 mov xl, #0 841 RETLDM "r4, r5, r6" 842 8431: @ 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 8541: 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. 863LSYM(Lml_i): 864 eor xh, xh, yh 865 866 @ Overflow: return INF (sign already in xh). 867LSYM(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. 875LSYM(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 886ARM_FUNC_START divdf3 887ARM_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 9401: 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. 9501: 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 10002: 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 10063: 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. 1023LSYM(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. 1039LSYM(Ldv_u): 1040 orr lr, r5, r6 1041 b LSYM(Lml_u) 1042 1043 @ One or both arguments is either INF, NAN or zero. 1044LSYM(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 10591: 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 10662: @ 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 1089ARM_FUNC_START gtdf2 1090ARM_FUNC_ALIAS gedf2 gtdf2 1091 CFI_START_FUNCTION 1092 mov ip, #-1 1093 b 1f 1094 1095ARM_FUNC_START ltdf2 1096ARM_FUNC_ALIAS ledf2 ltdf2 1097 mov ip, #1 1098 b 1f 1099 1100ARM_FUNC_START cmpdf2 1101ARM_FUNC_ALIAS nedf2 cmpdf2 1102ARM_FUNC_ALIAS eqdf2 cmpdf2 1103 mov ip, #1 @ how should we specify unordered here? 1104 11051: 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. 11272: 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 11583: @ 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 11694: 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 11755: 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 1189ARM_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 1200ARM_FUNC_START aeabi_cdcmpeq 1201ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq 1202 1203 @ The status-returning routines are required to preserve all 1204 @ registers except ip, lr, and cpsr. 12056: 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 1225ARM_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 1242ARM_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 1258ARM_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 1274ARM_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 1290ARM_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 1311ARM_FUNC_START unorddf2 1312ARM_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 13201: 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 13252: mov r0, #0 @ arguments are ordered. 1326 RET 1327 13283: 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 1339ARM_FUNC_START fixdfsi 1340ARM_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 13621: mov r0, #0 1363 RET 1364 13652: orrs xl, xl, xh, lsl #12 1366 bne 4f @ x is NAN. 13673: ands r0, xh, #0x80000000 @ the sign bit 1368 do_it eq 1369 moveq r0, #0x7fffffff @ maximum signed positive si 1370 RET 1371 13724: 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 1383ARM_FUNC_START fixunsdfsi 1384ARM_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 14041: mov r0, #0 1405 RET 1406 14072: orrs xl, xl, xh, lsl #12 1408 bne 4f @ value is NAN. 14093: mov r0, #0xffffffff @ maximum unsigned si 1410 RET 1411 14124: 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 1423ARM_FUNC_START truncdfsf2 1424ARM_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 14351: @ 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 14452: @ 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 14753: @ 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 14845: @ 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 */ 1495