2000-03-22 Mark Kettenis <kettenis@gnu.org>

* config/i386/tm-i386aix.h (I386_AIX_TARGET): Remove.
	* config/i386/tm-linux.h (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM):
	Remove
	* i386-tdep.c (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM): New defines.
	(i386_extract_return_value): Rewritten.  Correctly support all
	floating-point types and large integer types on targets that use
	the standard i386 GDB register layout and return floating-point
	values in the FPU.
This commit is contained in:
Mark Kettenis 2000-03-22 09:45:01 +00:00
parent 6a08e74c32
commit 1a309862a7
4 changed files with 53 additions and 43 deletions

View File

@ -1,3 +1,14 @@
2000-03-22 Mark Kettenis <kettenis@gnu.org>
* config/i386/tm-i386aix.h (I386_AIX_TARGET): Remove.
* config/i386/tm-linux.h (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM):
Remove
* i386-tdep.c (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM): New defines.
(i386_extract_return_value): Rewritten. Correctly support all
floating-point types and large integer types on targets that use
the standard i386 GDB register layout and return floating-point
values in the FPU.
Wed Mar 22 15:09:34 2000 Andrew Cagney <cagney@b1.cygnus.com> Wed Mar 22 15:09:34 2000 Andrew Cagney <cagney@b1.cygnus.com>
* configure.in (CONFIG_INITS): Do not append remote-nrom.c * configure.in (CONFIG_INITS): Do not append remote-nrom.c

View File

@ -30,14 +30,6 @@
#define I386 1 #define I386 1
#endif #endif
/* FIXME: kettenis/2000-03-02: This is used in
i386-tdep.c:i386_extract_return_value(), and will be remove once
I've fixed that. Meanwhile don't use it for any other purpose
please! */
#ifndef I386_AIX_TARGET
#define I386_AIX_TARGET 1
#endif
/* AIX/i386 has FPU support. However, the native configuration (which /* AIX/i386 has FPU support. However, the native configuration (which
is the only supported configuration) doesn't make the FPU control is the only supported configuration) doesn't make the FPU control
registers available. Override the appropriate symbols such that registers available. Override the appropriate symbols such that

View File

@ -30,9 +30,6 @@
#include "i386/tm-i386.h" #include "i386/tm-i386.h"
#include "tm-linux.h" #include "tm-linux.h"
#define LOW_RETURN_REGNUM 0 /* holds low four bytes of result */
#define HIGH_RETURN_REGNUM 2 /* holds high four bytes of result */
/* This should probably move to tm-i386.h. */ /* This should probably move to tm-i386.h. */
#define TARGET_LONG_DOUBLE_BIT 80 #define TARGET_LONG_DOUBLE_BIT 80

View File

@ -698,56 +698,66 @@ get_longjmp_target (pc)
#endif /* GET_LONGJMP_TARGET */ #endif /* GET_LONGJMP_TARGET */
/* These registers are used for returning integers (and on some
targets also for returning `struct' and `union' values when their
size and alignment match an integer type. */
#define LOW_RETURN_REGNUM 0 /* %eax */
#define HIGH_RETURN_REGNUM 2 /* %edx */
/* Extract from an array REGBUF containing the (raw) register state, a
function return value of TYPE, and copy that, in virtual format,
into VALBUF. */
void void
i386_extract_return_value (type, regbuf, valbuf) i386_extract_return_value (struct type *type, char *regbuf, char *valbuf)
struct type *type;
char regbuf[REGISTER_BYTES];
char *valbuf;
{ {
/* On AIX, i386 GNU/Linux and DJGPP, floating point values are int len = TYPE_LENGTH (type);
returned in floating point registers. */
/* FIXME: cagney/2000-02-29: This function needs to be rewritten
using multi-arch. Please don't keep adding to this #ifdef
spaghetti. */
#if defined(I386_AIX_TARGET) || defined(I386_GNULINUX_TARGET) || defined(I386_DJGPP_TARGET)
if (TYPE_CODE_FLT == TYPE_CODE (type)) if (TYPE_CODE_FLT == TYPE_CODE (type))
{ {
double d; if (NUM_FREGS == 0)
/* 387 %st(0), gcc uses this */ {
floatformat_to_double (&floatformat_i387_ext, warning ("Cannot find floating-point return value.");
#if defined(FPDATA_REGNUM) memset (valbuf, 0, len);
&regbuf[REGISTER_BYTE (FPDATA_REGNUM)], }
#else /* !FPDATA_REGNUM */
&regbuf[REGISTER_BYTE (FP0_REGNUM)],
#endif /* FPDATA_REGNUM */
&d); /* Floating-point return values can be found in %st(0). */
store_floating (valbuf, TYPE_LENGTH (type), d); if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
&& TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
{
/* Copy straight over, but take care of the padding. */
memcpy (valbuf, &regbuf[REGISTER_BYTE (FP0_REGNUM)],
FPU_REG_RAW_SIZE);
memset (valbuf + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
}
else
{
/* Convert the extended floating-point number found in
%st(0) to the desired type. This is probably not exactly
how it would happen on the target itself, but it is the
best we can do. */
DOUBLEST val;
floatformat_to_doublest (&floatformat_i387_ext,
&regbuf[REGISTER_BYTE (FP0_REGNUM)], &val);
store_floating (valbuf, TYPE_LENGTH (type), val);
}
} }
else else
#endif /* I386_AIX_TARGET || I386_GNULINUX_TARGET || I386_DJGPP_TARGET */
{ {
#if defined(LOW_RETURN_REGNUM)
int len = TYPE_LENGTH (type);
int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM); int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM);
int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM); int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM);
if (len <= low_size) if (len <= low_size)
memcpy (valbuf, regbuf + REGISTER_BYTE (LOW_RETURN_REGNUM), len); memcpy (valbuf, &regbuf[REGISTER_BYTE (LOW_RETURN_REGNUM)], len);
else if (len <= (low_size + high_size)) else if (len <= (low_size + high_size))
{ {
memcpy (valbuf, memcpy (valbuf,
regbuf + REGISTER_BYTE (LOW_RETURN_REGNUM), &regbuf[REGISTER_BYTE (LOW_RETURN_REGNUM)], low_size);
low_size);
memcpy (valbuf + low_size, memcpy (valbuf + low_size,
regbuf + REGISTER_BYTE (HIGH_RETURN_REGNUM), &regbuf[REGISTER_BYTE (HIGH_RETURN_REGNUM)], len - low_size);
len - low_size);
} }
else else
error ("GDB bug: i386-tdep.c (i386_extract_return_value): Don't know how to find a return value %d bytes long", len); internal_error ("Cannot extract return value of %d bytes long.", len);
#else /* !LOW_RETURN_REGNUM */
memcpy (valbuf, regbuf, TYPE_LENGTH (type));
#endif /* LOW_RETURN_REGNUM */
} }
} }