https://bugs.kde.org/show_bug.cgi?id=360035
Bug ID: 360035 Summary: POWER PC instruction bcdadd and bcdsubtract generate result with non-zero shadow bits Product: valgrind Version: 3.12 SVN Platform: Other OS: Linux Status: UNCONFIRMED Severity: normal Priority: NOR Component: vex Assignee: jsew...@acm.org Reporter: c...@us.ibm.com The Power BCD ADD and BCD SUB instructions generate a result with shadow bits set. This then results in valgrind generating a message: ==8979== Use of uninitialised value of size 8 ==8979== at 0x40F8BD8: _itoa_word (_itoa.c:180) ==8979== by 0x40FB05B: vfprintf@@GLIBC_2.17 (vfprintf.c:1641) ==8979== by 0x1000084F: main (test_vector_misc.c:83 The shadow bits for both of the source operands are all zeros. The vbits should all be set to zero as a result of executing the instruction, However, two of the 128 shadow bits are set to 1 causing Valgrind to generate the above error message. The gdb interface to print the contents of the Power VR registers and its shadow bits doesn't work. See bugzilla 360008. If you edit coregrind/m_gdbserver/valgrind-low-ppc64.c to put in debug prints that show the contents of the VSR32 and VSR33 as follows: case 72: *mod = False; break; // GDBTD???? VEX { "trap", 4512, 64 }, case 73: VG_(transfer) (&ppc64->guest_VSR32, buf, dir, size, mod); VG_(printf)("\nCARLL, VSR32 = 0x%x %x %x %x\n", ppc64->guest_VSR32[3], ppc64->guest_VSR32[2], ppc64->guest_VSR32[1], ppc64->guest_VSR32[0]); break; case 74: VG_(transfer) (&ppc64->guest_VSR33, buf, dir, size, mod); VG_(printf)("CARLL, VSR33 = 0x%x %x %x %x\n", ppc64->guest_VSR33[3], ppc64->guest_VSR33[2], ppc64->guest_VSR33[1], ppc64->guest_VSR33[0]); break; You can see the correct values in the registers. The P9/Tests/test_vector_convert test case demonstrates this. Run the test case under valgrind with the option --vgdb-shadow-registers=yes to display the register and shadow register contents. The command is: valgrind --vex-iropt-register-updates=allregs-at-each-insn --vgdb=yes --vgdb-error=0 --vgdb-shadow-registers=yes ./test_vector_misc Stop at function test_vector_convert. Put gdb into assembly mode with the command "layout asm". Do stepi to get to the bcdadd instruction. 0x10000894 <test_vector_convert+28> nop │0x10000898 <test_vector_convert+32> addi r9,r2,-32624 │0x1000089c <test_vector_convert+36> lxvd2x vs0,0,r9 │0x100008a0 <test_vector_convert+40> xxswapd vs0,vs0 │0x100008a4 <test_vector_convert+44> nop │0x100008a8 <test_vector_convert+48> addi r9,r2,-32560 │0x100008ac <test_vector_convert+52> lxvd2x vs12,0,r9 │0x100008b0 <test_vector_convert+56> xxswapd vs12,vs12 │0x100008b4 <test_vector_convert+60> xxlor vs32,vs0,vs0 │0x100008b8 <test_vector_convert+64> xxlor vs33,vs12,vs12 │0x100008bc <test_vector_convert+68> bcdadd. v0,v0,v1,0 │0x100008c0 <test_vector_convert+72> xxlor vs0,vs32,vs32 Note, the Power VS register 0 to 31 map to the VSR32 to VSR64 registers. The floating point registers to the upper 64-bits of the VSR0 to VSR31 registers. The instruction is using vr0 and vr1 which correspond to VSR32 and VSR33. When you stop at the bcdadd instruction the register contents are: register contents CARLL, VSR32 = 0xa0 0 0 8 CARLL, VSR33 = 0x0 99999999 99999999 9999959c shadow s1 CARLL, VSR32 = 0x0 0 0 0 CARLL, VSR33 = 0x0 0 0 0 shadow s2 CARLL, VSR32 = 0x0 0 0 0 CARLL, VSR33 = 0x0 0 0 0 on gdb use "info registers all" to have gdb display the register contents: vr0 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} vr1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ... vr0s1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} vr1s1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} Not that the contents are all zeros according to gdb but the debug prints say otherwise. Stepi one more time to execute the bcd instructiion and you get: register contents CARLL, VSR32 = 0x100 99999999 99999999 9999959c CARLL, VSR33 = 0x0 99999999 99999999 9999959c the s1 shadow contents CARLL, VSR32 = 0x0 0 0 c CARLL, VSR33 = 0x0 0 0 0 the s2 shadow contents CARLL, VSR32 = 0x0 0 0 0 CARLL, VSR33 = 0x0 0 0 0 gdb gives the following vr0 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} vr1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ... vr0s1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} vr1s1 {uint128 = 0x00000000000000000000000000000000, v4_float = {0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}} The value VSR32 = 0x100 99999999 99999999 9999959c is the correct result. It will be printed by the test case. Note, the shadow bits are not all zeros, that is the bug!!! So we see that the source register VBits were all valid before the instruction but the result of the bcdadd instruction has two of the shadow register vbits set indicating the bits are uninitialized. The vbits are set by the function do_shadow_store() in memcheck/MC_translate.c, line 5018. We are doing 128-bit operations so in the " else if (UNLIKELY(ty == Ity_V128)) {" block we have a call to MC_(helperc_STOREV64le) which calls mc_storev64() do the actual vbit store. mc_storev64() is defined in memcheck/mc_main.c at about line 4646. If you put an if statement in the code: /*------------------------------------------------------------*/ /*--- STOREV64 ---*/ /*------------------------------------------------------------*/ static INLINE void mc_STOREV64 ( Addr a, ULong vbits64, Bool isBigEndian ) { PROF_EVENT(MCPE_STOREV64); #ifndef PERF_FAST_STOREV // XXX: this slow case seems to be marginally faster than the fast case! // Investigate further. mc_STOREVn_slow( a, 64, vbits64, isBigEndian ); #else { UWord sm_off16, vabits16; SecMap* sm; if (vbits64 == 0xC) VG_(printf)("CARLL, write bad vbits\n"); if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) { PROF_EVENT(MCPE_STOREV64_SLOW1); mc_STOREVn_slow( a, 64, vbits64, isBigEndian ); return; } sm = get_secmap_for_reading_low(a); sm_off16 = SM_OFF_16(a); vabits16 = ((UShort*)(sm->vabits8))[sm_off16]; ... } You can get it to print the message "write bad vbits" for this particular case which corresponds to the valgrind generated messages: ==8979== Use of uninitialised value of size 8 ==8979== at 0x40F8BD8: _itoa_word (_itoa.c:180) ==8979== by 0x40FB05B: vfprintf@@GLIBC_2.17 (vfprintf.c:1641) ==8979== by 0x1000084F: main (test_vector_misc.c:83 What I have not been able to do is to find exactly where the vbits64 value gets generated when the bcdadd instruction executes. I don't know if it is done via generated assembly code or a call out to a C function like the mc_STOREV64() function that stores the vgit value. Need help to figure out why the vbits64 value is calculation is wrong. Reproducible: Always Steps to Reproduce: 1. given in the details. Attached the test program and a script to compile it. 2. 3. -- You are receiving this mail because: You are watching all bug changes.