GNU Binutils with patches for OS216
Revisión | 1dbcd68cf12168c359df2da36b5b612100310a30 (tree) |
---|---|
Tiempo | 2013-11-20 22:42:50 |
Autor | Walfred Tedeschi <walfred.tedeschi@inte...> |
Commiter | Walfred Tedeschi |
Add MPX support for i386
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
@@ -1,5 +1,62 @@ | ||
1 | 1 | 2013-11-20 Walfred Tedeschi <walfred.tedeschi@intel.com> |
2 | 2 | |
3 | + * i386-linux-nat.c (GETXSTATEREGS_SUPPLIES): Add MPX | |
4 | + registers on the range of registers to be read from | |
5 | + xsave buffer. | |
6 | + (i386_linux_read_description): Add case for MPX. | |
7 | + * i386-linux-tdep.c: Include features/i386/i386-mpx-linux.c. | |
8 | + (i386_linux_gregset_reg_offset): Add MPX registers. | |
9 | + (i386_linux_core_read_description): Initialize also MPX. | |
10 | + (_initialize_i386_linux_tdep): Add mpx initialization. | |
11 | + * i386-tdep.h (gdbarch_tdep): Add fields bnd0r_regnum, bnd0_regnum, | |
12 | + mpx_register_names. | |
13 | + (i386_regnum): Add MPX registers. | |
14 | + (I386_MPX_NUM_REGS): New macro. | |
15 | + (i386_bnd_regnum_p): New function. | |
16 | + * i386-linux-tdep.h (I386_LINUX_NUM_REGS): Set | |
17 | + number of registers to be the number of BNDSTATUS. | |
18 | + (tdesc_i386_mpx_linux): Add description for MPX Linux registers. | |
19 | + * i386-tdep.c: Include features/i386/i386-mpx.c. | |
20 | + (i386_mpx_names): Add MPX register names array. | |
21 | + (i386_bnd_names): Add bnd pseudo register names array. | |
22 | + (i386_bndr_regnum_p): Lookup register numbers for bnd raw | |
23 | + registers. | |
24 | + (i386_bndr_regnum_p): Lookup register numbers for bnd raw registers. | |
25 | + (386_mpx_ctrl_regnum_p): Lookup register numbers for MPX control | |
26 | + registers. | |
27 | + (i386_bnd_type): New function. | |
28 | + (i386_pseudo_register_type): Use i386_bnd_type for bnd pseudo | |
29 | + register types. | |
30 | + (i386_pseudo_register_read_into_value): Add bnd case. | |
31 | + (i386_pseudo_register_write): Add bnd pseudo registers. | |
32 | + (i386_register_reggroup_p): Add MPX register to the group all. | |
33 | + (i386_validate_tdesc_p): Add MPX to the target description | |
34 | + validation. | |
35 | + (i386_pseudo_register_name): Add bnd pseudo registers. | |
36 | + (i386_gdbarch_init): Add MPX for architecture initialization. | |
37 | + (_initia_initialize_i386_tdep): Add mpx initialization. | |
38 | + * i387-tdep.c (xsave_mpx_offset): New vector for MPX offsets on | |
39 | + XSAVE buffer. | |
40 | + (XSAVE_MPX_ADDR): New macro. | |
41 | + (i387_supply_xsave): Add MPX case. | |
42 | + (i387_collect_xsave): Add MPX case. | |
43 | + * i387-tdep.h (I387_BND0R_REGNUM): New macro. | |
44 | + (I387_BNDCFGU_REGNUM): New macro. | |
45 | + (I387_NUM_MPX_REGS): New macro. | |
46 | + (I387_NUM_BND_REGS): New macro. | |
47 | + (I387_NUM_MPX_CTRL_REGS): New macro. | |
48 | + (I387_MPXEND_REGNUM): New macro. | |
49 | + * common/i386-xstate.h (I386_XSTATE_BNDREGS): New macro. | |
50 | + (I386_XSTATE_BNDCFG): Likewise. | |
51 | + (I386_XSTATE_MPX_MASK): Likewise. | |
52 | + (I386_XSTATE_ALL_MASK): New macro represents flags for all states. | |
53 | + (I386_XSTATE_BNDREGS_SIZE): New macro. | |
54 | + (I386_XSTATE_BNDCFG_SIZE): Likewise. | |
55 | + (I386_XSTATE_SIZE): Adapt for MPX. | |
56 | + (I386_XSTATE_MAX_SIZE): Likewise. | |
57 | + | |
58 | +2013-11-20 Walfred Tedeschi <walfred.tedeschi@intel.com> | |
59 | + | |
3 | 60 | * features/i386/Makefile: Adapts for using MPX registers. |
4 | 61 | * features/i386/32bit-mpx.xml: New file. |
5 | 62 | * features/i386/64bit-mpx.xml: Likewise. |
@@ -24,19 +24,31 @@ | ||
24 | 24 | #define I386_XSTATE_X87 (1ULL << 0) |
25 | 25 | #define I386_XSTATE_SSE (1ULL << 1) |
26 | 26 | #define I386_XSTATE_AVX (1ULL << 2) |
27 | +#define I386_XSTATE_BNDREGS (1ULL << 3) | |
28 | +#define I386_XSTATE_BNDCFG (1ULL << 4) | |
27 | 29 | |
28 | 30 | /* Supported mask and size of the extended state. */ |
29 | 31 | #define I386_XSTATE_X87_MASK I386_XSTATE_X87 |
30 | 32 | #define I386_XSTATE_SSE_MASK (I386_XSTATE_X87 | I386_XSTATE_SSE) |
31 | 33 | #define I386_XSTATE_AVX_MASK (I386_XSTATE_SSE_MASK | I386_XSTATE_AVX) |
34 | +#define I386_XSTATE_MPX_MASK (I386_XSTATE_AVX_MASK \ | |
35 | + | I386_XSTATE_BNDREGS \ | |
36 | + | I386_XSTATE_BNDCFG) | |
37 | + | |
38 | +#define I386_XSTATE_ALL_MASK I386_XSTATE_MPX_MASK | |
32 | 39 | |
33 | 40 | #define I386_XSTATE_SSE_SIZE 576 |
34 | 41 | #define I386_XSTATE_AVX_SIZE 832 |
35 | -#define I386_XSTATE_MAX_SIZE 832 | |
42 | +#define I386_XSTATE_BNDREGS_SIZE 1024 | |
43 | +#define I386_XSTATE_BNDCFG_SIZE 1088 | |
44 | + | |
45 | +#define I386_XSTATE_MAX_SIZE 1088 | |
36 | 46 | |
37 | 47 | /* Get I386 XSAVE extended state size. */ |
38 | -#define I386_XSTATE_SIZE(XCR0) \ | |
39 | - (((XCR0) & I386_XSTATE_AVX) != 0 \ | |
40 | - ? I386_XSTATE_AVX_SIZE : I386_XSTATE_SSE_SIZE) | |
48 | +#define I386_XSTATE_SIZE(XCR0) \ | |
49 | + (((XCR0) & I386_XSTATE_BNDCFG) != 0 ? I386_XSTATE_BNDCFG_SIZE \ | |
50 | + : (((XCR0) & I386_XSTATE_BNDREGS) != 0 ? I386_XSTATE_BNDCFG_SIZE \ | |
51 | + : (((XCR0) & I386_XSTATE_AVX_SIZE) != 0 ? I386_XSTATE_AVX_SIZE \ | |
52 | + : I386_XSTATE_SSE_SIZE))) | |
41 | 53 | |
42 | 54 | #endif /* I386_XSTATE_H */ |
@@ -102,7 +102,7 @@ static int have_ptrace_getregset = -1; | ||
102 | 102 | (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS) |
103 | 103 | |
104 | 104 | #define GETXSTATEREGS_SUPPLIES(regno) \ |
105 | - (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX_NUM_REGS) | |
105 | + (I386_ST0_REGNUM <= (regno) && (regno) < I386_MPX_NUM_REGS) | |
106 | 106 | |
107 | 107 | /* Does the current host support the GETREGS request? */ |
108 | 108 | int have_ptrace_getregs = |
@@ -1041,9 +1041,18 @@ i386_linux_read_description (struct target_ops *ops) | ||
1041 | 1041 | } |
1042 | 1042 | |
1043 | 1043 | /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ |
1044 | - if (have_ptrace_getregset | |
1045 | - && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) | |
1046 | - return tdesc_i386_avx_linux; | |
1044 | + if (have_ptrace_getregset) | |
1045 | + { | |
1046 | + switch ((xcr0 & I386_XSTATE_ALL_MASK)) | |
1047 | + { | |
1048 | + case I386_XSTATE_MPX_MASK: | |
1049 | + return tdesc_i386_mpx_linux; | |
1050 | + case I386_XSTATE_AVX_MASK: | |
1051 | + return tdesc_i386_avx_linux; | |
1052 | + default: | |
1053 | + return tdesc_i386_linux; | |
1054 | + } | |
1055 | + } | |
1047 | 1056 | else |
1048 | 1057 | return tdesc_i386_linux; |
1049 | 1058 | } |
@@ -50,6 +50,7 @@ | ||
50 | 50 | |
51 | 51 | #include "features/i386/i386-linux.c" |
52 | 52 | #include "features/i386/i386-mmx-linux.c" |
53 | +#include "features/i386/i386-mpx-linux.c" | |
53 | 54 | #include "features/i386/i386-avx-linux.c" |
54 | 55 | |
55 | 56 | /* Supported register note sections. */ |
@@ -569,6 +570,8 @@ int i386_linux_gregset_reg_offset[] = | ||
569 | 570 | -1, -1, -1, -1, -1, -1, -1, -1, |
570 | 571 | -1, |
571 | 572 | -1, -1, -1, -1, -1, -1, -1, -1, |
573 | + -1, -1, -1, -1, /* MPX registers BND0 ... BND3. */ | |
574 | + -1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */ | |
572 | 575 | 11 * 4 /* "orig_eax" */ |
573 | 576 | }; |
574 | 577 |
@@ -642,8 +645,11 @@ i386_linux_core_read_description (struct gdbarch *gdbarch, | ||
642 | 645 | { |
643 | 646 | /* Linux/i386. */ |
644 | 647 | uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd); |
645 | - switch ((xcr0 & I386_XSTATE_AVX_MASK)) | |
648 | + | |
649 | + switch ((xcr0 & I386_XSTATE_ALL_MASK)) | |
646 | 650 | { |
651 | + case I386_XSTATE_MPX_MASK: | |
652 | + return tdesc_i386_mpx_linux; | |
647 | 653 | case I386_XSTATE_AVX_MASK: |
648 | 654 | return tdesc_i386_avx_linux; |
649 | 655 | case I386_XSTATE_SSE_MASK: |
@@ -979,4 +985,5 @@ _initialize_i386_linux_tdep (void) | ||
979 | 985 | initialize_tdesc_i386_linux (); |
980 | 986 | initialize_tdesc_i386_mmx_linux (); |
981 | 987 | initialize_tdesc_i386_avx_linux (); |
988 | + initialize_tdesc_i386_mpx_linux (); | |
982 | 989 | } |
@@ -29,7 +29,7 @@ | ||
29 | 29 | /* Register number for the "orig_eax" pseudo-register. If this |
30 | 30 | pseudo-register contains a value >= 0 it is interpreted as the |
31 | 31 | system call number that the kernel is supposed to restart. */ |
32 | -#define I386_LINUX_ORIG_EAX_REGNUM I386_AVX_NUM_REGS | |
32 | +#define I386_LINUX_ORIG_EAX_REGNUM I386_MPX_NUM_REGS | |
33 | 33 | |
34 | 34 | /* Total number of registers for GNU/Linux. */ |
35 | 35 | #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); | ||
41 | 41 | extern struct target_desc *tdesc_i386_linux; |
42 | 42 | extern struct target_desc *tdesc_i386_mmx_linux; |
43 | 43 | extern struct target_desc *tdesc_i386_avx_linux; |
44 | +extern struct target_desc *tdesc_i386_mpx_linux; | |
44 | 45 | |
45 | 46 | /* Format of XSAVE extended state is: |
46 | 47 | struct |
@@ -49,6 +50,7 @@ extern struct target_desc *tdesc_i386_avx_linux; | ||
49 | 50 | sw_usable_bytes[464..511] |
50 | 51 | xstate_hdr_bytes[512..575] |
51 | 52 | avx_bytes[576..831] |
53 | + mpx_bytes [960..1032] | |
52 | 54 | future_state etc |
53 | 55 | }; |
54 | 56 |
@@ -57,6 +57,7 @@ | ||
57 | 57 | |
58 | 58 | #include "features/i386/i386.c" |
59 | 59 | #include "features/i386/i386-avx.c" |
60 | +#include "features/i386/i386-mpx.c" | |
60 | 61 | #include "features/i386/i386-mmx.c" |
61 | 62 | |
62 | 63 | #include "ax.h" |
@@ -98,6 +99,18 @@ static const char *i386_ymmh_names[] = | ||
98 | 99 | "ymm4h", "ymm5h", "ymm6h", "ymm7h", |
99 | 100 | }; |
100 | 101 | |
102 | +static const char *i386_mpx_names[] = | |
103 | +{ | |
104 | + "bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus" | |
105 | +}; | |
106 | + | |
107 | +/* Register names for MPX pseudo-registers. */ | |
108 | + | |
109 | +static const char *i386_bnd_names[] = | |
110 | +{ | |
111 | + "bnd0", "bnd1", "bnd2", "bnd3" | |
112 | +}; | |
113 | + | |
101 | 114 | /* Register names for MMX pseudo-registers. */ |
102 | 115 | |
103 | 116 | static const char *i386_mmx_names[] = |
@@ -202,6 +215,21 @@ i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum) | ||
202 | 215 | return regnum >= 0 && regnum < tdep->num_ymm_regs; |
203 | 216 | } |
204 | 217 | |
218 | +/* BND register? */ | |
219 | + | |
220 | +int | |
221 | +i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum) | |
222 | +{ | |
223 | + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
224 | + int bnd0_regnum = tdep->bnd0_regnum; | |
225 | + | |
226 | + if (bnd0_regnum < 0) | |
227 | + return 0; | |
228 | + | |
229 | + regnum -= bnd0_regnum; | |
230 | + return regnum >= 0 && regnum < I387_NUM_BND_REGS; | |
231 | +} | |
232 | + | |
205 | 233 | /* SSE register? */ |
206 | 234 | |
207 | 235 | int |
@@ -254,6 +282,34 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum) | ||
254 | 282 | && regnum < I387_XMM0_REGNUM (tdep)); |
255 | 283 | } |
256 | 284 | |
285 | +/* BNDr (raw) register? */ | |
286 | + | |
287 | +static int | |
288 | +i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum) | |
289 | +{ | |
290 | + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
291 | + | |
292 | + if (I387_BND0R_REGNUM (tdep) < 0) | |
293 | + return 0; | |
294 | + | |
295 | + regnum -= tdep->bnd0r_regnum; | |
296 | + return regnum >= 0 && regnum < I387_NUM_BND_REGS; | |
297 | +} | |
298 | + | |
299 | +/* BND control register? */ | |
300 | + | |
301 | +static int | |
302 | +i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum) | |
303 | +{ | |
304 | + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
305 | + | |
306 | + if (I387_BNDCFGU_REGNUM (tdep) < 0) | |
307 | + return 0; | |
308 | + | |
309 | + regnum -= I387_BNDCFGU_REGNUM (tdep); | |
310 | + return regnum >= 0 && regnum < I387_NUM_MPX_CTRL_REGS; | |
311 | +} | |
312 | + | |
257 | 313 | /* Return the name of register REGNUM, or the empty string if it is |
258 | 314 | an anonymous register. */ |
259 | 315 |
@@ -273,6 +329,8 @@ const char * | ||
273 | 329 | i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum) |
274 | 330 | { |
275 | 331 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
332 | + if (i386_bnd_regnum_p (gdbarch, regnum)) | |
333 | + return i386_bnd_names[regnum - tdep->bnd0_regnum]; | |
276 | 334 | if (i386_mmx_regnum_p (gdbarch, regnum)) |
277 | 335 | return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)]; |
278 | 336 | else if (i386_ymm_regnum_p (gdbarch, regnum)) |
@@ -2750,6 +2808,43 @@ i387_ext_type (struct gdbarch *gdbarch) | ||
2750 | 2808 | return tdep->i387_ext_type; |
2751 | 2809 | } |
2752 | 2810 | |
2811 | +/* Construct type for pseudo BND registers. We can't use | |
2812 | + tdesc_find_type since a complement of one value has to be used | |
2813 | + to describe the upper bound. */ | |
2814 | + | |
2815 | +static struct type * | |
2816 | +i386_bnd_type (struct gdbarch *gdbarch) | |
2817 | +{ | |
2818 | + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
2819 | + | |
2820 | + | |
2821 | + if (!tdep->i386_bnd_type) | |
2822 | + { | |
2823 | + struct type *t, *bound_t; | |
2824 | + const struct builtin_type *bt = builtin_type (gdbarch); | |
2825 | + | |
2826 | + /* The type we're building is described bellow: */ | |
2827 | +#if 0 | |
2828 | + struct __bound128 | |
2829 | + { | |
2830 | + void *lbound; | |
2831 | + void *ubound; /* One complement of raw ubound field. */ | |
2832 | + }; | |
2833 | +#endif | |
2834 | + | |
2835 | + t = arch_composite_type (gdbarch, | |
2836 | + "__gdb_builtin_type_bound128", TYPE_CODE_STRUCT); | |
2837 | + | |
2838 | + append_composite_type_field (t, "lbound", bt->builtin_data_ptr); | |
2839 | + append_composite_type_field (t, "ubound", bt->builtin_data_ptr); | |
2840 | + | |
2841 | + TYPE_NAME (t) = "builtin_type_bound128"; | |
2842 | + tdep->i386_bnd_type = t; | |
2843 | + } | |
2844 | + | |
2845 | + return tdep->i386_bnd_type; | |
2846 | +} | |
2847 | + | |
2753 | 2848 | /* Construct vector type for pseudo YMM registers. We can't use |
2754 | 2849 | tdesc_find_type since YMM isn't described in target description. */ |
2755 | 2850 |
@@ -2851,6 +2946,8 @@ i386_mmx_type (struct gdbarch *gdbarch) | ||
2851 | 2946 | struct type * |
2852 | 2947 | i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum) |
2853 | 2948 | { |
2949 | + if (i386_bnd_regnum_p (gdbarch, regnum)) | |
2950 | + return i386_bnd_type (gdbarch); | |
2854 | 2951 | if (i386_mmx_regnum_p (gdbarch, regnum)) |
2855 | 2952 | return i386_mmx_type (gdbarch); |
2856 | 2953 | else if (i386_ymm_regnum_p (gdbarch, regnum)) |
@@ -2917,8 +3014,31 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch, | ||
2917 | 3014 | else |
2918 | 3015 | { |
2919 | 3016 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
3017 | + if (i386_bnd_regnum_p (gdbarch, regnum)) | |
3018 | + { | |
3019 | + regnum -= tdep->bnd0_regnum; | |
2920 | 3020 | |
2921 | - if (i386_ymm_regnum_p (gdbarch, regnum)) | |
3021 | + /* Extract (always little endian). Read lower 128bits. */ | |
3022 | + status = regcache_raw_read (regcache, | |
3023 | + I387_BND0R_REGNUM (tdep) + regnum, | |
3024 | + raw_buf); | |
3025 | + if (status != REG_VALID) | |
3026 | + mark_value_bytes_unavailable (result_value, 0, 16); | |
3027 | + else | |
3028 | + { | |
3029 | + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); | |
3030 | + LONGEST upper, lower; | |
3031 | + int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr); | |
3032 | + | |
3033 | + lower = extract_unsigned_integer (raw_buf, 8, byte_order); | |
3034 | + upper = extract_unsigned_integer (raw_buf + 8, 8, byte_order); | |
3035 | + upper = ~upper; | |
3036 | + | |
3037 | + memcpy (buf, &lower, size); | |
3038 | + memcpy (buf + size, &upper, size); | |
3039 | + } | |
3040 | + } | |
3041 | + else if (i386_ymm_regnum_p (gdbarch, regnum)) | |
2922 | 3042 | { |
2923 | 3043 | regnum -= tdep->ymm0_regnum; |
2924 | 3044 |
@@ -3011,7 +3131,34 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, | ||
3011 | 3131 | { |
3012 | 3132 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
3013 | 3133 | |
3014 | - if (i386_ymm_regnum_p (gdbarch, regnum)) | |
3134 | + if (i386_bnd_regnum_p (gdbarch, regnum)) | |
3135 | + { | |
3136 | + ULONGEST upper, lower; | |
3137 | + int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr); | |
3138 | + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); | |
3139 | + | |
3140 | + /* New values from input value. */ | |
3141 | + regnum -= tdep->bnd0_regnum; | |
3142 | + lower = extract_unsigned_integer (buf, size, byte_order); | |
3143 | + upper = extract_unsigned_integer (buf + size, size, byte_order); | |
3144 | + | |
3145 | + /* Fetching register buffer. */ | |
3146 | + regcache_raw_read (regcache, | |
3147 | + I387_BND0R_REGNUM (tdep) + regnum, | |
3148 | + raw_buf); | |
3149 | + | |
3150 | + upper = ~upper; | |
3151 | + | |
3152 | + /* Set register bits. */ | |
3153 | + memcpy (raw_buf, &lower, 8); | |
3154 | + memcpy (raw_buf + 8, &upper, 8); | |
3155 | + | |
3156 | + | |
3157 | + regcache_raw_write (regcache, | |
3158 | + I387_BND0R_REGNUM (tdep) + regnum, | |
3159 | + raw_buf); | |
3160 | + } | |
3161 | + else if (i386_ymm_regnum_p (gdbarch, regnum)) | |
3015 | 3162 | { |
3016 | 3163 | regnum -= tdep->ymm0_regnum; |
3017 | 3164 |
@@ -3866,7 +4013,8 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | ||
3866 | 4013 | { |
3867 | 4014 | const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
3868 | 4015 | int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p, |
3869 | - ymm_regnum_p, ymmh_regnum_p; | |
4016 | + ymm_regnum_p, ymmh_regnum_p, bndr_regnum_p, bnd_regnum_p, | |
4017 | + mpx_ctrl_regnum_p; | |
3870 | 4018 | |
3871 | 4019 | /* Don't include pseudo registers, except for MMX, in any register |
3872 | 4020 | groups. */ |
@@ -3911,13 +4059,31 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | ||
3911 | 4059 | || ymmh_regnum_p)) |
3912 | 4060 | return 0; |
3913 | 4061 | |
4062 | + bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum); | |
4063 | + if (group == all_reggroup | |
4064 | + && ((bnd_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) | |
4065 | + return bnd_regnum_p; | |
4066 | + | |
4067 | + bndr_regnum_p = i386_bndr_regnum_p (gdbarch, regnum); | |
4068 | + if (group == all_reggroup | |
4069 | + && ((bndr_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) | |
4070 | + return 0; | |
4071 | + | |
4072 | + mpx_ctrl_regnum_p = i386_mpx_ctrl_regnum_p (gdbarch, regnum); | |
4073 | + if (group == all_reggroup | |
4074 | + && ((mpx_ctrl_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) | |
4075 | + return mpx_ctrl_regnum_p; | |
4076 | + | |
3914 | 4077 | if (group == general_reggroup) |
3915 | 4078 | return (!fp_regnum_p |
3916 | 4079 | && !mmx_regnum_p |
3917 | 4080 | && !mxcsr_regnum_p |
3918 | 4081 | && !xmm_regnum_p |
3919 | 4082 | && !ymm_regnum_p |
3920 | - && !ymmh_regnum_p); | |
4083 | + && !ymmh_regnum_p | |
4084 | + && !bndr_regnum_p | |
4085 | + && !bnd_regnum_p | |
4086 | + && !mpx_ctrl_regnum_p); | |
3921 | 4087 | |
3922 | 4088 | return default_register_reggroup_p (gdbarch, regnum, group); |
3923 | 4089 | } |
@@ -7496,7 +7662,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, | ||
7496 | 7662 | { |
7497 | 7663 | const struct target_desc *tdesc = tdep->tdesc; |
7498 | 7664 | const struct tdesc_feature *feature_core; |
7499 | - const struct tdesc_feature *feature_sse, *feature_avx; | |
7665 | + const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx; | |
7500 | 7666 | int i, num_regs, valid_p; |
7501 | 7667 | |
7502 | 7668 | if (! tdesc_has_registers (tdesc)) |
@@ -7513,6 +7679,9 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, | ||
7513 | 7679 | /* Try AVX registers. */ |
7514 | 7680 | feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx"); |
7515 | 7681 | |
7682 | + /* Try MPX registers. */ | |
7683 | + feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx"); | |
7684 | + | |
7516 | 7685 | valid_p = 1; |
7517 | 7686 | |
7518 | 7687 | /* The XCR0 bits. */ |
@@ -7559,6 +7728,23 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, | ||
7559 | 7728 | tdep->register_names[i]); |
7560 | 7729 | } |
7561 | 7730 | |
7731 | + if (feature_mpx) | |
7732 | + { | |
7733 | + tdep->xcr0 = I386_XSTATE_MPX_MASK; | |
7734 | + | |
7735 | + if (tdep->bnd0r_regnum < 0) | |
7736 | + { | |
7737 | + tdep->mpx_register_names = i386_mpx_names; | |
7738 | + tdep->bnd0r_regnum = I386_BND0R_REGNUM; | |
7739 | + tdep->bndcfgu_regnum = I386_BNDCFGU_REGNUM; | |
7740 | + } | |
7741 | + | |
7742 | + for (i = 0; i < I387_NUM_MPX_REGS; i++) | |
7743 | + valid_p &= tdesc_numbered_register (feature_mpx, tdesc_data, | |
7744 | + I387_BND0R_REGNUM (tdep) + i, | |
7745 | + tdep->mpx_register_names[i]); | |
7746 | + } | |
7747 | + | |
7562 | 7748 | return valid_p; |
7563 | 7749 | } |
7564 | 7750 |
@@ -7572,6 +7758,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
7572 | 7758 | const struct target_desc *tdesc; |
7573 | 7759 | int mm0_regnum; |
7574 | 7760 | int ymm0_regnum; |
7761 | + int bnd0_regnum; | |
7762 | + int num_bnd_cooked; | |
7575 | 7763 | |
7576 | 7764 | /* If there is already a candidate, use it. */ |
7577 | 7765 | arches = gdbarch_list_lookup_by_info (arches, &info); |
@@ -7745,8 +7933,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
7745 | 7933 | |
7746 | 7934 | /* Even though the default ABI only includes general-purpose registers, |
7747 | 7935 | floating-point registers and the SSE registers, we have to leave a |
7748 | - gap for the upper AVX registers. */ | |
7749 | - set_gdbarch_num_regs (gdbarch, I386_AVX_NUM_REGS); | |
7936 | + gap for the upper AVX registers and the MPX registers. */ | |
7937 | + set_gdbarch_num_regs (gdbarch, I386_MPX_NUM_REGS); | |
7750 | 7938 | |
7751 | 7939 | /* Get the x86 target description from INFO. */ |
7752 | 7940 | tdesc = info.target_desc; |
@@ -7767,6 +7955,10 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
7767 | 7955 | tdep->num_mmx_regs = 8; |
7768 | 7956 | tdep->num_ymm_regs = 0; |
7769 | 7957 | |
7958 | + /* No MPX registers. */ | |
7959 | + tdep->bnd0r_regnum = -1; | |
7960 | + tdep->bndcfgu_regnum = -1; | |
7961 | + | |
7770 | 7962 | tdesc_data = tdesc_data_alloc (); |
7771 | 7963 | |
7772 | 7964 | set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction); |
@@ -7785,13 +7977,16 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
7785 | 7977 | return NULL; |
7786 | 7978 | } |
7787 | 7979 | |
7980 | + num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0); | |
7981 | + | |
7788 | 7982 | /* Wire in pseudo registers. Number of pseudo registers may be |
7789 | 7983 | changed. */ |
7790 | 7984 | set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs |
7791 | 7985 | + tdep->num_word_regs |
7792 | 7986 | + tdep->num_dword_regs |
7793 | 7987 | + tdep->num_mmx_regs |
7794 | - + tdep->num_ymm_regs)); | |
7988 | + + tdep->num_ymm_regs | |
7989 | + + num_bnd_cooked)); | |
7795 | 7990 | |
7796 | 7991 | /* Target description may be changed. */ |
7797 | 7992 | tdesc = tdep->tdesc; |
@@ -7825,14 +8020,21 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
7825 | 8020 | else |
7826 | 8021 | tdep->ymm0_regnum = -1; |
7827 | 8022 | |
8023 | + bnd0_regnum = mm0_regnum; | |
7828 | 8024 | if (tdep->num_mmx_regs != 0) |
7829 | 8025 | { |
7830 | 8026 | /* Support MMX pseudo-register if MMX hasn't been disabled. */ |
7831 | 8027 | tdep->mm0_regnum = mm0_regnum; |
8028 | + bnd0_regnum += tdep->num_mmx_regs; | |
7832 | 8029 | } |
7833 | 8030 | else |
7834 | 8031 | tdep->mm0_regnum = -1; |
7835 | 8032 | |
8033 | + if (tdep->bnd0r_regnum > 0) | |
8034 | + tdep->bnd0_regnum = bnd0_regnum; | |
8035 | + else | |
8036 | + tdep-> bnd0_regnum = -1; | |
8037 | + | |
7836 | 8038 | /* Hook in the legacy prologue-based unwinders last (fallback). */ |
7837 | 8039 | frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind); |
7838 | 8040 | frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind); |
@@ -7910,6 +8112,7 @@ is \"default\"."), | ||
7910 | 8112 | initialize_tdesc_i386 (); |
7911 | 8113 | initialize_tdesc_i386_mmx (); |
7912 | 8114 | initialize_tdesc_i386_avx (); |
8115 | + initialize_tdesc_i386_mpx (); | |
7913 | 8116 | |
7914 | 8117 | /* Tell remote stub that we support XML target description. */ |
7915 | 8118 | register_remote_support_xml ("i386"); |
@@ -130,6 +130,21 @@ struct gdbarch_tdep | ||
130 | 130 | /* Upper YMM register names. Only used for tdesc_numbered_register. */ |
131 | 131 | const char **ymmh_register_names; |
132 | 132 | |
133 | + /* Register number for %bnd0r. Set this to -1 to indicate the absence | |
134 | + bound registers. */ | |
135 | + int bnd0r_regnum; | |
136 | + | |
137 | + /* Register number for pseudo register %bnd0. Set this to -1 to indicate the absence | |
138 | + bound registers. */ | |
139 | + int bnd0_regnum; | |
140 | + | |
141 | + /* Register number for %bndcfgu. Set this to -1 to indicate the absence | |
142 | + bound control registers. */ | |
143 | + int bndcfgu_regnum; | |
144 | + | |
145 | + /* MPX register names. Only used for tdesc_numbered_register. */ | |
146 | + const char **mpx_register_names; | |
147 | + | |
133 | 148 | /* Target description. */ |
134 | 149 | const struct target_desc *tdesc; |
135 | 150 |
@@ -165,6 +180,7 @@ struct gdbarch_tdep | ||
165 | 180 | struct type *i386_mmx_type; |
166 | 181 | struct type *i386_ymm_type; |
167 | 182 | struct type *i387_ext_type; |
183 | + struct type *i386_bnd_type; | |
168 | 184 | |
169 | 185 | /* Process record/replay target. */ |
170 | 186 | /* The map for registers because the AMD64's registers order |
@@ -212,7 +228,11 @@ enum i386_regnum | ||
212 | 228 | I386_ST0_REGNUM, /* %st(0) */ |
213 | 229 | I386_MXCSR_REGNUM = 40, /* %mxcsr */ |
214 | 230 | I386_YMM0H_REGNUM, /* %ymm0h */ |
215 | - I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7 | |
231 | + I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7, | |
232 | + I386_BND0R_REGNUM, | |
233 | + I386_BND3R_REGNUM = I386_BND0R_REGNUM + 3, | |
234 | + I386_BNDCFGU_REGNUM, | |
235 | + I386_BNDSTATUS_REGNUM | |
216 | 236 | }; |
217 | 237 | |
218 | 238 | /* Register numbers of RECORD_REGMAP. */ |
@@ -250,6 +270,7 @@ enum record_i386_regnum | ||
250 | 270 | |
251 | 271 | #define I386_SSE_NUM_REGS (I386_MXCSR_REGNUM + 1) |
252 | 272 | #define I386_AVX_NUM_REGS (I386_YMM7H_REGNUM + 1) |
273 | +#define I386_MPX_NUM_REGS (I386_BNDSTATUS_REGNUM + 1) | |
253 | 274 | |
254 | 275 | /* Size of the largest register. */ |
255 | 276 | #define I386_MAX_REGISTER_SIZE 16 |
@@ -263,6 +284,7 @@ extern int i386_word_regnum_p (struct gdbarch *gdbarch, int regnum); | ||
263 | 284 | extern int i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum); |
264 | 285 | extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum); |
265 | 286 | extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum); |
287 | +extern int i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum); | |
266 | 288 | |
267 | 289 | extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch, |
268 | 290 | int regnum); |
@@ -763,9 +763,22 @@ static int xsave_avxh_offset[] = | ||
763 | 763 | 576 + 15 * 16 /* Upper 128bit of ... %ymm15 (128 bits each). */ |
764 | 764 | }; |
765 | 765 | |
766 | +static int xsave_mpx_offset[] = | |
767 | +{ | |
768 | + 960 + 0 * 16, /* bnd0r...bnd3r registers. */ | |
769 | + 960 + 1 * 16, | |
770 | + 960 + 2 * 16, | |
771 | + 960 + 3 * 16, | |
772 | + 1024 + 0 * 8, /* bndcfg ... bndstatus. */ | |
773 | + 1024 + 1 * 8, | |
774 | +}; | |
775 | + | |
766 | 776 | #define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \ |
767 | 777 | (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)]) |
768 | 778 | |
779 | +#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \ | |
780 | + (xsave + xsave_mpx_offset[regnum - I387_BND0R_REGNUM (tdep)]) | |
781 | + | |
769 | 782 | /* Similar to i387_supply_fxsave, but use XSAVE extended state. */ |
770 | 783 | |
771 | 784 | void |
@@ -783,7 +796,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum, | ||
783 | 796 | x87 = 0x1, |
784 | 797 | sse = 0x2, |
785 | 798 | avxh = 0x4, |
786 | - all = x87 | sse | avxh | |
799 | + mpx = 0x8, | |
800 | + all = x87 | sse | avxh | mpx | |
787 | 801 | } regclass; |
788 | 802 | |
789 | 803 | gdb_assert (regs != NULL); |
@@ -795,6 +809,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, | ||
795 | 809 | else if (regnum >= I387_YMM0H_REGNUM (tdep) |
796 | 810 | && regnum < I387_YMMENDH_REGNUM (tdep)) |
797 | 811 | regclass = avxh; |
812 | + else if (regnum >= I387_BND0R_REGNUM (tdep) | |
813 | + && regnum < I387_MPXEND_REGNUM (tdep)) | |
814 | + regclass = mpx; | |
798 | 815 | else if (regnum >= I387_XMM0_REGNUM(tdep) |
799 | 816 | && regnum < I387_MXCSR_REGNUM (tdep)) |
800 | 817 | regclass = sse; |
@@ -814,7 +831,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, | ||
814 | 831 | clear_bv = (~(*xstate_bv_p)) & tdep->xcr0; |
815 | 832 | } |
816 | 833 | else |
817 | - clear_bv = I386_XSTATE_AVX_MASK; | |
834 | + clear_bv = I386_XSTATE_ALL_MASK; | |
818 | 835 | |
819 | 836 | /* With the delayed xsave mechanism, in between the program |
820 | 837 | starting, and the program accessing the vector registers for the |
@@ -838,6 +855,14 @@ i387_supply_xsave (struct regcache *regcache, int regnum, | ||
838 | 855 | XSAVE_AVXH_ADDR (tdep, regs, regnum)); |
839 | 856 | return; |
840 | 857 | |
858 | + case mpx: | |
859 | + if ((clear_bv & I386_XSTATE_BNDREGS)) | |
860 | + regcache_raw_supply (regcache, regnum, zero); | |
861 | + else | |
862 | + regcache_raw_supply (regcache, regnum, | |
863 | + XSAVE_MPX_ADDR (tdep, regs, regnum)); | |
864 | + return; | |
865 | + | |
841 | 866 | case sse: |
842 | 867 | if ((clear_bv & I386_XSTATE_SSE)) |
843 | 868 | regcache_raw_supply (regcache, regnum, zero); |
@@ -875,6 +900,42 @@ i387_supply_xsave (struct regcache *regcache, int regnum, | ||
875 | 900 | } |
876 | 901 | } |
877 | 902 | |
903 | + /* Handle the MPX registers. */ | |
904 | + if ((tdep->xcr0 & I386_XSTATE_BNDREGS)) | |
905 | + { | |
906 | + if (clear_bv & I386_XSTATE_BNDREGS) | |
907 | + { | |
908 | + for (i = I387_BND0R_REGNUM (tdep); | |
909 | + i < I387_BNDCFGU_REGNUM (tdep); i++) | |
910 | + regcache_raw_supply (regcache, i, zero); | |
911 | + } | |
912 | + else | |
913 | + { | |
914 | + for (i = I387_BND0R_REGNUM (tdep); | |
915 | + i < I387_BNDCFGU_REGNUM (tdep); i++) | |
916 | + regcache_raw_supply (regcache, i, | |
917 | + XSAVE_MPX_ADDR (tdep, regs, i)); | |
918 | + } | |
919 | + } | |
920 | + | |
921 | + /* Handle the MPX registers. */ | |
922 | + if ((tdep->xcr0 & I386_XSTATE_BNDCFG)) | |
923 | + { | |
924 | + if (clear_bv & I386_XSTATE_BNDCFG) | |
925 | + { | |
926 | + for (i = I387_BNDCFGU_REGNUM (tdep); | |
927 | + i < I387_MPXEND_REGNUM (tdep); i++) | |
928 | + regcache_raw_supply (regcache, i, zero); | |
929 | + } | |
930 | + else | |
931 | + { | |
932 | + for (i = I387_BNDCFGU_REGNUM (tdep); | |
933 | + i < I387_MPXEND_REGNUM (tdep); i++) | |
934 | + regcache_raw_supply (regcache, i, | |
935 | + XSAVE_MPX_ADDR (tdep, regs, i)); | |
936 | + } | |
937 | + } | |
938 | + | |
878 | 939 | /* Handle the XMM registers. */ |
879 | 940 | if ((tdep->xcr0 & I386_XSTATE_SSE)) |
880 | 941 | { |
@@ -989,7 +1050,8 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
989 | 1050 | x87 = 0x2 | check, |
990 | 1051 | sse = 0x4 | check, |
991 | 1052 | avxh = 0x8 | check, |
992 | - all = x87 | sse | avxh | |
1053 | + mpx = 0x10 | check, | |
1054 | + all = x87 | sse | avxh | mpx | |
993 | 1055 | } regclass; |
994 | 1056 | |
995 | 1057 | gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); |
@@ -1000,7 +1062,10 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
1000 | 1062 | else if (regnum >= I387_YMM0H_REGNUM (tdep) |
1001 | 1063 | && regnum < I387_YMMENDH_REGNUM (tdep)) |
1002 | 1064 | regclass = avxh; |
1003 | - else if (regnum >= I387_XMM0_REGNUM(tdep) | |
1065 | + else if (regnum >= I387_BND0R_REGNUM (tdep) | |
1066 | + && regnum < I387_MPXEND_REGNUM (tdep)) | |
1067 | + regclass = mpx; | |
1068 | + else if (regnum >= I387_XMM0_REGNUM (tdep) | |
1004 | 1069 | && regnum < I387_MXCSR_REGNUM (tdep)) |
1005 | 1070 | regclass = sse; |
1006 | 1071 | else if (regnum >= I387_ST0_REGNUM (tdep) |
@@ -1032,6 +1097,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
1032 | 1097 | /* Clear register set if its bit in xstat_bv is zero. */ |
1033 | 1098 | if (clear_bv) |
1034 | 1099 | { |
1100 | + if ((clear_bv & I386_XSTATE_BNDREGS)) | |
1101 | + for (i = I387_BND0R_REGNUM (tdep); | |
1102 | + i < I387_BNDCFGU_REGNUM (tdep); i++) | |
1103 | + memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16); | |
1104 | + | |
1105 | + if ((clear_bv & I386_XSTATE_BNDCFG)) | |
1106 | + for (i = I387_BNDCFGU_REGNUM (tdep); | |
1107 | + i < I387_MPXEND_REGNUM (tdep); i++) | |
1108 | + memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8); | |
1109 | + | |
1035 | 1110 | if ((clear_bv & I386_XSTATE_AVX)) |
1036 | 1111 | for (i = I387_YMM0H_REGNUM (tdep); |
1037 | 1112 | i < I387_YMMENDH_REGNUM (tdep); i++) |
@@ -1063,6 +1138,33 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
1063 | 1138 | memcpy (p, raw, 16); |
1064 | 1139 | } |
1065 | 1140 | } |
1141 | + /* Check if any upper MPX registers are changed. */ | |
1142 | + if ((tdep->xcr0 & I386_XSTATE_BNDREGS)) | |
1143 | + for (i = I387_BND0R_REGNUM (tdep); | |
1144 | + i < I387_BNDCFGU_REGNUM (tdep); i++) | |
1145 | + { | |
1146 | + regcache_raw_collect (regcache, i, raw); | |
1147 | + p = XSAVE_MPX_ADDR (tdep, regs, i); | |
1148 | + if (memcmp (raw, p, 16)) | |
1149 | + { | |
1150 | + xstate_bv |= I386_XSTATE_BNDREGS; | |
1151 | + memcpy (p, raw, 16); | |
1152 | + } | |
1153 | + } | |
1154 | + | |
1155 | + /* Check if any upper MPX registers are changed. */ | |
1156 | + if ((tdep->xcr0 & I386_XSTATE_BNDCFG)) | |
1157 | + for (i = I387_BNDCFGU_REGNUM (tdep); | |
1158 | + i < I387_MPXEND_REGNUM (tdep); i++) | |
1159 | + { | |
1160 | + regcache_raw_collect (regcache, i, raw); | |
1161 | + p = XSAVE_MPX_ADDR (tdep, regs, i); | |
1162 | + if (memcmp (raw, p, 8)) | |
1163 | + { | |
1164 | + xstate_bv |= I386_XSTATE_BNDCFG; | |
1165 | + memcpy (p, raw, 8); | |
1166 | + } | |
1167 | + } | |
1066 | 1168 | |
1067 | 1169 | /* Check if any SSE registers are changed. */ |
1068 | 1170 | if ((tdep->xcr0 & I386_XSTATE_SSE)) |
@@ -1113,6 +1215,25 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
1113 | 1215 | } |
1114 | 1216 | break; |
1115 | 1217 | |
1218 | + case mpx: | |
1219 | + if (regnum < I387_BNDCFGU_REGNUM (tdep)) | |
1220 | + { | |
1221 | + regcache_raw_collect (regcache, regnum, raw); | |
1222 | + p = XSAVE_MPX_ADDR (tdep, regs, regnum); | |
1223 | + if (memcmp (raw, p, 16)) | |
1224 | + { | |
1225 | + xstate_bv |= I386_XSTATE_BNDREGS; | |
1226 | + memcpy (p, raw, 16); | |
1227 | + } | |
1228 | + } | |
1229 | + else | |
1230 | + { | |
1231 | + p = XSAVE_MPX_ADDR (tdep, regs, regnum); | |
1232 | + xstate_bv |= I386_XSTATE_BNDCFG; | |
1233 | + memcpy (p, raw, 8); | |
1234 | + } | |
1235 | + break; | |
1236 | + | |
1116 | 1237 | case sse: |
1117 | 1238 | /* This is an SSE register. */ |
1118 | 1239 | p = FXSAVE_ADDR (tdep, regs, regnum); |
@@ -1154,6 +1275,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, | ||
1154 | 1275 | case x87: |
1155 | 1276 | case sse: |
1156 | 1277 | case avxh: |
1278 | + case mpx: | |
1157 | 1279 | /* Register REGNUM has been updated. Return. */ |
1158 | 1280 | return; |
1159 | 1281 | } |
@@ -34,6 +34,13 @@ struct ui_file; | ||
34 | 34 | #define I387_MM0_REGNUM(tdep) ((tdep)->mm0_regnum) |
35 | 35 | #define I387_NUM_YMM_REGS(tdep) ((tdep)->num_ymm_regs) |
36 | 36 | #define I387_YMM0H_REGNUM(tdep) ((tdep)->ymm0h_regnum) |
37 | +#define I387_BND0R_REGNUM(tdep) ((tdep)->bnd0r_regnum) | |
38 | +#define I387_BNDCFGU_REGNUM(tdep) ((tdep)->bndcfgu_regnum) | |
39 | + | |
40 | +/* Set of constants used for 32 and 64-bit. */ | |
41 | +#define I387_NUM_MPX_REGS 6 | |
42 | +#define I387_NUM_BND_REGS 4 | |
43 | +#define I387_NUM_MPX_CTRL_REGS 2 | |
37 | 44 | |
38 | 45 | #define I387_FCTRL_REGNUM(tdep) (I387_ST0_REGNUM (tdep) + 8) |
39 | 46 | #define I387_FSTAT_REGNUM(tdep) (I387_FCTRL_REGNUM (tdep) + 1) |
@@ -48,6 +55,8 @@ struct ui_file; | ||
48 | 55 | (I387_XMM0_REGNUM (tdep) + I387_NUM_XMM_REGS (tdep)) |
49 | 56 | #define I387_YMMENDH_REGNUM(tdep) \ |
50 | 57 | (I387_YMM0H_REGNUM (tdep) + I387_NUM_YMM_REGS (tdep)) |
58 | +#define I387_MPXEND_REGNUM(tdep) \ | |
59 | + (I387_BND0R_REGNUM (tdep) + I387_NUM_MPX_REGS) | |
51 | 60 | |
52 | 61 | /* Print out the i387 floating point state. */ |
53 | 62 |