Add forgotten ChangeLog snippet for last elf64-x86-64.c patch.
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
index 3d4b39775fb5eb4160a78ae6e75a21e4f563b2a8..f7800af64159a29f358e35d535b9429487a98777 100644 (file)
@@ -1,6 +1,7 @@
 /* Intel 387 floating point stuff.
+
    Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
-   2001, 2002 Free Software Foundation, Inc.
+   2001, 2002, 2003 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "doublest.h"
+#include "floatformat.h"
 #include "frame.h"
+#include "gdbcore.h"
 #include "inferior.h"
 #include "language.h"
-#include "value.h"
-#include "gdbcore.h"
-#include "floatformat.h"
 #include "regcache.h"
+#include "value.h"
+
 #include "gdb_assert.h"
 #include "gdb_string.h"
-#include "doublest.h"
 
 #include "i386-tdep.h"
+#include "i387-tdep.h"
 
-/* FIXME: Eliminate the next two functions 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 (char *from, char *to)
-{
-  floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
-}
-
-void
-double_to_i387 (char *from, char *to)
-{
-  floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
-}
-
-\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 (unsigned int control);
-static void print_387_status_bits (unsigned int status);
-
-static void
-print_387_control_bits (unsigned int control)
-{
-  switch ((control >> 8) & 3)
-    {
-    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;
-    }
-  switch ((control >> 10) & 3)
-    {
-    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)
-    {
-      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 (";");
-    }
-
-  if (control & 0xe080)
-    warning ("\nreserved bits on: %s",
-            local_hex_string (control & 0xe080));
-}
-
-void
-print_387_control_word (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 (unsigned int 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) 
-    {
-      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 (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, struct ui_file *file)
 {
@@ -183,6 +64,7 @@ print_i387_value (char *raw, struct ui_file *file)
 }
 
 /* Print the classification for the register contents RAW.  */
+
 static void
 print_i387_ext (unsigned char *raw, struct ui_file *file)
 {
@@ -234,6 +116,7 @@ print_i387_ext (unsigned char *raw, struct ui_file *file)
 }
 
 /* Print the status word STATUS.  */
+
 static void
 print_i387_status_word (unsigned int status, struct ui_file *file)
 {
@@ -263,6 +146,7 @@ print_i387_status_word (unsigned int status, struct ui_file *file)
 }
 
 /* Print the control word CONTROL.  */
+
 static void
 print_i387_control_word (unsigned int control, struct ui_file *file)
 {
@@ -321,26 +205,35 @@ void
 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
                       struct frame_info *frame, const char *args)
 {
-  unsigned int fctrl;
-  unsigned int fstat;
-  unsigned int ftag;
-  unsigned int fiseg;
-  unsigned int fioff;
-  unsigned int foseg;
-  unsigned int fooff;
-  unsigned int fop;
+  char buf[4];
+  ULONGEST fctrl;
+  ULONGEST fstat;
+  ULONGEST ftag;
+  ULONGEST fiseg;
+  ULONGEST fioff;
+  ULONGEST foseg;
+  ULONGEST fooff;
+  ULONGEST 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);
-  
+  frame_register_read (frame, FCTRL_REGNUM, buf);
+  fctrl = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FSTAT_REGNUM, buf);
+  fstat = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FTAG_REGNUM, buf);
+  ftag = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FISEG_REGNUM, buf);
+  fiseg = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FIOFF_REGNUM, buf);
+  fioff = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FOSEG_REGNUM, buf);
+  foseg = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FOOFF_REGNUM, buf);
+  fooff = extract_unsigned_integer (buf, 4);
+  frame_register_read (frame, FOP_REGNUM, buf);
+  fop = extract_unsigned_integer (buf, 4);
+
   top = ((fstat >> 11) & 7);
 
   for (fpreg = 7; fpreg >= 0; fpreg--)
@@ -367,7 +260,7 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
          break;
        }
 
-      read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
+      frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
 
       fputs_filtered ("0x", file);
       for (i = 9; i >= 0; i--)
@@ -379,7 +272,7 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
       fputs_filtered ("\n", file);
     }
 
-  puts_filtered ("\n");
+  fputs_filtered ("\n", file);
 
   print_i387_status_word (fstat, file);
   print_i387_control_word (fctrl, file);
@@ -394,12 +287,60 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
   fprintf_filtered (file, "Opcode:              %s\n",
                    local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
 }
