Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: hjl@lucon.org (H.J. Lu)
To: shebs@cygnus.com (Stan Shebs)
Cc: jtc@redback.com, gdb@sourceware.cygnus.com
Subject: Re: x86 fpu
Date: Thu, 21 Oct 1999 07:50:00 -0000	[thread overview]
Message-ID: <19991021145036.E76601B493@ocean.lucon.org> (raw)
In-Reply-To: <199910210657.XAA08245@andros.cygnus.com>

> 
> 
>    Date: Wed, 20 Oct 1999 23:06:00 -0700 (PDT)
>    From: hjl@lucon.org (H.J. Lu)
> 
>    [...] It is a pain for me to maintain my
>    private versions. But I hate to see the Linux people nowhere to
>    go for help. Do you really honestly believe that a new official
>    version should be made whenever a serious Linux related bug is
>    fixed or we have to live with the bug which mainly affects Linux?
> 
> That's not necessarily a bad idea... If one were to look at which
> platform has the largest number of GDB-using programmers these days,
> it would most likely be GNU/Linux by far.  Why can't the GDB release

Please also remember that the GNU tools are the only ones GNU/Linux
get. If they don't work for us, we have to find a workaround one way
or the other.

> schedule be adjusted to accommodate the majority of users?

I am glad to see it is happening for gdb. Finally I can get rid of my
Linux version of gdb. I wish I could say the same for other tools.

BTW, I have sent in a patch for cplus-dem.c to the gcc patches mailing
list. It is/will be used by some of GNU/Linux tools. However, I have
a feeling that it will take forever to get accepted.

> 
>    I have been sending my patches to the appropriate people. But they
>    don't work only for Linux. My patches have to wait, but Linux cann't.
>    It is not that unusual to take a few months or more for my patches
>    to be installed.  What do we do?
> 
> This is the genesis of the situation.  Patch submissions should be
> acted upon promptly, whether to accept or reject.  It's my
> responsibility to see that this happens, and if I fail at that,
> I'm not going to fault anyone for coming up with workarounds like
> splinter versions.

Sometimes, it takes a splinter version to get things done and we have
to take the consequences. I am not proud of the Linux C library 5. I
wish it had never happened. But without it, we may never have Linux
nor glibc 2 today.

> 
> I hope everybody agrees that patch turnaround has improved over the
> past several months.  It's still not where it should be; if you feel a
> worthy patch is being ignored, please send me mail with lots of
> capital letters and exclamation points, or call me on the phone at
> +1 408 542 9678.

I will send in a few patches after x86 fpu is resolved.

> 
>    I will work with everyone to merge my changes. But it doesn't mean
>    I will stop working for the Linux community. We have different
>    priorities. That is life.
> 
> This should not be true however.  I used to think this myself, until
> RMS pointed out that since Linux is one of the official kernels for
> the GNU system, GDB support for it ought to be a higher priority than
> support for non-GNU systems.  Of course, GDB is still free software
> like always, and I still want to encourage people to contribute
> improvements for non-GNU systems as well.
> 
> Lately, Jim Blandy and Jim Kingdon have stepped up to the task of
> making sure the FSF version of GDB is fully functional for GNU/Linux,
> and there has been considerable progress, as witness the discussion of
> x86 float support.  Also, Scott Bambrough has been hard at work on
> Netwinder (ARM) support, and Kevin Buettner is on PowerPC.  At this
> rate, I expect that the upcoming 5.0 release will be the version of
> choice for GNU/Linux.

First is glibc, now is gdb. What are the next? binutils and gcc? I
am not holding my breath.

Thanks.


-- 
H.J. Lu (hjl@gnu.org)
From eliz@gnu.org Thu Oct 21 08:20:00 1999
From: Eli Zaretskii <eliz@gnu.org>
To: Mark Kettenis <kettenis@wins.uva.nl>
Cc: jtc@redback.com, jimb@cygnus.com, gdb@sourceware.cygnus.com
Subject: Re: Unifying the x86 FPU register sets
Date: Thu, 21 Oct 1999 08:20:00 -0000
Message-id: <199910211520.LAA21979@mescaline.gnu.org>
References: <199910151716.MAA03441@zwingli.cygnus.com> <5mwvsjoyu0.fsf@jtc.redbacknetworks.com> <199910211332.PAA00729@delius.kettenis.local>
X-SW-Source: 1999-q4/msg00094.html
Content-length: 822

