summaryrefslogtreecommitdiff
path: root/src/libultra/gcc_fix/__floatundisf.c
blob: b69a6103818270cc72d2d9e3ea9a4fd9c48e295e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifdef COMPILER_GCC

typedef union DoubleFloatUnion {
    double d;
    long long int ll;
    unsigned long long ull;
} DoubleFloatUnion;

/**
 * Gets float32 from uint64_t.
 *
 * https://gcc.gnu.org/onlinedocs/gccint/the-gcc-low-level-runtime-library/routines-for-floating-point-emulation.html#c.__floatundisf
 */
float __floatundisf(unsigned long long i) {
    register DoubleFloatUnion dull;
    register float ret;

    dull.ull = i;
    __asm__("cvt.s.l %0, %1" : "=f"(ret) : "f"(dull.d));
    if ((long) i < 0) {
        // cvt.s.l assumes signed input, adjust output
        ret += 4294967296.0f; // 2^32
    }

    return ret;
}
#endif