OSDN Git Service

2000-03-26 Mark Kettenis <kettenis@gnu.org>
authorkettenis <kettenis>
Sun, 26 Mar 2000 21:21:50 +0000 (21:21 +0000)
committerkettenis <kettenis>
Sun, 26 Mar 2000 21:21:50 +0000 (21:21 +0000)
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.

gdb/ChangeLog
gdb/config/i386/tm-i386.h
gdb/config/i386/tm-i386mk.h
gdb/config/i386/tm-linux.h
gdb/i386-tdep.c
gdb/i387-tdep.c

index 79752b4..de355b8 100644 (file)
@@ -1,3 +1,30 @@
+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.
+
 Sat Mar 25 18:55:57 2000  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * maint.c: Re-indent.
index 6e3207e..f241884 100644 (file)
@@ -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)
 
@@ -240,24 +253,21 @@ 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 *);
+/* 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)       \
-{                                                              \
-  double val;                                                  \
-  i387_to_double ((FROM), (char *)&val);                       \
-  store_floating ((TO), TYPE_LENGTH (TYPE), val);              \
-}
+#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);
 
-extern void double_to_i387 (char *, char *);
+/* 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)           \
-{                                                              \
-  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE));  \
-  double_to_i387((char *)&val, (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
@@ -279,10 +289,10 @@ extern void i387_float_info (void);
    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 3625efb..de66a69 100644 (file)
@@ -1,21 +1,22 @@
 /* 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.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 /* Until OSF switches to a newer Mach kernel that has
  * a different get_emul_vector() interface.
@@ -23,3 +24,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #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_BITS TARGET_DOUBLE_BITS
+
+   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_BITS
index 2e86a5c..d6a4616 100644 (file)
 #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                                                           \
@@ -61,30 +56,6 @@ extern int i387_store_floating   (PTR addr, int len, long double val);
     }                                                          \
   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
 
 /* The following works around a problem with /usr/include/sys/procfs.h  */
index 421a7a0..39990db 100644 (file)
@@ -761,6 +761,32 @@ i386_extract_return_value (struct type *type, char *regbuf, char *valbuf)
     }
 }
 