> Note that in `tm-go32.h' there is a
> 
>    #undef TARGET_LONG_DOUBLE_BIT
>    #define TARGET_LONG_DOUBLE_BIT 96
> 
> So DJGPP is already treating the 80-bit extended types as a 96-bit
> type.

Why, of course! ;-)  That's because somebody noticed, a long time ago,
that this is required in order to get 80-bit registers supported.

> Then it will be very easy to support the i387 data registers as `long
> doubles' on hosts that have an equivalent type, without the LD_387
> kludge that's now used by DJGPP and Linux/i386.

I'm not sure.  There's a related issue of whether the library supports
long double in scanf and printf families of functions.  (There's also
the issue of the compiler support for long double, but it's a
non-issue for DJGPP and Linux ;-)

Would your suggestion handle all of these considerations?
From Grant.Edwards@comtrol.com Thu Oct 21 09:03:00 1999
From: Grant.Edwards@comtrol.com
To: gdb@sourceware.cygnus.com
Subject: RDI target issues
Date: Thu, 21 Oct 1999 09:03:00 -0000
Message-id: <19991021110315.A3542@comtrol.com>
X-SW-Source: 1999-q4/msg00095.html
Content-length: 1431

I've been working on getting gdb 4.18 (arm-elf) to work with the
rdi target.  I've had to make some changes to the rdi library
code from ARM (in the rdi-share directory):

 1) Disable heartbeat functionality, since it makes the JTAG
    interface boxes from both ARM and EPI fall over..
    
 2) Fix the code that was throwing away error codes returned
    by the JTAG boxes with the "stopped" message.

 3) Added a considerable amount of logging functionality (this
    still needs to be cleaned up and made run-timeconfigurable).

I've also had to make changes to gdb code in remote-rdi.c::

 1) Make sure the ADP device is closed before attempting to
    open it.
    
 2) Allow target options to be passed to Adp_OpenDevice.

 3) Changed the way that log messages from remote are handled
    (this goes along with #3 above, and still needs work).
 
 4) Disable automatic setting of breakpoints on interrupt
    vectors.

Question: 

Change 4 only needs to happen if the target platform has ROM at
address 0.  Otherwise, (RAM ad address 0) the old behavior is
probably best.  How should this option be configured by the
user?  Right now, the parameters to the "target rdi" gdb
command are just passed on to the Adp_OpenDevice routine from
ARM.  I could parse those options and strip out the ones I want
to handle in remote-rdi.c before passing them on to the RDI
library.

Comments?

-- 
Grant Edwards
Grant.Edwards@comtrol.com
From kettenis@wins.uva.nl Thu Oct 21 09:13:00 1999
From: Mark Kettenis <kettenis@wins.uva.nl>
To: eliz@gnu.org
Cc: jtc@redback.com, jimb@cygnus.com, gdb@sourceware.cygnus.com
Subject: Re: Unifying the x86 FPU register sets
Date: Thu, 21 Oct 1999 09:13:00 -0000
Message-id: <199910211613.SAA03931@delius.kettenis.local>
References: <199910211504.LAA20217@mescaline.gnu.org>
X-SW-Source: 1999-q4/msg00096.html
Content-length: 1991

[ Sorry Eli, but I guess you know why you receive this message another
  time ;-)]

   Date: Thu, 21 Oct 1999 11:04:53 -0400
   From: Eli Zaretskii <eliz@gnu.org>

   < 5mwvsjoyu0.fsf@jtc.redbacknetworks.com > < 199910211332.PAA00729@delius.kettenis.local >
   Subject: Re: Unifying the x86 FPU register sets
   --text follows this line--
   > Note that in `tm-go32.h' there is a
   > 
   >    #undef TARGET_LONG_DOUBLE_BIT
   >    #define TARGET_LONG_DOUBLE_BIT 96
   > 
   > So DJGPP is already treating the 80-bit extended types as a 96-bit
   > type.

   Why, of course! ;-)  That's because somebody noticed, a long time ago,
   that this is required in order to get 80-bit registers supported.

Apparently the Linux people didn't notice it ;-).

   > Then it will be very easy to support the i387 data registers as `long
   > doubles' on hosts that have an equivalent type, without the LD_387
   > kludge that's now used by DJGPP and Linux/i386.

   I'm not sure.  There's a related issue of whether the library supports
   long double in scanf and printf families of functions.  (There's also
   the issue of the compiler support for long double, but it's a
   non-issue for DJGPP and Linux ;-)

   Would your suggestion handle all of these considerations?

