1169689Skan/* IEEE floating point support routines, for GDB, the GNU Debugger.
2169689Skan   Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
3169689Skan   Free Software Foundation, Inc.
4169689Skan
5169689SkanThis file is part of GDB.
6169689Skan
7169689SkanThis program is free software; you can redistribute it and/or modify
8169689Skanit under the terms of the GNU General Public License as published by
9169689Skanthe Free Software Foundation; either version 2 of the License, or
10169689Skan(at your option) any later version.
11169689Skan
12169689SkanThis program is distributed in the hope that it will be useful,
13169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
14169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15169689SkanGNU General Public License for more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with this program; if not, write to the Free Software
19169689SkanFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20169689Skan
21169689Skan/* This is needed to pick up the NAN macro on some systems.  */
22169689Skan#define _GNU_SOURCE
23169689Skan
24169689Skan#ifdef HAVE_CONFIG_H
25169689Skan#include "config.h"
26169689Skan#endif
27169689Skan
28169689Skan#include <math.h>
29169689Skan
30169689Skan#ifdef HAVE_STRING_H
31169689Skan#include <string.h>
32169689Skan#endif
33169689Skan
34169689Skan/* On some platforms, <float.h> provides DBL_QNAN.  */
35169689Skan#ifdef STDC_HEADERS
36169689Skan#include <float.h>
37169689Skan#endif
38169689Skan
39169689Skan#include "ansidecl.h"
40169689Skan#include "libiberty.h"
41169689Skan#include "floatformat.h"
42169689Skan
43169689Skan#ifndef INFINITY
44169689Skan#ifdef HUGE_VAL
45169689Skan#define INFINITY HUGE_VAL
46169689Skan#else
47169689Skan#define INFINITY (1.0 / 0.0)
48169689Skan#endif
49169689Skan#endif
50169689Skan
51169689Skan#ifndef NAN
52169689Skan#ifdef DBL_QNAN
53169689Skan#define NAN DBL_QNAN
54169689Skan#else
55169689Skan#define NAN (0.0 / 0.0)
56169689Skan#endif
57169689Skan#endif
58169689Skan
59169689Skanstatic unsigned long get_field (const unsigned char *,
60169689Skan                                enum floatformat_byteorders,
61169689Skan                                unsigned int,
62169689Skan                                unsigned int,
63169689Skan                                unsigned int);
64169689Skanstatic int floatformat_always_valid (const struct floatformat *fmt,
65169689Skan                                     const void *from);
66169689Skan
67169689Skanstatic int
68169689Skanfloatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
69169689Skan                          const void *from ATTRIBUTE_UNUSED)
70169689Skan{
71169689Skan  return 1;
72169689Skan}
73169689Skan
74169689Skan/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
75169689Skan   going to bother with trying to muck around with whether it is defined in
76169689Skan   a system header, what we do if not, etc.  */
77169689Skan#define FLOATFORMAT_CHAR_BIT 8
78169689Skan
79169689Skan/* floatformats for IEEE single and double, big and little endian.  */
80169689Skanconst struct floatformat floatformat_ieee_single_big =
81169689Skan{
82169689Skan  floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
83169689Skan  floatformat_intbit_no,
84169689Skan  "floatformat_ieee_single_big",
85169689Skan  floatformat_always_valid
86169689Skan};
87169689Skanconst struct floatformat floatformat_ieee_single_little =
88169689Skan{
89169689Skan  floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
90169689Skan  floatformat_intbit_no,
91169689Skan  "floatformat_ieee_single_little",
92169689Skan  floatformat_always_valid
93169689Skan};
94169689Skanconst struct floatformat floatformat_ieee_double_big =
95169689Skan{
96169689Skan  floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
97169689Skan  floatformat_intbit_no,
98169689Skan  "floatformat_ieee_double_big",
99169689Skan  floatformat_always_valid
100169689Skan};
101169689Skanconst struct floatformat floatformat_ieee_double_little =
102169689Skan{
103169689Skan  floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
104169689Skan  floatformat_intbit_no,
105169689Skan  "floatformat_ieee_double_little",
106169689Skan  floatformat_always_valid
107169689Skan};
108169689Skan
109169689Skan/* floatformat for IEEE double, little endian byte order, with big endian word
110169689Skan   ordering, as on the ARM.  */
111169689Skan
112169689Skanconst struct floatformat floatformat_ieee_double_littlebyte_bigword =
113169689Skan{
114169689Skan  floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
115169689Skan  floatformat_intbit_no,
116169689Skan  "floatformat_ieee_double_littlebyte_bigword",
117169689Skan  floatformat_always_valid
118169689Skan};
119169689Skan
120169689Skan/* floatformat for VAX.  Not quite IEEE, but close enough.  */
121169689Skan
122169689Skanconst struct floatformat floatformat_vax_f =
123169689Skan{
124169689Skan  floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
125169689Skan  floatformat_intbit_no,
126169689Skan  "floatformat_vax_f",
127169689Skan  floatformat_always_valid
128169689Skan};
129169689Skanconst struct floatformat floatformat_vax_d =
130169689Skan{
131169689Skan  floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
132169689Skan  floatformat_intbit_no,
133169689Skan  "floatformat_vax_d",
134169689Skan  floatformat_always_valid
135169689Skan};
136169689Skanconst struct floatformat floatformat_vax_g =
137169689Skan{
138169689Skan  floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
139169689Skan  floatformat_intbit_no,
140169689Skan  "floatformat_vax_g",
141169689Skan  floatformat_always_valid
142169689Skan};
143169689Skan
144169689Skanstatic int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
145169689Skan					  const void *from);
146169689Skan
147169689Skanstatic int
148169689Skanfloatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
149169689Skan{
150169689Skan  /* In the i387 double-extended format, if the exponent is all ones,
151169689Skan     then the integer bit must be set.  If the exponent is neither 0
152169689Skan     nor ~0, the intbit must also be set.  Only if the exponent is
153169689Skan     zero can it be zero, and then it must be zero.  */
154169689Skan  unsigned long exponent, int_bit;
155169689Skan  const unsigned char *ufrom = (const unsigned char *) from;
156169689Skan
157169689Skan  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
158169689Skan			fmt->exp_start, fmt->exp_len);
159169689Skan  int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
160169689Skan		       fmt->man_start, 1);
161169689Skan
162169689Skan  if ((exponent == 0) != (int_bit == 0))
163169689Skan    return 0;
164169689Skan  else
165169689Skan    return 1;
166169689Skan}
167169689Skan
168169689Skanconst struct floatformat floatformat_i387_ext =
169169689Skan{
170169689Skan  floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
171169689Skan  floatformat_intbit_yes,
172169689Skan  "floatformat_i387_ext",
173169689Skan  floatformat_i387_ext_is_valid
174169689Skan};
175169689Skanconst struct floatformat floatformat_m68881_ext =
176169689Skan{
177169689Skan  /* Note that the bits from 16 to 31 are unused.  */
178169689Skan  floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
179169689Skan  floatformat_intbit_yes,
180169689Skan  "floatformat_m68881_ext",
181169689Skan  floatformat_always_valid
182169689Skan};
183169689Skanconst struct floatformat floatformat_i960_ext =
184169689Skan{
185169689Skan  /* Note that the bits from 0 to 15 are unused.  */
186169689Skan  floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
187169689Skan  floatformat_intbit_yes,
188169689Skan  "floatformat_i960_ext",
189169689Skan  floatformat_always_valid
190169689Skan};
191169689Skanconst struct floatformat floatformat_m88110_ext =
192169689Skan{
193169689Skan  floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
194169689Skan  floatformat_intbit_yes,
195169689Skan  "floatformat_m88110_ext",
196169689Skan  floatformat_always_valid
197169689Skan};
198169689Skanconst struct floatformat floatformat_m88110_harris_ext =
199169689Skan{
200169689Skan  /* Harris uses raw format 128 bytes long, but the number is just an ieee
201169689Skan     double, and the last 64 bits are wasted. */
202169689Skan  floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
203169689Skan  floatformat_intbit_no,
204169689Skan  "floatformat_m88110_ext_harris",
205169689Skan  floatformat_always_valid
206169689Skan};
207169689Skanconst struct floatformat floatformat_arm_ext_big =
208169689Skan{
209169689Skan  /* Bits 1 to 16 are unused.  */
210169689Skan  floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
211169689Skan  floatformat_intbit_yes,
212169689Skan  "floatformat_arm_ext_big",
213169689Skan  floatformat_always_valid
214169689Skan};
215169689Skanconst struct floatformat floatformat_arm_ext_littlebyte_bigword =
216169689Skan{
217169689Skan  /* Bits 1 to 16 are unused.  */
218169689Skan  floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
219169689Skan  floatformat_intbit_yes,
220169689Skan  "floatformat_arm_ext_littlebyte_bigword",
221169689Skan  floatformat_always_valid
222169689Skan};
223169689Skanconst struct floatformat floatformat_ia64_spill_big =
224169689Skan{
225169689Skan  floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
226169689Skan  floatformat_intbit_yes,
227169689Skan  "floatformat_ia64_spill_big",
228169689Skan  floatformat_always_valid
229169689Skan};
230169689Skanconst struct floatformat floatformat_ia64_spill_little =
231169689Skan{
232169689Skan  floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
233169689Skan  floatformat_intbit_yes,
234169689Skan  "floatformat_ia64_spill_little",
235169689Skan  floatformat_always_valid
236169689Skan};
237169689Skanconst struct floatformat floatformat_ia64_quad_big =
238169689Skan{
239169689Skan  floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
240169689Skan  floatformat_intbit_no,
241169689Skan  "floatformat_ia64_quad_big",
242169689Skan  floatformat_always_valid
243169689Skan};
244169689Skanconst struct floatformat floatformat_ia64_quad_little =
245169689Skan{
246169689Skan  floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
247169689Skan  floatformat_intbit_no,
248169689Skan  "floatformat_ia64_quad_little",
249169689Skan  floatformat_always_valid
250169689Skan};
251169689Skan
252169689Skan
253169689Skan#ifndef min
254169689Skan#define min(a, b) ((a) < (b) ? (a) : (b))
255169689Skan#endif
256169689Skan
257169689Skan/* Extract a field which starts at START and is LEN bits long.  DATA and
258169689Skan   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
259169689Skanstatic unsigned long
260169689Skanget_field (const unsigned char *data, enum floatformat_byteorders order,
261169689Skan           unsigned int total_len, unsigned int start, unsigned int len)
262169689Skan{
263169689Skan  unsigned long result = 0;
264169689Skan  unsigned int cur_byte;
265169689Skan  int lo_bit, hi_bit, cur_bitshift = 0;
266169689Skan  int nextbyte = (order == floatformat_little) ? 1 : -1;
267169689Skan
268169689Skan  /* Start is in big-endian bit order!  Fix that first.  */
269169689Skan  start = total_len - (start + len);
270169689Skan
271169689Skan  /* Start at the least significant part of the field.  */
272169689Skan  if (order == floatformat_little)
273169689Skan    cur_byte = start / FLOATFORMAT_CHAR_BIT;
274169689Skan  else
275169689Skan    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
276169689Skan
277169689Skan  lo_bit = start % FLOATFORMAT_CHAR_BIT;
278169689Skan  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
279169689Skan
280169689Skan  do
281169689Skan    {
282169689Skan      unsigned int shifted = *(data + cur_byte) >> lo_bit;
283169689Skan      unsigned int bits = hi_bit - lo_bit;
284169689Skan      unsigned int mask = (1 << bits) - 1;
285169689Skan      result |= (shifted & mask) << cur_bitshift;
286169689Skan      len -= bits;
287169689Skan      cur_bitshift += bits;
288169689Skan      cur_byte += nextbyte;
289169689Skan      lo_bit = 0;
290169689Skan      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
291169689Skan    }
292169689Skan  while (len != 0);
293169689Skan
294169689Skan  return result;
295169689Skan}
296169689Skan
297169689Skan/* Convert from FMT to a double.
298169689Skan   FROM is the address of the extended float.
299169689Skan   Store the double in *TO.  */
300169689Skan
301169689Skanvoid
302169689Skanfloatformat_to_double (const struct floatformat *fmt,
303169689Skan                       const void *from, double *to)
304169689Skan{
305169689Skan  const unsigned char *ufrom = (const unsigned char *) from;
306169689Skan  double dto;
307169689Skan  long exponent;
308169689Skan  unsigned long mant;
309169689Skan  unsigned int mant_bits, mant_off;
310169689Skan  int mant_bits_left;
311169689Skan  int special_exponent;		/* It's a NaN, denorm or zero */
312
313  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
314			fmt->exp_start, fmt->exp_len);
315
316  /* If the exponent indicates a NaN, we don't have information to
317     decide what to do.  So we handle it like IEEE, except that we
318     don't try to preserve the type of NaN.  FIXME.  */
319  if ((unsigned long) exponent == fmt->exp_nan)
320    {
321      int nan;
322
323      mant_off = fmt->man_start;
324      mant_bits_left = fmt->man_len;
325      nan = 0;
326      while (mant_bits_left > 0)
327	{
328	  mant_bits = min (mant_bits_left, 32);
329
330	  if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
331			 mant_off, mant_bits) != 0)
332	    {
333	      /* This is a NaN.  */
334	      nan = 1;
335	      break;
336	    }
337
338	  mant_off += mant_bits;
339	  mant_bits_left -= mant_bits;
340	}
341
342      /* On certain systems (such as GNU/Linux), the use of the
343	 INFINITY macro below may generate a warning that can not be
344	 silenced due to a bug in GCC (PR preprocessor/11931).  The
345	 preprocessor fails to recognise the __extension__ keyword in
346	 conjunction with the GNU/C99 extension for hexadecimal
347	 floating point constants and will issue a warning when
348	 compiling with -pedantic.  */
349      if (nan)
350	dto = NAN;
351      else
352	dto = INFINITY;
353
354      if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
355	dto = -dto;
356
357      *to = dto;
358
359      return;
360    }
361
362  mant_bits_left = fmt->man_len;
363  mant_off = fmt->man_start;
364  dto = 0.0;
365
366  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
367
368  /* Don't bias zero's, denorms or NaNs.  */
369  if (!special_exponent)
370    exponent -= fmt->exp_bias;
371
372  /* Build the result algebraically.  Might go infinite, underflow, etc;
373     who cares. */
374
375  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
376     increment the exponent by one to account for the integer bit.  */
377
378  if (!special_exponent)
379    {
380      if (fmt->intbit == floatformat_intbit_no)
381	dto = ldexp (1.0, exponent);
382      else
383	exponent++;
384    }
385
386  while (mant_bits_left > 0)
387    {
388      mant_bits = min (mant_bits_left, 32);
389
390      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
391			 mant_off, mant_bits);
392
393      /* Handle denormalized numbers.  FIXME: What should we do for
394	 non-IEEE formats?  */
395      if (special_exponent && exponent == 0 && mant != 0)
396	dto += ldexp ((double)mant,
397		      (- fmt->exp_bias
398		       - mant_bits
399		       - (mant_off - fmt->man_start)
400		       + 1));
401      else
402	dto += ldexp ((double)mant, exponent - mant_bits);
403      if (exponent != 0)
404	exponent -= mant_bits;
405      mant_off += mant_bits;
406      mant_bits_left -= mant_bits;
407    }
408
409  /* Negate it if negative.  */
410  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
411    dto = -dto;
412  *to = dto;
413}
414
415static void put_field (unsigned char *, enum floatformat_byteorders,
416                       unsigned int,
417                       unsigned int,
418                       unsigned int,
419                       unsigned long);
420
421/* Set a field which starts at START and is LEN bits long.  DATA and
422   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
423static void
424put_field (unsigned char *data, enum floatformat_byteorders order,
425           unsigned int total_len, unsigned int start, unsigned int len,
426           unsigned long stuff_to_put)
427{
428  unsigned int cur_byte;
429  int lo_bit, hi_bit;
430  int nextbyte = (order == floatformat_little) ? 1 : -1;
431
432  /* Start is in big-endian bit order!  Fix that first.  */
433  start = total_len - (start + len);
434
435  /* Start at the least significant part of the field.  */
436  if (order == floatformat_little)
437    cur_byte = start / FLOATFORMAT_CHAR_BIT;
438  else
439    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
440
441  lo_bit = start % FLOATFORMAT_CHAR_BIT;
442  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
443
444  do
445    {
446      unsigned char *byte_ptr = data + cur_byte;
447      unsigned int bits = hi_bit - lo_bit;
448      unsigned int mask = ((1 << bits) - 1) << lo_bit;
449      *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
450      stuff_to_put >>= bits;
451      len -= bits;
452      cur_byte += nextbyte;
453      lo_bit = 0;
454      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
455    }
456  while (len != 0);
457}
458
459/* The converse: convert the double *FROM to an extended float
460   and store where TO points.  Neither FROM nor TO have any alignment
461   restrictions.  */
462
463void
464floatformat_from_double (const struct floatformat *fmt,
465                         const double *from, void *to)
466{
467  double dfrom;
468  int exponent;
469  double mant;
470  unsigned int mant_bits, mant_off;
471  int mant_bits_left;
472  unsigned char *uto = (unsigned char *) to;
473
474  dfrom = *from;
475  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
476
477  /* If negative, set the sign bit.  */
478  if (dfrom < 0)
479    {
480      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
481      dfrom = -dfrom;
482    }
483
484  if (dfrom == 0)
485    {
486      /* 0.0.  */
487      return;
488    }
489
490  if (dfrom != dfrom)
491    {
492      /* NaN.  */
493      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
494		 fmt->exp_len, fmt->exp_nan);
495      /* Be sure it's not infinity, but NaN value is irrelevant.  */
496      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
497		 32, 1);
498      return;
499    }
500
501  if (dfrom + dfrom == dfrom)
502    {
503      /* This can only happen for an infinite value (or zero, which we
504	 already handled above).  */
505      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
506		 fmt->exp_len, fmt->exp_nan);
507      return;
508    }
509
510  mant = frexp (dfrom, &exponent);
511  if (exponent + fmt->exp_bias - 1 > 0)
512    put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
513	       fmt->exp_len, exponent + fmt->exp_bias - 1);
514  else
515    {
516      /* Handle a denormalized number.  FIXME: What should we do for
517	 non-IEEE formats?  */
518      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
519		 fmt->exp_len, 0);
520      mant = ldexp (mant, exponent + fmt->exp_bias - 1);
521    }
522
523  mant_bits_left = fmt->man_len;
524  mant_off = fmt->man_start;
525  while (mant_bits_left > 0)
526    {
527      unsigned long mant_long;
528      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
529
530      mant *= 4294967296.0;
531      mant_long = (unsigned long)mant;
532      mant -= mant_long;
533
534      /* If the integer bit is implicit, and we are not creating a
535	 denormalized number, then we need to discard it.  */
536      if ((unsigned int) mant_bits_left == fmt->man_len
537	  && fmt->intbit == floatformat_intbit_no
538	  && exponent + fmt->exp_bias - 1 > 0)
539	{
540	  mant_long &= 0x7fffffff;
541	  mant_bits -= 1;
542	}
543      else if (mant_bits < 32)
544	{
545	  /* The bits we want are in the most significant MANT_BITS bits of
546	     mant_long.  Move them to the least significant.  */
547	  mant_long >>= 32 - mant_bits;
548	}
549
550      put_field (uto, fmt->byteorder, fmt->totalsize,
551		 mant_off, mant_bits, mant_long);
552      mant_off += mant_bits;
553      mant_bits_left -= mant_bits;
554    }
555}
556
557/* Return non-zero iff the data at FROM is a valid number in format FMT.  */
558
559int
560floatformat_is_valid (const struct floatformat *fmt, const void *from)
561{
562  return fmt->is_valid (fmt, from);
563}
564
565
566#ifdef IEEE_DEBUG
567
568#include <stdio.h>
569
570/* This is to be run on a host which uses IEEE floating point.  */
571
572void
573ieee_test (double n)
574{
575  double result;
576
577  floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
578  if ((n != result && (! isnan (n) || ! isnan (result)))
579      || (n < 0 && result >= 0)
580      || (n >= 0 && result < 0))
581    printf ("Differ(to): %.20g -> %.20g\n", n, result);
582
583  floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
584  if ((n != result && (! isnan (n) || ! isnan (result)))
585      || (n < 0 && result >= 0)
586      || (n >= 0 && result < 0))
587    printf ("Differ(from): %.20g -> %.20g\n", n, result);
588
589#if 0
590  {
591    char exten[16];
592
593    floatformat_from_double (&floatformat_m68881_ext, &n, exten);
594    floatformat_to_double (&floatformat_m68881_ext, exten, &result);
595    if (n != result)
596      printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
597  }
598#endif
599
600#if IEEE_DEBUG > 1
601  /* This is to be run on a host which uses 68881 format.  */
602  {
603    long double ex = *(long double *)exten;
604    if (ex != n)
605      printf ("Differ(from vs. extended): %.20g\n", n);
606  }
607#endif
608}
609
610int
611main (void)
612{
613  ieee_test (0.0);
614  ieee_test (0.5);
615  ieee_test (256.0);
616  ieee_test (0.12345);
617  ieee_test (234235.78907234);
618  ieee_test (-512.0);
619  ieee_test (-0.004321);
620  ieee_test (1.2E-70);
621  ieee_test (1.2E-316);
622  ieee_test (4.9406564584124654E-324);
623  ieee_test (- 4.9406564584124654E-324);
624  ieee_test (- 0.0);
625  ieee_test (- INFINITY);
626  ieee_test (- NAN);
627  ieee_test (INFINITY);
628  ieee_test (NAN);
629  return 0;
630}
631#endif
632