1214152Sed/* This file is distributed under the University of Illinois Open Source 2214152Sed * License. See LICENSE.TXT for details. 3214152Sed */ 4214152Sed 5214152Sed/* int64_t __fixunstfdi(long double x); 6214152Sed * This file implements the PowerPC 128-bit double-double -> int64_t conversion 7214152Sed */ 8214152Sed 9214152Sed#include "DD.h" 10229135Sed#include "../int_math.h" 11214152Sed 12214152Seduint64_t __fixtfdi(long double input) 13214152Sed{ 14214152Sed const DD x = { .ld = input }; 15214152Sed const doublebits hibits = { .d = x.s.hi }; 16214152Sed 17214152Sed const uint32_t absHighWord = (uint32_t)(hibits.x >> 32) & UINT32_C(0x7fffffff); 18214152Sed const uint32_t absHighWordMinusOne = absHighWord - UINT32_C(0x3ff00000); 19214152Sed 20214152Sed /* If (1.0 - tiny) <= input < 0x1.0p63: */ 21214152Sed if (UINT32_C(0x03f00000) > absHighWordMinusOne) 22214152Sed { 23214152Sed /* Do an unsigned conversion of the absolute value, then restore the sign. */ 24214152Sed const int unbiasedHeadExponent = absHighWordMinusOne >> 20; 25214152Sed 26214152Sed int64_t result = hibits.x & INT64_C(0x000fffffffffffff); /* mantissa(hi) */ 27214152Sed result |= INT64_C(0x0010000000000000); /* matissa(hi) with implicit bit */ 28214152Sed result <<= 10; /* mantissa(hi) with one zero preceeding bit. */ 29214152Sed 30214152Sed const int64_t hiNegationMask = ((int64_t)(hibits.x)) >> 63; 31214152Sed 32214152Sed /* If the tail is non-zero, we need to patch in the tail bits. */ 33214152Sed if (0.0 != x.s.lo) 34214152Sed { 35214152Sed const doublebits lobits = { .d = x.s.lo }; 36214152Sed int64_t tailMantissa = lobits.x & INT64_C(0x000fffffffffffff); 37214152Sed tailMantissa |= INT64_C(0x0010000000000000); 38214152Sed 39214152Sed /* At this point we have the mantissa of |tail| */ 40214152Sed /* We need to negate it if head and tail have different signs. */ 41214152Sed const int64_t loNegationMask = ((int64_t)(lobits.x)) >> 63; 42214152Sed const int64_t negationMask = loNegationMask ^ hiNegationMask; 43214152Sed tailMantissa = (tailMantissa ^ negationMask) - negationMask; 44214152Sed 45214152Sed /* Now we have the mantissa of tail as a signed 2s-complement integer */ 46214152Sed 47214152Sed const int biasedTailExponent = (int)(lobits.x >> 52) & 0x7ff; 48214152Sed 49214152Sed /* Shift the tail mantissa into the right position, accounting for the 50214152Sed * bias of 10 that we shifted the head mantissa by. 51214152Sed */ 52214152Sed tailMantissa >>= (unbiasedHeadExponent - (biasedTailExponent - (1023 - 10))); 53214152Sed 54214152Sed result += tailMantissa; 55214152Sed } 56214152Sed 57214152Sed result >>= (62 - unbiasedHeadExponent); 58214152Sed 59214152Sed /* Restore the sign of the result and return */ 60214152Sed result = (result ^ hiNegationMask) - hiNegationMask; 61214152Sed return result; 62214152Sed 63214152Sed } 64214152Sed 65214152Sed /* Edge cases handled here: */ 66214152Sed 67214152Sed /* |x| < 1, result is zero. */ 68229135Sed if (1.0 > crt_fabs(x.s.hi)) 69214152Sed return INT64_C(0); 70214152Sed 71214152Sed /* x very close to INT64_MIN, care must be taken to see which side we are on. */ 72214152Sed if (x.s.hi == -0x1.0p63) { 73214152Sed 74214152Sed int64_t result = INT64_MIN; 75214152Sed 76214152Sed if (0.0 < x.s.lo) 77214152Sed { 78214152Sed /* If the tail is positive, the correct result is something other than INT64_MIN. 79214152Sed * we'll need to figure out what it is. 80214152Sed */ 81214152Sed 82214152Sed const doublebits lobits = { .d = x.s.lo }; 83214152Sed int64_t tailMantissa = lobits.x & INT64_C(0x000fffffffffffff); 84214152Sed tailMantissa |= INT64_C(0x0010000000000000); 85214152Sed 86214152Sed /* Now we negate the tailMantissa */ 87214152Sed tailMantissa = (tailMantissa ^ INT64_C(-1)) + INT64_C(1); 88214152Sed 89214152Sed /* And shift it by the appropriate amount */ 90214152Sed const int biasedTailExponent = (int)(lobits.x >> 52) & 0x7ff; 91214152Sed tailMantissa >>= 1075 - biasedTailExponent; 92214152Sed 93214152Sed result -= tailMantissa; 94214152Sed } 95214152Sed 96214152Sed return result; 97214152Sed } 98214152Sed 99214152Sed /* Signed overflows, infinities, and NaNs */ 100214152Sed if (x.s.hi > 0.0) 101214152Sed return INT64_MAX; 102214152Sed else 103214152Sed return INT64_MIN; 104214152Sed} 105