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] Provide `long double' support for most i386 targets


Hi,

I just checked in the changes I discussed a few weeks ago that should
make `long double' support available in most i386 targets.  It gets
rid of most of the Linux-specific cruft.

The various i386 maintainers may want to put a

   #define HOST_LONG_DOUBLE_FORMAT &floatformat_i387_ext

in their host file.  This will optimize things a bit.  I'll take care
of Linux and the Hurd.

Eli may want to remove the REGISTER_CONVERT_TO_VIRTUAL,
REGISTER_CONVERT_TO_RAW and TARGET_LONG_DOUBLE_BIT stuff from
tm-go32.h.  The LD_I387 definition can probably also be removed.  Its
only purpose would be the HEX_LONG_DOUBLE_INPUT macro, but that macro
is never used in the GDB sources.  By the way Eli, the
I386_DJGPP_TARGET macro is redundant too now I've changed
i386_extract_return_value().

Mark


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

	* config/i386/tm-i386.h: Fix typo.  It is TARGET_LONG_DOUBLE_BIT
	instead of TARGET_LONG_DOUBLE_BITS.
	* config/i386/tm-i386mk.h: Likewise.

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

	Provide `long double' support for most i386 targets.
	* config/i386/tm-i386.h (TARGET_LONG_DOUBLE_FORMAT): Define as
	&floatformat_i387_ext.
	(TARGET_LONG_DOUBLE_BITS): Define as 96.
	(REGISTER_VIRTUAL_TYPE): Change type for FPU registers to
	`builtin_type_long_double'.
	(REGISTER_CONVERT_TO_VIRTUAL): Call
	i386_register_convert_to_virtual.
	(REGISTER_CONVERT_TO_RAW): Call i386_register_convert_to_raw.
	(i387_to_double, double_to_i387): Remove prototypes.
	(i386_extract_return_value): Change prototype to match definition
	in i386-tdep.c.
	* config/i386/tm-i386mk.h (TARGET_LONG_DOUBLE_FORMAT): #undef.
	(TARGET_LONG_DOUBLE_BITS): #undef.
	* config/i386/tm-linux.h (TARGET_LONG_DOUBLE_BIT): Remove.
	[HAVE_LONG_DOUBLE && HOST_I386] (LD_I387): Remove.
	(i387_extract_floating, i387_store_floating): Remove prototypes.
	(TARGET_EXTRACT_FLOATING, TARGET_STORE_FLOATING): Remove.
	(REGISTER_CONVERT_TO_VIRTUAL, REGOISTER_CONVERT_TO_RAW): Remove.
	(REGISTER_VIRTUAL_TYPE): Remove.
	* i386-tdep.c (i386_register_convert_to_virtual): New function.
	(i386_register_convert_to_raw): New function.
	* i387-tdep.c [LD_I387] (i387_extract_floating): Remove.
	(i387_store_floating): Remove.


Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -p -r1.8 -r1.9
--- i386-tdep.c	2000/03/22 09:45:01	1.8
+++ i386-tdep.c	2000/03/26 21:21:50	1.9
@@ -761,6 +761,32 @@ i386_extract_return_value (struct type *
     }
 }
 
