This is the mail archive of the gdb-patches@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]

[PATCH] Restructuring i386-tdep.c:i386_extract_return_value()


Hi,

I checked in the attached patch.  This is one of the patches I
discussed two weeks ago, which makes i386_extract_return_value() do
the right thing for most of the supported i386 targets.  Some targets
(for example those that use tm-i386v.h) still redefine
EXTRACT_RETURN_VALUE, so they don't take advantage of this
improvement.  I'll deal with that later.

Mark


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.


Index: config/i386/tm-i386aix.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386aix.h,v
retrieving revision 1.2
diff -u -p -r1.2 tm-i386aix.h
--- config/i386/tm-i386aix.h	2000/03/02 15:44:27	1.2
+++ config/i386/tm-i386aix.h	2000/03/22 09:41:10
@@ -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
Index: config/i386/tm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-linux.h,v
retrieving revision 1.4
diff -u -p -r1.4 tm-linux.h
--- config/i386/tm-linux.h	2000/03/16 22:46:30	1.4
+++ config/i386/tm-linux.h	2000/03/22 09:41:10
@@ -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
 
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.7
diff -u -p -r1.7 i386-tdep.c
--- i386-tdep.c	2000/03/16 22:46:26	1.7
+++ i386-tdep.c	2000/03/22 09:41:10
@@ -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)
-			     &regbuf[REGISTER_BYTE (FPDATA_REGNUM)],
-#else /* !FPDATA_REGNUM */
-			     &regbuf[REGISTER_BYTE (FP0_REGNUM)],
-#endif /* FPDATA_REGNUM */
+      if (NUM_FREGS == 0)
+	{
+	  warning ("Cannot find floating-point return value.");
+	  memset (valbuf, 0, len);
+	}
 
-			     &d);
-      store_floating (valbuf, TYPE_LENGTH (type), d);
+      /* 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, &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
-#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, &regbuf[REGISTER_BYTE (LOW_RETURN_REGNUM)], len);
       else if (len <= (low_size + high_size))
 	{
 	  memcpy (valbuf,
-		  regbuf + REGISTER_BYTE (LOW_RETURN_REGNUM),
-		  low_size);
+		  &regbuf[REGISTER_BYTE (LOW_RETURN_REGNUM)], low_size);
 	  memcpy (valbuf + low_size,
-		  regbuf + REGISTER_BYTE (HIGH_RETURN_REGNUM),
-		  len - low_size);
+		  &regbuf[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);
     }
 }
 

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