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