137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/*===-- floatundisf.c - Implement __floatundisf ---------------------------=== 237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * The LLVM Compiler Infrastructure 437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open 69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details. 737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------=== 937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * This file implements __floatundisf for the compiler_rt library. 1137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *===----------------------------------------------------------------------=== 1337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Returns: convert a to a float, rounding toward even. */ 16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Assumption: float is a IEEE 32 bit floating point type 1837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * du_int is a 64 bit integral type 1937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ 22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2337b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov#include "int_lib.h" 2437b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov 250193b74976719b8aea4cb8874ba36b75836a8d6eChandler CarruthARM_EABI_FNALIAS(ul2f, floatundisf) 2637b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov 271c5f89b1dd741135a4007ab577723d422f421eecAnton KorobeynikovCOMPILER_RT_ABI float 28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar__floatundisf(du_int a) 29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (a == 0) 31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return 0.0F; 32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const unsigned N = sizeof(du_int) * CHAR_BIT; 3337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan int sd = N - __builtin_clzll(a); /* number of significant digits */ 3437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan int e = sd - 1; /* 8 exponent */ 35b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (sd > FLT_MANT_DIG) 36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 3737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 3837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 3937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 12345678901234567890123456 4037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1 = msb 1 bit 4137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * P = bit FLT_MANT_DIG-1 bits to the right of 1 4237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * Q = bit FLT_MANT_DIG bits to the right of 1 4337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * R = "or" of all bits to the right of Q 4437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 45b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar switch (sd) 46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case FLT_MANT_DIG + 1: 48b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar a <<= 1; 49b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 50b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case FLT_MANT_DIG + 2: 51b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 52b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar default: 53b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar a = (a >> (sd - (FLT_MANT_DIG+2))) | 54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((a & ((du_int)(-1) >> ((N + FLT_MANT_DIG+2) - sd))) != 0); 55b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar }; 5637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* finish: */ 5737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan a |= (a & 4) != 0; /* Or P into R */ 5837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan ++a; /* round - this step may add a significant bit */ 5937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan a >>= 2; /* dump Q and R */ 6037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits */ 61b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (a & ((du_int)1 << FLT_MANT_DIG)) 62b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 63b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar a >>= 1; 64b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ++e; 65b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 6637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* a is now rounded to FLT_MANT_DIG bits */ 67b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 68b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar else 69b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 70b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar a <<= (FLT_MANT_DIG - sd); 7137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* a is now rounded to FLT_MANT_DIG bits */ 72b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 73b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar float_bits fb; 7437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan fb.u = ((e + 127) << 23) | /* exponent */ 7537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan ((su_int)a & 0x007FFFFF); /* mantissa */ 76b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return fb.f; 77b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 78