From b5420128da08dc81d94b265e88083d172909ea25 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 8 Nov 2018 12:12:05 +0100 Subject: [PATCH] x86-64: fix ZMM register state tracking The three AVX512 state components are entirely independent - one being in its "init state" has no implication whatsoever on either of the other two. Fully separate X86_XSTATE_ZMM_H and X86_XSTATE_ZMM handling, to prevent upper halves of the upper 16 ZMM registers to display as if they were zero (when they aren't) after e.g. VZEROALL/VZEROUPPER. --- gdb/ChangeLog | 6 ++++ gdb/i387-tdep.c | 40 +++++++++++++++++--------- gdb/testsuite/ChangeLog | 5 ++++ gdb/testsuite/gdb.arch/i386-avx512.c | 7 +++++ gdb/testsuite/gdb.arch/i386-avx512.exp | 10 +++++++ 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 48baa3742f0..6c18be9a747 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2018-11-08 Jan Beulich + + * i387-tdep.c (i387_supply_xsave): Split handling of + X86_XSTATE_ZMM_H and X86_XSTATE_ZMM. + (i387_collect_xsave): Likewise. + 2018-11-08 Andrew Burgess * riscv-tdep.c (riscv_insn::decode): Update header comment. diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index d0f64adcbb0..5d7fe6d1681 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -924,6 +924,12 @@ i387_supply_xsave (struct regcache *regcache, int regnum, struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const gdb_byte *regs = (const gdb_byte *) xsave; int i; + /* In 64-bit mode the split between "low" and "high" ZMM registers is at + ZMM16. Outside of 64-bit mode there are no "high" ZMM registers at all. + Precalculate the number to be used for the split point, with the all + registers in the "low" portion outside of 64-bit mode. */ + unsigned int zmm_endlo_regnum = I387_ZMM0H_REGNUM (tdep) + + std::min (tdep->num_zmm_regs, 16); ULONGEST clear_bv; static const gdb_byte zero[I386_MAX_REGISTER_SIZE] = { 0 }; enum @@ -1002,7 +1008,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case avx512_zmm_h: - if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) + if ((clear_bv & (regnum < zmm_endlo_regnum ? X86_XSTATE_ZMM_H + : X86_XSTATE_ZMM))) regcache->raw_supply (regnum, zero); else regcache->raw_supply (regnum, @@ -1080,21 +1087,17 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } } - /* Handle the upper ZMM registers. */ - if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) + /* Handle the upper halves of the low 8/16 ZMM registers. */ + if ((tdep->xcr0 & X86_XSTATE_ZMM_H)) { - if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) + if ((clear_bv & X86_XSTATE_ZMM_H)) { - for (i = I387_ZMM0H_REGNUM (tdep); - i < I387_ZMMENDH_REGNUM (tdep); - i++) + for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++) regcache->raw_supply (i, zero); } else { - for (i = I387_ZMM0H_REGNUM (tdep); - i < I387_ZMMENDH_REGNUM (tdep); - i++) + for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++) regcache->raw_supply (i, XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i)); } @@ -1119,11 +1122,13 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } } - /* Handle the YMM_AVX512 registers. */ + /* Handle the upper 16 ZMM/YMM/XMM registers (if any). */ if ((tdep->xcr0 & X86_XSTATE_ZMM)) { if ((clear_bv & X86_XSTATE_ZMM)) { + for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++) + regcache->raw_supply (i, zero); for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); i++) @@ -1135,6 +1140,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } else { + for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++) + regcache->raw_supply (i, + XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i)); for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); i++) @@ -1341,6 +1349,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, gdb_byte raw[I386_MAX_REGISTER_SIZE]; ULONGEST initial_xstate_bv, clear_bv, xstate_bv = 0; unsigned int i; + /* See the comment in i387_supply_xsave(). */ + unsigned int zmm_endlo_regnum = I387_ZMM0H_REGNUM (tdep) + + std::min (tdep->num_zmm_regs, 16); enum { x87_ctrl_or_mxcsr = 0x1, @@ -1441,9 +1452,8 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, i < I387_MPXEND_REGNUM (tdep); i++) memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8); - if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) - for (i = I387_ZMM0H_REGNUM (tdep); - i < I387_ZMMENDH_REGNUM (tdep); i++) + if ((clear_bv & X86_XSTATE_ZMM_H)) + for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++) memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32); if ((clear_bv & X86_XSTATE_K)) @@ -1453,6 +1463,8 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if ((clear_bv & X86_XSTATE_ZMM)) { + for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++) + memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32); for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); i++) memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 01fc0dbadf0..e0bb8382aa9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-11-08 Jan Beulich + + * testsuite/gdb.arch/i386-avx512.c, + testsuite/gdb.arch/i386-avx512.exp: Add 7th test. + 2018-11-08 Andrew Burgess * gdb.arch/riscv-reg-aliases.exp: Handle targets without floating diff --git a/gdb/testsuite/gdb.arch/i386-avx512.c b/gdb/testsuite/gdb.arch/i386-avx512.c index 9349f09d62e..0e273362ef7 100644 --- a/gdb/testsuite/gdb.arch/i386-avx512.c +++ b/gdb/testsuite/gdb.arch/i386-avx512.c @@ -249,6 +249,13 @@ main (int argc, char **argv) move back to array and check values. */ move_zmm_data_to_memory (); asm ("nop"); /* sixth breakpoint here */ + + asm ("vpternlogd $0xff, %zmm0, %zmm0, %zmm0"); +#ifdef __x86_64__ + asm ("vpternlogd $0xff, %zmm0, %zmm0, %zmm16"); +#endif + asm ("vzeroupper"); + asm ("nop"); /* seventh breakpoint here */ } return 0; diff --git a/gdb/testsuite/gdb.arch/i386-avx512.exp b/gdb/testsuite/gdb.arch/i386-avx512.exp index cd15e05fd03..43fde12f257 100644 --- a/gdb/testsuite/gdb.arch/i386-avx512.exp +++ b/gdb/testsuite/gdb.arch/i386-avx512.exp @@ -174,3 +174,13 @@ for { set r 0 } { $r < $nr_regs } { incr r } { ".. = \\{f = \\{[expr $r + 30], [expr $r.125 + 30], [expr $r.25 + 20], [expr $r.375 + 20], [expr $r.5 + 10], [expr $r.625 + 10], [expr $r.75 + 10], [expr $r.875 + 10]\\}\\}.*" \ "check contents of zmm_data\[$r\] after writing XMM regs" } + +gdb_test "break [gdb_get_line_number "seventh breakpoint here"]" \ + "Breakpoint .* at .*i386-avx512.c.*" \ + "set seventh breakpoint in main" +gdb_continue_to_breakpoint "continue to seventh breakpoint in main" +gdb_test "print \$zmm0.v16_int32" "= {-1, -1, -1, -1, 0 }" + +if { $nr_regs >= 16 } { + gdb_test "print \$zmm16.v16_int32" "= {-1 }" +} -- 2.30.2