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