Yes!

The nice thing is that GDB already has all the code that is necessary
to handle this.  If the compiler doesn't support a 80/96-bit `long
double' type, the registers are converted to ordinary doubles right
away.  Printing those should be no problem.  If the compiler does
support a 80/96-bit `long double' type, the registers are padded to
96-bits.  Before printing, these are converted to the representation
the host uses, taking in account endianness and other representation
details.  If the library on the host supports printing long double
(PRINTF_HAS_LONG_DOUBLE) it is printed with full precision.  If not,
then the result is converted to double before printing.  See
valprint.c:print_floating() for details.

Mark
From kettenis@wins.uva.nl Thu Oct 21 09:34:00 1999
From: Mark Kettenis <kettenis@wins.uva.nl>
To: gdb@sourceware.cygnus.com
Cc: jtc@redback.com, jimb@cygnus.com, eliz@gnu.org, gdb-patches@sourceware.cygnus.com
Subject: x86 FPU support: "info float" and `long double'
Date: Thu, 21 Oct 1999 09:34:00 -0000
Message-id: <199910211634.SAA03952@delius.kettenis.local>
X-SW-Source: 1999-q4/msg00097.html
Content-length: 17926

OK, here is my attempt at implementing the "info float" comment and
prividing proper long double support without any hacks.  Once this is
in we should remove the Linux-specific TARGET_{EXTRACT|STORE}_FLOATING
hooks that were introduced in findvar.c, and try to find a better
solution for TARGET_ANALYZE_FLOATING.

The output for "info float" is almost identical to DJGPP.  The FP
registers are printed in physical order with "=>" indicating the top
of stack.  Printing the opcode mnemonic is not so easy.  I looked at
libopcode, but I could not find an appropriate entry-point.

Anyway, the output looks like:

(gdb) info float
status 0x3800: flags 0000; top 7;
control 0x37f: 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS;
last FP instruction: opcode 0xdd05; pc 0x23:0x8048495; operand 0x2b:0x8048f04
regno tag     msb              lsb  value
=> 7: valid   4000c90fdaa22168c000  3.141592653589793116
   6: empty   3ff7d100000000000000  0.006378173828125
   5: empty   40098000000000000000  1024
   4: empty   3fff8000000000000000  1
   3: empty   3fff8000000000000000  1
   2: empty   3ffb9d8909ff2e48e8c0  0.076921537494659423997
   1: empty   3ffbdaf3e93361992eb3  0.10691053569844352396
   0: empty   00000000000000000000  0
(gdb)  

Suggestions for improvement are welcome!

I don't know if this stuff is ready for inclusion yet.  Given the size
of the patch a copyright assignment is probably needed.  I'll try to
assign past and future changes as soon as possible.

If Jim is still making changes to the register file layout, I'll keep
track of his changes and resend the patch.

Mark


1999-10-21  Mark Kettenis  <kettenis@gnu.org>

	* i387-tdep.c: Strip PARAMS.
	(i387_float_info): New function.
	(i387_register_virtual_type): New function.
	(i387_register_convert_to_virtual, i387_register_convert_to_raw):
	New functions.
	(i387_extract_floating, i387_store_floating): Removed.

	* config/i386/tm-i386.h (TARGET_LONG_DOUBLE_BIT,
	TARGET_LONG_DOUBLE_FORMAT): New definitions.
	TARGET_ANALYZE_FLOATING: Moved here from config/i386/tm-linux.h.
	(i387_register_virtual_type): New declaration.
	(REGISTER_VIRTUAL_TYPE): Call i387_register_virtual_type to get
	data type of FP data registers.
	(i387_to_double, double_to_i387): Removed declarations.
	(i387_register_convert_to_virtual, i387_register_convert_to_raw):
	New declarations.
	(REGISTER_CONVERT_TO_VIRTUAL): Let
	i387_register_convert_to_virtual handle the conversion.
	(REGISTER_CONVERT_TO_RAW): Let i387_register_convert_to_raw handle
	the conversion.
	[HAVE_I387_REGS] (i387_float_info): New declaration.
	[HAVE_I387_REGS] (FLOAT_INFO): New define.

	* config/i386/tm-linux.h (TARGET_LONG_DOUBLE_BIT,
	TARGET_EXTRACT_FLOATING, TARGET_STORE_FLOATING,
	REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW,
	REGISTER_VIRTUAL_TYPE): Remove definitions.
	(TARGET_ANALYZE_FLOATING): Moved to config/i386/tm-i386.h.
	(i387_extract_floating, i387_store_floating): Remove declarations.
	(LD_I387): Do not define.


