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