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