Index: gdb/gdb/i387-tdep.c
===================================================================
RCS file: /var/cvsroot/gdb/gdb/i387-tdep.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 i387-tdep.c
--- gdb/gdb/i387-tdep.c	1999/10/02 19:51:09	1.1.1.4
+++ gdb/gdb/i387-tdep.c	1999/10/21 15:57:28
@@ -1,5 +1,5 @@
 /* Intel 387 floating point stuff.
-   Copyright (C) 1988, 1989, 1991, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1989, 1991, 1998, 1999 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,34 +26,31 @@
 #include "gdbcore.h"
 #include "floatformat.h"
 
-void i387_to_double PARAMS ((char *, char *));
-void double_to_i387 PARAMS ((char *, char *));
+static void print_387_control_bits (unsigned int control);
+static void print_387_status_bits  (unsigned int status);
 
-static void print_387_control_bits PARAMS ((unsigned int control));
-static void print_387_status_bits  PARAMS ((unsigned int status));
+\f
+/* FIXME: Eliminate the next two functions when we have the time to
+   change all the callers.  */
 
-/* FIXME:  Eliminate these routines when we have the time to change all
-   the callers.  */
+void i387_to_double (char *from, char *to);
+void double_to_i387 (char *from, char *to);
 
 void
-i387_to_double (from, to)
-     char *from;
-     char *to;
+i387_to_double (char *from, char *to)
 {
   floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
 }
 
 void
-double_to_i387 (from, to)
-     char *from;
-     char *to;
+double_to_i387 (char *from, char *to)
 {
   floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
 }
 
+\f
 static void
-print_387_control_bits (control)
-     unsigned int control;
+print_387_control_bits (unsigned int control)
 {
   switch ((control >> 8) & 3)
     {
@@ -108,9 +105,10 @@
 	     local_hex_string (control & 0xe080));
 }
 
+/* FIXME: Make this static once we have converted all i386 targets to
+   use the GDB register file.  */
 void
-print_387_control_word (control)
-     unsigned int control;
+print_387_control_word (unsigned int control)
 {
   printf_filtered ("control %s:", local_hex_string(control & 0xffff));
   print_387_control_bits (control);
@@ -118,8 +116,7 @@
 }
 
 static void
-print_387_status_bits (status)
-     unsigned int status;
+print_387_status_bits (unsigned int status)
 {
   printf_unfiltered (" flags %d%d%d%d; ",
 		     (status & 0x4000) != 0,
@@ -140,53 +137,141 @@
     }
 }
 
+/* FIXME: Make this static once we have converted all i386 targets to
+   use the GDB register file.  */
 void
-print_387_status_word (status)
-     unsigned int status;
+print_387_status_word (unsigned int status)
 {
   printf_filtered ("status %s:", local_hex_string (status & 0xffff));
   print_387_status_bits (status);
   puts_unfiltered ("\n");
 }
 
