10b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
20b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
30b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
40b57cec5SDimitry Andric 
50b57cec5SDimitry Andric // long double __floatditf(long long x);
60b57cec5SDimitry Andric // This file implements the PowerPC long long -> long double conversion
70b57cec5SDimitry Andric 
80b57cec5SDimitry Andric #include "DD.h"
90b57cec5SDimitry Andric 
__floatditf(int64_t a)100b57cec5SDimitry Andric long double __floatditf(int64_t a) {
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric   static const double twop32 = 0x1.0p32;
130b57cec5SDimitry Andric   static const double twop52 = 0x1.0p52;
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric   doublebits low = {.d = twop52};
160b57cec5SDimitry Andric   low.x |= a & UINT64_C(0x00000000ffffffff); // 0x1.0p52 + low 32 bits of a.
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric   const double high_addend = (double)((int32_t)(a >> 32)) * twop32 - twop52;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric   // At this point, we have two double precision numbers
210b57cec5SDimitry Andric   // high_addend and low.d, and we wish to return their sum
220b57cec5SDimitry Andric   // as a canonicalized long double:
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric   // This implementation sets the inexact flag spuriously.
250b57cec5SDimitry Andric   // This could be avoided, but at some substantial cost.
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   DD result;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   result.s.hi = high_addend + low.d;
300b57cec5SDimitry Andric   result.s.lo = (high_addend - result.s.hi) + low.d;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   return result.ld;
330b57cec5SDimitry Andric }
34