Merge from vendor branch BIND:
[dragonfly.git] / contrib / binutils-2.15 / libiberty / floatformat.c
1 /* IEEE floating point support routines, for GDB, the GNU Debugger.
2    Copyright (C) 1991, 1994, 1999, 2000, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* This is needed to pick up the NAN macro on some systems.  */
21 #define _GNU_SOURCE
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <math.h>
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32
33 #include "ansidecl.h"
34 #include "libiberty.h"
35 #include "floatformat.h"
36
37 #ifndef INFINITY
38 #ifdef HUGE_VAL
39 #define INFINITY HUGE_VAL
40 #else
41 #define INFINITY (1.0 / 0.0)
42 #endif
43 #endif
44
45 #ifndef NAN
46 #define NAN (0.0 / 0.0)
47 #endif
48
49 static unsigned long get_field PARAMS ((const unsigned char *,
50                                         enum floatformat_byteorders,
51                                         unsigned int,
52                                         unsigned int,
53                                         unsigned int));
54 static int floatformat_always_valid PARAMS ((const struct floatformat *fmt,
55                                              const char *from));
56
57 static int
58 floatformat_always_valid (fmt, from)
59      const struct floatformat *fmt ATTRIBUTE_UNUSED;
60      const char *from ATTRIBUTE_UNUSED;
61 {
62   return 1;
63 }
64
65 /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
66    going to bother with trying to muck around with whether it is defined in
67    a system header, what we do if not, etc.  */
68 #define FLOATFORMAT_CHAR_BIT 8
69
70 /* floatformats for IEEE single and double, big and little endian.  */
71 const struct floatformat floatformat_ieee_single_big =
72 {
73   floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
74   floatformat_intbit_no,
75   "floatformat_ieee_single_big",
76   floatformat_always_valid
77 };
78 const struct floatformat floatformat_ieee_single_little =
79 {
80   floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
81   floatformat_intbit_no,
82   "floatformat_ieee_single_little",
83   floatformat_always_valid
84 };
85 const struct floatformat floatformat_ieee_double_big =
86 {
87   floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
88   floatformat_intbit_no,
89   "floatformat_ieee_double_big",
90   floatformat_always_valid
91 };
92 const struct floatformat floatformat_ieee_double_little =
93 {
94   floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
95   floatformat_intbit_no,
96   "floatformat_ieee_double_little",
97   floatformat_always_valid
98 };
99
100 /* floatformat for IEEE double, little endian byte order, with big endian word
101    ordering, as on the ARM.  */
102
103 const struct floatformat floatformat_ieee_double_littlebyte_bigword =
104 {
105   floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
106   floatformat_intbit_no,
107   "floatformat_ieee_double_littlebyte_bigword",
108   floatformat_always_valid
109 };
110
111 static int floatformat_i387_ext_is_valid PARAMS ((const struct floatformat *fmt, const char *from));
112
113 static int
114 floatformat_i387_ext_is_valid (fmt, from)
115      const struct floatformat *fmt;
116      const char *from;
117 {
118   /* In the i387 double-extended format, if the exponent is all ones,
119      then the integer bit must be set.  If the exponent is neither 0
120      nor ~0, the intbit must also be set.  Only if the exponent is
121      zero can it be zero, and then it must be zero.  */
122   unsigned long exponent, int_bit;
123   const unsigned char *ufrom = (const unsigned char *) from;
124   
125   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
126                         fmt->exp_start, fmt->exp_len);
127   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
128                        fmt->man_start, 1);
129   
130   if ((exponent == 0) != (int_bit == 0))
131     return 0;
132   else
133     return 1;
134 }
135
136 const struct floatformat floatformat_i387_ext =
137 {
138   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
139   floatformat_intbit_yes,
140   "floatformat_i387_ext",
141   floatformat_i387_ext_is_valid
142 };
143 const struct floatformat floatformat_m68881_ext =
144 {
145   /* Note that the bits from 16 to 31 are unused.  */
146   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
147   floatformat_intbit_yes,
148   "floatformat_m68881_ext",
149   floatformat_always_valid
150 };
151 const struct floatformat floatformat_i960_ext =
152 {
153   /* Note that the bits from 0 to 15 are unused.  */
154   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
155   floatformat_intbit_yes,
156   "floatformat_i960_ext",
157   floatformat_always_valid
158 };
159 const struct floatformat floatformat_m88110_ext =
160 {
161   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
162   floatformat_intbit_yes,
163   "floatformat_m88110_ext",
164   floatformat_always_valid
165 };
166 const struct floatformat floatformat_m88110_harris_ext =
167 {
168   /* Harris uses raw format 128 bytes long, but the number is just an ieee
169      double, and the last 64 bits are wasted. */
170   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
171   floatformat_intbit_no,
172   "floatformat_m88110_ext_harris",
173   floatformat_always_valid
174 };
175 const struct floatformat floatformat_arm_ext_big =
176 {
177   /* Bits 1 to 16 are unused.  */
178   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
179   floatformat_intbit_yes,
180   "floatformat_arm_ext_big",
181   floatformat_always_valid
182 };
183 const struct floatformat floatformat_arm_ext_littlebyte_bigword =
184 {
185   /* Bits 1 to 16 are unused.  */
186   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
187   floatformat_intbit_yes,
188   "floatformat_arm_ext_littlebyte_bigword",
189   floatformat_always_valid
190 };
191 const struct floatformat floatformat_ia64_spill_big =
192 {
193   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
194   floatformat_intbit_yes,
195   "floatformat_ia64_spill_big",
196   floatformat_always_valid
197 };
198 const struct floatformat floatformat_ia64_spill_little =
199 {
200   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
201   floatformat_intbit_yes,
202   "floatformat_ia64_spill_little",
203   floatformat_always_valid
204 };
205 const struct floatformat floatformat_ia64_quad_big =
206 {
207   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
208   floatformat_intbit_no,
209   "floatformat_ia64_quad_big",
210   floatformat_always_valid
211 };
212 const struct floatformat floatformat_ia64_quad_little =
213 {
214   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
215   floatformat_intbit_no,
216   "floatformat_ia64_quad_little",
217   floatformat_always_valid
218 };
219 \f
220 /* Extract a field which starts at START and is LEN bits long.  DATA and
221    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
222 static unsigned long
223 get_field (data, order, total_len, start, len)
224      const unsigned char *data;
225      enum floatformat_byteorders order;
226      unsigned int total_len;
227      unsigned int start;
228      unsigned int len;
229 {
230   unsigned long result;
231   unsigned int cur_byte;
232   int cur_bitshift;
233
234   /* Start at the least significant part of the field.  */
235   cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
236   if (order == floatformat_little)
237     cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
238   cur_bitshift =
239     ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
240   result = *(data + cur_byte) >> (-cur_bitshift);
241   cur_bitshift += FLOATFORMAT_CHAR_BIT;
242   if (order == floatformat_little)
243     ++cur_byte;
244   else
245     --cur_byte;
246
247   /* Move towards the most significant part of the field.  */
248   while ((unsigned int) cur_bitshift < len)
249     {
250       if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
251         /* This is the last byte; zero out the bits which are not part of
252            this field.  */
253         result |=
254           (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
255             << cur_bitshift;
256       else
257         result |= *(data + cur_byte) << cur_bitshift;
258       cur_bitshift += FLOATFORMAT_CHAR_BIT;
259       if (order == floatformat_little)
260         ++cur_byte;
261       else
262         --cur_byte;
263     }
264   return result;
265 }
266   
267 #ifndef min
268 #define min(a, b) ((a) < (b) ? (a) : (b))
269 #endif
270
271 /* Convert from FMT to a double.
272    FROM is the address of the extended float.
273    Store the double in *TO.  */
274
275 void
276 floatformat_to_double (fmt, from, to)
277      const struct floatformat *fmt;
278      const char *from;
279      double *to;
280 {
281   const unsigned char *ufrom = (const unsigned char *)from;
282   double dto;
283   long exponent;
284   unsigned long mant;
285   unsigned int mant_bits, mant_off;
286   int mant_bits_left;
287   int special_exponent;         /* It's a NaN, denorm or zero */
288
289   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
290                         fmt->exp_start, fmt->exp_len);
291
292   /* If the exponent indicates a NaN, we don't have information to
293      decide what to do.  So we handle it like IEEE, except that we
294      don't try to preserve the type of NaN.  FIXME.  */
295   if ((unsigned long) exponent == fmt->exp_nan)
296     {
297       int nan;
298
299       mant_off = fmt->man_start;
300       mant_bits_left = fmt->man_len;
301       nan = 0;
302       while (mant_bits_left > 0)
303         {
304           mant_bits = min (mant_bits_left, 32);
305
306           if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
307                          mant_off, mant_bits) != 0)
308             {
309               /* This is a NaN.  */
310               nan = 1;
311               break;
312             }
313
314           mant_off += mant_bits;
315           mant_bits_left -= mant_bits;
316         }
317
318       if (nan)
319         dto = NAN;
320       else
321         dto = INFINITY;
322
323       if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
324         dto = -dto;
325
326       *to = dto;
327
328       return;
329     }
330
331   mant_bits_left = fmt->man_len;
332   mant_off = fmt->man_start;
333   dto = 0.0;
334
335   special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
336
337   /* Don't bias zero's, denorms or NaNs.  */
338   if (!special_exponent)
339     exponent -= fmt->exp_bias;
340
341   /* Build the result algebraically.  Might go infinite, underflow, etc;
342      who cares. */
343
344   /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
345      increment the exponent by one to account for the integer bit.  */
346
347   if (!special_exponent)
348     {
349       if (fmt->intbit == floatformat_intbit_no)
350         dto = ldexp (1.0, exponent);
351       else
352         exponent++;
353     }
354
355   while (mant_bits_left > 0)
356     {
357       mant_bits = min (mant_bits_left, 32);
358
359       mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
360                          mant_off, mant_bits);
361
362       /* Handle denormalized numbers.  FIXME: What should we do for
363          non-IEEE formats?  */
364       if (exponent == 0 && mant != 0)
365         dto += ldexp ((double)mant,
366                       (- fmt->exp_bias
367                        - mant_bits
368                        - (mant_off - fmt->man_start)
369                        + 1));
370       else
371         dto += ldexp ((double)mant, exponent - mant_bits);
372       if (exponent != 0)
373         exponent -= mant_bits;
374       mant_off += mant_bits;
375       mant_bits_left -= mant_bits;
376     }
377
378   /* Negate it if negative.  */
379   if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
380     dto = -dto;
381   *to = dto;
382 }
383 \f
384 static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
385                                unsigned int,
386                                unsigned int,
387                                unsigned int,
388                                unsigned long));
389
390 /* Set a field which starts at START and is LEN bits long.  DATA and
391    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
392 static void
393 put_field (data, order, total_len, start, len, stuff_to_put)
394      unsigned char *data;
395      enum floatformat_byteorders order;
396      unsigned int total_len;
397      unsigned int start;
398      unsigned int len;
399      unsigned long stuff_to_put;
400 {
401   unsigned int cur_byte;
402   int cur_bitshift;
403
404   /* Start at the least significant part of the field.  */
405   cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
406   if (order == floatformat_little)
407     cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
408   cur_bitshift =
409     ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
410   *(data + cur_byte) &=
411     ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
412   *(data + cur_byte) |=
413     (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
414   cur_bitshift += FLOATFORMAT_CHAR_BIT;
415   if (order == floatformat_little)
416     ++cur_byte;
417   else
418     --cur_byte;
419
420   /* Move towards the most significant part of the field.  */
421   while ((unsigned int) cur_bitshift < len)
422     {
423       if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
424         {
425           /* This is the last byte.  */
426           *(data + cur_byte) &=
427             ~((1 << (len - cur_bitshift)) - 1);
428           *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
429         }
430       else
431         *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
432                               & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
433       cur_bitshift += FLOATFORMAT_CHAR_BIT;
434       if (order == floatformat_little)
435         ++cur_byte;
436       else
437         --cur_byte;
438     }
439 }
440
441 /* The converse: convert the double *FROM to an extended float
442    and store where TO points.  Neither FROM nor TO have any alignment
443    restrictions.  */
444
445 void
446 floatformat_from_double (fmt, from, to)
447      const struct floatformat *fmt;
448      const double *from;
449      char *to;
450 {
451   double dfrom;
452   int exponent;
453   double mant;
454   unsigned int mant_bits, mant_off;
455   int mant_bits_left;
456   unsigned char *uto = (unsigned char *)to;
457
458   dfrom = *from;
459   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
460
461   /* If negative, set the sign bit.  */
462   if (dfrom < 0)
463     {
464       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
465       dfrom = -dfrom;
466     }
467
468   if (dfrom == 0)
469     {
470       /* 0.0.  */
471       return;
472     }
473
474   if (dfrom != dfrom)
475     {
476       /* NaN.  */
477       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
478                  fmt->exp_len, fmt->exp_nan);
479       /* Be sure it's not infinity, but NaN value is irrelevant.  */
480       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
481                  32, 1);
482       return;
483     }
484
485   if (dfrom + dfrom == dfrom)
486     {
487       /* This can only happen for an infinite value (or zero, which we
488          already handled above).  */
489       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
490                  fmt->exp_len, fmt->exp_nan);
491       return;
492     }
493
494   mant = frexp (dfrom, &exponent);
495   if (exponent + fmt->exp_bias - 1 > 0)
496     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
497                fmt->exp_len, exponent + fmt->exp_bias - 1);
498   else
499     {
500       /* Handle a denormalized number.  FIXME: What should we do for
501          non-IEEE formats?  */
502       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
503                  fmt->exp_len, 0);
504       mant = ldexp (mant, exponent + fmt->exp_bias - 1);
505     }
506
507   mant_bits_left = fmt->man_len;
508   mant_off = fmt->man_start;
509   while (mant_bits_left > 0)
510     {
511       unsigned long mant_long;
512       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
513
514       mant *= 4294967296.0;
515       mant_long = (unsigned long)mant;
516       mant -= mant_long;
517
518       /* If the integer bit is implicit, and we are not creating a
519          denormalized number, then we need to discard it.  */
520       if ((unsigned int) mant_bits_left == fmt->man_len
521           && fmt->intbit == floatformat_intbit_no
522           && exponent + fmt->exp_bias - 1 > 0)
523         {
524           mant_long &= 0x7fffffff;
525           mant_bits -= 1;
526         }
527       else if (mant_bits < 32)
528         {
529           /* The bits we want are in the most significant MANT_BITS bits of
530              mant_long.  Move them to the least significant.  */
531           mant_long >>= 32 - mant_bits;
532         }
533
534       put_field (uto, fmt->byteorder, fmt->totalsize,
535                  mant_off, mant_bits, mant_long);
536       mant_off += mant_bits;
537       mant_bits_left -= mant_bits;
538     }
539 }
540
541 /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
542
543 int
544 floatformat_is_valid (fmt, from)
545      const struct floatformat *fmt;
546      const char *from;
547 {
548   return fmt->is_valid (fmt, from);
549 }
550
551
552 #ifdef IEEE_DEBUG
553
554 #include <stdio.h>
555
556 /* This is to be run on a host which uses IEEE floating point.  */
557
558 void
559 ieee_test (n)
560      double n;
561 {
562   double result;
563
564   floatformat_to_double (&floatformat_ieee_double_little, (char *) &n,
565                          &result);
566   if ((n != result && (! isnan (n) || ! isnan (result)))
567       || (n < 0 && result >= 0)
568       || (n >= 0 && result < 0))
569     printf ("Differ(to): %.20g -> %.20g\n", n, result);
570
571   floatformat_from_double (&floatformat_ieee_double_little, &n,
572                            (char *) &result);
573   if ((n != result && (! isnan (n) || ! isnan (result)))
574       || (n < 0 && result >= 0)
575       || (n >= 0 && result < 0))
576     printf ("Differ(from): %.20g -> %.20g\n", n, result);
577
578 #if 0
579   {
580     char exten[16];
581
582     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
583     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
584     if (n != result)
585       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
586   }
587 #endif
588
589 #if IEEE_DEBUG > 1
590   /* This is to be run on a host which uses 68881 format.  */
591   {
592     long double ex = *(long double *)exten;
593     if (ex != n)
594       printf ("Differ(from vs. extended): %.20g\n", n);
595   }
596 #endif
597 }
598
599 int
600 main ()
601 {
602   ieee_test (0.0);
603   ieee_test (0.5);
604   ieee_test (256.0);
605   ieee_test (0.12345);
606   ieee_test (234235.78907234);
607   ieee_test (-512.0);
608   ieee_test (-0.004321);
609   ieee_test (1.2E-70);
610   ieee_test (1.2E-316);
611   ieee_test (4.9406564584124654E-324);
612   ieee_test (- 4.9406564584124654E-324);
613   ieee_test (- 0.0);
614   ieee_test (- INFINITY);
615   ieee_test (- NAN);
616   ieee_test (INFINITY);
617   ieee_test (NAN);
618   return 0;
619 }
620 #endif