-#ifdef LD_I387
-int
-i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr)
+/* Print out the i387 floating poin state.  */
+void
+i387_float_info (void)
 {
-  if (len == TARGET_LONG_DOUBLE_BIT / 8)
+  unsigned int fctrl;
+  unsigned int fstat;
+  unsigned int ftag;
+  unsigned int fcs;
+  unsigned int fcoff;
+  unsigned int fds;
+  unsigned int fdoff;
+  unsigned int fop;
+  int fpreg;
+  int top;
+
+  read_register_gen (FCTRL_REGNUM, (char *) &fctrl);
+  read_register_gen (FSTAT_REGNUM, (char *) &fstat);
+  read_register_gen (FTAG_REGNUM,  (char *) &ftag);
+  read_register_gen (FCS_REGNUM,   (char *) &fcs);
+  read_register_gen (FCOFF_REGNUM, (char *) &fcoff);
+  read_register_gen (FDS_REGNUM,   (char *) &fds);
+  read_register_gen (FDOFF_REGNUM, (char *) &fdoff);
+  read_register_gen (FOP_REGNUM,   (char *) &fop);
+  
+  print_387_status_word (fstat);
+  print_387_control_word (fctrl);
+  printf_unfiltered ("last FP instruction: ");
+  printf_unfiltered ("opcode %s; ",
+		     local_hex_string (fop ? (fop | 0xd800) : 0));
+  printf_unfiltered ("pc %s:", local_hex_string (fcs));
+  printf_unfiltered ("%s; ", local_hex_string (fcoff));
+  printf_unfiltered ("operand %s", local_hex_string (fds));
+  printf_unfiltered (":%s\n", local_hex_string (fdoff));
+
+  top = ((fstat >> 11) & 7);
+
+  printf_unfiltered ("regno tag     msb              lsb  value\n");
+  for (fpreg = 7; fpreg >= 0; fpreg--)
     {
-      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
-	{
-	  DOUBLEST retval;
+      unsigned char raw[FPU_REG_RAW_SIZE];
+      DOUBLEST value;
+      int i;
+
+      printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
 
-	  memcpy (dretptr, addr, sizeof (retval));
+      switch ((ftag >> (fpreg * 2)) & 3)
+	{
+	case 0:
+	  printf_unfiltered ("valid   ");
+	  break;
+	case 1:
+	  printf_unfiltered ("zero    ");
+	  break;
+	case 2:
+	  printf_unfiltered ("special ");
+	  break;
+	case 3:
+	  printf_unfiltered ("empty   ");
+	  break;
 	}
-      else
-	floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr);
 
-      return 1;
+      read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
+      
+      for (i = 9; i >= 0; i--)
+	printf_unfiltered ("%02x", raw[i]);
+
+      floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
+
+#ifdef PRINTF_HAS_LONG_DOUBLE
+      printf_unfiltered ("  %.20Lg\n", (long double) value);
+#else
+      printf_unfiltered ("  %.20g\n", (double) value);
+#endif
     }
-  else
-    return 0;
 }
 
-int
-i387_store_floating (PTR addr, int len, DOUBLEST val)
+\f
+/* Return the "standard" data type of data in the FPU data registers.
+   We use `long double' if the host has them in a representation
+   equivalent with the i387 extended format, and `double' otherwise.  */
+struct type *
+i387_register_virtual_type (void)
 {
-  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);
+#ifdef HAVE_LONG_DOUBLE
+  if (sizeof (long double) == (TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT))
+    return  builtin_type_long_double;
+#endif
+  return builtin_type_double;
+}
 
-      return 1;
+/* Convert REGNUM, which raw contents are stored in FROM to "standard"
+   data type TYPE and store the result into TO.  */
+void
+i387_register_convert_to_virtual (int regnum, struct type *type,
+				  char *from, char *to)
+{
+#ifdef HAVE_LONG_DOUBLE
+  if (type == builtin_type_long_double)
+    {
+      memset (to, 0, REGISTER_VIRTUAL_SIZE (regnum));
+      memcpy (to, from, REGISTER_RAW_SIZE (regnum));
     }
+  else
+#endif
+    {
+      double val;
+      floatformat_to_double (&floatformat_i387_ext, from, &val);
+      floatformat_from_double (&floatformat_ieee_double_little, &val, to);
+    }
+}
+
+/* Convert the "standard" data type TYPE stored in FROM and store the
+   result in REGNUM whose raw contents live at TO.  */
+void
+i387_register_convert_to_raw (struct type *type, int regnum,
+			      char *from, char *to)
+{
+#ifdef HAVE_LONG_DOUBLE
+  if (type == builtin_type_long_double)
+    memcpy (to, from, REGISTER_RAW_SIZE (regnum));
   else
-    return 0;
+#endif
+    {
+      double val;
+      floatformat_to_double (&floatformat_ieee_double_little, from, &val);
+      floatformat_from_double (&floatformat_i387_ext, &val, to);
+    }
 }
-#endif /* LD_I387 */
Index: gdb/gdb/config/i386/tm-i386.h
===================================================================
RCS file: /var/cvsroot/gdb/gdb/config/i386/tm-i386.h,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 tm-i386.h
--- gdb/gdb/config/i386/tm-i386.h	1999/10/20 10:44:05	1.1.1.7
+++ gdb/gdb/config/i386/tm-i386.h	1999/10/21 15:08:56
@@ -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, 1999 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -222,43 +222,75 @@
 /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
 #define MAX_REGISTER_VIRTUAL_SIZE 16
 
