floattidf.c revision 222656
11573Srgrimes/* ===-- floattidf.c - Implement __floattidf -------------------------------=== 21573Srgrimes * 31573Srgrimes * The LLVM Compiler Infrastructure 41573Srgrimes * 51573Srgrimes * This file is dual licensed under the MIT and the University of Illinois Open 61573Srgrimes * Source Licenses. See LICENSE.TXT for details. 71573Srgrimes * 81573Srgrimes * ===----------------------------------------------------------------------=== 91573Srgrimes * 101573Srgrimes * This file implements __floattidf for the compiler_rt library. 111573Srgrimes * 121573Srgrimes * ===----------------------------------------------------------------------=== 131573Srgrimes */ 141573Srgrimes 151573Srgrimes#if __x86_64 161573Srgrimes 171573Srgrimes#include "int_lib.h" 181573Srgrimes#include <float.h> 191573Srgrimes 201573Srgrimes/* Returns: convert a to a double, rounding toward even.*/ 211573Srgrimes 221573Srgrimes/* Assumption: double is a IEEE 64 bit floating point type 231573Srgrimes * ti_int is a 128 bit integral type 241573Srgrimes */ 251573Srgrimes 261573Srgrimes/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ 271573Srgrimes 281573Srgrimessi_int __clzti2(ti_int a); 291573Srgrimes 301573Srgrimesdouble 311573Srgrimes__floattidf(ti_int a) 321573Srgrimes{ 331573Srgrimes if (a == 0) 341573Srgrimes return 0.0; 351573Srgrimes const unsigned N = sizeof(ti_int) * CHAR_BIT; 361573Srgrimes const ti_int s = a >> (N-1); 371573Srgrimes a = (a ^ s) - s; 381573Srgrimes int sd = N - __clzti2(a); /* number of significant digits */ 391573Srgrimes int e = sd - 1; /* exponent */ 401573Srgrimes if (sd > DBL_MANT_DIG) 411573Srgrimes { 421573Srgrimes /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 431573Srgrimes * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 441573Srgrimes * 12345678901234567890123456 451573Srgrimes * 1 = msb 1 bit 461573Srgrimes * P = bit DBL_MANT_DIG-1 bits to the right of 1 471573Srgrimes * Q = bit DBL_MANT_DIG bits to the right of 1 481573Srgrimes * R = "or" of all bits to the right of Q 491573Srgrimes */ 501573Srgrimes switch (sd) 511573Srgrimes { 521573Srgrimes case DBL_MANT_DIG + 1: 531573Srgrimes a <<= 1; 541573Srgrimes break; 551573Srgrimes case DBL_MANT_DIG + 2: 561573Srgrimes break; 571573Srgrimes default: 581573Srgrimes a = ((tu_int)a >> (sd - (DBL_MANT_DIG+2))) | 591573Srgrimes ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); 601573Srgrimes }; 611573Srgrimes /* finish: */ 621573Srgrimes a |= (a & 4) != 0; /* Or P into R */ 631573Srgrimes ++a; /* round - this step may add a significant bit */ 648870Srgrimes a >>= 2; /* dump Q and R */ 651573Srgrimes /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ 661573Srgrimes if (a & ((tu_int)1 << DBL_MANT_DIG)) 671573Srgrimes { 681573Srgrimes a >>= 1; 691573Srgrimes ++e; 701573Srgrimes } 711573Srgrimes /* a is now rounded to DBL_MANT_DIG bits */ 721573Srgrimes } 731573Srgrimes else 741573Srgrimes { 751573Srgrimes a <<= (DBL_MANT_DIG - sd); 761573Srgrimes /* a is now rounded to DBL_MANT_DIG bits */ 771573Srgrimes } 781573Srgrimes double_bits fb; 791573Srgrimes fb.u.s.high = ((su_int)s & 0x80000000) | /* sign */ 801573Srgrimes ((e + 1023) << 20) | /* exponent */ 811573Srgrimes ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ 821573Srgrimes fb.u.s.low = (su_int)a; /* mantissa-low */ 831573Srgrimes return fb.f; 841573Srgrimes} 851573Srgrimes 861573Srgrimes#endif 871573Srgrimes