Add MPX support for i386
authorWalfred Tedeschi <walfred.tedeschi@intel.com>
Wed, 20 Nov 2013 12:02:00 +0000 (13:02 +0100)
committerWalfred Tedeschi <walfred.tedeschi@intel.com>
Wed, 20 Nov 2013 13:42:50 +0000 (14:42 +0100)
2013-11-20  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 bnd0r_regnum, bnd0_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.

Change-Id: I9ddb7d49434d86fa18eb6b99515203d7c567aefd
Signed-off-by: Walfred Tedeschi <walfred.tedeschi@intel.com>
Conflicts:

gdb/ChangeLog

gdb/ChangeLog
gdb/common/i386-xstate.h
gdb/i386-linux-nat.c
gdb/i386-linux-tdep.c
gdb/i386-linux-tdep.h
gdb/i386-tdep.c
gdb/i386-tdep.h
gdb/i387-tdep.c
gdb/i387-tdep.h

index 5722ebe843fd77c6f3e7a864f65e085340f87cc4..5df6d6a30d531d73a4a871728413871d452a89f5 100644 (file)
@@ -1,3 +1,60 @@
+2013-11-20  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 bnd0r_regnum, bnd0_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.
+
 2013-11-20  Walfred Tedeschi  <walfred.tedeschi@intel.com>
 
        * features/i386/Makefile: Adapts for using MPX registers.
index ed0a6831688447dfdd57d673fdfd9b53c57b38cc..e76ecc14045465e1ac682c0e0e5dceacb84c93b7 100644 (file)
 #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)
+#define I386_XSTATE_SIZE(XCR0) \
+    (((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 */
index ba51d4c7735c1a1209d5e6e1ecebeb6c4c687e0c..c2f4fcc87005863b134196a9155d8b021d1295da 100644 (file)
@@ -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;
 }
index 21aee96b4888c053dccdf7d5cab5e547fa86b08a..b46a51e3006371f7ddd63ecbc8fe5a6e65b8d9c8 100644 (file)
@@ -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 ();
 }
index 8e4bbf77c83a551c06cd10036cdc97a4ab287922..54b5058cdfc7d4242208f148a67bcc0d39d1a3a6 100644 (file)
@@ -29,7 +29,7 @@
 /* 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_MPX_NUM_REGS
 
 /* Total number of registers for GNU/Linux.  */
 #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
@@ -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
        };
 
index 9529dcc7e93d452537cbc60a508611c10335a7b3..597d672d2ae6f640a266037f9e9bc2ede0043323 100644 (file)
@@ -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 < I387_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 < I387_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;
+}
+
 /* 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,23 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
                                            tdep->register_names[i]);
     }
 
+  if (feature_mpx)
+    {
+      tdep->xcr0 = I386_XSTATE_MPX_MASK;
+
+      if (tdep->bnd0r_regnum < 0)
+       {
+         tdep->mpx_register_names = i386_mpx_names;
+         tdep->bnd0r_regnum = I386_BND0R_REGNUM;
+         tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUM;
+       }
+
+      for (i = 0; i < I387_NUM_MPX_REGS; 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 +7758,8 @@ 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;
+  int num_bnd_cooked;
 
   /* If there is already a candidate, use it.  */
   arches = gdbarch_list_lookup_by_info (arches, &info);
@@ -7745,8 +7933,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;
@@ -7767,6 +7955,10 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->num_mmx_regs = 8;
   tdep->num_ymm_regs = 0;
 
+  /* No MPX registers.  */
+  tdep->bnd0r_regnum = -1;
+  tdep->bndcfgu_regnum = -1;
+
   tdesc_data = tdesc_data_alloc ();
 
   set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
@@ -7785,13 +7977,16 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       return NULL;
     }
 
+  num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
+
   /* Wire in pseudo registers.  Number of pseudo registers may be
      changed.  */
   set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs
                                         + tdep->num_word_regs
                                         + tdep->num_dword_regs
                                         + tdep->num_mmx_regs
-                                        + tdep->num_ymm_regs));
+                                        + tdep->num_ymm_regs
+                                        + num_bnd_cooked));
 
   /* Target description may be changed.  */
   tdesc = tdep->tdesc;
@@ -7825,14 +8020,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->bnd0r_regnum > 0)
+      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 +8112,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");
index 092744c8ba0ecec8b43c3a13f52e1f94ee5a7821..6529c98b58887d8e0c36beb9981cf772d91d69ae 100644 (file)
@@ -130,6 +130,21 @@ struct gdbarch_tdep
   /* Upper YMM register names.  Only used for tdesc_numbered_register.  */
   const char **ymmh_register_names;
 
+  /* 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;
+
+  /* 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;
 
@@ -165,6 +180,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
@@ -212,7 +228,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.  */
@@ -250,6 +270,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
@@ -263,6 +284,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);
index fd44386a4d0072fb86401f2e8bfda453b40c3af2..1bf14856b11da447745e8c412f78c395e7f00344 100644 (file)
@@ -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;
            }
index 64cbb1e525048e9b7c5f9f112612cb8bf115eff8..3f639710c6534b172488ead31999d233a54ba998 100644 (file)
@@ -34,6 +34,13 @@ 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)
+
+/* Set of constants used for 32 and 64-bit.  */
+#define I387_NUM_MPX_REGS 6
+#define I387_NUM_BND_REGS 4
+#define I387_NUM_MPX_CTRL_REGS 2
 
 #define I387_FCTRL_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 8)
 #define I387_FSTAT_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 1)
@@ -48,6 +55,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)
 
 /* Print out the i387 floating point state.  */