OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libiberty / floatformat.c
1 /* IEEE floating point support routines, for GDB, the GNU Debugger.
2    Copyright 1991, 1994, 1999, 2000, 2003, 2005
3    Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21 /* This is needed to pick up the NAN macro on some systems.  */
22 #define _GNU_SOURCE
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <math.h>
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33
34 #include "ansidecl.h"
35 #include "libiberty.h"
36 #include "floatformat.h"
37
38 #ifndef INFINITY
39 #ifdef HUGE_VAL
40 #define INFINITY HUGE_VAL
41 #else
42 #define INFINITY (1.0 / 0.0)
43 #endif
44 #endif
45
46 #ifndef NAN
47 #define NAN (0.0 / 0.0)
48 #endif
49
50 static unsigned long get_field (const unsigned char *,
51                                 enum floatformat_byteorders,
52                                 unsigned int,
53                                 unsigned int,
54                                 unsigned int);
55 static int floatformat_always_valid (const struct floatformat *fmt,
56                                      const void *from);
57
58 static int
59 floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
60                           const void *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 (const struct floatformat *fmt,
112                                           const void *from);
113
114 static int
115 floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
116 {
117   /* In the i387 double-extended format, if the exponent is all ones,
118      then the integer bit must be set.  If the exponent is neither 0
119      nor ~0, the intbit must also be set.  Only if the exponent is
120      zero can it be zero, and then it must be zero.  */
121   unsigned long exponent, int_bit;
122   const unsigned char *ufrom = from;
123
124   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
125                         fmt->exp_start, fmt->exp_len);
126   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
127                        fmt->man_start, 1);
128
129   if ((exponent == 0) != (int_bit == 0))
130     return 0;
131   else
132     return 1;
133 }
134
135 const struct floatformat floatformat_i387_ext =
136 {
137   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
138   floatformat_intbit_yes,
139   "floatformat_i387_ext",
140   floatformat_i387_ext_is_valid
141 };
142 const struct floatformat floatformat_m68881_ext =
143 {
144   /* Note that the bits from 16 to 31 are unused.  */
145   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
146   floatformat_intbit_yes,
147   "floatformat_m68881_ext",
148   floatformat_always_valid
149 };
150 const struct floatformat floatformat_i960_ext =
151 {
152   /* Note that the bits from 0 to 15 are unused.  */
153   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
154   floatformat_intbit_yes,
155   "floatformat_i960_ext",
156   floatformat_always_valid
157 };
158 const struct floatformat floatformat_m88110_ext =
159 {
160   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
161   floatformat_intbit_yes,
162   "floatformat_m88110_ext",
163   floatformat_always_valid
164 };
165 const struct floatformat floatformat_m88110_harris_ext =
166 {
167   /* Harris uses raw format 128 bytes long, but the number is just an ieee
168      double, and the last 64 bits are wasted. */
169   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
170   floatformat_intbit_no,
171   "floatformat_m88110_ext_harris",
172   floatformat_always_valid
173 };
174 const struct floatformat floatformat_arm_ext_big =
175 {
176   /* Bits 1 to 16 are unused.  */
177   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
178   floatformat_intbit_yes,
179   "floatformat_arm_ext_big",
180   floatformat_always_valid
181 };
182 const struct floatformat floatformat_arm_ext_littlebyte_bigword =
183 {
184   /* Bits 1 to 16 are unused.  */
185   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
186   floatformat_intbit_yes,
187   "floatformat_arm_ext_littlebyte_bigword",
188   floatformat_always_valid
189 };
190 const struct floatformat floatformat_ia64_spill_big =
191 {
192   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
193   floatformat_intbit_yes,
194   "floatformat_ia64_spill_big",
195   floatformat_always_valid
196 };
197 const struct floatformat floatformat_ia64_spill_little =
198 {
199   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
200   floatformat_intbit_yes,
201   "floatformat_ia64_spill_little",
202   floatformat_always_valid
203 };
204 const struct floatformat floatformat_ia64_quad_big =
205 {
206   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
207   floatformat_intbit_no,
208   "floatformat_ia64_quad_big",
209   floatformat_always_valid
210 };
211 const struct floatformat floatformat_ia64_quad_little =
212 {
213   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
214   floatformat_intbit_no,
215   "floatformat_ia64_quad_little",
216   floatformat_always_valid
217 };
218 \f
219 /* Extract a field which starts at START and is LEN bits long.  DATA and
220    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
221 static unsigned long
222 get_field (const unsigned char *data, enum floatformat_byteorders order,
223            unsigned int total_len, unsigned int start, unsigned int len)
224 {
225   unsigned long result;
226   unsigned int cur_byte;
227   int cur_bitshift;
228
229   /* Start at the least significant part of the field.  */
230   cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
231   if (order == floatformat_little)
232     cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
233   cur_bitshift =
234     ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
235   result = *(data + cur_byte) >> (-cur_bitshift);
236   cur_bitshift += FLOATFORMAT_CHAR_BIT;
237   if (order == floatformat_little)
238     ++cur_byte;
239   else
240     --cur_byte;
241
242   /* Move towards the most significant part of the field.  */
243   while ((unsigned int) cur_bitshift < len)
244     {
245       if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
246         /* This is the last byte; zero out the bits which are not part of
247            this field.  */
248         result |=
249           (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
250             << cur_bitshift;
251       else
252         result |= *(data + cur_byte) << cur_bitshift;
253       cur_bitshift += FLOATFORMAT_CHAR_BIT;
254       if (order == floatformat_little)
255         ++cur_byte;
256       else
257         --cur_byte;
258     }
259   return result;
260 }
261   
262 #ifndef min
263 #define min(a, b) ((a) < (b) ? (a) : (b))
264 #endif
265
266 /* Convert from FMT to a double.
267    FROM is the address of the extended float.
268    Store the double in *TO.  */
269
270 void
271 floatformat_to_double (const struct floatformat *fmt,
272                        const void *from, double *to)
273 {
274   const unsigned char *ufrom = from;
275   double dto;
276   long exponent;
277   unsigned long mant;
278   unsigned int mant_bits, mant_off;
279   int mant_bits_left;
280   int special_exponent;         /* It's a NaN, denorm or zero */
281
282   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
283                         fmt->exp_start, fmt->exp_len);
284
285   /* If the exponent indicates a NaN, we don't have information to
286      decide what to do.  So we handle it like IEEE, except that we
287      don't try to preserve the type of NaN.  FIXME.  */
288   if ((unsigned long) exponent == fmt->exp_nan)
289     {
290       int nan;
291
292       mant_off = fmt->man_start;
293       mant_bits_left = fmt->man_len;
294       nan = 0;
295       while (mant_bits_left > 0)
296         {
297           mant_bits = min (mant_bits_left, 32);
298
299           if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
300                          mant_off, mant_bits) != 0)
301             {
302               /* This is a NaN.  */
303               nan = 1;
304               break;
305             }
306
307           mant_off += mant_bits;
308           mant_bits_left -= mant_bits;
309         }
310
311       /* On certain systems (such as GNU/Linux), the use of the
312          INFINITY macro below may generate a warning that can not be
313          silenced due to a bug in GCC (PR preprocessor/11931).  The
314          preprocessor fails to recognise the __extension__ keyword in
315          conjunction with the GNU/C99 extension for hexadecimal
316          floating point constants and will issue a warning when
317          compiling with -pedantic.  */
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 (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 (unsigned char *data, enum floatformat_byteorders order,
394            unsigned int total_len, unsigned int start, unsigned int len,
395            unsigned long stuff_to_put)
396 {
397   unsigned int cur_byte;
398   int cur_bitshift;
399
400   /* Start at the least significant part of the field.  */
401   cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
402   if (order == floatformat_little)
403     cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
404   cur_bitshift =
405     ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
406   *(data + cur_byte) &=
407     ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
408   *(data + cur_byte) |=
409     (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
410   cur_bitshift += FLOATFORMAT_CHAR_BIT;
411   if (order == floatformat_little)
412     ++cur_byte;
413   else
414     --cur_byte;
415
416   /* Move towards the most significant part of the field.  */
417   while ((unsigned int) cur_bitshift < len)
418     {
419       if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
420         {
421           /* This is the last byte.  */
422           *(data + cur_byte) &=
423             ~((1 << (len - cur_bitshift)) - 1);
424           *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
425         }
426       else
427         *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
428                               & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
429       cur_bitshift += FLOATFORMAT_CHAR_BIT;
430       if (order == floatformat_little)
431         ++cur_byte;
432       else
433         --cur_byte;
434     }
435 }
436
437 /* The converse: convert the double *FROM to an extended float
438    and store where TO points.  Neither FROM nor TO have any alignment
439    restrictions.  */
440
441 void
442 floatformat_from_double (const struct floatformat *fmt,
443                          const double *from, void *to)
444 {
445   double dfrom;
446   int exponent;
447   double mant;
448   unsigned int mant_bits, mant_off;
449   int mant_bits_left;
450   unsigned char *uto = to;
451
452   dfrom = *from;
453   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
454
455   /* If negative, set the sign bit.  */
456   if (dfrom < 0)
457     {
458       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
459       dfrom = -dfrom;
460     }
461
462   if (dfrom == 0)
463     {
464       /* 0.0.  */
465       return;
466     }
467
468   if (dfrom != dfrom)
469     {
470       /* NaN.  */
471       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
472                  fmt->exp_len, fmt->exp_nan);
473       /* Be sure it's not infinity, but NaN value is irrelevant.  */
474       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
475                  32, 1);
476       return;
477     }
478
479   if (dfrom + dfrom == dfrom)
480     {
481       /* This can only happen for an infinite value (or zero, which we
482          already handled above).  */
483       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
484                  fmt->exp_len, fmt->exp_nan);
485       return;
486     }
487
488   mant = frexp (dfrom, &exponent);
489   if (exponent + fmt->exp_bias - 1 > 0)
490     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
491                fmt->exp_len, exponent + fmt->exp_bias - 1);
492   else
493     {
494       /* Handle a denormalized number.  FIXME: What should we do for
495          non-IEEE formats?  */
496       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
497                  fmt->exp_len, 0);
498       mant = ldexp (mant, exponent + fmt->exp_bias - 1);
499     }
500
501   mant_bits_left = fmt->man_len;
502   mant_off = fmt->man_start;
503   while (mant_bits_left > 0)
504     {
505       unsigned long mant_long;
506       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
507
508       mant *= 4294967296.0;
509       mant_long = (unsigned long)mant;
510       mant -= mant_long;
511
512       /* If the integer bit is implicit, and we are not creating a
513          denormalized number, then we need to discard it.  */
514       if ((unsigned int) mant_bits_left == fmt->man_len
515           && fmt->intbit == floatformat_intbit_no
516           && exponent + fmt->exp_bias - 1 > 0)
517         {
518           mant_long &= 0x7fffffff;
519           mant_bits -= 1;
520         }
521       else if (mant_bits < 32)
522         {
523           /* The bits we want are in the most significant MANT_BITS bits of
524              mant_long.  Move them to the least significant.  */
525           mant_long >>= 32 - mant_bits;
526         }
527
528       put_field (uto, fmt->byteorder, fmt->totalsize,
529                  mant_off, mant_bits, mant_long);
530       mant_off += mant_bits;
531       mant_bits_left -= mant_bits;
532     }
533 }
534
535 /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
536
537 int
538 floatformat_is_valid (const struct floatformat *fmt, const void *from)
539 {
540   return fmt->is_valid (fmt, from);
541 }
542
543
544 #ifdef IEEE_DEBUG
545
546 #include <stdio.h>
547
548 /* This is to be run on a host which uses IEEE floating point.  */
549
550 void
551 ieee_test (double n)
552 {
553   double result;
554
555   floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
556   if ((n != result && (! isnan (n) || ! isnan (result)))
557       || (n < 0 && result >= 0)
558       || (n >= 0 && result < 0))
559     printf ("Differ(to): %.20g -> %.20g\n", n, result);
560
561   floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
562   if ((n != result && (! isnan (n) || ! isnan (result)))
563       || (n < 0 && result >= 0)
564       || (n >= 0 && result < 0))
565     printf ("Differ(from): %.20g -> %.20g\n", n, result);
566
567 #if 0
568   {
569     char exten[16];
570
571     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
572     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
573     if (n != result)
574       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
575   }
576 #endif
577
578 #if IEEE_DEBUG > 1
579   /* This is to be run on a host which uses 68881 format.  */
580   {
581     long double ex = *(long double *)exten;
582     if (ex != n)
583       printf ("Differ(from vs. extended): %.20g\n", n);
584   }
585 #endif
586 }
587
588 int
589 main (void)
590 {
591   ieee_test (0.0);
592   ieee_test (0.5);
593   ieee_test (256.0);
594   ieee_test (0.12345);
595   ieee_test (234235.78907234);
596   ieee_test (-512.0);
597   ieee_test (-0.004321);
598   ieee_test (1.2E-70);
599   ieee_test (1.2E-316);
600   ieee_test (4.9406564584124654E-324);
601   ieee_test (- 4.9406564584124654E-324);
602   ieee_test (- 0.0);
603   ieee_test (- INFINITY);
604   ieee_test (- NAN);
605   ieee_test (INFINITY);
606   ieee_test (NAN);
607   return 0;
608 }
609 #endif