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