GCC Code Coverage Report
Directory: . Exec Total Coverage
File: build-coverage/deps/include/symfpu/core/packing.h Lines: 61 61 100.0 %
Date: 2021-09-16 Branches: 134 214 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
345
    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
345
    bwt pWidth = format.packedWidth();
35
345
    bwt exWidth = format.packedExponentWidth();
36
345
    bwt sigWidth = format.packedSignificandWidth();
37
38
345
    PRECONDITION(packedFloat.getWidth() == pWidth);
39
40
    // Extract
41
690
    ubv packedSignificand(packedFloat.extract(sigWidth - 1, 0));
42
690
    ubv packedExponent(packedFloat.extract(sigWidth + exWidth - 1, sigWidth));
43
363
    prop sign(packedFloat.extract(pWidth - 1, sigWidth + exWidth).isAllOnes());
44
45
    // Prepare the normal and subnormal cases
46
345
    bwt unpackedExWidth = unpackedFloat<t>::exponentWidth(format);
47
345
    bwt unpackedSigWidth = unpackedFloat<t>::significandWidth(format);
48
49
345
    INVARIANT(unpackedExWidth > exWidth); // To avoid overflow
50
690
    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
690
    ubv significandWithLeadingZero(packedSignificand.extend(unpackedSigWidth - sigWidth));
55
690
    ubv significandWithLeadingOne(unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format)) | significandWithLeadingZero);
56
57
690
    unpackedFloat<t> ufNormal(sign, biasedExponent, significandWithLeadingOne);
58
690
    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
363
    prop zeroExponent(packedExponent.isAllZeros());
67
363
    prop onesExponent(packedExponent.isAllOnes());
68
363
    prop zeroSignificand(significandWithLeadingZero.isAllZeros()); // Shared with normaliseUp
69
70
    // Identify the cases
71
363
    prop isZero(zeroExponent && zeroSignificand);
72
363
    prop isSubnormal(zeroExponent && !zeroSignificand);
73
363
    prop isNormal(!zeroExponent && !onesExponent);
74
363
    prop isInf(onesExponent && zeroSignificand);
75
363
    prop isNaN(onesExponent && !zeroSignificand);
76
77
345
    INVARIANT(isZero || isSubnormal || isNormal || isInf || isNaN);
78
79
345
    probabilityAnnotation<t,prop>(isSubnormal, UNLIKELY);
80
81
    // Splice together
82
999
    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
654
				    ITE(!isSubnormal,
89
					ufNormal,
90
					ufSubnormalBase.normaliseUp(format) )))));
91
92
345
    POSTCONDITION(uf.valid(format));
93
94
690
    return uf;
95
  }
96
97
98
  template<class t>
99
6321
    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
6321
    PRECONDITION(uf.valid(format));
106
107
    // Sign
108
12642
    ubv packedSign(uf.getSign());
109
110
    // Exponent
111
6321
    bwt packedExWidth(format.packedExponentWidth());
112
113
9465
    prop inNormalRange(uf.inNormalRange(format, prop(true)));
114
6321
    INVARIANT(inNormalRange || uf.inSubnormalRange(format, prop(true)));     // Default values ensure this.
115
    //prop inSubnormalRange(uf.inSubnormalRange(format));        // Allowing this optimisation
116
9465
    prop inSubnormalRange(!inNormalRange);
117
118
6321
    probabilityAnnotation<t,prop>(inNormalRange, LIKELY);
119
6321
    probabilityAnnotation<t,prop>(inSubnormalRange, UNLIKELY);
120
121
12642
    sbv biasedExp(uf.getExponent() + unpackedFloat<t>::bias(format));
122
    // Will be correct for normal values only, subnormals may still be negative.
123
12642
    ubv packedBiasedExp(biasedExp.toUnsigned().extract(packedExWidth - 1,0));
124
125
12642
    ubv maxExp(ubv::allOnes(packedExWidth));
126
12642
    ubv minExp(ubv::zero(packedExWidth));
127
128
9465
    prop hasMaxExp(uf.getNaN() || uf.getInf());
129
9465
    prop hasMinExp(uf.getZero() || inSubnormalRange);
130
9465
    prop hasFixedExp(hasMaxExp || hasMinExp);
131
132
12642
    ubv packedExp(ITE(hasFixedExp,
133
		      ITE(hasMaxExp, maxExp, minExp),
134
		      packedBiasedExp));
135
136
137
    // Significand
138
6321
    bwt packedSigWidth = format.packedSignificandWidth();
139
12642
    ubv unpackedSignificand(uf.getSignificand());
140
6321
    bwt unpackedSignificandWidth = unpackedSignificand.getWidth();
141
142
6321
    INVARIANT(packedSigWidth == unpackedSignificandWidth - 1);
143
12642
    ubv dropLeadingOne(unpackedSignificand.extract(packedSigWidth - 1,0));
144
145
12642
    ubv subnormalShiftAmount(uf.getSubnormalAmount(format).toUnsigned());
146
12642
    ubv shiftAmount((subnormalShiftAmount.getWidth() <= unpackedSignificandWidth) ?
147
		    subnormalShiftAmount.matchWidth(unpackedSignificand) :
148
		    subnormalShiftAmount.extract(unpackedSignificandWidth - 1, 0));
149
    // The extraction could loose data if exponent is much larger than the significand
150
    // However getSubnormalAmount is between 0 and packedSigWidth so it should be safe
151
12642
    ubv correctedSubnormal((unpackedSignificand >> shiftAmount).extract(packedSigWidth - 1,0));
152
153
9465
    prop hasFixedSignificand(uf.getNaN() || uf.getInf() || uf.getZero());
154
155
18963
    ubv packedSig(ITE(hasFixedSignificand,
156
6321
		      ITE(uf.getNaN(),
157
			  unpackedFloat<t>::nanPattern(packedSigWidth),
158
			  ubv::zero(packedSigWidth)),
159
		      ITE(inNormalRange,
160
			  dropLeadingOne,
161
			  correctedSubnormal)));
162
163
164
    // Finish up
165
6321
    ubv packed(packedSign.append(packedExp).append(packedSig));
166
167
6321
    POSTCONDITION(packed.getWidth() == format.packedWidth());
168
169
12642
    return packed;
170
  }
171
172
}
173
174
#endif