1276789Sdim//===-lib/fp_extend.h - low precision -> high precision conversion -*- C -*-===//
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// Set source and destination setting
11276789Sdim//
12276789Sdim//===----------------------------------------------------------------------===//
13276789Sdim
14276789Sdim#ifndef FP_EXTEND_HEADER
15276789Sdim#define FP_EXTEND_HEADER
16276789Sdim
17276789Sdim#include "int_lib.h"
18276789Sdim
19276789Sdim#if defined SRC_SINGLE
20276789Sdimtypedef float src_t;
21276789Sdimtypedef uint32_t src_rep_t;
22276789Sdim#define SRC_REP_C UINT32_C
23276789Sdimstatic const int srcSigBits = 23;
24276789Sdim#define src_rep_t_clz __builtin_clz
25276789Sdim
26276789Sdim#elif defined SRC_DOUBLE
27276789Sdimtypedef double src_t;
28276789Sdimtypedef uint64_t src_rep_t;
29276789Sdim#define SRC_REP_C UINT64_C
30276789Sdimstatic const int srcSigBits = 52;
31296417Sdimstatic __inline int src_rep_t_clz(src_rep_t a) {
32276789Sdim#if defined __LP64__
33276789Sdim    return __builtin_clzl(a);
34276789Sdim#else
35276789Sdim    if (a & REP_C(0xffffffff00000000))
36276789Sdim        return __builtin_clz(a >> 32);
37276789Sdim    else
38276789Sdim        return 32 + __builtin_clz(a & REP_C(0xffffffff));
39276789Sdim#endif
40276789Sdim}
41276789Sdim
42288943Sdim#elif defined SRC_HALF
43288943Sdimtypedef uint16_t src_t;
44288943Sdimtypedef uint16_t src_rep_t;
45288943Sdim#define SRC_REP_C UINT16_C
46288943Sdimstatic const int srcSigBits = 10;
47288943Sdim#define src_rep_t_clz __builtin_clz
48288943Sdim
49276789Sdim#else
50288943Sdim#error Source should be half, single, or double precision!
51276789Sdim#endif //end source precision
52276789Sdim
53288943Sdim#if defined DST_SINGLE
54288943Sdimtypedef float dst_t;
55288943Sdimtypedef uint32_t dst_rep_t;
56288943Sdim#define DST_REP_C UINT32_C
57288943Sdimstatic const int dstSigBits = 23;
58288943Sdim
59288943Sdim#elif defined DST_DOUBLE
60276789Sdimtypedef double dst_t;
61276789Sdimtypedef uint64_t dst_rep_t;
62276789Sdim#define DST_REP_C UINT64_C
63276789Sdimstatic const int dstSigBits = 52;
64276789Sdim
65276789Sdim#elif defined DST_QUAD
66276789Sdimtypedef long double dst_t;
67276789Sdimtypedef __uint128_t dst_rep_t;
68276789Sdim#define DST_REP_C (__uint128_t)
69276789Sdimstatic const int dstSigBits = 112;
70276789Sdim
71276789Sdim#else
72288943Sdim#error Destination should be single, double, or quad precision!
73276789Sdim#endif //end destination precision
74276789Sdim
75276789Sdim// End of specialization parameters.  Two helper routines for conversion to and
76276789Sdim// from the representation of floating-point data as integer values follow.
77276789Sdim
78296417Sdimstatic __inline src_rep_t srcToRep(src_t x) {
79276789Sdim    const union { src_t f; src_rep_t i; } rep = {.f = x};
80276789Sdim    return rep.i;
81276789Sdim}
82276789Sdim
83296417Sdimstatic __inline dst_t dstFromRep(dst_rep_t x) {
84276789Sdim    const union { dst_t f; dst_rep_t i; } rep = {.i = x};
85276789Sdim    return rep.f;
86276789Sdim}
87276789Sdim// End helper routines.  Conversion implementation follows.
88276789Sdim
89276789Sdim#endif //FP_EXTEND_HEADER
90