+\f
+
+/* Read a value of type TYPE from register REGNUM in frame FRAME, and
+   return its contents in TO.  */
+
+void
+i387_register_to_value (struct frame_info *frame, int regnum,
+                       struct type *type, void *to)
+{
+  char from[I386_MAX_REGISTER_SIZE];
 
-/* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
-   define their own routines to manage the floating-point registers in
-   GDB's register array.  Most (if not all) of these targets use the
-   format used by the "fsave" instruction in their communication with
-   the OS.  They should all be converted to use the routines below.  */
+  gdb_assert (i386_fp_regnum_p (regnum));
+
+  /* We only support floating-point values.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      warning ("Cannot convert floating-point register value "
+              "to non-floating-point type.");
+      return;
+    }
+
+  /* Convert to TYPE.  This should be a no-op if TYPE is equivalent to
+     the extended floating-point format used by the FPU.  */
+  frame_read_register (frame, regnum, from);
+  convert_typed_floating (from, builtin_type_i387_ext, to, type);
+}
+
+/* Write the contents FROM of a value of type TYPE into register
+   REGNUM in frame FRAME.  */
+
+void
+i387_value_to_register (struct frame_info *frame, int regnum,
+                       struct type *type, const void *from)
+{
+  char to[I386_MAX_REGISTER_SIZE];
+
+  gdb_assert (i386_fp_regnum_p (regnum));
+
+  /* We only support floating-point values.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      warning ("Cannot convert non-floating-point type "
+              "to floating-point register value.");
+      return;
+    }
+
+  /* Convert from TYPE.  This should be a no-op if TYPE is equivalent
+     to the extended floating-point format used by the FPU.  */
+  convert_typed_floating (from, type, to, builtin_type_i387_ext);
+  put_frame_register (frame, regnum, to);
+}
+\f
+
+/* Handle FSAVE and FXSAVE formats.  */
 
 /* At fsave_offset[REGNUM] you'll find the offset to the location in
    the data structure used by the "fsave" instruction where GDB
@@ -435,6 +376,12 @@ static int fsave_offset[] =
 void
 i387_supply_register (int regnum, char *fsave)
 {
+  if (fsave == NULL)
+    {
+      supply_register (regnum, NULL);
+      return;
+    }
+
   /* Most of the FPU control registers occupy only 16 bits in
      the fsave area.  Give those a special treatment.  */
   if (regnum >= FPC_REGNUM
@@ -524,19 +471,34 @@ static int fxsave_offset[] =
   20,                          /* FOSEG_REGNUM (16 bits).  */
   16,                          /* FOOFF_REGNUM.  */
   6,                           /* FOP_REGNUM (bottom 11 bits).  */
-  160,                         /* XMM0_REGNUM through ...  */
-  176,
-  192,
-  208,
-  224,
-  240,
-  256,
-  272,                         /* ... XMM7_REGNUM (128 bits each).  */
-  24,                          /* MXCSR_REGNUM.  */
+  160 + 0 * 16,                        /* XMM0_REGNUM through ...  */
+  160 + 1 * 16,
+  160 + 2 * 16,
+  160 + 3 * 16,
+  160 + 4 * 16,
+  160 + 5 * 16,
+  160 + 6 * 16,
+  160 + 7 * 16,
+  160 + 8 * 16,
+  160 + 9 * 16,
+  160 + 10 * 16,
+  160 + 11 * 16,
+  160 + 12 * 16,
+  160 + 13 * 16,
+  160 + 14 * 16,
+  160 + 15 * 16,               /* ... XMM15_REGNUM (128 bits each).  */
+  24                           /* MXCSR_REGNUM.  */
 };
 
+/* FIXME: kettenis/20030430: We made an unfortunate choice in putting
+   %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
+   it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
+   involved.  Hack around it by explicitly overriding the offset for
+   %mxcsr here.  */
+
 #define FXSAVE_ADDR(fxsave, regnum) \
-  (fxsave + fxsave_offset[regnum - FP0_REGNUM])
+  ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
+   (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
 
 static int i387_tag (unsigned char *raw);
 \f
@@ -555,6 +517,12 @@ i387_supply_fxsave (char *fxsave)
 
   for (i = FP0_REGNUM; i <= last_regnum; i++)
     {
+      if (fxsave == NULL)
+       {
+         supply_register (i, NULL);
+         continue;
+       }
+
       /* Most of the FPU control registers occupy only 16 bits in
         the fxsave area.  Give those a special treatment.  */
       if (i >= FPC_REGNUM && i < XMM0_REGNUM
@@ -621,7 +589,7 @@ i387_fill_fxsave (char *fxsave, int regnum)
        /* Most of the FPU control registers occupy only 16 bits in
            the fxsave area.  Give those a special treatment.  */
        if (i >= FPC_REGNUM && i < XMM0_REGNUM
-           && i != FIOFF_REGNUM && i != FDOFF_REGNUM)
+           && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
          {
            unsigned char buf[4];
 
This page took 0.027022 seconds and 4 git commands to generate.