diff options
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/config/i386/tm-i386aix.h | 8 | ||||
-rw-r--r-- | gdb/config/i386/tm-linux.h | 3 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 76 |
4 files changed, 54 insertions, 44 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 62b53b5..318aea5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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> * configure.in (CONFIG_INITS): Do not append remote-nrom.c diff --git a/gdb/config/i386/tm-i386aix.h b/gdb/config/i386/tm-i386aix.h index 6fed83d..809fb3d 100644 --- a/gdb/config/i386/tm-i386aix.h +++ b/gdb/config/i386/tm-i386aix.h @@ -30,14 +30,6 @@ #define I386 1 #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 is the only supported configuration) doesn't make the FPU control registers available. Override the appropriate symbols such that diff --git a/gdb/config/i386/tm-linux.h b/gdb/config/i386/tm-linux.h index c6d8dde..2e86a5c 100644 --- a/gdb/config/i386/tm-linux.h +++ b/gdb/config/i386/tm-linux.h @@ -30,9 +30,6 @@ #include "i386/tm-i386.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. */ #define TARGET_LONG_DOUBLE_BIT 80 diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 2420ec1..421a7a0 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -698,56 +698,66 @@ get_longjmp_target (pc) #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 -i386_extract_return_value (type, regbuf, valbuf) - struct type *type; - char regbuf[REGISTER_BYTES]; - char *valbuf; +i386_extract_return_value (struct type *type, char *regbuf, char *valbuf) { - /* On AIX, i386 GNU/Linux and DJGPP, floating point values are - 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) + int len = TYPE_LENGTH (type); + if (TYPE_CODE_FLT == TYPE_CODE (type)) { - double d; - /* 387 %st(0), gcc uses this */ - floatformat_to_double (&floatformat_i387_ext, -#if defined(FPDATA_REGNUM) - ®buf[REGISTER_BYTE (FPDATA_REGNUM)], -#else /* !FPDATA_REGNUM */ - ®buf[REGISTER_BYTE (FP0_REGNUM)], -#endif /* FPDATA_REGNUM */ - - &d); - store_floating (valbuf, TYPE_LENGTH (type), d); + if (NUM_FREGS == 0) + { + warning ("Cannot find floating-point return value."); + memset (valbuf, 0, len); + } + + /* Floating-point return values can be found in %st(0). */ + 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, ®buf[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, + ®buf[REGISTER_BYTE (FP0_REGNUM)], &val); + store_floating (valbuf, TYPE_LENGTH (type), val); + } } 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 high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM); if (len <= low_size) - memcpy (valbuf, regbuf + REGISTER_BYTE (LOW_RETURN_REGNUM), len); + memcpy (valbuf, ®buf[REGISTER_BYTE (LOW_RETURN_REGNUM)], len); else if (len <= (low_size + high_size)) { memcpy (valbuf, - regbuf + REGISTER_BYTE (LOW_RETURN_REGNUM), - low_size); + ®buf[REGISTER_BYTE (LOW_RETURN_REGNUM)], low_size); memcpy (valbuf + low_size, - regbuf + REGISTER_BYTE (HIGH_RETURN_REGNUM), - len - low_size); + ®buf[REGISTER_BYTE (HIGH_RETURN_REGNUM)], len - low_size); } else - error ("GDB bug: i386-tdep.c (i386_extract_return_value): Don't know how to find a return value %d bytes long", len); -#else /* !LOW_RETURN_REGNUM */ - memcpy (valbuf, regbuf, TYPE_LENGTH (type)); -#endif /* LOW_RETURN_REGNUM */ + internal_error ("Cannot extract return value of %d bytes long.", len); } } |