xref: /dflybsd-src/contrib/gdb-7/gdb/doublest.c (revision cf7f2e2d389e8012d562650bd94d7e433f449d6e)
15796c8dcSSimon Schubert /* Floating point routines for GDB, the GNU debugger.
25796c8dcSSimon Schubert 
35796c8dcSSimon Schubert    Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
4*cf7f2e2dSJohn Marino    1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010
55796c8dcSSimon Schubert    Free Software Foundation, Inc.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This file is part of GDB.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert    (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175796c8dcSSimon Schubert    GNU General Public License for more details.
185796c8dcSSimon Schubert 
195796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
215796c8dcSSimon Schubert 
225796c8dcSSimon Schubert /* Support for converting target fp numbers into host DOUBLEST format.  */
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert /* XXX - This code should really be in libiberty/floatformat.c,
255796c8dcSSimon Schubert    however configuration issues with libiberty made this very
265796c8dcSSimon Schubert    difficult to do in the available time.  */
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert #include "defs.h"
295796c8dcSSimon Schubert #include "doublest.h"
305796c8dcSSimon Schubert #include "floatformat.h"
315796c8dcSSimon Schubert #include "gdb_assert.h"
325796c8dcSSimon Schubert #include "gdb_string.h"
335796c8dcSSimon Schubert #include "gdbtypes.h"
345796c8dcSSimon Schubert #include <math.h>		/* ldexp */
355796c8dcSSimon Schubert 
365796c8dcSSimon Schubert /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
375796c8dcSSimon Schubert    going to bother with trying to muck around with whether it is defined in
385796c8dcSSimon Schubert    a system header, what we do if not, etc.  */
395796c8dcSSimon Schubert #define FLOATFORMAT_CHAR_BIT 8
405796c8dcSSimon Schubert 
415796c8dcSSimon Schubert /* The number of bytes that the largest floating-point type that we
425796c8dcSSimon Schubert    can convert to doublest will need.  */
435796c8dcSSimon Schubert #define FLOATFORMAT_LARGEST_BYTES 16
445796c8dcSSimon Schubert 
455796c8dcSSimon Schubert /* Extract a field which starts at START and is LEN bytes long.  DATA and
465796c8dcSSimon Schubert    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
475796c8dcSSimon Schubert static unsigned long
485796c8dcSSimon Schubert get_field (const bfd_byte *data, enum floatformat_byteorders order,
495796c8dcSSimon Schubert 	   unsigned int total_len, unsigned int start, unsigned int len)
505796c8dcSSimon Schubert {
515796c8dcSSimon Schubert   unsigned long result;
525796c8dcSSimon Schubert   unsigned int cur_byte;
535796c8dcSSimon Schubert   int cur_bitshift;
545796c8dcSSimon Schubert 
555796c8dcSSimon Schubert   /* Caller must byte-swap words before calling this routine.  */
565796c8dcSSimon Schubert   gdb_assert (order == floatformat_little || order == floatformat_big);
575796c8dcSSimon Schubert 
585796c8dcSSimon Schubert   /* Start at the least significant part of the field.  */
595796c8dcSSimon Schubert   if (order == floatformat_little)
605796c8dcSSimon Schubert     {
615796c8dcSSimon Schubert       /* We start counting from the other end (i.e, from the high bytes
625796c8dcSSimon Schubert 	 rather than the low bytes).  As such, we need to be concerned
635796c8dcSSimon Schubert 	 with what happens if bit 0 doesn't start on a byte boundary.
645796c8dcSSimon Schubert 	 I.e, we need to properly handle the case where total_len is
655796c8dcSSimon Schubert 	 not evenly divisible by 8.  So we compute ``excess'' which
665796c8dcSSimon Schubert 	 represents the number of bits from the end of our starting
675796c8dcSSimon Schubert 	 byte needed to get to bit 0. */
685796c8dcSSimon Schubert       int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
69*cf7f2e2dSJohn Marino 
705796c8dcSSimon Schubert       cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
715796c8dcSSimon Schubert                  - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
725796c8dcSSimon Schubert       cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
735796c8dcSSimon Schubert                      - FLOATFORMAT_CHAR_BIT;
745796c8dcSSimon Schubert     }
755796c8dcSSimon Schubert   else
765796c8dcSSimon Schubert     {
775796c8dcSSimon Schubert       cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
785796c8dcSSimon Schubert       cur_bitshift =
795796c8dcSSimon Schubert 	((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
805796c8dcSSimon Schubert     }
815796c8dcSSimon Schubert   if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
825796c8dcSSimon Schubert     result = *(data + cur_byte) >> (-cur_bitshift);
835796c8dcSSimon Schubert   else
845796c8dcSSimon Schubert     result = 0;
855796c8dcSSimon Schubert   cur_bitshift += FLOATFORMAT_CHAR_BIT;
865796c8dcSSimon Schubert   if (order == floatformat_little)
875796c8dcSSimon Schubert     ++cur_byte;
885796c8dcSSimon Schubert   else
895796c8dcSSimon Schubert     --cur_byte;
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert   /* Move towards the most significant part of the field.  */
925796c8dcSSimon Schubert   while (cur_bitshift < len)
935796c8dcSSimon Schubert     {
945796c8dcSSimon Schubert       result |= (unsigned long)*(data + cur_byte) << cur_bitshift;
955796c8dcSSimon Schubert       cur_bitshift += FLOATFORMAT_CHAR_BIT;
965796c8dcSSimon Schubert       switch (order)
975796c8dcSSimon Schubert 	{
985796c8dcSSimon Schubert 	case floatformat_little:
995796c8dcSSimon Schubert 	  ++cur_byte;
1005796c8dcSSimon Schubert 	  break;
1015796c8dcSSimon Schubert 	case floatformat_big:
1025796c8dcSSimon Schubert 	  --cur_byte;
1035796c8dcSSimon Schubert 	  break;
1045796c8dcSSimon Schubert 	}
1055796c8dcSSimon Schubert     }
1065796c8dcSSimon Schubert   if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT)
1075796c8dcSSimon Schubert     /* Mask out bits which are not part of the field */
1085796c8dcSSimon Schubert     result &= ((1UL << len) - 1);
1095796c8dcSSimon Schubert   return result;
1105796c8dcSSimon Schubert }
1115796c8dcSSimon Schubert 
1125796c8dcSSimon Schubert /* Normalize the byte order of FROM into TO.  If no normalization is
1135796c8dcSSimon Schubert    needed then FMT->byteorder is returned and TO is not changed;
1145796c8dcSSimon Schubert    otherwise the format of the normalized form in TO is returned.  */
1155796c8dcSSimon Schubert 
1165796c8dcSSimon Schubert static enum floatformat_byteorders
1175796c8dcSSimon Schubert floatformat_normalize_byteorder (const struct floatformat *fmt,
1185796c8dcSSimon Schubert 				 const void *from, void *to)
1195796c8dcSSimon Schubert {
1205796c8dcSSimon Schubert   const unsigned char *swapin;
1215796c8dcSSimon Schubert   unsigned char *swapout;
1225796c8dcSSimon Schubert   int words;
1235796c8dcSSimon Schubert 
1245796c8dcSSimon Schubert   if (fmt->byteorder == floatformat_little
1255796c8dcSSimon Schubert       || fmt->byteorder == floatformat_big)
1265796c8dcSSimon Schubert     return fmt->byteorder;
1275796c8dcSSimon Schubert 
1285796c8dcSSimon Schubert   words = fmt->totalsize / FLOATFORMAT_CHAR_BIT;
1295796c8dcSSimon Schubert   words >>= 2;
1305796c8dcSSimon Schubert 
1315796c8dcSSimon Schubert   swapout = (unsigned char *)to;
1325796c8dcSSimon Schubert   swapin = (const unsigned char *)from;
1335796c8dcSSimon Schubert 
1345796c8dcSSimon Schubert   if (fmt->byteorder == floatformat_vax)
1355796c8dcSSimon Schubert     {
1365796c8dcSSimon Schubert       while (words-- > 0)
1375796c8dcSSimon Schubert 	{
1385796c8dcSSimon Schubert 	  *swapout++ = swapin[1];
1395796c8dcSSimon Schubert 	  *swapout++ = swapin[0];
1405796c8dcSSimon Schubert 	  *swapout++ = swapin[3];
1415796c8dcSSimon Schubert 	  *swapout++ = swapin[2];
1425796c8dcSSimon Schubert 	  swapin += 4;
1435796c8dcSSimon Schubert 	}
1445796c8dcSSimon Schubert       /* This may look weird, since VAX is little-endian, but it is
1455796c8dcSSimon Schubert 	 easier to translate to big-endian than to little-endian.  */
1465796c8dcSSimon Schubert       return floatformat_big;
1475796c8dcSSimon Schubert     }
1485796c8dcSSimon Schubert   else
1495796c8dcSSimon Schubert     {
1505796c8dcSSimon Schubert       gdb_assert (fmt->byteorder == floatformat_littlebyte_bigword);
1515796c8dcSSimon Schubert 
1525796c8dcSSimon Schubert       while (words-- > 0)
1535796c8dcSSimon Schubert 	{
1545796c8dcSSimon Schubert 	  *swapout++ = swapin[3];
1555796c8dcSSimon Schubert 	  *swapout++ = swapin[2];
1565796c8dcSSimon Schubert 	  *swapout++ = swapin[1];
1575796c8dcSSimon Schubert 	  *swapout++ = swapin[0];
1585796c8dcSSimon Schubert 	  swapin += 4;
1595796c8dcSSimon Schubert 	}
1605796c8dcSSimon Schubert       return floatformat_big;
1615796c8dcSSimon Schubert     }
1625796c8dcSSimon Schubert }
1635796c8dcSSimon Schubert 
1645796c8dcSSimon Schubert /* Convert from FMT to a DOUBLEST.
1655796c8dcSSimon Schubert    FROM is the address of the extended float.
1665796c8dcSSimon Schubert    Store the DOUBLEST in *TO.  */
1675796c8dcSSimon Schubert 
1685796c8dcSSimon Schubert static void
1695796c8dcSSimon Schubert convert_floatformat_to_doublest (const struct floatformat *fmt,
1705796c8dcSSimon Schubert 				 const void *from,
1715796c8dcSSimon Schubert 				 DOUBLEST *to)
1725796c8dcSSimon Schubert {
1735796c8dcSSimon Schubert   unsigned char *ufrom = (unsigned char *) from;
1745796c8dcSSimon Schubert   DOUBLEST dto;
1755796c8dcSSimon Schubert   long exponent;
1765796c8dcSSimon Schubert   unsigned long mant;
1775796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
1785796c8dcSSimon Schubert   int mant_bits_left;
1795796c8dcSSimon Schubert   int special_exponent;		/* It's a NaN, denorm or zero */
1805796c8dcSSimon Schubert   enum floatformat_byteorders order;
1815796c8dcSSimon Schubert   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
1825796c8dcSSimon Schubert   enum float_kind kind;
1835796c8dcSSimon Schubert 
1845796c8dcSSimon Schubert   gdb_assert (fmt->totalsize
1855796c8dcSSimon Schubert 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert   /* For non-numbers, reuse libiberty's logic to find the correct
1885796c8dcSSimon Schubert      format.  We do not lose any precision in this case by passing
1895796c8dcSSimon Schubert      through a double.  */
1905796c8dcSSimon Schubert   kind = floatformat_classify (fmt, from);
1915796c8dcSSimon Schubert   if (kind == float_infinite || kind == float_nan)
1925796c8dcSSimon Schubert     {
1935796c8dcSSimon Schubert       double dto;
194*cf7f2e2dSJohn Marino 
1955796c8dcSSimon Schubert       floatformat_to_double (fmt, from, &dto);
1965796c8dcSSimon Schubert       *to = (DOUBLEST) dto;
1975796c8dcSSimon Schubert       return;
1985796c8dcSSimon Schubert     }
1995796c8dcSSimon Schubert 
2005796c8dcSSimon Schubert   order = floatformat_normalize_byteorder (fmt, ufrom, newfrom);
2015796c8dcSSimon Schubert 
2025796c8dcSSimon Schubert   if (order != fmt->byteorder)
2035796c8dcSSimon Schubert     ufrom = newfrom;
2045796c8dcSSimon Schubert 
2055796c8dcSSimon Schubert   if (fmt->split_half)
2065796c8dcSSimon Schubert     {
2075796c8dcSSimon Schubert       DOUBLEST dtop, dbot;
208*cf7f2e2dSJohn Marino 
2095796c8dcSSimon Schubert       floatformat_to_doublest (fmt->split_half, ufrom, &dtop);
2105796c8dcSSimon Schubert       /* Preserve the sign of 0, which is the sign of the top
2115796c8dcSSimon Schubert 	 half.  */
2125796c8dcSSimon Schubert       if (dtop == 0.0)
2135796c8dcSSimon Schubert 	{
2145796c8dcSSimon Schubert 	  *to = dtop;
2155796c8dcSSimon Schubert 	  return;
2165796c8dcSSimon Schubert 	}
2175796c8dcSSimon Schubert       floatformat_to_doublest (fmt->split_half,
2185796c8dcSSimon Schubert 			     ufrom + fmt->totalsize / FLOATFORMAT_CHAR_BIT / 2,
2195796c8dcSSimon Schubert 			     &dbot);
2205796c8dcSSimon Schubert       *to = dtop + dbot;
2215796c8dcSSimon Schubert       return;
2225796c8dcSSimon Schubert     }
2235796c8dcSSimon Schubert 
2245796c8dcSSimon Schubert   exponent = get_field (ufrom, order, fmt->totalsize, fmt->exp_start,
2255796c8dcSSimon Schubert 			fmt->exp_len);
2265796c8dcSSimon Schubert   /* Note that if exponent indicates a NaN, we can't really do anything useful
2275796c8dcSSimon Schubert      (not knowing if the host has NaN's, or how to build one).  So it will
2285796c8dcSSimon Schubert      end up as an infinity or something close; that is OK.  */
2295796c8dcSSimon Schubert 
2305796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
2315796c8dcSSimon Schubert   mant_off = fmt->man_start;
2325796c8dcSSimon Schubert   dto = 0.0;
2335796c8dcSSimon Schubert 
2345796c8dcSSimon Schubert   special_exponent = exponent == 0 || exponent == fmt->exp_nan;
2355796c8dcSSimon Schubert 
2365796c8dcSSimon Schubert   /* Don't bias NaNs. Use minimum exponent for denorms. For simplicity,
2375796c8dcSSimon Schubert      we don't check for zero as the exponent doesn't matter.  Note the cast
2385796c8dcSSimon Schubert      to int; exp_bias is unsigned, so it's important to make sure the
2395796c8dcSSimon Schubert      operation is done in signed arithmetic.  */
2405796c8dcSSimon Schubert   if (!special_exponent)
2415796c8dcSSimon Schubert     exponent -= fmt->exp_bias;
2425796c8dcSSimon Schubert   else if (exponent == 0)
2435796c8dcSSimon Schubert     exponent = 1 - fmt->exp_bias;
2445796c8dcSSimon Schubert 
2455796c8dcSSimon Schubert   /* Build the result algebraically.  Might go infinite, underflow, etc;
2465796c8dcSSimon Schubert      who cares. */
2475796c8dcSSimon Schubert 
2485796c8dcSSimon Schubert /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
2495796c8dcSSimon Schubert    increment the exponent by one to account for the integer bit.  */
2505796c8dcSSimon Schubert 
2515796c8dcSSimon Schubert   if (!special_exponent)
2525796c8dcSSimon Schubert     {
2535796c8dcSSimon Schubert       if (fmt->intbit == floatformat_intbit_no)
2545796c8dcSSimon Schubert 	dto = ldexp (1.0, exponent);
2555796c8dcSSimon Schubert       else
2565796c8dcSSimon Schubert 	exponent++;
2575796c8dcSSimon Schubert     }
2585796c8dcSSimon Schubert 
2595796c8dcSSimon Schubert   while (mant_bits_left > 0)
2605796c8dcSSimon Schubert     {
2615796c8dcSSimon Schubert       mant_bits = min (mant_bits_left, 32);
2625796c8dcSSimon Schubert 
2635796c8dcSSimon Schubert       mant = get_field (ufrom, order, fmt->totalsize, mant_off, mant_bits);
2645796c8dcSSimon Schubert 
2655796c8dcSSimon Schubert       dto += ldexp ((double) mant, exponent - mant_bits);
2665796c8dcSSimon Schubert       exponent -= mant_bits;
2675796c8dcSSimon Schubert       mant_off += mant_bits;
2685796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
2695796c8dcSSimon Schubert     }
2705796c8dcSSimon Schubert 
2715796c8dcSSimon Schubert   /* Negate it if negative.  */
2725796c8dcSSimon Schubert   if (get_field (ufrom, order, fmt->totalsize, fmt->sign_start, 1))
2735796c8dcSSimon Schubert     dto = -dto;
2745796c8dcSSimon Schubert   *to = dto;
2755796c8dcSSimon Schubert }
2765796c8dcSSimon Schubert 
2775796c8dcSSimon Schubert static void put_field (unsigned char *, enum floatformat_byteorders,
2785796c8dcSSimon Schubert 		       unsigned int,
2795796c8dcSSimon Schubert 		       unsigned int, unsigned int, unsigned long);
2805796c8dcSSimon Schubert 
2815796c8dcSSimon Schubert /* Set a field which starts at START and is LEN bytes long.  DATA and
2825796c8dcSSimon Schubert    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
2835796c8dcSSimon Schubert static void
2845796c8dcSSimon Schubert put_field (unsigned char *data, enum floatformat_byteorders order,
2855796c8dcSSimon Schubert 	   unsigned int total_len, unsigned int start, unsigned int len,
2865796c8dcSSimon Schubert 	   unsigned long stuff_to_put)
2875796c8dcSSimon Schubert {
2885796c8dcSSimon Schubert   unsigned int cur_byte;
2895796c8dcSSimon Schubert   int cur_bitshift;
2905796c8dcSSimon Schubert 
2915796c8dcSSimon Schubert   /* Caller must byte-swap words before calling this routine.  */
2925796c8dcSSimon Schubert   gdb_assert (order == floatformat_little || order == floatformat_big);
2935796c8dcSSimon Schubert 
2945796c8dcSSimon Schubert   /* Start at the least significant part of the field.  */
2955796c8dcSSimon Schubert   if (order == floatformat_little)
2965796c8dcSSimon Schubert     {
2975796c8dcSSimon Schubert       int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
298*cf7f2e2dSJohn Marino 
2995796c8dcSSimon Schubert       cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
3005796c8dcSSimon Schubert                  - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
3015796c8dcSSimon Schubert       cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
3025796c8dcSSimon Schubert                      - FLOATFORMAT_CHAR_BIT;
3035796c8dcSSimon Schubert     }
3045796c8dcSSimon Schubert   else
3055796c8dcSSimon Schubert     {
3065796c8dcSSimon Schubert       cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
3075796c8dcSSimon Schubert       cur_bitshift =
3085796c8dcSSimon Schubert 	((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
3095796c8dcSSimon Schubert     }
3105796c8dcSSimon Schubert   if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
3115796c8dcSSimon Schubert     {
3125796c8dcSSimon Schubert       *(data + cur_byte) &=
3135796c8dcSSimon Schubert 	~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1)
3145796c8dcSSimon Schubert 	  << (-cur_bitshift));
3155796c8dcSSimon Schubert       *(data + cur_byte) |=
3165796c8dcSSimon Schubert 	(stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
3175796c8dcSSimon Schubert     }
3185796c8dcSSimon Schubert   cur_bitshift += FLOATFORMAT_CHAR_BIT;
3195796c8dcSSimon Schubert   if (order == floatformat_little)
3205796c8dcSSimon Schubert     ++cur_byte;
3215796c8dcSSimon Schubert   else
3225796c8dcSSimon Schubert     --cur_byte;
3235796c8dcSSimon Schubert 
3245796c8dcSSimon Schubert   /* Move towards the most significant part of the field.  */
3255796c8dcSSimon Schubert   while (cur_bitshift < len)
3265796c8dcSSimon Schubert     {
3275796c8dcSSimon Schubert       if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
3285796c8dcSSimon Schubert 	{
3295796c8dcSSimon Schubert 	  /* This is the last byte.  */
3305796c8dcSSimon Schubert 	  *(data + cur_byte) &=
3315796c8dcSSimon Schubert 	    ~((1 << (len - cur_bitshift)) - 1);
3325796c8dcSSimon Schubert 	  *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
3335796c8dcSSimon Schubert 	}
3345796c8dcSSimon Schubert       else
3355796c8dcSSimon Schubert 	*(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
3365796c8dcSSimon Schubert 			      & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
3375796c8dcSSimon Schubert       cur_bitshift += FLOATFORMAT_CHAR_BIT;
3385796c8dcSSimon Schubert       if (order == floatformat_little)
3395796c8dcSSimon Schubert 	++cur_byte;
3405796c8dcSSimon Schubert       else
3415796c8dcSSimon Schubert 	--cur_byte;
3425796c8dcSSimon Schubert     }
3435796c8dcSSimon Schubert }
3445796c8dcSSimon Schubert 
3455796c8dcSSimon Schubert #ifdef HAVE_LONG_DOUBLE
3465796c8dcSSimon Schubert /* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR.
3475796c8dcSSimon Schubert    The range of the returned value is >= 0.5 and < 1.0.  This is equivalent to
3485796c8dcSSimon Schubert    frexp, but operates on the long double data type.  */
3495796c8dcSSimon Schubert 
3505796c8dcSSimon Schubert static long double ldfrexp (long double value, int *eptr);
3515796c8dcSSimon Schubert 
3525796c8dcSSimon Schubert static long double
3535796c8dcSSimon Schubert ldfrexp (long double value, int *eptr)
3545796c8dcSSimon Schubert {
3555796c8dcSSimon Schubert   long double tmp;
3565796c8dcSSimon Schubert   int exp;
3575796c8dcSSimon Schubert 
3585796c8dcSSimon Schubert   /* Unfortunately, there are no portable functions for extracting the exponent
3595796c8dcSSimon Schubert      of a long double, so we have to do it iteratively by multiplying or dividing
3605796c8dcSSimon Schubert      by two until the fraction is between 0.5 and 1.0.  */
3615796c8dcSSimon Schubert 
3625796c8dcSSimon Schubert   if (value < 0.0l)
3635796c8dcSSimon Schubert     value = -value;
3645796c8dcSSimon Schubert 
3655796c8dcSSimon Schubert   tmp = 1.0l;
3665796c8dcSSimon Schubert   exp = 0;
3675796c8dcSSimon Schubert 
3685796c8dcSSimon Schubert   if (value >= tmp)		/* Value >= 1.0 */
3695796c8dcSSimon Schubert     while (value >= tmp)
3705796c8dcSSimon Schubert       {
3715796c8dcSSimon Schubert 	tmp *= 2.0l;
3725796c8dcSSimon Schubert 	exp++;
3735796c8dcSSimon Schubert       }
3745796c8dcSSimon Schubert   else if (value != 0.0l)	/* Value < 1.0  and > 0.0 */
3755796c8dcSSimon Schubert     {
3765796c8dcSSimon Schubert       while (value < tmp)
3775796c8dcSSimon Schubert 	{
3785796c8dcSSimon Schubert 	  tmp /= 2.0l;
3795796c8dcSSimon Schubert 	  exp--;
3805796c8dcSSimon Schubert 	}
3815796c8dcSSimon Schubert       tmp *= 2.0l;
3825796c8dcSSimon Schubert       exp++;
3835796c8dcSSimon Schubert     }
3845796c8dcSSimon Schubert 
3855796c8dcSSimon Schubert   *eptr = exp;
3865796c8dcSSimon Schubert   return value / tmp;
3875796c8dcSSimon Schubert }
3885796c8dcSSimon Schubert #endif /* HAVE_LONG_DOUBLE */
3895796c8dcSSimon Schubert 
3905796c8dcSSimon Schubert 
3915796c8dcSSimon Schubert /* The converse: convert the DOUBLEST *FROM to an extended float and
3925796c8dcSSimon Schubert    store where TO points.  Neither FROM nor TO have any alignment
3935796c8dcSSimon Schubert    restrictions.  */
3945796c8dcSSimon Schubert 
3955796c8dcSSimon Schubert static void
3965796c8dcSSimon Schubert convert_doublest_to_floatformat (CONST struct floatformat *fmt,
3975796c8dcSSimon Schubert 				 const DOUBLEST *from, void *to)
3985796c8dcSSimon Schubert {
3995796c8dcSSimon Schubert   DOUBLEST dfrom;
4005796c8dcSSimon Schubert   int exponent;
4015796c8dcSSimon Schubert   DOUBLEST mant;
4025796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
4035796c8dcSSimon Schubert   int mant_bits_left;
4045796c8dcSSimon Schubert   unsigned char *uto = (unsigned char *) to;
4055796c8dcSSimon Schubert   enum floatformat_byteorders order = fmt->byteorder;
4065796c8dcSSimon Schubert   unsigned char newto[FLOATFORMAT_LARGEST_BYTES];
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert   if (order != floatformat_little)
4095796c8dcSSimon Schubert     order = floatformat_big;
4105796c8dcSSimon Schubert 
4115796c8dcSSimon Schubert   if (order != fmt->byteorder)
4125796c8dcSSimon Schubert     uto = newto;
4135796c8dcSSimon Schubert 
4145796c8dcSSimon Schubert   memcpy (&dfrom, from, sizeof (dfrom));
4155796c8dcSSimon Schubert   memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1)
4165796c8dcSSimon Schubert                     / FLOATFORMAT_CHAR_BIT);
4175796c8dcSSimon Schubert 
4185796c8dcSSimon Schubert   if (fmt->split_half)
4195796c8dcSSimon Schubert     {
4205796c8dcSSimon Schubert       /* Use static volatile to ensure that any excess precision is
4215796c8dcSSimon Schubert 	 removed via storing in memory, and so the top half really is
4225796c8dcSSimon Schubert 	 the result of converting to double.  */
4235796c8dcSSimon Schubert       static volatile double dtop, dbot;
4245796c8dcSSimon Schubert       DOUBLEST dtopnv, dbotnv;
425*cf7f2e2dSJohn Marino 
4265796c8dcSSimon Schubert       dtop = (double) dfrom;
4275796c8dcSSimon Schubert       /* If the rounded top half is Inf, the bottom must be 0 not NaN
4285796c8dcSSimon Schubert 	 or Inf.  */
4295796c8dcSSimon Schubert       if (dtop + dtop == dtop && dtop != 0.0)
4305796c8dcSSimon Schubert 	dbot = 0.0;
4315796c8dcSSimon Schubert       else
4325796c8dcSSimon Schubert 	dbot = (double) (dfrom - (DOUBLEST) dtop);
4335796c8dcSSimon Schubert       dtopnv = dtop;
4345796c8dcSSimon Schubert       dbotnv = dbot;
4355796c8dcSSimon Schubert       floatformat_from_doublest (fmt->split_half, &dtopnv, uto);
4365796c8dcSSimon Schubert       floatformat_from_doublest (fmt->split_half, &dbotnv,
4375796c8dcSSimon Schubert 			       (uto
4385796c8dcSSimon Schubert 				+ fmt->totalsize / FLOATFORMAT_CHAR_BIT / 2));
4395796c8dcSSimon Schubert       return;
4405796c8dcSSimon Schubert     }
4415796c8dcSSimon Schubert 
4425796c8dcSSimon Schubert   if (dfrom == 0)
4435796c8dcSSimon Schubert     return;			/* Result is zero */
4445796c8dcSSimon Schubert   if (dfrom != dfrom)		/* Result is NaN */
4455796c8dcSSimon Schubert     {
4465796c8dcSSimon Schubert       /* From is NaN */
4475796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize, fmt->exp_start,
4485796c8dcSSimon Schubert 		 fmt->exp_len, fmt->exp_nan);
4495796c8dcSSimon Schubert       /* Be sure it's not infinity, but NaN value is irrel */
4505796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize, fmt->man_start,
4515796c8dcSSimon Schubert 		 32, 1);
4525796c8dcSSimon Schubert       goto finalize_byteorder;
4535796c8dcSSimon Schubert     }
4545796c8dcSSimon Schubert 
4555796c8dcSSimon Schubert   /* If negative, set the sign bit.  */
4565796c8dcSSimon Schubert   if (dfrom < 0)
4575796c8dcSSimon Schubert     {
4585796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize, fmt->sign_start, 1, 1);
4595796c8dcSSimon Schubert       dfrom = -dfrom;
4605796c8dcSSimon Schubert     }
4615796c8dcSSimon Schubert 
4625796c8dcSSimon Schubert   if (dfrom + dfrom == dfrom && dfrom != 0.0)	/* Result is Infinity */
4635796c8dcSSimon Schubert     {
4645796c8dcSSimon Schubert       /* Infinity exponent is same as NaN's.  */
4655796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize, fmt->exp_start,
4665796c8dcSSimon Schubert 		 fmt->exp_len, fmt->exp_nan);
4675796c8dcSSimon Schubert       /* Infinity mantissa is all zeroes.  */
4685796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize, fmt->man_start,
4695796c8dcSSimon Schubert 		 fmt->man_len, 0);
4705796c8dcSSimon Schubert       goto finalize_byteorder;
4715796c8dcSSimon Schubert     }
4725796c8dcSSimon Schubert 
4735796c8dcSSimon Schubert #ifdef HAVE_LONG_DOUBLE
4745796c8dcSSimon Schubert   mant = ldfrexp (dfrom, &exponent);
4755796c8dcSSimon Schubert #else
4765796c8dcSSimon Schubert   mant = frexp (dfrom, &exponent);
4775796c8dcSSimon Schubert #endif
4785796c8dcSSimon Schubert 
4795796c8dcSSimon Schubert   put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len,
4805796c8dcSSimon Schubert 	     exponent + fmt->exp_bias - 1);
4815796c8dcSSimon Schubert 
4825796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
4835796c8dcSSimon Schubert   mant_off = fmt->man_start;
4845796c8dcSSimon Schubert   while (mant_bits_left > 0)
4855796c8dcSSimon Schubert     {
4865796c8dcSSimon Schubert       unsigned long mant_long;
487*cf7f2e2dSJohn Marino 
4885796c8dcSSimon Schubert       mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
4895796c8dcSSimon Schubert 
4905796c8dcSSimon Schubert       mant *= 4294967296.0;
4915796c8dcSSimon Schubert       mant_long = ((unsigned long) mant) & 0xffffffffL;
4925796c8dcSSimon Schubert       mant -= mant_long;
4935796c8dcSSimon Schubert 
4945796c8dcSSimon Schubert       /* If the integer bit is implicit, then we need to discard it.
4955796c8dcSSimon Schubert          If we are discarding a zero, we should be (but are not) creating
4965796c8dcSSimon Schubert          a denormalized number which means adjusting the exponent
4975796c8dcSSimon Schubert          (I think).  */
4985796c8dcSSimon Schubert       if (mant_bits_left == fmt->man_len
4995796c8dcSSimon Schubert 	  && fmt->intbit == floatformat_intbit_no)
5005796c8dcSSimon Schubert 	{
5015796c8dcSSimon Schubert 	  mant_long <<= 1;
5025796c8dcSSimon Schubert 	  mant_long &= 0xffffffffL;
5035796c8dcSSimon Schubert           /* If we are processing the top 32 mantissa bits of a doublest
5045796c8dcSSimon Schubert              so as to convert to a float value with implied integer bit,
5055796c8dcSSimon Schubert              we will only be putting 31 of those 32 bits into the
5065796c8dcSSimon Schubert              final value due to the discarding of the top bit.  In the
5075796c8dcSSimon Schubert              case of a small float value where the number of mantissa
5085796c8dcSSimon Schubert              bits is less than 32, discarding the top bit does not alter
5095796c8dcSSimon Schubert              the number of bits we will be adding to the result.  */
5105796c8dcSSimon Schubert           if (mant_bits == 32)
5115796c8dcSSimon Schubert             mant_bits -= 1;
5125796c8dcSSimon Schubert 	}
5135796c8dcSSimon Schubert 
5145796c8dcSSimon Schubert       if (mant_bits < 32)
5155796c8dcSSimon Schubert 	{
5165796c8dcSSimon Schubert 	  /* The bits we want are in the most significant MANT_BITS bits of
5175796c8dcSSimon Schubert 	     mant_long.  Move them to the least significant.  */
5185796c8dcSSimon Schubert 	  mant_long >>= 32 - mant_bits;
5195796c8dcSSimon Schubert 	}
5205796c8dcSSimon Schubert 
5215796c8dcSSimon Schubert       put_field (uto, order, fmt->totalsize,
5225796c8dcSSimon Schubert 		 mant_off, mant_bits, mant_long);
5235796c8dcSSimon Schubert       mant_off += mant_bits;
5245796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
5255796c8dcSSimon Schubert     }
5265796c8dcSSimon Schubert 
5275796c8dcSSimon Schubert  finalize_byteorder:
5285796c8dcSSimon Schubert   /* Do we need to byte-swap the words in the result?  */
5295796c8dcSSimon Schubert   if (order != fmt->byteorder)
5305796c8dcSSimon Schubert     floatformat_normalize_byteorder (fmt, newto, to);
5315796c8dcSSimon Schubert }
5325796c8dcSSimon Schubert 
5335796c8dcSSimon Schubert /* Check if VAL (which is assumed to be a floating point number whose
5345796c8dcSSimon Schubert    format is described by FMT) is negative.  */
5355796c8dcSSimon Schubert 
5365796c8dcSSimon Schubert int
5375796c8dcSSimon Schubert floatformat_is_negative (const struct floatformat *fmt,
5385796c8dcSSimon Schubert 			 const bfd_byte *uval)
5395796c8dcSSimon Schubert {
5405796c8dcSSimon Schubert   enum floatformat_byteorders order;
5415796c8dcSSimon Schubert   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
5425796c8dcSSimon Schubert 
5435796c8dcSSimon Schubert   gdb_assert (fmt != NULL);
5445796c8dcSSimon Schubert   gdb_assert (fmt->totalsize
5455796c8dcSSimon Schubert 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
5465796c8dcSSimon Schubert 
5475796c8dcSSimon Schubert   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert   if (order != fmt->byteorder)
5505796c8dcSSimon Schubert     uval = newfrom;
5515796c8dcSSimon Schubert 
5525796c8dcSSimon Schubert   return get_field (uval, order, fmt->totalsize, fmt->sign_start, 1);
5535796c8dcSSimon Schubert }
5545796c8dcSSimon Schubert 
5555796c8dcSSimon Schubert /* Check if VAL is "not a number" (NaN) for FMT.  */
5565796c8dcSSimon Schubert 
5575796c8dcSSimon Schubert enum float_kind
5585796c8dcSSimon Schubert floatformat_classify (const struct floatformat *fmt,
5595796c8dcSSimon Schubert 		      const bfd_byte *uval)
5605796c8dcSSimon Schubert {
5615796c8dcSSimon Schubert   long exponent;
5625796c8dcSSimon Schubert   unsigned long mant;
5635796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
5645796c8dcSSimon Schubert   int mant_bits_left;
5655796c8dcSSimon Schubert   enum floatformat_byteorders order;
5665796c8dcSSimon Schubert   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
5675796c8dcSSimon Schubert   int mant_zero;
5685796c8dcSSimon Schubert 
5695796c8dcSSimon Schubert   gdb_assert (fmt != NULL);
5705796c8dcSSimon Schubert   gdb_assert (fmt->totalsize
5715796c8dcSSimon Schubert 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
5725796c8dcSSimon Schubert 
5735796c8dcSSimon Schubert   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
5745796c8dcSSimon Schubert 
5755796c8dcSSimon Schubert   if (order != fmt->byteorder)
5765796c8dcSSimon Schubert     uval = newfrom;
5775796c8dcSSimon Schubert 
5785796c8dcSSimon Schubert   exponent = get_field (uval, order, fmt->totalsize, fmt->exp_start,
5795796c8dcSSimon Schubert 			fmt->exp_len);
5805796c8dcSSimon Schubert 
5815796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
5825796c8dcSSimon Schubert   mant_off = fmt->man_start;
5835796c8dcSSimon Schubert 
5845796c8dcSSimon Schubert   mant_zero = 1;
5855796c8dcSSimon Schubert   while (mant_bits_left > 0)
5865796c8dcSSimon Schubert     {
5875796c8dcSSimon Schubert       mant_bits = min (mant_bits_left, 32);
5885796c8dcSSimon Schubert 
5895796c8dcSSimon Schubert       mant = get_field (uval, order, fmt->totalsize, mant_off, mant_bits);
5905796c8dcSSimon Schubert 
5915796c8dcSSimon Schubert       /* If there is an explicit integer bit, mask it off.  */
5925796c8dcSSimon Schubert       if (mant_off == fmt->man_start
5935796c8dcSSimon Schubert 	  && fmt->intbit == floatformat_intbit_yes)
5945796c8dcSSimon Schubert 	mant &= ~(1 << (mant_bits - 1));
5955796c8dcSSimon Schubert 
5965796c8dcSSimon Schubert       if (mant)
5975796c8dcSSimon Schubert 	{
5985796c8dcSSimon Schubert 	  mant_zero = 0;
5995796c8dcSSimon Schubert 	  break;
6005796c8dcSSimon Schubert 	}
6015796c8dcSSimon Schubert 
6025796c8dcSSimon Schubert       mant_off += mant_bits;
6035796c8dcSSimon Schubert       mant_bits_left -= mant_bits;
6045796c8dcSSimon Schubert     }
6055796c8dcSSimon Schubert 
6065796c8dcSSimon Schubert   /* If exp_nan is not set, assume that inf, NaN, and subnormals are not
6075796c8dcSSimon Schubert      supported.  */
6085796c8dcSSimon Schubert   if (! fmt->exp_nan)
6095796c8dcSSimon Schubert     {
6105796c8dcSSimon Schubert       if (mant_zero)
6115796c8dcSSimon Schubert 	return float_zero;
6125796c8dcSSimon Schubert       else
6135796c8dcSSimon Schubert 	return float_normal;
6145796c8dcSSimon Schubert     }
6155796c8dcSSimon Schubert 
6165796c8dcSSimon Schubert   if (exponent == 0 && !mant_zero)
6175796c8dcSSimon Schubert     return float_subnormal;
6185796c8dcSSimon Schubert 
6195796c8dcSSimon Schubert   if (exponent == fmt->exp_nan)
6205796c8dcSSimon Schubert     {
6215796c8dcSSimon Schubert       if (mant_zero)
6225796c8dcSSimon Schubert 	return float_infinite;
6235796c8dcSSimon Schubert       else
6245796c8dcSSimon Schubert 	return float_nan;
6255796c8dcSSimon Schubert     }
6265796c8dcSSimon Schubert 
6275796c8dcSSimon Schubert   if (mant_zero)
6285796c8dcSSimon Schubert     return float_zero;
6295796c8dcSSimon Schubert 
6305796c8dcSSimon Schubert   return float_normal;
6315796c8dcSSimon Schubert }
6325796c8dcSSimon Schubert 
6335796c8dcSSimon Schubert /* Convert the mantissa of VAL (which is assumed to be a floating
6345796c8dcSSimon Schubert    point number whose format is described by FMT) into a hexadecimal
6355796c8dcSSimon Schubert    and store it in a static string.  Return a pointer to that string.  */
6365796c8dcSSimon Schubert 
6375796c8dcSSimon Schubert const char *
6385796c8dcSSimon Schubert floatformat_mantissa (const struct floatformat *fmt,
6395796c8dcSSimon Schubert 		      const bfd_byte *val)
6405796c8dcSSimon Schubert {
6415796c8dcSSimon Schubert   unsigned char *uval = (unsigned char *) val;
6425796c8dcSSimon Schubert   unsigned long mant;
6435796c8dcSSimon Schubert   unsigned int mant_bits, mant_off;
6445796c8dcSSimon Schubert   int mant_bits_left;
6455796c8dcSSimon Schubert   static char res[50];
6465796c8dcSSimon Schubert   char buf[9];
6475796c8dcSSimon Schubert   int len;
6485796c8dcSSimon Schubert   enum floatformat_byteorders order;
6495796c8dcSSimon Schubert   unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
6505796c8dcSSimon Schubert 
6515796c8dcSSimon Schubert   gdb_assert (fmt != NULL);
6525796c8dcSSimon Schubert   gdb_assert (fmt->totalsize
6535796c8dcSSimon Schubert 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
6545796c8dcSSimon Schubert 
6555796c8dcSSimon Schubert   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
6565796c8dcSSimon Schubert 
6575796c8dcSSimon Schubert   if (order != fmt->byteorder)
6585796c8dcSSimon Schubert     uval = newfrom;
6595796c8dcSSimon Schubert 
6605796c8dcSSimon Schubert   if (! fmt->exp_nan)
6615796c8dcSSimon Schubert     return 0;
6625796c8dcSSimon Schubert 
6635796c8dcSSimon Schubert   /* Make sure we have enough room to store the mantissa.  */
6645796c8dcSSimon Schubert   gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2);
6655796c8dcSSimon Schubert 
6665796c8dcSSimon Schubert   mant_off = fmt->man_start;
6675796c8dcSSimon Schubert   mant_bits_left = fmt->man_len;
6685796c8dcSSimon Schubert   mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32;
6695796c8dcSSimon Schubert 
6705796c8dcSSimon Schubert   mant = get_field (uval, order, fmt->totalsize, mant_off, mant_bits);
6715796c8dcSSimon Schubert 
6725796c8dcSSimon Schubert   len = xsnprintf (res, sizeof res, "%lx", mant);
6735796c8dcSSimon Schubert 
6745796c8dcSSimon Schubert   mant_off += mant_bits;
6755796c8dcSSimon Schubert   mant_bits_left -= mant_bits;
6765796c8dcSSimon Schubert 
6775796c8dcSSimon Schubert   while (mant_bits_left > 0)
6785796c8dcSSimon Schubert     {
6795796c8dcSSimon Schubert       mant = get_field (uval, order, fmt->totalsize, mant_off, 32);
6805796c8dcSSimon Schubert 
6815796c8dcSSimon Schubert       xsnprintf (buf, sizeof buf, "%08lx", mant);
6825796c8dcSSimon Schubert       gdb_assert (len + strlen (buf) <= sizeof res);
6835796c8dcSSimon Schubert       strcat (res, buf);
6845796c8dcSSimon Schubert 
6855796c8dcSSimon Schubert       mant_off += 32;
6865796c8dcSSimon Schubert       mant_bits_left -= 32;
6875796c8dcSSimon Schubert     }
6885796c8dcSSimon Schubert 
6895796c8dcSSimon Schubert   return res;
6905796c8dcSSimon Schubert }
6915796c8dcSSimon Schubert 
6925796c8dcSSimon Schubert 
6935796c8dcSSimon Schubert /* Convert TO/FROM target to the hosts DOUBLEST floating-point format.
6945796c8dcSSimon Schubert 
6955796c8dcSSimon Schubert    If the host and target formats agree, we just copy the raw data
6965796c8dcSSimon Schubert    into the appropriate type of variable and return, letting the host
6975796c8dcSSimon Schubert    increase precision as necessary.  Otherwise, we call the conversion
6985796c8dcSSimon Schubert    routine and let it do the dirty work.  */
6995796c8dcSSimon Schubert 
7005796c8dcSSimon Schubert static const struct floatformat *host_float_format = GDB_HOST_FLOAT_FORMAT;
7015796c8dcSSimon Schubert static const struct floatformat *host_double_format = GDB_HOST_DOUBLE_FORMAT;
7025796c8dcSSimon Schubert static const struct floatformat *host_long_double_format = GDB_HOST_LONG_DOUBLE_FORMAT;
7035796c8dcSSimon Schubert 
7045796c8dcSSimon Schubert void
7055796c8dcSSimon Schubert floatformat_to_doublest (const struct floatformat *fmt,
7065796c8dcSSimon Schubert 			 const void *in, DOUBLEST *out)
7075796c8dcSSimon Schubert {
7085796c8dcSSimon Schubert   gdb_assert (fmt != NULL);
7095796c8dcSSimon Schubert   if (fmt == host_float_format)
7105796c8dcSSimon Schubert     {
7115796c8dcSSimon Schubert       float val;
712*cf7f2e2dSJohn Marino 
7135796c8dcSSimon Schubert       memcpy (&val, in, sizeof (val));
7145796c8dcSSimon Schubert       *out = val;
7155796c8dcSSimon Schubert     }
7165796c8dcSSimon Schubert   else if (fmt == host_double_format)
7175796c8dcSSimon Schubert     {
7185796c8dcSSimon Schubert       double val;
719*cf7f2e2dSJohn Marino 
7205796c8dcSSimon Schubert       memcpy (&val, in, sizeof (val));
7215796c8dcSSimon Schubert       *out = val;
7225796c8dcSSimon Schubert     }
7235796c8dcSSimon Schubert   else if (fmt == host_long_double_format)
7245796c8dcSSimon Schubert     {
7255796c8dcSSimon Schubert       long double val;
726*cf7f2e2dSJohn Marino 
7275796c8dcSSimon Schubert       memcpy (&val, in, sizeof (val));
7285796c8dcSSimon Schubert       *out = val;
7295796c8dcSSimon Schubert     }
7305796c8dcSSimon Schubert   else
7315796c8dcSSimon Schubert     convert_floatformat_to_doublest (fmt, in, out);
7325796c8dcSSimon Schubert }
7335796c8dcSSimon Schubert 
7345796c8dcSSimon Schubert void
7355796c8dcSSimon Schubert floatformat_from_doublest (const struct floatformat *fmt,
7365796c8dcSSimon Schubert 			   const DOUBLEST *in, void *out)
7375796c8dcSSimon Schubert {
7385796c8dcSSimon Schubert   gdb_assert (fmt != NULL);
7395796c8dcSSimon Schubert   if (fmt == host_float_format)
7405796c8dcSSimon Schubert     {
7415796c8dcSSimon Schubert       float val = *in;
742*cf7f2e2dSJohn Marino 
7435796c8dcSSimon Schubert       memcpy (out, &val, sizeof (val));
7445796c8dcSSimon Schubert     }
7455796c8dcSSimon Schubert   else if (fmt == host_double_format)
7465796c8dcSSimon Schubert     {
7475796c8dcSSimon Schubert       double val = *in;
748*cf7f2e2dSJohn Marino 
7495796c8dcSSimon Schubert       memcpy (out, &val, sizeof (val));
7505796c8dcSSimon Schubert     }
7515796c8dcSSimon Schubert   else if (fmt == host_long_double_format)
7525796c8dcSSimon Schubert     {
7535796c8dcSSimon Schubert       long double val = *in;
754*cf7f2e2dSJohn Marino 
7555796c8dcSSimon Schubert       memcpy (out, &val, sizeof (val));
7565796c8dcSSimon Schubert     }
7575796c8dcSSimon Schubert   else
7585796c8dcSSimon Schubert     convert_doublest_to_floatformat (fmt, in, out);
7595796c8dcSSimon Schubert }
7605796c8dcSSimon Schubert 
7615796c8dcSSimon Schubert 
7625796c8dcSSimon Schubert /* Return a floating-point format for a floating-point variable of
7635796c8dcSSimon Schubert    length LEN.  If no suitable floating-point format is found, an
7645796c8dcSSimon Schubert    error is thrown.
7655796c8dcSSimon Schubert 
7665796c8dcSSimon Schubert    We need this functionality since information about the
7675796c8dcSSimon Schubert    floating-point format of a type is not always available to GDB; the
7685796c8dcSSimon Schubert    debug information typically only tells us the size of a
7695796c8dcSSimon Schubert    floating-point type.
7705796c8dcSSimon Schubert 
7715796c8dcSSimon Schubert    FIXME: kettenis/2001-10-28: In many places, particularly in
7725796c8dcSSimon Schubert    target-dependent code, the format of floating-point types is known,
7735796c8dcSSimon Schubert    but not passed on by GDB.  This should be fixed.  */
7745796c8dcSSimon Schubert 
7755796c8dcSSimon Schubert static const struct floatformat *
7765796c8dcSSimon Schubert floatformat_from_length (struct gdbarch *gdbarch, int len)
7775796c8dcSSimon Schubert {
7785796c8dcSSimon Schubert   const struct floatformat *format;
779*cf7f2e2dSJohn Marino 
780*cf7f2e2dSJohn Marino   if (len * TARGET_CHAR_BIT == gdbarch_half_bit (gdbarch))
781*cf7f2e2dSJohn Marino     format = gdbarch_half_format (gdbarch)
782*cf7f2e2dSJohn Marino 	       [gdbarch_byte_order (gdbarch)];
783*cf7f2e2dSJohn Marino   else if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch))
7845796c8dcSSimon Schubert     format = gdbarch_float_format (gdbarch)
7855796c8dcSSimon Schubert 	       [gdbarch_byte_order (gdbarch)];
7865796c8dcSSimon Schubert   else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (gdbarch))
7875796c8dcSSimon Schubert     format = gdbarch_double_format (gdbarch)
7885796c8dcSSimon Schubert 	       [gdbarch_byte_order (gdbarch)];
7895796c8dcSSimon Schubert   else if (len * TARGET_CHAR_BIT == gdbarch_long_double_bit (gdbarch))
7905796c8dcSSimon Schubert     format = gdbarch_long_double_format (gdbarch)
7915796c8dcSSimon Schubert 	       [gdbarch_byte_order (gdbarch)];
7925796c8dcSSimon Schubert   /* On i386 the 'long double' type takes 96 bits,
7935796c8dcSSimon Schubert      while the real number of used bits is only 80,
7945796c8dcSSimon Schubert      both in processor and in memory.
7955796c8dcSSimon Schubert      The code below accepts the real bit size.  */
7965796c8dcSSimon Schubert   else if ((gdbarch_long_double_format (gdbarch) != NULL)
797*cf7f2e2dSJohn Marino 	   && (len * TARGET_CHAR_BIT
798*cf7f2e2dSJohn Marino                == gdbarch_long_double_format (gdbarch)[0]->totalsize))
7995796c8dcSSimon Schubert     format = gdbarch_long_double_format (gdbarch)
8005796c8dcSSimon Schubert 	       [gdbarch_byte_order (gdbarch)];
8015796c8dcSSimon Schubert   else
8025796c8dcSSimon Schubert     format = NULL;
8035796c8dcSSimon Schubert   if (format == NULL)
8045796c8dcSSimon Schubert     error (_("Unrecognized %d-bit floating-point type."),
8055796c8dcSSimon Schubert 	   len * TARGET_CHAR_BIT);
8065796c8dcSSimon Schubert   return format;
8075796c8dcSSimon Schubert }
8085796c8dcSSimon Schubert 
8095796c8dcSSimon Schubert const struct floatformat *
8105796c8dcSSimon Schubert floatformat_from_type (const struct type *type)
8115796c8dcSSimon Schubert {
8125796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_type_arch (type);
813*cf7f2e2dSJohn Marino 
8145796c8dcSSimon Schubert   gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
8155796c8dcSSimon Schubert   if (TYPE_FLOATFORMAT (type) != NULL)
8165796c8dcSSimon Schubert     return TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
8175796c8dcSSimon Schubert   else
8185796c8dcSSimon Schubert     return floatformat_from_length (gdbarch, TYPE_LENGTH (type));
8195796c8dcSSimon Schubert }
8205796c8dcSSimon Schubert 
8215796c8dcSSimon Schubert /* Extract a floating-point number of type TYPE from a target-order
8225796c8dcSSimon Schubert    byte-stream at ADDR.  Returns the value as type DOUBLEST.  */
8235796c8dcSSimon Schubert 
8245796c8dcSSimon Schubert DOUBLEST
8255796c8dcSSimon Schubert extract_typed_floating (const void *addr, const struct type *type)
8265796c8dcSSimon Schubert {
8275796c8dcSSimon Schubert   const struct floatformat *fmt = floatformat_from_type (type);
8285796c8dcSSimon Schubert   DOUBLEST retval;
8295796c8dcSSimon Schubert 
8305796c8dcSSimon Schubert   floatformat_to_doublest (fmt, addr, &retval);
8315796c8dcSSimon Schubert   return retval;
8325796c8dcSSimon Schubert }
8335796c8dcSSimon Schubert 
8345796c8dcSSimon Schubert /* Store VAL as a floating-point number of type TYPE to a target-order
8355796c8dcSSimon Schubert    byte-stream at ADDR.  */
8365796c8dcSSimon Schubert 
8375796c8dcSSimon Schubert void
8385796c8dcSSimon Schubert store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
8395796c8dcSSimon Schubert {
8405796c8dcSSimon Schubert   const struct floatformat *fmt = floatformat_from_type (type);
8415796c8dcSSimon Schubert 
8425796c8dcSSimon Schubert   /* FIXME: kettenis/2001-10-28: It is debatable whether we should
8435796c8dcSSimon Schubert      zero out any remaining bytes in the target buffer when TYPE is
8445796c8dcSSimon Schubert      longer than the actual underlying floating-point format.  Perhaps
8455796c8dcSSimon Schubert      we should store a fixed bitpattern in those remaining bytes,
8465796c8dcSSimon Schubert      instead of zero, or perhaps we shouldn't touch those remaining
8475796c8dcSSimon Schubert      bytes at all.
8485796c8dcSSimon Schubert 
8495796c8dcSSimon Schubert      NOTE: cagney/2001-10-28: With the way things currently work, it
8505796c8dcSSimon Schubert      isn't a good idea to leave the end bits undefined.  This is
8515796c8dcSSimon Schubert      because GDB writes out the entire sizeof(<floating>) bits of the
8525796c8dcSSimon Schubert      floating-point type even though the value might only be stored
8535796c8dcSSimon Schubert      in, and the target processor may only refer to, the first N <
8545796c8dcSSimon Schubert      TYPE_LENGTH (type) bits.  If the end of the buffer wasn't
8555796c8dcSSimon Schubert      initialized, GDB would write undefined data to the target.  An
8565796c8dcSSimon Schubert      errant program, refering to that undefined data, would then
8575796c8dcSSimon Schubert      become non-deterministic.
8585796c8dcSSimon Schubert 
8595796c8dcSSimon Schubert      See also the function convert_typed_floating below.  */
8605796c8dcSSimon Schubert   memset (addr, 0, TYPE_LENGTH (type));
8615796c8dcSSimon Schubert 
8625796c8dcSSimon Schubert   floatformat_from_doublest (fmt, &val, addr);
8635796c8dcSSimon Schubert }
8645796c8dcSSimon Schubert 
8655796c8dcSSimon Schubert /* Convert a floating-point number of type FROM_TYPE from a
8665796c8dcSSimon Schubert    target-order byte-stream at FROM to a floating-point number of type
8675796c8dcSSimon Schubert    TO_TYPE, and store it to a target-order byte-stream at TO.  */
8685796c8dcSSimon Schubert 
8695796c8dcSSimon Schubert void
8705796c8dcSSimon Schubert convert_typed_floating (const void *from, const struct type *from_type,
8715796c8dcSSimon Schubert                         void *to, const struct type *to_type)
8725796c8dcSSimon Schubert {
8735796c8dcSSimon Schubert   const struct floatformat *from_fmt = floatformat_from_type (from_type);
8745796c8dcSSimon Schubert   const struct floatformat *to_fmt = floatformat_from_type (to_type);
8755796c8dcSSimon Schubert 
8765796c8dcSSimon Schubert   if (from_fmt == NULL || to_fmt == NULL)
8775796c8dcSSimon Schubert     {
8785796c8dcSSimon Schubert       /* If we don't know the floating-point format of FROM_TYPE or
8795796c8dcSSimon Schubert          TO_TYPE, there's not much we can do.  We might make the
8805796c8dcSSimon Schubert          assumption that if the length of FROM_TYPE and TO_TYPE match,
8815796c8dcSSimon Schubert          their floating-point format would match too, but that
8825796c8dcSSimon Schubert          assumption might be wrong on targets that support
8835796c8dcSSimon Schubert          floating-point types that only differ in endianness for
8845796c8dcSSimon Schubert          example.  So we warn instead, and zero out the target buffer.  */
8855796c8dcSSimon Schubert       warning (_("Can't convert floating-point number to desired type."));
8865796c8dcSSimon Schubert       memset (to, 0, TYPE_LENGTH (to_type));
8875796c8dcSSimon Schubert     }
8885796c8dcSSimon Schubert   else if (from_fmt == to_fmt)
8895796c8dcSSimon Schubert     {
8905796c8dcSSimon Schubert       /* We're in business.  The floating-point format of FROM_TYPE
8915796c8dcSSimon Schubert          and TO_TYPE match.  However, even though the floating-point
8925796c8dcSSimon Schubert          format matches, the length of the type might still be
8935796c8dcSSimon Schubert          different.  Make sure we don't overrun any buffers.  See
8945796c8dcSSimon Schubert          comment in store_typed_floating for a discussion about
8955796c8dcSSimon Schubert          zeroing out remaining bytes in the target buffer.  */
8965796c8dcSSimon Schubert       memset (to, 0, TYPE_LENGTH (to_type));
8975796c8dcSSimon Schubert       memcpy (to, from, min (TYPE_LENGTH (from_type), TYPE_LENGTH (to_type)));
8985796c8dcSSimon Schubert     }
8995796c8dcSSimon Schubert   else
9005796c8dcSSimon Schubert     {
9015796c8dcSSimon Schubert       /* The floating-point types don't match.  The best we can do
9025796c8dcSSimon Schubert          (apart from simulating the target FPU) is converting to the
9035796c8dcSSimon Schubert          widest floating-point type supported by the host, and then
9045796c8dcSSimon Schubert          again to the desired type.  */
9055796c8dcSSimon Schubert       DOUBLEST d;
9065796c8dcSSimon Schubert 
9075796c8dcSSimon Schubert       floatformat_to_doublest (from_fmt, from, &d);
9085796c8dcSSimon Schubert       floatformat_from_doublest (to_fmt, &d, to);
9095796c8dcSSimon Schubert     }
9105796c8dcSSimon Schubert }
9115796c8dcSSimon Schubert 
9125796c8dcSSimon Schubert const struct floatformat *floatformat_ieee_single[BFD_ENDIAN_UNKNOWN];
9135796c8dcSSimon Schubert const struct floatformat *floatformat_ieee_double[BFD_ENDIAN_UNKNOWN];
9145796c8dcSSimon Schubert const struct floatformat *floatformat_ieee_quad[BFD_ENDIAN_UNKNOWN];
9155796c8dcSSimon Schubert const struct floatformat *floatformat_arm_ext[BFD_ENDIAN_UNKNOWN];
9165796c8dcSSimon Schubert const struct floatformat *floatformat_ia64_spill[BFD_ENDIAN_UNKNOWN];
9175796c8dcSSimon Schubert 
9185796c8dcSSimon Schubert extern void _initialize_doublest (void);
9195796c8dcSSimon Schubert 
9205796c8dcSSimon Schubert extern void
9215796c8dcSSimon Schubert _initialize_doublest (void)
9225796c8dcSSimon Schubert {
9235796c8dcSSimon Schubert   floatformat_ieee_single[BFD_ENDIAN_LITTLE] = &floatformat_ieee_single_little;
9245796c8dcSSimon Schubert   floatformat_ieee_single[BFD_ENDIAN_BIG] = &floatformat_ieee_single_big;
9255796c8dcSSimon Schubert   floatformat_ieee_double[BFD_ENDIAN_LITTLE] = &floatformat_ieee_double_little;
9265796c8dcSSimon Schubert   floatformat_ieee_double[BFD_ENDIAN_BIG] = &floatformat_ieee_double_big;
9275796c8dcSSimon Schubert   floatformat_arm_ext[BFD_ENDIAN_LITTLE] = &floatformat_arm_ext_littlebyte_bigword;
9285796c8dcSSimon Schubert   floatformat_arm_ext[BFD_ENDIAN_BIG] = &floatformat_arm_ext_big;
9295796c8dcSSimon Schubert   floatformat_ia64_spill[BFD_ENDIAN_LITTLE] = &floatformat_ia64_spill_little;
9305796c8dcSSimon Schubert   floatformat_ia64_spill[BFD_ENDIAN_BIG] = &floatformat_ia64_spill_big;
9315796c8dcSSimon Schubert   floatformat_ieee_quad[BFD_ENDIAN_LITTLE] = &floatformat_ia64_quad_little;
9325796c8dcSSimon Schubert   floatformat_ieee_quad[BFD_ENDIAN_BIG] = &floatformat_ia64_quad_big;
9335796c8dcSSimon Schubert }
934