1238106Sdes/* ===-- fixunsdfsi.c - Implement __fixunsdfsi -----------------------------===
2238106Sdes *
3238106Sdes *                     The LLVM Compiler Infrastructure
4238106Sdes *
5269257Sdes * This file is dual licensed under the MIT and the University of Illinois Open
6238106Sdes * Source Licenses. See LICENSE.TXT for details.
7238106Sdes *
8238106Sdes * ===----------------------------------------------------------------------===
9269257Sdes *
10269257Sdes * This file implements __fixunsdfsi for the compiler_rt library.
11269257Sdes *
12269257Sdes * ===----------------------------------------------------------------------===
13269257Sdes */
14269257Sdes
15269257Sdes#include "int_lib.h"
16269257Sdes
17238106Sdes/* Returns: convert a to a unsigned int, rounding toward zero.
18269257Sdes *          Negative values all become zero.
19269257Sdes */
20269257Sdes
21238106Sdes/* Assumption: double is a IEEE 64 bit floating point type
22238106Sdes *             su_int is a 32 bit integral type
23238106Sdes *             value in double is representable in su_int or is negative
24238106Sdes *                 (no range checking performed)
25238106Sdes */
26238106Sdes
27238106Sdes/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
28238106Sdes
29238106SdesARM_EABI_FNALIAS(d2uiz, fixunsdfsi)
30238106Sdes
31238106SdesCOMPILER_RT_ABI su_int
32238106Sdes__fixunsdfsi(double a)
33238106Sdes{
34238106Sdes    double_bits fb;
35238106Sdes    fb.f = a;
36238106Sdes    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
37238106Sdes    if (e < 0 || (fb.u.s.high & 0x80000000))
38238106Sdes        return 0;
39238106Sdes    return (
40238106Sdes                0x80000000u                      |
41238106Sdes                ((fb.u.s.high & 0x000FFFFF) << 11) |
42238106Sdes                (fb.u.s.low >> 21)
43238106Sdes           ) >> (31 - e);
44238106Sdes}
45238106Sdes