GCC Code Coverage Report
Directory: . Exec Total Coverage
File: deps/install/include/symfpu/core/packing.h Lines: 58 58 100.0 %
Date: 2021-03-22 Branches: 129 206 62.6 %

Line Exec Source
1
/*
2
** Copyright (C) 2018 Martin Brain
3
**
4
** See the file LICENSE for licensing information.
5
*/
6
7
/*
8
** packing.h
9
**
10
** Martin Brain
11
** martin.brain@cs.ox.ac.uk
12
** 03/06/14
13
**
14
** Algorithms for converting from a packed float (a bit vector) into
15
** the working, unpacked float format.  Should be instantiated with a
16
** traits structure from one of the baseTypes/ implementations.
17
**
18
*/
19
20
#include "symfpu/core/unpackedFloat.h"
21
22
#ifndef SYMFPU_PACKING
23
#define SYMFPU_PACKING
24
25
namespace symfpu {
26
27
  template<class t>
28
327
    unpackedFloat<t> unpack (const typename t::fpt format, const typename t::ubv &packedFloat) {
29
    typedef typename t::bwt bwt;
30
    typedef typename t::prop prop;
31
    typedef typename t::ubv ubv;
32
    typedef typename t::sbv sbv;
33
34
327
    bwt pWidth = format.packedWidth();
35
327
    bwt exWidth = format.packedExponentWidth();
36
327
    bwt sigWidth = format.packedSignificandWidth();
37
38
327
    PRECONDITION(packedFloat.getWidth() == pWidth);
39
40
    // Extract
41
654
    ubv packedSignificand(packedFloat.extract(sigWidth - 1, 0));
42
654
    ubv packedExponent(packedFloat.extract(sigWidth + exWidth - 1, sigWidth));
43
341
    prop sign(packedFloat.extract(pWidth - 1, sigWidth + exWidth).isAllOnes());
44
45
    // Prepare the normal and subnormal cases
46
327
    bwt unpackedExWidth = unpackedFloat<t>::exponentWidth(format);
47
327
    bwt unpackedSigWidth = unpackedFloat<t>::significandWidth(format);
48
49
327
    INVARIANT(unpackedExWidth > exWidth); // To avoid overflow
50
654
    sbv biasedExponent(packedExponent.extend(unpackedExWidth - exWidth).toSigned() - unpackedFloat<t>::bias(format));
51
    // Optimisation : both the normal and subnormal paths subtract a constant
52
    // from the exponent as the last step (bias and minNormalExponent respectively)
53
54
654
    ubv significandWithLeadingZero(packedSignificand.extend(unpackedSigWidth - sigWidth));
55
654
    ubv significandWithLeadingOne(unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format)) | significandWithLeadingZero);
56
57
654
    unpackedFloat<t> ufNormal(sign, biasedExponent, significandWithLeadingOne);
58
654
    unpackedFloat<t> ufSubnormalBase(sign, unpackedFloat<t>::minNormalExponent(format), significandWithLeadingZero);
59
60
    // Optimisation : right shift the significand by one if subnormal
61
    //                and then set the carry in when you add to the exponent.
62
    //                May be sufficient to just assert that it has a leading zero
63
64
65
    // Analyse
66
341
    prop zeroExponent(packedExponent.isAllZeros());
67
341
    prop onesExponent(packedExponent.isAllOnes());
68
341
    prop zeroSignificand(significandWithLeadingZero.isAllZeros()); // Shared with normaliseUp
69
70
    // Identify the cases
71
341
    prop isZero(zeroExponent && zeroSignificand);
72
341
    prop isSubnormal(zeroExponent && !zeroSignificand);
73
341
    prop isNormal(!zeroExponent && !onesExponent);
74
341
    prop isInf(onesExponent && zeroSignificand);
75
341
    prop isNaN(onesExponent && !zeroSignificand);
76
77
327
    INVARIANT(isZero || isSubnormal || isNormal || isInf || isNaN);
78
79
327
    probabilityAnnotation<t,prop>(isSubnormal, UNLIKELY);
