OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [libiberty/] [floatformat.c] - Blame information for rev 241

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 khays
/* IEEE floating point support routines, for GDB, the GNU Debugger.
2
   Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006, 2010
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 <math.h>
29
 
30
#ifdef HAVE_STRING_H
31
#include <string.h>
32
#endif
33
 
34
/* On some platforms, <float.h> provides DBL_QNAN.  */
35
#ifdef STDC_HEADERS
36
#include <float.h>
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 =
375
{
376
  floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
377
  floatformat_intbit_no,
378
  "floatformat_ibm_long_double",
379
  floatformat_ibm_long_double_is_valid,
380
  &floatformat_ieee_double_big
381
};
382
 
383
 
384
#ifndef min
385
#define min(a, b) ((a) < (b) ? (a) : (b))
386
#endif
387
 
388
/* Return 1 if any bits are explicitly set in the mantissa of UFROM,
389
   format FMT, 0 otherwise.  */
390
static int
391
mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
392
{
393
  unsigned int mant_bits, mant_off;
394
  int mant_bits_left;
395
 
396
  mant_off = fmt->man_start;
397
  mant_bits_left = fmt->man_len;
398
  while (mant_bits_left > 0)
399
    {
400
      mant_bits = min (mant_bits_left, 32);
401
 
402
      if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
403
                     mant_off, mant_bits) != 0)
404
        return 1;
405
 
406
      mant_off += mant_bits;
407
      mant_bits_left -= mant_bits;
408
    }
409
  return 0;
410
}
411
 
412
/* Extract a field which starts at START and is LEN bits long.  DATA and
413
   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
414
static unsigned long
415
get_field (const unsigned char *data, enum floatformat_byteorders order,
416
           unsigned int total_len, unsigned int start, unsigned int len)
417
{
418
  unsigned long result = 0;
419
  unsigned int cur_byte;
420
  int lo_bit, hi_bit, cur_bitshift = 0;
421
  int nextbyte = (order == floatformat_little) ? 1 : -1;
422
 
423
  /* Start is in big-endian bit order!  Fix that first.  */
424
  start = total_len - (start + len);
425
 
426
  /* Start at the least significant part of the field.  */
427
  if (order == floatformat_little)
428
    cur_byte = start / FLOATFORMAT_CHAR_BIT;
429
  else
430
    cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
431
 
432
  lo_bit = start % FLOATFORMAT_CHAR_BIT;
433
  hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
434
 
435
  do
436
    {
437
      unsigned int shifted = *(data + cur_byte) >> lo_bit;
438
      unsigned int bits = hi_bit - lo_bit;
439
      unsigned int mask = (1 << bits) - 1;
440
      result |= (shifted & mask) << cur_bitshift;
441
      len -= bits;
442
      cur_bitshift += bits;
443
      cur_byte += nextbyte;
444
      lo_bit = 0;
445
      hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
446
    }
447
  while (len != 0);
448
 
449
  return result;
450
}
451
 
452
/* Convert from FMT to a double.
453
   FROM is the address of the extended float.
454
   Store the double in *TO.  */
455
 
456
void
457
floatformat_to_double (const struct floatformat *fmt,
458
                       const void *from, double *to)
459
{
460
  const unsigned char *ufrom = (const unsigned char *) from;
461
  double dto;
462
  long exponent;
463
  unsigned long mant;
464
  unsigned int mant_bits, mant_off;
465
  int mant_bits_left;
466
  int special_exponent;         /* It's a NaN, denorm or zero */
467
 
468
  /* Split values are not handled specially, since the top half has
469
     the correctly rounded double value (in the only supported case of
470
     split values).  */
471
 
472
  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
473
                        fmt->exp_start, fmt->exp_len);
474
 
475
  /* If the exponent indicates a NaN, we don't have information to
476
     decide what to do.  So we handle it like IEEE, except that we
477
     don't try to preserve the type of NaN.  FIXME.  */
478
  if ((unsigned long) exponent == fmt->exp_nan)
479
    {
480
      int nan = mant_bits_set (fmt, ufrom);
481
 
482
      /* On certain systems (such as GNU/Linux), the use of the
483
         INFINITY macro below may generate a warning that can not be
484
         silenced due to a bug in GCC (PR preprocessor/11931).  The
485
         preprocessor fails to recognise the __extension__ keyword in
486
         conjunction with the GNU/C99 extension for hexadecimal
487
         floating point constants and will issue a warning when
488
         compiling with -pedantic.  */
489
      if (nan)
490
        dto = NAN;
491
      else
492
        dto = INFINITY;
493
 
494
      if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
495
        dto = -dto;
496
 
497
      *to = dto;
498
 
499
      return;
500
    }
501
 
502
  mant_bits_left = fmt->man_len;
503
  mant_off = fmt->man_start;
504
  dto = 0.0;
505
 
506
  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
507
 
508
  /* Don't bias zero's, denorms or NaNs.  */
509
  if (!special_exponent)
510
    exponent -= fmt->exp_bias;
511
 
512
  /* Build the result algebraically.  Might go infinite, underflow, etc;
513
     who cares. */
514
 
515
  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
516
     increment the exponent by one to account for the integer bit.  */
517
 
518
  if (!special_exponent)
519
    {
520
      if (fmt->intbit == floatformat_intbit_no)
521
        dto = ldexp (1.0, exponent);
522
      else
523
        exponent++;
524
    }
525
 
526
  while (mant_bits_left > 0)
527
    {
528
      mant_bits = min (mant_bits_left, 32);
529
 
530
      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
531
                         mant_off, mant_bits);
532
 
533
      /* Handle denormalized numbers.  FIXME: What should we do for
534
         non-IEEE formats?  */
535
      if (special_exponent && exponent == 0 && mant != 0)
536
        dto += ldexp ((double)mant,
537
                      (- fmt->exp_bias
538
                       - mant_bits
539
                       - (mant_off - fmt->man_start)
540
                       + 1));
541
      else
542
        dto += ldexp ((double)mant, exponent - mant_bits);
543
      if (exponent != 0)
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 <stdio.h>
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 (256.0);
760
  ieee_test (0.12345);
761
  ieee_test (234235.78907234);
762
  ieee_test (-512.0);
763
  ieee_test (-0.004321);
764
  ieee_test (1.2E-70);
765
  ieee_test (1.2E-316);
766
  ieee_test (4.9406564584124654E-324);
767
  ieee_test (- 4.9406564584124654E-324);
768
  ieee_test (- 0.0);
769
  ieee_test (- INFINITY);
770
  ieee_test (- NAN);
771
  ieee_test (INFINITY);
772
  ieee_test (NAN);
773
  return 0;
774
}
775
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.