xref: /dflybsd-src/contrib/gdb-7/libiberty/floatformat.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* IEEE floating point support routines, for GDB, the GNU Debugger.
2*ef5ccd6cSJohn Marino    Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006, 2010, 2012
35796c8dcSSimon Schubert    Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 2 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program; if not, write to the Free Software
195796c8dcSSimon Schubert Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert /* This is needed to pick up the NAN macro on some systems.  */
225796c8dcSSimon Schubert #define _GNU_SOURCE
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert #ifdef HAVE_CONFIG_H
255796c8dcSSimon Schubert #include "config.h"
265796c8dcSSimon Schubert #endif
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert #include <math.h>
295796c8dcSSimon Schubert 
305796c8dcSSimon Schubert #ifdef HAVE_STRING_H
315796c8dcSSimon Schubert #include <string.h>
325796c8dcSSimon Schubert #endif
335796c8dcSSimon Schubert 
345796c8dcSSimon Schubert /* On some platforms, <float.h> provides DBL_QNAN.  */
355796c8dcSSimon Schubert #ifdef STDC_HEADERS
365796c8dcSSimon Schubert #include <float.h>
375796c8dcSSimon Schubert #endif
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert #include "ansidecl.h"
405796c8dcSSimon Schubert #include "libiberty.h"
415796c8dcSSimon Schubert #include "floatformat.h"
425796c8dcSSimon Schubert 
435796c8dcSSimon Schubert #ifndef INFINITY
445796c8dcSSimon Schubert #ifdef HUGE_VAL
455796c8dcSSimon Schubert #define INFINITY HUGE_VAL
465796c8dcSSimon Schubert #else
475796c8dcSSimon Schubert #define INFINITY (1.0 / 0.0)
485796c8dcSSimon Schubert #endif
495796c8dcSSimon Schubert #endif
505796c8dcSSimon Schubert 
515796c8dcSSimon Schubert #ifndef NAN
525796c8dcSSimon Schubert #ifdef DBL_QNAN
535796c8dcSSimon Schubert #define NAN DBL_QNAN
545796c8dcSSimon Schubert #else
555796c8dcSSimon Schubert #define NAN (0.0 / 0.0)
565796c8dcSSimon Schubert #endif
575796c8dcSSimon Schubert #endif
585796c8dcSSimon Schubert 
595796c8dcSSimon Schubert static int mant_bits_set (const struct floatformat *, const unsigned char *);
605796c8dcSSimon Schubert static unsigned long get_field (const unsigned char *,
615796c8dcSSimon Schubert                                 enum floatformat_byteorders,
625796c8dcSSimon Schubert                                 unsigned int,
635796c8dcSSimon Schubert                                 unsigned int,
645796c8dcSSimon Schubert                                 unsigned int);
655796c8dcSSimon Schubert static int floatformat_always_valid (const struct floatformat *fmt,
665796c8dcSSimon Schubert                                      const void *from);
675796c8dcSSimon Schubert 
685796c8dcSSimon Schubert static int
floatformat_always_valid(const struct floatformat * fmt ATTRIBUTE_UNUSED,const void * from ATTRIBUTE_UNUSED)695796c8dcSSimon Schubert floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
705796c8dcSSimon Schubert                           const void *from ATTRIBUTE_UNUSED)
715796c8dcSSimon Schubert {
725796c8dcSSimon Schubert   return 1;
735796c8dcSSimon Schubert }
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
765796c8dcSSimon Schubert    going to bother with trying to muck around with whether it is defined in
775796c8dcSSimon Schubert    a system header, what we do if not, etc.  */
785796c8dcSSimon Schubert #define FLOATFORMAT_CHAR_BIT 8
795796c8dcSSimon Schubert 
80cf7f2e2dSJohn Marino /* floatformats for IEEE half, single and double, big and little endian.  */
81cf7f2e2dSJohn Marino const struct floatformat floatformat_ieee_half_big =
82cf7f2e2dSJohn Marino {
83cf7f2e2dSJohn Marino   floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
84cf7f2e2dSJohn Marino   floatformat_intbit_no,
85cf7f2e2dSJohn Marino   "floatformat_ieee_half_big",
86cf7f2e2dSJohn Marino   floatformat_always_valid,
87cf7f2e2dSJohn Marino   NULL
88cf7f2e2dSJohn Marino };
89cf7f2e2dSJohn Marino const struct floatformat floatformat_ieee_half_little =
90cf7f2e2dSJohn Marino {
91cf7f2e2dSJohn Marino   floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
92cf7f2e2dSJohn Marino   floatformat_intbit_no,
93cf7f2e2dSJohn Marino   "floatformat_ieee_half_little",
94cf7f2e2dSJohn Marino   floatformat_always_valid,
95cf7f2e2dSJohn Marino   NULL
96cf7f2e2dSJohn Marino };
975796c8dcSSimon Schubert const struct floatformat floatformat_ieee_single_big =
985796c8dcSSimon Schubert {
995796c8dcSSimon Schubert   floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
1005796c8dcSSimon Schubert   floatformat_intbit_no,
1015796c8dcSSimon Schubert   "floatformat_ieee_single_big",
1025796c8dcSSimon Schubert   floatformat_always_valid,
1035796c8dcSSimon Schubert   NULL
1045796c8dcSSimon Schubert };
1055796c8dcSSimon Schubert const struct floatformat floatformat_ieee_single_little =
1065796c8dcSSimon Schubert {
1075796c8dcSSimon Schubert   floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
1085796c8dcSSimon Schubert   floatformat_intbit_no,
1095796c8dcSSimon Schubert   "floatformat_ieee_single_little",
1105796c8dcSSimon Schubert   floatformat_always_valid,
1115796c8dcSSimon Schubert   NULL
1125796c8dcSSimon Schubert };
1135796c8dcSSimon Schubert const struct floatformat floatformat_ieee_double_big =
1145796c8dcSSimon Schubert {
1155796c8dcSSimon Schubert   floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
1165796c8dcSSimon Schubert   floatformat_intbit_no,
1175796c8dcSSimon Schubert   "floatformat_ieee_double_big",
1185796c8dcSSimon Schubert   floatformat_always_valid,
1195796c8dcSSimon Schubert   NULL
1205796c8dcSSimon Schubert };
1215796c8dcSSimon Schubert const struct floatformat floatformat_ieee_double_little =
1225796c8dcSSimon Schubert {
1235796c8dcSSimon Schubert   floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
1245796c8dcSSimon Schubert   floatformat_intbit_no,
1255796c8dcSSimon Schubert   "floatformat_ieee_double_little",
1265796c8dcSSimon Schubert   floatformat_always_valid,
1275796c8dcSSimon Schubert   NULL
1285796c8dcSSimon Schubert };
1295796c8dcSSimon Schubert 
1305796c8dcSSimon Schubert /* floatformat for IEEE double, little endian byte order, with big endian word
1315796c8dcSSimon Schubert    ordering, as on the ARM.  */
1325796c8dcSSimon Schubert 
1335796c8dcSSimon Schubert const struct floatformat floatformat_ieee_double_littlebyte_bigword =
1345796c8dcSSimon Schubert {
1355796c8dcSSimon Schubert   floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
1365796c8dcSSimon Schubert   floatformat_intbit_no,
1375796c8dcSSimon Schubert   "floatformat_ieee_double_littlebyte_bigword",
1385796c8dcSSimon Schubert   floatformat_always_valid,
1395796c8dcSSimon Schubert   NULL
1405796c8dcSSimon Schubert };
1415796c8dcSSimon Schubert 
1425796c8dcSSimon Schubert /* floatformat for VAX.  Not quite IEEE, but close enough.  */
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert const struct floatformat floatformat_vax_f =
1455796c8dcSSimon Schubert {
1465796c8dcSSimon Schubert   floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
1475796c8dcSSimon Schubert   floatformat_intbit_no,
1485796c8dcSSimon Schubert   "floatformat_vax_f",
1495796c8dcSSimon Schubert   floatformat_always_valid,
1505796c8dcSSimon Schubert   NULL
1515796c8dcSSimon Schubert };
1525796c8dcSSimon Schubert const struct floatformat floatformat_vax_d =
1535796c8dcSSimon Schubert {
1545796c8dcSSimon Schubert   floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
1555796c8dcSSimon Schubert   floatformat_intbit_no,
1565796c8dcSSimon Schubert   "floatformat_vax_d",
1575796c8dcSSimon Schubert   floatformat_always_valid,
1585796c8dcSSimon Schubert   NULL
1595796c8dcSSimon Schubert };
1605796c8dcSSimon Schubert const struct floatformat floatformat_vax_g =
1615796c8dcSSimon Schubert {
1625796c8dcSSimon Schubert   floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
1635796c8dcSSimon Schubert   floatformat_intbit_no,
1645796c8dcSSimon Schubert   "floatformat_vax_g",
1655796c8dcSSimon Schubert   floatformat_always_valid,
1665796c8dcSSimon Schubert   NULL
1675796c8dcSSimon Schubert };
1685796c8dcSSimon Schubert 
1695796c8dcSSimon Schubert static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
1705796c8dcSSimon Schubert 					  const void *from);
1715796c8dcSSimon Schubert 
1725796c8dcSSimon Schubert static int
floatformat_i387_ext_is_valid(const struct floatformat * fmt,const void * from)1735796c8dcSSimon Schubert floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
1745796c8dcSSimon Schubert {
1755796c8dcSSimon Schubert   /* In the i387 double-extended format, if the exponent is all ones,
1765796c8dcSSimon Schubert      then the integer bit must be set.  If the exponent is neither 0
1775796c8dcSSimon Schubert      nor ~0, the intbit must also be set.  Only if the exponent is
1785796c8dcSSimon Schubert      zero can it be zero, and then it must be zero.  */
1795796c8dcSSimon Schubert   unsigned long exponent, int_bit;
1805796c8dcSSimon Schubert   const unsigned char *ufrom = (const unsigned char *) from;
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
1835796c8dcSSimon Schubert 			fmt->exp_start, fmt->exp_len);
1845796c8dcSSimon Schubert   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
1855796c8dcSSimon Schubert 		       fmt->man_start, 1);
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert   if ((exponent == 0) != (int_bit == 0))
1885796c8dcSSimon Schubert     return 0;
1895796c8dcSSimon Schubert   else
1905796c8dcSSimon Schubert     return 1;
1915796c8dcSSimon Schubert }
1925796c8dcSSimon Schubert 
1935796c8dcSSimon Schubert const struct floatformat floatformat_i387_ext =
1945796c8dcSSimon Schubert {
1955796c8dcSSimon Schubert   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
1965796c8dcSSimon Schubert   floatformat_intbit_yes,
1975796c8dcSSimon Schubert   "floatformat_i387_ext",
1985796c8dcSSimon Schubert   floatformat_i387_ext_is_valid,
1995796c8dcSSimon Schubert   NULL
2005796c8dcSSimon Schubert };
2015796c8dcSSimon Schubert const struct floatformat floatformat_m68881_ext =
2025796c8dcSSimon Schubert {
2035796c8dcSSimon Schubert   /* Note that the bits from 16 to 31 are unused.  */
2045796c8dcSSimon Schubert   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
2055796c8dcSSimon Schubert   floatformat_intbit_yes,
2065796c8dcSSimon Schubert   "floatformat_m68881_ext",
2075796c8dcSSimon Schubert   floatformat_always_valid,
2085796c8dcSSimon Schubert   NULL
2095796c8dcSSimon Schubert };
2105796c8dcSSimon Schubert const struct floatformat floatformat_i960_ext =
2115796c8dcSSimon Schubert {
2125796c8dcSSimon Schubert   /* Note that the bits from 0 to 15 are unused.  */
2135796c8dcSSimon Schubert   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
2145796c8dcSSimon Schubert   floatformat_intbit_yes,
2155796c8dcSSimon Schubert   "floatformat_i960_ext",
2165796c8dcSSimon Schubert   floatformat_always_valid,
2175796c8dcSSimon Schubert   NULL
2185796c8dcSSimon Schubert };
2195796c8dcSSimon Schubert const struct floatformat floatformat_m88110_ext =
2205796c8dcSSimon Schubert {
2215796c8dcSSimon Schubert   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
2225796c8dcSSimon Schubert   floatformat_intbit_yes,
2235796c8dcSSimon Schubert   "floatformat_m88110_ext",
2245796c8dcSSimon Schubert   floatformat_always_valid,
2255796c8dcSSimon Schubert   NULL
2265796c8dcSSimon Schubert };
2275796c8dcSSimon Schubert const struct floatformat floatformat_m88110_harris_ext =
2285796c8dcSSimon Schubert {
2295796c8dcSSimon Schubert   /* Harris uses raw format 128 bytes long, but the number is just an ieee
2305796c8dcSSimon Schubert      double, and the last 64 bits are wasted. */
2315796c8dcSSimon Schubert   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
2325796c8dcSSimon Schubert   floatformat_intbit_no,
2335796c8dcSSimon Schubert   "floatformat_m88110_ext_harris",
2345796c8dcSSimon Schubert   floatformat_always_valid,
2355796c8dcSSimon Schubert   NULL
2365796c8dcSSimon Schubert };
2375796c8dcSSimon Schubert const struct floatformat floatformat_arm_ext_big =
2385796c8dcSSimon Schubert {
2395796c8dcSSimon Schubert   /* Bits 1 to 16 are unused.  */
2405796c8dcSSimon Schubert   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
2415796c8dcSSimon Schubert   floatformat_intbit_yes,
2425796c8dcSSimon Schubert   "floatformat_arm_ext_big",
2435796c8dcSSimon Schubert   floatformat_always_valid,
2445796c8dcSSimon Schubert   NULL
2455796c8dcSSimon Schubert };
2465796c8dcSSimon Schubert const struct floatformat floatformat_arm_ext_littlebyte_bigword =
2475796c8dcSSimon Schubert {
2485796c8dcSSimon Schubert   /* Bits 1 to 16 are unused.  */
2495796c8dcSSimon Schubert   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
2505796c8dcSSimon Schubert   floatformat_intbit_yes,
2515796c8dcSSimon Schubert   "floatformat_arm_ext_littlebyte_bigword",
2525796c8dcSSimon Schubert   floatformat_always_valid,
2535796c8dcSSimon Schubert   NULL
2545796c8dcSSimon Schubert };
2555796c8dcSSimon Schubert const struct floatformat floatformat_ia64_spill_big =
2565796c8dcSSimon Schubert {
2575796c8dcSSimon Schubert   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
2585796c8dcSSimon Schubert   floatformat_intbit_yes,
2595796c8dcSSimon Schubert   "floatformat_ia64_spill_big",
2605796c8dcSSimon Schubert   floatformat_always_valid,
2615796c8dcSSimon Schubert   NULL
2625796c8dcSSimon Schubert };
2635796c8dcSSimon Schubert const struct floatformat floatformat_ia64_spill_little =
2645796c8dcSSimon Schubert {
2655796c8dcSSimon Schubert   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
2665796c8dcSSimon Schubert   floatformat_intbit_yes,
2675796c8dcSSimon Schubert   "floatformat_ia64_spill_little",
2685796c8dcSSimon Schubert   floatformat_always_valid,
2695796c8dcSSimon Schubert   NULL
2705796c8dcSSimon Schubert };
2715796c8dcSSimon Schubert const struct floatformat floatformat_ia64_quad_big =
2725796c8dcSSimon Schubert {
2735796c8dcSSimon Schubert   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
2745796c8dcSSimon Schubert   floatformat_intbit_no,
2755796c8dcSSimon Schubert   "floatformat_ia64_quad_big",
2765796c8dcSSimon Schubert   floatformat_always_valid,
2775796c8dcSSimon Schubert   NULL
2785796c8dcSSimon Schubert };
2795796c8dcSSimon Schubert const struct floatformat floatformat_ia64_quad_little =
2805796c8dcSSimon Schubert {
2815796c8dcSSimon Schubert   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
2825796c8dcSSimon Schubert   floatformat_intbit_no,
2835796c8dcSSimon Schubert   "floatformat_ia64_quad_little",
2845796c8dcSSimon Schubert   floatformat_always_valid,
2855796c8dcSSimon Schubert   NULL
2865796c8dcSSimon Schubert };
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert static int
floatformat_ibm_long_double_is_valid(const struct floatformat * fmt,const void * from)2895796c8dcSSimon Schubert floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
2905796c8dcSSimon Schubert 				      const void *from)
2915796c8dcSSimon Schubert {
2925796c8dcSSimon Schubert   const unsigned char *ufrom = (const unsigned char *) from;
2935796c8dcSSimon Schubert   const struct floatformat *hfmt = fmt->split_half;
2945796c8dcSSimon Schubert   long top_exp, bot_exp;
2955796c8dcSSimon Schubert   int top_nan = 0;
2965796c8dcSSimon Schubert 
2975796c8dcSSimon Schubert   top_exp = get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
2985796c8dcSSimon Schubert 		       hfmt->exp_start, hfmt->exp_len);
2995796c8dcSSimon Schubert   bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
3005796c8dcSSimon Schubert 		       hfmt->exp_start, hfmt->exp_len);
3015796c8dcSSimon Schubert 
3025796c8dcSSimon Schubert   if ((unsigned long) top_exp == hfmt->exp_nan)
3035796c8dcSSimon Schubert     top_nan = mant_bits_set (hfmt, ufrom);
3045796c8dcSSimon Schubert 
3055796c8dcSSimon Schubert   /* A NaN is valid with any low part.  */
3065796c8dcSSimon Schubert   if (top_nan)
3075796c8dcSSimon Schubert     return 1;
3085796c8dcSSimon Schubert 
3095796c8dcSSimon Schubert   /* An infinity, zero or denormal requires low part 0 (positive or
3105796c8dcSSimon Schubert      negative).  */
3115796c8dcSSimon Schubert   if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
3125796c8dcSSimon Schubert     {
3135796c8dcSSimon Schubert       if (bot_exp != 0)
3145796c8dcSSimon Schubert 	return 0;
3155796c8dcSSimon Schubert 
3165796c8dcSSimon Schubert       return !mant_bits_set (hfmt, ufrom + 8);
3175796c8dcSSimon Schubert     }
3185796c8dcSSimon Schubert 
3195796c8dcSSimon Schubert   /* The top part is now a finite normal value.  The long double value
3205796c8dcSSimon Schubert      is the sum of the two parts, and the top part must equal the
3215796c8dcSSimon Schubert      result of rounding the long double value to nearest double.  Thus
3225796c8dcSSimon Schubert      the bottom part must be <= 0.5ulp of the top part in absolute
3235796c8dcSSimon Schubert      value, and if it is < 0.5ulp then the long double is definitely
3245796c8dcSSimon Schubert      valid.  */
3255796c8dcSSimon Schubert   if (bot_exp < top_exp - 53)
3265796c8dcSSimon Schubert     return 1;
3275796c8dcSSimon Schubert   if (bot_exp > top_exp - 53 && bot_exp != 0)
3285796c8dcSSimon Schubert     return 0;
3295796c8dcSSimon Schubert   if (bot_exp == 0)
3305796c8dcSSimon Schubert     {
3315796c8dcSSimon Schubert       /* The bottom part is 0 or denormal.  Determine which, and if
3325796c8dcSSimon Schubert 	 denormal the first two set bits.  */
3335796c8dcSSimon Schubert       int first_bit = -1, second_bit = -1, cur_bit;
3345796c8dcSSimon Schubert       for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
3355796c8dcSSimon Schubert 	if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
3365796c8dcSSimon Schubert 		       hfmt->man_start + cur_bit, 1))
3375796c8dcSSimon Schubert 	  {
3385796c8dcSSimon Schubert 	    if (first_bit == -1)
3395796c8dcSSimon Schubert 	      first_bit = cur_bit;
3405796c8dcSSimon Schubert 	    else
3415796c8dcSSimon Schubert 	      {
3425796c8dcSSimon Schubert 		second_bit = cur_bit;
3435796c8dcSSimon Schubert 		break;
3445796c8dcSSimon Schubert 	      }
3455796c8dcSSimon Schubert 	  }
3465796c8dcSSimon Schubert       /* Bottom part 0 is OK.  */
3475796c8dcSSimon Schubert       if (first_bit == -1)
3485796c8dcSSimon Schubert 	return 1;
3495796c8dcSSimon Schubert       /* The real exponent of the bottom part is -first_bit.  */
3505796c8dcSSimon Schubert       if (-first_bit < top_exp - 53)
3515796c8dcSSimon Schubert 	return 1;
3525796c8dcSSimon Schubert       if (-first_bit > top_exp - 53)
3535796c8dcSSimon Schubert 	return 0;
3545796c8dcSSimon Schubert       /* The bottom part is at least 0.5ulp of the top part.  For this
3555796c8dcSSimon Schubert 	 to be OK, the bottom part must be exactly 0.5ulp (i.e. no
3565796c8dcSSimon Schubert 	 more bits set) and the top part must have last bit 0.  */
3575796c8dcSSimon Schubert       if (second_bit != -1)
3585796c8dcSSimon Schubert 	return 0;
3595796c8dcSSimon Schubert       return !get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
3605796c8dcSSimon Schubert 			 hfmt->man_start + hfmt->man_len - 1, 1);
3615796c8dcSSimon Schubert     }
3625796c8dcSSimon Schubert   else
3635796c8dcSSimon Schubert     {
3645796c8dcSSimon Schubert       /* The bottom part is at least 0.5ulp of the top part.  For this
3655796c8dcSSimon Schubert 	 to be OK, it must be exactly 0.5ulp (i.e. no explicit bits
3665796c8dcSSimon Schubert 	 set) and the top part must have last bit 0.  */
3675796c8dcSSimon Schubert       if (get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
3685796c8dcSSimon Schubert 		     hfmt->man_start + hfmt->man_len - 1, 1))
3695796c8dcSSimon Schubert 	return 0;
3705796c8dcSSimon Schubert       return !mant_bits_set (hfmt, ufrom + 8);
3715796c8dcSSimon Schubert     }
3725796c8dcSSimon Schubert }
3735796c8dcSSimon Schubert 
3745796c8dcSSimon Schubert const struct floatformat floatformat_ibm_long_double =
3755796c8dcSSimon Schubert {
3765796c8dcSSimon Schubert   floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
3775796c8dcSSimon Schubert   floatformat_intbit_no,
3785796c8dcSSimon Schubert   "floatformat_ibm_long_double",
3795796c8dcSSimon Schubert   floatformat_ibm_long_double_is_valid,
3805796c8dcSSimon Schubert   &floatformat_ieee_double_big
3815796c8dcSSimon Schubert };
3825796c8dcSSimon Schubert 
3835796c8dcSSimon Schubert 
3845796c8dcSSimon Schubert #ifndef min
3855796c8dcSSimon Schubert #define min(a, b) ((a) < (b) ? (a) : (b))
3865796c8dcSSimon Schubert #endif
3875796c8dcSSimon Schubert 
3885796c8dcSSimon Schubert /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
3895796c8dcSSimon Schubert    format FMT, 0 otherwise.  */
3905796c8dcSSimon Schubert static int
mant_bits_set(const struct floatformat * fmt,const unsigned char * ufrom)3915796c8dcSSimon Schubert mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
3925796c8dcSSimon Schubert {
3935796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
3945796c8dcSSimon Schubert   int mant_bits_left;
3955796c8dcSSimon Schubert 
3965796c8dcSSimon Schubert   mant_off = fmt->man_start;
3975796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
3985796c8dcSSimon Schubert   while (mant_bits_left > 0)
3995796c8dcSSimon Schubert     {
4005796c8dcSSimon Schubert       mant_bits = min (mant_bits_left, 32);
4015796c8dcSSimon Schubert 
4025796c8dcSSimon Schubert       if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
4035796c8dcSSimon Schubert 		     mant_off, mant_bits) != 0)
4045796c8dcSSimon Schubert 	return 1;
4055796c8dcSSimon Schubert 
4065796c8dcSSimon Schubert       mant_off += mant_bits;
4075796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
4085796c8dcSSimon Schubert     }
4095796c8dcSSimon Schubert   return 0;
4105796c8dcSSimon Schubert }
4115796c8dcSSimon Schubert 
4125796c8dcSSimon Schubert /* Extract a field which starts at START and is LEN bits long.  DATA and
4135796c8dcSSimon Schubert    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
4145796c8dcSSimon Schubert static unsigned long
get_field(const unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len)4155796c8dcSSimon Schubert get_field (const unsigned char *data, enum floatformat_byteorders order,
4165796c8dcSSimon Schubert            unsigned int total_len, unsigned int start, unsigned int len)
4175796c8dcSSimon Schubert {
4185796c8dcSSimon Schubert   unsigned long result = 0;
4195796c8dcSSimon Schubert   unsigned int cur_byte;
4205796c8dcSSimon Schubert   int lo_bit, hi_bit, cur_bitshift = 0;
4215796c8dcSSimon Schubert   int nextbyte = (order == floatformat_little) ? 1 : -1;
4225796c8dcSSimon Schubert 
4235796c8dcSSimon Schubert   /* Start is in big-endian bit order!  Fix that first.  */
4245796c8dcSSimon Schubert   start = total_len - (start + len);
4255796c8dcSSimon Schubert 
4265796c8dcSSimon Schubert   /* Start at the least significant part of the field.  */
4275796c8dcSSimon Schubert   if (order == floatformat_little)
4285796c8dcSSimon Schubert     cur_byte = start / FLOATFORMAT_CHAR_BIT;
4295796c8dcSSimon Schubert   else
4305796c8dcSSimon Schubert     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
4315796c8dcSSimon Schubert 
4325796c8dcSSimon Schubert   lo_bit = start % FLOATFORMAT_CHAR_BIT;
4335796c8dcSSimon Schubert   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
4345796c8dcSSimon Schubert 
4355796c8dcSSimon Schubert   do
4365796c8dcSSimon Schubert     {
4375796c8dcSSimon Schubert       unsigned int shifted = *(data + cur_byte) >> lo_bit;
4385796c8dcSSimon Schubert       unsigned int bits = hi_bit - lo_bit;
4395796c8dcSSimon Schubert       unsigned int mask = (1 << bits) - 1;
4405796c8dcSSimon Schubert       result |= (shifted & mask) << cur_bitshift;
4415796c8dcSSimon Schubert       len -= bits;
4425796c8dcSSimon Schubert       cur_bitshift += bits;
4435796c8dcSSimon Schubert       cur_byte += nextbyte;
4445796c8dcSSimon Schubert       lo_bit = 0;
4455796c8dcSSimon Schubert       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
4465796c8dcSSimon Schubert     }
4475796c8dcSSimon Schubert   while (len != 0);
4485796c8dcSSimon Schubert 
4495796c8dcSSimon Schubert   return result;
4505796c8dcSSimon Schubert }
4515796c8dcSSimon Schubert 
4525796c8dcSSimon Schubert /* Convert from FMT to a double.
4535796c8dcSSimon Schubert    FROM is the address of the extended float.
4545796c8dcSSimon Schubert    Store the double in *TO.  */
4555796c8dcSSimon Schubert 
4565796c8dcSSimon Schubert void
floatformat_to_double(const struct floatformat * fmt,const void * from,double * to)4575796c8dcSSimon Schubert floatformat_to_double (const struct floatformat *fmt,
4585796c8dcSSimon Schubert                        const void *from, double *to)
4595796c8dcSSimon Schubert {
4605796c8dcSSimon Schubert   const unsigned char *ufrom = (const unsigned char *) from;
4615796c8dcSSimon Schubert   double dto;
4625796c8dcSSimon Schubert   long exponent;
4635796c8dcSSimon Schubert   unsigned long mant;
4645796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
4655796c8dcSSimon Schubert   int mant_bits_left;
4665796c8dcSSimon Schubert 
4675796c8dcSSimon Schubert   /* Split values are not handled specially, since the top half has
4685796c8dcSSimon Schubert      the correctly rounded double value (in the only supported case of
4695796c8dcSSimon Schubert      split values).  */
4705796c8dcSSimon Schubert 
4715796c8dcSSimon Schubert   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
4725796c8dcSSimon Schubert 			fmt->exp_start, fmt->exp_len);
4735796c8dcSSimon Schubert 
4745796c8dcSSimon Schubert   /* If the exponent indicates a NaN, we don't have information to
4755796c8dcSSimon Schubert      decide what to do.  So we handle it like IEEE, except that we
4765796c8dcSSimon Schubert      don't try to preserve the type of NaN.  FIXME.  */
4775796c8dcSSimon Schubert   if ((unsigned long) exponent == fmt->exp_nan)
4785796c8dcSSimon Schubert     {
4795796c8dcSSimon Schubert       int nan = mant_bits_set (fmt, ufrom);
4805796c8dcSSimon Schubert 
4815796c8dcSSimon Schubert       /* On certain systems (such as GNU/Linux), the use of the
4825796c8dcSSimon Schubert 	 INFINITY macro below may generate a warning that can not be
4835796c8dcSSimon Schubert 	 silenced due to a bug in GCC (PR preprocessor/11931).  The
4845796c8dcSSimon Schubert 	 preprocessor fails to recognise the __extension__ keyword in
4855796c8dcSSimon Schubert 	 conjunction with the GNU/C99 extension for hexadecimal
4865796c8dcSSimon Schubert 	 floating point constants and will issue a warning when
4875796c8dcSSimon Schubert 	 compiling with -pedantic.  */
4885796c8dcSSimon Schubert       if (nan)
4895796c8dcSSimon Schubert 	dto = NAN;
4905796c8dcSSimon Schubert       else
4915796c8dcSSimon Schubert 	dto = INFINITY;
4925796c8dcSSimon Schubert 
4935796c8dcSSimon Schubert       if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
4945796c8dcSSimon Schubert 	dto = -dto;
4955796c8dcSSimon Schubert 
4965796c8dcSSimon Schubert       *to = dto;
4975796c8dcSSimon Schubert 
4985796c8dcSSimon Schubert       return;
4995796c8dcSSimon Schubert     }
5005796c8dcSSimon Schubert 
5015796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
5025796c8dcSSimon Schubert   mant_off = fmt->man_start;
5035796c8dcSSimon Schubert   dto = 0.0;
5045796c8dcSSimon Schubert 
5055796c8dcSSimon Schubert   /* Build the result algebraically.  Might go infinite, underflow, etc;
5065796c8dcSSimon Schubert      who cares. */
5075796c8dcSSimon Schubert 
508*ef5ccd6cSJohn Marino   /* For denorms use minimum exponent.  */
509*ef5ccd6cSJohn Marino   if (exponent == 0)
510*ef5ccd6cSJohn Marino     exponent = 1 - fmt->exp_bias;
511*ef5ccd6cSJohn Marino   else
5125796c8dcSSimon Schubert     {
513*ef5ccd6cSJohn Marino       exponent -= fmt->exp_bias;
514*ef5ccd6cSJohn Marino 
515*ef5ccd6cSJohn Marino       /* If this format uses a hidden bit, explicitly add it in now.
516*ef5ccd6cSJohn Marino 	 Otherwise, increment the exponent by one to account for the
517*ef5ccd6cSJohn Marino 	 integer bit.  */
518*ef5ccd6cSJohn Marino 
5195796c8dcSSimon Schubert       if (fmt->intbit == floatformat_intbit_no)
5205796c8dcSSimon Schubert 	dto = ldexp (1.0, exponent);
5215796c8dcSSimon Schubert       else
5225796c8dcSSimon Schubert 	exponent++;
5235796c8dcSSimon Schubert     }
5245796c8dcSSimon Schubert 
5255796c8dcSSimon Schubert   while (mant_bits_left > 0)
5265796c8dcSSimon Schubert     {
5275796c8dcSSimon Schubert       mant_bits = min (mant_bits_left, 32);
5285796c8dcSSimon Schubert 
5295796c8dcSSimon Schubert       mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
5305796c8dcSSimon Schubert 			 mant_off, mant_bits);
5315796c8dcSSimon Schubert 
5325796c8dcSSimon Schubert       dto += ldexp ((double) mant, exponent - mant_bits);
5335796c8dcSSimon Schubert       exponent -= mant_bits;
5345796c8dcSSimon Schubert       mant_off += mant_bits;
5355796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
5365796c8dcSSimon Schubert     }
5375796c8dcSSimon Schubert 
5385796c8dcSSimon Schubert   /* Negate it if negative.  */
5395796c8dcSSimon Schubert   if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
5405796c8dcSSimon Schubert     dto = -dto;
5415796c8dcSSimon Schubert   *to = dto;
5425796c8dcSSimon Schubert }
5435796c8dcSSimon Schubert 
5445796c8dcSSimon Schubert static void put_field (unsigned char *, enum floatformat_byteorders,
5455796c8dcSSimon Schubert                        unsigned int,
5465796c8dcSSimon Schubert                        unsigned int,
5475796c8dcSSimon Schubert                        unsigned int,
5485796c8dcSSimon Schubert                        unsigned long);
5495796c8dcSSimon Schubert 
5505796c8dcSSimon Schubert /* Set a field which starts at START and is LEN bits long.  DATA and
5515796c8dcSSimon Schubert    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
5525796c8dcSSimon Schubert static void
put_field(unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len,unsigned long stuff_to_put)5535796c8dcSSimon Schubert put_field (unsigned char *data, enum floatformat_byteorders order,
5545796c8dcSSimon Schubert            unsigned int total_len, unsigned int start, unsigned int len,
5555796c8dcSSimon Schubert            unsigned long stuff_to_put)
5565796c8dcSSimon Schubert {
5575796c8dcSSimon Schubert   unsigned int cur_byte;
5585796c8dcSSimon Schubert   int lo_bit, hi_bit;
5595796c8dcSSimon Schubert   int nextbyte = (order == floatformat_little) ? 1 : -1;
5605796c8dcSSimon Schubert 
5615796c8dcSSimon Schubert   /* Start is in big-endian bit order!  Fix that first.  */
5625796c8dcSSimon Schubert   start = total_len - (start + len);
5635796c8dcSSimon Schubert 
5645796c8dcSSimon Schubert   /* Start at the least significant part of the field.  */
5655796c8dcSSimon Schubert   if (order == floatformat_little)
5665796c8dcSSimon Schubert     cur_byte = start / FLOATFORMAT_CHAR_BIT;
5675796c8dcSSimon Schubert   else
5685796c8dcSSimon Schubert     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
5695796c8dcSSimon Schubert 
5705796c8dcSSimon Schubert   lo_bit = start % FLOATFORMAT_CHAR_BIT;
5715796c8dcSSimon Schubert   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
5725796c8dcSSimon Schubert 
5735796c8dcSSimon Schubert   do
5745796c8dcSSimon Schubert     {
5755796c8dcSSimon Schubert       unsigned char *byte_ptr = data + cur_byte;
5765796c8dcSSimon Schubert       unsigned int bits = hi_bit - lo_bit;
5775796c8dcSSimon Schubert       unsigned int mask = ((1 << bits) - 1) << lo_bit;
5785796c8dcSSimon Schubert       *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
5795796c8dcSSimon Schubert       stuff_to_put >>= bits;
5805796c8dcSSimon Schubert       len -= bits;
5815796c8dcSSimon Schubert       cur_byte += nextbyte;
5825796c8dcSSimon Schubert       lo_bit = 0;
5835796c8dcSSimon Schubert       hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
5845796c8dcSSimon Schubert     }
5855796c8dcSSimon Schubert   while (len != 0);
5865796c8dcSSimon Schubert }
5875796c8dcSSimon Schubert 
5885796c8dcSSimon Schubert /* The converse: convert the double *FROM to an extended float
5895796c8dcSSimon Schubert    and store where TO points.  Neither FROM nor TO have any alignment
5905796c8dcSSimon Schubert    restrictions.  */
5915796c8dcSSimon Schubert 
5925796c8dcSSimon Schubert void
floatformat_from_double(const struct floatformat * fmt,const double * from,void * to)5935796c8dcSSimon Schubert floatformat_from_double (const struct floatformat *fmt,
5945796c8dcSSimon Schubert                          const double *from, void *to)
5955796c8dcSSimon Schubert {
5965796c8dcSSimon Schubert   double dfrom;
5975796c8dcSSimon Schubert   int exponent;
5985796c8dcSSimon Schubert   double mant;
5995796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
6005796c8dcSSimon Schubert   int mant_bits_left;
6015796c8dcSSimon Schubert   unsigned char *uto = (unsigned char *) to;
6025796c8dcSSimon Schubert 
6035796c8dcSSimon Schubert   dfrom = *from;
6045796c8dcSSimon Schubert   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
6055796c8dcSSimon Schubert 
6065796c8dcSSimon Schubert   /* Split values are not handled specially, since a bottom half of
6075796c8dcSSimon Schubert      zero is correct for any value representable as double (in the
6085796c8dcSSimon Schubert      only supported case of split values).  */
6095796c8dcSSimon Schubert 
6105796c8dcSSimon Schubert   /* If negative, set the sign bit.  */
6115796c8dcSSimon Schubert   if (dfrom < 0)
6125796c8dcSSimon Schubert     {
6135796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
6145796c8dcSSimon Schubert       dfrom = -dfrom;
6155796c8dcSSimon Schubert     }
6165796c8dcSSimon Schubert 
6175796c8dcSSimon Schubert   if (dfrom == 0)
6185796c8dcSSimon Schubert     {
6195796c8dcSSimon Schubert       /* 0.0.  */
6205796c8dcSSimon Schubert       return;
6215796c8dcSSimon Schubert     }
6225796c8dcSSimon Schubert 
6235796c8dcSSimon Schubert   if (dfrom != dfrom)
6245796c8dcSSimon Schubert     {
6255796c8dcSSimon Schubert       /* NaN.  */
6265796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
6275796c8dcSSimon Schubert 		 fmt->exp_len, fmt->exp_nan);
6285796c8dcSSimon Schubert       /* Be sure it's not infinity, but NaN value is irrelevant.  */
6295796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
6305796c8dcSSimon Schubert 		 32, 1);
6315796c8dcSSimon Schubert       return;
6325796c8dcSSimon Schubert     }
6335796c8dcSSimon Schubert 
6345796c8dcSSimon Schubert   if (dfrom + dfrom == dfrom)
6355796c8dcSSimon Schubert     {
6365796c8dcSSimon Schubert       /* This can only happen for an infinite value (or zero, which we
6375796c8dcSSimon Schubert 	 already handled above).  */
6385796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
6395796c8dcSSimon Schubert 		 fmt->exp_len, fmt->exp_nan);
6405796c8dcSSimon Schubert       return;
6415796c8dcSSimon Schubert     }
6425796c8dcSSimon Schubert 
6435796c8dcSSimon Schubert   mant = frexp (dfrom, &exponent);
6445796c8dcSSimon Schubert   if (exponent + fmt->exp_bias - 1 > 0)
6455796c8dcSSimon Schubert     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
6465796c8dcSSimon Schubert 	       fmt->exp_len, exponent + fmt->exp_bias - 1);
6475796c8dcSSimon Schubert   else
6485796c8dcSSimon Schubert     {
6495796c8dcSSimon Schubert       /* Handle a denormalized number.  FIXME: What should we do for
6505796c8dcSSimon Schubert 	 non-IEEE formats?  */
6515796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
6525796c8dcSSimon Schubert 		 fmt->exp_len, 0);
6535796c8dcSSimon Schubert       mant = ldexp (mant, exponent + fmt->exp_bias - 1);
6545796c8dcSSimon Schubert     }
6555796c8dcSSimon Schubert 
6565796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
6575796c8dcSSimon Schubert   mant_off = fmt->man_start;
6585796c8dcSSimon Schubert   while (mant_bits_left > 0)
6595796c8dcSSimon Schubert     {
6605796c8dcSSimon Schubert       unsigned long mant_long;
6615796c8dcSSimon Schubert       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
6625796c8dcSSimon Schubert 
6635796c8dcSSimon Schubert       mant *= 4294967296.0;
6645796c8dcSSimon Schubert       mant_long = (unsigned long)mant;
6655796c8dcSSimon Schubert       mant -= mant_long;
6665796c8dcSSimon Schubert 
6675796c8dcSSimon Schubert       /* If the integer bit is implicit, and we are not creating a
6685796c8dcSSimon Schubert 	 denormalized number, then we need to discard it.  */
6695796c8dcSSimon Schubert       if ((unsigned int) mant_bits_left == fmt->man_len
6705796c8dcSSimon Schubert 	  && fmt->intbit == floatformat_intbit_no
6715796c8dcSSimon Schubert 	  && exponent + fmt->exp_bias - 1 > 0)
6725796c8dcSSimon Schubert 	{
6735796c8dcSSimon Schubert 	  mant_long &= 0x7fffffff;
6745796c8dcSSimon Schubert 	  mant_bits -= 1;
6755796c8dcSSimon Schubert 	}
6765796c8dcSSimon Schubert       else if (mant_bits < 32)
6775796c8dcSSimon Schubert 	{
6785796c8dcSSimon Schubert 	  /* The bits we want are in the most significant MANT_BITS bits of
6795796c8dcSSimon Schubert 	     mant_long.  Move them to the least significant.  */
6805796c8dcSSimon Schubert 	  mant_long >>= 32 - mant_bits;
6815796c8dcSSimon Schubert 	}
6825796c8dcSSimon Schubert 
6835796c8dcSSimon Schubert       put_field (uto, fmt->byteorder, fmt->totalsize,
6845796c8dcSSimon Schubert 		 mant_off, mant_bits, mant_long);
6855796c8dcSSimon Schubert       mant_off += mant_bits;
6865796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
6875796c8dcSSimon Schubert     }
6885796c8dcSSimon Schubert }
6895796c8dcSSimon Schubert 
6905796c8dcSSimon Schubert /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
6915796c8dcSSimon Schubert 
6925796c8dcSSimon Schubert int
floatformat_is_valid(const struct floatformat * fmt,const void * from)6935796c8dcSSimon Schubert floatformat_is_valid (const struct floatformat *fmt, const void *from)
6945796c8dcSSimon Schubert {
6955796c8dcSSimon Schubert   return fmt->is_valid (fmt, from);
6965796c8dcSSimon Schubert }
6975796c8dcSSimon Schubert 
6985796c8dcSSimon Schubert 
6995796c8dcSSimon Schubert #ifdef IEEE_DEBUG
7005796c8dcSSimon Schubert 
7015796c8dcSSimon Schubert #include <stdio.h>
7025796c8dcSSimon Schubert 
7035796c8dcSSimon Schubert /* This is to be run on a host which uses IEEE floating point.  */
7045796c8dcSSimon Schubert 
7055796c8dcSSimon Schubert void
ieee_test(double n)7065796c8dcSSimon Schubert ieee_test (double n)
7075796c8dcSSimon Schubert {
7085796c8dcSSimon Schubert   double result;
7095796c8dcSSimon Schubert 
7105796c8dcSSimon Schubert   floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
7115796c8dcSSimon Schubert   if ((n != result && (! isnan (n) || ! isnan (result)))
7125796c8dcSSimon Schubert       || (n < 0 && result >= 0)
7135796c8dcSSimon Schubert       || (n >= 0 && result < 0))
7145796c8dcSSimon Schubert     printf ("Differ(to): %.20g -> %.20g\n", n, result);
7155796c8dcSSimon Schubert 
7165796c8dcSSimon Schubert   floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
7175796c8dcSSimon Schubert   if ((n != result && (! isnan (n) || ! isnan (result)))
7185796c8dcSSimon Schubert       || (n < 0 && result >= 0)
7195796c8dcSSimon Schubert       || (n >= 0 && result < 0))
7205796c8dcSSimon Schubert     printf ("Differ(from): %.20g -> %.20g\n", n, result);
7215796c8dcSSimon Schubert 
7225796c8dcSSimon Schubert #if 0
7235796c8dcSSimon Schubert   {
7245796c8dcSSimon Schubert     char exten[16];
7255796c8dcSSimon Schubert 
7265796c8dcSSimon Schubert     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
7275796c8dcSSimon Schubert     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
7285796c8dcSSimon Schubert     if (n != result)
7295796c8dcSSimon Schubert       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
7305796c8dcSSimon Schubert   }
7315796c8dcSSimon Schubert #endif
7325796c8dcSSimon Schubert 
7335796c8dcSSimon Schubert #if IEEE_DEBUG > 1
7345796c8dcSSimon Schubert   /* This is to be run on a host which uses 68881 format.  */
7355796c8dcSSimon Schubert   {
7365796c8dcSSimon Schubert     long double ex = *(long double *)exten;
7375796c8dcSSimon Schubert     if (ex != n)
7385796c8dcSSimon Schubert       printf ("Differ(from vs. extended): %.20g\n", n);
7395796c8dcSSimon Schubert   }
7405796c8dcSSimon Schubert #endif
7415796c8dcSSimon Schubert }
7425796c8dcSSimon Schubert 
7435796c8dcSSimon Schubert int
main(void)7445796c8dcSSimon Schubert main (void)
7455796c8dcSSimon Schubert {
7465796c8dcSSimon Schubert   ieee_test (0.0);
7475796c8dcSSimon Schubert   ieee_test (0.5);
748*ef5ccd6cSJohn Marino   ieee_test (1.1);
7495796c8dcSSimon Schubert   ieee_test (256.0);
7505796c8dcSSimon Schubert   ieee_test (0.12345);
7515796c8dcSSimon Schubert   ieee_test (234235.78907234);
7525796c8dcSSimon Schubert   ieee_test (-512.0);
7535796c8dcSSimon Schubert   ieee_test (-0.004321);
7545796c8dcSSimon Schubert   ieee_test (1.2E-70);
7555796c8dcSSimon Schubert   ieee_test (1.2E-316);
7565796c8dcSSimon Schubert   ieee_test (4.9406564584124654E-324);
7575796c8dcSSimon Schubert   ieee_test (- 4.9406564584124654E-324);
7585796c8dcSSimon Schubert   ieee_test (- 0.0);
7595796c8dcSSimon Schubert   ieee_test (- INFINITY);
7605796c8dcSSimon Schubert   ieee_test (- NAN);
7615796c8dcSSimon Schubert   ieee_test (INFINITY);
7625796c8dcSSimon Schubert   ieee_test (NAN);
7635796c8dcSSimon Schubert   return 0;
7645796c8dcSSimon Schubert }
7655796c8dcSSimon Schubert #endif
766