80
81
    // Splice together
82
953
    unpackedFloat<t> uf(ITE(isNaN,
83
			    unpackedFloat<t>::makeNaN(format),
84
			    ITE(isInf,
85
				unpackedFloat<t>::makeInf(format, sign),
86
				ITE(isZero,
87
				    unpackedFloat<t>::makeZero(format, sign),
88
626
				    ITE(!isSubnormal,
89
					ufNormal,
90
					ufSubnormalBase.normaliseUp(format) )))));
91
92
327
    POSTCONDITION(uf.valid(format));
93
94
654
    return uf;
95
  }
96
97
98
  template<class t>
99
6687
    typename t::ubv pack (const typename t::fpt &format, const unpackedFloat<t> &uf) {
100
    typedef typename t::bwt bwt;
101
    typedef typename t::prop prop;
102
    typedef typename t::ubv ubv;
103
    typedef typename t::sbv sbv;
104
105
6687
    PRECONDITION(uf.valid(format));
106
107
    // Sign
108
13374
    ubv packedSign(uf.getSign());
109
110
    // Exponent
111
6687
    bwt packedExWidth = format.packedExponentWidth();
112
113
9993
    prop inNormalRange(uf.inNormalRange(format, prop(true)));
114
6687
    INVARIANT(inNormalRange || uf.inSubnormalRange(format, prop(true)));     // Default values ensure this.
115
    //prop inSubnormalRange(uf.inSubnormalRange(format));        // Allowing this optimisation
116
9993
    prop inSubnormalRange(!inNormalRange);
117
118
6687
    probabilityAnnotation<t,prop>(inNormalRange, LIKELY);
119
6687
    probabilityAnnotation<t,prop>(inSubnormalRange, UNLIKELY);
120
121
13374
    sbv biasedExp(uf.getExponent() + unpackedFloat<t>::bias(format));
122
    // Will be correct for normal values only, subnormals may still be negative.
123
13374
    ubv packedBiasedExp(biasedExp.toUnsigned().extract(packedExWidth - 1,0));
124
125
13374
    ubv maxExp(ubv::allOnes(packedExWidth));
126
13374
    ubv minExp(ubv::zero(packedExWidth));
127
128
9993
    prop hasMaxExp(uf.getNaN() || uf.getInf());
129
9993
    prop hasMinExp(uf.getZero() || inSubnormalRange);
130
9993
    prop hasFixedExp(hasMaxExp || hasMinExp);
131
132
13374
    ubv packedExp(ITE(hasFixedExp,
133
		      ITE(hasMaxExp, maxExp, minExp),
134
		      packedBiasedExp));
135
136
137
    // Significand
138
6687
    bwt packedSigWidth = format.packedSignificandWidth();
139
13374
    ubv unpackedSignificand(uf.getSignificand());
140
141
6687
    INVARIANT(packedSigWidth == unpackedSignificand.getWidth() - 1);
142
13374
    ubv dropLeadingOne(unpackedSignificand.extract(packedSigWidth - 1,0));
143
13374
    ubv correctedSubnormal((unpackedSignificand >> (uf.getSubnormalAmount(format).toUnsigned().matchWidth(unpackedSignificand))).extract(packedSigWidth - 1,0));
144
145
9993
    prop hasFixedSignificand(uf.getNaN() || uf.getInf() || uf.getZero());
146
147
20061
    ubv packedSig(ITE(hasFixedSignificand,
148
6687
		      ITE(uf.getNaN(),
149
			  unpackedFloat<t>::nanPattern(packedSigWidth),
150
			  ubv::zero(packedSigWidth)),
151
		      ITE(inNormalRange,
152
			  dropLeadingOne,
153
			  correctedSubnormal)));
154
155
156
    // Finish up
157
6687
    ubv packed(packedSign.append(packedExp).append(packedSig));
158
159
6687
    POSTCONDITION(packed.getWidth() == format.packedWidth());
160
161
13374
    return packed;
162
  }
163
164
}
165
166
#endif