This is the mail archive of the gdb-patches@sourceware.org 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 V5 3/8] Add MPX support for i386


2013-14-06  Walfred Tedeschi  <walfred.tedeschi@intel.com>

	* i386-linux-nat.c (GETXSTATEREGS_SUPPLIES): Add MPX
	registers on the range of registers to be read from
	xsave buffer.
	(i386_linux_read_description): Add case for MPX.
	* i386-linux-tdep.c: Include features/i386/i386-mpx-linux.c.
	(i386_linux_gregset_reg_offset): Add MPX registers.
	(i386_linux_core_read_description): Initialize also MPX.
	(_initialize_i386_linux_tdep): Add mpx initialization.
	* i386-tdep.h (gdbarch_tdep): Add fields	num_mpx_regs,
	num_mpx_regs, bnd0r_regnum, bnd0_regnum, num_bnd_regs,
	bndcfgu_regnum, mpx_register_names.
	(i386_regnum): Add MPX registers.
	(I386_MPX_NUM_REGS): New macro.
	(i386_bnd_regnum_p): New function.
	* i386-linux-tdep.h (I386_LINUX_NUM_REGS): Set
	number of registers to be the number of BNDSTATUS.
	(tdesc_i386_mpx_linux): Add description for MPX Linux registers.
	* i386-tdep.c: Include features/i386/i386-mpx.c.
	(i386_mpx_names): Add MPX register names array.
	(i386_bnd_names): Add bnd pseudo register names array.
	(i386_bndr_regnum_p): Lookup register numbers for bnd raw
	registers.
	(i386_bndr_regnum_p): Lookup register numbers for bnd raw registers.
	(386_mpx_ctrl_regnum_p): Lookup register numbers for MPX control
	registers.
	(i386_bnd_type): New function.
	(i386_pseudo_register_type): Use i386_bnd_type for bnd pseudo
	register types.
	(i386_pseudo_register_read_into_value): Add bnd case.
	(i386_pseudo_register_write): Add bnd pseudo registers.
	(i386_register_reggroup_p): Add MPX register to the group all.
	(i386_validate_tdesc_p): Add MPX to the target 	description
	validation.
	(i386_pseudo_register_name): Add bnd pseudo registers.
	(i386_gdbarch_init): Add MPX for architecture initialization.
	(_initia_initialize_i386_tdep): Add mpx initialization.
	* i387-tdep.c (xsave_mpx_offset): New vector for MPX offsets on
	XSAVE buffer.
	(XSAVE_MPX_ADDR): New macro.
	(i387_supply_xsave): Add MPX case.
	(i387_collect_xsave): Add MPX case.
	* i387-tdep.h (I387_BND0R_REGNUM): New macro.
	(I387_BNDCFGU_REGNUM): New macro.
	(I387_NUM_MPX_REGS): New macro.
	(I387_NUM_BND_REGS): New macro.
	(I387_NUM_MPX_CTRL_REGS): New macro.
	(I387_MPXEND_REGNUM): New macro.
	* common/i386-xstate.h (I386_XSTATE_BNDREGS): New macro.
	(I386_XSTATE_BNDCFG): Likewise.
	(I386_XSTATE_MPX_MASK): Likewise.
	(I386_XSTATE_ALL_MASK): New macro represents flags for all states.
	(I386_XSTATE_BNDREGS_SIZE): New macro.
	(I386_XSTATE_BNDCFG_SIZE): Likewise.
	(I386_XSTATE_SIZE): Adapt for MPX.
	(I386_XSTATE_MAX_SIZE): Likewise.

---
 gdb/common/i386-xstate.h |   21 ++++-
 gdb/i386-linux-nat.c     |   17 +++-
 gdb/i386-linux-tdep.c    |    9 +-
 gdb/i386-linux-tdep.h    |    6 +-
 gdb/i386-tdep.c          |  216 ++++++++++++++++++++++++++++++++++++++++++++--
 gdb/i386-tdep.h          |   30 ++++++-
 gdb/i387-tdep.c          |  130 +++++++++++++++++++++++++++-
 gdb/i387-tdep.h          |    7 ++
 8 files changed, 413 insertions(+), 23 deletions(-)

