1169695Skan/* IEEE floating point support routines, for GDB, the GNU Debugger. 2169695Skan Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006 3169695Skan Free Software Foundation, Inc. 4169695Skan 5169695SkanThis file is part of GDB. 6169695Skan 7169695SkanThis program is free software; you can redistribute it and/or modify 8169695Skanit under the terms of the GNU General Public License as published by 9169695Skanthe Free Software Foundation; either version 2 of the License, or 10169695Skan(at your option) any later version. 11169695Skan 12169695SkanThis program is distributed in the hope that it will be useful, 13169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 14169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15169695SkanGNU General Public License for more details. 16169695Skan 17169695SkanYou should have received a copy of the GNU General Public License 18169695Skanalong with this program; if not, write to the Free Software 19169695SkanFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20169695Skan 21169695Skan/* This is needed to pick up the NAN macro on some systems. */ 22169695Skan#define _GNU_SOURCE 23169695Skan 24169695Skan#ifdef HAVE_CONFIG_H 25169695Skan#include "config.h" 26169695Skan#endif 27169695Skan 28169695Skan#include <math.h> 29169695Skan 30169695Skan#ifdef HAVE_STRING_H 31169695Skan#include <string.h> 32169695Skan#endif 33169695Skan 34169695Skan/* On some platforms, <float.h> provides DBL_QNAN. */ 35169695Skan#ifdef STDC_HEADERS 36169695Skan#include <float.h> 37169695Skan#endif 38169695Skan 39169695Skan#include "ansidecl.h" 40169695Skan#include "libiberty.h" 41169695Skan#include "floatformat.h" 42169695Skan 43169695Skan#ifndef INFINITY 44169695Skan#ifdef HUGE_VAL 45169695Skan#define INFINITY HUGE_VAL 46169695Skan#else 47169695Skan#define INFINITY (1.0 / 0.0) 48169695Skan#endif 49169695Skan#endif 50169695Skan 51169695Skan#ifndef NAN 52169695Skan#ifdef DBL_QNAN 53169695Skan#define NAN DBL_QNAN 54169695Skan#else 55169695Skan#define NAN (0.0 / 0.0) 56169695Skan#endif 57169695Skan#endif 58169695Skan 59169695Skanstatic unsigned long get_field (const unsigned char *, 60169695Skan enum floatformat_byteorders, 61169695Skan unsigned int, 62169695Skan unsigned int, 63169695Skan unsigned int); 64169695Skanstatic int floatformat_always_valid (const struct floatformat *fmt, 65169695Skan const void *from); 66169695Skan 67169695Skanstatic int 68169695Skanfloatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED, 69169695Skan const void *from ATTRIBUTE_UNUSED) 70169695Skan{ 71169695Skan return 1; 72169695Skan} 73169695Skan 74169695Skan/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not 75169695Skan going to bother with trying to muck around with whether it is defined in 76169695Skan a system header, what we do if not, etc. */ 77169695Skan#define FLOATFORMAT_CHAR_BIT 8 78169695Skan 79169695Skan/* floatformats for IEEE single and double, big and little endian. */ 80169695Skanconst struct floatformat floatformat_ieee_single_big = 81169695Skan{ 82169695Skan floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, 83169695Skan floatformat_intbit_no, 84169695Skan "floatformat_ieee_single_big", 85169695Skan floatformat_always_valid 86169695Skan}; 87169695Skanconst struct floatformat floatformat_ieee_single_little = 88169695Skan{ 89169695Skan floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, 90169695Skan floatformat_intbit_no, 91169695Skan "floatformat_ieee_single_little", 92169695Skan floatformat_always_valid 93169695Skan}; 94169695Skanconst struct floatformat floatformat_ieee_double_big = 95169695Skan{ 96169695Skan floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, 97169695Skan floatformat_intbit_no, 98169695Skan "floatformat_ieee_double_big", 99169695Skan floatformat_always_valid 100169695Skan}; 101169695Skanconst struct floatformat floatformat_ieee_double_little = 102169695Skan{ 103169695Skan floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, 104169695Skan floatformat_intbit_no, 105169695Skan "floatformat_ieee_double_little", 106169695Skan floatformat_always_valid 107169695Skan}; 108169695Skan 109169695Skan/* floatformat for IEEE double, little endian byte order, with big endian word 110169695Skan ordering, as on the ARM. */ 111169695Skan 112169695Skanconst struct floatformat floatformat_ieee_double_littlebyte_bigword = 113169695Skan{ 114169695Skan floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52, 115169695Skan floatformat_intbit_no, 116169695Skan "floatformat_ieee_double_littlebyte_bigword", 117169695Skan floatformat_always_valid 118169695Skan}; 119169695Skan 120169695Skan/* floatformat for VAX. Not quite IEEE, but close enough. */ 121169695Skan 122169695Skanconst struct floatformat floatformat_vax_f = 123169695Skan{ 124169695Skan floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23, 125169695Skan floatformat_intbit_no, 126169695Skan "floatformat_vax_f", 127169695Skan floatformat_always_valid 128169695Skan}; 129169695Skanconst struct floatformat floatformat_vax_d = 130169695Skan{ 131169695Skan floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55, 132169695Skan floatformat_intbit_no, 133169695Skan "floatformat_vax_d", 134169695Skan floatformat_always_valid 135169695Skan}; 136169695Skanconst struct floatformat floatformat_vax_g = 137169695Skan{ 138169695Skan floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52, 139169695Skan floatformat_intbit_no, 140169695Skan "floatformat_vax_g", 141169695Skan floatformat_always_valid 142169695Skan}; 143169695Skan 144169695Skanstatic int floatformat_i387_ext_is_valid (const struct floatformat *fmt, 145169695Skan const void *from); 146169695Skan 147169695Skanstatic int 148169695Skanfloatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from) 149169695Skan{ 150169695Skan /* In the i387 double-extended format, if the exponent is all ones, 151169695Skan then the integer bit must be set. If the exponent is neither 0 152169695Skan nor ~0, the intbit must also be set. Only if the exponent is 153169695Skan zero can it be zero, and then it must be zero. */ 154169695Skan unsigned long exponent, int_bit; 155169695Skan const unsigned char *ufrom = (const unsigned char *) from; 156169695Skan 157169695Skan exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 158169695Skan fmt->exp_start, fmt->exp_len); 159169695Skan int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize, 160169695Skan fmt->man_start, 1); 161169695Skan 162169695Skan if ((exponent == 0) != (int_bit == 0)) 163169695Skan return 0; 164169695Skan else 165169695Skan return 1; 166169695Skan} 167169695Skan 168169695Skanconst struct floatformat floatformat_i387_ext = 169169695Skan{ 170169695Skan floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, 171169695Skan floatformat_intbit_yes, 172169695Skan "floatformat_i387_ext", 173169695Skan floatformat_i387_ext_is_valid 174169695Skan}; 175169695Skanconst struct floatformat floatformat_m68881_ext = 176169695Skan{ 177169695Skan /* Note that the bits from 16 to 31 are unused. */ 178169695Skan floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, 179169695Skan floatformat_intbit_yes, 180169695Skan "floatformat_m68881_ext", 181169695Skan floatformat_always_valid 182169695Skan}; 183169695Skanconst struct floatformat floatformat_i960_ext = 184169695Skan{ 185169695Skan /* Note that the bits from 0 to 15 are unused. */ 186169695Skan floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64, 187169695Skan floatformat_intbit_yes, 188169695Skan "floatformat_i960_ext", 189169695Skan floatformat_always_valid 190169695Skan}; 191169695Skanconst struct floatformat floatformat_m88110_ext = 192169695Skan{ 193169695Skan floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, 194169695Skan floatformat_intbit_yes, 195169695Skan "floatformat_m88110_ext", 196169695Skan floatformat_always_valid 197169695Skan}; 198169695Skanconst struct floatformat floatformat_m88110_harris_ext = 199169695Skan{ 200169695Skan /* Harris uses raw format 128 bytes long, but the number is just an ieee 201169695Skan double, and the last 64 bits are wasted. */ 202169695Skan floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52, 203169695Skan floatformat_intbit_no, 204169695Skan "floatformat_m88110_ext_harris", 205169695Skan floatformat_always_valid 206169695Skan}; 207169695Skanconst struct floatformat floatformat_arm_ext_big = 208169695Skan{ 209169695Skan /* Bits 1 to 16 are unused. */ 210169695Skan floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, 211169695Skan floatformat_intbit_yes, 212169695Skan "floatformat_arm_ext_big", 213169695Skan floatformat_always_valid 214169695Skan}; 215169695Skanconst struct floatformat floatformat_arm_ext_littlebyte_bigword = 216169695Skan{ 217169695Skan /* Bits 1 to 16 are unused. */ 218169695Skan floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, 219169695Skan floatformat_intbit_yes, 220169695Skan "floatformat_arm_ext_littlebyte_bigword", 221169695Skan floatformat_always_valid 222169695Skan}; 223169695Skanconst struct floatformat floatformat_ia64_spill_big = 224169695Skan{ 225169695Skan floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, 226169695Skan floatformat_intbit_yes, 227169695Skan "floatformat_ia64_spill_big", 228169695Skan floatformat_always_valid 229169695Skan}; 230169695Skanconst struct floatformat floatformat_ia64_spill_little = 231169695Skan{ 232169695Skan floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, 233169695Skan floatformat_intbit_yes, 234169695Skan "floatformat_ia64_spill_little", 235169695Skan floatformat_always_valid 236169695Skan}; 237169695Skanconst struct floatformat floatformat_ia64_quad_big = 238169695Skan{ 239169695Skan floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, 240169695Skan floatformat_intbit_no, 241169695Skan "floatformat_ia64_quad_big", 242169695Skan floatformat_always_valid 243169695Skan}; 244169695Skanconst struct floatformat floatformat_ia64_quad_little = 245169695Skan{ 246169695Skan floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, 247169695Skan floatformat_intbit_no, 248169695Skan "floatformat_ia64_quad_little", 249169695Skan floatformat_always_valid 250169695Skan}; 251169695Skan 252259705Spfg 253259705Spfg#ifndef min 254259705Spfg#define min(a, b) ((a) < (b) ? (a) : (b)) 255259705Spfg#endif 256259705Spfg 257169695Skan/* Extract a field which starts at START and is LEN bits long. DATA and 258169695Skan TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 259169695Skanstatic unsigned long 260169695Skanget_field (const unsigned char *data, enum floatformat_byteorders order, 261169695Skan unsigned int total_len, unsigned int start, unsigned int len) 262169695Skan{ 263259705Spfg unsigned long result = 0; 264169695Skan unsigned int cur_byte; 265259705Spfg int lo_bit, hi_bit, cur_bitshift = 0; 266259705Spfg int nextbyte = (order == floatformat_little) ? 1 : -1; 267169695Skan 268259705Spfg /* Start is in big-endian bit order! Fix that first. */ 269259705Spfg start = total_len - (start + len); 270259705Spfg 271169695Skan /* Start at the least significant part of the field. */ 272169695Skan if (order == floatformat_little) 273259705Spfg cur_byte = start / FLOATFORMAT_CHAR_BIT; 274169695Skan else 275259705Spfg cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT; 276169695Skan 277259705Spfg lo_bit = start % FLOATFORMAT_CHAR_BIT; 278259705Spfg hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT); 279259705Spfg 280259705Spfg do 281169695Skan { 282259705Spfg unsigned int shifted = *(data + cur_byte) >> lo_bit; 283259705Spfg unsigned int bits = hi_bit - lo_bit; 284259705Spfg unsigned int mask = (1 << bits) - 1; 285259705Spfg result |= (shifted & mask) << cur_bitshift; 286259705Spfg len -= bits; 287259705Spfg cur_bitshift += bits; 288259705Spfg cur_byte += nextbyte; 289259705Spfg lo_bit = 0; 290259705Spfg hi_bit = min (len, FLOATFORMAT_CHAR_BIT); 291169695Skan } 292259705Spfg while (len != 0); 293259705Spfg 294169695Skan return result; 295169695Skan} 296169695Skan 297169695Skan/* Convert from FMT to a double. 298169695Skan FROM is the address of the extended float. 299169695Skan Store the double in *TO. */ 300169695Skan 301169695Skanvoid 302169695Skanfloatformat_to_double (const struct floatformat *fmt, 303169695Skan const void *from, double *to) 304169695Skan{ 305169695Skan const unsigned char *ufrom = (const unsigned char *) from; 306169695Skan double dto; 307169695Skan long exponent; 308169695Skan unsigned long mant; 309169695Skan unsigned int mant_bits, mant_off; 310169695Skan int mant_bits_left; 311169695Skan int special_exponent; /* It's a NaN, denorm or zero */ 312169695Skan 313169695Skan exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 314169695Skan fmt->exp_start, fmt->exp_len); 315169695Skan 316169695Skan /* If the exponent indicates a NaN, we don't have information to 317169695Skan decide what to do. So we handle it like IEEE, except that we 318169695Skan don't try to preserve the type of NaN. FIXME. */ 319169695Skan if ((unsigned long) exponent == fmt->exp_nan) 320169695Skan { 321169695Skan int nan; 322169695Skan 323169695Skan mant_off = fmt->man_start; 324169695Skan mant_bits_left = fmt->man_len; 325169695Skan nan = 0; 326169695Skan while (mant_bits_left > 0) 327169695Skan { 328169695Skan mant_bits = min (mant_bits_left, 32); 329169695Skan 330169695Skan if (get_field (ufrom, fmt->byteorder, fmt->totalsize, 331169695Skan mant_off, mant_bits) != 0) 332169695Skan { 333169695Skan /* This is a NaN. */ 334169695Skan nan = 1; 335169695Skan break; 336169695Skan } 337169695Skan 338169695Skan mant_off += mant_bits; 339169695Skan mant_bits_left -= mant_bits; 340169695Skan } 341169695Skan 342169695Skan /* On certain systems (such as GNU/Linux), the use of the 343169695Skan INFINITY macro below may generate a warning that can not be 344169695Skan silenced due to a bug in GCC (PR preprocessor/11931). The 345169695Skan preprocessor fails to recognise the __extension__ keyword in 346169695Skan conjunction with the GNU/C99 extension for hexadecimal 347169695Skan floating point constants and will issue a warning when 348169695Skan compiling with -pedantic. */ 349169695Skan if (nan) 350169695Skan dto = NAN; 351169695Skan else 352169695Skan dto = INFINITY; 353169695Skan 354169695Skan if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 355169695Skan dto = -dto; 356169695Skan 357169695Skan *to = dto; 358169695Skan 359169695Skan return; 360169695Skan } 361169695Skan 362169695Skan mant_bits_left = fmt->man_len; 363169695Skan mant_off = fmt->man_start; 364169695Skan dto = 0.0; 365169695Skan 366169695Skan special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan; 367169695Skan 368169695Skan /* Don't bias zero's, denorms or NaNs. */ 369169695Skan if (!special_exponent) 370169695Skan exponent -= fmt->exp_bias; 371169695Skan 372169695Skan /* Build the result algebraically. Might go infinite, underflow, etc; 373169695Skan who cares. */ 374169695Skan 375169695Skan /* If this format uses a hidden bit, explicitly add it in now. Otherwise, 376169695Skan increment the exponent by one to account for the integer bit. */ 377169695Skan 378169695Skan if (!special_exponent) 379169695Skan { 380169695Skan if (fmt->intbit == floatformat_intbit_no) 381169695Skan dto = ldexp (1.0, exponent); 382169695Skan else 383169695Skan exponent++; 384169695Skan } 385169695Skan 386169695Skan while (mant_bits_left > 0) 387169695Skan { 388169695Skan mant_bits = min (mant_bits_left, 32); 389169695Skan 390169695Skan mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, 391169695Skan mant_off, mant_bits); 392169695Skan 393169695Skan /* Handle denormalized numbers. FIXME: What should we do for 394169695Skan non-IEEE formats? */ 395169695Skan if (special_exponent && exponent == 0 && mant != 0) 396169695Skan dto += ldexp ((double)mant, 397169695Skan (- fmt->exp_bias 398169695Skan - mant_bits 399169695Skan - (mant_off - fmt->man_start) 400169695Skan + 1)); 401169695Skan else 402169695Skan dto += ldexp ((double)mant, exponent - mant_bits); 403169695Skan if (exponent != 0) 404169695Skan exponent -= mant_bits; 405169695Skan mant_off += mant_bits; 406169695Skan mant_bits_left -= mant_bits; 407169695Skan } 408169695Skan 409169695Skan /* Negate it if negative. */ 410169695Skan if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 411169695Skan dto = -dto; 412169695Skan *to = dto; 413169695Skan} 414169695Skan 415169695Skanstatic void put_field (unsigned char *, enum floatformat_byteorders, 416169695Skan unsigned int, 417169695Skan unsigned int, 418169695Skan unsigned int, 419169695Skan unsigned long); 420169695Skan 421169695Skan/* Set a field which starts at START and is LEN bits long. DATA and 422169695Skan TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 423169695Skanstatic void 424169695Skanput_field (unsigned char *data, enum floatformat_byteorders order, 425169695Skan unsigned int total_len, unsigned int start, unsigned int len, 426169695Skan unsigned long stuff_to_put) 427169695Skan{ 428169695Skan unsigned int cur_byte; 429259705Spfg int lo_bit, hi_bit; 430259705Spfg int nextbyte = (order == floatformat_little) ? 1 : -1; 431169695Skan 432259705Spfg /* Start is in big-endian bit order! Fix that first. */ 433259705Spfg start = total_len - (start + len); 434259705Spfg 435169695Skan /* Start at the least significant part of the field. */ 436169695Skan if (order == floatformat_little) 437259705Spfg cur_byte = start / FLOATFORMAT_CHAR_BIT; 438169695Skan else 439259705Spfg cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT; 440169695Skan 441259705Spfg lo_bit = start % FLOATFORMAT_CHAR_BIT; 442259705Spfg hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT); 443259705Spfg 444259705Spfg do 445169695Skan { 446259705Spfg unsigned char *byte_ptr = data + cur_byte; 447259705Spfg unsigned int bits = hi_bit - lo_bit; 448259705Spfg unsigned int mask = ((1 << bits) - 1) << lo_bit; 449259705Spfg *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask); 450259705Spfg stuff_to_put >>= bits; 451259705Spfg len -= bits; 452259705Spfg cur_byte += nextbyte; 453259705Spfg lo_bit = 0; 454259705Spfg hi_bit = min (len, FLOATFORMAT_CHAR_BIT); 455169695Skan } 456259705Spfg while (len != 0); 457169695Skan} 458169695Skan 459169695Skan/* The converse: convert the double *FROM to an extended float 460169695Skan and store where TO points. Neither FROM nor TO have any alignment 461169695Skan restrictions. */ 462169695Skan 463169695Skanvoid 464169695Skanfloatformat_from_double (const struct floatformat *fmt, 465169695Skan const double *from, void *to) 466169695Skan{ 467169695Skan double dfrom; 468169695Skan int exponent; 469169695Skan double mant; 470169695Skan unsigned int mant_bits, mant_off; 471169695Skan int mant_bits_left; 472169695Skan unsigned char *uto = (unsigned char *) to; 473169695Skan 474169695Skan dfrom = *from; 475169695Skan memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); 476169695Skan 477169695Skan /* If negative, set the sign bit. */ 478169695Skan if (dfrom < 0) 479169695Skan { 480169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); 481169695Skan dfrom = -dfrom; 482169695Skan } 483169695Skan 484169695Skan if (dfrom == 0) 485169695Skan { 486169695Skan /* 0.0. */ 487169695Skan return; 488169695Skan } 489169695Skan 490169695Skan if (dfrom != dfrom) 491169695Skan { 492169695Skan /* NaN. */ 493169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 494169695Skan fmt->exp_len, fmt->exp_nan); 495169695Skan /* Be sure it's not infinity, but NaN value is irrelevant. */ 496169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 497169695Skan 32, 1); 498169695Skan return; 499169695Skan } 500169695Skan 501169695Skan if (dfrom + dfrom == dfrom) 502169695Skan { 503169695Skan /* This can only happen for an infinite value (or zero, which we 504169695Skan already handled above). */ 505169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 506169695Skan fmt->exp_len, fmt->exp_nan); 507169695Skan return; 508169695Skan } 509169695Skan 510169695Skan mant = frexp (dfrom, &exponent); 511169695Skan if (exponent + fmt->exp_bias - 1 > 0) 512169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 513169695Skan fmt->exp_len, exponent + fmt->exp_bias - 1); 514169695Skan else 515169695Skan { 516169695Skan /* Handle a denormalized number. FIXME: What should we do for 517169695Skan non-IEEE formats? */ 518169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 519169695Skan fmt->exp_len, 0); 520169695Skan mant = ldexp (mant, exponent + fmt->exp_bias - 1); 521169695Skan } 522169695Skan 523169695Skan mant_bits_left = fmt->man_len; 524169695Skan mant_off = fmt->man_start; 525169695Skan while (mant_bits_left > 0) 526169695Skan { 527169695Skan unsigned long mant_long; 528169695Skan mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; 529169695Skan 530169695Skan mant *= 4294967296.0; 531169695Skan mant_long = (unsigned long)mant; 532169695Skan mant -= mant_long; 533169695Skan 534169695Skan /* If the integer bit is implicit, and we are not creating a 535169695Skan denormalized number, then we need to discard it. */ 536169695Skan if ((unsigned int) mant_bits_left == fmt->man_len 537169695Skan && fmt->intbit == floatformat_intbit_no 538169695Skan && exponent + fmt->exp_bias - 1 > 0) 539169695Skan { 540169695Skan mant_long &= 0x7fffffff; 541169695Skan mant_bits -= 1; 542169695Skan } 543169695Skan else if (mant_bits < 32) 544169695Skan { 545169695Skan /* The bits we want are in the most significant MANT_BITS bits of 546169695Skan mant_long. Move them to the least significant. */ 547169695Skan mant_long >>= 32 - mant_bits; 548169695Skan } 549169695Skan 550169695Skan put_field (uto, fmt->byteorder, fmt->totalsize, 551169695Skan mant_off, mant_bits, mant_long); 552169695Skan mant_off += mant_bits; 553169695Skan mant_bits_left -= mant_bits; 554169695Skan } 555169695Skan} 556169695Skan 557169695Skan/* Return non-zero iff the data at FROM is a valid number in format FMT. */ 558169695Skan 559169695Skanint 560169695Skanfloatformat_is_valid (const struct floatformat *fmt, const void *from) 561169695Skan{ 562169695Skan return fmt->is_valid (fmt, from); 563169695Skan} 564169695Skan 565169695Skan 566169695Skan#ifdef IEEE_DEBUG 567169695Skan 568169695Skan#include <stdio.h> 569169695Skan 570169695Skan/* This is to be run on a host which uses IEEE floating point. */ 571169695Skan 572169695Skanvoid 573169695Skanieee_test (double n) 574169695Skan{ 575169695Skan double result; 576169695Skan 577169695Skan floatformat_to_double (&floatformat_ieee_double_little, &n, &result); 578169695Skan if ((n != result && (! isnan (n) || ! isnan (result))) 579169695Skan || (n < 0 && result >= 0) 580169695Skan || (n >= 0 && result < 0)) 581169695Skan printf ("Differ(to): %.20g -> %.20g\n", n, result); 582169695Skan 583169695Skan floatformat_from_double (&floatformat_ieee_double_little, &n, &result); 584169695Skan if ((n != result && (! isnan (n) || ! isnan (result))) 585169695Skan || (n < 0 && result >= 0) 586169695Skan || (n >= 0 && result < 0)) 587169695Skan printf ("Differ(from): %.20g -> %.20g\n", n, result); 588169695Skan 589169695Skan#if 0 590169695Skan { 591169695Skan char exten[16]; 592169695Skan 593169695Skan floatformat_from_double (&floatformat_m68881_ext, &n, exten); 594169695Skan floatformat_to_double (&floatformat_m68881_ext, exten, &result); 595169695Skan if (n != result) 596169695Skan printf ("Differ(to+from): %.20g -> %.20g\n", n, result); 597169695Skan } 598169695Skan#endif 599169695Skan 600169695Skan#if IEEE_DEBUG > 1 601169695Skan /* This is to be run on a host which uses 68881 format. */ 602169695Skan { 603169695Skan long double ex = *(long double *)exten; 604169695Skan if (ex != n) 605169695Skan printf ("Differ(from vs. extended): %.20g\n", n); 606169695Skan } 607169695Skan#endif 608169695Skan} 609169695Skan 610169695Skanint 611169695Skanmain (void) 612169695Skan{ 613169695Skan ieee_test (0.0); 614169695Skan ieee_test (0.5); 615169695Skan ieee_test (256.0); 616169695Skan ieee_test (0.12345); 617169695Skan ieee_test (234235.78907234); 618169695Skan ieee_test (-512.0); 619169695Skan ieee_test (-0.004321); 620169695Skan ieee_test (1.2E-70); 621169695Skan ieee_test (1.2E-316); 622169695Skan ieee_test (4.9406564584124654E-324); 623169695Skan ieee_test (- 4.9406564584124654E-324); 624169695Skan ieee_test (- 0.0); 625169695Skan ieee_test (- INFINITY); 626169695Skan ieee_test (- NAN); 627169695Skan ieee_test (INFINITY); 628169695Skan ieee_test (NAN); 629169695Skan return 0; 630169695Skan} 631169695Skan#endif 632