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