+/* Although the i387 has a 80-bit extended floating point type, almost
+   all systems supported by GCC use 96-bit and extra padding for
+   alignment.  The exception seems to be OSF/1, where `long double' is
+   the same as `double', but there is no OSF/1 support in GDB.  */
+#define TARGET_LONG_DOUBLE_BIT 96
+#define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+
+/* Detect NaNs for the i387 extended floating point format.
+   FIXME: This is not very well hought out and should be replaced by
+   NaN classification based on floatformat.h, fully integrated in GDB.  */
+#define TARGET_ANALYZE_FLOATING					\
+  do								\
+    {								\
+      if (len == 10)                                            \
+        {							\
+          unsigned expon;		 			\
+								\
+	  low = extract_unsigned_integer (valaddr, 4);		\
+          high = extract_unsigned_integer (valaddr + 4, 4);	\
+          expon = extract_unsigned_integer (valaddr + 8, 2);	\
+								\
+          nonnegative = ((expon & 0x8000) == 0);		\
+          is_nan = ((expon & 0x7fff) == 0x7fff)			\
+	    && ((high & 0x80000000) == 0x80000000)		\
+	    && (((high & 0x7fffffff) | low) != 0);		\
+        }                                                       \
+      else                                                      \
+        is_nan = 0;                                             \
+    }								\
+  while (0)
+
 /* Return the GDB type object for the "standard" data type of data in 
    register N.  Perhaps si and di should go here, but potentially they
    could be used for things other than address.  */
 
+/* Return the "standard" data type of data in the FPU data registers.
+   We use `long double' if the host has them in a representation
+   equivalent with the i387 extended format, and `double' otherwise.  */
+extern struct type *i387_register_virtual_type (void);
+
 #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) ? i387_register_virtual_type ()            \
    : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
    : builtin_type_int)
+
+/* Convert the 80-bit FPU data registers to the "standard" data type
+   and back.  */
+extern void i387_register_convert_to_virtual (int regnum, struct type *type,
+					      char *from, char *to);
+extern void i387_register_convert_to_raw (struct type *type, int regnum,
+					  char *from, char *to);
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(regnum, type, from, to) \
+  i387_register_convert_to_virtual ((regnum), (type), (from), (to))
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(type, regnum, from, to)	\
+  i387_register_convert_to_raw ((type), (regnum), (from), (to))
 
-/* REGISTER_CONVERTIBLE(N) is true iff register N's virtual format is
-   different from its raw format.  Note that this definition assumes
-   that the host supports IEEE 32-bit floats, since it doesn't say
-   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 *);
-
-#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));				\
-}
+/* Print out the i387 floating point state.  */
+#ifdef HAVE_I387_REGS
+extern void i387_float_info (void);
+#define FLOAT_INFO { i387_float_info (); }
+#endif
 
+\f
 /* Store the address of the place in which to copy the structure the
    subroutine will return.  This is called from call_function. */
 
Index: gdb/gdb/config/i386/tm-linux.h
===================================================================
RCS file: /var/cvsroot/gdb/gdb/config/i386/tm-linux.h,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 tm-linux.h
--- gdb/gdb/config/i386/tm-linux.h	1999/10/20 10:44:05	1.1.1.5
+++ gdb/gdb/config/i386/tm-linux.h	1999/10/21 15:09:22
@@ -1,5 +1,5 @@
 /* Definitions to target GDB to GNU/Linux on 386.
-   Copyright 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1992, 1993, 1999 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -41,59 +41,6 @@
 
 #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
-
-#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								\
-    {								\
-      unsigned expon;						\
-								\
-      low = extract_unsigned_integer (valaddr, 4);		\
-      high = extract_unsigned_integer (valaddr + 4, 4);		\
-      expon = extract_unsigned_integer (valaddr + 8, 2);	\
-								\
-      nonnegative = ((expon & 0x8000) == 0);			\
-      is_nan = ((expon & 0x7fff) == 0x7fff)			\
-	&& ((high & 0x80000000) == 0x80000000)			\
-	&& (((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)					\
-  (IS_FP_REGNUM (N) ? builtin_type_long_double : builtin_type_int)
-
-#endif
 
 /* The following works around a problem with /usr/include/sys/procfs.h  */
 #define sys_quotactl 1
