1132732Skan/* Floating point routines for GDB, the GNU debugger. 272564Sobrien 3169702Skan Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 4169702Skan 1996, 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, 518334Speter Inc. 690091Sobrien 718334Speter This file is part of GDB. 890091Sobrien 990091Sobrien This program is free software; you can redistribute it and/or modify 1090091Sobrien it under the terms of the GNU General Public License as published by 1190091Sobrien the Free Software Foundation; either version 2 of the License, or 1218334Speter (at your option) any later version. 1390091Sobrien 1490091Sobrien This program is distributed in the hope that it will be useful, 1590091Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1690091Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1718334Speter GNU General Public License for more details. 1818334Speter 1990091Sobrien You should have received a copy of the GNU General Public License 20169702Skan along with this program; if not, write to the Free Software 21169702Skan Foundation, Inc., 59 Temple Place - Suite 330, 2218334Speter Boston, MA 02111-1307, USA. */ 23124160Skan 24124160Skan/* Support for converting target fp numbers into host DOUBLEST format. */ 2518334Speter 2618334Speter/* XXX - This code should really be in libiberty/floatformat.c, 2718334Speter however configuration issues with libiberty made this very 2818334Speter difficult to do in the available time. */ 2918334Speter 3018334Speter#include "defs.h" 3118334Speter#include "doublest.h" 3218334Speter#include "floatformat.h" 3318334Speter#include "gdb_assert.h" 3418334Speter#include "gdb_string.h" 3518334Speter#include "gdbtypes.h" 3618334Speter#include <math.h> /* ldexp */ 37169702Skan 3818334Speter/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not 3918334Speter going to bother with trying to muck around with whether it is defined in 4052268Sobrien a system header, what we do if not, etc. */ 41132732Skan#define FLOATFORMAT_CHAR_BIT 8 42132732Skan 4318334Speterstatic unsigned long get_field (unsigned char *, 4418334Speter enum floatformat_byteorders, 4518334Speter unsigned int, unsigned int, unsigned int); 4652268Sobrien 4718334Speter/* Extract a field which starts at START and is LEN bytes long. DATA and 4818334Speter TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 49132732Skanstatic unsigned long 5090091Sobrienget_field (unsigned char *data, enum floatformat_byteorders order, 5118334Speter unsigned int total_len, unsigned int start, unsigned int len) 5218334Speter{ 5318334Speter unsigned long result; 5418334Speter unsigned int cur_byte; 5518334Speter int cur_bitshift; 5618334Speter 5752268Sobrien /* Start at the least significant part of the field. */ 58117404Skan if (order == floatformat_little || order == floatformat_littlebyte_bigword) 5990091Sobrien { 6090091Sobrien /* We start counting from the other end (i.e, from the high bytes 6190091Sobrien rather than the low bytes). As such, we need to be concerned 62107605Sobrien with what happens if bit 0 doesn't start on a byte boundary. 63132732Skan I.e, we need to properly handle the case where total_len is 64169702Skan not evenly divisible by 8. So we compute ``excess'' which 65169702Skan represents the number of bits from the end of our starting 66169702Skan byte needed to get to bit 0. */ 67169702Skan int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); 68169702Skan cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 6918334Speter - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); 7052518Sobrien cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 7152518Sobrien - FLOATFORMAT_CHAR_BIT; 7252518Sobrien } 7352518Sobrien else 74132732Skan { 75132732Skan cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; 76132732Skan cur_bitshift = 77132732Skan ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; 78132732Skan } 79132732Skan if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) 8018334Speter result = *(data + cur_byte) >> (-cur_bitshift); 8118334Speter else 8218334Speter result = 0; 8352268Sobrien cur_bitshift += FLOATFORMAT_CHAR_BIT; 8418334Speter if (order == floatformat_little || order == floatformat_littlebyte_bigword) 8518334Speter ++cur_byte; 8618334Speter else 8718334Speter --cur_byte; 8818334Speter 8918334Speter /* Move towards the most significant part of the field. */ 9018334Speter while (cur_bitshift < len) 9118334Speter { 9218334Speter result |= (unsigned long)*(data + cur_byte) << cur_bitshift; 9318334Speter cur_bitshift += FLOATFORMAT_CHAR_BIT; 9418334Speter if (order == floatformat_little || order == floatformat_littlebyte_bigword) 9518334Speter ++cur_byte; 9618334Speter else 9752518Sobrien --cur_byte; 9852518Sobrien } 9952518Sobrien if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) 10090091Sobrien /* Mask out bits which are not part of the field */ 10152518Sobrien result &= ((1UL << len) - 1); 10218334Speter return result; 10352518Sobrien} 10452518Sobrien 10590091Sobrien/* Convert from FMT to a DOUBLEST. 10652518Sobrien FROM is the address of the extended float. 10752518Sobrien Store the DOUBLEST in *TO. */ 10852518Sobrien 10952518Sobrienstatic void 11052518Sobrienconvert_floatformat_to_doublest (const struct floatformat *fmt, 11152518Sobrien const void *from, 11252518Sobrien DOUBLEST *to) 11390091Sobrien{ 11490091Sobrien unsigned char *ufrom = (unsigned char *) from; 11590091Sobrien DOUBLEST dto; 11690091Sobrien long exponent; 11790091Sobrien unsigned long mant; 11852518Sobrien unsigned int mant_bits, mant_off; 119261188Spfg int mant_bits_left; 120261188Spfg int special_exponent; /* It's a NaN, denorm or zero */ 121261188Spfg 122261188Spfg /* If the mantissa bits are not contiguous from one end of the 123117404Skan mantissa to the other, we need to make a private copy of the 124132732Skan source bytes that is in the right order since the unpacking 12596283Sobrien algorithm assumes that the bits are contiguous. 12690091Sobrien 12790091Sobrien Swap the bytes individually rather than accessing them through 128132732Skan "long *" since we have no guarantee that they start on a long 12952518Sobrien alignment, and also sizeof(long) for the host could be different 13090091Sobrien than sizeof(long) for the target. FIXME: Assumes sizeof(long) 13190091Sobrien for the target is 4. */ 13218334Speter 13390091Sobrien if (fmt->byteorder == floatformat_littlebyte_bigword) 134169702Skan { 135169702Skan static unsigned char *newfrom; 13618334Speter unsigned char *swapin, *swapout; 13790091Sobrien int longswaps; 13818334Speter 139169702Skan longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT; 14018334Speter longswaps >>= 3; 14118334Speter 14218334Speter if (newfrom == NULL) 14318334Speter { 14418334Speter newfrom = (unsigned char *) xmalloc (fmt->totalsize); 14518334Speter } 14618334Speter swapout = newfrom; 14718334Speter swapin = ufrom; 14818334Speter ufrom = newfrom; 14918334Speter while (longswaps-- > 0) 15018334Speter { 15118334Speter /* This is ugly, but efficient */ 15218334Speter *swapout++ = swapin[4]; 15318334Speter *swapout++ = swapin[5]; 15418334Speter *swapout++ = swapin[6]; 15518334Speter *swapout++ = swapin[7]; 15618334Speter *swapout++ = swapin[0]; 15718334Speter *swapout++ = swapin[1]; 15818334Speter *swapout++ = swapin[2]; 159117404Skan *swapout++ = swapin[3]; 16018334Speter swapin += 8; 16118334Speter } 16218334Speter } 163169702Skan 164169702Skan exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 165169702Skan fmt->exp_start, fmt->exp_len); 16652268Sobrien /* Note that if exponent indicates a NaN, we can't really do anything useful 16718334Speter (not knowing if the host has NaN's, or how to build one). So it will 16818334Speter end up as an infinity or something close; that is OK. */ 16918334Speter 17018334Speter mant_bits_left = fmt->man_len; 17190091Sobrien mant_off = fmt->man_start; 17290091Sobrien dto = 0.0; 17318334Speter 17452268Sobrien special_exponent = exponent == 0 || exponent == fmt->exp_nan; 17590091Sobrien 17690091Sobrien /* Don't bias NaNs. Use minimum exponent for denorms. For simplicity, 17790091Sobrien we don't check for zero as the exponent doesn't matter. Note the cast 17890091Sobrien to int; exp_bias is unsigned, so it's important to make sure the 17990091Sobrien operation is done in signed arithmetic. */ 180117404Skan if (!special_exponent) 18118334Speter exponent -= fmt->exp_bias; 182117404Skan else if (exponent == 0) 18318334Speter exponent = 1 - fmt->exp_bias; 18418334Speter 18518334Speter /* Build the result algebraically. Might go infinite, underflow, etc; 186117404Skan who cares. */ 18718334Speter 18818334Speter/* If this format uses a hidden bit, explicitly add it in now. Otherwise, 18918334Speter increment the exponent by one to account for the integer bit. */ 19052268Sobrien 19118334Speter if (!special_exponent) 19218334Speter { 19352268Sobrien if (fmt->intbit == floatformat_intbit_no) 19418334Speter dto = ldexp (1.0, exponent); 19552268Sobrien else 19618334Speter exponent++; 19718334Speter } 198132732Skan 199132732Skan while (mant_bits_left > 0) 200132732Skan { 201132732Skan mant_bits = min (mant_bits_left, 32); 202132732Skan 203169702Skan mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, 204132732Skan mant_off, mant_bits); 205132732Skan 206132732Skan dto += ldexp ((double) mant, exponent - mant_bits); 207169702Skan exponent -= mant_bits; 20890091Sobrien mant_off += mant_bits; 209169702Skan mant_bits_left -= mant_bits; 210169702Skan } 21190091Sobrien 212132732Skan /* Negate it if negative. */ 21352268Sobrien if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 21490091Sobrien dto = -dto; 215132732Skan *to = dto; 21690091Sobrien} 217132732Skan 218132732Skanstatic void put_field (unsigned char *, enum floatformat_byteorders, 219132732Skan unsigned int, 220132732Skan unsigned int, unsigned int, unsigned long); 221261188Spfg 222261188Spfg/* Set a field which starts at START and is LEN bytes long. DATA and 22318334Speter TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 22418334Speterstatic void 225132732Skanput_field (unsigned char *data, enum floatformat_byteorders order, 22618334Speter unsigned int total_len, unsigned int start, unsigned int len, 22718334Speter unsigned long stuff_to_put) 22818334Speter{ 22918334Speter unsigned int cur_byte; 23018334Speter int cur_bitshift; 231132732Skan 23218334Speter /* Start at the least significant part of the field. */ 23318334Speter if (order == floatformat_little || order == floatformat_littlebyte_bigword) 23452268Sobrien { 23590091Sobrien int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); 23618334Speter cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) 23718334Speter - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); 23852268Sobrien cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) 239169702Skan - FLOATFORMAT_CHAR_BIT; 24018334Speter } 24118334Speter else 24218334Speter { 24390091Sobrien cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; 244117404Skan cur_bitshift = 24590091Sobrien ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; 24690091Sobrien } 24718334Speter if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) 24818334Speter { 249169702Skan *(data + cur_byte) &= 25018334Speter ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) 25190091Sobrien << (-cur_bitshift)); 25218334Speter *(data + cur_byte) |= 25390091Sobrien (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); 25490091Sobrien } 25590091Sobrien cur_bitshift += FLOATFORMAT_CHAR_BIT; 25690091Sobrien if (order == floatformat_little || order == floatformat_littlebyte_bigword) 25790091Sobrien ++cur_byte; 25818334Speter else 25918334Speter --cur_byte; 260169702Skan 26190091Sobrien /* Move towards the most significant part of the field. */ 26290091Sobrien while (cur_bitshift < len) 26318334Speter { 26418334Speter if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) 26518334Speter { 266132732Skan /* This is the last byte. */ 26718334Speter *(data + cur_byte) &= 26818334Speter ~((1 << (len - cur_bitshift)) - 1); 26918334Speter *(data + cur_byte) |= (stuff_to_put >> cur_bitshift); 27018334Speter } 27118334Speter else 27218334Speter *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) 27318334Speter & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); 27418334Speter cur_bitshift += FLOATFORMAT_CHAR_BIT; 275132732Skan if (order == floatformat_little || order == floatformat_littlebyte_bigword) 27618334Speter ++cur_byte; 27718334Speter else 27818334Speter --cur_byte; 27990091Sobrien } 28090091Sobrien} 28118334Speter 28218334Speter#ifdef HAVE_LONG_DOUBLE 28318334Speter/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR. 284169702Skan The range of the returned value is >= 0.5 and < 1.0. This is equivalent to 28518334Speter frexp, but operates on the long double data type. */ 28618334Speter 28718334Speterstatic long double ldfrexp (long double value, int *eptr); 28890091Sobrien 28918334Speterstatic long double 29018334Speterldfrexp (long double value, int *eptr) 29190091Sobrien{ 292132732Skan long double tmp; 29318334Speter int exp; 29418334Speter 29518334Speter /* Unfortunately, there are no portable functions for extracting the exponent 29690091Sobrien of a long double, so we have to do it iteratively by multiplying or dividing 29790091Sobrien by two until the fraction is between 0.5 and 1.0. */ 29890091Sobrien 29990091Sobrien if (value < 0.0l) 30090091Sobrien value = -value; 30190091Sobrien 302132732Skan tmp = 1.0l; 30390091Sobrien exp = 0; 30490091Sobrien 30590091Sobrien if (value >= tmp) /* Value >= 1.0 */ 30690091Sobrien while (value >= tmp) 30790091Sobrien { 30890091Sobrien tmp *= 2.0l; 309169702Skan exp++; 31090091Sobrien } 31190091Sobrien else if (value != 0.0l) /* Value < 1.0 and > 0.0 */ 31290091Sobrien { 31390091Sobrien while (value < tmp) 31490091Sobrien { 31590091Sobrien tmp /= 2.0l; 31690091Sobrien exp--; 317132732Skan } 31890091Sobrien tmp *= 2.0l; 319169702Skan exp++; 320169702Skan } 321169702Skan 322169702Skan *eptr = exp; 323117404Skan return value / tmp; 324117404Skan} 325117404Skan#endif /* HAVE_LONG_DOUBLE */ 326117404Skan 327117404Skan 328169702Skan/* The converse: convert the DOUBLEST *FROM to an extended float 32990091Sobrien and store where TO points. Neither FROM nor TO have any alignment 330169702Skan restrictions. */ 331169702Skan 33290091Sobrienstatic void 33390091Sobrienconvert_doublest_to_floatformat (CONST struct floatformat *fmt, 33490091Sobrien const DOUBLEST *from, 33590091Sobrien void *to) 33690091Sobrien{ 337132732Skan DOUBLEST dfrom; 33890091Sobrien int exponent; 339169702Skan DOUBLEST mant; 34090091Sobrien unsigned int mant_bits, mant_off; 34190091Sobrien int mant_bits_left; 34290091Sobrien unsigned char *uto = (unsigned char *) to; 34390091Sobrien 34418334Speter memcpy (&dfrom, from, sizeof (dfrom)); 34518334Speter memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1) 34618334Speter / FLOATFORMAT_CHAR_BIT); 34790091Sobrien if (dfrom == 0) 34890091Sobrien return; /* Result is zero */ 34952518Sobrien if (dfrom != dfrom) /* Result is NaN */ 35018334Speter { 35118334Speter /* From is NaN */ 352169702Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 353132732Skan fmt->exp_len, fmt->exp_nan); 35418334Speter /* Be sure it's not infinity, but NaN value is irrel */ 355169702Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 356169702Skan 32, 1); 357169702Skan return; 358169702Skan } 35918334Speter 36018334Speter /* If negative, set the sign bit. */ 36190091Sobrien if (dfrom < 0) 36290091Sobrien { 36390091Sobrien put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); 364169702Skan dfrom = -dfrom; 36590091Sobrien } 366132732Skan 36790091Sobrien if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ 36890091Sobrien { 36990091Sobrien /* Infinity exponent is same as NaN's. */ 37090091Sobrien put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 371169702Skan fmt->exp_len, fmt->exp_nan); 372169702Skan /* Infinity mantissa is all zeroes. */ 373169702Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 374169702Skan fmt->man_len, 0); 375169702Skan return; 376169702Skan } 377169702Skan 378169702Skan#ifdef HAVE_LONG_DOUBLE 379169702Skan mant = ldfrexp (dfrom, &exponent); 380169702Skan#else 381169702Skan mant = frexp (dfrom, &exponent); 382169702Skan#endif 383169702Skan 384169702Skan put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, 385169702Skan exponent + fmt->exp_bias - 1); 386169702Skan 387169702Skan mant_bits_left = fmt->man_len; 388169702Skan mant_off = fmt->man_start; 389169702Skan while (mant_bits_left > 0) 390169702Skan { 39118334Speter unsigned long mant_long; 39218334Speter mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; 39390091Sobrien 39418334Speter mant *= 4294967296.0; 39518334Speter mant_long = ((unsigned long) mant) & 0xffffffffL; 39618334Speter mant -= mant_long; 397146908Skan 39818334Speter /* If the integer bit is implicit, then we need to discard it. 39918334Speter If we are discarding a zero, we should be (but are not) creating 40090091Sobrien a denormalized number which means adjusting the exponent 40118334Speter (I think). */ 40290091Sobrien if (mant_bits_left == fmt->man_len 40390091Sobrien && fmt->intbit == floatformat_intbit_no) 40490091Sobrien { 405132732Skan mant_long <<= 1; 406132732Skan mant_long &= 0xffffffffL; 40718334Speter /* If we are processing the top 32 mantissa bits of a doublest 40890091Sobrien so as to convert to a float value with implied integer bit, 40918334Speter we will only be putting 31 of those 32 bits into the 410169702Skan final value due to the discarding of the top bit. In the 41190091Sobrien case of a small float value where the number of mantissa 41218334Speter bits is less than 32, discarding the top bit does not alter 41318334Speter the number of bits we will be adding to the result. */ 41418334Speter if (mant_bits == 32) 41552518Sobrien mant_bits -= 1; 41652518Sobrien } 41718334Speter 41852518Sobrien if (mant_bits < 32) 41990091Sobrien { 42090091Sobrien /* The bits we want are in the most significant MANT_BITS bits of 42152518Sobrien mant_long. Move them to the least significant. */ 42252518Sobrien mant_long >>= 32 - mant_bits; 42352518Sobrien } 424169702Skan 42552518Sobrien put_field (uto, fmt->byteorder, fmt->totalsize, 42652518Sobrien mant_off, mant_bits, mant_long); 42752518Sobrien mant_off += mant_bits; 42852518Sobrien mant_bits_left -= mant_bits; 42918334Speter } 43018334Speter if (fmt->byteorder == floatformat_littlebyte_bigword) 43118334Speter { 43218334Speter int count; 43318334Speter unsigned char *swaplow = uto; 43418334Speter unsigned char *swaphigh = uto + 4; 435146908Skan unsigned char tmp; 436146908Skan 43718334Speter for (count = 0; count < 4; count++) 43818334Speter { 43918334Speter tmp = *swaplow; 440169702Skan *swaplow++ = *swaphigh; 441169702Skan *swaphigh++ = tmp; 44252518Sobrien } 44390091Sobrien } 44490091Sobrien} 44590091Sobrien 44690091Sobrien/* Check if VAL (which is assumed to be a floating point number whose 44790091Sobrien format is described by FMT) is negative. */ 44890091Sobrien 44990091Sobrienint 45090091Sobrienfloatformat_is_negative (const struct floatformat *fmt, char *val) 45190091Sobrien{ 45290091Sobrien unsigned char *uval = (unsigned char *) val; 45390091Sobrien gdb_assert (fmt != NULL); 45490091Sobrien return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1); 45590091Sobrien} 456132732Skan 457132732Skan/* Check if VAL is "not a number" (NaN) for FMT. */ 458132732Skan 459132732Skanint 460132732Skanfloatformat_is_nan (const struct floatformat *fmt, char *val) 461132732Skan{ 462132732Skan unsigned char *uval = (unsigned char *) val; 463132732Skan long exponent; 464132732Skan unsigned long mant; 465132732Skan unsigned int mant_bits, mant_off; 466132732Skan int mant_bits_left; 467169702Skan 468169702Skan gdb_assert (fmt != NULL); 469169702Skan 470169702Skan if (! fmt->exp_nan) 471169702Skan return 0; 472169702Skan 473169702Skan exponent = get_field (uval, fmt->byteorder, fmt->totalsize, 474169702Skan fmt->exp_start, fmt->exp_len); 475169702Skan 476169702Skan if (exponent != fmt->exp_nan) 477132732Skan return 0; 47818334Speter 47918334Speter mant_bits_left = fmt->man_len; 48018334Speter mant_off = fmt->man_start; 481169702Skan 48218334Speter while (mant_bits_left > 0) 48318334Speter { 48418334Speter mant_bits = min (mant_bits_left, 32); 48518334Speter 48690091Sobrien mant = get_field (uval, fmt->byteorder, fmt->totalsize, 48718334Speter mant_off, mant_bits); 488132732Skan 48918334Speter /* If there is an explicit integer bit, mask it off. */ 490132732Skan if (mant_off == fmt->man_start 49118334Speter && fmt->intbit == floatformat_intbit_yes) 49218334Speter mant &= ~(1 << (mant_bits - 1)); 493132732Skan 494132732Skan if (mant) 495132732Skan return 1; 49618334Speter 497169702Skan mant_off += mant_bits; 498169702Skan mant_bits_left -= mant_bits; 49918334Speter } 50052268Sobrien 501169702Skan return 0; 50218334Speter} 50390091Sobrien 50490091Sobrien/* Convert the mantissa of VAL (which is assumed to be a floating 50518334Speter point number whose format is described by FMT) into a hexadecimal 506169702Skan and store it in a static string. Return a pointer to that string. */ 507169702Skan 508169702Skanchar * 50918334Speterfloatformat_mantissa (const struct floatformat *fmt, char *val) 51018334Speter{ 51118334Speter unsigned char *uval = (unsigned char *) val; 51290091Sobrien unsigned long mant; 51390091Sobrien unsigned int mant_bits, mant_off; 51418334Speter int mant_bits_left; 51590091Sobrien static char res[50]; 516132732Skan char buf[9]; 51718334Speter 51890091Sobrien /* Make sure we have enough room to store the mantissa. */ 51918334Speter gdb_assert (fmt != NULL); 520169702Skan gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2); 52118334Speter 522169702Skan mant_off = fmt->man_start; 523169702Skan mant_bits_left = fmt->man_len; 524169702Skan mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32; 525169702Skan 526169702Skan mant = get_field (uval, fmt->byteorder, fmt->totalsize, 527169702Skan mant_off, mant_bits); 528169702Skan 529169702Skan sprintf (res, "%lx", mant); 530169702Skan 531169702Skan mant_off += mant_bits; 532169702Skan mant_bits_left -= mant_bits; 533169702Skan 534169702Skan while (mant_bits_left > 0) 535169702Skan { 536169702Skan mant = get_field (uval, fmt->byteorder, fmt->totalsize, 537169702Skan mant_off, 32); 538169702Skan 539169702Skan sprintf (buf, "%08lx", mant); 540169702Skan strcat (res, buf); 541169702Skan 542169702Skan mant_off += 32; 543169702Skan mant_bits_left -= 32; 544169702Skan } 545169702Skan 546169702Skan return res; 547169702Skan} 548169702Skan 549169702Skan 550169702Skan/* Convert TO/FROM target to the hosts DOUBLEST floating-point format. 551169702Skan 552169702Skan If the host and target formats agree, we just copy the raw data 553169702Skan into the appropriate type of variable and return, letting the host 554169702Skan increase precision as necessary. Otherwise, we call the conversion 555169702Skan routine and let it do the dirty work. */ 556169702Skan 557169702Skan#ifndef HOST_FLOAT_FORMAT 558169702Skan#define HOST_FLOAT_FORMAT 0 559169702Skan#endif 560169702Skan#ifndef HOST_DOUBLE_FORMAT 561169702Skan#define HOST_DOUBLE_FORMAT 0 562169702Skan#endif 563169702Skan#ifndef HOST_LONG_DOUBLE_FORMAT 564169702Skan#define HOST_LONG_DOUBLE_FORMAT 0 565169702Skan#endif 566169702Skan 567169702Skanstatic const struct floatformat *host_float_format = HOST_FLOAT_FORMAT; 568169702Skanstatic const struct floatformat *host_double_format = HOST_DOUBLE_FORMAT; 569169702Skanstatic const struct floatformat *host_long_double_format = HOST_LONG_DOUBLE_FORMAT; 570169702Skan 571169702Skanvoid 572169702Skanfloatformat_to_doublest (const struct floatformat *fmt, 573169702Skan const void *in, DOUBLEST *out) 574169702Skan{ 575169702Skan gdb_assert (fmt != NULL); 576169702Skan if (fmt == host_float_format) 577169702Skan { 578169702Skan float val; 579169702Skan memcpy (&val, in, sizeof (val)); 580169702Skan *out = val; 581169702Skan } 582169702Skan else if (fmt == host_double_format) 583169702Skan { 584169702Skan double val; 585169702Skan memcpy (&val, in, sizeof (val)); 586169702Skan *out = val; 587169702Skan } 588169702Skan else if (fmt == host_long_double_format) 589169702Skan { 590169702Skan long double val; 591169702Skan memcpy (&val, in, sizeof (val)); 592169702Skan *out = val; 593169702Skan } 594169702Skan else 595169702Skan convert_floatformat_to_doublest (fmt, in, out); 596169702Skan} 597169702Skan 598169702Skanvoid 599169702Skanfloatformat_from_doublest (const struct floatformat *fmt, 60018334Speter const DOUBLEST *in, void *out) 60118334Speter{ 60218334Speter gdb_assert (fmt != NULL); 60318334Speter if (fmt == host_float_format) 60418334Speter { 60518334Speter float val = *in; 60618334Speter memcpy (out, &val, sizeof (val)); 60718334Speter } 60818334Speter else if (fmt == host_double_format) 60918334Speter { 610169702Skan double val = *in; 611169702Skan memcpy (out, &val, sizeof (val)); 612169702Skan } 61318334Speter else if (fmt == host_long_double_format) 61452518Sobrien { 61552518Sobrien long double val = *in; 61690091Sobrien memcpy (out, &val, sizeof (val)); 617169702Skan } 618169702Skan else 61918334Speter convert_doublest_to_floatformat (fmt, in, out); 62090091Sobrien} 621169702Skan 622102794Skan 62318334Speter/* Return a floating-point format for a floating-point variable of 62418334Speter length LEN. Return NULL, if no suitable floating-point format 62518334Speter could be found. 626169702Skan 62718334Speter We need this functionality since information about the 628169702Skan floating-point format of a type is not always available to GDB; the 629169702Skan debug information typically only tells us the size of a 630169702Skan floating-point type. 63152518Sobrien 63252518Sobrien FIXME: kettenis/2001-10-28: In many places, particularly in 63390091Sobrien target-dependent code, the format of floating-point types is known, 63490091Sobrien but not passed on by GDB. This should be fixed. */ 63552518Sobrien 63652518Sobrienstatic const struct floatformat * 637169702Skanfloatformat_from_length (int len) 63890091Sobrien{ 63952518Sobrien if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) 64052518Sobrien return TARGET_FLOAT_FORMAT; 64152518Sobrien else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) 64252518Sobrien return TARGET_DOUBLE_FORMAT; 64352518Sobrien else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) 644169702Skan return TARGET_LONG_DOUBLE_FORMAT; 645169702Skan /* On i386 the 'long double' type takes 96 bits, 646169702Skan while the real number of used bits is only 80, 647169702Skan both in processor and in memory. 648169702Skan The code below accepts the real bit size. */ 649169702Skan else if ((TARGET_LONG_DOUBLE_FORMAT != NULL) 650169702Skan && (len * TARGET_CHAR_BIT == 651169702Skan TARGET_LONG_DOUBLE_FORMAT->totalsize)) 652169702Skan return TARGET_LONG_DOUBLE_FORMAT; 653169702Skan 654169702Skan return NULL; 655169702Skan} 656169702Skan 657169702Skanconst struct floatformat * 658169702Skanfloatformat_from_type (const struct type *type) 659169702Skan{ 660169702Skan gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 661169702Skan if (TYPE_FLOATFORMAT (type) != NULL) 662169702Skan return TYPE_FLOATFORMAT (type); 663169702Skan else 664169702Skan return floatformat_from_length (TYPE_LENGTH (type)); 665169702Skan} 666169702Skan 667169702Skan/* If the host doesn't define NAN, use zero instead. */ 668169702Skan#ifndef NAN 669169702Skan#define NAN 0.0 67018334Speter#endif 67118334Speter 67218334Speter/* Extract a floating-point number of length LEN from a target-order 67318334Speter byte-stream at ADDR. Returns the value as type DOUBLEST. */ 674169702Skan 675169702Skanstatic DOUBLEST 676169702Skanextract_floating_by_length (const void *addr, int len) 67718334Speter{ 67818334Speter const struct floatformat *fmt = floatformat_from_length (len); 67918334Speter DOUBLEST val; 68090091Sobrien 68118334Speter if (fmt == NULL) 68252518Sobrien { 68352268Sobrien warning ("Can't extract a floating-point number of %d bytes.", len); 68418334Speter return NAN; 68518334Speter } 68618334Speter 687132732Skan floatformat_to_doublest (fmt, addr, &val); 68818334Speter return val; 68918334Speter} 69018334Speter 69118334SpeterDOUBLEST 692169702Skandeprecated_extract_floating (const void *addr, int len) 69352518Sobrien{ 69418334Speter return extract_floating_by_length (addr, len); 69590091Sobrien} 696169702Skan 69718334Speter/* Store VAL as a floating-point number of length LEN to a 69852268Sobrien target-order byte-stream at ADDR. */ 69952268Sobrien 70018334Speterstatic void 70118334Speterstore_floating_by_length (void *addr, int len, DOUBLEST val) 70218334Speter{ 70318334Speter const struct floatformat *fmt = floatformat_from_length (len); 70418334Speter 70518334Speter if (fmt == NULL) 70690091Sobrien { 70718334Speter warning ("Can't store a floating-point number of %d bytes.", len); 708169702Skan memset (addr, 0, len); 70918334Speter return; 71052268Sobrien } 71152268Sobrien 712132732Skan floatformat_from_doublest (fmt, &val, addr); 71352268Sobrien} 71452518Sobrien 71552518Sobrienvoid 71652518Sobriendeprecated_store_floating (void *addr, int len, DOUBLEST val) 71752268Sobrien{ 71852518Sobrien store_floating_by_length (addr, len, val); 71952518Sobrien} 72052518Sobrien 721169702Skan/* Extract a floating-point number of type TYPE from a target-order 72252518Sobrien byte-stream at ADDR. Returns the value as type DOUBLEST. */ 72352763Sobrien 724132732SkanDOUBLEST 72552763Sobrienextract_typed_floating (const void *addr, const struct type *type) 72652518Sobrien{ 72752518Sobrien DOUBLEST retval; 72852518Sobrien 72952518Sobrien gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 73018334Speter 73118334Speter if (TYPE_FLOATFORMAT (type) == NULL) 73218334Speter /* Not all code remembers to set the FLOATFORMAT (language 73318334Speter specific code? stabs?) so handle that here as a special case. */ 73418334Speter return extract_floating_by_length (addr, TYPE_LENGTH (type)); 73518334Speter 73618334Speter floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval); 737169702Skan return retval; 738169702Skan} 739169702Skan 740169702Skan/* Store VAL as a floating-point number of type TYPE to a target-order 74152268Sobrien byte-stream at ADDR. */ 74218334Speter 743169702Skanvoid 744169702Skanstore_typed_floating (void *addr, const struct type *type, DOUBLEST val) 745169702Skan{ 746169702Skan gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); 747169702Skan 748169702Skan /* FIXME: kettenis/2001-10-28: It is debatable whether we should 749169702Skan zero out any remaining bytes in the target buffer when TYPE is 750169702Skan longer than the actual underlying floating-point format. Perhaps 751169702Skan we should store a fixed bitpattern in those remaining bytes, 752169702Skan instead of zero, or perhaps we shouldn't touch those remaining 75318334Speter bytes at all. 754169702Skan 755169702Skan NOTE: cagney/2001-10-28: With the way things currently work, it 75618334Speter isn't a good idea to leave the end bits undefined. This is 75718334Speter because GDB writes out the entire sizeof(<floating>) bits of the 758169702Skan floating-point type even though the value might only be stored 75918334Speter in, and the target processor may only refer to, the first N < 76018334Speter TYPE_LENGTH (type) bits. If the end of the buffer wasn't 76190091Sobrien initialized, GDB would write undefined data to the target. An 762169702Skan errant program, refering to that undefined data, would then 763169702Skan become non-deterministic. 76418334Speter 765169702Skan See also the function convert_typed_floating below. */ 766169702Skan memset (addr, 0, TYPE_LENGTH (type)); 76752268Sobrien 768102794Skan if (TYPE_FLOATFORMAT (type) == NULL) 769102794Skan /* Not all code remembers to set the FLOATFORMAT (language 770102794Skan specific code? stabs?) so handle that here as a special case. */ 771102794Skan store_floating_by_length (addr, TYPE_LENGTH (type), val); 77290091Sobrien else 77390091Sobrien floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr); 77490091Sobrien} 775102794Skan 776102794Skan/* Convert a floating-point number of type FROM_TYPE from a 77790091Sobrien target-order byte-stream at FROM to a floating-point number of type 77890091Sobrien TO_TYPE, and store it to a target-order byte-stream at TO. */ 77990091Sobrien 78090091Sobrienvoid 781102794Skanconvert_typed_floating (const void *from, const struct type *from_type, 782102794Skan void *to, const struct type *to_type) 78390091Sobrien{ 784169702Skan const struct floatformat *from_fmt = floatformat_from_type (from_type); 78590091Sobrien const struct floatformat *to_fmt = floatformat_from_type (to_type); 786102794Skan 78718334Speter gdb_assert (TYPE_CODE (from_type) == TYPE_CODE_FLT); 78852518Sobrien gdb_assert (TYPE_CODE (to_type) == TYPE_CODE_FLT); 78952518Sobrien 79052518Sobrien if (from_fmt == NULL || to_fmt == NULL) 79152518Sobrien { 79252518Sobrien /* If we don't know the floating-point format of FROM_TYPE or 793132732Skan TO_TYPE, there's not much we can do. We might make the 79452518Sobrien assumption that if the length of FROM_TYPE and TO_TYPE match, 79552518Sobrien their floating-point format would match too, but that 79652518Sobrien assumption might be wrong on targets that support 79752268Sobrien floating-point types that only differ in endianness for 79896283Sobrien example. So we warn instead, and zero out the target buffer. */ 79996283Sobrien warning ("Can't convert floating-point number to desired type."); 80096283Sobrien memset (to, 0, TYPE_LENGTH (to_type)); 80196283Sobrien } 80252268Sobrien else if (from_fmt == to_fmt) 80352268Sobrien { 80452268Sobrien /* We're in business. The floating-point format of FROM_TYPE 80552268Sobrien and TO_TYPE match. However, even though the floating-point 80652268Sobrien format matches, the length of the type might still be 80718334Speter different. Make sure we don't overrun any buffers. See 80852268Sobrien comment in store_typed_floating for a discussion about 809132732Skan zeroing out remaining bytes in the target buffer. */ 810132732Skan memset (to, 0, TYPE_LENGTH (to_type)); 81152268Sobrien memcpy (to, from, min (TYPE_LENGTH (from_type), TYPE_LENGTH (to_type))); 81296283Sobrien } 81396283Sobrien else 814169702Skan { 81596283Sobrien /* The floating-point types don't match. The best we can do 81690091Sobrien (aport from simulating the target FPU) is converting to the 81752268Sobrien widest floating-point type supported by the host, and then 81896283Sobrien again to the desired type. */ 81996283Sobrien DOUBLEST d; 82096283Sobrien 82196283Sobrien floatformat_to_doublest (from_fmt, from, &d); 82296283Sobrien floatformat_from_doublest (to_fmt, &d, to); 82396283Sobrien } 824169702Skan} 825169702Skan