Subject: gcc/egcs problem with shifts on i386
To: None <current-users@netbsd.org>
From: Colin Wood <cwood@ichips.intel.com>
List: current-users
Date: 08/16/1999 21:00:47
i wrote a little program to play with shifts today (i needed it for work)
and discovered a problem with shifts under i386 (or IA32 as we like to say
here at work ;-)  the program is included below for reference.  what i've
found is that if i specify a shift count of 32 for either a right or left
shift (i.e num << 32), i get back the same number i put in, rather than a
0.  for example:

<nb00:ender>/home/ender/junk% ./shift l 0x7fffffff 32
shl 0x7fffffff, 0x20 -> 0x7fffffff
<nb00:ender>/home/ender/junk% ./shift l 0x7fffffff 31
shl 0x7fffffff, 0x1f -> 0x80000000
<nb00:ender>/home/ender/junk% ./shift r 0x7fffffff 31
shr 0x7fffffff, 0x1f -> 0x0
<nb00:ender>/home/ender/junk% ./shift r 0x7fffffff 32
shr 0x7fffffff, 0x20 -> 0x7fffffff


this only appears to occur on i386 (and i can probably explain it fairly
easily if a shift is implemented via SHL/SHR).  what i'm wondering is if
this is a bug in egcs/gcc, or if this is simply a hole in the C spec and
either behavior is allowed.

anyone know?

later.

colin


--
Colin Wood                                 cwood@ichips.intel.com
Component Design Engineer - PMD                 Intel Corporation
-----------------------------------------------------------------
I speak only on my own behalf, not for my employer.



#include<stdio.h>
#include<stdlib.h>

int
main(int argc, char *argv[])
{
	long in, shift, out;
	char dir;

	if (argc != 4) {
		fprintf(stderr, "Usage: shift <dir> <number> <shift count>\n");
		exit(-1);
	}

	dir = *(argv[1]);	
	in = strtoul(argv[2], NULL, 0);
	shift = strtoul(argv[3], NULL, 0);
	switch (dir) {
	case 'l':
		out = in << shift;
		break;
	case 'r':
		out = in >> shift;
		break;
	}

	fprintf(stdout, "sh%c 0x%x, 0x%x -> 0x%x\n", dir, in, shift, out);

	return (0);
}