From patchwork Wed Oct 10 15:12:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 29697 Received: (qmail 106711 invoked by alias); 10 Oct 2018 15:12:18 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 106695 invoked by uid 89); 10 Oct 2018 15:12:18 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=implication, 7th X-HELO: prv1-mh.provo.novell.com Received: from prv1-mh.provo.novell.com (HELO prv1-mh.provo.novell.com) (137.65.248.33) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 10 Oct 2018 15:12:16 +0000 Received: from INET-PRV1-MTA by prv1-mh.provo.novell.com with Novell_GroupWise; Wed, 10 Oct 2018 09:12:15 -0600 Message-Id: <5BBE16CC02000078001F07A1@prv1-mh.provo.novell.com> Date: Wed, 10 Oct 2018 09:12:12 -0600 From: "Jan Beulich" To: "GDB" Cc: "Markus T Metzger" , "Simon Marchi" Subject: [PATCH v2] x86-64: fix ZMM register state tracking References: <5B8FD8B302000078001E5940@prv1-mh.provo.novell.com> Mime-Version: 1.0 Content-Disposition: inline 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/ 2018-10-10 Jan Beulich * i387-tdep.c (i387_supply_xsave): Split handling of X86_XSTATE_ZMM_H and X86_XSTATE_ZMM. (i387_collect_xsave): Likewise. gdb/testsuite/ 2018-10-10 Simon Marchi * testsuite/gdb.arch/i386-avx512.c, testsuite/gdb.arch/i386-avx512.exp: Add 7th test. --- v2: Attach comments to zmm_endlo_regnum declarations. Add testcase provided by Simon. --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -924,6 +924,12 @@ i387_supply_xsave (struct regcache *regc 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 *regc 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 *regc } } - /* 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 *regc } } - /* 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 *regc } 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 regcach 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 regcach 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 regcach 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); --- 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; --- 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 ".. = \\{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 }" +}