diff --git a/gdb/common/i386-xstate.h b/gdb/common/i386-xstate.h
index ed0a683..37e68f8 100644
--- a/gdb/common/i386-xstate.h
+++ b/gdb/common/i386-xstate.h
@@ -24,19 +24,34 @@
 #define I386_XSTATE_X87		(1ULL << 0)
 #define I386_XSTATE_SSE		(1ULL << 1)
 #define I386_XSTATE_AVX		(1ULL << 2)
+#define I386_XSTATE_BNDREGS	(1ULL << 3)
+#define I386_XSTATE_BNDCFG	(1ULL << 4)
 
 /* Supported mask and size of the extended state.  */
 #define I386_XSTATE_X87_MASK	I386_XSTATE_X87
 #define I386_XSTATE_SSE_MASK	(I386_XSTATE_X87 | I386_XSTATE_SSE)
 #define I386_XSTATE_AVX_MASK	(I386_XSTATE_SSE_MASK | I386_XSTATE_AVX)
+#define I386_XSTATE_MPX_MASK	(I386_XSTATE_AVX_MASK | \
+		I386_XSTATE_BNDREGS | \
+		I386_XSTATE_BNDCFG)
+
+#define I386_XSTATE_ALL_MASK    I386_XSTATE_MPX_MASK
 
 #define I386_XSTATE_SSE_SIZE	576
 #define I386_XSTATE_AVX_SIZE	832
-#define I386_XSTATE_MAX_SIZE	832
+#define I386_XSTATE_BNDREGS_SIZE	1024
+#define I386_XSTATE_BNDCFG_SIZE	1088
+
+#define I386_XSTATE_MAX_SIZE	1088
 
 /* Get I386 XSAVE extended state size.  */
 #define I386_XSTATE_SIZE(XCR0)	\
-  (((XCR0) & I386_XSTATE_AVX) != 0 \
-   ? I386_XSTATE_AVX_SIZE : I386_XSTATE_SSE_SIZE)
+  (((XCR0) & I386_XSTATE_BNDCFG) != 0 \
+   ? I386_XSTATE_BNDCFG_SIZE : \
+	(((XCR0) & I386_XSTATE_BNDREGS) != 0 \
+   ? I386_XSTATE_BNDCFG_SIZE : \
+	(((XCR0) & I386_XSTATE_AVX_SIZE) != 0 \
+   ? I386_XSTATE_AVX_SIZE : \
+			I386_XSTATE_SSE_SIZE)))\
 
 #endif /* I386_XSTATE_H */
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index be2b6c9..ecc79c6 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -102,7 +102,7 @@ static int have_ptrace_getregset = -1;
   (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS)
 
 #define GETXSTATEREGS_SUPPLIES(regno) \
-  (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX_NUM_REGS)
+  (I386_ST0_REGNUM <= (regno) && (regno) < I386_MPX_NUM_REGS)
 
 /* Does the current host support the GETREGS request?  */
 int have_ptrace_getregs =
@@ -1041,9 +1041,18 @@ i386_linux_read_description (struct target_ops *ops)
     }
 
   /* Check the native XCR0 only if PTRACE_GETREGSET is available.  */
-  if (have_ptrace_getregset
-      && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
-    return tdesc_i386_avx_linux;
+  if (have_ptrace_getregset)
+    {
+      switch ((xcr0 & I386_XSTATE_ALL_MASK))
+	{
+	case I386_XSTATE_MPX_MASK:
+	  return tdesc_i386_mpx_linux;
+	case I386_XSTATE_AVX_MASK:
+	  return tdesc_i386_avx_linux;
+	default:
+	  return tdesc_i386_linux;
+	}
+    }
   else
     return tdesc_i386_linux;
 }
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 7b69aab..6d88df3 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -50,6 +50,7 @@
 
 #include "features/i386/i386-linux.c"
 #include "features/i386/i386-mmx-linux.c"
+#include "features/i386/i386-mpx-linux.c"
 #include "features/i386/i386-avx-linux.c"
 
 /* Supported register note sections.  */
@@ -569,6 +570,8 @@ int i386_linux_gregset_reg_offset[] =
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1,		/* MPX registers BND0 ... BND3.  */
+  -1, -1,			/* MPX registers BNDCFGU, BNDSTATUS.  */
   11 * 4			/* "orig_eax" */
 };
 
