Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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