OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [libiberty/] [floatformat.c] - Blame information for rev 168

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

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

powered by: WebSVN 2.1.0

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