@@ -642,8 +645,11 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
 {
   /* Linux/i386.  */
   uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
-  switch ((xcr0 & I386_XSTATE_AVX_MASK))
+
+  switch ((xcr0 & I386_XSTATE_ALL_MASK))
     {
+    case I386_XSTATE_MPX_MASK:
+      return tdesc_i386_mpx_linux;
     case I386_XSTATE_AVX_MASK:
       return tdesc_i386_avx_linux;
     case I386_XSTATE_SSE_MASK:
@@ -979,4 +985,5 @@ _initialize_i386_linux_tdep (void)
   initialize_tdesc_i386_linux ();
   initialize_tdesc_i386_mmx_linux ();
   initialize_tdesc_i386_avx_linux ();
+  initialize_tdesc_i386_mpx_linux ();
 }
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index 8e4bbf7..98e7ac2 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -29,10 +29,10 @@
 /* Register number for the "orig_eax" pseudo-register.  If this
    pseudo-register contains a value >= 0 it is interpreted as the
    system call number that the kernel is supposed to restart.  */
-#define I386_LINUX_ORIG_EAX_REGNUM I386_AVX_NUM_REGS
+#define I386_LINUX_ORIG_EAX_REGNUM I386_BNDSTATUS_REGNUM + 1
 
 /* Total number of registers for GNU/Linux.  */
-#define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
+#define I386_LINUX_NUM_REGS (I386_BNDSTATUS_REGNUM + 2)
 
 /* Get XSAVE extended state xcr0 from core dump.  */
 extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
@@ -41,6 +41,7 @@ extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
 extern struct target_desc *tdesc_i386_linux;
 extern struct target_desc *tdesc_i386_mmx_linux;
 extern struct target_desc *tdesc_i386_avx_linux;
+extern struct target_desc *tdesc_i386_mpx_linux;
 
 /* Format of XSAVE extended state is:
  	struct
@@ -49,6 +50,7 @@ extern struct target_desc *tdesc_i386_avx_linux;
 	  sw_usable_bytes[464..511]
 	  xstate_hdr_bytes[512..575]
 	  avx_bytes[576..831]
+	  mpx_bytes [960..1032]
 	  future_state etc
 	};
 
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b159b49..f5d9f49 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -57,6 +57,7 @@
 
 #include "features/i386/i386.c"
 #include "features/i386/i386-avx.c"
+#include "features/i386/i386-mpx.c"
 #include "features/i386/i386-mmx.c"
 
 #include "ax.h"
@@ -98,6 +99,18 @@ static const char *i386_ymmh_names[] =
   "ymm4h",  "ymm5h",   "ymm6h",  "ymm7h",
 };
 
+static const char *i386_mpx_names[] =
+{
+  "bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus"
+};
+
+/* Register names for MPX pseudo-registers.  */
+
+static const char *i386_bnd_names[] =
+{
+  "bnd0", "bnd1", "bnd2", "bnd3"
+};
+
 /* Register names for MMX pseudo-registers.  */
 
 static const char *i386_mmx_names[] =
@@ -202,6 +215,21 @@ i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum)
   return regnum >= 0 && regnum < tdep->num_ymm_regs;
 }
 
+/* BND register?  */
+
+int
+i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int bnd0_regnum = tdep->bnd0_regnum;
+
+  if (bnd0_regnum < 0)
+    return 0;
+
+  regnum -= bnd0_regnum;
+  return regnum >= 0 && regnum < tdep->num_bnd_regs;
+}
+
 /* SSE register?  */
 
 int
@@ -254,6 +282,34 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
 	  && regnum < I387_XMM0_REGNUM (tdep));
 }
 
+/* BNDr (raw) register?  */
+
+static int
+i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+   if (I387_BND0R_REGNUM (tdep) < 0)
+     return 0;
+
+  regnum -= tdep->bnd0r_regnum;
+  return regnum >= 0 && regnum < tdep->num_bnd_regs;
+}
+
+/* BND control register?  */
+
+static int
+i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+   if (I387_BNDCFGU_REGNUM (tdep) < 0)
+     return 0;
+
+  regnum -= I387_BNDCFGU_REGNUM (tdep);
+  return regnum >= 0 && regnum < I387_NUM_MPX_CTRL_REGS (tdep);
+}
+
 /* Return the name of register REGNUM, or the empty string if it is
    an anonymous register.  */
 
@@ -273,6 +329,8 @@ const char *
 i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (i386_bnd_regnum_p (gdbarch, regnum))
