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