From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24325 invoked by alias); 30 Aug 2013 09:58:26 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 24254 invoked by uid 89); 30 Aug 2013 09:58:26 -0000 Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 30 Aug 2013 09:58:26 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,RDNS_NONE,T_FRT_BELOW2 autolearn=no version=3.3.2 X-HELO: mga02.intel.com Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 30 Aug 2013 02:58:21 -0700 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga001.jf.intel.com with ESMTP; 30 Aug 2013 02:58:19 -0700 Received: from ulslx001.iul.intel.com (ulslx001.iul.intel.com [172.28.207.63]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id r7U9wJWx014666; Fri, 30 Aug 2013 10:58:19 +0100 Received: from ulslx001.iul.intel.com (localhost [127.0.0.1]) by ulslx001.iul.intel.com with ESMTP id r7U9wIIx011333; Fri, 30 Aug 2013 11:58:18 +0200 Received: (from wtedesch@localhost) by ulslx001.iul.intel.com with id r7U9wIct011329; Fri, 30 Aug 2013 11:58:18 +0200 From: Walfred Tedeschi To: gdb-patches@sourceware.org, walfred.tedeschi@intel.com, mircea.gherzan@intel.com Subject: [PATCH v3 3/8] Add MPX support for i386 Date: Fri, 30 Aug 2013 09:58:00 -0000 Message-Id: <1377856683-11267-4-git-send-email-walfred.tedeschi@intel.com> In-Reply-To: <1377856683-11267-1-git-send-email-walfred.tedeschi@intel.com> References: <1377856683-11267-1-git-send-email-walfred.tedeschi@intel.com> X-SW-Source: 2013-08/txt/msg00906.txt.bz2 2013-14-06 Walfred Tedeschi * 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. Signed-off-by: Walfred Tedeschi --- 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..f8d8d8f 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..777af34 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_REGNUN + 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_REGNUN + 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..3a4c580 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_REGNUN - I386_BND0R_REGNUM + 1; + tdep->bnd0r_regnum = I386_BND0R_REGNUM; + tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUN; + 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..a92faf9 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_YMM7H_REGNUM + 1, /* One left for orig_rax. */ + I386_BND3R_REGNUM = I386_BND0R_REGNUM + 3, + I386_BNDCFGU_REGNUN, + I386_BNDSTATUS_REGNUN }; /* 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_REGNUN + 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