1*0b57cec5SDimitry Andric //===-- lib/builtins/ppc/floattitf.c - Convert int128->long double -*-C -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements converting a signed 128 bit integer to a 128bit IBM / 10*0b57cec5SDimitry Andric // PowerPC long double (double-double) value. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include <stdint.h> 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric // Conversions from signed and unsigned 64-bit int to long double. 17*0b57cec5SDimitry Andric long double __floatditf(int64_t); 18*0b57cec5SDimitry Andric long double __floatunditf(uint64_t); 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric // Convert a signed 128-bit integer to long double. 21*0b57cec5SDimitry Andric // This uses the following property: Let hi and lo be 64-bits each, 22*0b57cec5SDimitry Andric // and let signed_val_k() and unsigned_val_k() be the value of the 23*0b57cec5SDimitry Andric // argument interpreted as a signed or unsigned k-bit integer. Then, 24*0b57cec5SDimitry Andric // 25*0b57cec5SDimitry Andric // signed_val_128(hi,lo) = signed_val_64(hi) * 2^64 + unsigned_val_64(lo) 26*0b57cec5SDimitry Andric // = (long double)hi * 2^64 + (long double)lo, 27*0b57cec5SDimitry Andric // 28*0b57cec5SDimitry Andric // where (long double)hi and (long double)lo are signed and 29*0b57cec5SDimitry Andric // unsigned 64-bit integer to long double conversions, respectively. __floattitf(__int128_t arg)30*0b57cec5SDimitry Andriclong double __floattitf(__int128_t arg) { 31*0b57cec5SDimitry Andric // Split the int128 argument into 64-bit high and low int64 parts. 32*0b57cec5SDimitry Andric int64_t ArgHiPart = (int64_t)(arg >> 64); 33*0b57cec5SDimitry Andric uint64_t ArgLoPart = (uint64_t)arg; 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric // Convert each 64-bit part into long double. The high part 36*0b57cec5SDimitry Andric // must be a signed conversion and the low part an unsigned conversion 37*0b57cec5SDimitry Andric // to ensure the correct result. 38*0b57cec5SDimitry Andric long double ConvertedHiPart = __floatditf(ArgHiPart); 39*0b57cec5SDimitry Andric long double ConvertedLoPart = __floatunditf(ArgLoPart); 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric // The low bit of ArgHiPart corresponds to the 2^64 bit in arg. 42*0b57cec5SDimitry Andric // Multiply the high part by 2^64 to undo the right shift by 64-bits 43*0b57cec5SDimitry Andric // done in the splitting. Then, add to the low part to obtain the 44*0b57cec5SDimitry Andric // final result. 45*0b57cec5SDimitry Andric return ((ConvertedHiPart * 0x1.0p64) + ConvertedLoPart); 46*0b57cec5SDimitry Andric } 47