blob: b3c01049119d0f66929b9639829a1d1f7529bb3b [file] [log] [blame]
Stephen Canonb1fdde12010-07-01 15:52:42 +00001// This file is a configuration header for soft-float routines in compiler-rt.
2// This file does not provide any part of the compiler-rt interface.
3
4// Assumes that float and double correspond to the IEEE-754 binary32 and
5// binary64 types, respectively.
6
7#ifndef FP_LIB_HEADER
8#define FP_LIB_HEADER
9
10#include <stdint.h>
11#include <stdbool.h>
12#include <limits.h>
13
14#if defined SINGLE_PRECISION
15#if 0
16#pragma mark single definitions
17#endif
18
19typedef uint32_t rep_t;
20typedef int32_t srep_t;
21typedef float fp_t;
22#define REP_C UINT32_C
23#define significandBits 23
24
25static inline int rep_clz(rep_t a) {
26 return __builtin_clz(a);
27}
28
29#elif defined DOUBLE_PRECISION
30#if 0
31#pragma mark double definitions
32#endif
33
34typedef uint64_t rep_t;
35typedef int64_t srep_t;
36typedef double fp_t;
37#define REP_C UINT64_C
38#define significandBits 52
39
40static inline int rep_clz(rep_t a) {
41#if defined __LP64__
42 return __builtin_clzl(a);
43#else
44 if (a & REP_C(0xffffffff00000000))
45 return 32 + __builtin_clz(a >> 32);
46 else
47 return __builtin_clz(a & REP_C(0xffffffff));
48#endif
49}
50
51#else
52#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
53#endif
54
55#if 0
56#pragma mark -
57#pragma mark integer constants
58#endif
59
60#define typeWidth (sizeof(rep_t)*CHAR_BIT)
61#define exponentBits (typeWidth - significandBits - 1)
62#define maxExponent ((1 << exponentBits) - 1)
63#define exponentBias (maxExponent >> 1)
64
65#if 0
66#pragma mark -
67#pragma mark rep_t constants
68#endif
69
70#define implicitBit (REP_C(1) << significandBits)
71#define significandMask (implicitBit - 1U)
72#define signBit (REP_C(1) << (significandBits + exponentBits))
73#define absMask (signBit - 1U)
74#define exponentMask (absMask ^ significandMask)
75#define oneRep ((rep_t)exponentBias << significandBits)
76#define infRep exponentMask
77#define quietBit (implicitBit >> 1)
78#define qnanRep (exponentMask | quietBit)
79
80#if 0
81#pragma mark -
82#pragma mark generic functions
83#endif
84
85static inline rep_t toRep(fp_t x) {
86 const union { fp_t f; rep_t i; } rep = {.f = x};
87 return rep.i;
88}
89
90static inline fp_t fromRep(rep_t x) {
91 const union { fp_t f; rep_t i; } rep = {.i = x};
92 return rep.f;
93}
94
95static inline int normalize(rep_t *significand) {
96 const int shift = rep_clz(*significand) - rep_clz(implicitBit);
97 *significand <<= shift;
98 return 1 - shift;
99}
100
101static inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
102 *hi = *hi << count | *lo >> (typeWidth - count);
103 *lo = *lo << count;
104}
105
106static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, int count) {
107 if (count < typeWidth) {
108 const bool sticky = *lo << (typeWidth - count);
109 *lo = *hi << (typeWidth - count) | *lo >> count | sticky;
110 *hi = *hi >> count;
111 }
112 else if (count < 2*typeWidth) {
113 const bool sticky = *hi << (2*typeWidth - count) | *lo;
114 *lo = *hi >> (count - typeWidth) | sticky;
115 *hi = 0;
116 } else {
117 const bool sticky = *hi | *lo;
118 *lo = sticky;
119 *hi = 0;
120 }
121}
122
123#endif // FP_LIB_HEADER