Coverage Report

Created: 2025-06-24 06:45

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