[gnu.gcc.bug] volatile unsigned short reference problem

satz@CISCO.COM (03/12/89)

The following program when compiled on SunOS 3.5 (3/280) using gcc 1.34
loads the wrong byte from a volatile location.

typedef struct foo1 {
	volatile unsigned short *data;
	volatile unsigned short	*status;
} footype;

void test (ptr)
    footype *ptr;
{
    register unsigned int status;
    register int flag;
    register unsigned char c;

	while ((status = *ptr->status) & 1) {
	    c = *ptr->data;
	    if (status & 128) {
		while (*ptr->status & 1)
		    c = *ptr->data;
		c = 0;
		flag = doit(ptr,c,1);
	    }
	}
}

The temporary variable c when declared as a char gets the upper byte of
*ptr->data instead of the lower. The workaround we used was to declare c as
an unsigned short.

gcc version 1.34
 /usr/src/gnu/gcc-1.34/cpp -v -DCSC2 -I../h -undef -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -D__HAVE_68881__ -Dmc68020 foo.c /tmp/cca12938.cpp
GNU CPP version 1.34
 /usr/src/gnu/gcc-1.34/cc1 /tmp/cca12938.cpp -quiet -dumpbase foo.c -O -W -version -o foo.s
GNU C version 1.34 (68k, MIT syntax) compiled by GNU C version 1.34.

#NO_APP
gcc_compiled.:
.text
	.even
.globl _test
_test:
	link a6,#0
	moveml #0x2020,sp@-
	movel a6@(8),a2
	clrl d2
	jra L2
L8:
	movel a2@,a0
	moveb a0@(1),d0		<-- off by one
	tstb d2
	jge L2
	movel a2@(4),a1
	jra L5
L7:
	movel a2@,a0
	moveb a0@(1),d0
L5:
	movew a1@,d0
	btst #0,d0
	jne L7
	pea 1:w
	clrl sp@-
	movel a2,sp@-
	jbsr _doit
	addw #12,sp
L2:
	movel a2@(4),a0
	movew a0@,a0
	movew a0,d2
	btst #0,d2
	jne L8
	moveml a6@(-8),#0x404
	unlk a6
	rts