This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Unsaved register?


I'm working on a bitstream implementation using mmx, with extensive
inlining support, etc.  I've run across what I think is a bug in the
register-stomping code.  The routine in question is:

extern inline
uint32_t bitstream_get_mmx(bitstream_t *bs,uint32_t num_bits) {
  uint32_t bits,result;
//fprintf(stderr,"num_bits is %d\n",num_bits);
  asm volatile (
        "movq %4, %%mm7\n\t"            // put current bits into mm7
        "movl %5, %3\n\t"               // put remaining bits into reg3
        "subl %6, %3\n\t"               // subtract num_bits from reg3
        "jnl 1f\n\t"                    // skip if we have enough bits
        "pushl %6\n\t"                  // push num_bits
        "pushl %7\n\t"                  // push bs
        "call bitstream_get_bh_mmx\n\t" // call the bottom half
        "movl %%eax, %0\n\t"            // save the result
        "jmp 2f\n\t"
        "1:\n\t"
        "movd %8, %%mm5\n\t"            // put the shift count into mm5
        // we know we have enough bits, they're at the top of mm7
        "movq %%mm7, %%mm6\n\t"         // working copy in mm6
        "movd %6, %%mm4\n\t"            // get the bit count again
        "psrlq %%mm5, %%mm6\n\t"        // shift mm6 right by 64 - numbits
        // mm6 now has the right data
        "movl %3, %2\n\t"               // save back the modified curbits
        "movd %%mm6, %0\n\t"            // write the resulting bits out
        "psllq %%mm4, %%mm7\n\t"        // strip those bits off mm7
        "movq %%mm7, %1\n\t"            // save the remaining bits back
        "2:\n\t"
        :
    "=r"(result), "=m"(bs->current.u64), "=m"(bs->current_bits), "=r"(bits) :
    "1"(bs->current.u64), "2"(bs->current_bits), "r"(num_bits), "r"(bs),
      "rm"(_bitstream_mmx_64_minus[num_bits]) :
    "memory"
  );
  return result;
}

This is compiling down to the following:

        movl    $5, %ecx		// constant arg num_bits = 5
	. . .

        movq (%edi), %mm7
        movl 8(%edi), %eax
        subl %ecx, %eax
        jnl 1f
        pushl %ecx
        pushl %edi
        call bitstream_get_bh_mmx
        movl %eax, %edx
        jmp 2f
        1:
        movd _bitstream_mmx_64_minus+20, %mm5
        movq %mm7, %mm6
        movd %ecx, %mm4
        psrlq %mm5, %mm6
        movl %eax, 8(%edi)
        movd %mm6, %edx
        psllq %mm4, %mm7
        movq %mm7, (%edi)
        2:

Now, bitstream_get_bh_mmx calls bitstream_next_word_mmx at the end, which
seems to be the culprit:

	. . .
        .stabn 68,0,36,.LM173-bitstream_next_word_mmx
.LM173:
        movl    44(%esi), %ecx
        movzbl  (%ebx,%ecx), %edx
        movzbl  1(%ebx,%ecx), %eax
	. . .

Now, in looking through all the generated code for this function (which is
a mix of C and libmmx code), I see *no* previous references to %ecx.
AFAICT, gcc should either be saving the contents of %ecx at the top of
next_word, or should not be assigning %ecx to the num_bits argument.

It feels like a bug to me, but I only last night finally conquered the
inline asm syntax, and maybe only partially at that.  Am I doing something
wrong in the inline asm routine that's allowing this?  If it is a bug, is
there a way around it?

TIA,
   Omega

P.S. I'm not on the gcc-bugs list, so please cc: me, thanx.

      Erik Walthinsen <omega@temple-baptist.com> - System Administrator
        __
       /  \                GStreamer - The only way to stream!
      |    | M E G A        ***** http://gstreamer.net/ *****
      _\  /_



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]