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