]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/floatformat.c
README: Mention changes to Makefile.in and functions.texi.
[thirdparty/gcc.git] / libiberty / floatformat.c
CommitLineData
6599da04 1/* IEEE floating point support routines, for GDB, the GNU Debugger.
12c61ac3 2 Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
e89b6c1c 3 Free Software Foundation, Inc.
6599da04
JM
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
ee58dffd 19Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
6599da04 20
bee6ab3e
ILT
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
12c61ac3
RS
34/* On some platforms, <float.h> provides DBL_QNAN. */
35#ifdef STDC_HEADERS
36#include <float.h>
37#endif
38
c9ac9147 39#include "ansidecl.h"
bee6ab3e 40#include "libiberty.h"
6599da04 41#include "floatformat.h"
bee6ab3e
ILT
42
43#ifndef INFINITY
44#ifdef HUGE_VAL
45#define INFINITY HUGE_VAL
6599da04 46#else
bee6ab3e
ILT
47#define INFINITY (1.0 / 0.0)
48#endif
49#endif
50
51#ifndef NAN
12c61ac3
RS
52#ifdef DBL_QNAN
53#define NAN DBL_QNAN
54#else
bee6ab3e 55#define NAN (0.0 / 0.0)
6599da04 56#endif
12c61ac3 57#endif
6599da04 58
da59326f 59static int mant_bits_set (const struct floatformat *, const unsigned char *);
6da879de
GDR
60static unsigned long get_field (const unsigned char *,
61 enum floatformat_byteorders,
62 unsigned int,
63 unsigned int,
64 unsigned int);
65static int floatformat_always_valid (const struct floatformat *fmt,
e89b6c1c 66 const void *from);
83c07342
AC
67
68static int
6da879de 69floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
e89b6c1c 70 const void *from ATTRIBUTE_UNUSED)
83c07342
AC
71{
72 return 1;
73}
74
6599da04
JM
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. */
81const struct floatformat floatformat_ieee_single_big =
82{
0b72c3df
AC
83 floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
84 floatformat_intbit_no,
83c07342 85 "floatformat_ieee_single_big",
da59326f
JM
86 floatformat_always_valid,
87 NULL
6599da04
JM
88};
89const struct floatformat floatformat_ieee_single_little =
90{
0b72c3df
AC
91 floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
92 floatformat_intbit_no,
83c07342 93 "floatformat_ieee_single_little",
da59326f
JM
94 floatformat_always_valid,
95 NULL
6599da04
JM
96};
97const struct floatformat floatformat_ieee_double_big =
98{
0b72c3df
AC
99 floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
100 floatformat_intbit_no,
83c07342 101 "floatformat_ieee_double_big",
da59326f
JM
102 floatformat_always_valid,
103 NULL
6599da04
JM
104};
105const struct floatformat floatformat_ieee_double_little =
106{
0b72c3df
AC
107 floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
108 floatformat_intbit_no,
83c07342 109 "floatformat_ieee_double_little",
da59326f
JM
110 floatformat_always_valid,
111 NULL
6599da04
JM
112};
113
114/* floatformat for IEEE double, little endian byte order, with big endian word
115 ordering, as on the ARM. */
116
117const struct floatformat floatformat_ieee_double_littlebyte_bigword =
118{
0b72c3df
AC
119 floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
120 floatformat_intbit_no,
83c07342 121 "floatformat_ieee_double_littlebyte_bigword",
da59326f
JM
122 floatformat_always_valid,
123 NULL
6599da04
JM
124};
125
0432a5de
MK
126/* floatformat for VAX. Not quite IEEE, but close enough. */
127
128const 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",
da59326f
JM
133 floatformat_always_valid,
134 NULL
0432a5de
MK
135};
136const 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",
da59326f
JM
141 floatformat_always_valid,
142 NULL
0432a5de
MK
143};
144const 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",
da59326f
JM
149 floatformat_always_valid,
150 NULL
0432a5de
MK
151};
152
e89b6c1c
MK
153static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
154 const void *from);
83c07342
AC
155
156static int
e89b6c1c 157floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
83c07342
AC
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;
573b07c7 164 const unsigned char *ufrom = (const unsigned char *) from;
e89b6c1c 165
83c07342
AC
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);
e89b6c1c 170
83c07342
AC
171 if ((exponent == 0) != (int_bit == 0))
172 return 0;
173 else
174 return 1;
175}
176
6599da04
JM
177const struct floatformat floatformat_i387_ext =
178{
179 floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
0b72c3df 180 floatformat_intbit_yes,
83c07342 181 "floatformat_i387_ext",
da59326f
JM
182 floatformat_i387_ext_is_valid,
183 NULL
6599da04
JM
184};
185const struct floatformat floatformat_m68881_ext =
186{
187 /* Note that the bits from 16 to 31 are unused. */
0b72c3df
AC
188 floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
189 floatformat_intbit_yes,
83c07342 190 "floatformat_m68881_ext",
da59326f
JM
191 floatformat_always_valid,
192 NULL
6599da04
JM
193};
194const 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,
0b72c3df 198 floatformat_intbit_yes,
83c07342 199 "floatformat_i960_ext",
da59326f
JM
200 floatformat_always_valid,
201 NULL
6599da04
JM
202};
203const struct floatformat floatformat_m88110_ext =
204{
0310e5ac
AC
205 floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
206 floatformat_intbit_yes,
83c07342 207 "floatformat_m88110_ext",
da59326f
JM
208 floatformat_always_valid,
209 NULL
0310e5ac
AC
210};
211const struct floatformat floatformat_m88110_harris_ext =
212{
6599da04
JM
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,
0b72c3df 216 floatformat_intbit_no,
83c07342 217 "floatformat_m88110_ext_harris",
da59326f
JM
218 floatformat_always_valid,
219 NULL
6599da04 220};
0310e5ac
AC
221const 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,
83c07342 226 "floatformat_arm_ext_big",
da59326f
JM
227 floatformat_always_valid,
228 NULL
0310e5ac
AC
229};
230const 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,
83c07342 235 "floatformat_arm_ext_littlebyte_bigword",
da59326f
JM
236 floatformat_always_valid,
237 NULL
0310e5ac
AC
238};
239const struct floatformat floatformat_ia64_spill_big =
240{
241 floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
242 floatformat_intbit_yes,
83c07342 243 "floatformat_ia64_spill_big",
da59326f
JM
244 floatformat_always_valid,
245 NULL
0310e5ac
AC
246};
247const struct floatformat floatformat_ia64_spill_little =
248{
249 floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
250 floatformat_intbit_yes,
83c07342 251 "floatformat_ia64_spill_little",
da59326f
JM
252 floatformat_always_valid,
253 NULL
0310e5ac
AC
254};
255const struct floatformat floatformat_ia64_quad_big =
256{
257 floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
258 floatformat_intbit_no,
83c07342 259 "floatformat_ia64_quad_big",
da59326f
JM
260 floatformat_always_valid,
261 NULL
0310e5ac
AC
262};
263const struct floatformat floatformat_ia64_quad_little =
264{
265 floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
266 floatformat_intbit_no,
83c07342 267 "floatformat_ia64_quad_little",
da59326f
JM
268 floatformat_always_valid,
269 NULL
270};
271
272static int
273floatformat_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
983a6f8d 286 if ((unsigned long) top_exp == hfmt->exp_nan)
da59326f
JM
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). */
983a6f8d 295 if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
da59326f 296 {
da59326f
JM
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;
983a6f8d 318 for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
da59326f
JM
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
358const 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",
983a6f8d 363 floatformat_ibm_long_double_is_valid,
da59326f 364 &floatformat_ieee_double_big
0310e5ac 365};
6599da04 366\f
36b82060
JB
367
368#ifndef min
369#define min(a, b) ((a) < (b) ? (a) : (b))
370#endif
371
da59326f
JM
372/* Return 1 if any bits are explicitly set in the mantissa of UFROM,
373 format FMT, 0 otherwise. */
374static int
375mant_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
9c8860c3 396/* Extract a field which starts at START and is LEN bits long. DATA and
6599da04
JM
397 TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
398static unsigned long
6da879de
GDR
399get_field (const unsigned char *data, enum floatformat_byteorders order,
400 unsigned int total_len, unsigned int start, unsigned int len)
6599da04 401{
36b82060 402 unsigned long result = 0;
6599da04 403 unsigned int cur_byte;
36b82060
JB
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);
6599da04
JM
409
410 /* Start at the least significant part of the field. */
6599da04 411 if (order == floatformat_little)
36b82060 412 cur_byte = start / FLOATFORMAT_CHAR_BIT;
6599da04 413 else
36b82060 414 cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
6599da04 415
36b82060
JB
416 lo_bit = start % FLOATFORMAT_CHAR_BIT;
417 hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
418
419 do
6599da04 420 {
36b82060
JB
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);
6599da04 430 }
36b82060
JB
431 while (len != 0);
432
6599da04
JM
433 return result;
434}
435
6599da04
JM
436/* Convert from FMT to a double.
437 FROM is the address of the extended float.
438 Store the double in *TO. */
439
440void
6da879de 441floatformat_to_double (const struct floatformat *fmt,
e89b6c1c 442 const void *from, double *to)
6599da04 443{
573b07c7 444 const unsigned char *ufrom = (const unsigned char *) from;
6599da04
JM
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
da59326f
JM
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
6599da04
JM
456 exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
457 fmt->exp_start, fmt->exp_len);
bee6ab3e
ILT
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 {
da59326f 464 int nan = mant_bits_set (fmt, ufrom);
bee6ab3e 465
72f93778
BE
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. */
bee6ab3e
ILT
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 }
6599da04
JM
485
486 mant_bits_left = fmt->man_len;
487 mant_off = fmt->man_start;
488 dto = 0.0;
489
5ad5a984 490 special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
6599da04
JM
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)
087aa398
KG
503 {
504 if (fmt->intbit == floatformat_intbit_no)
505 dto = ldexp (1.0, exponent);
506 else
507 exponent++;
508 }
6599da04
JM
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
bee6ab3e
ILT
517 /* Handle denormalized numbers. FIXME: What should we do for
518 non-IEEE formats? */
9fff6432 519 if (special_exponent && exponent == 0 && mant != 0)
bee6ab3e
ILT
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;
6599da04
JM
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\f
6da879de
GDR
539static void put_field (unsigned char *, enum floatformat_byteorders,
540 unsigned int,
541 unsigned int,
542 unsigned int,
543 unsigned long);
6599da04 544
9c8860c3 545/* Set a field which starts at START and is LEN bits long. DATA and
6599da04
JM
546 TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
547static void
6da879de
GDR
548put_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)
6599da04
JM
551{
552 unsigned int cur_byte;
36b82060
JB
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);
6599da04
JM
558
559 /* Start at the least significant part of the field. */
6599da04 560 if (order == floatformat_little)
36b82060 561 cur_byte = start / FLOATFORMAT_CHAR_BIT;
6599da04 562 else
36b82060 563 cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
6599da04 564
36b82060
JB
565 lo_bit = start % FLOATFORMAT_CHAR_BIT;
566 hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
567
568 do
6599da04 569 {
36b82060
JB
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);
6599da04 579 }
36b82060 580 while (len != 0);
6599da04
JM
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
587void
6da879de 588floatformat_from_double (const struct floatformat *fmt,
e89b6c1c 589 const double *from, void *to)
6599da04
JM
590{
591 double dfrom;
592 int exponent;
593 double mant;
594 unsigned int mant_bits, mant_off;
595 int mant_bits_left;
573b07c7 596 unsigned char *uto = (unsigned char *) to;
6599da04 597
bee6ab3e 598 dfrom = *from;
6599da04 599 memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
bee6ab3e 600
da59326f
JM
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
bee6ab3e
ILT
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
6599da04 612 if (dfrom == 0)
bee6ab3e
ILT
613 {
614 /* 0.0. */
615 return;
616 }
617
6599da04
JM
618 if (dfrom != dfrom)
619 {
bee6ab3e 620 /* NaN. */
6599da04
JM
621 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
622 fmt->exp_len, fmt->exp_nan);
bee6ab3e 623 /* Be sure it's not infinity, but NaN value is irrelevant. */
6599da04
JM
624 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
625 32, 1);
626 return;
627 }
628
bee6ab3e 629 if (dfrom + dfrom == dfrom)
6599da04 630 {
bee6ab3e
ILT
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;
6599da04
JM
636 }
637
6599da04 638 mant = frexp (dfrom, &exponent);
bee6ab3e
ILT
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 }
6599da04
JM
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
bee6ab3e
ILT
662 /* If the integer bit is implicit, and we are not creating a
663 denormalized number, then we need to discard it. */
5ad5a984 664 if ((unsigned int) mant_bits_left == fmt->man_len
bee6ab3e
ILT
665 && fmt->intbit == floatformat_intbit_no
666 && exponent + fmt->exp_bias - 1 > 0)
6599da04
JM
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
9c8860c3
DJ
685/* Return non-zero iff the data at FROM is a valid number in format FMT. */
686
687int
e89b6c1c 688floatformat_is_valid (const struct floatformat *fmt, const void *from)
9c8860c3 689{
83c07342 690 return fmt->is_valid (fmt, from);
9c8860c3
DJ
691}
692
6599da04
JM
693
694#ifdef IEEE_DEBUG
695
bee6ab3e
ILT
696#include <stdio.h>
697
6599da04
JM
698/* This is to be run on a host which uses IEEE floating point. */
699
700void
6da879de 701ieee_test (double n)
6599da04
JM
702{
703 double result;
6599da04 704
e89b6c1c 705 floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
bee6ab3e
ILT
706 if ((n != result && (! isnan (n) || ! isnan (result)))
707 || (n < 0 && result >= 0)
708 || (n >= 0 && result < 0))
6599da04 709 printf ("Differ(to): %.20g -> %.20g\n", n, result);
bee6ab3e 710
e89b6c1c 711 floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
bee6ab3e
ILT
712 if ((n != result && (! isnan (n) || ! isnan (result)))
713 || (n < 0 && result >= 0)
714 || (n >= 0 && result < 0))
6599da04
JM
715 printf ("Differ(from): %.20g -> %.20g\n", n, result);
716
bee6ab3e
ILT
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
6599da04
JM
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
738int
6da879de 739main (void)
6599da04 740{
bee6ab3e 741 ieee_test (0.0);
6599da04
JM
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);
bee6ab3e
ILT
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);
6599da04
JM
757 return 0;
758}
759#endif