floatformat.c revision 1.1.1.7 1 1.1 christos /* IEEE floating point support routines, for GDB, the GNU Debugger.
2 1.1.1.7 christos Copyright (C) 1991-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GDB.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 2 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
19 1.1 christos
20 1.1 christos /* This is needed to pick up the NAN macro on some systems. */
21 1.1.1.4 christos #ifndef _GNU_SOURCE
22 1.1 christos #define _GNU_SOURCE
23 1.1.1.4 christos #endif
24 1.1 christos
25 1.1 christos #ifdef HAVE_CONFIG_H
26 1.1 christos #include "config.h"
27 1.1 christos #endif
28 1.1 christos
29 1.1 christos #include <math.h>
30 1.1 christos
31 1.1 christos #ifdef HAVE_STRING_H
32 1.1 christos #include <string.h>
33 1.1 christos #endif
34 1.1 christos
35 1.1 christos /* On some platforms, <float.h> provides DBL_QNAN. */
36 1.1 christos #ifdef STDC_HEADERS
37 1.1 christos #include <float.h>
38 1.1 christos #endif
39 1.1 christos
40 1.1 christos #include "ansidecl.h"
41 1.1 christos #include "libiberty.h"
42 1.1 christos #include "floatformat.h"
43 1.1 christos
44 1.1 christos #ifndef INFINITY
45 1.1 christos #ifdef HUGE_VAL
46 1.1 christos #define INFINITY HUGE_VAL
47 1.1 christos #else
48 1.1 christos #define INFINITY (1.0 / 0.0)
49 1.1 christos #endif
50 1.1 christos #endif
51 1.1 christos
52 1.1 christos #ifndef NAN
53 1.1 christos #ifdef DBL_QNAN
54 1.1 christos #define NAN DBL_QNAN
55 1.1 christos #else
56 1.1 christos #define NAN (0.0 / 0.0)
57 1.1 christos #endif
58 1.1 christos #endif
59 1.1 christos
60 1.1 christos static int mant_bits_set (const struct floatformat *, const unsigned char *);
61 1.1 christos static unsigned long get_field (const unsigned char *,
62 1.1 christos enum floatformat_byteorders,
63 1.1 christos unsigned int,
64 1.1 christos unsigned int,
65 1.1 christos unsigned int);
66 1.1 christos static int floatformat_always_valid (const struct floatformat *fmt,
67 1.1 christos const void *from);
68 1.1 christos
69 1.1 christos static int
70 1.1 christos floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
71 1.1 christos const void *from ATTRIBUTE_UNUSED)
72 1.1 christos {
73 1.1 christos return 1;
74 1.1 christos }
75 1.1 christos
76 1.1 christos /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
77 1.1 christos going to bother with trying to muck around with whether it is defined in
78 1.1 christos a system header, what we do if not, etc. */
79 1.1 christos #define FLOATFORMAT_CHAR_BIT 8
80 1.1 christos
81 1.1 christos /* floatformats for IEEE half, single and double, big and little endian. */
82 1.1 christos const struct floatformat floatformat_ieee_half_big =
83 1.1 christos {
84 1.1 christos floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
85 1.1 christos floatformat_intbit_no,
86 1.1 christos "floatformat_ieee_half_big",
87 1.1 christos floatformat_always_valid,
88 1.1 christos NULL
89 1.1 christos };
90 1.1 christos const struct floatformat floatformat_ieee_half_little =
91 1.1 christos {
92 1.1 christos floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
93 1.1 christos floatformat_intbit_no,
94 1.1 christos "floatformat_ieee_half_little",
95 1.1 christos floatformat_always_valid,
96 1.1 christos NULL
97 1.1 christos };
98 1.1 christos const struct floatformat floatformat_ieee_single_big =
99 1.1 christos {
100 1.1 christos floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
101 1.1 christos floatformat_intbit_no,
102 1.1 christos "floatformat_ieee_single_big",
103 1.1 christos floatformat_always_valid,
104 1.1 christos NULL
105 1.1 christos };
106 1.1 christos const struct floatformat floatformat_ieee_single_little =
107 1.1 christos {
108 1.1 christos floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
109 1.1 christos floatformat_intbit_no,
110 1.1 christos "floatformat_ieee_single_little",
111 1.1 christos floatformat_always_valid,
112 1.1 christos NULL
113 1.1 christos };
114 1.1 christos const struct floatformat floatformat_ieee_double_big =
115 1.1 christos {
116 1.1 christos floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
117 1.1 christos floatformat_intbit_no,
118 1.1 christos "floatformat_ieee_double_big",
119 1.1 christos floatformat_always_valid,
120 1.1 christos NULL
121 1.1 christos };
122 1.1 christos const struct floatformat floatformat_ieee_double_little =
123 1.1 christos {
124 1.1 christos floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
125 1.1 christos floatformat_intbit_no,
126 1.1 christos "floatformat_ieee_double_little",
127 1.1 christos floatformat_always_valid,
128 1.1 christos NULL
129 1.1 christos };
130 1.1 christos
131 1.1 christos /* floatformat for IEEE double, little endian byte order, with big endian word
132 1.1 christos ordering, as on the ARM. */
133 1.1 christos
134 1.1 christos const struct floatformat floatformat_ieee_double_littlebyte_bigword =
135 1.1 christos {
136 1.1 christos floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
137 1.1 christos floatformat_intbit_no,
138 1.1 christos "floatformat_ieee_double_littlebyte_bigword",
139 1.1 christos floatformat_always_valid,
140 1.1 christos NULL
141 1.1 christos };
142 1.1 christos
143 1.1 christos /* floatformat for VAX. Not quite IEEE, but close enough. */
144 1.1 christos
145 1.1 christos const struct floatformat floatformat_vax_f =
146 1.1 christos {
147 1.1 christos floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
148 1.1 christos floatformat_intbit_no,
149 1.1 christos "floatformat_vax_f",
150 1.1 christos floatformat_always_valid,
151 1.1 christos NULL
152 1.1 christos };
153 1.1 christos const struct floatformat floatformat_vax_d =
154 1.1 christos {
155 1.1 christos floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
156 1.1 christos floatformat_intbit_no,
157 1.1 christos "floatformat_vax_d",
158 1.1 christos floatformat_always_valid,
159 1.1 christos NULL
160 1.1 christos };
161 1.1 christos const struct floatformat floatformat_vax_g =
162 1.1 christos {
163 1.1 christos floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
164 1.1 christos floatformat_intbit_no,
165 1.1 christos "floatformat_vax_g",
166 1.1 christos floatformat_always_valid,
167 1.1 christos NULL
168 1.1 christos };
169 1.1 christos
170 1.1 christos static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
171 1.1 christos const void *from);
172 1.1 christos
173 1.1 christos static int
174 1.1 christos floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
175 1.1 christos {
176 1.1 christos /* In the i387 double-extended format, if the exponent is all ones,
177 1.1 christos then the integer bit must be set. If the exponent is neither 0
178 1.1 christos nor ~0, the intbit must also be set. Only if the exponent is
179 1.1 christos zero can it be zero, and then it must be zero. */
180 1.1 christos unsigned long exponent, int_bit;
181 1.1 christos const unsigned char *ufrom = (const unsigned char *) from;
182 1.1 christos
183 1.1 christos exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
184 1.1 christos fmt->exp_start, fmt->exp_len);
185 1.1 christos int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
186 1.1 christos fmt->man_start, 1);
187 1.1 christos
188 1.1 christos if ((exponent == 0) != (int_bit == 0))
189 1.1 christos return 0;
190 1.1 christos else
191 1.1 christos return 1;
192 1.1 christos }
193 1.1 christos
194 1.1 christos const struct floatformat floatformat_i387_ext =
195 1.1 christos {
196 1.1 christos floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
197 1.1 christos floatformat_intbit_yes,
198 1.1 christos "floatformat_i387_ext",
199 1.1 christos floatformat_i387_ext_is_valid,
200 1.1 christos NULL
201 1.1 christos };
202 1.1 christos const struct floatformat floatformat_m68881_ext =
203 1.1 christos {
204 1.1 christos /* Note that the bits from 16 to 31 are unused. */
205 1.1 christos floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
206 1.1 christos floatformat_intbit_yes,
207 1.1 christos "floatformat_m68881_ext",
208 1.1 christos floatformat_always_valid,
209 1.1 christos NULL
210 1.1 christos };
211 1.1 christos const struct floatformat floatformat_i960_ext =
212 1.1 christos {
213 1.1 christos /* Note that the bits from 0 to 15 are unused. */
214 1.1 christos floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
215 1.1 christos floatformat_intbit_yes,
216 1.1 christos "floatformat_i960_ext",
217 1.1 christos floatformat_always_valid,
218 1.1 christos NULL
219 1.1 christos };
220 1.1 christos const struct floatformat floatformat_m88110_ext =
221 1.1 christos {
222 1.1 christos floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
223 1.1 christos floatformat_intbit_yes,
224 1.1 christos "floatformat_m88110_ext",
225 1.1 christos floatformat_always_valid,
226 1.1 christos NULL
227 1.1 christos };
228 1.1 christos const struct floatformat floatformat_m88110_harris_ext =
229 1.1 christos {
230 1.1 christos /* Harris uses raw format 128 bytes long, but the number is just an ieee
231 1.1 christos double, and the last 64 bits are wasted. */
232 1.1 christos floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
233 1.1 christos floatformat_intbit_no,
234 1.1 christos "floatformat_m88110_ext_harris",
235 1.1 christos floatformat_always_valid,
236 1.1 christos NULL
237 1.1 christos };
238 1.1 christos const struct floatformat floatformat_arm_ext_big =
239 1.1 christos {
240 1.1 christos /* Bits 1 to 16 are unused. */
241 1.1 christos floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
242 1.1 christos floatformat_intbit_yes,
243 1.1 christos "floatformat_arm_ext_big",
244 1.1 christos floatformat_always_valid,
245 1.1 christos NULL
246 1.1 christos };
247 1.1 christos const struct floatformat floatformat_arm_ext_littlebyte_bigword =
248 1.1 christos {
249 1.1 christos /* Bits 1 to 16 are unused. */
250 1.1 christos floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
251 1.1 christos floatformat_intbit_yes,
252 1.1 christos "floatformat_arm_ext_littlebyte_bigword",
253 1.1 christos floatformat_always_valid,
254 1.1 christos NULL
255 1.1 christos };
256 1.1 christos const struct floatformat floatformat_ia64_spill_big =
257 1.1 christos {
258 1.1 christos floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
259 1.1 christos floatformat_intbit_yes,
260 1.1 christos "floatformat_ia64_spill_big",
261 1.1 christos floatformat_always_valid,
262 1.1 christos NULL
263 1.1 christos };
264 1.1 christos const struct floatformat floatformat_ia64_spill_little =
265 1.1 christos {
266 1.1 christos floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
267 1.1 christos floatformat_intbit_yes,
268 1.1 christos "floatformat_ia64_spill_little",
269 1.1 christos floatformat_always_valid,
270 1.1 christos NULL
271 1.1 christos };
272 1.1 christos const struct floatformat floatformat_ia64_quad_big =
273 1.1 christos {
274 1.1 christos floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
275 1.1 christos floatformat_intbit_no,
276 1.1 christos "floatformat_ia64_quad_big",
277 1.1 christos floatformat_always_valid,
278 1.1 christos NULL
279 1.1 christos };
280 1.1 christos const struct floatformat floatformat_ia64_quad_little =
281 1.1 christos {
282 1.1 christos floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
283 1.1 christos floatformat_intbit_no,
284 1.1 christos "floatformat_ia64_quad_little",
285 1.1 christos floatformat_always_valid,
286 1.1 christos NULL
287 1.1 christos };
288 1.1 christos
289 1.1 christos static int
290 1.1 christos floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
291 1.1 christos const void *from)
292 1.1 christos {
293 1.1 christos const unsigned char *ufrom = (const unsigned char *) from;
294 1.1 christos const struct floatformat *hfmt = fmt->split_half;
295 1.1 christos long top_exp, bot_exp;
296 1.1 christos int top_nan = 0;
297 1.1 christos
298 1.1 christos top_exp = get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
299 1.1 christos hfmt->exp_start, hfmt->exp_len);
300 1.1 christos bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
301 1.1 christos hfmt->exp_start, hfmt->exp_len);
302 1.1 christos
303 1.1 christos if ((unsigned long) top_exp == hfmt->exp_nan)
304 1.1 christos top_nan = mant_bits_set (hfmt, ufrom);
305 1.1 christos
306 1.1 christos /* A NaN is valid with any low part. */
307 1.1 christos if (top_nan)
308 1.1 christos return 1;
309 1.1 christos
310 1.1 christos /* An infinity, zero or denormal requires low part 0 (positive or
311 1.1 christos negative). */
312 1.1 christos if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
313 1.1 christos {
314 1.1 christos if (bot_exp != 0)
315 1.1 christos return 0;
316 1.1 christos
317 1.1 christos return !mant_bits_set (hfmt, ufrom + 8);
318 1.1 christos }
319 1.1 christos
320 1.1 christos /* The top part is now a finite normal value. The long double value
321 1.1 christos is the sum of the two parts, and the top part must equal the
322 1.1 christos result of rounding the long double value to nearest double. Thus
323 1.1 christos the bottom part must be <= 0.5ulp of the top part in absolute
324 1.1 christos value, and if it is < 0.5ulp then the long double is definitely
325 1.1 christos valid. */
326 1.1 christos if (bot_exp < top_exp - 53)
327 1.1 christos return 1;
328 1.1 christos if (bot_exp > top_exp - 53 && bot_exp != 0)
329 1.1 christos return 0;
330 1.1 christos if (bot_exp == 0)
331 1.1 christos {
332 1.1 christos /* The bottom part is 0 or denormal. Determine which, and if
333 1.1 christos denormal the first two set bits. */
334 1.1 christos int first_bit = -1, second_bit = -1, cur_bit;
335 1.1 christos for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
336 1.1 christos if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
337 1.1 christos hfmt->man_start + cur_bit, 1))
338 1.1 christos {
339 1.1 christos if (first_bit == -1)
340 1.1 christos first_bit = cur_bit;
341 1.1 christos else
342 1.1 christos {
343 1.1 christos second_bit = cur_bit;
344 1.1 christos break;
345 1.1 christos }
346 1.1 christos }
347 1.1 christos /* Bottom part 0 is OK. */
348 1.1 christos if (first_bit == -1)
349 1.1 christos return 1;
350 1.1 christos /* The real exponent of the bottom part is -first_bit. */
351 1.1 christos if (-first_bit < top_exp - 53)
352 1.1 christos return 1;
353 1.1 christos if (-first_bit > top_exp - 53)
354 1.1 christos return 0;
355 1.1 christos /* The bottom part is at least 0.5ulp of the top part. For this
356 1.1 christos to be OK, the bottom part must be exactly 0.5ulp (i.e. no
357 1.1 christos more bits set) and the top part must have last bit 0. */
358 1.1 christos if (second_bit != -1)
359 1.1 christos return 0;
360 1.1 christos return !get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
361 1.1 christos hfmt->man_start + hfmt->man_len - 1, 1);
362 1.1 christos }
363 1.1 christos else
364 1.1 christos {
365 1.1 christos /* The bottom part is at least 0.5ulp of the top part. For this
366 1.1 christos to be OK, it must be exactly 0.5ulp (i.e. no explicit bits
367 1.1 christos set) and the top part must have last bit 0. */
368 1.1 christos if (get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
369 1.1 christos hfmt->man_start + hfmt->man_len - 1, 1))
370 1.1 christos return 0;
371 1.1 christos return !mant_bits_set (hfmt, ufrom + 8);
372 1.1 christos }
373 1.1 christos }
374 1.1 christos
375 1.1.1.3 christos const struct floatformat floatformat_ibm_long_double_big =
376 1.1 christos {
377 1.1 christos floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
378 1.1 christos floatformat_intbit_no,
379 1.1.1.3 christos "floatformat_ibm_long_double_big",
380 1.1 christos floatformat_ibm_long_double_is_valid,
381 1.1 christos &floatformat_ieee_double_big
382 1.1 christos };
383 1.1.1.3 christos
384 1.1.1.3 christos const struct floatformat floatformat_ibm_long_double_little =
385 1.1.1.3 christos {
386 1.1.1.3 christos floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52,
387 1.1.1.3 christos floatformat_intbit_no,
388 1.1.1.3 christos "floatformat_ibm_long_double_little",
389 1.1.1.3 christos floatformat_ibm_long_double_is_valid,
390 1.1.1.3 christos &floatformat_ieee_double_little
391 1.1.1.3 christos };
392 1.1.1.7 christos
393 1.1.1.7 christos const struct floatformat floatformat_bfloat16_big =
394 1.1.1.7 christos {
395 1.1.1.7 christos floatformat_big, 16, 0, 1, 8, 127, 255, 9, 7,
396 1.1.1.7 christos floatformat_intbit_no,
397 1.1.1.7 christos "floatformat_bfloat16_big",
398 1.1.1.7 christos floatformat_always_valid,
399 1.1.1.7 christos NULL
400 1.1.1.7 christos };
401 1.1.1.7 christos
402 1.1.1.7 christos const struct floatformat floatformat_bfloat16_little =
403 1.1.1.7 christos {
404 1.1.1.7 christos floatformat_little, 16, 0, 1, 8, 127, 255, 9, 7,
405 1.1.1.7 christos floatformat_intbit_no,
406 1.1.1.7 christos "floatformat_bfloat16_little",
407 1.1.1.7 christos floatformat_always_valid,
408 1.1.1.7 christos NULL
409 1.1.1.7 christos };
410 1.1 christos
411 1.1 christos #ifndef min
412 1.1 christos #define min(a, b) ((a) < (b) ? (a) : (b))
413 1.1 christos #endif
414 1.1 christos
415 1.1 christos /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
416 1.1 christos format FMT, 0 otherwise. */
417 1.1 christos static int
418 1.1 christos mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
419 1.1 christos {
420 1.1 christos unsigned int mant_bits, mant_off;
421 1.1 christos int mant_bits_left;
422 1.1 christos
423 1.1 christos mant_off = fmt->man_start;
424 1.1 christos mant_bits_left = fmt->man_len;
425 1.1 christos while (mant_bits_left > 0)
426 1.1 christos {
427 1.1 christos mant_bits = min (mant_bits_left, 32);
428 1.1 christos
429 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
430 1.1 christos mant_off, mant_bits) != 0)
431 1.1 christos return 1;
432 1.1 christos
433 1.1 christos mant_off += mant_bits;
434 1.1 christos mant_bits_left -= mant_bits;
435 1.1 christos }
436 1.1 christos return 0;
437 1.1 christos }
438 1.1 christos
439 1.1 christos /* Extract a field which starts at START and is LEN bits long. DATA and
440 1.1 christos TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
441 1.1 christos static unsigned long
442 1.1 christos get_field (const unsigned char *data, enum floatformat_byteorders order,
443 1.1 christos unsigned int total_len, unsigned int start, unsigned int len)
444 1.1 christos {
445 1.1 christos unsigned long result = 0;
446 1.1 christos unsigned int cur_byte;
447 1.1 christos int lo_bit, hi_bit, cur_bitshift = 0;
448 1.1 christos int nextbyte = (order == floatformat_little) ? 1 : -1;
449 1.1 christos
450 1.1 christos /* Start is in big-endian bit order! Fix that first. */
451 1.1 christos start = total_len - (start + len);
452 1.1 christos
453 1.1 christos /* Start at the least significant part of the field. */
454 1.1 christos if (order == floatformat_little)
455 1.1 christos cur_byte = start / FLOATFORMAT_CHAR_BIT;
456 1.1 christos else
457 1.1 christos cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
458 1.1 christos
459 1.1 christos lo_bit = start % FLOATFORMAT_CHAR_BIT;
460 1.1 christos hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
461 1.1 christos
462 1.1 christos do
463 1.1 christos {
464 1.1 christos unsigned int shifted = *(data + cur_byte) >> lo_bit;
465 1.1 christos unsigned int bits = hi_bit - lo_bit;
466 1.1 christos unsigned int mask = (1 << bits) - 1;
467 1.1 christos result |= (shifted & mask) << cur_bitshift;
468 1.1 christos len -= bits;
469 1.1 christos cur_bitshift += bits;
470 1.1 christos cur_byte += nextbyte;
471 1.1 christos lo_bit = 0;
472 1.1 christos hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
473 1.1 christos }
474 1.1 christos while (len != 0);
475 1.1 christos
476 1.1 christos return result;
477 1.1 christos }
478 1.1 christos
479 1.1 christos /* Convert from FMT to a double.
480 1.1 christos FROM is the address of the extended float.
481 1.1 christos Store the double in *TO. */
482 1.1 christos
483 1.1 christos void
484 1.1 christos floatformat_to_double (const struct floatformat *fmt,
485 1.1 christos const void *from, double *to)
486 1.1 christos {
487 1.1 christos const unsigned char *ufrom = (const unsigned char *) from;
488 1.1 christos double dto;
489 1.1 christos long exponent;
490 1.1 christos unsigned long mant;
491 1.1 christos unsigned int mant_bits, mant_off;
492 1.1 christos int mant_bits_left;
493 1.1 christos
494 1.1 christos /* Split values are not handled specially, since the top half has
495 1.1 christos the correctly rounded double value (in the only supported case of
496 1.1 christos split values). */
497 1.1 christos
498 1.1 christos exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
499 1.1 christos fmt->exp_start, fmt->exp_len);
500 1.1 christos
501 1.1 christos /* If the exponent indicates a NaN, we don't have information to
502 1.1 christos decide what to do. So we handle it like IEEE, except that we
503 1.1 christos don't try to preserve the type of NaN. FIXME. */
504 1.1 christos if ((unsigned long) exponent == fmt->exp_nan)
505 1.1 christos {
506 1.1 christos int nan = mant_bits_set (fmt, ufrom);
507 1.1 christos
508 1.1 christos /* On certain systems (such as GNU/Linux), the use of the
509 1.1.1.7 christos INFINITY macro below may generate a warning that cannot be
510 1.1 christos silenced due to a bug in GCC (PR preprocessor/11931). The
511 1.1 christos preprocessor fails to recognise the __extension__ keyword in
512 1.1 christos conjunction with the GNU/C99 extension for hexadecimal
513 1.1 christos floating point constants and will issue a warning when
514 1.1 christos compiling with -pedantic. */
515 1.1 christos if (nan)
516 1.1 christos dto = NAN;
517 1.1 christos else
518 1.1 christos dto = INFINITY;
519 1.1 christos
520 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
521 1.1 christos dto = -dto;
522 1.1 christos
523 1.1 christos *to = dto;
524 1.1 christos
525 1.1 christos return;
526 1.1 christos }
527 1.1 christos
528 1.1 christos mant_bits_left = fmt->man_len;
529 1.1 christos mant_off = fmt->man_start;
530 1.1 christos dto = 0.0;
531 1.1 christos
532 1.1 christos /* Build the result algebraically. Might go infinite, underflow, etc;
533 1.1 christos who cares. */
534 1.1 christos
535 1.1.1.2 christos /* For denorms use minimum exponent. */
536 1.1.1.2 christos if (exponent == 0)
537 1.1.1.2 christos exponent = 1 - fmt->exp_bias;
538 1.1.1.2 christos else
539 1.1 christos {
540 1.1.1.2 christos exponent -= fmt->exp_bias;
541 1.1.1.2 christos
542 1.1.1.2 christos /* If this format uses a hidden bit, explicitly add it in now.
543 1.1.1.2 christos Otherwise, increment the exponent by one to account for the
544 1.1.1.2 christos integer bit. */
545 1.1.1.2 christos
546 1.1 christos if (fmt->intbit == floatformat_intbit_no)
547 1.1 christos dto = ldexp (1.0, exponent);
548 1.1 christos else
549 1.1 christos exponent++;
550 1.1 christos }
551 1.1 christos
552 1.1 christos while (mant_bits_left > 0)
553 1.1 christos {
554 1.1 christos mant_bits = min (mant_bits_left, 32);
555 1.1 christos
556 1.1 christos mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
557 1.1 christos mant_off, mant_bits);
558 1.1 christos
559 1.1.1.2 christos dto += ldexp ((double) mant, exponent - mant_bits);
560 1.1.1.2 christos exponent -= mant_bits;
561 1.1 christos mant_off += mant_bits;
562 1.1 christos mant_bits_left -= mant_bits;
563 1.1 christos }
564 1.1 christos
565 1.1 christos /* Negate it if negative. */
566 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
567 1.1 christos dto = -dto;
568 1.1 christos *to = dto;
569 1.1 christos }
570 1.1 christos
571 1.1 christos static void put_field (unsigned char *, enum floatformat_byteorders,
573 1.1 christos unsigned int,
574 1.1 christos unsigned int,
575 1.1 christos unsigned int,
576 1.1 christos unsigned long);
577 1.1 christos
578 1.1 christos /* Set a field which starts at START and is LEN bits long. DATA and
579 1.1 christos TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
580 1.1 christos static void
581 1.1 christos put_field (unsigned char *data, enum floatformat_byteorders order,
582 1.1 christos unsigned int total_len, unsigned int start, unsigned int len,
583 1.1 christos unsigned long stuff_to_put)
584 1.1 christos {
585 1.1 christos unsigned int cur_byte;
586 1.1 christos int lo_bit, hi_bit;
587 1.1 christos int nextbyte = (order == floatformat_little) ? 1 : -1;
588 1.1 christos
589 1.1 christos /* Start is in big-endian bit order! Fix that first. */
590 1.1 christos start = total_len - (start + len);
591 1.1 christos
592 1.1 christos /* Start at the least significant part of the field. */
593 1.1 christos if (order == floatformat_little)
594 1.1 christos cur_byte = start / FLOATFORMAT_CHAR_BIT;
595 1.1 christos else
596 1.1 christos cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
597 1.1 christos
598 1.1 christos lo_bit = start % FLOATFORMAT_CHAR_BIT;
599 1.1 christos hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
600 1.1 christos
601 1.1 christos do
602 1.1 christos {
603 1.1 christos unsigned char *byte_ptr = data + cur_byte;
604 1.1 christos unsigned int bits = hi_bit - lo_bit;
605 1.1 christos unsigned int mask = ((1 << bits) - 1) << lo_bit;
606 1.1 christos *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
607 1.1 christos stuff_to_put >>= bits;
608 1.1 christos len -= bits;
609 1.1 christos cur_byte += nextbyte;
610 1.1 christos lo_bit = 0;
611 1.1 christos hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
612 1.1 christos }
613 1.1 christos while (len != 0);
614 1.1 christos }
615 1.1 christos
616 1.1 christos /* The converse: convert the double *FROM to an extended float
617 1.1 christos and store where TO points. Neither FROM nor TO have any alignment
618 1.1 christos restrictions. */
619 1.1 christos
620 1.1 christos void
621 1.1 christos floatformat_from_double (const struct floatformat *fmt,
622 1.1 christos const double *from, void *to)
623 1.1 christos {
624 1.1 christos double dfrom;
625 1.1 christos int exponent;
626 1.1 christos double mant;
627 1.1 christos unsigned int mant_bits, mant_off;
628 1.1 christos int mant_bits_left;
629 1.1 christos unsigned char *uto = (unsigned char *) to;
630 1.1 christos
631 1.1 christos dfrom = *from;
632 1.1 christos memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
633 1.1 christos
634 1.1 christos /* Split values are not handled specially, since a bottom half of
635 1.1 christos zero is correct for any value representable as double (in the
636 1.1 christos only supported case of split values). */
637 1.1 christos
638 1.1 christos /* If negative, set the sign bit. */
639 1.1 christos if (dfrom < 0)
640 1.1 christos {
641 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
642 1.1 christos dfrom = -dfrom;
643 1.1 christos }
644 1.1 christos
645 1.1 christos if (dfrom == 0)
646 1.1 christos {
647 1.1 christos /* 0.0. */
648 1.1 christos return;
649 1.1 christos }
650 1.1 christos
651 1.1 christos if (dfrom != dfrom)
652 1.1 christos {
653 1.1 christos /* NaN. */
654 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
655 1.1 christos fmt->exp_len, fmt->exp_nan);
656 1.1 christos /* Be sure it's not infinity, but NaN value is irrelevant. */
657 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
658 1.1 christos 32, 1);
659 1.1 christos return;
660 1.1 christos }
661 1.1 christos
662 1.1 christos if (dfrom + dfrom == dfrom)
663 1.1 christos {
664 1.1 christos /* This can only happen for an infinite value (or zero, which we
665 1.1 christos already handled above). */
666 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
667 1.1 christos fmt->exp_len, fmt->exp_nan);
668 1.1 christos return;
669 1.1 christos }
670 1.1 christos
671 1.1 christos mant = frexp (dfrom, &exponent);
672 1.1 christos if (exponent + fmt->exp_bias - 1 > 0)
673 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
674 1.1 christos fmt->exp_len, exponent + fmt->exp_bias - 1);
675 1.1 christos else
676 1.1 christos {
677 1.1 christos /* Handle a denormalized number. FIXME: What should we do for
678 1.1 christos non-IEEE formats? */
679 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
680 1.1 christos fmt->exp_len, 0);
681 1.1 christos mant = ldexp (mant, exponent + fmt->exp_bias - 1);
682 1.1 christos }
683 1.1 christos
684 1.1 christos mant_bits_left = fmt->man_len;
685 1.1 christos mant_off = fmt->man_start;
686 1.1 christos while (mant_bits_left > 0)
687 1.1 christos {
688 1.1 christos unsigned long mant_long;
689 1.1 christos mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
690 1.1 christos
691 1.1 christos mant *= 4294967296.0;
692 1.1 christos mant_long = (unsigned long)mant;
693 1.1 christos mant -= mant_long;
694 1.1 christos
695 1.1 christos /* If the integer bit is implicit, and we are not creating a
696 1.1 christos denormalized number, then we need to discard it. */
697 1.1 christos if ((unsigned int) mant_bits_left == fmt->man_len
698 1.1 christos && fmt->intbit == floatformat_intbit_no
699 1.1 christos && exponent + fmt->exp_bias - 1 > 0)
700 1.1 christos {
701 1.1 christos mant_long &= 0x7fffffff;
702 1.1 christos mant_bits -= 1;
703 1.1 christos }
704 1.1 christos else if (mant_bits < 32)
705 1.1 christos {
706 1.1 christos /* The bits we want are in the most significant MANT_BITS bits of
707 1.1 christos mant_long. Move them to the least significant. */
708 1.1 christos mant_long >>= 32 - mant_bits;
709 1.1 christos }
710 1.1 christos
711 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize,
712 1.1 christos mant_off, mant_bits, mant_long);
713 1.1 christos mant_off += mant_bits;
714 1.1 christos mant_bits_left -= mant_bits;
715 1.1 christos }
716 1.1 christos }
717 1.1 christos
718 1.1 christos /* Return non-zero iff the data at FROM is a valid number in format FMT. */
719 1.1 christos
720 1.1 christos int
721 1.1 christos floatformat_is_valid (const struct floatformat *fmt, const void *from)
722 1.1 christos {
723 1.1 christos return fmt->is_valid (fmt, from);
724 1.1 christos }
725 1.1 christos
726 1.1 christos
727 1.1 christos #ifdef IEEE_DEBUG
728 1.1 christos
729 1.1 christos #include <stdio.h>
730 1.1 christos
731 1.1 christos /* This is to be run on a host which uses IEEE floating point. */
732 1.1 christos
733 1.1 christos void
734 1.1 christos ieee_test (double n)
735 1.1 christos {
736 1.1 christos double result;
737 1.1 christos
738 1.1 christos floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
739 1.1 christos if ((n != result && (! isnan (n) || ! isnan (result)))
740 1.1 christos || (n < 0 && result >= 0)
741 1.1 christos || (n >= 0 && result < 0))
742 1.1 christos printf ("Differ(to): %.20g -> %.20g\n", n, result);
743 1.1 christos
744 1.1 christos floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
745 1.1 christos if ((n != result && (! isnan (n) || ! isnan (result)))
746 1.1 christos || (n < 0 && result >= 0)
747 1.1 christos || (n >= 0 && result < 0))
748 1.1 christos printf ("Differ(from): %.20g -> %.20g\n", n, result);
749 1.1 christos
750 1.1 christos #if 0
751 1.1 christos {
752 1.1 christos char exten[16];
753 1.1 christos
754 1.1 christos floatformat_from_double (&floatformat_m68881_ext, &n, exten);
755 1.1 christos floatformat_to_double (&floatformat_m68881_ext, exten, &result);
756 1.1 christos if (n != result)
757 1.1 christos printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
758 1.1 christos }
759 1.1 christos #endif
760 1.1 christos
761 1.1 christos #if IEEE_DEBUG > 1
762 1.1 christos /* This is to be run on a host which uses 68881 format. */
763 1.1 christos {
764 1.1 christos long double ex = *(long double *)exten;
765 1.1 christos if (ex != n)
766 1.1 christos printf ("Differ(from vs. extended): %.20g\n", n);
767 1.1 christos }
768 1.1 christos #endif
769 1.1 christos }
770 1.1 christos
771 1.1 christos int
772 1.1 christos main (void)
773 1.1 christos {
774 1.1 christos ieee_test (0.0);
775 1.1.1.2 christos ieee_test (0.5);
776 1.1 christos ieee_test (1.1);
777 1.1 christos ieee_test (256.0);
778 1.1 christos ieee_test (0.12345);
779 1.1 christos ieee_test (234235.78907234);
780 1.1 christos ieee_test (-512.0);
781 1.1 christos ieee_test (-0.004321);
782 1.1 christos ieee_test (1.2E-70);
783 1.1 christos ieee_test (1.2E-316);
784 1.1 christos ieee_test (4.9406564584124654E-324);
785 1.1 christos ieee_test (- 4.9406564584124654E-324);
786 1.1 christos ieee_test (- 0.0);
787 1.1 christos ieee_test (- INFINITY);
788 1.1 christos ieee_test (- NAN);
789 1.1 christos ieee_test (INFINITY);
790 1.1 christos ieee_test (NAN);
791 1.1 christos return 0;
792 1.1 christos }
793 #endif
794