177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* This file is distributed under the University of Illinois Open Source
277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * License. See LICENSE.TXT for details.
377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */
477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* uint64_t __fixunstfdi(long double x); */
677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* This file implements the PowerPC 128-bit double-double -> uint64_t conversion */
777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include "DD.h"
977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdint.h>
1077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
1177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaouint64_t __fixunstfdi(long double input)
1277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{
1377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	const DD x = { .ld = input };
1477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	const doublebits hibits = { .d = x.s.hi };
1577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
1677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	const uint32_t highWordMinusOne = (uint32_t)(hibits.x >> 32) - UINT32_C(0x3ff00000);
1777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
1877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	/* If (1.0 - tiny) <= input < 0x1.0p64: */
1977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	if (UINT32_C(0x04000000) > highWordMinusOne)
2077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	{
2177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		const int unbiasedHeadExponent = highWordMinusOne >> 20;
2277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		uint64_t result = hibits.x & UINT64_C(0x000fffffffffffff); /* mantissa(hi) */
2477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		result |= UINT64_C(0x0010000000000000); /* matissa(hi) with implicit bit */
2577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		result <<= 11; /* mantissa(hi) left aligned in the int64 field. */
2677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		/* If the tail is non-zero, we need to patch in the tail bits. */
2877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		if (0.0 != x.s.lo)
2977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		{
3077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			const doublebits lobits = { .d = x.s.lo };
3177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			int64_t tailMantissa = lobits.x & INT64_C(0x000fffffffffffff);
3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			tailMantissa |= INT64_C(0x0010000000000000);
3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			/* At this point we have the mantissa of |tail| */
3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			const int64_t negationMask = ((int64_t)(lobits.x)) >> 63;
3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			tailMantissa = (tailMantissa ^ negationMask) - negationMask;
3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			/* Now we have the mantissa of tail as a signed 2s-complement integer */
4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			const int biasedTailExponent = (int)(lobits.x >> 52) & 0x7ff;
4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			/* Shift the tail mantissa into the right position, accounting for the
4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			 * bias of 11 that we shifted the head mantissa by.
4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			 */
4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			tailMantissa >>= (unbiasedHeadExponent - (biasedTailExponent - (1023 - 11)));
4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao			result += tailMantissa;
4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		}
5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		result >>= (63 - unbiasedHeadExponent);
5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		return result;
5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	}
5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	/* Edge cases are handled here, with saturation. */
5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	if (1.0 > x.s.hi)
5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		return UINT64_C(0);
5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	else
5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao		return UINT64_MAX;
6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao}
61