18bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan/* This file is distributed under the University of Illinois Open Source 28bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * License. See LICENSE.TXT for details. 38bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan */ 4b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 58bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan/* int64_t __fixunstfdi(long double x); 68bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * This file implements the PowerPC 128-bit double-double -> int64_t conversion 78bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan */ 8b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 9b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#include "DD.h" 10c25c6d10b18efa071f0016f31f6f3dd8a8fa6676Daniel Dunbar#include "../int_math.h" 11b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 12b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbaruint64_t __fixtfdi(long double input) 13b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const DD x = { .ld = input }; 158bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan const doublebits hibits = { .d = x.s.hi }; 16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 17b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint32_t absHighWord = (uint32_t)(hibits.x >> 32) & UINT32_C(0x7fffffff); 18b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint32_t absHighWordMinusOne = absHighWord - UINT32_C(0x3ff00000); 19b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 208bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* If (1.0 - tiny) <= input < 0x1.0p63: */ 21b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (UINT32_C(0x03f00000) > absHighWordMinusOne) 22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 238bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Do an unsigned conversion of the absolute value, then restore the sign. */ 24b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int unbiasedHeadExponent = absHighWordMinusOne >> 20; 25b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 268bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan int64_t result = hibits.x & INT64_C(0x000fffffffffffff); /* mantissa(hi) */ 278bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan result |= INT64_C(0x0010000000000000); /* matissa(hi) with implicit bit */ 282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result <<= 10; /* mantissa(hi) with one zero preceding bit. */ 29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int64_t hiNegationMask = ((int64_t)(hibits.x)) >> 63; 31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 328bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* If the tail is non-zero, we need to patch in the tail bits. */ 338bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (0.0 != x.s.lo) 34b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 358bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan const doublebits lobits = { .d = x.s.lo }; 36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar int64_t tailMantissa = lobits.x & INT64_C(0x000fffffffffffff); 37b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa |= INT64_C(0x0010000000000000); 38b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 398bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* At this point we have the mantissa of |tail| */ 408bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* We need to negate it if head and tail have different signs. */ 41b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int64_t loNegationMask = ((int64_t)(lobits.x)) >> 63; 42b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int64_t negationMask = loNegationMask ^ hiNegationMask; 43b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa = (tailMantissa ^ negationMask) - negationMask; 44b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 458bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Now we have the mantissa of tail as a signed 2s-complement integer */ 46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int biasedTailExponent = (int)(lobits.x >> 52) & 0x7ff; 48b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 498bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Shift the tail mantissa into the right position, accounting for the 508bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * bias of 10 that we shifted the head mantissa by. 518bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan */ 52b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa >>= (unbiasedHeadExponent - (biasedTailExponent - (1023 - 10))); 53b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result += tailMantissa; 55b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 56b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 57b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result >>= (62 - unbiasedHeadExponent); 58b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 598bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Restore the sign of the result and return */ 60b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result = (result ^ hiNegationMask) - hiNegationMask; 61b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return result; 62b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 63b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 64b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 658bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Edge cases handled here: */ 66b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 678bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* |x| < 1, result is zero. */ 68c25c6d10b18efa071f0016f31f6f3dd8a8fa6676Daniel Dunbar if (1.0 > crt_fabs(x.s.hi)) 69b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return INT64_C(0); 70b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 718bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* x very close to INT64_MIN, care must be taken to see which side we are on. */ 728bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (x.s.hi == -0x1.0p63) { 73b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 74b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar int64_t result = INT64_MIN; 75b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 768bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (0.0 < x.s.lo) 77b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 788bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* If the tail is positive, the correct result is something other than INT64_MIN. 798bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * we'll need to figure out what it is. 808bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan */ 818bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan 828bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan const doublebits lobits = { .d = x.s.lo }; 83b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar int64_t tailMantissa = lobits.x & INT64_C(0x000fffffffffffff); 84b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa |= INT64_C(0x0010000000000000); 85b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 868bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Now we negate the tailMantissa */ 87b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa = (tailMantissa ^ INT64_C(-1)) + INT64_C(1); 88b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 898bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* And shift it by the appropriate amount */ 90b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const int biasedTailExponent = (int)(lobits.x >> 52) & 0x7ff; 91b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar tailMantissa >>= 1075 - biasedTailExponent; 92b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 93b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result -= tailMantissa; 94b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 95b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 96b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return result; 97b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 98b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 998bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* Signed overflows, infinities, and NaNs */ 1008bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (x.s.hi > 0.0) 101b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return INT64_MAX; 102b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar else 103b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return INT64_MIN; 104b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 105