Subject: 3.1 sparc64 codegen bug?
To: None <port-sparc64@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: port-sparc64
Date: 09/24/2007 03:45:56
I ran into a problem on sparc64.  Adding debugging code, I found my
debugging code was broken.  It looks to me like a codegen bug, and I'm
wondering if anyone else can agree, disagree, reproduce, etc.  In
particular, if others using sparc64 3.1 *can't* reproduce this, that
would be very interesting information.

z.c:
	#include <stdio.h>
	
	typedef unsigned long int int64_t;
	
	#define BYTES_PER_64 8
	
	static void check(int64_t a, int64_t b, int64_t c, int64_t d)
	{
	 unsigned char cb[BYTES_PER_64];
	 unsigned char db[BYTES_PER_64];
	 unsigned char pb[2*BYTES_PER_64];
	 int i;
	 int j;
	 int k;
	 int s;
	
	 for (i=0;i<BYTES_PER_64;i++)
	  { cb[i] = (c >> (i*8)) & 0xff;
	    db[i] = (d >> (i*8)) & 0xff;
	    pb[i] = 0;
	    pb[i+BYTES_PER_64] = 0;
	  }
	 for (i=0;i<BYTES_PER_64;i++)
	  { for (j=0;j<BYTES_PER_64;j++)
	     { s = cb[i] * db[j];
	       k = i + j;
	       while (s)
		{ s += pb[k];
		  pb[k] = s & 0xff;
		  s >>= 8;
		  k ++;
		}
	     }
	  }
	 for (i=0;i<BYTES_PER_64;i++)
	  { if ( (pb[i] != (b >> (i*8)) & 0xff) ||
		 ( (pb[i+BYTES_PER_64] != (a >> (i*8)) & 0xff) &&
		   ((i+=BYTES_PER_64),1) ) )
	     { fprintf(stderr,"mul failed at %d\n",i);
	       for (i=BYTES_PER_64-1;i>=0;i--) fprintf(stderr,"%02x",cb[i]);
	       fprintf(stderr," * ");
	       for (i=BYTES_PER_64-1;i>=0;i--) fprintf(stderr,"%02x",db[i]);
	       fprintf(stderr,"\ngot ");
	       for (i=BYTES_PER_64-1;i>=0;i--) fprintf(stderr,"%02x",(a>>(i*8))&0xff);
	       for (i=BYTES_PER_64-1;i>=0;i--) fprintf(stderr,"%02x",(b>>(i*8))&0xff);
	       fprintf(stderr,"\nnot ");
	       for (i=(2*BYTES_PER_64)-1;i>=0;i--) fprintf(stderr,"%02x",pb[i]);
	       fprintf(stderr,"\n");
	       abort();
	     }
	  }
	}

If I compile this with "cc -S z.c -g", I get z.s, which is over 1500
lines, but the relevant part is the beginning of the body of the last
loop:

		.loc 1 36 0
		ld	[%fp+1979], %g1
		sra	%g1, 0, %g2
		add	%fp, 2031, %g1
		add	%g1, %g2, %g1
		ldub	[%g1-48], %g1
		and	%g1, 0xff, %g3
		ld	[%fp+1979], %g1
		sll	%g1, 3, %g2
		ldx	[%fp+2183], %g1
		srlx	%g1, %g2, %g1
		cmp	%g3, %g1
		bne	%xcc, .LL26
		nop

As I read it, this code corresponds to

	  { if ( (pb[i] & 0xff != (b >> (i*8))) ||
		 ....

which is not what the source says.

In case it matters, the hardware is an Ultra 5:

cpu0 at mainbus0: SUNW,UltraSPARC-IIi @ 269.805 MHz, version 0 FPU
cpu0: 32K instruction (32 b/l), 16K data (32 b/l), 256K external (64 b/l)

Any thoughts?  Apply a patch?  Send-pr?

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B