1169695Skan/* IEEE floating point support routines, for GDB, the GNU Debugger.
2169695Skan   Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
3169695Skan   Free Software Foundation, Inc.
4169695Skan
5169695SkanThis file is part of GDB.
6169695Skan
7169695SkanThis program is free software; you can redistribute it and/or modify
8169695Skanit under the terms of the GNU General Public License as published by
9169695Skanthe Free Software Foundation; either version 2 of the License, or
10169695Skan(at your option) any later version.
11169695Skan
12169695SkanThis program is distributed in the hope that it will be useful,
13169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
14169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15169695SkanGNU General Public License for more details.
16169695Skan
17169695SkanYou should have received a copy of the GNU General Public License
18169695Skanalong with this program; if not, write to the Free Software
19169695SkanFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20169695Skan
21169695Skan/* This is needed to pick up the NAN macro on some systems.  */
22169695Skan#define _GNU_SOURCE
23169695Skan
24169695Skan#ifdef HAVE_CONFIG_H
25169695Skan#include "config.h"
26169695Skan#endif
27169695Skan
28169695Skan#include <math.h>
29169695Skan
30169695Skan#ifdef HAVE_STRING_H
31169695Skan#include <string.h>
32169695Skan#endif
33169695Skan
34169695Skan/* On some platforms, <float.h> provides DBL_QNAN.  */
35169695Skan#ifdef STDC_HEADERS
36169695Skan#include <float.h>
37169695Skan#endif
38169695Skan
39169695Skan#include "ansidecl.h"
40169695Skan#include "libiberty.h"
41169695Skan#include "floatformat.h"
42169695Skan
43169695Skan#ifndef INFINITY
44169695Skan#ifdef HUGE_VAL
45169695Skan#define INFINITY HUGE_VAL
46169695Skan#else
47169695Skan#define INFINITY (1.0 / 0.0)
48169695Skan#endif
49169695Skan#endif
50169695Skan
51169695Skan#ifndef NAN
52169695Skan#ifdef DBL_QNAN
53169695Skan#define NAN DBL_QNAN
54169695Skan#else
55169695Skan#define NAN (0.0 / 0.0)
56169695Skan#endif
57169695Skan#endif
58169695Skan
59169695Skanstatic unsigned long get_field (const unsigned char *,
60169695Skan                                enum floatformat_byteorders,
61169695Skan                                unsigned int,
62169695Skan                                unsigned int,
63169695Skan                                unsigned int);
64169695Skanstatic int floatformat_always_valid (const struct floatformat *fmt,
65169695Skan                                     const void *from);
66169695Skan
67169695Skanstatic int
68169695Skanfloatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
69169695Skan                          const void *from ATTRIBUTE_UNUSED)
70169695Skan{
71169695Skan  return 1;
72169695Skan}
73169695Skan
74169695Skan/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
75169695Skan   going to bother with trying to muck around with whether it is defined in
76169695Skan   a system header, what we do if not, etc.  */
77169695Skan#define FLOATFORMAT_CHAR_BIT 8
78169695Skan
79169695Skan/* floatformats for IEEE single and double, big and little endian.  */
80169695Skanconst struct floatformat floatformat_ieee_single_big =
81169695Skan{
82169695Skan  floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
83169695Skan  floatformat_intbit_no,
84169695Skan  "floatformat_ieee_single_big",
85169695Skan  floatformat_always_valid
86169695Skan};
87169695Skanconst struct floatformat floatformat_ieee_single_little =
88169695Skan{
89169695Skan  floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
90169695Skan  floatformat_intbit_no,
91169695Skan  "floatformat_ieee_single_little",
92169695Skan  floatformat_always_valid
93169695Skan};
94169695Skanconst struct floatformat floatformat_ieee_double_big =
95169695Skan{
96169695Skan  floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
97169695Skan  floatformat_intbit_no,
98169695Skan  "floatformat_ieee_double_big",
99169695Skan  floatformat_always_valid
100169695Skan};
101169695Skanconst struct floatformat floatformat_ieee_double_little =
102169695Skan{
103169695Skan  floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
104169695Skan  floatformat_intbit_no,
105169695Skan  "floatformat_ieee_double_little",
106169695Skan  floatformat_always_valid
107169695Skan};
108169695Skan
109169695Skan/* floatformat for IEEE double, little endian byte order, with big endian word
110169695Skan   ordering, as on the ARM.  */
111169695Skan
112169695Skanconst struct floatformat floatformat_ieee_double_littlebyte_bigword =
113169695Skan{
114169695Skan  floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
115169695Skan  floatformat_intbit_no,
116169695Skan  "floatformat_ieee_double_littlebyte_bigword",
117169695Skan  floatformat_always_valid
118169695Skan};
119169695Skan
120169695Skan/* floatformat for VAX.  Not quite IEEE, but close enough.  */
121169695Skan
122169695Skanconst struct floatformat floatformat_vax_f =
123169695Skan{
124169695Skan  floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
125169695Skan  floatformat_intbit_no,
126169695Skan  "floatformat_vax_f",
127169695Skan  floatformat_always_valid
128169695Skan};
129169695Skanconst struct floatformat floatformat_vax_d =
130169695Skan{
131169695Skan  floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
132169695Skan  floatformat_intbit_no,
133169695Skan  "floatformat_vax_d",
134169695Skan  floatformat_always_valid
135169695Skan};
136169695Skanconst struct floatformat floatformat_vax_g =
137169695Skan{
138169695Skan  floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
139169695Skan  floatformat_intbit_no,
140169695Skan  "floatformat_vax_g",
141169695Skan  floatformat_always_valid
142169695Skan};
143169695Skan
144169695Skanstatic int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
145169695Skan					  const void *from);
146169695Skan
147169695Skanstatic int
148169695Skanfloatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
149169695Skan{
150169695Skan  /* In the i387 double-extended format, if the exponent is all ones,
151169695Skan     then the integer bit must be set.  If the exponent is neither 0
152169695Skan     nor ~0, the intbit must also be set.  Only if the exponent is
153169695Skan     zero can it be zero, and then it must be zero.  */
154169695Skan  unsigned long exponent, int_bit;
155169695Skan  const unsigned char *ufrom = (const unsigned char *) from;
156169695Skan
157169695Skan  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
158169695Skan			fmt->exp_start, fmt->exp_len);
159169695Skan  int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
160169695Skan		       fmt->man_start, 1);
161169695Skan
162169695Skan  if ((exponent == 0) != (int_bit == 0))
163169695Skan    return 0;
164169695Skan  else
165169695Skan    return 1;
166169695Skan}
167169695Skan
168169695Skanconst struct floatformat floatformat_i387_ext =
169169695Skan{
170169695Skan  floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
171169695Skan  floatformat_intbit_yes,
172169695Skan  "floatformat_i387_ext",
173169695Skan  floatformat_i387_ext_is_valid
174169695Skan};
175169695Skanconst struct floatformat floatformat_m68881_ext =
176169695Skan{
177169695Skan  /* Note that the bits from 16 to 31 are unused.  */
178169695Skan  floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
179169695Skan  floatformat_intbit_yes,
180169695Skan  "floatformat_m68881_ext",
181169695Skan  floatformat_always_valid
182169695Skan};
183169695Skanconst struct floatformat floatformat_i960_ext =
184169695Skan{
185169695Skan  /* Note that the bits from 0 to 15 are unused.  */
186169695Skan  floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
187169695Skan  floatformat_intbit_yes,
188169695Skan  "floatformat_i960_ext",
189169695Skan  floatformat_always_valid
190169695Skan};
191169695Skanconst struct floatformat floatformat_m88110_ext =
192169695Skan{
193169695Skan  floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
194169695Skan  floatformat_intbit_yes,
195169695Skan  "floatformat_m88110_ext",
196169695Skan  floatformat_always_valid
197169695Skan};
198169695Skanconst struct floatformat floatformat_m88110_harris_ext =
199169695Skan{
200169695Skan  /* Harris uses raw format 128 bytes long, but the number is just an ieee
201169695Skan     double, and the last 64 bits are wasted. */
202169695Skan  floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
203169695Skan  floatformat_intbit_no,
204169695Skan  "floatformat_m88110_ext_harris",
205169695Skan  floatformat_always_valid
206169695Skan};
207169695Skanconst struct floatformat floatformat_arm_ext_big =
208169695Skan{
209169695Skan  /* Bits 1 to 16 are unused.  */
210169695Skan  floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
211169695Skan  floatformat_intbit_yes,
212169695Skan  "floatformat_arm_ext_big",
213169695Skan  floatformat_always_valid
214169695Skan};
215169695Skanconst struct floatformat floatformat_arm_ext_littlebyte_bigword =
216169695Skan{
217169695Skan  /* Bits 1 to 16 are unused.  */
218169695Skan  floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
219169695Skan  floatformat_intbit_yes,
220169695Skan  "floatformat_arm_ext_littlebyte_bigword",
221169695Skan  floatformat_always_valid
222169695Skan};
223169695Skanconst struct floatformat floatformat_ia64_spill_big =
224169695Skan{
225169695Skan  floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
226169695Skan  floatformat_intbit_yes,
227169695Skan  "floatformat_ia64_spill_big",
228169695Skan  floatformat_always_valid
229169695Skan};
230169695Skanconst struct floatformat floatformat_ia64_spill_little =
231169695Skan{
232169695Skan  floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
233169695Skan  floatformat_intbit_yes,
234169695Skan  "floatformat_ia64_spill_little",
235169695Skan  floatformat_always_valid
236169695Skan};
237169695Skanconst struct floatformat floatformat_ia64_quad_big =
238169695Skan{
239169695Skan  floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
240169695Skan  floatformat_intbit_no,
241169695Skan  "floatformat_ia64_quad_big",
242169695Skan  floatformat_always_valid
243169695Skan};
244169695Skanconst struct floatformat floatformat_ia64_quad_little =
245169695Skan{
246169695Skan  floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
247169695Skan  floatformat_intbit_no,
248169695Skan  "floatformat_ia64_quad_little",
249169695Skan  floatformat_always_valid
250169695Skan};
251169695Skan
252259705Spfg
253259705Spfg#ifndef min
254259705Spfg#define min(a, b) ((a) < (b) ? (a) : (b))
255259705Spfg#endif
256259705Spfg
257169695Skan/* Extract a field which starts at START and is LEN bits long.  DATA and
258169695Skan   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
259169695Skanstatic unsigned long
260169695Skanget_field (const unsigned char *data, enum floatformat_byteorders order,
261169695Skan           unsigned int total_len, unsigned int start, unsigned int len)
262169695Skan{
263259705Spfg  unsigned long result = 0;
264169695Skan  unsigned int cur_byte;
265259705Spfg  int lo_bit, hi_bit, cur_bitshift = 0;
266259705Spfg  int nextbyte = (order == floatformat_little) ? 1 : -1;
267169695Skan
268259705Spfg  /* Start is in big-endian bit order!  Fix that first.  */
269259705Spfg  start = total_len - (start + len);
270259705Spfg
271169695Skan  /* Start at the least significant part of the field.  */
272169695Skan  if (order == floatformat_little)
273259705Spfg    cur_byte = start / FLOATFORMAT_CHAR_BIT;
274169695Skan  else
275259705Spfg    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
276169695Skan
277259705Spfg  lo_bit = start % FLOATFORMAT_CHAR_BIT;
278259705Spfg  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
279259705Spfg
280259705Spfg  do
281169695Skan    {
282259705Spfg      unsigned int shifted = *(data + cur_byte) >> lo_bit;
283259705Spfg      unsigned int bits = hi_bit - lo_bit;
284259705Spfg      unsigned int mask = (1 << bits) - 1;
285259705Spfg      result |= (shifted & mask) << cur_bitshift;
286259705Spfg      len -= bits;
287259705Spfg      cur_bitshift += bits;
288259705Spfg      cur_byte += nextbyte;
289259705Spfg      lo_bit = 0;
290259705Spfg      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
291169695Skan    }
292259705Spfg  while (len != 0);
293259705Spfg
294169695Skan  return result;
295169695Skan}
296169695Skan
297169695Skan/* Convert from FMT to a double.
298169695Skan   FROM is the address of the extended float.
299169695Skan   Store the double in *TO.  */
300169695Skan
301169695Skanvoid
302169695Skanfloatformat_to_double (const struct floatformat *fmt,
303169695Skan                       const void *from, double *to)
304169695Skan{
305169695Skan  const unsigned char *ufrom = (const unsigned char *) from;
306169695Skan  double dto;
307169695Skan  long exponent;
308169695Skan  unsigned long mant;
309169695Skan  unsigned int mant_bits, mant_off;
310169695Skan  int mant_bits_left;
311169695Skan  int special_exponent;		/* It's a NaN, denorm or zero */
312169695Skan
313169695Skan  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
314169695Skan			fmt->exp_start, fmt->exp_len);
315169695Skan
316169695Skan  /* If the exponent indicates a NaN, we don't have information to
317169695Skan     decide what to do.  So we handle it like IEEE, except that we
318169695Skan     don't try to preserve the type of NaN.  FIXME.  */
319169695Skan  if ((unsigned long) exponent == fmt->exp_nan)
320169695Skan    {
321169695Skan      int nan;
322169695Skan
323169695Skan      mant_off = fmt->man_start;
324169695Skan      mant_bits_left = fmt->man_len;
325169695Skan      nan = 0;
326169695Skan      while (mant_bits_left > 0)
327169695Skan	{
328169695Skan	  mant_bits = min (mant_bits_left, 32);
329169695Skan
330169695Skan	  if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
331169695Skan			 mant_off, mant_bits) != 0)
332169695Skan	    {
333169695Skan	      /* This is a NaN.  */
334169695Skan	      nan = 1;
335169695Skan	      break;
336169695Skan	    }
337169695Skan
338169695Skan	  mant_off += mant_bits;
339169695Skan	  mant_bits_left -= mant_bits;
340169695Skan	}
341169695Skan
342169695Skan      /* On certain systems (such as GNU/Linux), the use of the
343169695Skan	 INFINITY macro below may generate a warning that can not be
344169695Skan	 silenced due to a bug in GCC (PR preprocessor/11931).  The
345169695Skan	 preprocessor fails to recognise the __extension__ keyword in
346169695Skan	 conjunction with the GNU/C99 extension for hexadecimal
347169695Skan	 floating point constants and will issue a warning when
348169695Skan	 compiling with -pedantic.  */
349169695Skan      if (nan)
350169695Skan	dto = NAN;
351169695Skan      else
352169695Skan	dto = INFINITY;
353169695Skan
354169695Skan      if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
355169695Skan	dto = -dto;
356169695Skan
357169695Skan      *to = dto;
358169695Skan
359169695Skan      return;
360169695Skan    }
361169695Skan
362169695Skan  mant_bits_left = fmt->man_len;
363169695Skan  mant_off = fmt->man_start;
364169695Skan  dto = 0.0;
365169695Skan
366169695Skan  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
367169695Skan
368169695Skan  /* Don't bias zero's, denorms or NaNs.  */
369169695Skan  if (!special_exponent)
370169695Skan    exponent -= fmt->exp_bias;
371169695Skan
372169695Skan  /* Build the result algebraically.  Might go infinite, underflow, etc;
373169695Skan     who cares. */
374169695Skan
375169695Skan  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
376169695Skan     increment the exponent by one to account for the integer bit.  */
377169695Skan
378169695Skan  if (!special_exponent)
379169695Skan    {
380169695Skan      if (fmt->intbit == floatformat_intbit_no)
381169695Skan	dto = ldexp (1.0, exponent);
382169695Skan      else
383169695Skan	exponent++;
384169695Skan    }
385169695Skan
386169695Skan  while (mant_bits_left > 0)
387169695Skan    {
388169695Skan      mant_bits = min (mant_bits_left, 32);
389169695Skan
390169695Skan      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
391169695Skan			 mant_off, mant_bits);
392169695Skan
393169695Skan      /* Handle denormalized numbers.  FIXME: What should we do for
394169695Skan	 non-IEEE formats?  */
395169695Skan      if (special_exponent && exponent == 0 && mant != 0)
396169695Skan	dto += ldexp ((double)mant,
397169695Skan		      (- fmt->exp_bias
398169695Skan		       - mant_bits
399169695Skan		       - (mant_off - fmt->man_start)
400169695Skan		       + 1));
401169695Skan      else
402169695Skan	dto += ldexp ((double)mant, exponent - mant_bits);
403169695Skan      if (exponent != 0)
404169695Skan	exponent -= mant_bits;
405169695Skan      mant_off += mant_bits;
406169695Skan      mant_bits_left -= mant_bits;
407169695Skan    }
408169695Skan
409169695Skan  /* Negate it if negative.  */
410169695Skan  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
411169695Skan    dto = -dto;
412169695Skan  *to = dto;
413169695Skan}
414169695Skan
415169695Skanstatic void put_field (unsigned char *, enum floatformat_byteorders,
416169695Skan                       unsigned int,
417169695Skan                       unsigned int,
418169695Skan                       unsigned int,
419169695Skan                       unsigned long);
420169695Skan
421169695Skan/* Set a field which starts at START and is LEN bits long.  DATA and
422169695Skan   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
423169695Skanstatic void
424169695Skanput_field (unsigned char *data, enum floatformat_byteorders order,
425169695Skan           unsigned int total_len, unsigned int start, unsigned int len,
426169695Skan           unsigned long stuff_to_put)
427169695Skan{
428169695Skan  unsigned int cur_byte;
429259705Spfg  int lo_bit, hi_bit;
430259705Spfg  int nextbyte = (order == floatformat_little) ? 1 : -1;
431169695Skan
432259705Spfg  /* Start is in big-endian bit order!  Fix that first.  */
433259705Spfg  start = total_len - (start + len);
434259705Spfg
435169695Skan  /* Start at the least significant part of the field.  */
436169695Skan  if (order == floatformat_little)
437259705Spfg    cur_byte = start / FLOATFORMAT_CHAR_BIT;
438169695Skan  else
439259705Spfg    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
440169695Skan
441259705Spfg  lo_bit = start % FLOATFORMAT_CHAR_BIT;
442259705Spfg  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
443259705Spfg
444259705Spfg  do
445169695Skan    {
446259705Spfg      unsigned char *byte_ptr = data + cur_byte;
447259705Spfg      unsigned int bits = hi_bit - lo_bit;
448259705Spfg      unsigned int mask = ((1 << bits) - 1) << lo_bit;
449259705Spfg      *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
450259705Spfg      stuff_to_put >>= bits;
451259705Spfg      len -= bits;
452259705Spfg      cur_byte += nextbyte;
453259705Spfg      lo_bit = 0;
454259705Spfg      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
455169695Skan    }
456259705Spfg  while (len != 0);
457169695Skan}
458169695Skan
459169695Skan/* The converse: convert the double *FROM to an extended float
460169695Skan   and store where TO points.  Neither FROM nor TO have any alignment
461169695Skan   restrictions.  */
462169695Skan
463169695Skanvoid
464169695Skanfloatformat_from_double (const struct floatformat *fmt,
465169695Skan                         const double *from, void *to)
466169695Skan{
467169695Skan  double dfrom;
468169695Skan  int exponent;
469169695Skan  double mant;
470169695Skan  unsigned int mant_bits, mant_off;
471169695Skan  int mant_bits_left;
472169695Skan  unsigned char *uto = (unsigned char *) to;
473169695Skan
474169695Skan  dfrom = *from;
475169695Skan  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
476169695Skan
477169695Skan  /* If negative, set the sign bit.  */
478169695Skan  if (dfrom < 0)
479169695Skan    {
480169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
481169695Skan      dfrom = -dfrom;
482169695Skan    }
483169695Skan
484169695Skan  if (dfrom == 0)
485169695Skan    {
486169695Skan      /* 0.0.  */
487169695Skan      return;
488169695Skan    }
489169695Skan
490169695Skan  if (dfrom != dfrom)
491169695Skan    {
492169695Skan      /* NaN.  */
493169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
494169695Skan		 fmt->exp_len, fmt->exp_nan);
495169695Skan      /* Be sure it's not infinity, but NaN value is irrelevant.  */
496169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
497169695Skan		 32, 1);
498169695Skan      return;
499169695Skan    }
500169695Skan
501169695Skan  if (dfrom + dfrom == dfrom)
502169695Skan    {
503169695Skan      /* This can only happen for an infinite value (or zero, which we
504169695Skan	 already handled above).  */
505169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
506169695Skan		 fmt->exp_len, fmt->exp_nan);
507169695Skan      return;
508169695Skan    }
509169695Skan
510169695Skan  mant = frexp (dfrom, &exponent);
511169695Skan  if (exponent + fmt->exp_bias - 1 > 0)
512169695Skan    put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
513169695Skan	       fmt->exp_len, exponent + fmt->exp_bias - 1);
514169695Skan  else
515169695Skan    {
516169695Skan      /* Handle a denormalized number.  FIXME: What should we do for
517169695Skan	 non-IEEE formats?  */
518169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
519169695Skan		 fmt->exp_len, 0);
520169695Skan      mant = ldexp (mant, exponent + fmt->exp_bias - 1);
521169695Skan    }
522169695Skan
523169695Skan  mant_bits_left = fmt->man_len;
524169695Skan  mant_off = fmt->man_start;
525169695Skan  while (mant_bits_left > 0)
526169695Skan    {
527169695Skan      unsigned long mant_long;
528169695Skan      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
529169695Skan
530169695Skan      mant *= 4294967296.0;
531169695Skan      mant_long = (unsigned long)mant;
532169695Skan      mant -= mant_long;
533169695Skan
534169695Skan      /* If the integer bit is implicit, and we are not creating a
535169695Skan	 denormalized number, then we need to discard it.  */
536169695Skan      if ((unsigned int) mant_bits_left == fmt->man_len
537169695Skan	  && fmt->intbit == floatformat_intbit_no
538169695Skan	  && exponent + fmt->exp_bias - 1 > 0)
539169695Skan	{
540169695Skan	  mant_long &= 0x7fffffff;
541169695Skan	  mant_bits -= 1;
542169695Skan	}
543169695Skan      else if (mant_bits < 32)
544169695Skan	{
545169695Skan	  /* The bits we want are in the most significant MANT_BITS bits of
546169695Skan	     mant_long.  Move them to the least significant.  */
547169695Skan	  mant_long >>= 32 - mant_bits;
548169695Skan	}
549169695Skan
550169695Skan      put_field (uto, fmt->byteorder, fmt->totalsize,
551169695Skan		 mant_off, mant_bits, mant_long);
552169695Skan      mant_off += mant_bits;
553169695Skan      mant_bits_left -= mant_bits;
554169695Skan    }
555169695Skan}
556169695Skan
557169695Skan/* Return non-zero iff the data at FROM is a valid number in format FMT.  */
558169695Skan
559169695Skanint
560169695Skanfloatformat_is_valid (const struct floatformat *fmt, const void *from)
561169695Skan{
562169695Skan  return fmt->is_valid (fmt, from);
563169695Skan}
564169695Skan
565169695Skan
566169695Skan#ifdef IEEE_DEBUG
567169695Skan
568169695Skan#include <stdio.h>
569169695Skan
570169695Skan/* This is to be run on a host which uses IEEE floating point.  */
571169695Skan
572169695Skanvoid
573169695Skanieee_test (double n)
574169695Skan{
575169695Skan  double result;
576169695Skan
577169695Skan  floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
578169695Skan  if ((n != result && (! isnan (n) || ! isnan (result)))
579169695Skan      || (n < 0 && result >= 0)
580169695Skan      || (n >= 0 && result < 0))
581169695Skan    printf ("Differ(to): %.20g -> %.20g\n", n, result);
582169695Skan
583169695Skan  floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
584169695Skan  if ((n != result && (! isnan (n) || ! isnan (result)))
585169695Skan      || (n < 0 && result >= 0)
586169695Skan      || (n >= 0 && result < 0))
587169695Skan    printf ("Differ(from): %.20g -> %.20g\n", n, result);
588169695Skan
589169695Skan#if 0
590169695Skan  {
591169695Skan    char exten[16];
592169695Skan
593169695Skan    floatformat_from_double (&floatformat_m68881_ext, &n, exten);
594169695Skan    floatformat_to_double (&floatformat_m68881_ext, exten, &result);
595169695Skan    if (n != result)
596169695Skan      printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
597169695Skan  }
598169695Skan#endif
599169695Skan
600169695Skan#if IEEE_DEBUG > 1
601169695Skan  /* This is to be run on a host which uses 68881 format.  */
602169695Skan  {
603169695Skan    long double ex = *(long double *)exten;
604169695Skan    if (ex != n)
605169695Skan      printf ("Differ(from vs. extended): %.20g\n", n);
606169695Skan  }
607169695Skan#endif
608169695Skan}
609169695Skan
610169695Skanint
611169695Skanmain (void)
612169695Skan{
613169695Skan  ieee_test (0.0);
614169695Skan  ieee_test (0.5);
615169695Skan  ieee_test (256.0);
616169695Skan  ieee_test (0.12345);
617169695Skan  ieee_test (234235.78907234);
618169695Skan  ieee_test (-512.0);
619169695Skan  ieee_test (-0.004321);
620169695Skan  ieee_test (1.2E-70);
621169695Skan  ieee_test (1.2E-316);
622169695Skan  ieee_test (4.9406564584124654E-324);
623169695Skan  ieee_test (- 4.9406564584124654E-324);
624169695Skan  ieee_test (- 0.0);
625169695Skan  ieee_test (- INFINITY);
626169695Skan  ieee_test (- NAN);
627169695Skan  ieee_test (INFINITY);
628169695Skan  ieee_test (NAN);
629169695Skan  return 0;
630169695Skan}
631169695Skan#endif
632