]>
Commit | Line | Data |
---|---|---|
d9dd51dc PB |
1 | /* Half-float conversion routines. |
2 | ||
8d9254fc | 3 | Copyright (C) 2008-2020 Free Software Foundation, Inc. |
d9dd51dc PB |
4 | Contributed by CodeSourcery. |
5 | ||
6 | This file is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
8 | Free Software Foundation; either version 3, or (at your option) any | |
9 | later version. | |
10 | ||
11 | This file is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
16 | Under Section 7 of GPL version 3, you are granted additional | |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
24 | ||
8630cadb JG |
25 | struct format |
26 | { | |
27 | /* Number of bits. */ | |
28 | unsigned long long size; | |
29 | /* Exponent bias. */ | |
30 | unsigned long long bias; | |
31 | /* Exponent width in bits. */ | |
32 | unsigned long long exponent; | |
33 | /* Significand precision in explicitly stored bits. */ | |
34 | unsigned long long significand; | |
35 | }; | |
36 | ||
37 | static const struct format | |
38 | binary32 = | |
39 | { | |
40 | 32, /* size. */ | |
41 | 127, /* bias. */ | |
42 | 8, /* exponent. */ | |
43 | 23 /* significand. */ | |
44 | }; | |
45 | ||
bea64ca3 JG |
46 | static const struct format |
47 | binary64 = | |
48 | { | |
49 | 64, /* size. */ | |
50 | 1023, /* bias. */ | |
51 | 11, /* exponent. */ | |
52 | 52 /* significand. */ | |
53 | }; | |
54 | ||
d9dd51dc | 55 | static inline unsigned short |
8630cadb JG |
56 | __gnu_float2h_internal (const struct format* fmt, |
57 | unsigned long long a, int ieee) | |
d9dd51dc | 58 | { |
8630cadb JG |
59 | unsigned long long point = 1ULL << fmt->significand; |
60 | unsigned short sign = (a >> (fmt->size - 16)) & 0x8000; | |
61 | int aexp; | |
62 | unsigned long long mantissa; | |
63 | unsigned long long mask; | |
64 | unsigned long long increment; | |
65 | ||
66 | /* Get the exponent and mantissa encodings. */ | |
67 | mantissa = a & (point - 1); | |
d9dd51dc | 68 | |
8630cadb JG |
69 | mask = (1 << fmt->exponent) - 1; |
70 | aexp = (a >> fmt->significand) & mask; | |
71 | ||
72 | /* Infinity, NaN and alternative format special case. */ | |
73 | if (((unsigned int) aexp) == mask) | |
d9dd51dc PB |
74 | { |
75 | if (!ieee) | |
76 | return sign; | |
4dfe21ac RE |
77 | if (mantissa == 0) |
78 | return sign | 0x7c00; /* Infinity. */ | |
79 | /* Remaining cases are NaNs. Convert SNaN to QNaN. */ | |
8630cadb | 80 | return sign | 0x7e00 | (mantissa >> (fmt->significand - 10)); |
d9dd51dc | 81 | } |
4dfe21ac | 82 | |
8630cadb | 83 | /* Zero. */ |
d9dd51dc PB |
84 | if (aexp == 0 && mantissa == 0) |
85 | return sign; | |
86 | ||
8630cadb JG |
87 | /* Construct the exponent and mantissa. */ |
88 | aexp -= fmt->bias; | |
89 | ||
90 | /* Decimal point is immediately after the significand. */ | |
91 | mantissa |= point; | |
d9dd51dc | 92 | |
d9dd51dc PB |
93 | if (aexp < -14) |
94 | { | |
8630cadb JG |
95 | mask = point | (point - 1); |
96 | /* Minimum exponent for half-precision is 2^-24. */ | |
65f14117 | 97 | if (aexp >= -25) |
4dfe21ac | 98 | mask >>= 25 + aexp; |
d9dd51dc PB |
99 | } |
100 | else | |
8630cadb | 101 | mask = (point - 1) >> 10; |
d9dd51dc PB |
102 | |
103 | /* Round. */ | |
104 | if (mantissa & mask) | |
105 | { | |
106 | increment = (mask + 1) >> 1; | |
107 | if ((mantissa & mask) == increment) | |
108 | increment = mantissa & (increment << 1); | |
109 | mantissa += increment; | |
8630cadb JG |
110 | if (mantissa >= (point << 1)) |
111 | { | |
d9dd51dc PB |
112 | mantissa >>= 1; |
113 | aexp++; | |
114 | } | |
115 | } | |
116 | ||
117 | if (ieee) | |
118 | { | |
119 | if (aexp > 15) | |
120 | return sign | 0x7c00; | |
121 | } | |
122 | else | |
123 | { | |
124 | if (aexp > 16) | |
125 | return sign | 0x7fff; | |
126 | } | |
127 | ||
128 | if (aexp < -24) | |
129 | return sign; | |
130 | ||
131 | if (aexp < -14) | |
132 | { | |
133 | mantissa >>= -14 - aexp; | |
134 | aexp = -14; | |
135 | } | |
136 | ||
8630cadb JG |
137 | /* Encode the final 16-bit floating-point value. |
138 | ||
139 | This is formed of the sign bit, the bias-adjusted exponent, and the | |
140 | calculated mantissa, with the following caveats: | |
141 | ||
142 | 1. The mantissa calculated after rounding could have a leading 1. | |
143 | To compensate for this, subtract one from the exponent bias (15) | |
144 | before adding it to the calculated exponent. | |
145 | 2. When we were calculating rounding, we left the mantissa with the | |
146 | number of bits of the source operand, it needs reduced to ten | |
147 | bits (+1 for the afforementioned leading 1) by shifting right by | |
148 | the number of bits in the source mantissa - 10. | |
149 | 3. To ensure the leading 1 in the mantissa is applied to the exponent | |
150 | we need to add the mantissa rather than apply an arithmetic "or" | |
151 | to it. */ | |
152 | ||
153 | return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10))); | |
154 | } | |
155 | ||
156 | static inline unsigned short | |
157 | __gnu_f2h_internal (unsigned int a, int ieee) | |
158 | { | |
159 | return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee); | |
d9dd51dc PB |
160 | } |
161 | ||
bea64ca3 JG |
162 | static inline unsigned short |
163 | __gnu_d2h_internal (unsigned long long a, int ieee) | |
164 | { | |
165 | return __gnu_float2h_internal (&binary64, a, ieee); | |
166 | } | |
167 | ||
d9dd51dc PB |
168 | unsigned int |
169 | __gnu_h2f_internal(unsigned short a, int ieee) | |
170 | { | |
171 | unsigned int sign = (unsigned int)(a & 0x8000) << 16; | |
172 | int aexp = (a >> 10) & 0x1f; | |
173 | unsigned int mantissa = a & 0x3ff; | |
174 | ||
175 | if (aexp == 0x1f && ieee) | |
176 | return sign | 0x7f800000 | (mantissa << 13); | |
177 | ||
178 | if (aexp == 0) | |
179 | { | |
180 | int shift; | |
181 | ||
182 | if (mantissa == 0) | |
183 | return sign; | |
184 | ||
185 | shift = __builtin_clz(mantissa) - 21; | |
186 | mantissa <<= shift; | |
187 | aexp = -shift; | |
188 | } | |
189 | ||
190 | return sign | (((aexp + 0x70) << 23) + (mantissa << 13)); | |
191 | } | |
192 | ||
193 | unsigned short | |
194 | __gnu_f2h_ieee(unsigned int a) | |
195 | { | |
196 | return __gnu_f2h_internal(a, 1); | |
197 | } | |
198 | ||
199 | unsigned int | |
200 | __gnu_h2f_ieee(unsigned short a) | |
201 | { | |
202 | return __gnu_h2f_internal(a, 1); | |
203 | } | |
204 | ||
205 | unsigned short | |
206 | __gnu_f2h_alternative(unsigned int x) | |
207 | { | |
208 | return __gnu_f2h_internal(x, 0); | |
209 | } | |
210 | ||
211 | unsigned int | |
212 | __gnu_h2f_alternative(unsigned short a) | |
213 | { | |
214 | return __gnu_h2f_internal(a, 0); | |
215 | } | |
bea64ca3 JG |
216 | |
217 | unsigned short | |
218 | __gnu_d2h_ieee (unsigned long long a) | |
219 | { | |
220 | return __gnu_d2h_internal (a, 1); | |
221 | } | |
222 | ||
223 | unsigned short | |
224 | __gnu_d2h_alternative (unsigned long long x) | |
225 | { | |
226 | return __gnu_d2h_internal (x, 0); | |
227 | } |