+/* Convert data from raw format for register REGNUM in buffer FROM to
+   virtual format with type TYPE in buffer TO.  In principle both
+   formats are identical except that the virtual format has two extra
+   bytes appended that aren't used.  We set these to zero.  */
+
+void
+i386_register_convert_to_virtual (int regnum, struct type *type,
+				  char *from, char *to)
+{
+  /* Copy straight over, but take care of the padding.  */
+  memcpy (to, from, FPU_REG_RAW_SIZE);
+  memset (to + FPU_REG_RAW_SIZE, 0, TYPE_LENGTH (type) - FPU_REG_RAW_SIZE);
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM to
+   raw format for register REGNUM in buffer TO.  Simply omit the two
+   unused bytes.  */
+
+void
+i386_register_convert_to_raw (struct type *type, int regnum,
+			      char *from, char *to)
+{
+  memcpy (to, from, FPU_REG_RAW_SIZE);
+}
+
+     
 #ifdef I386V4_SIGTRAMP_SAVED_PC
 /* Get saved user PC for sigtramp from the pushed ucontext on the stack
    for all three variants of SVR4 sigtramps.  */
Index: i387-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i387-tdep.c,v
retrieving revision 1.1.1.6
retrieving revision 1.2
diff -u -p -r1.1.1.6 -r1.2
--- i387-tdep.c	1999/12/08 02:50:38	1.1.1.6
+++ i387-tdep.c	2000/03/26 21:21:50	1.2
@@ -1,5 +1,5 @@
 /* Intel 387 floating point stuff.
-   Copyright (C) 1988, 1989, 1991, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1988, 89, 91, 98, 99, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -387,51 +387,3 @@ i387_float_info (void)
   printf_filtered ("Opcode:              %s\n",
 		   local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
 }
-
-
-/* FIXME: The functions on this page are used to provide `long double'
-   support for Linux.  However, the approach does not seem to be the
-   right one, and we are planning to solve this in a way that should
-   work for all i386 targets.  These functions will disappear in the
-   near future, so please don't use them.  */
-#ifdef LD_I387
-int
-i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr)
-{
-  if (len == TARGET_LONG_DOUBLE_BIT / 8)
-    {
-      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
-	{
-	  DOUBLEST retval;
-
-	  memcpy (dretptr, addr, sizeof (retval));
-	}
-      else
-	floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr);
-
-      return 1;
-    }
-  else
-    return 0;
-}
-
-int
-i387_store_floating (PTR addr, int len, DOUBLEST val)
-{
-  if (len == TARGET_LONG_DOUBLE_BIT / 8)
-    {
-      /* This `if' may be totally stupid.  I just put it in here to be
-	 absolutely sure I'm preserving the semantics of the code I'm
-	 frobbing, while I try to maintain portability boundaries; I
-	 don't actually know exactly what it's doing.  -JimB, May 1999 */
-      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
-	memcpy (addr, &val, sizeof (val));
-      else
-	floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
-
-      return 1;
-    }
-  else
-    return 0;
-}
-#endif /* LD_I387 */
Index: config/i386/tm-i386.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386.h,v
retrieving revision 1.2
diff -u -p -r1.2 tm-i386.h
--- config/i386/tm-i386.h	2000/02/29 13:28:24	1.2
+++ config/i386/tm-i386.h	2000/03/26 22:08:41
@@ -1,5 +1,5 @@
 /* Macro definitions for GDB on an Intel i[345]86.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -28,6 +28,19 @@ struct type;
 
 #define TARGET_BYTE_ORDER LITTLE_ENDIAN
 
+/* The format used for `long double' on almost all i386 targets is the
+   i387 extended floating-point format.  In fact, of all targets in the
+   GCC 2.95 tree, only OSF/1 does it different, and insists on having
+   a `long double' that's not `long' at all.  */
+
+#define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+
+/* Although the i386 extended floating-point has only 80 significant
+   bits, a `long double' actually takes up 96, probably to enforce
+   alignment.  */
+
+#define TARGET_LONG_DOUBLE_BIT 96
+
 /* Used for example in valprint.c:print_floating() to enable checking
    for NaN's */
 
@@ -229,7 +242,7 @@ extern int i386_register_virtual_size[];
 #define REGISTER_VIRTUAL_TYPE(N)				\
   (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM)	\
    ? lookup_pointer_type (builtin_type_void)			\
-   : IS_FP_REGNUM(N) ? builtin_type_double			\
+   : IS_FP_REGNUM(N) ? builtin_type_long_double			\
    : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
    : builtin_type_int)
 
@@ -240,25 +253,22 @@ extern int i386_register_virtual_size[];
    counterexample, this is still sloppy.  */
 #define REGISTER_CONVERTIBLE(n) (IS_FP_REGNUM (n))
 
-/* Convert data from raw format for register REGNUM in buffer FROM
-   to virtual format with type TYPE in buffer TO.  */
-extern void i387_to_double (char *, char *);
-
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO)	\
-{								\
-  double val;							\
-  i387_to_double ((FROM), (char *)&val);			\
-  store_floating ((TO), TYPE_LENGTH (TYPE), val);		\
-}
-
-extern void double_to_i387 (char *, char *);
-
-#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO)		\
-{								\
-  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE));	\
-  double_to_i387((char *)&val, (TO));				\
-}
+/* Convert data from raw format for register REGNUM in buffer FROM to
+   virtual format with type TYPE in buffer TO.  */
 
+#define REGISTER_CONVERT_TO_VIRTUAL(regnum, type, from, to) \
+  i386_register_convert_to_virtual ((regnum), (type), (from), (to));
+extern void i386_register_convert_to_virtual (int regnum, struct type *type,
+					      char *from, char *to);
+
+/* Convert data from virtual format with type TYPE in buffer FROM to
+   raw format for register REGNUM in buffer TO.  */
+
+#define REGISTER_CONVERT_TO_RAW(type, regnum, from, to) \
+  i386_register_convert_to_raw ((type), (regnum), (from), (to));
+extern void i386_register_convert_to_raw (struct type *type, int regnum,
+					  char *from, char *to);
+
 /* Print out the i387 floating point state.  */
 #ifdef HAVE_I387_REGS
 extern void i387_float_info (void);
