1/* ieee754-sf.S single-precision floating point support for ARM 2 3 Copyright (C) 2003-2018 Free Software Foundation, Inc. 4 Contributed by Nicolas Pitre (nico@cam.org) 5 6 This file is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published by the 8 Free Software Foundation; either version 3, or (at your option) any 9 later version. 10 11 This file is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 Under Section 7 of GPL version 3, you are granted additional 17 permissions described in the GCC Runtime Library Exception, version 18 3.1, as published by the Free Software Foundation. 19 20 You should have received a copy of the GNU General Public License and 21 a copy of the GCC Runtime Library Exception along with this program; 22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 <http://www.gnu.org/licenses/>. */ 24 25/* 26 * Notes: 27 * 28 * The goal of this code is to be as fast as possible. This is 29 * not meant to be easy to understand for the casual reader. 30 * 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 tst r0, #0x00800000 172 sub r2, r2, #1 173 bne LSYM(Lad_e) 174 175 @ No rounding necessary since r1 will always be 0 at this point. 176LSYM(Lad_l): 177 178#if __ARM_ARCH__ < 5 179 180 movs ip, r0, lsr #12 181 moveq r0, r0, lsl #12 182 subeq r2, r2, #12 183 tst r0, #0x00ff0000 184 moveq r0, r0, lsl #8 185 subeq r2, r2, #8 186 tst r0, #0x00f00000 187 moveq r0, r0, lsl #4 188 subeq r2, r2, #4 189 tst r0, #0x00c00000 190 moveq r0, r0, lsl #2 191 subeq r2, r2, #2 192 cmp r0, #0x00800000 193 movcc r0, r0, lsl #1 194 sbcs r2, r2, #0 195 196#else 197 198 clz ip, r0 199 sub ip, ip, #8 200 subs r2, r2, ip 201 shift1 lsl, r0, r0, ip 202 203#endif 204 205 @ Final result with sign 206 @ If exponent negative, denormalize result. 207 do_it ge, et 208 addge r0, r0, r2, lsl #23 209 rsblt r2, r2, #0 210 orrge r0, r0, r3 211#if defined(__thumb2__) 212 do_it lt, t 213 lsrlt r0, r0, r2 214 orrlt r0, r3, r0 215#else 216 orrlt r0, r3, r0, lsr r2 217#endif 218 RET 219 220 @ Fixup and adjust bit position for denormalized arguments. 221 @ Note that r2 must not remain equal to 0. 222LSYM(Lad_d): 223 teq r2, #0 224 eor r1, r1, #0x00800000 225 do_it eq, te 226 eoreq r0, r0, #0x00800000 227 addeq r2, r2, #1 228 subne r3, r3, #1 229 b LSYM(Lad_x) 230 231LSYM(Lad_s): 232 mov r3, r1, lsl #1 233 234 mvns ip, r2, asr #24 235 do_it ne 236 COND(mvn,s,ne) ip, r3, asr #24 237 beq LSYM(Lad_i) 238 239 teq r2, r3 240 beq 1f 241 242 @ Result is x + 0.0 = x or 0.0 + y = y. 243 teq r2, #0 244 do_it eq 245 moveq r0, r1 246 RET 247 2481: teq r0, r1 249 250 @ Result is x - x = 0. 251 do_it ne, t 252 movne r0, #0 253 RETc(ne) 254 255 @ Result is x + x = 2x. 256 tst r2, #0xff000000 257 bne 2f 258 movs r0, r0, lsl #1 259 do_it cs 260 orrcs r0, r0, #0x80000000 261 RET 2622: adds r2, r2, #(2 << 24) 263 do_it cc, t 264 addcc r0, r0, #(1 << 23) 265 RETc(cc) 266 and r3, r0, #0x80000000 267 268 @ Overflow: return INF. 269LSYM(Lad_o): 270 orr r0, r3, #0x7f000000 271 orr r0, r0, #0x00800000 272 RET 273 274 @ At least one of r0/r1 is INF/NAN. 275 @ if r0 != INF/NAN: return r1 (which is INF/NAN) 276 @ if r1 != INF/NAN: return r0 (which is INF/NAN) 277 @ if r0 or r1 is NAN: return NAN 278 @ if opposite sign: return NAN 279 @ otherwise return r0 (which is INF or -INF) 280LSYM(Lad_i): 281 mvns r2, r2, asr #24 282 do_it ne, et 283 movne r0, r1 284 COND(mvn,s,eq) r3, r3, asr #24 285 movne r1, r0 286 movs r2, r0, lsl #9 287 do_it eq, te 288 COND(mov,s,eq) r3, r1, lsl #9 289 teqeq r0, r1 290 orrne r0, r0, #0x00400000 @ quiet NAN 291 RET 292 293 CFI_END_FUNCTION 294 FUNC_END aeabi_frsub 295 FUNC_END aeabi_fadd 296 FUNC_END addsf3 297 FUNC_END aeabi_fsub 298 FUNC_END subsf3 299 300ARM_FUNC_START floatunsisf 301ARM_FUNC_ALIAS aeabi_ui2f floatunsisf 302 CFI_START_FUNCTION 303 304 mov r3, #0 305 b 1f 306 307ARM_FUNC_START floatsisf 308ARM_FUNC_ALIAS aeabi_i2f floatsisf 309 310 ands r3, r0, #0x80000000 311 do_it mi 312 rsbmi r0, r0, #0 313 3141: movs ip, r0 315 do_it eq 316 RETc(eq) 317 318 @ Add initial exponent to sign 319 orr r3, r3, #((127 + 23) << 23) 320 321 .ifnc ah, r0 322 mov ah, r0 323 .endif 324 mov al, #0 325 b 2f 326 327 CFI_END_FUNCTION 328 FUNC_END aeabi_i2f 329 FUNC_END floatsisf 330 FUNC_END aeabi_ui2f 331 FUNC_END floatunsisf 332 333ARM_FUNC_START floatundisf 334ARM_FUNC_ALIAS aeabi_ul2f floatundisf 335 CFI_START_FUNCTION 336 337 orrs r2, r0, r1 338 do_it eq 339 RETc(eq) 340 341 mov r3, #0 342 b 1f 343 344ARM_FUNC_START floatdisf 345ARM_FUNC_ALIAS aeabi_l2f floatdisf 346 347 orrs r2, r0, r1 348 do_it eq 349 RETc(eq) 350 351 ands r3, ah, #0x80000000 @ sign bit in r3 352 bpl 1f 353#if defined(__thumb2__) 354 negs al, al 355 sbc ah, ah, ah, lsl #1 356#else 357 rsbs al, al, #0 358 rsc ah, ah, #0 359#endif 3601: 361 movs ip, ah 362 do_it eq, tt 363 moveq ip, al 364 moveq ah, al 365 moveq al, #0 366 367 @ Add initial exponent to sign 368 orr r3, r3, #((127 + 23 + 32) << 23) 369 do_it eq 370 subeq r3, r3, #(32 << 23) 3712: sub r3, r3, #(1 << 23) 372 373#if __ARM_ARCH__ < 5 374 375 mov r2, #23 376 cmp ip, #(1 << 16) 377 do_it hs, t 378 movhs ip, ip, lsr #16 379 subhs r2, r2, #16 380 cmp ip, #(1 << 8) 381 do_it hs, t 382 movhs ip, ip, lsr #8 383 subhs r2, r2, #8 384 cmp ip, #(1 << 4) 385 do_it hs, t 386 movhs ip, ip, lsr #4 387 subhs r2, r2, #4 388 cmp ip, #(1 << 2) 389 do_it hs, e 390 subhs r2, r2, #2 391 sublo r2, r2, ip, lsr #1 392 subs r2, r2, ip, lsr #3 393 394#else 395 396 clz r2, ip 397 subs r2, r2, #8 398 399#endif 400 401 sub r3, r3, r2, lsl #23 402 blt 3f 403 404 shiftop add r3 r3 ah lsl r2 ip 405 shift1 lsl, ip, al, r2 406 rsb r2, r2, #32 407 cmp ip, #0x80000000 408 shiftop adc r0 r3 al lsr r2 r2 409 do_it eq 410 biceq r0, r0, #1 411 RET 412 4133: add r2, r2, #32 414 shift1 lsl, ip, ah, r2 415 rsb r2, r2, #32 416 orrs al, al, ip, lsl #1 417 shiftop adc r0 r3 ah lsr r2 r2 418 do_it eq 419 biceq r0, r0, ip, lsr #31 420 RET 421 422 CFI_END_FUNCTION 423 FUNC_END floatdisf 424 FUNC_END aeabi_l2f 425 FUNC_END floatundisf 426 FUNC_END aeabi_ul2f 427 428#endif /* L_addsubsf3 */ 429 430#ifdef L_arm_muldivsf3 431 432ARM_FUNC_START mulsf3 433ARM_FUNC_ALIAS aeabi_fmul mulsf3 434 CFI_START_FUNCTION 435 436 @ Mask out exponents, trap any zero/denormal/INF/NAN. 437 mov ip, #0xff 438 ands r2, ip, r0, lsr #23 439 do_it ne, tt 440 COND(and,s,ne) r3, ip, r1, lsr #23 441 teqne r2, ip 442 teqne r3, ip 443 beq LSYM(Lml_s) 444LSYM(Lml_x): 445 446 @ Add exponents together 447 add r2, r2, r3 448 449 @ Determine final sign. 450 eor ip, r0, r1 451 452 @ Convert mantissa to unsigned integer. 453 @ If power of two, branch to a separate path. 454 @ Make up for final alignment. 455 movs r0, r0, lsl #9 456 do_it ne 457 COND(mov,s,ne) r1, r1, lsl #9 458 beq LSYM(Lml_1) 459 mov r3, #0x08000000 460 orr r0, r3, r0, lsr #5 461 orr r1, r3, r1, lsr #5 462 463#if __ARM_ARCH__ < 4 464 465 @ Put sign bit in r3, which will be restored into r0 later. 466 and r3, ip, #0x80000000 467 468 @ Well, no way to make it shorter without the umull instruction. 469 do_push {r3, r4, r5} @ sp -= 12 470 .cfi_remember_state @ Save the current CFI state 471 .cfi_adjust_cfa_offset 12 @ CFA is now sp + previousOffset + 12 472 .cfi_rel_offset r3, 0 @ Registers are saved from sp to sp + 8 473 .cfi_rel_offset r4, 4 474 .cfi_rel_offset r5, 8 475 476 mov r4, r0, lsr #16 477 mov r5, r1, lsr #16 478 bic r0, r0, r4, lsl #16 479 bic r1, r1, r5, lsl #16 480 mul ip, r4, r5 481 mul r3, r0, r1 482 mul r0, r5, r0 483 mla r0, r4, r1, r0 484 adds r3, r3, r0, lsl #16 485 adc r1, ip, r0, lsr #16 486 do_pop {r0, r4, r5} @ sp += 12 487 .cfi_restore_state @ Restore the previous CFI state 488 489#else 490 491 @ The actual multiplication. 492 umull r3, r1, r0, r1 493 494 @ Put final sign in r0. 495 and r0, ip, #0x80000000 496 497#endif 498 499 @ Adjust result upon the MSB position. 500 cmp r1, #(1 << 23) 501 do_it cc, tt 502 movcc r1, r1, lsl #1 503 orrcc r1, r1, r3, lsr #31 504 movcc r3, r3, lsl #1 505 506 @ Add sign to result. 507 orr r0, r0, r1 508 509 @ Apply exponent bias, check for under/overflow. 510 sbc r2, r2, #127 511 cmp r2, #(254 - 1) 512 bhi LSYM(Lml_u) 513 514 @ Round the result, merge final exponent. 515 cmp r3, #0x80000000 516 adc r0, r0, r2, lsl #23 517 do_it eq 518 biceq r0, r0, #1 519 RET 520 521 @ Multiplication by 0x1p*: let''s shortcut a lot of code. 522LSYM(Lml_1): 523 teq r0, #0 524 and ip, ip, #0x80000000 525 do_it eq 526 moveq r1, r1, lsl #9 527 orr r0, ip, r0, lsr #9 528 orr r0, r0, r1, lsr #9 529 subs r2, r2, #127 530 do_it gt, tt 531 COND(rsb,s,gt) r3, r2, #255 532 orrgt r0, r0, r2, lsl #23 533 RETc(gt) 534 535 @ Under/overflow: fix things up for the code below. 536 orr r0, r0, #0x00800000 537 mov r3, #0 538 subs r2, r2, #1 539 540LSYM(Lml_u): 541 @ Overflow? 542 bgt LSYM(Lml_o) 543 544 @ Check if denormalized result is possible, otherwise return signed 0. 545 cmn r2, #(24 + 1) 546 do_it le, t 547 bicle r0, r0, #0x7fffffff 548 RETc(le) 549 550 @ Shift value right, round, etc. 551 rsb r2, r2, #0 552 movs r1, r0, lsl #1 553 shift1 lsr, r1, r1, r2 554 rsb r2, r2, #32 555 shift1 lsl, ip, r0, r2 556 movs r0, r1, rrx 557 adc r0, r0, #0 558 orrs r3, r3, ip, lsl #1 559 do_it eq 560 biceq r0, r0, ip, lsr #31 561 RET 562 563 @ One or both arguments are denormalized. 564 @ Scale them leftwards and preserve sign bit. 565LSYM(Lml_d): 566 teq r2, #0 567 and ip, r0, #0x80000000 5681: do_it eq, tt 569 moveq r0, r0, lsl #1 570 tsteq r0, #0x00800000 571 subeq r2, r2, #1 572 beq 1b 573 orr r0, r0, ip 574 teq r3, #0 575 and ip, r1, #0x80000000 5762: do_it eq, tt 577 moveq r1, r1, lsl #1 578 tsteq r1, #0x00800000 579 subeq r3, r3, #1 580 beq 2b 581 orr r1, r1, ip 582 b LSYM(Lml_x) 583 584LSYM(Lml_s): 585 @ Isolate the INF and NAN cases away 586 and r3, ip, r1, lsr #23 587 teq r2, ip 588 do_it ne 589 teqne r3, ip 590 beq 1f 591 592 @ Here, one or more arguments are either denormalized or zero. 593 bics ip, r0, #0x80000000 594 do_it ne 595 COND(bic,s,ne) ip, r1, #0x80000000 596 bne LSYM(Lml_d) 597 598 @ Result is 0, but determine sign anyway. 599LSYM(Lml_z): 600 eor r0, r0, r1 601 bic r0, r0, #0x7fffffff 602 RET 603 6041: @ One or both args are INF or NAN. 605 teq r0, #0x0 606 do_it ne, ett 607 teqne r0, #0x80000000 608 moveq r0, r1 609 teqne r1, #0x0 610 teqne r1, #0x80000000 611 beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN 612 teq r2, ip 613 bne 1f 614 movs r2, r0, lsl #9 615 bne LSYM(Lml_n) @ NAN * <anything> -> NAN 6161: teq r3, ip 617 bne LSYM(Lml_i) 618 movs r3, r1, lsl #9 619 do_it ne 620 movne r0, r1 621 bne LSYM(Lml_n) @ <anything> * NAN -> NAN 622 623 @ Result is INF, but we need to determine its sign. 624LSYM(Lml_i): 625 eor r0, r0, r1 626 627 @ Overflow: return INF (sign already in r0). 628LSYM(Lml_o): 629 and r0, r0, #0x80000000 630 orr r0, r0, #0x7f000000 631 orr r0, r0, #0x00800000 632 RET 633 634 @ Return a quiet NAN. 635LSYM(Lml_n): 636 orr r0, r0, #0x7f000000 637 orr r0, r0, #0x00c00000 638 RET 639 640 CFI_END_FUNCTION 641 FUNC_END aeabi_fmul 642 FUNC_END mulsf3 643 644ARM_FUNC_START divsf3 645ARM_FUNC_ALIAS aeabi_fdiv divsf3 646 CFI_START_FUNCTION 647 648 @ Mask out exponents, trap any zero/denormal/INF/NAN. 649 mov ip, #0xff 650 ands r2, ip, r0, lsr #23 651 do_it ne, tt 652 COND(and,s,ne) r3, ip, r1, lsr #23 653 teqne r2, ip 654 teqne r3, ip 655 beq LSYM(Ldv_s) 656LSYM(Ldv_x): 657 658 @ Subtract divisor exponent from dividend''s 659 sub r2, r2, r3 660 661 @ Preserve final sign into ip. 662 eor ip, r0, r1 663 664 @ Convert mantissa to unsigned integer. 665 @ Dividend -> r3, divisor -> r1. 666 movs r1, r1, lsl #9 667 mov r0, r0, lsl #9 668 beq LSYM(Ldv_1) 669 mov r3, #0x10000000 670 orr r1, r3, r1, lsr #4 671 orr r3, r3, r0, lsr #4 672 673 @ Initialize r0 (result) with final sign bit. 674 and r0, ip, #0x80000000 675 676 @ Ensure result will land to known bit position. 677 @ Apply exponent bias accordingly. 678 cmp r3, r1 679 do_it cc 680 movcc r3, r3, lsl #1 681 adc r2, r2, #(127 - 2) 682 683 @ The actual division loop. 684 mov ip, #0x00800000 6851: cmp r3, r1 686 do_it cs, t 687 subcs r3, r3, r1 688 orrcs r0, r0, ip 689 cmp r3, r1, lsr #1 690 do_it cs, t 691 subcs r3, r3, r1, lsr #1 692 orrcs r0, r0, ip, lsr #1 693 cmp r3, r1, lsr #2 694 do_it cs, t 695 subcs r3, r3, r1, lsr #2 696 orrcs r0, r0, ip, lsr #2 697 cmp r3, r1, lsr #3 698 do_it cs, t 699 subcs r3, r3, r1, lsr #3 700 orrcs r0, r0, ip, lsr #3 701 movs r3, r3, lsl #4 702 do_it ne 703 COND(mov,s,ne) ip, ip, lsr #4 704 bne 1b 705 706 @ Check exponent for under/overflow. 707 cmp r2, #(254 - 1) 708 bhi LSYM(Lml_u) 709 710 @ Round the result, merge final exponent. 711 cmp r3, r1 712 adc r0, r0, r2, lsl #23 713 do_it eq 714 biceq r0, r0, #1 715 RET 716 717 @ Division by 0x1p*: let''s shortcut a lot of code. 718LSYM(Ldv_1): 719 and ip, ip, #0x80000000 720 orr r0, ip, r0, lsr #9 721 adds r2, r2, #127 722 do_it gt, tt 723 COND(rsb,s,gt) r3, r2, #255 724 orrgt r0, r0, r2, lsl #23 725 RETc(gt) 726 727 orr r0, r0, #0x00800000 728 mov r3, #0 729 subs r2, r2, #1 730 b LSYM(Lml_u) 731 732 @ One or both arguments are denormalized. 733 @ Scale them leftwards and preserve sign bit. 734LSYM(Ldv_d): 735 teq r2, #0 736 and ip, r0, #0x80000000 7371: do_it eq, tt 738 moveq r0, r0, lsl #1 739 tsteq r0, #0x00800000 740 subeq r2, r2, #1 741 beq 1b 742 orr r0, r0, ip 743 teq r3, #0 744 and ip, r1, #0x80000000 7452: do_it eq, tt 746 moveq r1, r1, lsl #1 747 tsteq r1, #0x00800000 748 subeq r3, r3, #1 749 beq 2b 750 orr r1, r1, ip 751 b LSYM(Ldv_x) 752 753 @ One or both arguments are either INF, NAN, zero or denormalized. 754LSYM(Ldv_s): 755 and r3, ip, r1, lsr #23 756 teq r2, ip 757 bne 1f 758 movs r2, r0, lsl #9 759 bne LSYM(Lml_n) @ NAN / <anything> -> NAN 760 teq r3, ip 761 bne LSYM(Lml_i) @ INF / <anything> -> INF 762 mov r0, r1 763 b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN 7641: teq r3, ip 765 bne 2f 766 movs r3, r1, lsl #9 767 beq LSYM(Lml_z) @ <anything> / INF -> 0 768 mov r0, r1 769 b LSYM(Lml_n) @ <anything> / NAN -> NAN 7702: @ If both are nonzero, we need to normalize and resume above. 771 bics ip, r0, #0x80000000 772 do_it ne 773 COND(bic,s,ne) ip, r1, #0x80000000 774 bne LSYM(Ldv_d) 775 @ One or both arguments are zero. 776 bics r2, r0, #0x80000000 777 bne LSYM(Lml_i) @ <non_zero> / 0 -> INF 778 bics r3, r1, #0x80000000 779 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 780 b LSYM(Lml_n) @ 0 / 0 -> NAN 781 782 CFI_END_FUNCTION 783 FUNC_END aeabi_fdiv 784 FUNC_END divsf3 785 786#endif /* L_muldivsf3 */ 787 788#ifdef L_arm_cmpsf2 789 790 @ The return value in r0 is 791 @ 792 @ 0 if the operands are equal 793 @ 1 if the first operand is greater than the second, or 794 @ the operands are unordered and the operation is 795 @ CMP, LT, LE, NE, or EQ. 796 @ -1 if the first operand is less than the second, or 797 @ the operands are unordered and the operation is GT 798 @ or GE. 799 @ 800 @ The Z flag will be set iff the operands are equal. 801 @ 802 @ The following registers are clobbered by this function: 803 @ ip, r0, r1, r2, r3 804 805ARM_FUNC_START gtsf2 806ARM_FUNC_ALIAS gesf2 gtsf2 807 CFI_START_FUNCTION 808 mov ip, #-1 809 b 1f 810 811ARM_FUNC_START ltsf2 812ARM_FUNC_ALIAS lesf2 ltsf2 813 mov ip, #1 814 b 1f 815 816ARM_FUNC_START cmpsf2 817ARM_FUNC_ALIAS nesf2 cmpsf2 818ARM_FUNC_ALIAS eqsf2 cmpsf2 819 mov ip, #1 @ how should we specify unordered here? 820 8211: str ip, [sp, #-4]! 822 .cfi_adjust_cfa_offset 4 @ CFA is now sp + previousOffset + 4. 823 @ We're not adding CFI for ip as it's pushed into the stack only because 824 @ it may be popped off later as a return value (i.e. we're not preserving 825 @ it anyways). 826 827 @ Trap any INF/NAN first. 828 mov r2, r0, lsl #1 829 mov r3, r1, lsl #1 830 mvns ip, r2, asr #24 831 do_it ne 832 COND(mvn,s,ne) ip, r3, asr #24 833 beq 3f 834 .cfi_remember_state 835 @ Save the current CFI state. This is done because the branch is conditional, 836 @ and if we don't take it we'll issue a .cfi_adjust_cfa_offset and return. 837 @ If we do take it, however, the .cfi_adjust_cfa_offset from the non-branch 838 @ code will affect the branch code as well. To avoid this we'll restore 839 @ the current state before executing the branch code. 840 841 @ Compare values. 842 @ Note that 0.0 is equal to -0.0. 8432: add sp, sp, #4 844 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset. 845 846 orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag 847 do_it ne 848 teqne r0, r1 @ if not 0 compare sign 849 do_it pl 850 COND(sub,s,pl) r0, r2, r3 @ if same sign compare values, set r0 851 852 @ Result: 853 do_it hi 854 movhi r0, r1, asr #31 855 do_it lo 856 mvnlo r0, r1, asr #31 857 do_it ne 858 orrne r0, r0, #1 859 RET 860 8613: @ Look for a NAN. 862 863 @ Restore the previous CFI state (i.e. keep the CFI state as it was 864 @ before the branch). 865 .cfi_restore_state 866 867 mvns ip, r2, asr #24 868 bne 4f 869 movs ip, r0, lsl #9 870 bne 5f @ r0 is NAN 8714: mvns ip, r3, asr #24 872 bne 2b 873 movs ip, r1, lsl #9 874 beq 2b @ r1 is not NAN 875 8765: ldr r0, [sp], #4 @ return unordered code. 877 .cfi_adjust_cfa_offset -4 @ CFA is now sp + previousOffset. 878 RET 879 880 CFI_END_FUNCTION 881 FUNC_END gesf2 882 FUNC_END gtsf2 883 FUNC_END lesf2 884 FUNC_END ltsf2 885 FUNC_END nesf2 886 FUNC_END eqsf2 887 FUNC_END cmpsf2 888 889ARM_FUNC_START aeabi_cfrcmple 890 CFI_START_FUNCTION 891 892 mov ip, r0 893 mov r0, r1 894 mov r1, ip 895 b 6f 896 897ARM_FUNC_START aeabi_cfcmpeq 898ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq 899 900 @ The status-returning routines are required to preserve all 901 @ registers except ip, lr, and cpsr. 9026: do_push {r0, r1, r2, r3, lr} 903 .cfi_adjust_cfa_offset 20 @ CFA is at sp + previousOffset + 20 904 .cfi_rel_offset r0, 0 @ Registers are saved from sp to sp + 16 905 .cfi_rel_offset r1, 4 906 .cfi_rel_offset r2, 8 907 .cfi_rel_offset r3, 12 908 .cfi_rel_offset lr, 16 909 910 ARM_CALL cmpsf2 911 @ Set the Z flag correctly, and the C flag unconditionally. 912 cmp r0, #0 913 @ Clear the C flag if the return value was -1, indicating 914 @ that the first operand was smaller than the second. 915 do_it mi 916 cmnmi r0, #0 917 RETLDM "r0, r1, r2, r3" 918 919 CFI_END_FUNCTION 920 FUNC_END aeabi_cfcmple 921 FUNC_END aeabi_cfcmpeq 922 FUNC_END aeabi_cfrcmple 923 924ARM_FUNC_START aeabi_fcmpeq 925 CFI_START_FUNCTION 926 927 str lr, [sp, #-8]! @ sp -= 8 928 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 929 .cfi_rel_offset lr, 0 @ lr is at sp 930 931 ARM_CALL aeabi_cfcmple 932 do_it eq, e 933 moveq r0, #1 @ Equal to. 934 movne r0, #0 @ Less than, greater than, or unordered. 935 RETLDM 936 937 CFI_END_FUNCTION 938 FUNC_END aeabi_fcmpeq 939 940ARM_FUNC_START aeabi_fcmplt 941 CFI_START_FUNCTION 942 943 str lr, [sp, #-8]! @ sp -= 8 944 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 945 .cfi_rel_offset lr, 0 @ lr is at sp 946 947 ARM_CALL aeabi_cfcmple 948 do_it cc, e 949 movcc r0, #1 @ Less than. 950 movcs r0, #0 @ Equal to, greater than, or unordered. 951 RETLDM 952 953 CFI_END_FUNCTION 954 FUNC_END aeabi_fcmplt 955 956ARM_FUNC_START aeabi_fcmple 957 CFI_START_FUNCTION 958 959 str lr, [sp, #-8]! @ sp -= 8 960 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 961 .cfi_rel_offset lr, 0 @ lr is at sp 962 963 ARM_CALL aeabi_cfcmple 964 do_it ls, e 965 movls r0, #1 @ Less than or equal to. 966 movhi r0, #0 @ Greater than or unordered. 967 RETLDM 968 969 CFI_END_FUNCTION 970 FUNC_END aeabi_fcmple 971 972ARM_FUNC_START aeabi_fcmpge 973 CFI_START_FUNCTION 974 975 str lr, [sp, #-8]! @ sp -= 8 976 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 977 .cfi_rel_offset lr, 0 @ lr is at sp 978 979 ARM_CALL aeabi_cfrcmple 980 do_it ls, e 981 movls r0, #1 @ Operand 2 is less than or equal to operand 1. 982 movhi r0, #0 @ Operand 2 greater than operand 1, or unordered. 983 RETLDM 984 985 CFI_END_FUNCTION 986 FUNC_END aeabi_fcmpge 987 988ARM_FUNC_START aeabi_fcmpgt 989 CFI_START_FUNCTION 990 991 str lr, [sp, #-8]! @ sp -= 8 992 .cfi_adjust_cfa_offset 8 @ CFA is now sp + previousOffset + 8 993 .cfi_rel_offset lr, 0 @ lr is at sp 994 995 ARM_CALL aeabi_cfrcmple 996 do_it cc, e 997 movcc r0, #1 @ Operand 2 is less than operand 1. 998 movcs r0, #0 @ Operand 2 is greater than or equal to operand 1, 999 @ or they are unordered. 1000 RETLDM 1001 1002 CFI_END_FUNCTION 1003 FUNC_END aeabi_fcmpgt 1004 1005#endif /* L_cmpsf2 */ 1006 1007#ifdef L_arm_unordsf2 1008 1009ARM_FUNC_START unordsf2 1010ARM_FUNC_ALIAS aeabi_fcmpun unordsf2 1011 CFI_START_FUNCTION 1012 1013 mov r2, r0, lsl #1 1014 mov r3, r1, lsl #1 1015 mvns ip, r2, asr #24 1016 bne 1f 1017 movs ip, r0, lsl #9 1018 bne 3f @ r0 is NAN 10191: mvns ip, r3, asr #24 1020 bne 2f 1021 movs ip, r1, lsl #9 1022 bne 3f @ r1 is NAN 10232: mov r0, #0 @ arguments are ordered. 1024 RET 10253: mov r0, #1 @ arguments are unordered. 1026 RET 1027 1028 CFI_END_FUNCTION 1029 FUNC_END aeabi_fcmpun 1030 FUNC_END unordsf2 1031 1032#endif /* L_unordsf2 */ 1033 1034#ifdef L_arm_fixsfsi 1035 1036ARM_FUNC_START fixsfsi 1037ARM_FUNC_ALIAS aeabi_f2iz fixsfsi 1038 CFI_START_FUNCTION 1039 1040 @ check exponent range. 1041 mov r2, r0, lsl #1 1042 cmp r2, #(127 << 24) 1043 bcc 1f @ value is too small 1044 mov r3, #(127 + 31) 1045 subs r2, r3, r2, lsr #24 1046 bls 2f @ value is too large 1047 1048 @ scale value 1049 mov r3, r0, lsl #8 1050 orr r3, r3, #0x80000000 1051 tst r0, #0x80000000 @ the sign bit 1052 shift1 lsr, r0, r3, r2 1053 do_it ne 1054 rsbne r0, r0, #0 1055 RET 1056 10571: mov r0, #0 1058 RET 1059 10602: cmp r2, #(127 + 31 - 0xff) 1061 bne 3f 1062 movs r2, r0, lsl #9 1063 bne 4f @ r0 is NAN. 10643: ands r0, r0, #0x80000000 @ the sign bit 1065 do_it eq 1066 moveq r0, #0x7fffffff @ the maximum signed positive si 1067 RET 1068 10694: mov r0, #0 @ What should we convert NAN to? 1070 RET 1071 1072 CFI_END_FUNCTION 1073 FUNC_END aeabi_f2iz 1074 FUNC_END fixsfsi 1075 1076#endif /* L_fixsfsi */ 1077 1078#ifdef L_arm_fixunssfsi 1079 1080ARM_FUNC_START fixunssfsi 1081ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi 1082 CFI_START_FUNCTION 1083 1084 @ check exponent range. 1085 movs r2, r0, lsl #1 1086 bcs 1f @ value is negative 1087 cmp r2, #(127 << 24) 1088 bcc 1f @ value is too small 1089 mov r3, #(127 + 31) 1090 subs r2, r3, r2, lsr #24 1091 bmi 2f @ value is too large 1092 1093 @ scale the value 1094 mov r3, r0, lsl #8 1095 orr r3, r3, #0x80000000 1096 shift1 lsr, r0, r3, r2 1097 RET 1098 10991: mov r0, #0 1100 RET 1101 11022: cmp r2, #(127 + 31 - 0xff) 1103 bne 3f 1104 movs r2, r0, lsl #9 1105 bne 4f @ r0 is NAN. 11063: mov r0, #0xffffffff @ maximum unsigned si 1107 RET 1108 11094: mov r0, #0 @ What should we convert NAN to? 1110 RET 1111 1112 CFI_END_FUNCTION 1113 FUNC_END aeabi_f2uiz 1114 FUNC_END fixunssfsi 1115 1116#endif /* L_fixunssfsi */ 1117