xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/floatdidf.c (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- floatdidf.c - Implement __floatdidf -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements __floatdidf for the compiler_rt library.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "int_lib.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric // Returns: convert a to a double, rounding toward even.
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric // Assumption: double is a IEEE 64 bit floating point type
180b57cec5SDimitry Andric //             di_int is a 64 bit integral type
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric // seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm
210b57cec5SDimitry Andric // mmmm
220b57cec5SDimitry Andric 
23fe6060f1SDimitry Andric #ifndef __SOFTFP__
240b57cec5SDimitry Andric // Support for systems that have hardware floating-point; we'll set the inexact
250b57cec5SDimitry Andric // flag as a side-effect of this computation.
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric COMPILER_RT_ABI double __floatdidf(di_int a) {
280b57cec5SDimitry Andric   static const double twop52 = 4503599627370496.0; // 0x1.0p52
290b57cec5SDimitry Andric   static const double twop32 = 4294967296.0;       // 0x1.0p32
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   union {
320b57cec5SDimitry Andric     int64_t x;
330b57cec5SDimitry Andric     double d;
340b57cec5SDimitry Andric   } low = {.d = twop52};
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   const double high = (int32_t)(a >> 32) * twop32;
370b57cec5SDimitry Andric   low.x |= a & INT64_C(0x00000000ffffffff);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   const double result = (high - twop52) + low.d;
400b57cec5SDimitry Andric   return result;
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #else
440b57cec5SDimitry Andric // Support for systems that don't have hardware floating-point; there are no
450b57cec5SDimitry Andric // flags to set, and we don't want to code-gen to an unknown soft-float
460b57cec5SDimitry Andric // implementation.
470b57cec5SDimitry Andric 
48*5f757f3fSDimitry Andric #define SRC_I64
49*5f757f3fSDimitry Andric #define DST_DOUBLE
50*5f757f3fSDimitry Andric #include "int_to_fp_impl.inc"
51*5f757f3fSDimitry Andric 
52*5f757f3fSDimitry Andric COMPILER_RT_ABI double __floatdidf(di_int a) { return __floatXiYf__(a); }
530b57cec5SDimitry Andric #endif
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #if defined(__ARM_EABI__)
560b57cec5SDimitry Andric #if defined(COMPILER_RT_ARMHF_TARGET)
570b57cec5SDimitry Andric AEABI_RTABI double __aeabi_l2d(di_int a) { return __floatdidf(a); }
580b57cec5SDimitry Andric #else
590b57cec5SDimitry Andric COMPILER_RT_ALIAS(__floatdidf, __aeabi_l2d)
600b57cec5SDimitry Andric #endif
610b57cec5SDimitry Andric #endif
62349cc55cSDimitry Andric 
63349cc55cSDimitry Andric #if defined(__MINGW32__) && defined(__arm__)
64349cc55cSDimitry Andric COMPILER_RT_ALIAS(__floatdidf, __i64tod)
65349cc55cSDimitry Andric #endif
66