doublest.c revision 98944
1/* Floating point routines for GDB, the GNU debugger. 2 Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 3 1997, 1998, 1999, 2000, 2001 4 Free Software Foundation, Inc. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, 21 Boston, MA 02111-1307, USA. */ 22 23/* Support for converting target fp numbers into host DOUBLEST format. */ 24 25/* XXX - This code should really be in libiberty/floatformat.c, 26 however configuration issues with libiberty made this very 27 difficult to do in the available time. */ 28 29#include "defs.h" 30#include "doublest.h" 31#include "floatformat.h" 32#include "gdb_assert.h" 33#include "gdb_string.h" 34#include "gdbtypes.h" 35#include <math.h> /* ldexp */ 36 37/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not 38 going to bother with trying to muck around with whether it is defined in 39 a system header, what we do if not, etc. */ 40#define FLOATFORMAT_CHAR_BIT 8 41 42static unsigned long get_field (unsigned char *, 43 enum floatformat_byteorders, 44 unsigned int, unsigned int, unsigned int); 45 46/* Extract a field which starts at START and is LEN bytes long. DATA and 47 TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 48static unsigned long 49get_field (unsigned char *data, enum floatformat_byteorders order, 50 unsigned int total_len, unsigned int start, unsigned int len) 51{ 52 unsigned long result; 53 unsigned int cur_byte; 54 int cur_bitshift; 55 56 /* Start at the least significant part of the field. */ 57 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 58 { 59 /* We start counting from the other end (i.e, from the high bytes 60 rather than the low bytes). As such, we need to be concerned 61 with what happens if bit 0 doesn't start on a byte boundary. 62 I.e, we need to properly handle the case where total_len is 63 not evenly divisible by 8. So we compute ``excess'' which 64 represents the number of bits from the end of our starting 65 byte needed to get to bit 0. */ 66 int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); 67 cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 68 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); 69 cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 70 - FLOATFORMAT_CHAR_BIT; 71 } 72 else 73 { 74 cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; 75 cur_bitshift = 76 ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; 77 } 78 if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) 79 result = *(data + cur_byte) >> (-cur_bitshift); 80 else 81 result = 0; 82 cur_bitshift += FLOATFORMAT_CHAR_BIT; 83 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 84 ++cur_byte; 85 else 86 --cur_byte; 87 88 /* Move towards the most significant part of the field. */ 89 while (cur_bitshift < len) 90 { 91 result |= (unsigned long)*(data + cur_byte) << cur_bitshift; 92 cur_bitshift += FLOATFORMAT_CHAR_BIT; 93 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 94 ++cur_byte; 95 else 96 --cur_byte; 97 } 98 if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) 99 /* Mask out bits which are not part of the field */ 100 result &= ((1UL << len) - 1); 101 return result; 102} 103 104/* Convert from FMT to a DOUBLEST. 105 FROM is the address of the extended float. 106 Store the DOUBLEST in *TO. */ 107 108static void 109convert_floatformat_to_doublest (const struct floatformat *fmt, 110 const void *from, 111 DOUBLEST *to) 112{ 113 unsigned char *ufrom = (unsigned char *) from; 114 DOUBLEST dto; 115 long exponent; 116 unsigned long mant; 117 unsigned int mant_bits, mant_off; 118 int mant_bits_left; 119 int special_exponent; /* It's a NaN, denorm or zero */ 120 121 /* If the mantissa bits are not contiguous from one end of the 122 mantissa to the other, we need to make a private copy of the 123 source bytes that is in the right order since the unpacking 124 algorithm assumes that the bits are contiguous. 125 126 Swap the bytes individually rather than accessing them through 127 "long *" since we have no guarantee that they start on a long 128 alignment, and also sizeof(long) for the host could be different 129 than sizeof(long) for the target. FIXME: Assumes sizeof(long) 130 for the target is 4. */ 131 132 if (fmt->byteorder == floatformat_littlebyte_bigword) 133 { 134 static unsigned char *newfrom; 135 unsigned char *swapin, *swapout; 136 int longswaps; 137 138 longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT; 139 longswaps >>= 3; 140 141 if (newfrom == NULL) 142 { 143 newfrom = (unsigned char *) xmalloc (fmt->totalsize); 144 } 145 swapout = newfrom; 146 swapin = ufrom; 147 ufrom = newfrom; 148 while (longswaps-- > 0) 149 { 150 /* This is ugly, but efficient */ 151 *swapout++ = swapin[4]; 152 *swapout++ = swapin[5]; 153 *swapout++ = swapin[6]; 154 *swapout++ = swapin[7]; 155 *swapout++ = swapin[0]; 156 *swapout++ = swapin[1]; 157 *swapout++ = swapin[2]; 158 *swapout++ = swapin[3]; 159 swapin += 8; 160 } 161 } 162 163 exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 164 fmt->exp_start, fmt->exp_len); 165 /* Note that if exponent indicates a NaN, we can't really do anything useful 166 (not knowing if the host has NaN's, or how to build one). So it will 167 end up as an infinity or something close; that is OK. */ 168 169 mant_bits_left = fmt->man_len; 170 mant_off = fmt->man_start; 171 dto = 0.0; 172 173 special_exponent = exponent == 0 || exponent == fmt->exp_nan; 174 175/* Don't bias NaNs. Use minimum exponent for denorms. For simplicity, 176 we don't check for zero as the exponent doesn't matter. */ 177 if (!special_exponent) 178 exponent -= fmt->exp_bias; 179 else if (exponent == 0) 180 exponent = 1 - fmt->exp_bias; 181 182 /* Build the result algebraically. Might go infinite, underflow, etc; 183 who cares. */ 184 185/* If this format uses a hidden bit, explicitly add it in now. Otherwise, 186 increment the exponent by one to account for the integer bit. */ 187 188 if (!special_exponent) 189 { 190 if (fmt->intbit == floatformat_intbit_no) 191 dto = ldexp (1.0, exponent); 192 else 193 exponent++; 194 } 195 196 while (mant_bits_left > 0) 197 { 198 mant_bits = min (mant_bits_left, 32); 199 200 mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, 201 mant_off, mant_bits); 202 203 dto += ldexp ((double) mant, exponent - mant_bits); 204 exponent -= mant_bits; 205 mant_off += mant_bits; 206 mant_bits_left -= mant_bits; 207 } 208 209 /* Negate it if negative. */ 210 if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 211 dto = -dto; 212 *to = dto; 213} 214 215static void put_field (unsigned char *, enum floatformat_byteorders, 216 unsigned int, 217 unsigned int, unsigned int, unsigned long); 218 219/* Set a field which starts at START and is LEN bytes long. DATA and 220 TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 221static void 222put_field (unsigned char *data, enum floatformat_byteorders order, 223 unsigned int total_len, unsigned int start, unsigned int len, 224 unsigned long stuff_to_put) 225{ 226 unsigned int cur_byte; 227 int cur_bitshift; 228 229 /* Start at the least significant part of the field. */ 230 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 231 { 232 int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); 233 cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 234 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); 235 cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 236 - FLOATFORMAT_CHAR_BIT; 237 } 238 else 239 { 240 cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; 241 cur_bitshift = 242 ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; 243 } 244 if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) 245 { 246 *(data + cur_byte) &= 247 ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) 248 << (-cur_bitshift)); 249 *(data + cur_byte) |= 250 (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); 251 } 252 cur_bitshift += FLOATFORMAT_CHAR_BIT; 253 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 254 ++cur_byte; 255 else 256 --cur_byte; 257 258 /* Move towards the most significant part of the field. */ 259 while (cur_bitshift < len) 260 { 261 if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) 262 { 263 /* This is the last byte. */ 264 *(data + cur_byte) &= 265 ~((1 << (len - cur_bitshift)) - 1); 266 *(data + cur_byte) |= (stuff_to_put >> cur_bitshift); 267 } 268 else 269 *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) 270 & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); 271 cur_bitshift += FLOATFORMAT_CHAR_BIT; 272 if (order == floatformat_little || order == floatformat_littlebyte_bigword) 273 ++cur_byte; 274 else 275 --cur_byte; 276 } 277} 278 279#ifdef HAVE_LONG_DOUBLE 280/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR. 281 The range of the returned value is >= 0.5 and < 1.0. This is equivalent to 282 frexp, but operates on the long double data type. */ 283 284static long double ldfrexp (long double value, int *eptr); 285 286static long double 287ldfrexp (long double value, int *eptr) 288{ 289 long double tmp; 290 int exp; 291 292 /* Unfortunately, there are no portable functions for extracting the exponent 293 of a long double, so we have to do it iteratively by multiplying or dividing 294 by two until the fraction is between 0.5 and 1.0. */ 295 296 if (value < 0.0l) 297 value = -value; 298 299 tmp = 1.0l; 300 exp = 0; 301 302 if (value >= tmp) /* Value >= 1.0 */ 303 while (value >= tmp) 304 { 305 tmp *= 2.0l; 306 exp++; 307 } 308 else if (value != 0.0l) /* Value < 1.0 and > 0.0 */ 309 { 310 while (value < tmp) 311 { 312 tmp /= 2.0l; 313 exp--; 314 } 315 tmp *= 2.0l; 316 exp++; 317 } 318 319 *eptr = exp; 320 return value / tmp; 321} 322#endif /* HAVE_LONG_DOUBLE */ 323 324 325/* The converse: convert the DOUBLEST *FROM to an extended float 326 and store where TO points. Neither FROM nor TO have any alignment 327 restrictions. */ 328 329static void 330convert_doublest_to_floatformat (CONST struct floatformat *fmt, 331 const DOUBLEST *from, 332 void *to) 333{ 334 DOUBLEST dfrom; 335 int exponent; 336 DOUBLEST mant; 337 unsigned int mant_bits, mant_off; 338 int mant_bits_left; 339 unsigned char *uto = (unsigned char *) to; 340 341 memcpy (&dfrom, from, sizeof (dfrom)); 342 memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1) 343 / FLOATFORMAT_CHAR_BIT); 344 if (dfrom == 0) 345 return; /* Result is zero */ 346 if (dfrom != dfrom) /* Result is NaN */ 347 { 348 /* From is NaN */ 349 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 350 fmt->exp_len, fmt->exp_nan); 351 /* Be sure it's not infinity, but NaN value is irrel */ 352 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 353 32, 1); 354 return; 355 } 356 357 /* If negative, set the sign bit. */ 358 if (dfrom < 0) 359 { 360 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); 361 dfrom = -dfrom; 362 } 363 364 if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ 365 { 366 /* Infinity exponent is same as NaN's. */ 367 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 368 fmt->exp_len, fmt->exp_nan); 369 /* Infinity mantissa is all zeroes. */ 370 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 371 fmt->man_len, 0); 372 return; 373 } 374 375#ifdef HAVE_LONG_DOUBLE 376 mant = ldfrexp (dfrom, &exponent); 377#else 378 mant = frexp (dfrom, &exponent); 379#endif 380 381 put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, 382 exponent + fmt->exp_bias - 1); 383 384 mant_bits_left = fmt->man_len; 385 mant_off = fmt->man_start; 386 while (mant_bits_left > 0) 387 { 388 unsigned long mant_long; 389 mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; 390 391 mant *= 4294967296.0; 392 mant_long = ((unsigned long) mant) & 0xffffffffL; 393 mant -= mant_long; 394 395 /* If the integer bit is implicit, then we need to discard it. 396 If we are discarding a zero, we should be (but are not) creating 397 a denormalized number which means adjusting the exponent 398 (I think). */ 399 if (mant_bits_left == fmt->man_len 400 && fmt->intbit == floatformat_intbit_no) 401 { 402 mant_long <<= 1; 403 mant_long &= 0xffffffffL; 404 mant_bits -= 1; 405 } 406 407 if (mant_bits < 32) 408 { 409 /* The bits we want are in the most significant MANT_BITS bits of 410 mant_long. Move them to the least significant. */ 411 mant_long >>= 32 - mant_bits; 412 } 413 414 put_field (uto, fmt->byteorder, fmt->totalsize, 415 mant_off, mant_bits, mant_long); 416 mant_off += mant_bits; 417 mant_bits_left -= mant_bits; 418 } 419 if (fmt->byteorder == floatformat_littlebyte_bigword) 420 { 421 int count; 422 unsigned char *swaplow = uto; 423 unsigned char *swaphigh = uto + 4; 424 unsigned char tmp; 425 426 for (count = 0; count < 4; count++) 427 { 428 tmp = *swaplow; 429 *swaplow++ = *swaphigh; 430 *swaphigh++ = tmp; 431 } 432 } 433} 434 435/* Check if VAL (which is assumed to be a floating point number whose 436 format is described by FMT) is negative. */ 437 438int 439floatformat_is_negative (const struct floatformat *fmt, char *val) 440{ 441 unsigned char *uval = (unsigned char *) val; 442 gdb_assert (fmt != NULL); 443 return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1); 444} 445 446/* Check if VAL is "not a number" (NaN) for FMT. */ 447 448int 449floatformat_is_nan (const struct floatformat *fmt, char *val) 450{ 451 unsigned char *uval = (unsigned char *) val; 452 long exponent; 453 unsigned long mant; 454 unsigned int mant_bits, mant_off; 455 int mant_bits_left; 456 457 gdb_assert (fmt != NULL); 458 459 if (! fmt->exp_nan) 460 return 0; 461 462 exponent = get_field (uval, fmt->byteorder, fmt->totalsize, 463 fmt->exp_start, fmt->exp_len); 464 465 if (exponent != fmt->exp_nan) 466 return 0; 467 468 mant_bits_left = fmt->man_len; 469 mant_off = fmt->man_start; 470 471 while (mant_bits_left > 0) 472 { 473 mant_bits = min (mant_bits_left, 32); 474 475 mant = get_field (uval, fmt->byteorder, fmt->totalsize, 476 mant_off, mant_bits); 477 478 /* If there is an explicit integer bit, mask it off. */ 479 if (mant_off == fmt->man_start 480 && fmt->intbit == floatformat_intbit_yes) 481 mant &= ~(1 << (mant_bits - 1)); 482 483 if (mant) 484 return 1; 485 486 mant_off += mant_bits; 487 mant_bits_left -= mant_bits; 488 } 489 490 return 0; 491} 492 493/* Convert the mantissa of VAL (which is assumed to be a floating 494 point number whose format is described by FMT) into a hexadecimal 495 and store it in a static string. Return a pointer to that string. */ 496 497char * 498floatformat_mantissa (const struct floatformat *fmt, char *val) 499{ 500 unsigned char *uval = (unsigned char *) val; 501 unsigned long mant; 502 unsigned int mant_bits, mant_off; 503 int mant_bits_left; 504 static char res[50]; 505 char buf[9]; 506 507 /* Make sure we have enough room to store the mantissa. */ 508 gdb_assert (fmt != NULL); 509 gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2); 510 511 mant_off = fmt->man_start; 512 mant_bits_left = fmt->man_len; 513 mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32; 514 515 mant = get_field (uval, fmt->byteorder, fmt->totalsize, 516 mant_off, mant_bits); 517 518 sprintf (res, "%lx", mant); 519 520 mant_off += mant_bits; 521 mant_bits_left -= mant_bits; 522 523 while (mant_bits_left > 0) 524 { 525 mant = get_field (uval, fmt->byteorder, fmt->totalsize, 526 mant_off, 32); 527 528 sprintf (buf, "%08lx", mant); 529 strcat (res, buf); 530 531 mant_off += 32; 532 mant_bits_left -= 32; 533 } 534 535 return res; 536} 537 538 539/* Convert TO/FROM target to the hosts DOUBLEST floating-point format. 540 541 If the host and target formats agree, we just copy the raw data 542 into the appropriate type of variable and return, letting the host 543 increase precision as necessary. Otherwise, we call the conversion 544 routine and let it do the dirty work. */ 545 546#ifndef HOST_FLOAT_FORMAT 547#define HOST_FLOAT_FORMAT 0 548#endif 549#ifndef HOST_DOUBLE_FORMAT 550#define HOST_DOUBLE_FORMAT 0 551#endif 552#ifndef HOST_LONG_DOUBLE_FORMAT 553#define HOST_LONG_DOUBLE_FORMAT 0 554#endif 555 556static const struct floatformat *host_float_format = HOST_FLOAT_FORMAT; 557static const struct floatformat *host_double_format = HOST_DOUBLE_FORMAT; 558static const struct floatformat *host_long_double_format = HOST_LONG_DOUBLE_FORMAT; 559 560void 561floatformat_to_doublest (const struct floatformat *fmt, 562 const void *in, DOUBLEST *out) 563{ 564 gdb_assert (fmt != NULL); 565 if (fmt == host_float_format) 566 { 567 float val; 568 memcpy (&val, in, sizeof (val)); 569 *out = val; 570 } 571 else if (fmt == host_double_format) 572 { 573 double val; 574 memcpy (&val, in, sizeof (val)); 575 *out = val; 576 } 577 else if (fmt == host_long_double_format) 578 { 579 long double val; 580 memcpy (&val, in, sizeof (val)); 581 *out = val; 582 } 583 else 584 convert_floatformat_to_doublest (fmt, in, out); 585} 586 587void 588floatformat_from_doublest (const struct floatformat *fmt, 589 const DOUBLEST *in, void *out) 590{ 591 gdb_assert (fmt != NULL); 592 if (fmt == host_float_format) 593 { 594 float val = *in; 595 memcpy (out, &val, sizeof (val)); 596 } 597 else if (fmt == host_double_format) 598 { 599 double val = *in; 600 memcpy (out, &val, sizeof (val)); 601 } 602 else if (fmt == host_long_double_format) 603 { 604 long double val = *in; 605 memcpy (out, &val, sizeof (val)); 606 } 607 else 608 convert_doublest_to_floatformat (fmt, in, out); 609} 610 611 612/* Return a floating-point format for a floating-point variable of 613 length LEN. Return NULL, if no suitable floating-point format 614 could be found. 615 616 We need this functionality since information about the 617 floating-point format of a type is not always available to GDB; the 618 debug information typically only tells us the size of a 619 floating-point type. 620 621 FIXME: kettenis/2001-10-28: In many places, particularly in 622 target-dependent code, the format of floating-point types is known, 623 but not passed on by GDB. This should be fixed. */ 624 625const struct floatformat * 626floatformat_from_length (int len) 627{ 628 if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) 629 return TARGET_FLOAT_FORMAT; 630 else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) 631 return TARGET_DOUBLE_FORMAT; 632 else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) 633 return TARGET_LONG_DOUBLE_FORMAT; 634 635 return NULL; 636} 637 638const struct floatformat * 639floatformat_from_type (const struct type *type) 640{ 641 gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 642 if (TYPE_FLOATFORMAT (type) != NULL) 643 return TYPE_FLOATFORMAT (type); 644 else 645 return floatformat_from_length (TYPE_LENGTH (type)); 646} 647 648/* If the host doesn't define NAN, use zero instead. */ 649#ifndef NAN 650#define NAN 0.0 651#endif 652 653/* Extract a floating-point number of length LEN from a target-order 654 byte-stream at ADDR. Returns the value as type DOUBLEST. */ 655 656DOUBLEST 657extract_floating (const void *addr, int len) 658{ 659 const struct floatformat *fmt = floatformat_from_length (len); 660 DOUBLEST val; 661 662 if (fmt == NULL) 663 { 664 warning ("Can't store a floating-point number of %d bytes.", len); 665 return NAN; 666 } 667 668 floatformat_to_doublest (fmt, addr, &val); 669 return val; 670} 671 672/* Store VAL as a floating-point number of length LEN to a 673 target-order byte-stream at ADDR. */ 674 675void 676store_floating (void *addr, int len, DOUBLEST val) 677{ 678 const struct floatformat *fmt = floatformat_from_length (len); 679 680 if (fmt == NULL) 681 { 682 warning ("Can't store a floating-point number of %d bytes.", len); 683 memset (addr, 0, len); 684 } 685 686 floatformat_from_doublest (fmt, &val, addr); 687} 688 689/* Extract a floating-point number of type TYPE from a target-order 690 byte-stream at ADDR. Returns the value as type DOUBLEST. */ 691 692DOUBLEST 693extract_typed_floating (const void *addr, const struct type *type) 694{ 695 DOUBLEST retval; 696 697 gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 698 699 if (TYPE_FLOATFORMAT (type) == NULL) 700 return extract_floating (addr, TYPE_LENGTH (type)); 701 702 floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval); 703 return retval; 704} 705 706/* Store VAL as a floating-point number of type TYPE to a target-order 707 byte-stream at ADDR. */ 708 709void 710store_typed_floating (void *addr, const struct type *type, DOUBLEST val) 711{ 712 gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 713 714 /* FIXME: kettenis/2001-10-28: It is debatable whether we should 715 zero out any remaining bytes in the target buffer when TYPE is 716 longer than the actual underlying floating-point format. Perhaps 717 we should store a fixed bitpattern in those remaining bytes, 718 instead of zero, or perhaps we shouldn't touch those remaining 719 bytes at all. 720 721 NOTE: cagney/2001-10-28: With the way things currently work, it 722 isn't a good idea to leave the end bits undefined. This is 723 because GDB writes out the entire sizeof(<floating>) bits of the 724 floating-point type even though the value might only be stored 725 in, and the target processor may only refer to, the first N < 726 TYPE_LENGTH (type) bits. If the end of the buffer wasn't 727 initialized, GDB would write undefined data to the target. An 728 errant program, refering to that undefined data, would then 729 become non-deterministic. 730 731 See also the function convert_typed_floating below. */ 732 memset (addr, 0, TYPE_LENGTH (type)); 733 734 if (TYPE_FLOATFORMAT (type) == NULL) 735 store_floating (addr, TYPE_LENGTH (type), val); 736 else 737 floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr); 738} 739 740/* Convert a floating-point number of type FROM_TYPE from a 741 target-order byte-stream at FROM to a floating-point number of type 742 TO_TYPE, and store it to a target-order byte-stream at TO. */ 743 744void 745convert_typed_floating (const void *from, const struct type *from_type, 746 void *to, const struct type *to_type) 747{ 748 const struct floatformat *from_fmt = floatformat_from_type (from_type); 749 const struct floatformat *to_fmt = floatformat_from_type (to_type); 750 751 gdb_assert (TYPE_CODE (from_type) == TYPE_CODE_FLT); 752 gdb_assert (TYPE_CODE (to_type) == TYPE_CODE_FLT); 753 754 if (from_fmt == NULL || to_fmt == NULL) 755 { 756 /* If we don't know the floating-point format of FROM_TYPE or 757 TO_TYPE, there's not much we can do. We might make the 758 assumption that if the length of FROM_TYPE and TO_TYPE match, 759 their floating-point format would match too, but that 760 assumption might be wrong on targets that support 761 floating-point types that only differ in endianness for 762 example. So we warn instead, and zero out the target buffer. */ 763 warning ("Can't convert floating-point number to desired type."); 764 memset (to, 0, TYPE_LENGTH (to_type)); 765 } 766 else if (from_fmt == to_fmt) 767 { 768 /* We're in business. The floating-point format of FROM_TYPE 769 and TO_TYPE match. However, even though the floating-point 770 format matches, the length of the type might still be 771 different. Make sure we don't overrun any buffers. See 772 comment in store_typed_floating for a discussion about 773 zeroing out remaining bytes in the target buffer. */ 774 memset (to, 0, TYPE_LENGTH (to_type)); 775 memcpy (to, from, min (TYPE_LENGTH (from_type), TYPE_LENGTH (to_type))); 776 } 777 else 778 { 779 /* The floating-point types don't match. The best we can do 780 (aport from simulating the target FPU) is converting to the 781 widest floating-point type supported by the host, and then 782 again to the desired type. */ 783 DOUBLEST d; 784 785 floatformat_to_doublest (from_fmt, from, &d); 786 floatformat_from_doublest (to_fmt, &d, to); 787 } 788} 789