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]

Re: bug in arm_push_arguments()


On Feb 25,  1:06pm, Scott Bambrough wrote:

>      /* ANSI C code passes float arguments as integers, K&R code
>          passes float arguments as doubles.  The .stabs record for 
>          for ANSI prototype floating point arguments records the
>          type as FP_INTEGER, while a K&R style (no prototype)
>          .stabs records the type as FP_FLOAT.  In this latter case
>          the compiler converts the float arguments to double before
>          calling the function.  */
>       if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
>         {
>           float f;
>           double d;
>           char * bufo = (char *) &d;
>           char * bufd = (char *) &dbl_arg;
> 
>           len = sizeof (double);
>           f = *(float *) val;
>           SWAP_TARGET_AND_HOST (&f, sizeof (float));  /* adjust endianess */
>           d = f;
>           /* We must revert the longwords so they get loaded into the
>              the right registers. */
>           memcpy (bufd, bufo + len / 2, len / 2);
>           SWAP_TARGET_AND_HOST (bufd, len / 2);  /* adjust endianess */
>           memcpy (bufd + len / 2, bufo, len / 2);
>           SWAP_TARGET_AND_HOST (bufd + len / 2, len / 2); /* adjust endianess */
>           val = (char *) &dbl_arg;
>         }
> 
> I added this particular piece of code to handle functions without prototypes
> that pass floats as parameters, because the compiler treats them differently. 
> Someone added code which is attempting the following (see my comments):
> 
> 	  /* The value is in TARGET byte order.  Convert it to HOST byte 
> 	     order in preparation for conversion to a double.  */
>           f = *(float *) val;
>           SWAP_TARGET_AND_HOST (&f, sizeof (float));  /* adjust endianess */
> 
> 	  /* Convert the float to a double in HOST byte order.  */
>           d = f;
> 
> 	  /* Convert the double to TARGET byte order and swap things to 
> 	     conform to the ARM floating point layout.  */
>           memcpy (bufd, bufo + len / 2, len / 2);
>           SWAP_TARGET_AND_HOST (bufd, len / 2);  /* adjust endianess */
>           memcpy (bufd + len / 2, bufo, len / 2);
>           SWAP_TARGET_AND_HOST (bufd + len / 2, len / 2); /* adjust endianess */
>           val = (char *) &dbl_arg;
> 
> This is ok, but the code for the last step is unnecessarily complex.  I think
> something similar to the following should suffice.
> 
> 	  int tmp, *buf = &d;
> 	  SWAP_TARGET_AND_HOST (&d, sizeof (double));
> 	  tmp = buf[0];
> 	  buf[0] = buf[1];
> 	  buf[1] = tmp;
> 
> I think this will result in better code from the compiler.  There are a couple
> of problems though with this code.  First what happens if sizeof (TARGET_DOUBLE)
> != sizeof (HOST_DOUBLE).  Second, this breaks in the native case, because the
> double is already in the right format. This is why I have regressions I believe
> (I have yet to test my theory).  Is there a clean way to solve these problems?

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.

Kevin

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