* i386-tdep.h: Put opaque declarations in alphabetical
authorMark Kettenis <kettenis@gnu.org>
Sat, 27 Sep 2003 21:57:56 +0000 (21:57 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sat, 27 Sep 2003 21:57:56 +0000 (21:57 +0000)
order.  Remove spurious whitespace.
(struct gdbarch_tdep): add st0_regnum and mm0_regnum members.
(i386_sse_regnum_p, i386_mxcsr_regnum_p): Remove prototypes.
* i386-tdep.c (MM0_REGNUM): Remove define.
(i386_mmx_regnum_p): Add gdbarch argument.
(i386_sse_regnum_p, i386_mxcsr_regnum_p): Add gdbarch argument.
Rewrite using new macro definitions for FPU/SSE registers.
(i386_fp_regnum_p, i386_fpc_regnum_p): Rewrite using new macro
definitions from i387-tdep.h.
(i386_register_name): Update.
(i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum): Update to use
new macro definitions for FPU/SSE registers.
(i386_extract_return_value): Determine whether floating-point
registers are present by examining REGCACHE's architecture.
(i386_store_return_value): Likewise.  Use I386_MAX_REGISTER_SIZE
instead of FPU_REG_RAW_SIZE.  Use new macro definitions for
FPU/SSE registers.
(i386_register_type): Update.
(i386_mmx_regnum_to_fp_regnum): Rewrite using new macro
definitions for FPU registers.  Use REGCACHE's architecture to
determine the appropriate register numbers.
(i386_pseudo_register_read, i386_pseudo_register_write,
i386_register_reggroup_p): Update.
(i386_gdbarch_init): Initialize TDEP->st0_regnum and
TDEP->mm0_regnum.
* i387-tdep.h (I387_FCTRL_REGNUM, I387_FSTAT_REGNUM,
I387_FTAG_REGNUM, I387_FISEG_REGNUM, I387_FIOFF_REGNUM,
I387_FOSEG_REGNUM, I387_FOOFF_REGNUM, I387_FOP_REGNUM,
I387_XMM0_REGNUM, I387_MXCSR_REGNUM): New defines.
(i387_supply_fsave, i387_fill_fsave, i387_supply_fxsave,
i387_fill_fxsave): Change type of fsave/fxsave argument from `char
*' to `void *'.
* i387-tdep.c (i387_print_float_info, fsave_offset, FSAVE_ADDR,
i387_supply_fsave, i387_fill_fsave, fxsave_offset, FXSAVE_ADDR,
i387_supply_fxsave, i387_fill_fxsave): Update to use new macro
definitions for FPU/SSE registers.
(FXSAVE_MXCSR_ADDR): New define.
* x86-64-tdep.c (x86_64_init_abi): Override TDEP->st0_regnum and
TDEP->mm0_regnum.
(I387_FISEG_REGNUM, I387_FOSEG_REGNUM): Remove defines.
(I387_ST0_REGNUM): Define.

gdb/ChangeLog
gdb/i386-tdep.c
gdb/i386-tdep.h
gdb/i387-tdep.c
gdb/i387-tdep.h
gdb/x86-64-tdep.c

index 6bf0549..c0e544a 100644 (file)
@@ -1,5 +1,48 @@
 2003-09-27  Mark Kettenis  <kettenis@gnu.org>
 
+       * i386-tdep.h: Put opaque declarations in alphabetical
+       order.  Remove spurious whitespace.
+       (struct gdbarch_tdep): add st0_regnum and mm0_regnum members.
+       (i386_sse_regnum_p, i386_mxcsr_regnum_p): Remove prototypes.
+       * i386-tdep.c (MM0_REGNUM): Remove define.
+       (i386_mmx_regnum_p): Add gdbarch argument.
+       (i386_sse_regnum_p, i386_mxcsr_regnum_p): Add gdbarch argument.
+       Rewrite using new macro definitions for FPU/SSE registers.
+       (i386_fp_regnum_p, i386_fpc_regnum_p): Rewrite using new macro
+       definitions from i387-tdep.h.
+       (i386_register_name): Update.
+       (i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum): Update to use
+       new macro definitions for FPU/SSE registers.
+       (i386_extract_return_value): Determine whether floating-point
+       registers are present by examining REGCACHE's architecture.
+       (i386_store_return_value): Likewise.  Use I386_MAX_REGISTER_SIZE
+       instead of FPU_REG_RAW_SIZE.  Use new macro definitions for
+       FPU/SSE registers.
+       (i386_register_type): Update.
+       (i386_mmx_regnum_to_fp_regnum): Rewrite using new macro
+       definitions for FPU registers.  Use REGCACHE's architecture to
+       determine the appropriate register numbers.
+       (i386_pseudo_register_read, i386_pseudo_register_write,
+       i386_register_reggroup_p): Update.
+       (i386_gdbarch_init): Initialize TDEP->st0_regnum and
+       TDEP->mm0_regnum.
+       * i387-tdep.h (I387_FCTRL_REGNUM, I387_FSTAT_REGNUM,
+       I387_FTAG_REGNUM, I387_FISEG_REGNUM, I387_FIOFF_REGNUM,
+       I387_FOSEG_REGNUM, I387_FOOFF_REGNUM, I387_FOP_REGNUM,
+       I387_XMM0_REGNUM, I387_MXCSR_REGNUM): New defines.
+       (i387_supply_fsave, i387_fill_fsave, i387_supply_fxsave,
+       i387_fill_fxsave): Change type of fsave/fxsave argument from `char
+       *' to `void *'.
+       * i387-tdep.c (i387_print_float_info, fsave_offset, FSAVE_ADDR,
+       i387_supply_fsave, i387_fill_fsave, fxsave_offset, FXSAVE_ADDR,
+       i387_supply_fxsave, i387_fill_fxsave): Update to use new macro
+       definitions for FPU/SSE registers.
+       (FXSAVE_MXCSR_ADDR): New define.
+       * x86-64-tdep.c (x86_64_init_abi): Override TDEP->st0_regnum and
+       TDEP->mm0_regnum.
+       (I387_FISEG_REGNUM, I387_FOSEG_REGNUM): Remove defines.
+       (I387_ST0_REGNUM): Define.
+
        * regcache.h (get_regcache_arch): New prototype.
        * regcache.c (get_regcache_arch): New function.
 
index f4cbc34..d3e3357 100644 (file)
@@ -79,45 +79,75 @@ static char *i386_mmx_names[] =
 
 static const int i386_num_mmx_regs = ARRAY_SIZE (i386_mmx_names);
 
-#define MM0_REGNUM NUM_REGS
-
 static int
-i386_mmx_regnum_p (int regnum)
+i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (regnum >= MM0_REGNUM
-         && regnum < MM0_REGNUM + i386_num_mmx_regs);
+  int mm0_regnum = gdbarch_tdep (gdbarch)->mm0_regnum;
+
+  if (mm0_regnum < 0)
+    return 0;
+
+  return (regnum >= mm0_regnum && regnum < mm0_regnum + i386_num_mmx_regs);
 }
 
