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