This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Cleanup FPU/SSE registers on i386 and AMD64


In preparation of the regset stuff, this cleans up the numbering of
FPU/SSE registers on i386 and AMD64.

Committed.

Mark


Index: ChangeLog
from  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.

 
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.168
diff -u -p -r1.168 i386-tdep.c
--- i386-tdep.c 27 Sep 2003 17:45:01 -0000 1.168
+++ i386-tdep.c 27 Sep 2003 21:56:30 -0000
@@ -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
 
 
 /* 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 *
 
   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 *ty
   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 *ty
          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 *ty
 	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 *gdba
   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 *gdba
 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 (FP0_REGNUM + fpi);
+  return (I387_ST0_REGNUM + fpreg);
+
+#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 i
   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.
+  /* 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;
 
-     FIXME: kettenis/20020614: They do include the FPU registers for
-     now, which probably is not quite right.  */
+  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
   tdep->num_xmm_regs = I386_NUM_XREGS - 1;
 
   tdep->jb_pc_offset = -1;
@@ -1873,6 +1927,11 @@ i386_gdbarch_init (struct gdbarch_info i
 
   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: i386-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.h,v
retrieving revision 1.25
diff -u -p -r1.25 i386-tdep.h
--- i386-tdep.h 16 Aug 2003 18:52:43 -0000 1.25
+++ i386-tdep.h 27 Sep 2003 21:56:30 -0000
@@ -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: i387-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i387-tdep.c,v
retrieving revision 1.35
diff -u -p -r1.35 i387-tdep.c
--- i387-tdep.c 23 Aug 2003 08:56:45 -0000 1.35
+++ i387-tdep.c 27 Sep 2003 21:56:30 -0000
@@ -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 *g
   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 *g
 	  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 *g
   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
 }
 
 
@@ -331,34 +340,42 @@ i387_value_to_register (struct frame_inf
   put_frame_register (frame, regnum, to);
 }
 
+
 
 /* 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])
 
 
 /* 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, in
    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
 }
 
 
@@ -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);
 
@@ -493,34 +529,43 @@ static int i387_tag (const unsigned char
    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);
+
+  /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+     proper definitions for REGCACHE's architecture.  */
 
-  if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
-    last_regnum = FOP_REGNUM;
+#define I387_ST0_REGNUM	tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
 
-  for (i = FP0_REGNUM; i <= last_regnum; i++)
+  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 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, 
 
 		    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, 
 		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, 
    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 regn
 		      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: i387-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i387-tdep.h,v
retrieving revision 1.7
diff -u -p -r1.7 i387-tdep.h
--- i387-tdep.h 24 Aug 2003 13:55:48 -0000 1.7
+++ i387-tdep.h 27 Sep 2003 21:56:30 -0000
@@ -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)
+
+
 /* 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 (stru
    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: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.92
diff -u -p -r1.92 x86-64-tdep.c
--- x86-64-tdep.c 27 Sep 2003 18:11:58 -0000 1.92
+++ x86-64-tdep.c 27 Sep 2003 21:56:32 -0000
@@ -1209,7 +1209,8 @@ x86_64_init_abi (struct gdbarch_info inf
 {
   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 inf
 
   /* 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 inf
 }
 
 
-#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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]