-/* FP register?  */
+/* SSE register?  */
 
-int
-i386_fp_regnum_p (int regnum)
+static int
+i386_sse_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (regnum < NUM_REGS
-         && (FP0_REGNUM && FP0_REGNUM <= regnum && regnum < FPC_REGNUM));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  if (I387_NUM_XMM_REGS == 0)
+    return 0;
+
+  return (I387_XMM0_REGNUM <= regnum && regnum < I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
-int
-i386_fpc_regnum_p (int regnum)
+static int
+i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  return (regnum < NUM_REGS
-         && (FPC_REGNUM <= regnum && regnum < XMM0_REGNUM));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  if (I387_NUM_XMM_REGS == 0)
+    return 0;
+
+  return (regnum == I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
-/* SSE register?  */
+#define I387_ST0_REGNUM (gdbarch_tdep (current_gdbarch)->st0_regnum)
+#define I387_MM0_REGNUM (gdbarch_tdep (current_gdbarch)->mm0_regnum)
+#define I387_NUM_XMM_REGS (gdbarch_tdep (current_gdbarch)->num_xmm_regs)
+
+/* FP register?  */
 
 int
-i386_sse_regnum_p (int regnum)
+i386_fp_regnum_p (int regnum)
 {
-  return (regnum < NUM_REGS
-         && (XMM0_REGNUM <= regnum && regnum < MXCSR_REGNUM));
+  if (I387_ST0_REGNUM < 0)
+    return 0;
+
+  return (I387_ST0_REGNUM <= regnum && regnum < I387_FCTRL_REGNUM);
 }
 
 int
-i386_mxcsr_regnum_p (int regnum)
+i386_fpc_regnum_p (int regnum)
 {
-  return (regnum < NUM_REGS
-         && regnum == MXCSR_REGNUM);
+  if (I387_ST0_REGNUM < 0)
+    return 0;
+
+  return (I387_FCTRL_REGNUM <= regnum && regnum < I387_XMM0_REGNUM);
 }
 
 /* Return the name of register REG.  */
@@ -125,8 +155,8 @@ i386_mxcsr_regnum_p (int regnum)
 const char *
 i386_register_name (int reg)
 {
-  if (i386_mmx_regnum_p (reg))
-    return i386_mmx_names[reg - MM0_REGNUM];
+  if (i386_mmx_regnum_p (current_gdbarch, reg))
+    return i386_mmx_names[reg - I387_MM0_REGNUM];
 
   if (reg >= 0 && reg < i386_num_register_names)
     return i386_register_names[reg];
@@ -149,17 +179,17 @@ i386_stab_reg_to_regnum (int reg)
   else if (reg >= 12 && reg <= 19)
     {
       /* Floating-point registers.  */
-      return reg - 12 + FP0_REGNUM;
+      return reg - 12 + I387_ST0_REGNUM;
     }
   else if (reg >= 21 && reg <= 28)
     {
       /* SSE registers.  */
-      return reg - 21 + XMM0_REGNUM;
+      return reg - 21 + I387_XMM0_REGNUM;
     }
   else if (reg >= 29 && reg <= 36)
     {
       /* MMX registers.  */
-      return reg - 29 + MM0_REGNUM;
+      return reg - 29 + I387_MM0_REGNUM;
     }
 
   /* This will hopefully provoke a warning.  */
@@ -182,7 +212,7 @@ i386_dwarf_reg_to_regnum (int reg)
   else if (reg >= 11 && reg <= 18)
     {
       /* Floating-point registers.  */
-      return reg - 11 + FP0_REGNUM;
+      return reg - 11 + I387_ST0_REGNUM;
     }
   else if (reg >= 21)
     {
@@ -193,6 +223,10 @@ i386_dwarf_reg_to_regnum (int reg)
   /* This will hopefully provoke a warning.  */
   return NUM_REGS + NUM_PSEUDO_REGS;
 }
+
+#undef I387_ST0_REGNUM
+#undef I387_MM0_REGNUM
+#undef I387_NUM_XMM_REGS
 \f
 
 /* This is the variable that is set with "set disassembly-flavor", and
@@ -1121,6 +1155,7 @@ static void
 i386_extract_return_value (struct type *type, struct regcache *regcache,
                           void *dst)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
   bfd_byte *valbuf = dst;
   int len = TYPE_LENGTH (type);
   char buf[I386_MAX_REGISTER_SIZE];
@@ -1134,7 +1169,7 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      if (FP0_REGNUM < 0)
+      if (tdep->st0_regnum < 0)
        {
          warning ("Cannot find floating-point return value.");
          memset (valbuf, 0, len);
@@ -1178,8 +1213,13 @@ static void
 i386_store_return_value (struct type *type, struct regcache *regcache,
                         const void *valbuf)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
   int len = TYPE_LENGTH (type);
 
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for the architecture.  */
+#define I387_ST0_REGNUM I386_ST0_REGNUM
+
   if (TYPE_CODE (type) == TYPE_CODE_STRUCT
       && TYPE_NFIELDS (type) == 1)
     {
@@ -1190,9 +1230,9 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
       ULONGEST fstat;
-      char buf[FPU_REG_RAW_SIZE];
+      char buf[I386_MAX_REGISTER_SIZE];
 
-      if (FP0_REGNUM < 0)
+      if (tdep->st0_regnum < 0)
        {
          warning ("Cannot set floating-point return value.");
          return;
@@ -1213,14 +1253,14 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
          actual value doesn't really matter, but 7 is what a normal
          function return would end up with if the program started out
          with a freshly initialized FPU.  */
-      regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+      regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
       fstat |= (7 << 11);
-      regcache_raw_write_unsigned (regcache, FSTAT_REGNUM, fstat);
+      regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM, fstat);
 
       /* Mark %st(1) through %st(7) as empty.  Since we set the top of
          the floating-point register stack to 7, the appropriate value
          for the tag word is 0x3fff.  */
-      regcache_raw_write_unsigned (regcache, FTAG_REGNUM, 0x3fff);
+      regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
     }
   else
     {
@@ -1239,6 +1279,8 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
        internal_error (__FILE__, __LINE__,
                        "Cannot store return value of %d bytes long.", len);
     }
+
+#undef I387_ST0_REGNUM
 }
 
 /* Extract from REGCACHE, which contains the (raw) register state, the
@@ -1300,10 +1342,10 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
   if (i386_fp_regnum_p (regnum))
     return builtin_type_i387_ext;
 
-  if (i386_sse_regnum_p (regnum))
+  if (i386_sse_regnum_p (gdbarch, regnum))
     return builtin_type_vec128i;
 
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     return builtin_type_vec64i;
 
   return builtin_type_int;
@@ -1315,24 +1357,30 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
 static int
 i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
 {
-  int mmxi;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  int mmxreg, fpreg;
   ULONGEST fstat;
   int tos;
-  int fpi;
 
-  mmxi = regnum - MM0_REGNUM;
-  regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for REGCACHE's architecture.  */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+  mmxreg = regnum - tdep->mm0_regnum;
+  regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
   tos = (fstat >> 11) & 0x7;
-  fpi = (mmxi + tos) % 8;
+  fpreg = (mmxreg + tos) % 8;
+
+  return (I387_ST0_REGNUM + fpreg);
 
-  return (FP0_REGNUM + fpi);
+#undef I387_ST0_REGNUM
 }
 
 static void
 i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, void *buf)
 {
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     {
       char mmx_buf[MAX_REGISTER_SIZE];
       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
@@ -1349,7 +1397,7 @@ static void
 i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int regnum, const void *buf)
 {
-  if (i386_mmx_regnum_p (regnum))
+  if (i386_mmx_regnum_p (gdbarch, regnum))
     {
       char mmx_buf[MAX_REGISTER_SIZE];
       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
@@ -1708,11 +1756,11 @@ int
 i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
                          struct reggroup *group)
 {
-  int sse_regnum_p = (i386_sse_regnum_p (regnum)
-                     || i386_mxcsr_regnum_p (regnum));
+  int sse_regnum_p = (i386_sse_regnum_p (gdbarch, regnum)
+                     || i386_mxcsr_regnum_p (gdbarch, regnum));
   int fp_regnum_p = (i386_fp_regnum_p (regnum)
                     || i386_fpc_regnum_p (regnum));
-  int mmx_regnum_p = (i386_mmx_regnum_p (regnum));
+  int mmx_regnum_p = (i386_mmx_regnum_p (gdbarch, regnum));
 
   if (group == i386_mmx_reggroup)
     return mmx_regnum_p;
@@ -1755,22 +1803,28 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep = XMALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  /* The i386 default settings now include the SSE registers.
-     I386_NUM_XREGS includes mxcsr, and we don't want to count
-     this as one of the xmm regs -- which is why we subtract one.
-
-     Note: kevinb/2003-07-14: Whatever Mark's concerns are about the
-     FPU registers in the FIXME below apply to the SSE registers as well.
-     The only problem that I see is that these registers will show up
-     in "info all-registers" even on CPUs where they don't exist.  IMO,
-     however, if it's a choice between printing them always (even when
-     they don't exist) or never showing them to the user (even when they
-     do exist), I prefer the former over the latter.  Ideally, of course,
-     we'd somehow autodetect that we have them (or not) and display them
-     when we have them and suppress them when we don't.
-
-     FIXME: kettenis/20020614: They do include the FPU registers for
-     now, which probably is not quite right.  */
+  /* The default settings include the FPU registers, the MMX registers
+     and the SSE registers.  This can be overidden for a specific ABI
+     by adjusting the members `st0_regnum', `mm0_regnum' and
+     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
+     will show up in the output of "info all-registers".  Ideally we
+     should try to autodetect whether they are available, such that we
+     can prevent "info all-registers" from displaying registers that
+     aren't available.
+
+     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
+     [the SSE registers] always (even when they don't exist) or never
+     showing them to the user (even when they do exist), I prefer the
+     former over the latter.  */
+
+  tdep->st0_regnum = I386_ST0_REGNUM;
+
+  /* The MMX registers are implemented as pseudo-registers.  Put off
+     caclulating the register number for %mm0 until we know the number
+     of raw registers.  */
+  tdep->mm0_regnum = 0;
+
+  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
   tdep->num_xmm_regs = I386_NUM_XREGS - 1;
 
   tdep->jb_pc_offset = -1;
@@ -1874,6 +1928,11 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_unwind_append_sniffer (gdbarch, i386_sigtramp_frame_sniffer);
   frame_unwind_append_sniffer (gdbarch, i386_frame_sniffer);
 
+  /* Unless support for MMX has been disabled, make %mm0 the first
+     pseudo-register.  */
+  if (tdep->mm0_regnum == 0)
+    tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
+
   return gdbarch;
 }
 
index 7412b8e..6c4cf73 100644 (file)
@@ -1,4 +1,5 @@
-/* Target-dependent code for GDB, the GNU debugger.
+/* Target-dependent code for the i386.
+
    Copyright 2001, 2002, 2003
    Free Software Foundation, Inc.
 
@@ -22,9 +23,9 @@
 #ifndef I386_TDEP_H
 #define I386_TDEP_H
 
-struct reggroup;
-struct gdbarch;
 struct frame_info;
+struct gdbarch;
+struct reggroup;
 
 /* GDB's i386 target supports both the 32-bit Intel Architecture
    (IA-32) and the 64-bit AMD x86-64 architecture.  Internally it uses
@@ -55,6 +56,15 @@ enum struct_return
 /* i386 architecture specific information.  */
 struct gdbarch_tdep
 {
+  /* Register number for %st(0).  The register numbers for the other
+     registers follow from this one.  Set this to -1 to indicate the
+     absence of an FPU.  */
+  int st0_regnum;
+
+  /* Register number for %mm0.  Set this to -1 to indicate the absence
+     of MMX support.  */
+  int mm0_regnum;
+
   /* Number of SSE registers.  */
   int num_xmm_regs;
 
@@ -131,11 +141,6 @@ extern int i386_fpc_regnum_p (int regnum);
 #define MXCSR_REGNUM \
   (XMM0_REGNUM + gdbarch_tdep (current_gdbarch)->num_xmm_regs)
 
-/* Return non-zero if REGNUM matches the SSE register and the SSE
-   register set is active.  */
-extern int i386_sse_regnum_p (int regnum);
-extern int i386_mxcsr_regnum_p (int regnum);
-
 /* FIXME: kettenis/2001-11-24: Obsolete macro's.  */
 #define FCS_REGNUM FISEG_REGNUM
 #define FCOFF_REGNUM FIOFF_REGNUM
@@ -194,4 +199,3 @@ extern int i386obsd_sc_reg_offset[];
 extern int i386bsd_sc_reg_offset[];
 
 #endif /* i386-tdep.h */
-
index 6feb392..63943e7 100644 (file)
@@ -205,6 +205,7 @@ void
 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
                       struct frame_info *frame, const char *args)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
   char buf[4];
   ULONGEST fctrl;
   ULONGEST fstat;
@@ -217,20 +218,26 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
   int fpreg;
   int top;
 
-  fctrl = get_frame_register_unsigned (frame, FCTRL_REGNUM);
-  fstat = get_frame_register_unsigned (frame, FSTAT_REGNUM);
-  ftag = get_frame_register_unsigned (frame, FTAG_REGNUM);
-  fiseg = get_frame_register_unsigned (frame, FISEG_REGNUM);
-  fioff = get_frame_register_unsigned (frame, FIOFF_REGNUM);
-  foseg = get_frame_register_unsigned (frame, FOSEG_REGNUM);
-  fooff = get_frame_register_unsigned (frame, FOOFF_REGNUM);
-  fop = get_frame_register_unsigned (frame, FOP_REGNUM);
+  gdb_assert (gdbarch == get_frame_arch (frame));
+
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for FRAME's architecture.  */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+  fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM);
+  fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM);
+  ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM);
+  fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM);
+  fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM);
+  foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM);
+  fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM);
+  fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM);
 
   top = ((fstat >> 11) & 7);
 
   for (fpreg = 7; fpreg >= 0; fpreg--)
     {
-      unsigned char raw[FPU_REG_RAW_SIZE];
+      unsigned char raw[I386_MAX_REGISTER_SIZE];
       int tag = (ftag >> (fpreg * 2)) & 3;
       int i;
 
@@ -252,7 +259,7 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
          break;
        }
 
