floatundisf.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //===-- floatundisf.c - Implement __floatundisf ---------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements __floatundisf for the compiler_rt library.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. // Returns: convert a to a float, rounding toward even.
  13. // Assumption: float is a IEEE 32 bit floating point type
  14. // du_int is a 64 bit integral type
  15. // seee eeee emmm mmmm mmmm mmmm mmmm mmmm
  16. #include "int_lib.h"
  17. COMPILER_RT_ABI float __floatundisf(du_int a) {
  18. if (a == 0)
  19. return 0.0F;
  20. const unsigned N = sizeof(du_int) * CHAR_BIT;
  21. int sd = N - __builtin_clzll(a); // number of significant digits
  22. si_int e = sd - 1; // 8 exponent
  23. if (sd > FLT_MANT_DIG) {
  24. // start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
  25. // finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
  26. // 12345678901234567890123456
  27. // 1 = msb 1 bit
  28. // P = bit FLT_MANT_DIG-1 bits to the right of 1
  29. // Q = bit FLT_MANT_DIG bits to the right of 1
  30. // R = "or" of all bits to the right of Q
  31. switch (sd) {
  32. case FLT_MANT_DIG + 1:
  33. a <<= 1;
  34. break;
  35. case FLT_MANT_DIG + 2:
  36. break;
  37. default:
  38. a = (a >> (sd - (FLT_MANT_DIG + 2))) |
  39. ((a & ((du_int)(-1) >> ((N + FLT_MANT_DIG + 2) - sd))) != 0);
  40. };
  41. // finish:
  42. a |= (a & 4) != 0; // Or P into R
  43. ++a; // round - this step may add a significant bit
  44. a >>= 2; // dump Q and R
  45. // a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits
  46. if (a & ((du_int)1 << FLT_MANT_DIG)) {
  47. a >>= 1;
  48. ++e;
  49. }
  50. // a is now rounded to FLT_MANT_DIG bits
  51. } else {
  52. a <<= (FLT_MANT_DIG - sd);
  53. // a is now rounded to FLT_MANT_DIG bits
  54. }
  55. float_bits fb;
  56. fb.u = ((e + 127) << 23) | // exponent
  57. ((su_int)a & 0x007FFFFF); // mantissa
  58. return fb.f;
  59. }
  60. #if defined(__ARM_EABI__)
  61. #if defined(COMPILER_RT_ARMHF_TARGET)
  62. AEABI_RTABI float __aeabi_ul2f(du_int a) { return __floatundisf(a); }
  63. #else
  64. COMPILER_RT_ALIAS(__floatundisf, __aeabi_ul2f)
  65. #endif
  66. #endif
  67. #if defined(__MINGW32__) && defined(__arm__)
  68. COMPILER_RT_ALIAS(__floatundisf, __u64tos)
  69. #endif