+/* 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);
+}
+
+\f     
 #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 869ab9a..20e446d 100644 (file)
@@ -1,42 +1,44 @@
 /* Intel 387 floating point stuff.
-   Copyright (C) 1988, 1989, 1991, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1988, 89, 91, 98, 99, 2000 Free Software Foundation, Inc.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "frame.h"
 #include "inferior.h"
 #include "language.h"
+#include "value.h"
 #include "gdbcore.h"
 #include "floatformat.h"
 
-void i387_to_double PARAMS ((char *, char *));
 
-void double_to_i387 PARAMS ((char *, char *));
+/* 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 PARAMS ((char *from, char *to));
+void double_to_i387 PARAMS ((char *from, char *to));
 
 void
 i387_to_double (from, to)
      char *from;
      char *to;
 {
-  floatformat_to_double (&floatformat_i387_ext, from, (double *)to);
+  floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
 }
 
 void
@@ -44,68 +46,344 @@ double_to_i387 (from, to)
      char *from;
      char *to;
 {
-  floatformat_from_double (&floatformat_i387_ext, (double *)from, to);
+  floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
 }
 
-void
-print_387_control_word (control)
+\f
+/* FIXME: The functions on this page are used by the old `info float'
+   implementations that a few of the i386 targets provide.  These
+   functions should be removed if all of these have been converted to
+   use the generic implementation based on the new register file
+   layout.  */
+
+static void print_387_control_bits PARAMS ((unsigned int control));
+static void print_387_status_bits PARAMS ((unsigned int status));
+
+static void
+print_387_control_bits (control)
      unsigned int control;
 {
-  printf_unfiltered ("control %s: ", local_hex_string(control));
-  printf_unfiltered ("compute to ");
-  switch ((control >> 8) & 3) 
+  switch ((control >> 8) & 3)
     {
-    case 0: printf_unfiltered ("24 bits; "); break;
-    case 1: printf_unfiltered ("(bad); "); break;
-    case 2: printf_unfiltered ("53 bits; "); break;
-    case 3: printf_unfiltered ("64 bits; "); break;
+    case 0:
+      puts_unfiltered (" 24 bit; ");
+      break;
+    case 1:
+      puts_unfiltered (" (bad); ");
+      break;
+    case 2:
+      puts_unfiltered (" 53 bit; ");
+      break;
+    case 3:
+      puts_unfiltered (" 64 bit; ");
+      break;
     }
-  printf_unfiltered ("round ");
-  switch ((control >> 10) & 3) 
+  switch ((control >> 10) & 3)
     {
-    case 0: printf_unfiltered ("NEAREST; "); break;
-    case 1: printf_unfiltered ("DOWN; "); break;
-    case 2: printf_unfiltered ("UP; "); break;
-    case 3: printf_unfiltered ("CHOP; "); break;
+    case 0:
+      puts_unfiltered ("NEAR; ");
+      break;
+    case 1:
+      puts_unfiltered ("DOWN; ");
+      break;
+    case 2:
+      puts_unfiltered ("UP; ");
+      break;
+    case 3:
+      puts_unfiltered ("CHOP; ");
+      break;
     }
-  if (control & 0x3f) 
+  if (control & 0x3f)
     {
-      printf_unfiltered ("mask:");
-      if (control & 0x0001) printf_unfiltered (" INVALID");
-      if (control & 0x0002) printf_unfiltered (" DENORM");
-      if (control & 0x0004) printf_unfiltered (" DIVZ");
-      if (control & 0x0008) printf_unfiltered (" OVERF");
-      if (control & 0x0010) printf_unfiltered (" UNDERF");
-      if (control & 0x0020) printf_unfiltered (" LOS");
-      printf_unfiltered (";");
+      puts_unfiltered ("mask");
+      if (control & 0x0001)
+       puts_unfiltered (" INVAL");
+      if (control & 0x0002)
+       puts_unfiltered (" DENOR");
+      if (control & 0x0004)
+       puts_unfiltered (" DIVZ");
+      if (control & 0x0008)
+       puts_unfiltered (" OVERF");
+      if (control & 0x0010)
+       puts_unfiltered (" UNDER");
+      if (control & 0x0020)
+       puts_unfiltered (" LOS");
+      puts_unfiltered (";");
     }
-  printf_unfiltered ("\n");
-  if (control & 0xe080) warning ("reserved bits on: %s\n",
-                               local_hex_string(control & 0xe080));
+
+  if (control & 0xe080)
+    warning ("\nreserved bits on: %s",
+            local_hex_string (control & 0xe080));
 }
 
 void
