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