-      get_frame_register (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
+      get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM, raw);
 
       fputs_filtered ("0x", file);
       for (i = 9; i >= 0; i--)
@@ -278,6 +285,8 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
   fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
   fprintf_filtered (file, "Opcode:              %s\n",
                    local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
+
+#undef I387_ST0_REGNUM
 }
 \f
 
@@ -331,34 +340,42 @@ i387_value_to_register (struct frame_info *frame, int regnum,
   put_frame_register (frame, regnum, to);
 }
 \f
+\f
 
 /* Handle FSAVE and FXSAVE formats.  */
 
+/* FIXME: kettenis/20030927: The functions below should accept a
+   `regcache' argument, but I don't want to change the function
+   signature just yet.  There's some band-aid in the functions below
+   in the form of the `regcache' local variables.  This will ease the
+   transition later on.  */
+
 /* At fsave_offset[REGNUM] you'll find the offset to the location in
    the data structure used by the "fsave" instruction where GDB
    register REGNUM is stored.  */
 
 static int fsave_offset[] =
 {
-  28 + 0 * FPU_REG_RAW_SIZE,   /* FP0_REGNUM through ...  */
-  28 + 1 * FPU_REG_RAW_SIZE,  
-  28 + 2 * FPU_REG_RAW_SIZE,  
-  28 + 3 * FPU_REG_RAW_SIZE,  
-  28 + 4 * FPU_REG_RAW_SIZE,  
-  28 + 5 * FPU_REG_RAW_SIZE,  
-  28 + 6 * FPU_REG_RAW_SIZE,  
-  28 + 7 * FPU_REG_RAW_SIZE,   /* ... FP7_REGNUM.  */
-  0,                           /* FCTRL_REGNUM (16 bits).  */
-  4,                           /* FSTAT_REGNUM (16 bits).  */
-  8,                           /* FTAG_REGNUM (16 bits).  */
-  16,                          /* FISEG_REGNUM (16 bits).  */
-  12,                          /* FIOFF_REGNUM.  */
-  24,                          /* FOSEG_REGNUM.  */
-  20,                          /* FOOFF_REGNUM.  */
-  18                           /* FOP_REGNUM (bottom 11 bits).  */
+  28 + 0 * 10,                 /* %st(0) ...  */
+  28 + 1 * 10,
+  28 + 2 * 10,
+  28 + 3 * 10,
+  28 + 4 * 10,
+  28 + 5 * 10,
+  28 + 6 * 10,
+  28 + 7 * 10,                 /* ... %st(7).  */
+  0,                           /* `fctrl' (16 bits).  */
+  4,                           /* `fstat' (16 bits).  */
+  8,                           /* `ftag' (16 bits).  */
+  16,                          /* `fiseg' (16 bits).  */
+  12,                          /* `fioff'.  */
+  24,                          /* `foseg' (16 bits).  */
+  20,                          /* `fooff'.  */
+  18                           /* `fop' (bottom 11 bits).  */
 };
 
