1 //===-- lib/floatuntitf.c - uint128 -> quad-precision conversion --*- C -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements tu_int to quad-precision conversion for the 11 // compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even 12 // mode. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #define QUAD_PRECISION 17 #include "fp_lib.h" 18 #include "int_lib.h" 19 20 /* Returns: convert a tu_int to a fp_t, rounding toward even. */ 21 22 /* Assumption: fp_t is a IEEE 128 bit floating point type 23 * tu_int is a 128 bit integral type 24 */ 25 26 /* seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | 27 * mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm 28 */ 29 30 #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) 31 COMPILER_RT_ABI fp_t 32 __floatuntitf(tu_int a) { 33 if (a == 0) 34 return 0.0; 35 const unsigned N = sizeof(tu_int) * CHAR_BIT; 36 int sd = N - __clzti2(a); /* number of significant digits */ 37 int e = sd - 1; /* exponent */ 38 if (sd > LDBL_MANT_DIG) { 39 /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 40 * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 41 * 12345678901234567890123456 42 * 1 = msb 1 bit 43 * P = bit LDBL_MANT_DIG-1 bits to the right of 1 44 * Q = bit LDBL_MANT_DIG bits to the right of 1 45 * R = "or" of all bits to the right of Q 46 */ 47 switch (sd) { 48 case LDBL_MANT_DIG + 1: 49 a <<= 1; 50 break; 51 case LDBL_MANT_DIG + 2: 52 break; 53 default: 54 a = (a >> (sd - (LDBL_MANT_DIG+2))) | 55 ((a & ((tu_int)(-1) >> ((N + LDBL_MANT_DIG+2) - sd))) != 0); 56 }; 57 /* finish: */ 58 a |= (a & 4) != 0; /* Or P into R */ 59 ++a; /* round - this step may add a significant bit */ 60 a >>= 2; /* dump Q and R */ 61 /* a is now rounded to LDBL_MANT_DIG or LDBL_MANT_DIG+1 bits */ 62 if (a & ((tu_int)1 << LDBL_MANT_DIG)) { 63 a >>= 1; 64 ++e; 65 } 66 /* a is now rounded to LDBL_MANT_DIG bits */ 67 } else { 68 a <<= (LDBL_MANT_DIG - sd); 69 /* a is now rounded to LDBL_MANT_DIG bits */ 70 } 71 72 long_double_bits fb; 73 fb.u.high.all = (du_int)(e + 16383) << 48 /* exponent */ 74 | ((a >> 64) & 0x0000ffffffffffffLL); /* significand */ 75 fb.u.low.all = (du_int)(a); 76 return fb.f; 77 } 78 79 #endif 80