This is the mail archive of the gdb@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

store_floating() rewrite (was Re: bug in arm_push_arguments())


On Feb 28, 11:03pm, Andrew Cagney wrote:

> Kevin Buttner wrote:
> > It seems to me that you should be able to use store_floating() to do
> > what you want.  It'll handle both the conversion and the byte swapping.
> 
> Yes, that looks correct. I'm just not 100% sure on it working - would
> one of those if()'s before the TARGET_EXTRACT_FLOATING() get in the way?
                                 ^^^^^^^^^^^^^^^^^^^^^^^

Did you mean TARGET_STORE_FLOATING?

The part that bothers me about the way that store_floating() is
implemented is that we're comparing the size of the thing we're trying
to store into (on the target) against sizes of the host formats.  I.e,
the following lines bother me.

  if (len == sizeof (float))
  else if (len == sizeof (double))
  else if (len == sizeof (DOUBLEST))

I think we should be comparing against the sizes of the target formats.

Suppose, for example, that we have the following configuration

    host float:		32 bits
    host double		64 bits
    target float	64 bits
    target double	128 bits

and that we enter store_floating with len == 8.

This'll cause us to wind up in the following code:

  else if (len == sizeof (double))
    {
      if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
	{
	  double doubleval = val;

	  memcpy (addr, &doubleval, sizeof (doubleval));
	}
      else
	floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr);
    }

Because the sizes of the doubles are different, HOST_DOUBLE_FORMAT
will not be the same as TARGET_DOUBLE_FORMAT.  This means that we'll
execute the floatformat_from_doublest call which attempts to store a
(target) double.

But this is wrong since the size of a target double is 16 bytes and we
were attempting to store a floating point value whose size is 8 bytes.

Here is my rewrite of this function:

void
store_floating (void *addr, int len, DOUBLEST val)
{
  if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
    {
      float floatval = val;

      memcpy (addr, &floatval, sizeof (floatval));
    }
  else if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
    {
      double doubleval = val;

      memcpy (addr, &doubleval, sizeof (doubleval));
    }
  else if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
    memcpy (addr, &val, sizeof (val));
  else if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
    floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr);
  else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT)
    floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr);
  else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
    floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
#ifdef TARGET_STORE_FLOATING
  else if (TARGET_STORE_FLOATING (addr, len, val))
    return;
#endif 
  else
    error ("Can't deal with a floating point number of %d bytes.", len);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]