This is the mail archive of the
gdb@sourceware.cygnus.com
mailing list for the GDB project.
Re: bug in arm_push_arguments()
- To: Scott Bambrough <scottb at netwinder dot org>
- Subject: Re: bug in arm_push_arguments()
- From: Kevin Buettner <kevinb at cygnus dot com>
- Date: Fri, 25 Feb 2000 12:08:17 -0700
- Cc: GDB Mailing List <gdb at sourceware dot cygnus dot com>
- References: <38B6C4A1.7A1461C4@netwinder.org>
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