OSDN Git Service

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