Home | History | Annotate | Line # | Download | only in libiberty
floatformat.c revision 1.11
      1   1.1     skrll /* IEEE floating point support routines, for GDB, the GNU Debugger.
      2  1.11  christos    Copyright (C) 1991-2026 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.8  christos /* floatformats for IEEE half, single, double and quad, 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.8  christos const struct floatformat floatformat_ieee_quad_big =
    131   1.8  christos {
    132   1.8  christos   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
    133   1.8  christos   floatformat_intbit_no,
    134   1.8  christos   "floatformat_ieee_quad_big",
    135   1.8  christos   floatformat_always_valid,
    136   1.8  christos   NULL
    137   1.8  christos };
    138   1.8  christos const struct floatformat floatformat_ieee_quad_little =
    139   1.8  christos {
    140   1.8  christos   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
    141   1.8  christos   floatformat_intbit_no,
    142   1.8  christos   "floatformat_ieee_quad_little",
    143   1.8  christos   floatformat_always_valid,
    144   1.8  christos   NULL
    145   1.8  christos };
    146   1.1     skrll 
    147   1.1     skrll /* floatformat for IEEE double, little endian byte order, with big endian word
    148   1.1     skrll    ordering, as on the ARM.  */
    149   1.1     skrll 
    150   1.1     skrll const struct floatformat floatformat_ieee_double_littlebyte_bigword =
    151   1.1     skrll {
    152   1.1     skrll   floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
    153   1.1     skrll   floatformat_intbit_no,
    154   1.1     skrll   "floatformat_ieee_double_littlebyte_bigword",
    155   1.1     skrll   floatformat_always_valid,
    156   1.1     skrll   NULL
    157   1.1     skrll };
    158   1.1     skrll 
    159   1.1     skrll /* floatformat for VAX.  Not quite IEEE, but close enough.  */
    160   1.1     skrll 
    161   1.1     skrll const struct floatformat floatformat_vax_f =
    162   1.1     skrll {
    163   1.1     skrll   floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
    164   1.1     skrll   floatformat_intbit_no,
    165   1.1     skrll   "floatformat_vax_f",
    166   1.1     skrll   floatformat_always_valid,
    167   1.1     skrll   NULL
    168   1.1     skrll };
    169   1.1     skrll const struct floatformat floatformat_vax_d =
    170   1.1     skrll {
    171   1.1     skrll   floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
    172   1.1     skrll   floatformat_intbit_no,
    173   1.1     skrll   "floatformat_vax_d",
    174   1.1     skrll   floatformat_always_valid,
    175   1.1     skrll   NULL
    176   1.1     skrll };
    177   1.1     skrll const struct floatformat floatformat_vax_g =
    178   1.1     skrll {
    179   1.1     skrll   floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
    180   1.1     skrll   floatformat_intbit_no,
    181   1.1     skrll   "floatformat_vax_g",
    182   1.1     skrll   floatformat_always_valid,
    183   1.1     skrll   NULL
    184   1.1     skrll };
    185   1.1     skrll 
    186   1.1     skrll static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
    187   1.1     skrll 					  const void *from);
    188   1.1     skrll 
    189   1.1     skrll static int
    190   1.1     skrll floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
    191   1.1     skrll {
    192   1.1     skrll   /* In the i387 double-extended format, if the exponent is all ones,
    193   1.1     skrll      then the integer bit must be set.  If the exponent is neither 0
    194   1.1     skrll      nor ~0, the intbit must also be set.  Only if the exponent is
    195   1.1     skrll      zero can it be zero, and then it must be zero.  */
    196   1.1     skrll   unsigned long exponent, int_bit;
    197   1.1     skrll   const unsigned char *ufrom = (const unsigned char *) from;
    198   1.1     skrll 
    199   1.1     skrll   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    200   1.1     skrll 			fmt->exp_start, fmt->exp_len);
    201   1.1     skrll   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    202   1.1     skrll 		       fmt->man_start, 1);
    203   1.1     skrll 
    204   1.1     skrll   if ((exponent == 0) != (int_bit == 0))
    205   1.1     skrll     return 0;
    206   1.1     skrll   else
    207   1.1     skrll     return 1;
    208   1.1     skrll }
    209   1.1     skrll 
    210   1.1     skrll const struct floatformat floatformat_i387_ext =
    211   1.1     skrll {
    212   1.1     skrll   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
    213   1.1     skrll   floatformat_intbit_yes,
    214   1.1     skrll   "floatformat_i387_ext",
    215   1.1     skrll   floatformat_i387_ext_is_valid,
    216   1.1     skrll   NULL
    217   1.1     skrll };
    218   1.1     skrll const struct floatformat floatformat_m68881_ext =
    219   1.1     skrll {
    220   1.1     skrll   /* Note that the bits from 16 to 31 are unused.  */
    221   1.1     skrll   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
    222   1.1     skrll   floatformat_intbit_yes,
    223   1.1     skrll   "floatformat_m68881_ext",
    224   1.1     skrll   floatformat_always_valid,
    225   1.1     skrll   NULL
    226   1.1     skrll };
    227   1.1     skrll const struct floatformat floatformat_i960_ext =
    228   1.1     skrll {
    229   1.1     skrll   /* Note that the bits from 0 to 15 are unused.  */
    230   1.1     skrll   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
    231   1.1     skrll   floatformat_intbit_yes,
    232   1.1     skrll   "floatformat_i960_ext",
    233   1.1     skrll   floatformat_always_valid,
    234   1.1     skrll   NULL
    235   1.1     skrll };
    236   1.1     skrll const struct floatformat floatformat_m88110_ext =
    237   1.1     skrll {
    238   1.1     skrll   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
    239   1.1     skrll   floatformat_intbit_yes,
    240   1.1     skrll   "floatformat_m88110_ext",
    241   1.1     skrll   floatformat_always_valid,
    242   1.1     skrll   NULL
    243   1.1     skrll };
    244   1.1     skrll const struct floatformat floatformat_m88110_harris_ext =
    245   1.1     skrll {
    246   1.1     skrll   /* Harris uses raw format 128 bytes long, but the number is just an ieee
    247   1.1     skrll      double, and the last 64 bits are wasted. */
    248   1.1     skrll   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
    249   1.1     skrll   floatformat_intbit_no,
    250   1.1     skrll   "floatformat_m88110_ext_harris",
    251   1.1     skrll   floatformat_always_valid,
    252   1.1     skrll   NULL
    253   1.1     skrll };
    254   1.1     skrll const struct floatformat floatformat_arm_ext_big =
    255   1.1     skrll {
    256   1.1     skrll   /* Bits 1 to 16 are unused.  */
    257   1.1     skrll   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
    258   1.1     skrll   floatformat_intbit_yes,
    259   1.1     skrll   "floatformat_arm_ext_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_arm_ext_littlebyte_bigword =
    264   1.1     skrll {
    265   1.1     skrll   /* Bits 1 to 16 are unused.  */
    266   1.1     skrll   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
    267   1.1     skrll   floatformat_intbit_yes,
    268   1.1     skrll   "floatformat_arm_ext_littlebyte_bigword",
    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_spill_big =
    273   1.1     skrll {
    274   1.1     skrll   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
    275   1.1     skrll   floatformat_intbit_yes,
    276   1.1     skrll   "floatformat_ia64_spill_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_spill_little =
    281   1.1     skrll {
    282   1.1     skrll   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
    283   1.1     skrll   floatformat_intbit_yes,
    284   1.1     skrll   "floatformat_ia64_spill_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.8  christos 
    393   1.8  christos const struct floatformat floatformat_bfloat16_big =
    394   1.8  christos {
    395   1.8  christos   floatformat_big, 16, 0, 1, 8, 127, 255, 9, 7,
    396   1.8  christos   floatformat_intbit_no,
    397   1.8  christos   "floatformat_bfloat16_big",
    398   1.8  christos   floatformat_always_valid,
    399   1.8  christos   NULL
    400   1.8  christos };
    401   1.8  christos 
    402   1.8  christos const struct floatformat floatformat_bfloat16_little =
    403   1.8  christos {
    404   1.8  christos   floatformat_little, 16, 0, 1, 8, 127, 255, 9, 7,
    405   1.8  christos   floatformat_intbit_no,
    406   1.8  christos   "floatformat_bfloat16_little",
    407   1.8  christos   floatformat_always_valid,
    408   1.8  christos   NULL
    409   1.8  christos };
    410   1.1     skrll 
    411   1.1     skrll #ifndef min
    412   1.1     skrll #define min(a, b) ((a) < (b) ? (a) : (b))
    413   1.1     skrll #endif
    414   1.1     skrll 
    415   1.1     skrll /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
    416   1.1     skrll    format FMT, 0 otherwise.  */
    417   1.1     skrll static int
    418   1.1     skrll mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
    419   1.1     skrll {
    420   1.1     skrll   unsigned int mant_bits, mant_off;
    421   1.1     skrll   int mant_bits_left;
    422   1.1     skrll 
    423   1.1     skrll   mant_off = fmt->man_start;
    424   1.1     skrll   mant_bits_left = fmt->man_len;
    425   1.1     skrll   while (mant_bits_left > 0)
    426   1.1     skrll     {
    427   1.1     skrll       mant_bits = min (mant_bits_left, 32);
    428   1.1     skrll 
    429   1.1     skrll       if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
    430   1.1     skrll 		     mant_off, mant_bits) != 0)
    431   1.1     skrll 	return 1;
    432   1.1     skrll 
    433   1.1     skrll       mant_off += mant_bits;
    434   1.1     skrll       mant_bits_left -= mant_bits;
    435   1.1     skrll     }
    436   1.1     skrll   return 0;
    437   1.1     skrll }
    438   1.1     skrll 
    439   1.1     skrll /* Extract a field which starts at START and is LEN bits long.  DATA and
    440   1.1     skrll    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
    441   1.1     skrll static unsigned long
    442   1.1     skrll get_field (const unsigned char *data, enum floatformat_byteorders order,
    443   1.1     skrll            unsigned int total_len, unsigned int start, unsigned int len)
    444   1.1     skrll {
    445   1.1     skrll   unsigned long result = 0;
    446   1.1     skrll   unsigned int cur_byte;
    447   1.1     skrll   int lo_bit, hi_bit, cur_bitshift = 0;
    448   1.1     skrll   int nextbyte = (order == floatformat_little) ? 1 : -1;
    449   1.1     skrll 
    450   1.1     skrll   /* Start is in big-endian bit order!  Fix that first.  */
    451   1.1     skrll   start = total_len - (start + len);
    452   1.1     skrll 
    453   1.1     skrll   /* Start at the least significant part of the field.  */
    454   1.1     skrll   if (order == floatformat_little)
    455   1.1     skrll     cur_byte = start / FLOATFORMAT_CHAR_BIT;
    456   1.1     skrll   else
    457   1.1     skrll     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
    458   1.1     skrll 
    459   1.1     skrll   lo_bit = start % FLOATFORMAT_CHAR_BIT;
    460   1.1     skrll   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
    461   1.1     skrll 
    462   1.1     skrll   do
    463   1.1     skrll     {
    464   1.1     skrll       unsigned int shifted = *(data + cur_byte) >> lo_bit;
    465   1.1     skrll       unsigned int bits = hi_bit - lo_bit;
    466   1.1     skrll       unsigned int mask = (1 << bits) - 1;
    467   1.1     skrll       result |= (shifted & mask) << cur_bitshift;
    468   1.1     skrll       len -= bits;
    469   1.1     skrll       cur_bitshift += bits;
    470   1.1     skrll       cur_byte += nextbyte;
    471   1.1     skrll       lo_bit = 0;
    472   1.1     skrll       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
    473   1.1     skrll     }
    474   1.1     skrll   while (len != 0);
    475   1.1     skrll 
    476   1.1     skrll   return result;
    477   1.1     skrll }
    478   1.1     skrll 
    479   1.1     skrll /* Convert from FMT to a double.
    480   1.1     skrll    FROM is the address of the extended float.
    481   1.1     skrll    Store the double in *TO.  */
    482   1.1     skrll 
    483   1.1     skrll void
    484   1.1     skrll floatformat_to_double (const struct floatformat *fmt,
    485   1.1     skrll                        const void *from, double *to)
    486   1.1     skrll {
    487   1.1     skrll   const unsigned char *ufrom = (const unsigned char *) from;
    488   1.1     skrll   double dto;
    489   1.1     skrll   long exponent;
    490   1.1     skrll   unsigned long mant;
    491   1.1     skrll   unsigned int mant_bits, mant_off;
    492   1.1     skrll   int mant_bits_left;
    493   1.1     skrll 
    494   1.1     skrll   /* Split values are not handled specially, since the top half has
    495   1.1     skrll      the correctly rounded double value (in the only supported case of
    496   1.1     skrll      split values).  */
    497   1.1     skrll 
    498   1.1     skrll   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    499   1.1     skrll 			fmt->exp_start, fmt->exp_len);
    500   1.1     skrll 
    501   1.1     skrll   /* If the exponent indicates a NaN, we don't have information to
    502   1.1     skrll      decide what to do.  So we handle it like IEEE, except that we
    503   1.1     skrll      don't try to preserve the type of NaN.  FIXME.  */
    504   1.1     skrll   if ((unsigned long) exponent == fmt->exp_nan)
    505   1.1     skrll     {
    506   1.1     skrll       int nan = mant_bits_set (fmt, ufrom);
    507   1.1     skrll 
    508   1.1     skrll       /* On certain systems (such as GNU/Linux), the use of the
    509   1.7  christos 	 INFINITY macro below may generate a warning that cannot be
    510   1.1     skrll 	 silenced due to a bug in GCC (PR preprocessor/11931).  The
    511   1.1     skrll 	 preprocessor fails to recognise the __extension__ keyword in
    512   1.1     skrll 	 conjunction with the GNU/C99 extension for hexadecimal
    513   1.1     skrll 	 floating point constants and will issue a warning when
    514   1.1     skrll 	 compiling with -pedantic.  */
    515   1.1     skrll       if (nan)
    516   1.1     skrll 	dto = NAN;
    517   1.1     skrll       else
    518   1.2     joerg #ifdef __vax__
    519   1.2     joerg 	dto = HUGE_VAL;
    520   1.2     joerg #else
    521   1.1     skrll 	dto = INFINITY;
    522   1.2     joerg #endif
    523   1.1     skrll 
    524   1.1     skrll       if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
    525   1.1     skrll 	dto = -dto;
    526   1.1     skrll 
    527   1.1     skrll       *to = dto;
    528   1.1     skrll 
    529   1.1     skrll       return;
    530   1.1     skrll     }
    531   1.1     skrll 
    532   1.1     skrll   mant_bits_left = fmt->man_len;
    533   1.1     skrll   mant_off = fmt->man_start;
    534   1.1     skrll   dto = 0.0;
    535   1.1     skrll 
    536   1.1     skrll   /* Build the result algebraically.  Might go infinite, underflow, etc;
    537   1.1     skrll      who cares. */
    538   1.1     skrll 
    539   1.5  christos   /* For denorms use minimum exponent.  */
    540   1.5  christos   if (exponent == 0)
    541   1.5  christos     exponent = 1 - fmt->exp_bias;
    542   1.5  christos   else
    543   1.5  christos     {
    544   1.5  christos       exponent -= fmt->exp_bias;
    545   1.5  christos 
    546   1.5  christos       /* If this format uses a hidden bit, explicitly add it in now.
    547   1.5  christos 	 Otherwise, increment the exponent by one to account for the
    548   1.5  christos 	 integer bit.  */
    549   1.1     skrll 
    550   1.1     skrll       if (fmt->intbit == floatformat_intbit_no)
    551   1.1     skrll 	dto = ldexp (1.0, exponent);
    552   1.1     skrll       else
    553   1.1     skrll 	exponent++;
    554   1.1     skrll     }
    555   1.1     skrll 
    556   1.1     skrll   while (mant_bits_left > 0)
    557   1.1     skrll     {
    558   1.1     skrll       mant_bits = min (mant_bits_left, 32);
    559   1.1     skrll 
    560   1.1     skrll       mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    561   1.1     skrll 			 mant_off, mant_bits);
    562   1.1     skrll 
    563   1.5  christos       dto += ldexp ((double) mant, exponent - mant_bits);
    564   1.5  christos       exponent -= mant_bits;
    565   1.1     skrll       mant_off += mant_bits;
    566   1.1     skrll       mant_bits_left -= mant_bits;
    567   1.1     skrll     }
    568   1.1     skrll 
    569   1.1     skrll   /* Negate it if negative.  */
    570   1.1     skrll   if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
    571   1.1     skrll     dto = -dto;
    572   1.1     skrll   *to = dto;
    573   1.1     skrll }
    574   1.1     skrll 
    575   1.1     skrll static void put_field (unsigned char *, enum floatformat_byteorders,
    577   1.1     skrll                        unsigned int,
    578   1.1     skrll                        unsigned int,
    579   1.1     skrll                        unsigned int,
    580   1.1     skrll                        unsigned long);
    581   1.1     skrll 
    582   1.1     skrll /* Set a field which starts at START and is LEN bits long.  DATA and
    583   1.1     skrll    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
    584   1.1     skrll static void
    585   1.1     skrll put_field (unsigned char *data, enum floatformat_byteorders order,
    586   1.1     skrll            unsigned int total_len, unsigned int start, unsigned int len,
    587   1.1     skrll            unsigned long stuff_to_put)
    588   1.1     skrll {
    589   1.1     skrll   unsigned int cur_byte;
    590   1.1     skrll   int lo_bit, hi_bit;
    591   1.1     skrll   int nextbyte = (order == floatformat_little) ? 1 : -1;
    592   1.1     skrll 
    593   1.1     skrll   /* Start is in big-endian bit order!  Fix that first.  */
    594   1.1     skrll   start = total_len - (start + len);
    595   1.1     skrll 
    596   1.1     skrll   /* Start at the least significant part of the field.  */
    597   1.1     skrll   if (order == floatformat_little)
    598   1.1     skrll     cur_byte = start / FLOATFORMAT_CHAR_BIT;
    599   1.1     skrll   else
    600   1.1     skrll     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
    601   1.1     skrll 
    602   1.1     skrll   lo_bit = start % FLOATFORMAT_CHAR_BIT;
    603   1.1     skrll   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
    604   1.1     skrll 
    605   1.1     skrll   do
    606   1.1     skrll     {
    607   1.1     skrll       unsigned char *byte_ptr = data + cur_byte;
    608   1.1     skrll       unsigned int bits = hi_bit - lo_bit;
    609   1.1     skrll       unsigned int mask = ((1 << bits) - 1) << lo_bit;
    610   1.1     skrll       *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
    611   1.1     skrll       stuff_to_put >>= bits;
    612   1.1     skrll       len -= bits;
    613   1.1     skrll       cur_byte += nextbyte;
    614   1.1     skrll       lo_bit = 0;
    615   1.1     skrll       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
    616   1.1     skrll     }
    617   1.1     skrll   while (len != 0);
    618   1.1     skrll }
    619   1.1     skrll 
    620   1.1     skrll /* The converse: convert the double *FROM to an extended float
    621   1.1     skrll    and store where TO points.  Neither FROM nor TO have any alignment
    622   1.1     skrll    restrictions.  */
    623   1.1     skrll 
    624   1.1     skrll void
    625   1.1     skrll floatformat_from_double (const struct floatformat *fmt,
    626   1.1     skrll                          const double *from, void *to)
    627   1.1     skrll {
    628   1.1     skrll   double dfrom;
    629   1.1     skrll   int exponent;
    630   1.1     skrll   double mant;
    631   1.1     skrll   unsigned int mant_bits, mant_off;
    632   1.1     skrll   int mant_bits_left;
    633   1.1     skrll   unsigned char *uto = (unsigned char *) to;
    634   1.1     skrll 
    635   1.1     skrll   dfrom = *from;
    636   1.1     skrll   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
    637   1.1     skrll 
    638   1.1     skrll   /* Split values are not handled specially, since a bottom half of
    639   1.1     skrll      zero is correct for any value representable as double (in the
    640   1.1     skrll      only supported case of split values).  */
    641   1.1     skrll 
    642   1.1     skrll   /* If negative, set the sign bit.  */
    643   1.1     skrll   if (dfrom < 0)
    644   1.1     skrll     {
    645   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
    646   1.1     skrll       dfrom = -dfrom;
    647   1.1     skrll     }
    648   1.1     skrll 
    649   1.1     skrll   if (dfrom == 0)
    650   1.1     skrll     {
    651   1.1     skrll       /* 0.0.  */
    652   1.1     skrll       return;
    653   1.1     skrll     }
    654   1.1     skrll 
    655   1.1     skrll   if (dfrom != dfrom)
    656   1.1     skrll     {
    657   1.1     skrll       /* NaN.  */
    658   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    659   1.1     skrll 		 fmt->exp_len, fmt->exp_nan);
    660   1.1     skrll       /* Be sure it's not infinity, but NaN value is irrelevant.  */
    661   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
    662   1.1     skrll 		 32, 1);
    663   1.1     skrll       return;
    664   1.1     skrll     }
    665   1.1     skrll 
    666   1.1     skrll   if (dfrom + dfrom == dfrom)
    667   1.1     skrll     {
    668   1.1     skrll       /* This can only happen for an infinite value (or zero, which we
    669   1.1     skrll 	 already handled above).  */
    670   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    671   1.1     skrll 		 fmt->exp_len, fmt->exp_nan);
    672   1.1     skrll       return;
    673   1.1     skrll     }
    674   1.1     skrll 
    675   1.1     skrll   mant = frexp (dfrom, &exponent);
    676   1.1     skrll   if (exponent + fmt->exp_bias - 1 > 0)
    677   1.1     skrll     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    678   1.1     skrll 	       fmt->exp_len, exponent + fmt->exp_bias - 1);
    679   1.1     skrll   else
    680   1.1     skrll     {
    681   1.1     skrll       /* Handle a denormalized number.  FIXME: What should we do for
    682   1.1     skrll 	 non-IEEE formats?  */
    683   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    684   1.1     skrll 		 fmt->exp_len, 0);
    685   1.1     skrll       mant = ldexp (mant, exponent + fmt->exp_bias - 1);
    686   1.1     skrll     }
    687   1.1     skrll 
    688   1.1     skrll   mant_bits_left = fmt->man_len;
    689   1.1     skrll   mant_off = fmt->man_start;
    690   1.1     skrll   while (mant_bits_left > 0)
    691   1.1     skrll     {
    692   1.1     skrll       unsigned long mant_long;
    693   1.1     skrll       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
    694   1.1     skrll 
    695   1.1     skrll       mant *= 4294967296.0;
    696   1.1     skrll       mant_long = (unsigned long)mant;
    697   1.1     skrll       mant -= mant_long;
    698   1.1     skrll 
    699   1.1     skrll       /* If the integer bit is implicit, and we are not creating a
    700   1.1     skrll 	 denormalized number, then we need to discard it.  */
    701   1.1     skrll       if ((unsigned int) mant_bits_left == fmt->man_len
    702   1.1     skrll 	  && fmt->intbit == floatformat_intbit_no
    703   1.1     skrll 	  && exponent + fmt->exp_bias - 1 > 0)
    704   1.1     skrll 	{
    705   1.1     skrll 	  mant_long &= 0x7fffffff;
    706   1.1     skrll 	  mant_bits -= 1;
    707   1.1     skrll 	}
    708   1.1     skrll       else if (mant_bits < 32)
    709   1.1     skrll 	{
    710   1.1     skrll 	  /* The bits we want are in the most significant MANT_BITS bits of
    711   1.1     skrll 	     mant_long.  Move them to the least significant.  */
    712   1.1     skrll 	  mant_long >>= 32 - mant_bits;
    713   1.1     skrll 	}
    714   1.1     skrll 
    715   1.1     skrll       put_field (uto, fmt->byteorder, fmt->totalsize,
    716   1.1     skrll 		 mant_off, mant_bits, mant_long);
    717   1.1     skrll       mant_off += mant_bits;
    718   1.1     skrll       mant_bits_left -= mant_bits;
    719   1.1     skrll     }
    720   1.1     skrll }
    721   1.1     skrll 
    722   1.1     skrll /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
    723   1.1     skrll 
    724   1.1     skrll int
    725   1.1     skrll floatformat_is_valid (const struct floatformat *fmt, const void *from)
    726   1.1     skrll {
    727   1.1     skrll   return fmt->is_valid (fmt, from);
    728   1.1     skrll }
    729   1.1     skrll 
    730   1.1     skrll 
    731   1.1     skrll #ifdef IEEE_DEBUG
    732   1.1     skrll 
    733   1.1     skrll #include <stdio.h>
    734   1.1     skrll 
    735   1.1     skrll /* This is to be run on a host which uses IEEE floating point.  */
    736   1.1     skrll 
    737   1.1     skrll void
    738   1.1     skrll ieee_test (double n)
    739   1.1     skrll {
    740   1.1     skrll   double result;
    741   1.1     skrll 
    742   1.1     skrll   floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
    743   1.1     skrll   if ((n != result && (! isnan (n) || ! isnan (result)))
    744   1.1     skrll       || (n < 0 && result >= 0)
    745   1.1     skrll       || (n >= 0 && result < 0))
    746   1.1     skrll     printf ("Differ(to): %.20g -> %.20g\n", n, result);
    747   1.1     skrll 
    748   1.1     skrll   floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
    749   1.1     skrll   if ((n != result && (! isnan (n) || ! isnan (result)))
    750   1.1     skrll       || (n < 0 && result >= 0)
    751   1.1     skrll       || (n >= 0 && result < 0))
    752   1.1     skrll     printf ("Differ(from): %.20g -> %.20g\n", n, result);
    753   1.1     skrll 
    754   1.1     skrll #if 0
    755   1.1     skrll   {
    756   1.1     skrll     char exten[16];
    757   1.1     skrll 
    758   1.1     skrll     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
    759   1.1     skrll     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
    760   1.1     skrll     if (n != result)
    761   1.1     skrll       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
    762   1.1     skrll   }
    763   1.1     skrll #endif
    764   1.1     skrll 
    765   1.1     skrll #if IEEE_DEBUG > 1
    766   1.1     skrll   /* This is to be run on a host which uses 68881 format.  */
    767   1.1     skrll   {
    768   1.1     skrll     long double ex = *(long double *)exten;
    769   1.1     skrll     if (ex != n)
    770   1.1     skrll       printf ("Differ(from vs. extended): %.20g\n", n);
    771   1.1     skrll   }
    772   1.1     skrll #endif
    773   1.1     skrll }
    774   1.1     skrll 
    775   1.1     skrll int
    776   1.1     skrll main (void)
    777   1.1     skrll {
    778   1.1     skrll   ieee_test (0.0);
    779   1.5  christos   ieee_test (0.5);
    780   1.1     skrll   ieee_test (1.1);
    781   1.1     skrll   ieee_test (256.0);
    782   1.1     skrll   ieee_test (0.12345);
    783   1.1     skrll   ieee_test (234235.78907234);
    784   1.1     skrll   ieee_test (-512.0);
    785   1.1     skrll   ieee_test (-0.004321);
    786   1.1     skrll   ieee_test (1.2E-70);
    787   1.1     skrll   ieee_test (1.2E-316);
    788   1.1     skrll   ieee_test (4.9406564584124654E-324);
    789   1.1     skrll   ieee_test (- 4.9406564584124654E-324);
    790   1.1     skrll   ieee_test (- 0.0);
    791   1.1     skrll   ieee_test (- INFINITY);
    792   1.1     skrll   ieee_test (- NAN);
    793   1.1     skrll   ieee_test (INFINITY);
    794   1.1     skrll   ieee_test (NAN);
    795   1.1     skrll   return 0;
    796   1.1     skrll }
    797                 #endif
    798