+    return i386_bnd_names[regnum - tdep->bnd0_regnum];
   if (i386_mmx_regnum_p (gdbarch, regnum))
     return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)];
   else if (i386_ymm_regnum_p (gdbarch, regnum))
@@ -2750,6 +2808,43 @@ i387_ext_type (struct gdbarch *gdbarch)
   return tdep->i387_ext_type;
 }
 
+/* Construct type for pseudo BND registers.  We can't use
+   tdesc_find_type since a complement of one value has to be used
+   to describe the upper bound.  */
+
+static struct type *
+i386_bnd_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+
+  if (!tdep->i386_bnd_type)
+    {
+      struct type *t, *bound_t;
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
+      /* The type we're building is described bellow:  */
+#if 0
+      struct __bound128
+      {
+	void *lbound;
+	void *ubound;		/* One complement of raw ubound field.  */
+      };
+#endif
+
+      t = arch_composite_type (gdbarch,
+			       "__gdb_builtin_type_bound128", TYPE_CODE_STRUCT);
+
+      append_composite_type_field (t, "lbound", bt->builtin_data_ptr);
+      append_composite_type_field (t, "ubound", bt->builtin_data_ptr);
+
+      TYPE_NAME (t) = "builtin_type_bound128";
+      tdep->i386_bnd_type = t;
+    }
+
+  return tdep->i386_bnd_type;
+}
+
 /* Construct vector type for pseudo YMM registers.  We can't use
    tdesc_find_type since YMM isn't described in target description.  */
 
@@ -2851,6 +2946,8 @@ i386_mmx_type (struct gdbarch *gdbarch)
 struct type *
 i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
+  if (i386_bnd_regnum_p (gdbarch, regnum))
+    return i386_bnd_type (gdbarch);
   if (i386_mmx_regnum_p (gdbarch, regnum))
     return i386_mmx_type (gdbarch);
   else if (i386_ymm_regnum_p (gdbarch, regnum))
@@ -2917,8 +3014,31 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
   else
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+      if (i386_bnd_regnum_p (gdbarch, regnum))
+	{
+	  regnum -= tdep->bnd0_regnum;
 
-      if (i386_ymm_regnum_p (gdbarch, regnum))
+	  /* Extract (always little endian).  Read lower 128bits.  */
+	  status = regcache_raw_read (regcache,
+				      I387_BND0R_REGNUM (tdep) + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    mark_value_bytes_unavailable (result_value, 0, 16);
+	  else
+	    {
+	      enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+	      LONGEST upper, lower;
+	      int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
+
+	      lower = extract_unsigned_integer (raw_buf, 8, byte_order);
+	      upper = extract_unsigned_integer (raw_buf + 8, 8, byte_order);
+	      upper = ~upper;
+
+	      memcpy (buf, &lower, size);
+	      memcpy (buf + size, &upper, size);
+	    }
+	}
+      else if (i386_ymm_regnum_p (gdbarch, regnum))
 	{
 	  regnum -= tdep->ymm0_regnum;
 
@@ -3011,7 +3131,34 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-      if (i386_ymm_regnum_p (gdbarch, regnum))
+      if (i386_bnd_regnum_p (gdbarch, regnum))
+	{
+	  ULONGEST upper, lower;
+	  int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
+	  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+
+	  /* New values from input value.  */
+	  regnum -= tdep->bnd0_regnum;
+	  lower = extract_unsigned_integer (buf, size, byte_order);
+	  upper = extract_unsigned_integer (buf + size, size, byte_order);
+
+	  /* Fetching register buffer.  */
+	  regcache_raw_read (regcache,
+			     I387_BND0R_REGNUM (tdep) + regnum,
+			     raw_buf);
+
+	  upper = ~upper;
+
+	  /* Set register bits.  */
+	  memcpy (raw_buf, &lower, 8);
+	  memcpy (raw_buf + 8, &upper, 8);
+
+
+	  regcache_raw_write (regcache,
+			      I387_BND0R_REGNUM (tdep) + regnum,
+			      raw_buf);
+	}
+      else if (i386_ymm_regnum_p (gdbarch, regnum))
 	{
 	  regnum -= tdep->ymm0_regnum;
 
@@ -3866,7 +4013,8 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 {
   const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
-      ymm_regnum_p, ymmh_regnum_p;
+      ymm_regnum_p, ymmh_regnum_p, bndr_regnum_p, bnd_regnum_p,
+      mpx_ctrl_regnum_p;
 
   /* Don't include pseudo registers, except for MMX, in any register
      groups.  */
@@ -3911,13 +4059,31 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 	  || ymmh_regnum_p))
     return 0;
 
+  bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum);
+  if (group == all_reggroup
+      && ((bnd_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK))))
+    return bnd_regnum_p;
+
+  bndr_regnum_p = i386_bndr_regnum_p (gdbarch, regnum);
+  if (group == all_reggroup
+      && ((bndr_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK))))
+    return 0;
+
+  mpx_ctrl_regnum_p = i386_mpx_ctrl_regnum_p (gdbarch, regnum);
+  if (group == all_reggroup
+      && ((mpx_ctrl_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK))))
+    return mpx_ctrl_regnum_p;
+
   if (group == general_reggroup)
     return (!fp_regnum_p
 	    && !mmx_regnum_p
 	    && !mxcsr_regnum_p
 	    && !xmm_regnum_p
 	    && !ymm_regnum_p
-	    && !ymmh_regnum_p);
+	    && !ymmh_regnum_p
+	    && !bndr_regnum_p
+	    && !bnd_regnum_p
+	    && !mpx_ctrl_regnum_p);
 
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
@@ -7496,7 +7662,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
 {
   const struct target_desc *tdesc = tdep->tdesc;
   const struct tdesc_feature *feature_core;
-  const struct tdesc_feature *feature_sse, *feature_avx;
+  const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx;
   int i, num_regs, valid_p;
 
   if (! tdesc_has_registers (tdesc))
@@ -7513,6 +7679,9 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
   /* Try AVX registers.  */
   feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
 
+  /* Try MPX registers.  */
+  feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
+
   valid_p = 1;
 
   /* The XCR0 bits.  */
@@ -7559,6 +7728,26 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
 					    tdep->register_names[i]);
     }
 
