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