`long double' support for ix86 targets

Mark Kettenis kettenis@wins.uva.nl
Fri Mar 3 07:31:00 GMT 2000


Hi,

Kevin's changes to findvar.c:extract_floating() and store_floating()
together with some further analysis have convinced me that for all but
one ix86 targets 96-bit long doubles of type &floatformat_i387_ext are
the right thing.  This would give most of the ix86 targets instant
support for long doubles.  It also gives us the opportunity to remove
some ugly bits introduced by people who tried to hack around the
current limitations.

Here are some personal notes I made about this:

   Support for `long double'
   -------------------------

   The majority of i386 targets in GCC have a `long double' that is
   96 bits wide (of which only 80 bits are used, the rest is padding).
   In fact the only exception is OSF/1, where `long double' is equivalent
   to `double' and has only 64 bits.  This length of 96 bits is also
   used in the debugging information generated by the compiler.

   The origional i386 System V ABI specification doesn't say anything about
   `long double', but the new (draft) IA-64 System V ABI specification
   uses a `long double' of 96 bits for things running in 32-bit mode.
   I guess that 32-bit mode is supposed to be provided for compatible
   with IA-32, this implies that 96 bits is supposed to be the standard.

   Therefore, `config/i386/tm-i386.h' should define:

     #define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext
     #define TARGET_LONG_DOUBLE_BITS 96

   Targets such as OSF/1 can override this.

   If we do the above, we can make the default "virtual" type of the FPU
   registers `builtin_type_long_double'.  A lot of the Linux cruft for
   dealing with `long double' could be removed.

I intend to check in the following patch in a week or two, but since
this change affects most of the ix86 targets, I'd like to give people
the opportunity to object.

Mark


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

	* 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): Simply copy over the data, and pad
	with zeroes.
	(REGISTER_CONVERT_TO_RAW): Simply copy over the significant data.
	(i387_to_double, double_to_i387): Remove prototypes.


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/03 15:00:49
@@ -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_BITS 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)
 
@@ -239,25 +252,22 @@ extern int i386_register_virtual_size[];
    that SSE registers need conversion.  Even if we can't find a
    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 *);
 
+/* 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.  */
 #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));				\
-}
+  {								\
+    memset ((TO), 0, TYPE_LENGTH (TYPE));			\
+    memcpy ((TO), (FROM), 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.  */
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+  memcpy ((TO), (FROM), FPU_REG_RAW_SIZE)
 
 /* Print out the i387 floating point state.  */
 #ifdef HAVE_I387_REGS


More information about the Gdb mailing list