From hjl@lucon.org Thu Oct 21 10:13:00 1999
From: hjl@lucon.org (H.J. Lu)
To: kettenis@wins.uva.nl (Mark Kettenis)
Cc: gdb@sourceware.cygnus.com, jtc@redback.com, jimb@cygnus.com, eliz@gnu.org, gdb-patches@sourceware.cygnus.com
Subject: Re: x86 FPU support: "info float" and `long double'
Date: Thu, 21 Oct 1999 10:13:00 -0000
Message-id: <19991021171307.87FEC1B493@ocean.lucon.org>
References: <199910211634.SAA03952@delius.kettenis.local>
X-SW-Source: 1999-q4/msg00098.html
Content-length: 2762

> (gdb) info float
> status 0x3800: flags 0000; top 7;
> control 0x37f: 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS;
> last FP instruction: opcode 0xdd05; pc 0x23:0x8048495; operand 0x2b:0x8048f04
> regno tag     msb              lsb  value
> => 7: valid   4000c90fdaa22168c000  3.141592653589793116
>    6: empty   3ff7d100000000000000  0.006378173828125
>    5: empty   40098000000000000000  1024
>    4: empty   3fff8000000000000000  1
>    3: empty   3fff8000000000000000  1
>    2: empty   3ffb9d8909ff2e48e8c0  0.076921537494659423997
>    1: empty   3ffbdaf3e93361992eb3  0.10691053569844352396
>    0: empty   00000000000000000000  0
> (gdb)  
> 
> Suggestions for improvement are welcome!
> 

My current gdb has

(gdb) info float
     st0: 0x3ffed6d6d6d6d6d6d800  Empty Normal 0.8392156862745098200307
     st1: 0x00000000000000000000  Empty Zero   0
     st2: 0x00000000000000000000  Empty Zero   0
     st3: 0x00000000000000000000  Empty Zero   0
     st4: 0x00000000000000000000  Empty Zero   0
     st5: 0x3ffe8000000000000000  Empty Normal 0.5
     st6: 0x4003b000000000000000  Empty Normal 22
     st7: 0x4003b000000000000000  Empty Normal 22
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS;
   fstat:     0x0000 flags 0000; top 0; 
    ftag:     0xffff
     fip: 0x00000000
     fcs: 0x00000000
  fopoff: 0x00000000
  fopsel:     0x0000

It is also the same as yours. However, I have an extra field for stack
register:

     st0: 0x3ffed6d6d6d6d6d6d800  Empty Normal 0.8392156862745098200307
					^^^^^^

It shouldn't be hard to add. I am enclosing the relevant code here.


H.J.
----
      expon = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum)
					+ 8, 2);
      sign = expon & 0x8000;
      expon &= 0x7fff;
      ms = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + 4, 4);
      ls = extract_signed_integer (raw_regs + REGISTER_BYTE (regnum), 4);
      norm = ms & 0x80000000;

      if ( expon == 0 )
	{
	  if ( ms | ls )
	    {
	      /* Denormal or Pseudodenormal. */
	      if ( norm )
		puts_unfiltered ("Pseudo ");
	      else
		puts_unfiltered ("Denorm ");
	    }
	  else
	    {
	      /* Zero. */
	      puts_unfiltered ("Zero   ");
	    }
	}
      else if ( expon == 0x7fff )
	{
	  /* Infinity, NaN or unsupported. */
	  if ( (ms == 0x80000000) &&
	       (ls == 0) )
	    {
              puts_unfiltered ("Infty  ");
	    }
	  else if ( norm )
	    {
	      if ( ms & 0x40000000 )
		puts_unfiltered ("QNaN   ");
	      else
		puts_unfiltered ("SNaN   ");
	    }
	  else
	    {
              puts_unfiltered ("Unsupp ");
	    }
	}
      else
	{
	  /* Normal or unsupported. */
	  if ( norm )
	    puts_unfiltered ("Normal ");
	  else
	    puts_unfiltered ("Unsupp ");
	}


       reply	other threads:[~1999-10-21  7:50 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <199910210657.XAA08245@andros.cygnus.com>
1999-10-21  7:50 ` H.J. Lu [this message]
     [not found] <19991019182843.E7C093FC1@valinux.com>
     [not found] ` <npemerjigt.fsf@zwingli.cygnus.com>
1999-10-19 16:43   ` Mark Kettenis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=19991021145036.E76601B493@ocean.lucon.org \
    --to=hjl@lucon.org \
    --cc=gdb@sourceware.cygnus.com \
    --cc=jtc@redback.com \
    --cc=shebs@cygnus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox