fixunssfdi.c revision 296373
134355Sjb/* ===-- fixunssfdi.c - Implement __fixunssfdi -----------------------------===
234355Sjb *
346155Sphk *                     The LLVM Compiler Infrastructure
434355Sjb *
534355Sjb * This file is dual licensed under the MIT and the University of Illinois Open
634355Sjb * Source Licenses. See LICENSE.TXT for details.
734355Sjb *
834355Sjb * ===----------------------------------------------------------------------===
934355Sjb *
1034355Sjb * This file implements __fixunssfdi for the compiler_rt library.
1134355Sjb *
1234355Sjb * ===----------------------------------------------------------------------===
1334355Sjb */
1434355Sjb
1534355Sjb#include "int_lib.h"
1634355Sjb/* Returns: convert a to a unsigned long long, rounding toward zero.
1734355Sjb *          Negative values all become zero.
1834355Sjb */
1934355Sjb
2034355Sjb/* Assumption: float is a IEEE 32 bit floating point type
2134355Sjb *             du_int is a 64 bit integral type
2234355Sjb *             value in float is representable in du_int or is negative
2334355Sjb *                 (no range checking performed)
2434355Sjb */
2534355Sjb
2634355Sjb/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
2734355Sjb
2834355SjbARM_EABI_FNALIAS(f2ulz, fixunssfdi)
2934355Sjb
3034355SjbCOMPILER_RT_ABI du_int
3134355Sjb__fixunssfdi(float a)
3234355Sjb{
3334355Sjb    float_bits fb;
3434355Sjb    fb.f = a;
3534355Sjb    int e = ((fb.u & 0x7F800000) >> 23) - 127;
3634355Sjb    if (e < 0 || (fb.u & 0x80000000))
3734355Sjb        return 0;
3834355Sjb    du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
3934355Sjb    if (e > 23)
4034355Sjb        r <<= (e - 23);
4134355Sjb    else
4234355Sjb        r >>= (23 - e);
4334355Sjb    return r;
4434355Sjb}
4534355Sjb