-print_387_status_word (status)
+print_387_control_word (control)
+     unsigned int control;
+{
+  printf_filtered ("control %s:", local_hex_string(control & 0xffff));
+  print_387_control_bits (control);
+  puts_unfiltered ("\n");
+}
+
+static void
+print_387_status_bits (status)
      unsigned int status;
 {
-  printf_unfiltered ("status %s: ", local_hex_string (status));
+  printf_unfiltered (" flags %d%d%d%d; ",
+                    (status & 0x4000) != 0,
+                    (status & 0x0400) != 0,
+                    (status & 0x0200) != 0,
+                    (status & 0x0100) != 0);
+  printf_unfiltered ("top %d; ", (status >> 11) & 7);
   if (status & 0xff) 
     {
-      printf_unfiltered ("exceptions:");
-      if (status & 0x0001) printf_unfiltered (" INVALID");
-      if (status & 0x0002) printf_unfiltered (" DENORM");
-      if (status & 0x0004) printf_unfiltered (" DIVZ");
-      if (status & 0x0008) printf_unfiltered (" OVERF");
-      if (status & 0x0010) printf_unfiltered (" UNDERF");
-      if (status & 0x0020) printf_unfiltered (" LOS");
-      if (status & 0x0040) printf_unfiltered (" FPSTACK");
-      printf_unfiltered ("; ");
+      puts_unfiltered ("excep");
+      if (status & 0x0001) puts_unfiltered (" INVAL");
+      if (status & 0x0002) puts_unfiltered (" DENOR");
+      if (status & 0x0004) puts_unfiltered (" DIVZ");
+      if (status & 0x0008) puts_unfiltered (" OVERF");
+      if (status & 0x0010) puts_unfiltered (" UNDER");
+      if (status & 0x0020) puts_unfiltered (" LOS");
+      if (status & 0x0040) puts_unfiltered (" STACK");
+    }
+}
+
+void
+print_387_status_word (status)
+     unsigned int status;
+{
+  printf_filtered ("status %s:", local_hex_string (status & 0xffff));
+  print_387_status_bits (status);
+  puts_unfiltered ("\n");
+}
+
+\f
+/* Implement the `info float' layout based on the register definitions
+   in `tm-i386.h'.  */
+
+/* Print the floating point number specified by RAW.  */
+static void
+print_i387_value (char *raw)
+{
+  DOUBLEST value;
+  
+  floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
+
+  /* We try to print 19 digits.  The last digit may or may not contain
+     garbage, but we'd better print one too many.  We need enough room
+     to print the value, 1 position for the sign, 1 for the decimal
+     point, 19 for the digits and 6 for the exponent adds up to 27.  */
+#ifdef PRINTF_HAS_LONG_DOUBLE
+  printf_filtered (" %-+27.19Lg", (long double) value);
+#else
+  printf_filtered (" %-+27.19g", (double) value);
+#endif
+}
+
+/* Print the classification for the register contents RAW.  */
+static void
+print_i387_ext (unsigned char *raw)
+{
+  int sign;
+  int integer;
+  unsigned int exponent;
+  unsigned long fraction[2];
+
+  sign = raw[9] & 0x80;
+  integer = raw[7] & 0x80;
+  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
+  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
+  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
+                | (raw[5] << 8) | raw[4]);
+
+  if (exponent == 0x7fff && integer)
+    {
+      if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
+       /* Infinity.  */
+       printf_filtered (" %cInf", (sign ? '-' : '+'));
+      else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
+       /* Real Indefinite (QNaN).  */
+       puts_unfiltered (" Real Indefinite (QNaN)");
+      else if (fraction[1] & 0x40000000)
+       /* QNaN.  */
+       puts_filtered (" QNaN");
+      else
+       /* SNaN.  */
+       puts_filtered (" SNaN");
+    }
+  else if (exponent < 0x7fff && exponent > 0x0000 && integer)
+    /* Normal.  */
+    print_i387_value (raw);
+  else if (exponent == 0x0000)
+    {
+      /* Denormal or zero.  */
+      print_i387_value (raw);
+      
+      if (integer)
+       /* Pseudo-denormal.  */
+       puts_filtered (" Pseudo-denormal");
+      else if (fraction[0] || fraction[1])
+       /* Denormal.  */
+       puts_filtered (" Denormal");
+    }
+  else
+    /* Unsupported.  */
+    puts_filtered (" Unsupported");
+}
+
+/* Print the status word STATUS.  */
+static void
+print_i387_status_word (unsigned int status)
+{
+  printf_filtered ("Status Word:         %s",
+                  local_hex_string_custom (status, "04"));
+  puts_filtered ("  ");
+  printf_filtered (" %s", (status & 0x0001) ? "IE" : "  ");
+  printf_filtered (" %s", (status & 0x0002) ? "DE" : "  ");
+  printf_filtered (" %s", (status & 0x0004) ? "ZE" : "  ");
+  printf_filtered (" %s", (status & 0x0008) ? "OE" : "  ");
+  printf_filtered (" %s", (status & 0x0010) ? "UE" : "  ");
+  printf_filtered (" %s", (status & 0x0020) ? "PE" : "  ");
+  puts_filtered ("  ");
+  printf_filtered (" %s", (status & 0x0080) ? "ES" : "  ");
+  puts_filtered ("  ");
+  printf_filtered (" %s", (status & 0x0080) ? "SF" : "  ");
+  puts_filtered ("  ");
+  printf_filtered (" %s", (status & 0x0100) ? "C0" : "  ");
+  printf_filtered (" %s", (status & 0x0200) ? "C1" : "  ");
+  printf_filtered (" %s", (status & 0x0400) ? "C2" : "  ");
+  printf_filtered (" %s", (status & 0x4000) ? "C3" : "  ");
+
+  puts_filtered ("\n");
+
+  printf_filtered ("                       TOP: %d\n", ((status >> 11) & 7));
+}
+
+/* Print the control word CONTROL.  */
+static void
+print_i387_control_word (unsigned int control)
+{
+  printf_filtered ("Control Word:        %s",
+                  local_hex_string_custom (control, "04"));
+  puts_filtered ("  ");
+  printf_filtered (" %s", (control & 0x0001) ? "IM" : "  ");
+  printf_filtered (" %s", (control & 0x0002) ? "DM" : "  ");
+  printf_filtered (" %s", (control & 0x0004) ? "ZM" : "  ");
+  printf_filtered (" %s", (control & 0x0008) ? "OM" : "  ");
+  printf_filtered (" %s", (control & 0x0010) ? "UM" : "  ");
+  printf_filtered (" %s", (control & 0x0020) ? "PM" : "  ");
+
+  puts_filtered ("\n");
+
+  puts_filtered ("                       PC: ");
+  switch ((control >> 8) & 3)
+    {
+    case 0:
+      puts_filtered ("Single Precision (24-bits)\n");
+      break;
+    case 1:
+      puts_filtered ("Reserved\n");
+      break;
+    case 2:
+      puts_filtered ("Double Precision (53-bits)\n");
+      break;
+    case 3:
+      puts_filtered ("Extended Precision (64-bits)\n");
+      break;
+    }
+      
+  puts_filtered ("                       RC: ");
+  switch ((control >> 10) & 3)
+    {
+    case 0:
+      puts_filtered ("Round to nearest\n");
+      break;
+    case 1:
+      puts_filtered ("Round down\n");
+      break;
+    case 2:
+      puts_filtered ("Round up\n");
+      break;
+    case 3:
+      puts_filtered ("Round toward zero\n");
+      break;
     }
-  printf_unfiltered ("flags: %d%d%d%d; ",
-         (status & 0x4000) != 0,
-         (status & 0x0400) != 0,
-         (status & 0x0200) != 0,
-         (status & 0x0100) != 0);
+}
+
+/* Print out the i387 floating poin state.  */
+void
+i387_float_info (void)
+{
+  unsigned int fctrl;
+  unsigned int fstat;
+  unsigned int ftag;
+  unsigned int fiseg;
+  unsigned int fioff;
+  unsigned int foseg;
+  unsigned int fooff;
+  unsigned int fop;
+  int fpreg;
+  int top;
+
+  fctrl = read_register (FCTRL_REGNUM);
+  fstat = read_register (FSTAT_REGNUM);
+  ftag  = read_register (FTAG_REGNUM);
+  fiseg = read_register (FCS_REGNUM);
+  fioff = read_register (FCOFF_REGNUM);
+  foseg = read_register (FDS_REGNUM);
+  fooff = read_register (FDOFF_REGNUM);
+  fop   = read_register (FOP_REGNUM);
+  
+  top = ((fstat >> 11) & 7);
+
+  for (fpreg = 7; fpreg >= 0; fpreg--)
+    {
+      unsigned char raw[FPU_REG_RAW_SIZE];
+      int tag = (ftag >> (fpreg * 2)) & 3;
+      int i;
+
+      printf_filtered ("%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
+
+      switch (tag)
+       {
+       case 0:
+         puts_filtered ("Valid   ");
+         break;
+       case 1:
+         puts_filtered ("Zero    ");
+         break;
+       case 2:
+         puts_filtered ("Special ");
+         break;
+       case 3:
+         puts_filtered ("Empty   ");
+         break;
+       }
+
+      read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
+
+      puts_filtered ("0x");
+      for (i = 9; i >= 0; i--)
+       printf_filtered ("%02x", raw[i]);
+
+      if (tag != 3)
+       print_i387_ext (raw);
+
+      puts_filtered ("\n");
+    }
+
+  puts_filtered ("\n");
 
-  printf_unfiltered ("top %d\n", (status >> 11) & 7);
+  print_i387_status_word (fstat);
+  print_i387_control_word (fctrl);
+  printf_filtered ("Tag Word:            %s\n",
+                  local_hex_string_custom (ftag, "04"));
+  printf_filtered ("Instruction Pointer: %s:",
+                  local_hex_string_custom (fiseg, "02"));
+  printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
+  printf_filtered ("Operand Pointer:     %s:",
+                  local_hex_string_custom (foseg, "02"));
+  printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
+  printf_filtered ("Opcode:              %s\n",
+                  local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
 }