blob: c8c72342dc6ff58cc3ba8e6bbee7c670235f0fca [file] [log] [blame]
Stephen Canon5c6d2ec2010-07-01 17:58:24 +00001//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Stephen Canone5086322010-07-01 15:52:42 +000010// This file is a configuration header for soft-float routines in compiler-rt.
Stephen Canon5c6d2ec2010-07-01 17:58:24 +000011// This file does not provide any part of the compiler-rt interface, but defines
12// many useful constants and utility routines that are used in the
13// implementation of the soft-float routines in compiler-rt.
14//
Stephen Canone5086322010-07-01 15:52:42 +000015// Assumes that float and double correspond to the IEEE-754 binary32 and
Stephen Canon5c6d2ec2010-07-01 17:58:24 +000016// binary64 types, respectively, and that integer endianness matches floating
17// point endianness on the target platform.
18//
19//===----------------------------------------------------------------------===//
Stephen Canone5086322010-07-01 15:52:42 +000020
21#ifndef FP_LIB_HEADER
22#define FP_LIB_HEADER
23
24#include <stdint.h>
25#include <stdbool.h>
26#include <limits.h>
27
28#if defined SINGLE_PRECISION
Stephen Canone5086322010-07-01 15:52:42 +000029
30typedef uint32_t rep_t;
31typedef int32_t srep_t;
32typedef float fp_t;
33#define REP_C UINT32_C
34#define significandBits 23
35
36static inline int rep_clz(rep_t a) {
37 return __builtin_clz(a);
38}
39
40#elif defined DOUBLE_PRECISION
Stephen Canone5086322010-07-01 15:52:42 +000041
42typedef uint64_t rep_t;
43typedef int64_t srep_t;
44typedef double fp_t;
45#define REP_C UINT64_C
46#define significandBits 52
47
48static inline int rep_clz(rep_t a) {
49#if defined __LP64__
50 return __builtin_clzl(a);
51#else
52 if (a & REP_C(0xffffffff00000000))
53 return 32 + __builtin_clz(a >> 32);
54 else
55 return __builtin_clz(a & REP_C(0xffffffff));
56#endif
57}
58
59#else
60#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
61#endif
62
Stephen Canone5086322010-07-01 15:52:42 +000063#define typeWidth (sizeof(rep_t)*CHAR_BIT)
64#define exponentBits (typeWidth - significandBits - 1)
65#define maxExponent ((1 << exponentBits) - 1)
66#define exponentBias (maxExponent >> 1)
67
Stephen Canone5086322010-07-01 15:52:42 +000068#define implicitBit (REP_C(1) << significandBits)
69#define significandMask (implicitBit - 1U)
70#define signBit (REP_C(1) << (significandBits + exponentBits))
71#define absMask (signBit - 1U)
72#define exponentMask (absMask ^ significandMask)
73#define oneRep ((rep_t)exponentBias << significandBits)
74#define infRep exponentMask
75#define quietBit (implicitBit >> 1)
76#define qnanRep (exponentMask | quietBit)
77
Stephen Canone5086322010-07-01 15:52:42 +000078static inline rep_t toRep(fp_t x) {
79 const union { fp_t f; rep_t i; } rep = {.f = x};
80 return rep.i;
81}
82
83static inline fp_t fromRep(rep_t x) {
84 const union { fp_t f; rep_t i; } rep = {.i = x};
85 return rep.f;
86}
87
88static inline int normalize(rep_t *significand) {
89 const int shift = rep_clz(*significand) - rep_clz(implicitBit);
90 *significand <<= shift;
91 return 1 - shift;
92}
93
94static inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
95 *hi = *hi << count | *lo >> (typeWidth - count);
96 *lo = *lo << count;
97}
98
99static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, int count) {
100 if (count < typeWidth) {
101 const bool sticky = *lo << (typeWidth - count);
102 *lo = *hi << (typeWidth - count) | *lo >> count | sticky;
103 *hi = *hi >> count;
104 }
105 else if (count < 2*typeWidth) {
106 const bool sticky = *hi << (2*typeWidth - count) | *lo;
107 *lo = *hi >> (count - typeWidth) | sticky;
108 *hi = 0;
109 } else {
110 const bool sticky = *hi | *lo;
111 *lo = sticky;
112 *hi = 0;
113 }
114}
115
116#endif // FP_LIB_HEADER