+  if (feature_mpx)
+    {
+      tdep->xcr0 = I386_XSTATE_MPX_MASK;
+
+      if (I387_NUM_MPX_REGS (tdep) == 0)
+	{
+	  tdep->mpx_register_names = i386_mpx_names;
+	  tdep->num_mpx_regs =
+	      I386_BNDSTATUS_REGNUM - I386_BND0R_REGNUM + 1;
+	  tdep->bnd0r_regnum = I386_BND0R_REGNUM;
+	  tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUM;
+	  tdep->num_bnd_regs = 4;
+	}
+
+      for (i = 0; i < I387_NUM_MPX_REGS (tdep); i++)
+	valid_p &= tdesc_numbered_register (feature_mpx, tdesc_data,
+	    I387_BND0R_REGNUM (tdep) + i,
+	    tdep->mpx_register_names[i]);
+    }
+
   return valid_p;
 }
 
@@ -7572,6 +7761,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   const struct target_desc *tdesc;
   int mm0_regnum;
   int ymm0_regnum;
+  int bnd0_regnum;
 
   /* If there is already a candidate, use it.  */
   arches = gdbarch_list_lookup_by_info (arches, &info);
@@ -7745,8 +7935,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Even though the default ABI only includes general-purpose registers,
      floating-point registers and the SSE registers, we have to leave a
-     gap for the upper AVX registers.  */
-  set_gdbarch_num_regs (gdbarch, I386_AVX_NUM_REGS);
+     gap for the upper AVX registers and the MPX registers.  */
+  set_gdbarch_num_regs (gdbarch, I386_MPX_NUM_REGS);
 
   /* Get the x86 target description from INFO.  */
   tdesc = info.target_desc;
@@ -7766,6 +7956,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->num_dword_regs = 0;
   tdep->num_mmx_regs = 8;
   tdep->num_ymm_regs = 0;
+  tdep->num_bnd_regs = 0;
 
   tdesc_data = tdesc_data_alloc ();
 
@@ -7791,7 +7982,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					 + tdep->num_word_regs
 					 + tdep->num_dword_regs
 					 + tdep->num_mmx_regs
-					 + tdep->num_ymm_regs));
+					 + tdep->num_ymm_regs
+					 + tdep->num_bnd_regs));
 
   /* Target description may be changed.  */
   tdesc = tdep->tdesc;
@@ -7825,14 +8017,21 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     tdep->ymm0_regnum = -1;
 
