1276789Sdim/* ===-- floatuntisf.c - Implement __floatuntisf ---------------------------=== 2276789Sdim * 3276789Sdim * The LLVM Compiler Infrastructure 4276789Sdim * 5276789Sdim * This file is dual licensed under the MIT and the University of Illinois Open 6276789Sdim * Source Licenses. See LICENSE.TXT for details. 7276789Sdim * 8276789Sdim * ===----------------------------------------------------------------------=== 9276789Sdim * 10276789Sdim * This file implements __floatuntisf for the compiler_rt library. 11276789Sdim * 12276789Sdim * ===----------------------------------------------------------------------=== 13276789Sdim */ 14276789Sdim 15276789Sdim#include "int_lib.h" 16276789Sdim 17276789Sdim#ifdef CRT_HAS_128BIT 18276789Sdim 19276789Sdim/* Returns: convert a to a float, rounding toward even. */ 20276789Sdim 21276789Sdim/* Assumption: float is a IEEE 32 bit floating point type 22276789Sdim * tu_int is a 128 bit integral type 23276789Sdim */ 24276789Sdim 25276789Sdim/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ 26276789Sdim 27276789SdimCOMPILER_RT_ABI float 28276789Sdim__floatuntisf(tu_int a) 29276789Sdim{ 30276789Sdim if (a == 0) 31276789Sdim return 0.0F; 32276789Sdim const unsigned N = sizeof(tu_int) * CHAR_BIT; 33276789Sdim int sd = N - __clzti2(a); /* number of significant digits */ 34276789Sdim int e = sd - 1; /* exponent */ 35276789Sdim if (sd > FLT_MANT_DIG) 36276789Sdim { 37276789Sdim /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 38276789Sdim * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 39276789Sdim * 12345678901234567890123456 40276789Sdim * 1 = msb 1 bit 41276789Sdim * P = bit FLT_MANT_DIG-1 bits to the right of 1 42276789Sdim * Q = bit FLT_MANT_DIG bits to the right of 1 43276789Sdim * R = "or" of all bits to the right of Q 44276789Sdim */ 45276789Sdim switch (sd) 46276789Sdim { 47276789Sdim case FLT_MANT_DIG + 1: 48276789Sdim a <<= 1; 49276789Sdim break; 50276789Sdim case FLT_MANT_DIG + 2: 51276789Sdim break; 52276789Sdim default: 53276789Sdim a = (a >> (sd - (FLT_MANT_DIG+2))) | 54276789Sdim ((a & ((tu_int)(-1) >> ((N + FLT_MANT_DIG+2) - sd))) != 0); 55276789Sdim }; 56276789Sdim /* finish: */ 57276789Sdim a |= (a & 4) != 0; /* Or P into R */ 58276789Sdim ++a; /* round - this step may add a significant bit */ 59276789Sdim a >>= 2; /* dump Q and R */ 60276789Sdim /* a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits */ 61276789Sdim if (a & ((tu_int)1 << FLT_MANT_DIG)) 62276789Sdim { 63276789Sdim a >>= 1; 64276789Sdim ++e; 65276789Sdim } 66276789Sdim /* a is now rounded to FLT_MANT_DIG bits */ 67276789Sdim } 68276789Sdim else 69276789Sdim { 70276789Sdim a <<= (FLT_MANT_DIG - sd); 71276789Sdim /* a is now rounded to FLT_MANT_DIG bits */ 72276789Sdim } 73276789Sdim float_bits fb; 74276789Sdim fb.u = ((e + 127) << 23) | /* exponent */ 75276789Sdim ((su_int)a & 0x007FFFFF); /* mantissa */ 76276789Sdim return fb.f; 77276789Sdim} 78276789Sdim 79276789Sdim#endif /* CRT_HAS_128BIT */ 80