xref: /netbsd-src/external/gpl3/gcc.old/dist/libiberty/floatformat.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* IEEE floating point support routines, for GDB, the GNU Debugger.
2    Copyright (C) 1991-2020 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
floatformat_always_valid(const struct floatformat * fmt ATTRIBUTE_UNUSED,const void * from ATTRIBUTE_UNUSED)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 and double, 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 
136 /* floatformat for IEEE double, little endian byte order, with big endian word
137    ordering, as on the ARM.  */
138 
139 const struct floatformat floatformat_ieee_double_littlebyte_bigword =
140 {
141   floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
142   floatformat_intbit_no,
143   "floatformat_ieee_double_littlebyte_bigword",
144   floatformat_always_valid,
145   NULL
146 };
147 
148 /* floatformat for VAX.  Not quite IEEE, but close enough.  */
149 
150 const struct floatformat floatformat_vax_f =
151 {
152   floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
153   floatformat_intbit_no,
154   "floatformat_vax_f",
155   floatformat_always_valid,
156   NULL
157 };
158 const struct floatformat floatformat_vax_d =
159 {
160   floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
161   floatformat_intbit_no,
162   "floatformat_vax_d",
163   floatformat_always_valid,
164   NULL
165 };
166 const struct floatformat floatformat_vax_g =
167 {
168   floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
169   floatformat_intbit_no,
170   "floatformat_vax_g",
171   floatformat_always_valid,
172   NULL
173 };
174 
175 static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
176 					  const void *from);
177 
178 static int
floatformat_i387_ext_is_valid(const struct floatformat * fmt,const void * from)179 floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
180 {
181   /* In the i387 double-extended format, if the exponent is all ones,
182      then the integer bit must be set.  If the exponent is neither 0
183      nor ~0, the intbit must also be set.  Only if the exponent is
184      zero can it be zero, and then it must be zero.  */
185   unsigned long exponent, int_bit;
186   const unsigned char *ufrom = (const unsigned char *) from;
187 
188   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
189 			fmt->exp_start, fmt->exp_len);
190   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
191 		       fmt->man_start, 1);
192 
193   if ((exponent == 0) != (int_bit == 0))
194     return 0;
195   else
196     return 1;
197 }
198 
199 const struct floatformat floatformat_i387_ext =
200 {
201   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
202   floatformat_intbit_yes,
203   "floatformat_i387_ext",
204   floatformat_i387_ext_is_valid,
205   NULL
206 };
207 const struct floatformat floatformat_m68881_ext =
208 {
209   /* Note that the bits from 16 to 31 are unused.  */
210   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
211   floatformat_intbit_yes,
212   "floatformat_m68881_ext",
213   floatformat_always_valid,
214   NULL
215 };
216 const struct floatformat floatformat_i960_ext =
217 {
218   /* Note that the bits from 0 to 15 are unused.  */
219   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
220   floatformat_intbit_yes,
221   "floatformat_i960_ext",
222   floatformat_always_valid,
223   NULL
224 };
225 const struct floatformat floatformat_m88110_ext =
226 {
227   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
228   floatformat_intbit_yes,
229   "floatformat_m88110_ext",
230   floatformat_always_valid,
231   NULL
232 };
233 const struct floatformat floatformat_m88110_harris_ext =
234 {
235   /* Harris uses raw format 128 bytes long, but the number is just an ieee
236      double, and the last 64 bits are wasted. */
237   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
238   floatformat_intbit_no,
239   "floatformat_m88110_ext_harris",
240   floatformat_always_valid,
241   NULL
242 };
243 const struct floatformat floatformat_arm_ext_big =
244 {
245   /* Bits 1 to 16 are unused.  */
246   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
247   floatformat_intbit_yes,
248   "floatformat_arm_ext_big",
249   floatformat_always_valid,
250   NULL
251 };
252 const struct floatformat floatformat_arm_ext_littlebyte_bigword =
253 {
254   /* Bits 1 to 16 are unused.  */
255   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
256   floatformat_intbit_yes,
257   "floatformat_arm_ext_littlebyte_bigword",
258   floatformat_always_valid,
259   NULL
260 };
261 const struct floatformat floatformat_ia64_spill_big =
262 {
263   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
264   floatformat_intbit_yes,
265   "floatformat_ia64_spill_big",
266   floatformat_always_valid,
267   NULL
268 };
269 const struct floatformat floatformat_ia64_spill_little =
270 {
271   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
272   floatformat_intbit_yes,
273   "floatformat_ia64_spill_little",
274   floatformat_always_valid,
275   NULL
276 };
277 const struct floatformat floatformat_ia64_quad_big =
278 {
279   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
280   floatformat_intbit_no,
281   "floatformat_ia64_quad_big",
282   floatformat_always_valid,
283   NULL
284 };
285 const struct floatformat floatformat_ia64_quad_little =
286 {
287   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
288   floatformat_intbit_no,
289   "floatformat_ia64_quad_little",
290   floatformat_always_valid,
291   NULL
292 };
293 
294 static int
floatformat_ibm_long_double_is_valid(const struct floatformat * fmt,const void * from)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 
399 #ifndef min
400 #define min(a, b) ((a) < (b) ? (a) : (b))
401 #endif
402 
403 /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
404    format FMT, 0 otherwise.  */
405 static int
mant_bits_set(const struct floatformat * fmt,const unsigned char * ufrom)406 mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
407 {
408   unsigned int mant_bits, mant_off;
409   int mant_bits_left;
410 
411   mant_off = fmt->man_start;
412   mant_bits_left = fmt->man_len;
413   while (mant_bits_left > 0)
414     {
415       mant_bits = min (mant_bits_left, 32);
416 
417       if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
418 		     mant_off, mant_bits) != 0)
419 	return 1;
420 
421       mant_off += mant_bits;
422       mant_bits_left -= mant_bits;
423     }
424   return 0;
425 }
426 
427 /* Extract a field which starts at START and is LEN bits long.  DATA and
428    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
429 static unsigned long
get_field(const unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len)430 get_field (const unsigned char *data, enum floatformat_byteorders order,
431            unsigned int total_len, unsigned int start, unsigned int len)
432 {
433   unsigned long result = 0;
434   unsigned int cur_byte;
435   int lo_bit, hi_bit, cur_bitshift = 0;
436   int nextbyte = (order == floatformat_little) ? 1 : -1;
437 
438   /* Start is in big-endian bit order!  Fix that first.  */
439   start = total_len - (start + len);
440 
441   /* Start at the least significant part of the field.  */
442   if (order == floatformat_little)
443     cur_byte = start / FLOATFORMAT_CHAR_BIT;
444   else
445     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
446 
447   lo_bit = start % FLOATFORMAT_CHAR_BIT;
448   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
449 
450   do
451     {
452       unsigned int shifted = *(data + cur_byte) >> lo_bit;
453       unsigned int bits = hi_bit - lo_bit;
454       unsigned int mask = (1 << bits) - 1;
455       result |= (shifted & mask) << cur_bitshift;
456       len -= bits;
457       cur_bitshift += bits;
458       cur_byte += nextbyte;
459       lo_bit = 0;
460       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
461     }
462   while (len != 0);
463 
464   return result;
465 }
466 
467 /* Convert from FMT to a double.
468    FROM is the address of the extended float.
469    Store the double in *TO.  */
470 
471 void
floatformat_to_double(const struct floatformat * fmt,const void * from,double * to)472 floatformat_to_double (const struct floatformat *fmt,
473                        const void *from, double *to)
474 {
475   const unsigned char *ufrom = (const unsigned char *) from;
476   double dto;
477   long exponent;
478   unsigned long mant;
479   unsigned int mant_bits, mant_off;
480   int mant_bits_left;
481 
482   /* Split values are not handled specially, since the top half has
483      the correctly rounded double value (in the only supported case of
484      split values).  */
485 
486   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
487 			fmt->exp_start, fmt->exp_len);
488 
489   /* If the exponent indicates a NaN, we don't have information to
490      decide what to do.  So we handle it like IEEE, except that we
491      don't try to preserve the type of NaN.  FIXME.  */
492   if ((unsigned long) exponent == fmt->exp_nan)
493     {
494       int nan = mant_bits_set (fmt, ufrom);
495 
496       /* On certain systems (such as GNU/Linux), the use of the
497 	 INFINITY macro below may generate a warning that cannot be
498 	 silenced due to a bug in GCC (PR preprocessor/11931).  The
499 	 preprocessor fails to recognise the __extension__ keyword in
500 	 conjunction with the GNU/C99 extension for hexadecimal
501 	 floating point constants and will issue a warning when
502 	 compiling with -pedantic.  */
503       if (nan)
504 	dto = NAN;
505       else
506 #ifdef __vax__
507 	dto = HUGE_VAL;
508 #else
509 	dto = INFINITY;
510 #endif
511 
512       if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
513 	dto = -dto;
514 
515       *to = dto;
516 
517       return;
518     }
519 
520   mant_bits_left = fmt->man_len;
521   mant_off = fmt->man_start;
522   dto = 0.0;
523 
524   /* Build the result algebraically.  Might go infinite, underflow, etc;
525      who cares. */
526 
527   /* For denorms use minimum exponent.  */
528   if (exponent == 0)
529     exponent = 1 - fmt->exp_bias;
530   else
531     {
532       exponent -= fmt->exp_bias;
533 
534       /* If this format uses a hidden bit, explicitly add it in now.
535 	 Otherwise, increment the exponent by one to account for the
536 	 integer bit.  */
537 
538       if (fmt->intbit == floatformat_intbit_no)
539 	dto = ldexp (1.0, exponent);
540       else
541 	exponent++;
542     }
543 
544   while (mant_bits_left > 0)
545     {
546       mant_bits = min (mant_bits_left, 32);
547 
548       mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
549 			 mant_off, mant_bits);
550 
551       dto += ldexp ((double) mant, exponent - mant_bits);
552       exponent -= mant_bits;
553       mant_off += mant_bits;
554       mant_bits_left -= mant_bits;
555     }
556 
557   /* Negate it if negative.  */
558   if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
559     dto = -dto;
560   *to = dto;
561 }
562 
563 static void put_field (unsigned char *, enum floatformat_byteorders,
564                        unsigned int,
565                        unsigned int,
566                        unsigned int,
567                        unsigned long);
568 
569 /* Set a field which starts at START and is LEN bits long.  DATA and
570    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
571 static void
put_field(unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len,unsigned long stuff_to_put)572 put_field (unsigned char *data, enum floatformat_byteorders order,
573            unsigned int total_len, unsigned int start, unsigned int len,
574            unsigned long stuff_to_put)
575 {
576   unsigned int cur_byte;
577   int lo_bit, hi_bit;
578   int nextbyte = (order == floatformat_little) ? 1 : -1;
579 
580   /* Start is in big-endian bit order!  Fix that first.  */
581   start = total_len - (start + len);
582 
583   /* Start at the least significant part of the field.  */
584   if (order == floatformat_little)
585     cur_byte = start / FLOATFORMAT_CHAR_BIT;
586   else
587     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
588 
589   lo_bit = start % FLOATFORMAT_CHAR_BIT;
590   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
591 
592   do
593     {
594       unsigned char *byte_ptr = data + cur_byte;
595       unsigned int bits = hi_bit - lo_bit;
596       unsigned int mask = ((1 << bits) - 1) << lo_bit;
597       *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
598       stuff_to_put >>= bits;
599       len -= bits;
600       cur_byte += nextbyte;
601       lo_bit = 0;
602       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
603     }
604   while (len != 0);
605 }
606 
607 /* The converse: convert the double *FROM to an extended float
608    and store where TO points.  Neither FROM nor TO have any alignment
609    restrictions.  */
610 
611 void
floatformat_from_double(const struct floatformat * fmt,const double * from,void * to)612 floatformat_from_double (const struct floatformat *fmt,
613                          const double *from, void *to)
614 {
615   double dfrom;
616   int exponent;
617   double mant;
618   unsigned int mant_bits, mant_off;
619   int mant_bits_left;
620   unsigned char *uto = (unsigned char *) to;
621 
622   dfrom = *from;
623   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
624 
625   /* Split values are not handled specially, since a bottom half of
626      zero is correct for any value representable as double (in the
627      only supported case of split values).  */
628 
629   /* If negative, set the sign bit.  */
630   if (dfrom < 0)
631     {
632       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
633       dfrom = -dfrom;
634     }
635 
636   if (dfrom == 0)
637     {
638       /* 0.0.  */
639       return;
640     }
641 
642   if (dfrom != dfrom)
643     {
644       /* NaN.  */
645       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
646 		 fmt->exp_len, fmt->exp_nan);
647       /* Be sure it's not infinity, but NaN value is irrelevant.  */
648       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
649 		 32, 1);
650       return;
651     }
652 
653   if (dfrom + dfrom == dfrom)
654     {
655       /* This can only happen for an infinite value (or zero, which we
656 	 already handled above).  */
657       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
658 		 fmt->exp_len, fmt->exp_nan);
659       return;
660     }
661 
662   mant = frexp (dfrom, &exponent);
663   if (exponent + fmt->exp_bias - 1 > 0)
664     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
665 	       fmt->exp_len, exponent + fmt->exp_bias - 1);
666   else
667     {
668       /* Handle a denormalized number.  FIXME: What should we do for
669 	 non-IEEE formats?  */
670       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
671 		 fmt->exp_len, 0);
672       mant = ldexp (mant, exponent + fmt->exp_bias - 1);
673     }
674 
675   mant_bits_left = fmt->man_len;
676   mant_off = fmt->man_start;
677   while (mant_bits_left > 0)
678     {
679       unsigned long mant_long;
680       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
681 
682       mant *= 4294967296.0;
683       mant_long = (unsigned long)mant;
684       mant -= mant_long;
685 
686       /* If the integer bit is implicit, and we are not creating a
687 	 denormalized number, then we need to discard it.  */
688       if ((unsigned int) mant_bits_left == fmt->man_len
689 	  && fmt->intbit == floatformat_intbit_no
690 	  && exponent + fmt->exp_bias - 1 > 0)
691 	{
692 	  mant_long &= 0x7fffffff;
693 	  mant_bits -= 1;
694 	}
695       else if (mant_bits < 32)
696 	{
697 	  /* The bits we want are in the most significant MANT_BITS bits of
698 	     mant_long.  Move them to the least significant.  */
699 	  mant_long >>= 32 - mant_bits;
700 	}
701 
702       put_field (uto, fmt->byteorder, fmt->totalsize,
703 		 mant_off, mant_bits, mant_long);
704       mant_off += mant_bits;
705       mant_bits_left -= mant_bits;
706     }
707 }
708 
709 /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
710 
711 int
floatformat_is_valid(const struct floatformat * fmt,const void * from)712 floatformat_is_valid (const struct floatformat *fmt, const void *from)
713 {
714   return fmt->is_valid (fmt, from);
715 }
716 
717 
718 #ifdef IEEE_DEBUG
719 
720 #include <stdio.h>
721 
722 /* This is to be run on a host which uses IEEE floating point.  */
723 
724 void
ieee_test(double n)725 ieee_test (double n)
726 {
727   double result;
728 
729   floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
730   if ((n != result && (! isnan (n) || ! isnan (result)))
731       || (n < 0 && result >= 0)
732       || (n >= 0 && result < 0))
733     printf ("Differ(to): %.20g -> %.20g\n", n, result);
734 
735   floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
736   if ((n != result && (! isnan (n) || ! isnan (result)))
737       || (n < 0 && result >= 0)
738       || (n >= 0 && result < 0))
739     printf ("Differ(from): %.20g -> %.20g\n", n, result);
740 
741 #if 0
742   {
743     char exten[16];
744 
745     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
746     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
747     if (n != result)
748       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
749   }
750 #endif
751 
752 #if IEEE_DEBUG > 1
753   /* This is to be run on a host which uses 68881 format.  */
754   {
755     long double ex = *(long double *)exten;
756     if (ex != n)
757       printf ("Differ(from vs. extended): %.20g\n", n);
758   }
759 #endif
760 }
761 
762 int
main(void)763 main (void)
764 {
765   ieee_test (0.0);
766   ieee_test (0.5);
767   ieee_test (1.1);
768   ieee_test (256.0);
769   ieee_test (0.12345);
770   ieee_test (234235.78907234);
771   ieee_test (-512.0);
772   ieee_test (-0.004321);
773   ieee_test (1.2E-70);
774   ieee_test (1.2E-316);
775   ieee_test (4.9406564584124654E-324);
776   ieee_test (- 4.9406564584124654E-324);
777   ieee_test (- 0.0);
778   ieee_test (- INFINITY);
779   ieee_test (- NAN);
780   ieee_test (INFINITY);
781   ieee_test (NAN);
782   return 0;
783 }
784 #endif
785