Is this (gasp) a chip bug?

Jon Ryshpan jon at hitachi.uucp
Tue Jul 31 06:47:08 AEST 1990


In article <1990Jul23.223341.26431 at cbnewsc.att.com> imdave at cbnewsc.att.com (david.e.bodenstab) writes:

>Here is a little program derived from a problem we tracked down in a
>driver:
>
>	main()
>	{
>	    unsigned y = 0x7ffff0ff;
>	    unsigned x = 0x7ffff000;
>
>	    while (1) {
>		if ( ((int)(y - x)) < 0 )
>		    printf("WRONG x=%x y=%x (y - x)=%x\n",x,y,y-x);
>		x++;
>		y++;
>	    }
>	}
>
>This program `fails' on both a 386 and another cpu in-house -- the
>range of values for the `failure' are:
>
>	0x80000000 <= y <= 0x800000fe
>	0x7fffff01 <= x <= 0x7fffffff
>

It's a compiler bug.  On the 68020 (Sun 3) I get the following code from
the standard Sun compiler:

	L14:
		movl	a6@(-0x4),d0
		subl	a6@(-0x8),d0
		tstl	d0
		jge	L16
		...
		jbsr	_printf
		lea	sp@(0x10),sp
	L16:

This is correct.  Note the key instruction "tstl d0", which is the
result of the cast from unsigned to int.

Under Interactive 386/ix, using the Interactive port of the ATT C
compiler (or whatever is the standard C compiler for 386/ix ver 2.02) I
get this code:

	.L16:
		movl    -4(%ebp),%eax
		subl    -8(%ebp),%eax
		jge     .L17
		...
		call    printf
		addl    $16,%esp
	.L17:

This code is wrong since there is no cast from unsigned to int.  It's
not possible to fix this by using an unsigned rather than a signed
branch, since this would just substitute one range of values which
produce an incorrect branch for another.

Jonathan Ryshpan		<...!uunet!hitachi!jon>

M/S 420				(415) 244-7369  	
Hitachi America Ltd.
2000 Sierra Pt. Pkwy.
Brisbane CA 94005-1819



More information about the Comp.unix.i386 mailing list