-#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
+#define FSAVE_ADDR(fsave, regnum) \
+  (fsave + fsave_offset[regnum - I387_ST0_REGNUM])
 \f
 
 /* Fill register REGNUM in GDB's register cache with the appropriate
@@ -366,35 +383,45 @@ static int fsave_offset[] =
    bits in *FSAVE.  */
 
 void
-i387_supply_fsave (const char *fsave, int regnum)
+i387_supply_fsave (const void *fsave, int regnum)
 {
+  struct regcache *regcache = current_regcache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const char *regs = fsave;
   int i;
 
-  for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
+  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for REGCACHE's architecture.  */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+  for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
     if (regnum == -1 || regnum == i)
       {
        if (fsave == NULL)
          {
-           supply_register (i, NULL);
-           return;
+           regcache_raw_supply (regcache, i, NULL);
+           continue;
          }
 
        /* Most of the FPU control registers occupy only 16 bits in the
           fsave area.  Give those a special treatment.  */
-       if (i >= FPC_REGNUM
-           && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+       if (i >= I387_FCTRL_REGNUM
+           && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
          {
            unsigned char val[4];
 
-           memcpy (val, FSAVE_ADDR (fsave, i), 2);
+           memcpy (val, FSAVE_ADDR (regs, i), 2);
            val[2] = val[3] = 0;
-           if (i == FOP_REGNUM)
+           if (i == I387_FOP_REGNUM)
              val[1] &= ((1 << 3) - 1);
-           supply_register (i, val);
+           regcache_raw_supply (regcache, i, val);
          }
        else
-         supply_register (i, FSAVE_ADDR (fsave, i));
+         regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
       }
+#undef I387_ST0_REGNUM
 }
 
 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
@@ -403,34 +430,44 @@ i387_supply_fsave (const char *fsave, int regnum)
    bits in *FSAVE.  */
 
 void
-i387_fill_fsave (char *fsave, int regnum)
+i387_fill_fsave (void *fsave, int regnum)
 {
+  struct regcache *regcache = current_regcache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  char *regs = fsave;
   int i;
 
-  for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
+  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+
+  /* Define I387_ST0_REGNUM such that we use the proper definitions
+     for REGCACHE's architecture.  */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+  for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
     if (regnum == -1 || regnum == i)
       {
        /* Most of the FPU control registers occupy only 16 bits in
            the fsave area.  Give those a special treatment.  */
-       if (i >= FPC_REGNUM
-           && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+       if (i >= I387_FCTRL_REGNUM
+           && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
          {
            unsigned char buf[4];
 
-           regcache_collect (i, buf);
+           regcache_raw_collect (regcache, i, buf);
 
-           if (i == FOP_REGNUM)
+           if (i == I387_FOP_REGNUM)
              {
                /* The opcode occupies only 11 bits.  Make sure we
                    don't touch the other bits.  */
                buf[1] &= ((1 << 3) - 1);
-               buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
+               buf[1] |= ((FSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
              }
-           memcpy (FSAVE_ADDR (fsave, i), buf, 2);
+           memcpy (FSAVE_ADDR (regs, i), buf, 2);
          }
        else
-         regcache_collect (i, FSAVE_ADDR (fsave, i));
+         regcache_raw_collect (regcache, i, FSAVE_ADDR (regs, i));
       }
+#undef I387_ST0_REGNUM
 }
 \f
 
@@ -440,23 +477,23 @@ i387_fill_fsave (char *fsave, int regnum)
 
 static int fxsave_offset[] =
 {
-  32,                          /* FP0_REGNUM through ...  */
+  32,                          /* %st(0) through ...  */
   48,
   64,
   80,
   96,
   112,
   128,
-  144,                         /* ... FP7_REGNUM (80 bits each).  */
-  0,                           /* FCTRL_REGNUM (16 bits).  */
-  2,                           /* FSTAT_REGNUM (16 bits).  */
-  4,                           /* FTAG_REGNUM (16 bits).  */
-  12,                          /* FISEG_REGNUM (16 bits).  */
-  8,                           /* FIOFF_REGNUM.  */
-  20,                          /* FOSEG_REGNUM (16 bits).  */
-  16,                          /* FOOFF_REGNUM.  */
-  6,                           /* FOP_REGNUM (bottom 11 bits).  */
-  160 + 0 * 16,                        /* XMM0_REGNUM through ...  */
+  144,                         /* ... %st(7) (80 bits each).  */
+  0,                           /* `fctrl' (16 bits).  */
+  2,                           /* `fstat' (16 bits).  */
+  4,                           /* `ftag' (16 bits).  */
+  12,                          /* `fiseg' (16 bits).  */
+  8,                           /* `fioff'.  */
+  20,                          /* `foseg' (16 bits).  */
+  16,                          /* `fooff'.  */
+  6,                           /* `fop' (bottom 11 bits).  */
+  160 + 0 * 16,                        /* %xmm0 through ...  */
   160 + 1 * 16,
   160 + 2 * 16,
   160 + 3 * 16,
@@ -471,19 +508,18 @@ static int fxsave_offset[] =
   160 + 12 * 16,
   160 + 13 * 16,
   160 + 14 * 16,
-  160 + 15 * 16,               /* ... XMM15_REGNUM (128 bits each).  */
-  24                           /* MXCSR_REGNUM.  */
+  160 + 15 * 16,               /* ... %xmm15 (128 bits each).  */
 };
 
-/* 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) \
-  ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
-   (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
+  (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM])
+
+/* 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 AMD64 a bit involved.  Therefore we
+   don't include the offset for %mxcsr here above.  */
+
+#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
 
 static int i387_tag (const unsigned char *raw);
 \f
@@ -493,34 +529,43 @@ static int i387_tag (const unsigned char *raw);
    masks off any of the reserved bits in *FXSAVE.  */
 
 void
-i387_supply_fxsave (const char *fxsave, int regnum)
+i387_supply_fxsave (const void *fxsave, int regnum)
 {
-  int i, last_regnum = MXCSR_REGNUM;
+  struct regcache *regcache = current_regcache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const char *regs = fxsave;
+  int i;
+
+  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+  gdb_assert (tdep->num_xmm_regs > 0);
 
-  if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
-    last_regnum = FOP_REGNUM;
+  /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+     proper definitions for REGCACHE's architecture.  */
 
-  for (i = FP0_REGNUM; i <= last_regnum; i++)
+#define I387_ST0_REGNUM        tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
     if (regnum == -1 || regnum == i)
       {
-       if (fxsave == NULL)
+       if (regs == NULL)
          {
-           supply_register (i, NULL);
+           regcache_raw_supply (regcache, 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
-           && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+       if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
+           && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
          {
            unsigned char val[4];
 
-           memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
+           memcpy (val, FXSAVE_ADDR (regs, i), 2);
            val[2] = val[3] = 0;
-           if (i == FOP_REGNUM)
+           if (i == I387_FOP_REGNUM)
              val[1] &= ((1 << 3) - 1);
-           else if (i== FTAG_REGNUM)
+           else if (i== I387_FTAG_REGNUM)
              {
                /* The fxsave area contains a simplified version of
                   the tag word.  We have to look at the actual 80-bit
@@ -530,7 +575,8 @@ i387_supply_fxsave (const char *fxsave, int regnum)
                int fpreg;
                int top;
 
-               top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
+               top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
+               top &= 0x7;
 
                for (fpreg = 7; fpreg >= 0; fpreg--)
                  {
@@ -538,8 +584,8 @@ i387_supply_fxsave (const char *fxsave, int regnum)
 
                    if (val[0] & (1 << fpreg))
                      {
-                       int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
-                       tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
+                       int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
+                       tag = i387_tag (FXSAVE_ADDR (regs, regnum));
                      }
                    else
                      tag = 3;          /* Empty */
@@ -549,11 +595,23 @@ i387_supply_fxsave (const char *fxsave, int regnum)
                val[0] = ftag & 0xff;
                val[1] = (ftag >> 8) & 0xff;
              }
-           supply_register (i, val);
+           regcache_raw_supply (regcache, i, val);
          }
        else
-         supply_register (i, FXSAVE_ADDR (fxsave, i));
+         regcache_raw_supply (regcache, i, FXSAVE_ADDR (regs, i));
       }
+
+  if (regnum == I387_MXCSR_REGNUM || regnum == -1)
+    {
+      if (regs == NULL)
+       regcache_raw_supply (regcache, I387_MXCSR_REGNUM, NULL);
+      else
+       regcache_raw_supply (regcache, I387_MXCSR_REGNUM,
+                            FXSAVE_MXCSR_ADDR (regs));
+    }
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
 /* Fill register REGNUM (if it is a floating-point or SSE register) in
@@ -562,33 +620,42 @@ i387_supply_fxsave (const char *fxsave, int regnum)
    reserved bits in *FXSAVE.  */
 
 void
-i387_fill_fxsave (char *fxsave, int regnum)
+i387_fill_fxsave (void *fxsave, int regnum)
 {
-  int i, last_regnum = MXCSR_REGNUM;
+  struct regcache *regcache = current_regcache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  char *regs = fxsave;
+  int i;
+
+  gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+  gdb_assert (tdep->num_xmm_regs > 0);
 
-  if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
-    last_regnum = FOP_REGNUM;
+  /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+     proper definitions for REGCACHE's architecture.  */
 
-  for (i = FP0_REGNUM; i <= last_regnum; i++)
+#define I387_ST0_REGNUM        tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+  for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
     if (regnum == -1 || regnum == i)
       {
        /* 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 != FOOFF_REGNUM)
+       if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
+           && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
          {
            unsigned char buf[4];
 
-           regcache_collect (i, buf);
+           regcache_raw_collect (regcache, i, buf);
 
-           if (i == FOP_REGNUM)
+           if (i == I387_FOP_REGNUM)
              {
                /* The opcode occupies only 11 bits.  Make sure we
                    don't touch the other bits.  */
                buf[1] &= ((1 << 3) - 1);
-               buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
+               buf[1] |= ((FXSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
              }
-           else if (i == FTAG_REGNUM)
+           else if (i == I387_FTAG_REGNUM)
              {
                /* Converting back is much easier.  */
 
@@ -607,11 +674,18 @@ i387_fill_fxsave (char *fxsave, int regnum)
                      buf[0] |= (1 << fpreg);
                  }
              }
-           memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
+           memcpy (FXSAVE_ADDR (regs, i), buf, 2);
          }
        else
-         regcache_collect (i, FXSAVE_ADDR (fxsave, i));
+         regcache_raw_collect (regcache, i, FXSAVE_ADDR (regs, i));
       }
+
+  if (regnum == I387_MXCSR_REGNUM || regnum == -1)
+    regcache_raw_collect (regcache, I387_MXCSR_REGNUM,
+                         FXSAVE_MXCSR_ADDR (regs));
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
 }
 
 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
index 654b4a5..41e695b 100644 (file)
@@ -27,6 +27,27 @@ struct ui_file;
 struct frame_info;
 struct type;
 
+/* Because the number of general-purpose registers is different for
+   AMD64, the floating-point registers and SSE registers get shifted.
+   The following definitions are intended to help writing code that
+   needs the register numbers of floating-point registers and SSE
+   registers.  In order to use these, one should provide a definition
+   for I387_ST0_REGNUM, and possibly I387_NUM_XMM_REGS, preferably by
+   using a local "#define" in the body of the function that uses this.
+   Please "#undef" them before the end of the function.  */
+
+#define I387_FCTRL_REGNUM      (I387_ST0_REGNUM + 8)
+#define I387_FSTAT_REGNUM      (I387_FCTRL_REGNUM + 1)
+#define I387_FTAG_REGNUM       (I387_FCTRL_REGNUM + 2)
+#define I387_FISEG_REGNUM      (I387_FCTRL_REGNUM + 3)
+#define I387_FIOFF_REGNUM      (I387_FCTRL_REGNUM + 4)
+#define I387_FOSEG_REGNUM      (I387_FCTRL_REGNUM + 5)
+#define I387_FOOFF_REGNUM      (I387_FCTRL_REGNUM + 6)
+#define I387_FOP_REGNUM                (I387_FCTRL_REGNUM + 7)
+#define I387_XMM0_REGNUM       (I387_ST0_REGNUM + 16)
+#define I387_MXCSR_REGNUM      (I387_XMM0_REGNUM + I387_NUM_XMM_REGS)
+\f
+
 /* Print out the i387 floating point state.  */
 
 extern void i387_print_float_info (struct gdbarch *gdbarch,
@@ -56,26 +77,26 @@ extern void i387_value_to_register (struct frame_info *frame, int regnum,
    value from *FSAVE.  This function masks off any of the reserved
    bits in *FSAVE.  */
 
-extern void i387_supply_fsave (const char *fsave, int regnum);
+extern void i387_supply_fsave (const void *fsave, int regnum);
 
 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
    with the value in GDB's register cache.  If REGNUM is -1, do this
    for all registers.  This function doesn't touch any of the reserved
    bits in *FSAVE.  */
 
-extern void i387_fill_fsave (char *fsave, int regnum);
+extern void i387_fill_fsave (void *fsave, int regnum);
 
 /* Fill register REGNUM in GDB's register cache with the appropriate
    floating-point or SSE register value from *FXSAVE.  This function
    masks off any of the reserved bits in *FXSAVE.  */
 
-extern void i387_supply_fxsave (const char *fxsave, int regnum);
+extern void i387_supply_fxsave (const void *fxsave, int regnum);
 
 /* Fill register REGNUM (if it is a floating-point or SSE register) in
    *FXSAVE with the value in GDB's register cache.  If REGNUM is -1, do
    this for all registers.  This function doesn't touch any of the
    reserved bits in *FXSAVE.  */
 
-extern void i387_fill_fxsave (char *fxsave, int regnum);
+extern void i387_fill_fxsave (void *fxsave, int regnum);
 
 #endif /* i387-tdep.h */
index 038ebd2..13fc5d2 100644 (file)
@@ -1209,7 +1209,8 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* The x86-64 has 16 SSE registers.  */
+  /* AMD64 has an FPU and 16 SSE registers.  */
+  tdep->st0_regnum = X86_64_ST0_REGNUM;
   tdep->num_xmm_regs = 16;
 
   /* This is what all the fuss is about.  */
@@ -1264,6 +1265,7 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   /* Avoid wiring in the MMX registers for now.  */
   set_gdbarch_num_pseudo_regs (gdbarch, 0);
+  tdep->mm0_regnum = -1;
 
   set_gdbarch_unwind_dummy_id (gdbarch, x86_64_unwind_dummy_id);
 
@@ -1278,8 +1280,7 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 }
 \f
 
-#define I387_FISEG_REGNUM FISEG_REGNUM
-#define I387_FOSEG_REGNUM FOSEG_REGNUM
+#define I387_ST0_REGNUM X86_64_ST0_REGNUM
 
 /* The 64-bit FXSAVE format differs from the 32-bit format in the
    sense that the instruction pointer and data pointer are simply