@@ -278,11 +288,11 @@ extern void i387_float_info (void);
 /* Extract from an array REGBUF containing the (raw) register state
    a function return value of type TYPE, and copy that, in virtual format,
    into VALBUF.  */
-
-#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
-   i386_extract_return_value ((TYPE),(REGBUF),(VALBUF))
 
-extern void i386_extract_return_value PARAMS ((struct type *, char[], char *));
+#define EXTRACT_RETURN_VALUE(type, regbuf, valbuf) \
+  i386_extract_return_value ((type), (regbuf), (valbuf))
+extern void i386_extract_return_value (struct type *type, char *regbuf,
+				       char *valbuf);
 
 /* Write into appropriate registers a function return value of type TYPE, given
    in virtual format.  */
Index: config/i386/tm-i386mk.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386mk.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 tm-i386mk.h
--- config/i386/tm-i386mk.h	1999/07/07 20:13:09	1.1.1.2
+++ config/i386/tm-i386mk.h	2000/03/26 22:08:41
@@ -1,5 +1,5 @@
 /* Macro definitions for i386, Mach 3.0, OSF 1/MK
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -24,3 +24,15 @@
 #define MK67 1
 
 #include "i386/tm-i386m3.h"
+
+/* FIMXE: kettenis/2000-03-26: On OSF 1, `long double' is equivalent
+   to `double'.  However, I'm not sure what is the consequence of:
+
+   #define TARGET_LONG_DOUBLE_FORMAT TARGET_DOUBLE_FORMAT
+   #define TARGET_LONG_DOUBLE_BIT TARGET_DOUBLE_BIT
+
+   So I'll go with the current status quo instead.  It looks like this
+   target won't compile anyway.  Perhaps it should be obsoleted?  */
+   
+#undef TARGET_LONG_DOUBLE_FORMAT
+#undef TARGET_LONG_DOUBLE_BIT
Index: config/i386/tm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-linux.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-linux.h
--- config/i386/tm-linux.h	2000/03/22 09:45:01	1.5
+++ config/i386/tm-linux.h	2000/03/26 22:08:41
@@ -30,21 +30,16 @@
 #include "i386/tm-i386.h"
 #include "tm-linux.h"
 
-/* This should probably move to tm-i386.h.  */
-#define TARGET_LONG_DOUBLE_BIT 80
+/* FIXME: kettenis/2000-03-26: We should get rid of this last piece of
+   Linux-specific `long double'-support code, probably by adding code
+   to valprint.c:print_floating() to recognize various extended
+   floating-point formats.  */
 
 #if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386)
 /* The host and target are i386 machines and the compiler supports
    long doubles. Long doubles on the host therefore have the same
    layout as a 387 FPU stack register. */
-#define LD_I387
 
-extern int i387_extract_floating (PTR addr, int len, long double *dretptr);
-extern int i387_store_floating   (PTR addr, int len, long double val);
-
-#define TARGET_EXTRACT_FLOATING i387_extract_floating
-#define TARGET_STORE_FLOATING   i387_store_floating
-
 #define TARGET_ANALYZE_FLOATING					\
   do								\
     {								\
@@ -60,30 +55,6 @@ extern int i387_store_floating   (PTR ad
 	&& (((high & 0x7fffffff) | low) != 0);			\
     }								\
   while (0)
-
-#undef REGISTER_CONVERT_TO_VIRTUAL
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO)	\
-{								\
-  long double val = *((long double *)FROM);			\
-  store_floating ((TO), TYPE_LENGTH (TYPE), val);		\
-}
-
-#undef REGISTER_CONVERT_TO_RAW
-#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO)			\
-{									\
-  long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE));	\
-  *((long double *)TO) = val;						\
-}
-
-/* Return the GDB type object for the "standard" data type
-   of data in register N.  */
-#undef REGISTER_VIRTUAL_TYPE
-#define REGISTER_VIRTUAL_TYPE(N)				\
-  (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM)	\
-   ? lookup_pointer_type (builtin_type_void)			\
-   : IS_FP_REGNUM(N) ? builtin_type_long_double			\
-   : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
-   : builtin_type_int)
 
 #endif
 

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