2000-05-26 Michael Snyder <msnyder@seadog.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / i386v4-nat.c
index 10802cb730b8d88183b33711f799916b5351ab75..3ed273e7b1320bd1939b17c842f889e5ef146983 100644 (file)
@@ -31,6 +31,9 @@
 
 #include <sys/procfs.h>
 
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
 /*  The /proc interface divides the target machine's register set up into
    two different sets, the general register set (gregset) and the floating
    point register set (fpregset).  For each set, there is an ioctl to get
@@ -142,17 +145,65 @@ fill_gregset (gregsetp, regno)
 
 #endif /* HAVE_GREGSET_T */
 
-#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+#if defined (HAVE_FPREGSET_T)
 
 /*  Given a pointer to a floating point register set in /proc format
    (fpregset_t *), unpack the register contents and supply them as gdb's
    idea of the current floating point register values. */
 
+/* FIXME: Assumes that fpregsetp contains an i387 FSAVE area. */
+static const int freg_offset_map[] =
+{
+#if !defined(FPREGSET_FSAVE_OFFSET)
+#define FPREGSET_FSAVE_OFFSET  0
+#endif
+  FPREGSET_FSAVE_OFFSET + 28 + 0 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 1 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 2 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 3 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 4 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 5 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 6 * 10,
+  FPREGSET_FSAVE_OFFSET + 28 + 7 * 10,
+  FPREGSET_FSAVE_OFFSET + 0,
+  FPREGSET_FSAVE_OFFSET + 4,
+  FPREGSET_FSAVE_OFFSET + 8,
+  FPREGSET_FSAVE_OFFSET + 16,
+  FPREGSET_FSAVE_OFFSET + 12,
+  FPREGSET_FSAVE_OFFSET + 24,
+  FPREGSET_FSAVE_OFFSET + 20,
+  FPREGSET_FSAVE_OFFSET + 16
+};
+
 void
 supply_fpregset (fpregsetp)
      fpregset_t *fpregsetp;
 {
-  /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+  int regi;
+  
+  if (NUM_FREGS == 0)
+    return;
+  for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
+    {
+      char tbuf[4];
+      ULONGEST tval;
+      char *from = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
+
+      if (regi == FCS_REGNUM)
+       {
+         tval = extract_unsigned_integer (from, 4) & 0xffff;
+         store_unsigned_integer (tbuf, 4, tval);
+         supply_register (regi, tbuf);
+       }
+      else if (regi == FOP_REGNUM)
+       {
+         tval = (extract_unsigned_integer (from, 4) >> 16) & ((1 << 11) - 1);
+         store_unsigned_integer (tbuf, 4, tval);
+         supply_register (regi, tbuf);
+       }
+      else
+       supply_register (regi, from);
+    }
 }
 
 /*  Given a pointer to a floating point register set in /proc format
@@ -165,9 +216,41 @@ fill_fpregset (fpregsetp, regno)
      fpregset_t *fpregsetp;
      int regno;
 {
-  /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+  int regi;
+
+  if (NUM_FREGS == 0)
+    return;
+  for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
+    {
+      if ((regno == -1) || (regno == regi))
+       {
+         char *to = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
+         char *from = (char *) &registers[REGISTER_BYTE (regi)];
+         ULONGEST valto;
+         ULONGEST valfrom;
+
+         if (regi == FCS_REGNUM)
+           {
+             valto = extract_unsigned_integer (to, 4);
+             valfrom = extract_unsigned_integer (from, 4);
+             valto = (valto & ~0xffff) | (valfrom & 0xffff);
+             store_unsigned_integer (to, 4, valto);
+           }
+         else if (regi == FOP_REGNUM)
+           {
+             valto = extract_unsigned_integer (to, 4);
+             valfrom = extract_unsigned_integer (from, 4);
+             valto = (valto & 0xffff) | ((valfrom & ((1 << 11) - 1)) << 16);
+             store_unsigned_integer (to, 4, valto);
+           }
+         else
+           {
+             memcpy (to, from, REGISTER_RAW_SIZE (regi));
+           }
+       }
+    }
 }
 
-#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
+#endif /* defined (HAVE_FPREGSET_T) */
 
 #endif /* HAVE_SYS_PROCFS_H */
This page took 0.035057 seconds and 4 git commands to generate.