+  bnd0_regnum = mm0_regnum;
   if (tdep->num_mmx_regs != 0)
     {
       /* Support MMX pseudo-register if MMX hasn't been disabled.  */
       tdep->mm0_regnum = mm0_regnum;
+      bnd0_regnum += tdep->num_mmx_regs;
     }
   else
     tdep->mm0_regnum = -1;
 
+  if (tdep->num_bnd_regs)
+      tdep->bnd0_regnum = bnd0_regnum;
+  else
+    tdep-> bnd0_regnum = -1;
+
   /* Hook in the legacy prologue-based unwinders last (fallback).  */
   frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind);
   frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
@@ -7910,6 +8109,7 @@ is \"default\"."),
   initialize_tdesc_i386 ();
   initialize_tdesc_i386_mmx ();
   initialize_tdesc_i386_avx ();
+  initialize_tdesc_i386_mpx ();
 
   /* Tell remote stub that we support XML target description.  */
   register_remote_support_xml ("i386");
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 69bd281..cfffbac 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -173,6 +173,27 @@ struct gdbarch_tdep
   /* Upper YMM register names.  Only used for tdesc_numbered_register.  */
   const char **ymmh_register_names;
 
+  /* Number of MPX registers.  */
+  int num_mpx_regs;
+
+  /* Register number for %bnd0r.  Set this to -1 to indicate the absence
+     bound registers.  */
+  int bnd0r_regnum;
+
+  /* Register number for pseudo register %bnd0.  Set this to -1 to indicate the absence
+     bound registers.  */
+  int bnd0_regnum;
+
+  /* Number of bnd pseudo registers.  */
+  int num_bnd_regs;
+
+  /* Register number for %bndcfgu. Set this to -1 to indicate the absence
+     bound control registers.  */
+  int bndcfgu_regnum;
+
+  /* MPX register names.  Only used for tdesc_numbered_register.  */
+  const char **mpx_register_names;
+
   /* Target description.  */
   const struct target_desc *tdesc;
 
@@ -208,6 +229,7 @@ struct gdbarch_tdep
   struct type *i386_mmx_type;
   struct type *i386_ymm_type;
   struct type *i387_ext_type;
+  struct type *i386_bnd_type;
 
   /* Process record/replay target.  */
   /* The map for registers because the AMD64's registers order
@@ -255,7 +277,11 @@ enum i386_regnum
   I386_ST0_REGNUM,		/* %st(0) */
   I386_MXCSR_REGNUM = 40,	/* %mxcsr */ 
   I386_YMM0H_REGNUM,		/* %ymm0h */
-  I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7
+  I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7,
+  I386_BND0R_REGNUM,
+  I386_BND3R_REGNUM = I386_BND0R_REGNUM + 3,
+  I386_BNDCFGU_REGNUM,
+  I386_BNDSTATUS_REGNUM
 };
 
 /* Register numbers of RECORD_REGMAP.  */
@@ -293,6 +319,7 @@ enum record_i386_regnum
 
 #define I386_SSE_NUM_REGS	(I386_MXCSR_REGNUM + 1)
 #define I386_AVX_NUM_REGS	(I386_YMM7H_REGNUM + 1)
+#define I386_MPX_NUM_REGS	(I386_BNDSTATUS_REGNUM + 1)
 
 /* Size of the largest register.  */
 #define I386_MAX_REGISTER_SIZE	16
@@ -306,6 +333,7 @@ extern int i386_word_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern int i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
+extern int i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum);
 
 extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
 					      int regnum);
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 48a00c3..5871b19 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -763,9 +763,22 @@ static int xsave_avxh_offset[] =
   576 + 15 * 16		/* Upper 128bit of ... %ymm15 (128 bits each).  */
 };
 
+static int xsave_mpx_offset[] =
+{
+  960 + 0 * 16,			/* bnd0r...bnd3r registers.  */
+  960 + 1 * 16,
+  960 + 2 * 16,
+  960 + 3 * 16,
+  1024 + 0 * 8,			/* bndcfg ... bndstatus.  */
+  1024 + 1 * 8,
+};
+
 #define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
   (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
 
+#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \
+  (xsave + xsave_mpx_offset[regnum - I387_BND0R_REGNUM (tdep)])
+
 /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
 
 void
@@ -783,7 +796,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       x87 = 0x1,
       sse = 0x2,
       avxh = 0x4,
-      all = x87 | sse | avxh
+      mpx  = 0x8,
+      all = x87 | sse | avxh | mpx
     } regclass;
 
   gdb_assert (regs != NULL);
