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