1/* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include "pico/asm_helper.S" 8#include "pico/runtime_init.h" 9#include "pico/bootrom/sf_table.h" 10#include "hardware/divider_helper.S" 11 12PICO_RUNTIME_INIT_FUNC_RUNTIME(__aeabi_float_init, PICO_RUNTIME_INIT_AEABI_FLOAT) 13 14pico_default_asm_setup 15 16.macro float_section name 17#if PICO_FLOAT_IN_RAM 18.section RAM_SECTION_NAME(\name), "ax" 19#else 20.section SECTION_NAME(\name), "ax" 21#endif 22.endm 23 24.macro float_wrapper_section func 25float_section WRAPPER_FUNC_NAME(\func) 26.endm 27 28.macro _float_wrapper_func x 29 wrapper_func \x 30.endm 31 32.macro wrapper_func_f1 x 33 _float_wrapper_func \x 34#if PICO_FLOAT_PROPAGATE_NANS 35 mov ip, lr 36 bl __check_nan_f1 37 mov lr, ip 38#endif 39.endm 40 41.macro wrapper_func_f2 x 42 _float_wrapper_func \x 43#if PICO_FLOAT_PROPAGATE_NANS 44 mov ip, lr 45 bl __check_nan_f2 46 mov lr, ip 47#endif 48.endm 49 50.section .text 51 52#if PICO_FLOAT_PROPAGATE_NANS 53.thumb_func 54__check_nan_f1: 55 movs r3, #1 56 lsls r3, #24 57 lsls r2, r0, #1 58 adds r2, r3 59 bhi 1f 60 bx lr 611: 62 bx ip 63 64.thumb_func 65__check_nan_f2: 66 movs r3, #1 67 lsls r3, #24 68 lsls r2, r0, #1 69 adds r2, r3 70 bhi 1f 71 lsls r2, r1, #1 72 adds r2, r3 73 bhi 2f 74 bx lr 752: 76 mov r0, r1 771: 78 bx ip 79#endif 80 81.macro table_tail_call SF_TABLE_OFFSET 82#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED 83#ifndef NDEBUG 84 movs r3, #0 85 mov ip, r3 86#endif 87#endif 88 ldr r3, =sf_table 89 ldr r3, [r3, #\SF_TABLE_OFFSET] 90 bx r3 91.endm 92 93.macro shimmable_table_tail_call SF_TABLE_OFFSET shim 94 ldr r3, =sf_table 95 ldr r3, [r3, #\SF_TABLE_OFFSET] 96#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED 97 mov ip, pc 98#endif 99 bx r3 100#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED 101.byte \SF_TABLE_OFFSET, 0xdf 102.word \shim 103#endif 104.endm 105 106 107// note generally each function is in a separate section unless there is fall thru or branching between them 108// note fadd, fsub, fmul, fdiv are so tiny and just defer to rom so are lumped together so they can share constant pool 109 110// note functions are word aligned except where they are an odd number of linear instructions 111 112// float FUNC_NAME(__aeabi_fadd)(float, float) single-precision addition 113float_wrapper_section __aeabi_farithmetic 114// float FUNC_NAME(__aeabi_frsub)(float x, float y) single-precision reverse subtraction, y - x 115 116// frsub first because it is the only one that needs alignment 117.align 2 118wrapper_func __aeabi_frsub 119 eors r0, r1 120 eors r1, r0 121 eors r0, r1 122 // fall thru 123 124// float FUNC_NAME(__aeabi_fsub)(float x, float y) single-precision subtraction, x - y 125wrapper_func_f2 __aeabi_fsub 126#if PICO_FLOAT_PROPAGATE_NANS 127 // we want to return nan for inf-inf or -inf - -inf, but without too much upfront cost 128 mov r2, r0 129 eors r2, r1 130 bmi 1f // different signs 131 push {r0, r1, lr} 132 bl 1f 133 b fdiv_fsub_nan_helper 1341: 135#endif 136 table_tail_call SF_TABLE_FSUB 137 138wrapper_func_f2 __aeabi_fadd 139 table_tail_call SF_TABLE_FADD 140 141// float FUNC_NAME(__aeabi_fdiv)(float n, float d) single-precision division, n / d 142wrapper_func_f2 __aeabi_fdiv 143#if PICO_FLOAT_PROPAGATE_NANS 144 push {r0, r1, lr} 145 bl 1f 146 b fdiv_fsub_nan_helper 1471: 148#endif 149#if !PICO_DIVIDER_DISABLE_INTERRUPTS 150 // to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty 151 ldr r2, =(SIO_BASE) 152 ldr r3, [r2, #SIO_DIV_CSR_OFFSET] 153 lsrs r3, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY 154 bcs fdiv_save_state 155#else 156 // to avoid worrying about IRQs (or context switches), simply disable interrupts around call 157 push {r4, lr} 158 mrs r4, PRIMASK 159 cpsid i 160 bl fdiv_shim_call 161 msr PRIMASK, r4 162 pop {r4, pc} 163#endif 164fdiv_shim_call: 165 table_tail_call SF_TABLE_FDIV 166#if !PICO_DIVIDER_DISABLE_INTERRUPTS 167fdiv_save_state: 168 save_div_state_and_lr 169 bl fdiv_shim_call 170 ldr r2, =(SIO_BASE) 171 restore_div_state_and_return 172#endif 173 174fdiv_fsub_nan_helper: 175#if PICO_FLOAT_PROPAGATE_NANS 176 pop {r1, r2} 177 178 // check for infinite op infinite (or rather check for infinite result with both 179 // operands being infinite) 180 lsls r3, r0, #1 181 asrs r3, r3, #24 182 adds r3, #1 183 beq 2f 184 pop {pc} 1852: 186 lsls r1, #1 187 asrs r1, r1, #24 188 lsls r2, #1 189 asrs r2, r2, #24 190 ands r1, r2 191 adds r1, #1 192 bne 3f 193 // infinite to nan 194 movs r1, #1 195 lsls r1, #22 196 orrs r0, r1 1973: 198 pop {pc} 199#endif 200 201// float FUNC_NAME(__aeabi_fmul)(float, float) single-precision multiplication 202wrapper_func_f2 __aeabi_fmul 203#if PICO_FLOAT_PROPAGATE_NANS 204 push {r0, r1, lr} 205 bl 1f 206 pop {r1, r2} 207 208 // check for multiplication of infinite by zero (or rather check for infinite result with either 209 // operand 0) 210 lsls r3, r0, #1 211 asrs r3, r3, #24 212 adds r3, #1 213 beq 2f 214 pop {pc} 2152: 216 ands r1, r2 217 bne 3f 218 // infinite to nan 219 movs r1, #1 220 lsls r1, #22 221 orrs r0, r1 2223: 223 pop {pc} 2241: 225#endif 226 table_tail_call SF_TABLE_FMUL 227 228// void FUNC_NAME(__aeabi_cfrcmple)(float, float) reversed 3-way (<, =, ?>) compare [1], result in PSR ZC flags 229float_wrapper_section __aeabi_cfcmple 230.align 2 231wrapper_func __aeabi_cfrcmple 232 push {r0-r2, lr} 233 eors r0, r1 234 eors r1, r0 235 eors r0, r1 236 b __aeabi_cfcmple_guts 237 238// NOTE these share an implementation as we have no excepting NaNs. 239// void FUNC_NAME(__aeabi_cfcmple)(float, float) 3-way (<, =, ?>) compare [1], result in PSR ZC flags 240// void FUNC_NAME(__aeabi_cfcmpeq)(float, float) non-excepting equality comparison [1], result in PSR ZC flags 241.align 2 242wrapper_func __aeabi_cfcmple 243wrapper_func __aeabi_cfcmpeq 244 push {r0-r2, lr} 245 246__aeabi_cfcmple_guts: 247 lsls r2,r0,#1 248 lsrs r2,#24 249 beq 1f 250 cmp r2,#0xff 251 bne 2f 252 lsls r2, r0, #9 253 bhi 3f 2541: 255 lsrs r0,#23 @ clear mantissa if denormal or infinite 256 lsls r0,#23 2572: 258 lsls r2,r1,#1 259 lsrs r2,#24 260 beq 1f 261 cmp r2,#0xff 262 bne 2f 263 lsls r2, r1, #9 264 bhi 3f 2651: 266 lsrs r1,#23 @ clear mantissa if denormal or infinite 267 lsls r1,#23 2682: 269 movs r2,#1 @ initialise result 270 eors r1,r0 271 bmi 2f @ opposite signs? then can proceed on basis of sign of x 272 eors r1,r0 @ restore y 273 bpl 1f 274 cmp r1,r0 275 pop {r0-r2, pc} 2761: 277 cmp r0,r1 278 pop {r0-r2, pc} 2792: 280 orrs r1, r0 @ handle 0/-0 281 adds r1, r1 @ note this always sets C 282 beq 3f 283 mvns r0, r0 @ carry inverse of r0 sign 284 adds r0, r0 2853: 286 pop {r0-r2, pc} 287 288 289// int FUNC_NAME(__aeabi_fcmpeq)(float, float) result (1, 0) denotes (=, ?<>) [2], use for C == and != 290float_wrapper_section __aeabi_fcmpeq 291.align 2 292wrapper_func __aeabi_fcmpeq 293 push {lr} 294 bl __aeabi_cfcmpeq 295 beq 1f 296 movs r0, #0 297 pop {pc} 2981: 299 movs r0, #1 300 pop {pc} 301 302// int FUNC_NAME(__aeabi_fcmplt)(float, float) result (1, 0) denotes (<, ?>=) [2], use for C < 303float_wrapper_section __aeabi_fcmplt 304.align 2 305wrapper_func __aeabi_fcmplt 306 push {lr} 307 bl __aeabi_cfcmple 308 sbcs r0, r0 309 pop {pc} 310 311// int FUNC_NAME(__aeabi_fcmple)(float, float) result (1, 0) denotes (<=, ?>) [2], use for C <= 312float_wrapper_section __aeabi_fcmple 313.align 2 314wrapper_func __aeabi_fcmple 315 push {lr} 316 bl __aeabi_cfcmple 317 bls 1f 318 movs r0, #0 319 pop {pc} 3201: 321 movs r0, #1 322 pop {pc} 323 324// int FUNC_NAME(__aeabi_fcmpge)(float, float) result (1, 0) denotes (>=, ?<) [2], use for C >= 325float_wrapper_section __aeabi_fcmpge 326.align 2 327wrapper_func __aeabi_fcmpge 328 push {lr} 329 // because of NaNs it is better to reverse the args than the result 330 bl __aeabi_cfrcmple 331 bls 1f 332 movs r0, #0 333 pop {pc} 3341: 335 movs r0, #1 336 pop {pc} 337 338// int FUNC_NAME(__aeabi_fcmpgt)(float, float) result (1, 0) denotes (>, ?<=) [2], use for C > 339float_wrapper_section __aeabi_fcmpgt 340wrapper_func __aeabi_fcmpgt 341 push {lr} 342 // because of NaNs it is better to reverse the args than the result 343 bl __aeabi_cfrcmple 344 sbcs r0, r0 345 pop {pc} 346 347// int FUNC_NAME(__aeabi_fcmpun)(float, float) result (1, 0) denotes (?, <=>) [2], use for C99 isunordered() 348float_wrapper_section __aeabi_fcmpun 349wrapper_func __aeabi_fcmpun 350 movs r3, #1 351 lsls r3, #24 352 lsls r2, r0, #1 353 adds r2, r3 354 bhi 1f 355 lsls r2, r1, #1 356 adds r2, r3 357 bhi 1f 358 movs r0, #0 359 bx lr 3601: 361 movs r0, #1 362 bx lr 363 364 365// float FUNC_NAME(__aeabi_ui2f)(unsigned) unsigned to float (single precision) conversion 366float_wrapper_section __aeabi_ui2f 367wrapper_func __aeabi_ui2f 368regular_func uint2float 369 subs r1, r1 370 cmp r0, #0 371 bne __aeabi_i2f_main 372 mov r0, r1 373 bx lr 374 375float_wrapper_section __aeabi_i2f 376// float FUNC_NAME(__aeabi_i2f)(int) integer to float (single precision) conversion 377wrapper_func __aeabi_i2f 378regular_func int2float 379 lsrs r1, r0, #31 380 lsls r1, #31 381 bpl 1f 382 negs r0, r0 3831: 384 cmp r0, #0 385 beq 7f 386__aeabi_i2f_main: 387 388 mov ip, lr 389 push {r0, r1} 390 ldr r3, =sf_clz_func 391 ldr r3, [r3] 392 blx r3 393 pop {r1, r2} 394 lsls r1, r0 395 subs r0, #158 396 negs r0, r0 397 398 adds r1,#0x80 @ rounding 399 bcs 5f @ tripped carry? then have leading 1 in C as required (and result is even so can ignore sticky bits) 400 401 lsls r3,r1,#24 @ check bottom 8 bits of r1 402 beq 6f @ in rounding-tie case? 403 lsls r1,#1 @ remove leading 1 4043: 405 lsrs r1,#9 @ align mantissa 406 lsls r0,#23 @ align exponent 407 orrs r0,r2 @ assemble exponent and mantissa 4084: 409 orrs r0,r1 @ apply sign 4101: 411 bx ip 4125: 413 adds r0,#1 @ correct exponent offset 414 b 3b 4156: 416 lsrs r1,#9 @ ensure even result 417 lsls r1,#10 418 b 3b 4197: 420 bx lr 421 422 423// int FUNC_NAME(__aeabi_f2iz)(float) float (single precision) to integer C-style conversion [3] 424float_wrapper_section __aeabi_f2iz 425wrapper_func __aeabi_f2iz 426regular_func float2int_z 427 lsls r1, r0, #1 428 lsrs r2, r1, #24 429 movs r3, #0x80 430 lsls r3, #24 431 cmp r2, #126 432 ble 1f 433 subs r2, #158 434 bge 2f 435 asrs r1, r0, #31 436 lsls r0, #9 437 lsrs r0, #1 438 orrs r0, r3 439 negs r2, r2 440 lsrs r0, r2 441 lsls r1, #1 442 adds r1, #1 443 muls r0, r1 444 bx lr 4451: 446 movs r0, #0 447 bx lr 4482: 449 lsrs r0, #31 450 adds r0, r3 451 subs r0, #1 452 bx lr 453 454 cmn r0, r0 455 bcc float2int 456 push {lr} 457 lsls r0, #1 458 lsrs r0, #1 459 movs r1, #0 460 bl __aeabi_f2uiz 461 cmp r0, #0 462 bmi 1f 463 negs r0, r0 464 pop {pc} 4651: 466 movs r0, #128 467 lsls r0, #24 468 pop {pc} 469 470float_section float2int 471regular_func float2int 472 shimmable_table_tail_call SF_TABLE_FLOAT2INT float2int_shim 473 474float_section float2fix 475regular_func float2fix 476 shimmable_table_tail_call SF_TABLE_FLOAT2FIX float2fix_shim 477 478float_section float2ufix 479regular_func float2ufix 480 table_tail_call SF_TABLE_FLOAT2UFIX 481 482// unsigned FUNC_NAME(__aeabi_f2uiz)(float) float (single precision) to unsigned C-style conversion [3] 483float_wrapper_section __aeabi_f2uiz 484wrapper_func __aeabi_f2uiz 485regular_func float2uint_z 486 table_tail_call SF_TABLE_FLOAT2UINT 487 488float_section fix2float 489regular_func fix2float 490 table_tail_call SF_TABLE_FIX2FLOAT 491 492float_section ufix2float 493regular_func ufix2float 494 table_tail_call SF_TABLE_UFIX2FLOAT 495 496float_section fix642float 497regular_func fix642float 498 shimmable_table_tail_call SF_TABLE_FIX642FLOAT fix642float_shim 499 500float_section ufix642float 501regular_func ufix642float 502 shimmable_table_tail_call SF_TABLE_UFIX642FLOAT ufix642float_shim 503 504// float FUNC_NAME(__aeabi_l2f)(long long) long long to float (single precision) conversion 505float_wrapper_section __aeabi_l2f 5061: 507 ldr r2, =__aeabi_i2f 508 bx r2 509wrapper_func __aeabi_l2f 510regular_func int642float 511 asrs r2, r0, #31 512 cmp r1, r2 513 beq 1b 514 shimmable_table_tail_call SF_TABLE_INT642FLOAT int642float_shim 515 516// float FUNC_NAME(__aeabi_l2f)(long long) long long to float (single precision) conversion 517float_wrapper_section __aeabi_ul2f 5181: 519 ldr r2, =__aeabi_ui2f 520 bx r2 521wrapper_func __aeabi_ul2f 522regular_func uint642float 523 cmp r1, #0 524 beq 1b 525 shimmable_table_tail_call SF_TABLE_UINT642FLOAT uint642float_shim 526 527// long long FUNC_NAME(__aeabi_f2lz)(float) float (single precision) to long long C-style conversion [3] 528float_wrapper_section __aeabi_f2lz 529wrapper_func __aeabi_f2lz 530regular_func float2int64_z 531 cmn r0, r0 532 bcc float2int64 533 push {lr} 534 lsls r0, #1 535 lsrs r0, #1 536 movs r1, #0 537 bl float2ufix64 538 cmp r1, #0 539 bmi 1f 540 movs r2, #0 541 negs r0, r0 542 sbcs r2, r1 543 mov r1, r2 544 pop {pc} 5451: 546 movs r1, #128 547 lsls r1, #24 548 movs r0, #0 549 pop {pc} 550 551float_section float2int64 552regular_func float2int64 553 shimmable_table_tail_call SF_TABLE_FLOAT2INT64 float2int64_shim 554 555float_section float2fix64 556regular_func float2fix64 557 shimmable_table_tail_call SF_TABLE_FLOAT2FIX64 float2fix64_shim 558 559// unsigned long long FUNC_NAME(__aeabi_f2ulz)(float) float to unsigned long long C-style conversion [3] 560float_wrapper_section __aeabi_f2ulz 561wrapper_func __aeabi_f2ulz 562regular_func float2uint64_z 563 shimmable_table_tail_call SF_TABLE_FLOAT2UINT64 float2uint64_shim 564 565float_section float2ufix64 566regular_func float2ufix64 567 shimmable_table_tail_call SF_TABLE_FLOAT2UFIX64 float2ufix64_shim 568 569float_wrapper_section __aeabi_f2d 5701: 571#if PICO_FLOAT_PROPAGATE_NANS 572 // copy sign bit and 25 NAN id bits into sign bit and significant ID bits, also setting the high id bit 573 asrs r1, r0, #3 574 movs r2, #0xf 575 lsls r2, #27 576 orrs r1, r2 577 lsls r0, #25 578 bx lr 579#endif 580wrapper_func __aeabi_f2d 581#if PICO_FLOAT_PROPAGATE_NANS 582 movs r3, #1 583 lsls r3, #24 584 lsls r2, r0, #1 585 adds r2, r3 586 bhi 1b 587#endif 588 shimmable_table_tail_call SF_TABLE_FLOAT2DOUBLE float2double_shim 589 590float_wrapper_section sqrtf 591wrapper_func_f1 sqrtf 592#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED 593 // check for negative 594 asrs r1, r0, #23 595 bmi 1f 596#endif 597 table_tail_call SF_TABLE_FSQRT 598#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED 5991: 600 mvns r0, r1 601 cmp r0, #255 602 bne 2f 603 // -0 or -Denormal return -0 (0x80000000) 604 lsls r0, #31 605 bx lr 6062: 607 // return -Inf (0xff800000) 608 asrs r0, r1, #31 609 lsls r0, #23 610 bx lr 611#endif 612 613float_wrapper_section cosf 614// note we don't use _f1 since we do an infinity/nan check for outside of range 615wrapper_func cosf 616 // rom version only works for -128 < angle < 128 617 lsls r1, r0, #1 618 lsrs r1, #24 619 cmp r1, #127 + 7 620 bge 1f 6212: 622 table_tail_call SF_TABLE_FCOS 6231: 624#if PICO_FLOAT_PROPAGATE_NANS 625 // also check for infinites 626 cmp r1, #255 627 bne 3f 628 // infinite to nan 629 movs r1, #1 630 lsls r1, #22 631 orrs r0, r1 632 bx lr 6333: 634#endif 635 ldr r1, =0x40c90fdb // 2 * M_PI 636 push {lr} 637 bl remainderf 638 pop {r1} 639 mov lr, r1 640 b 2b 641 642float_wrapper_section sinf 643// note we don't use _f1 since we do an infinity/nan check for outside of range 644wrapper_func sinf 645 // rom version only works for -128 < angle < 128 646 lsls r1, r0, #1 647 lsrs r1, #24 648 cmp r1, #127 + 7 649 bge 1f 6502: 651 table_tail_call SF_TABLE_FSIN 6521: 653#if PICO_FLOAT_PROPAGATE_NANS 654 // also check for infinites 655 cmp r1, #255 656 bne 3f 657 // infinite to nan 658 movs r1, #1 659 lsls r1, #22 660 orrs r0, r1 661 bx lr 6623: 663#endif 664 ldr r1, =0x40c90fdb // 2 * M_PI 665 push {lr} 666 bl remainderf 667 pop {r1} 668 mov lr, r1 669 b 2b 670 671float_wrapper_section sincosf 672// note we don't use _f1 since we do an infinity/nan check for outside of range 673wrapper_func sincosf 674 push {r1, r2, lr} 675 // rom version only works for -128 < angle < 128 676 lsls r3, r0, #1 677 lsrs r3, #24 678 cmp r3, #127 + 7 679 bge 3f 6802: 681 ldr r3, =sf_table 682 ldr r3, [r3, #SF_TABLE_FSIN] 683 blx r3 684 pop {r2, r3} 685 str r0, [r2] 686 str r1, [r3] 687 pop {pc} 688#if PICO_FLOAT_PROPAGATE_NANS 689.align 2 690 pop {pc} 691#endif 6923: 693#if PICO_FLOAT_PROPAGATE_NANS 694 // also check for infinites 695 cmp r3, #255 696 bne 4f 697 // infinite to nan 698 movs r3, #1 699 lsls r3, #22 700 orrs r0, r3 701 str r0, [r1] 702 str r0, [r2] 703 add sp, #12 704 bx lr 7054: 706#endif 707 ldr r1, =0x40c90fdb // 2 * M_PI 708 push {lr} 709 bl remainderf 710 pop {r1} 711 mov lr, r1 712 b 2b 713 714float_wrapper_section tanf 715// note we don't use _f1 since we do an infinity/nan check for outside of range 716wrapper_func tanf 717 // rom version only works for -128 < angle < 128 718 lsls r1, r0, #1 719 lsrs r1, #24 720 cmp r1, #127 + 7 721 bge ftan_out_of_range 722ftan_in_range: 723#if !PICO_DIVIDER_DISABLE_INTERRUPTS 724 // to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty 725 ldr r2, =(SIO_BASE) 726 ldr r3, [r2, #SIO_DIV_CSR_OFFSET] 727 lsrs r3, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY 728 bcs ftan_save_state 729#else 730 // to avoid worrying about IRQs (or context switches), simply disable interrupts around call 731 push {r4, lr} 732 mrs r4, PRIMASK 733 cpsid i 734 bl ftan_shim_call 735 msr PRIMASK, r4 736 pop {r4, pc} 737#endif 738ftan_shim_call: 739 table_tail_call SF_TABLE_FTAN 740#if !PICO_DIVIDER_DISABLE_INTERRUPTS 741ftan_save_state: 742 save_div_state_and_lr 743 bl ftan_shim_call 744 ldr r2, =(SIO_BASE) 745 restore_div_state_and_return 746#endif 747ftan_out_of_range: 748#if PICO_FLOAT_PROPAGATE_NANS 749 // also check for infinites 750 cmp r1, #255 751 bne 3f 752 // infinite to nan 753 movs r1, #1 754 lsls r1, #22 755 orrs r0, r1 756 bx lr 7573: 758#endif 759 ldr r1, =0x40c90fdb // 2 * M_PI 760 push {lr} 761 bl remainderf 762 pop {r1} 763 mov lr, r1 764 b ftan_in_range 765 766float_wrapper_section atan2f 767wrapper_func_f2 atan2f 768 shimmable_table_tail_call SF_TABLE_FATAN2 fatan2_shim 769 770float_wrapper_section expf 771wrapper_func_f1 expf 772 table_tail_call SF_TABLE_FEXP 773 774float_wrapper_section logf 775wrapper_func_f1 logf 776 table_tail_call SF_TABLE_FLN 777