@@ -795,6 +809,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
   else if (regnum >= I387_YMM0H_REGNUM (tdep)
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
+  else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_MPXEND_REGNUM (tdep))
+    regclass = mpx;
   else if (regnum >= I387_XMM0_REGNUM(tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
@@ -814,7 +831,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       clear_bv = (~(*xstate_bv_p)) & tdep->xcr0;
     }
   else
-    clear_bv = I386_XSTATE_AVX_MASK;
+    clear_bv = I386_XSTATE_ALL_MASK;
 
   /* With the delayed xsave mechanism, in between the program
      starting, and the program accessing the vector registers for the
@@ -838,6 +855,14 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 			     XSAVE_AVXH_ADDR (tdep, regs, regnum));
       return;
 
+    case mpx:
+      if ((clear_bv & I386_XSTATE_BNDREGS))
+	regcache_raw_supply (regcache, regnum, zero);
+      else
+	regcache_raw_supply (regcache, regnum,
+			     XSAVE_MPX_ADDR (tdep, regs, regnum));
+      return;
+
     case sse:
       if ((clear_bv & I386_XSTATE_SSE))
 	regcache_raw_supply (regcache, regnum, zero);
@@ -875,6 +900,42 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    }
 	}
 
+      /* Handle the MPX registers.  */
+      if ((tdep->xcr0 & I386_XSTATE_BNDREGS))
+	{
+	  if (clear_bv & I386_XSTATE_BNDREGS)
+	    {
+	      for (i = I387_BND0R_REGNUM (tdep);
+		   i < I387_BNDCFGU_REGNUM (tdep); i++)
+		regcache_raw_supply (regcache, i, zero);
+	    }
+	  else
+	    {
+	      for (i = I387_BND0R_REGNUM (tdep);
+		   i < I387_BNDCFGU_REGNUM (tdep); i++)
+		regcache_raw_supply (regcache, i,
+				     XSAVE_MPX_ADDR (tdep, regs, i));
+	    }
+	}
+
+      /* Handle the MPX registers.  */
+      if ((tdep->xcr0 & I386_XSTATE_BNDCFG))
+	{
+	  if (clear_bv & I386_XSTATE_BNDCFG)
+	    {
+	      for (i = I387_BNDCFGU_REGNUM (tdep);
+		   i < I387_MPXEND_REGNUM (tdep); i++)
+		regcache_raw_supply (regcache, i, zero);
+	    }
+	  else
+	    {
+	      for (i = I387_BNDCFGU_REGNUM (tdep);
+		   i < I387_MPXEND_REGNUM (tdep); i++)
+		regcache_raw_supply (regcache, i,
+				     XSAVE_MPX_ADDR (tdep, regs, i));
+	    }
+	}
+
       /* Handle the XMM registers.  */
       if ((tdep->xcr0 & I386_XSTATE_SSE))
 	{
@@ -989,7 +1050,8 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       x87 = 0x2 | check,
       sse = 0x4 | check,
       avxh = 0x8 | check,
-      all = x87 | sse | avxh
+      mpx  = 0x10 | check,
+      all = x87 | sse | avxh | mpx
     } regclass;
 
   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
@@ -1000,7 +1062,10 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
   else if (regnum >= I387_YMM0H_REGNUM (tdep)
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
-  else if (regnum >= I387_XMM0_REGNUM(tdep)
+  else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_MPXEND_REGNUM (tdep))
+    regclass = mpx;
+  else if (regnum >= I387_XMM0_REGNUM (tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
   else if (regnum >= I387_ST0_REGNUM (tdep)
@@ -1032,6 +1097,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       /* Clear register set if its bit in xstat_bv is zero.  */
       if (clear_bv)
 	{
+	  if ((clear_bv & I386_XSTATE_BNDREGS))
+	    for (i = I387_BND0R_REGNUM (tdep);
+		 i < I387_BNDCFGU_REGNUM (tdep); i++)
+	      memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16);
+
+	  if ((clear_bv & I386_XSTATE_BNDCFG))
+	    for (i = I387_BNDCFGU_REGNUM (tdep);
+		 i < I387_MPXEND_REGNUM (tdep); i++)
+	      memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
+
 	  if ((clear_bv & I386_XSTATE_AVX))
 	    for (i = I387_YMM0H_REGNUM (tdep);
 		 i < I387_YMMENDH_REGNUM (tdep); i++)
@@ -1063,6 +1138,33 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 		    memcpy (p, raw, 16);
 		  }
 	      }
+	  /* Check if any upper MPX registers are changed.  */
+	  if ((tdep->xcr0 & I386_XSTATE_BNDREGS))
+	    for (i = I387_BND0R_REGNUM (tdep);
+		 i < I387_BNDCFGU_REGNUM (tdep); i++)
+	      {
+		regcache_raw_collect (regcache, i, raw);
+		p = XSAVE_MPX_ADDR (tdep, regs, i);
+		if (memcmp (raw, p, 16))
+		  {
+		    xstate_bv |= I386_XSTATE_BNDREGS;
+		    memcpy (p, raw, 16);
+		  }
+	      }
+
+	  /* Check if any upper MPX registers are changed.  */
+	  if ((tdep->xcr0 & I386_XSTATE_BNDCFG))
+	    for (i = I387_BNDCFGU_REGNUM (tdep);
+		 i < I387_MPXEND_REGNUM (tdep); i++)
+	      {
+		regcache_raw_collect (regcache, i, raw);
+		p = XSAVE_MPX_ADDR (tdep, regs, i);
+		if (memcmp (raw, p, 8))
+		  {
+		    xstate_bv |= I386_XSTATE_BNDCFG;
+		    memcpy (p, raw, 8);
+		  }
+	      }
 
 	  /* Check if any SSE registers are changed.  */
 	  if ((tdep->xcr0 & I386_XSTATE_SSE))
@@ -1113,6 +1215,25 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 		}
 	      break;
 
+	    case mpx:
+	      if (regnum < I387_BNDCFGU_REGNUM (tdep))
+		{
+		  regcache_raw_collect (regcache, regnum, raw);
+		  p = XSAVE_MPX_ADDR (tdep, regs, regnum);
+		  if (memcmp (raw, p, 16))
+		    {
+		      xstate_bv |= I386_XSTATE_BNDREGS;
+		      memcpy (p, raw, 16);
+		    }
+		}
+	      else
+		{
+		  p = XSAVE_MPX_ADDR (tdep, regs, regnum);
+		  xstate_bv |= I386_XSTATE_BNDCFG;
+		  memcpy (p, raw, 8);
+		}
+	      break;
+
 	    case sse:
 	      /* This is an SSE register.  */
 	      p = FXSAVE_ADDR (tdep, regs, regnum);
@@ -1154,6 +1275,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	    case x87:
 	    case sse:
 	    case avxh:
+	    case mpx:
 	      /* Register REGNUM has been updated.  Return.  */
 	      return;
 	    }
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index 64cbb1e..ac4f001 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -34,6 +34,11 @@ struct ui_file;
 #define I387_MM0_REGNUM(tdep) ((tdep)->mm0_regnum)
 #define I387_NUM_YMM_REGS(tdep) ((tdep)->num_ymm_regs)
 #define I387_YMM0H_REGNUM(tdep) ((tdep)->ymm0h_regnum)
+#define I387_BND0R_REGNUM(tdep) ((tdep)->bnd0r_regnum)
+#define I387_BNDCFGU_REGNUM(tdep) ((tdep)->bndcfgu_regnum)
+#define I387_NUM_MPX_REGS(tdep) ((tdep)->num_mpx_regs)
+#define I387_NUM_BND_REGS(tdep) ((tdep)->num_bnd_regs)
+#define I387_NUM_MPX_CTRL_REGS(tdep) ((tdep)->num_mpx_regs - (tdep)->num_bnd_regs)
 
 #define I387_FCTRL_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 8)
 #define I387_FSTAT_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 1)
@@ -48,6 +53,8 @@ struct ui_file;
   (I387_XMM0_REGNUM (tdep) + I387_NUM_XMM_REGS (tdep))
 #define I387_YMMENDH_REGNUM(tdep) \
   (I387_YMM0H_REGNUM (tdep) + I387_NUM_YMM_REGS (tdep))
+#define I387_MPXEND_REGNUM(tdep) \
+  (I387_BND0R_REGNUM (tdep) + I387_NUM_MPX_REGS (tdep))
 
 /* Print out the i387 floating point state.  */
 
-- 
1.7.10.4


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