Date: Thu, 08 Mar 2001 15:50:29 -0500 (EST) From: "Philippe O. Pouliquen" <philippe@alpha.ece.jhu.edu> To: freebsd-alpha@FreeBSD.ORG Subject: Re: Strange results from compiled alpha code Message-ID: <200103082050.PAA0000024187@alpha.ece.jhu.edu>
next in thread | raw e-mail | index | archive | help
I've had an e-mail exchange with Ray Newman, and have investigated the problem further. Peter Jeremy <peter.jeremy@alcatel.com.au> wrote: > Ray Newman <raymond@one.com.au> wrote: >>Tony Griffiths wrote: >>> In the case you give below, the 'short len' is misaligned on an >>> odd byte boundary. This might be the cause of the problem... > I suspect that gcc is ignoring the low bit of the address when > loading the short. The Compaq CC masks the address so as to create > an alignment fault in this case. Just to clear things up here, in the C sequence: *((short *) char_pointer) The problem only occurs with GCC when the word (short in C, 16 bit) straddles a quad-word (long in C, 64 bit) boundary. The instruction sequence emitted by GCC works fine for any word completely contained in a quad-word (see end of message). In any case, the instruction sequence *never* generates an alignment trap (it uses LDQ_U) -- it just silently loads the wrong value when the straddling occurs. *This is legal ANSI C behavior.* According to the ANSI C standard, loading a short from an unaligned address results in undefined behavior. The Compaq CC is friendlier: if the word is not word aligned, an alignement trap is generated, and the proper value is loaded by the kernel. >>> I know that with DEC/Compaq cc there is a #pragma and also a >>> compiler switch to assume_unaligned pointers for cases like this. >... >>> I don't know that the [g]cc equivalent switch is but presume that >>> there is one! >Actually, there doesn't appear to be one. #pragma pack 1 only works in Compaq's CC, but causes structure to be created without internal padding. As a side effect, the compiler then assumes that pointers will be misaligned. Packing the structures in Ray's case may be a good thing, because beyond the misaligned pointer, his code assumes that the second structure member is stored two bytes after the first (that's why he has sizeof(short) in there): typedef struct CSTRING { short len; u_char buf[32768]; } cstring; mumpspc += ((cstring*)mumpspc)->len + sizeof(short) + 1; >>> Alternatively, change the code slightly to ensure that the >>> 'mumpspc' pointer is always incremented by an even number of bytes. >>> eg. >>> >>> mumpspc += ( ((cstring*)mumpspc)->len + sizeof(short) + 2 ) & ~1; > > If you can't guarantee alignment, then your other option is to > totally avoid the use of CSTRING and use code like (assuming > little-endian data): > > short len = mumpspc[0] | (mumpspc[1] << 8); > mumpspc = mumpspc + len + sizeof(short) + 1; Ray was hoping not to modify his code, as the problem occurs in many locations. In any case, the code above is not strictly correct. First, it does not properly access the structure elements, because it assumes that 'buf' (second structure member) is stored two bytes (sizeof(short)) after 'len' (first structure member). Second, 'len' is a signed (16 bit) integer, but mumpspc is a pointer to unsigned byte. (and, as mentioned by Peter, the code is endian dependent) Here is the shortest sequence that I could come up with which highlights the problem: ---------------------------------------------------------------- #include <stdio.h> unsigned char data[16]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10}; short get_short(unsigned char *ptr) { return(*((short *)ptr)); } main() { printf("0x%X\n",get_short(&(data[7]))); } ---------------------------------------------------------------- gcc version 2.95.2 (alpha-dec-osf4.0) prints 0x100. Comapq C V6.1-011 on Digital UNIX V5.0 (Rev. 910) generates an unaligned access trap and prints 0x908. Here is the GCC instruction sequence: (gcc -O) addq a0, 0x2, a0 // a0=a0+2 (2=sizeof(short)) ldq_u v0, -2(a0) // v0=*((long *)(a0-2)) (won't trap) extqh v0, a0, v0 // v0=v0<<((64-8*a0)&0x3F) To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-alpha" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103082050.PAA0000024187>