Subversion Repositories Kolibri OS

Rev

Rev 5191 | Details | Compare with Previous | Last modification | View Log | RSS feed

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