C compiler bug

Kuck And Associates kai at sp1.csrd.uiuc.edu
Thu Jul 19 00:54:59 AEST 1990


kai at sp1.csrd.uiuc.edu (Kuck And Associates) writes:
>It appears the "wrong answer" machines are all Big Endian (bytes are stored in
>memory in the order 4321, as opposed to the S81's i386 processors, which are
>Little Endian).  Perhaps the code isn't quite portable.

I was right.  Compile the following fixed version of that pgm defining
BIG_ENDIAN on hosts running 680x0's, MIPS processors, and you get the exact
same results as on Little Endian machines, like your Sequent S81.  The
program's author DOES warn to "Watch bit fields...see my C book...".

	Patrick Wolfe   (pat at kai.com, kailand!pat)
	System Programmer/Operations Manager, Kuck & Associates
	"Any opinions expressed are my own, not my employers's.
	 Please don't call my boss and complain ... again."

--  cut here  --  cut here  --  cut here  --  cut here  --  cut here  --

/*---------------------------------------------------------*/
/*          High Performance CRC Computation Routine       */
/*                                                         */
/*            Copyright 1985 W. David Schwaderer           */
/*                 All rights reserved                     */
/*                                                         */
/*     Compiler used:  Computer Innovations C86 V2.10A     */
/*                                                         */
/*        Warning...this program uses bit fields!          */
/*         For warnings on bit field hazards see:          */
/*                                                         */
/*    The C Wizard's Programming Reference Handbook        */
/*               W. David Schwaderer                       */
/*            John Wiley and Sons, 1985                    */
/*                                                         */
/*---------------------------------------------------------*/

/* Watch bit fields...see my C book... */

#include <stdio.h>

#define VOID int

unsigned crc_table[256];    /*   globally accessible   */

main(argc, argv)
int   argc;
char *argv[];
{
   VOID    GenerateTable();
   unsigned GenerateCRC();

   unsigned length, crc;

               /* crc = 0x9001 */
   static char TestArray1[] = {'\001', '\000'};

   static char TestArray2[] = {'\001','\000', '\001', '\220'};
                              /* bytewise      bytewise */
                              /* unreversed    reversed */

   static char TestMsg[] = "This is a test message.";

   GenerateTable();        /* fill in the crc_table */

   PrintTable();          /* display the table      */

   length = sizeof(TestArray1);
   crc = GenerateCRC(length, TestArray1); /* calculate CRC */
   printf("\n\n\nTestArray1 CRC = 0x%04x", crc);

   length = sizeof(TestArray2);
   crc = GenerateCRC(length, TestArray2); /* calculate CRC */
   printf("\n\n\nTestArray2 CRC = 0x%04x", crc);
   length = sizeof(TestMsg) - 1; /* avoid terminating NUL */
   crc = GenerateCRC(length, TestMsg); /* calculate a CRC */
   printf("\n\n\nText = [%s]\nCRC = %04x\n\n", TestMsg, crc);

   return(0);

}

VOID GenerateTable()   /* generate the look-up table */
{
   int temp;
   union { int i;
       struct {
#ifdef BIG_ENDIAN
           unsigned     :24; /* bytes 4, 3 and 2 */
           unsigned i8  :1; /* byte 1 */
           unsigned i7  :1;
           unsigned i6  :1;
           unsigned i5  :1;
           unsigned i4  :1;
           unsigned i3  :1;
           unsigned i2  :1;
           unsigned i1  :1;
#else  /* ! BIG_ENDIAN */
           unsigned i1  :1; /* low order bit */
           unsigned i2  :1;
           unsigned i3  :1;
           unsigned i4  :1;
           unsigned i5  :1;
           unsigned i6  :1;
           unsigned i7  :1;
           unsigned i8  :1; /* high order bit */
           unsigned     :24; /* unused         */
#endif /* BIG_ENDIAN */
           } Bit;
       } iUn;

   union {  unsigned int  Entry;
       struct {
#ifdef BIG_ENDIAN
	   unsigned     :16; /* bytes 4 and 3 */
           unsigned b16 :1;
           unsigned b15 :1;
           unsigned b14 :1;
           unsigned b13 :1;
           unsigned b12 :1;
           unsigned b11 :1;
           unsigned b10	:1;
           unsigned b9  :1; /* byte 2 */
           unsigned b8  :1; /* byte 1 */
           unsigned b7  :1;
           unsigned b6  :1;
           unsigned b5  :1;
           unsigned b4  :1;
           unsigned b3  :1;
           unsigned b2  :1;
           unsigned b1  :1;
#else	/* ! BIG_ENDIAN */
           unsigned b1  :1; /* low order bit */
           unsigned b2  :1;
           unsigned b3  :1;
           unsigned b4  :1;
           unsigned b5  :1;
           unsigned b6  :1;
           unsigned b7  :1;
           unsigned b8  :1;
           unsigned b9  :1;
           unsigned b10	:1;
           unsigned b11 :1;
           unsigned b12 :1;
           unsigned b13 :1;
           unsigned b14 :1;
           unsigned b15 :1;
           unsigned b16 :1; /* high order bit */
	   unsigned     :16; /* unused */
#endif /* BIG_ENDIAN */
	} EntryBit;
       } EntryUn;
	
	for (iUn.i = 0; iUn.i < 256; iUn.i++) {
       EntryUn.Entry = 0; /* bits 2 thru 6 zeroed out now */
       temp = (iUn.Bit.i7 ^ iUn.Bit.i6 ^ iUn.Bit.i5 ^
               iUn.Bit.i4 ^ iUn.Bit.i3 ^ iUn.Bit.i2 ^
               iUn.Bit.i1);

       EntryUn.EntryBit.b16 = (iUn.Bit.i8 ^ temp);
       EntryUn.EntryBit.b15 = (temp);
       EntryUn.EntryBit.b14 = (iUn.Bit.i8 ^ iUn.Bit.i7);
       EntryUn.EntryBit.b13 = (iUn.Bit.i7 ^ iUn.Bit.i6);
       EntryUn.EntryBit.b12 = (iUn.Bit.i6 ^ iUn.Bit.i5);
       EntryUn.EntryBit.b11 = (iUn.Bit.i5 ^ iUn.Bit.i4);
       EntryUn.EntryBit.b10 = (iUn.Bit.i4 ^ iUn.Bit.i3);
       EntryUn.EntryBit.b9  = (iUn.Bit.i3 ^ iUn.Bit.i2);
       EntryUn.EntryBit.b8  = (iUn.Bit.i2 ^ iUn.Bit.i1);
       EntryUn.EntryBit.b7  = (iUn.Bit.i1);
       EntryUn.EntryBit.b1  = (iUn.Bit.i8 ^ temp);

       crc_table[iUn.i] = EntryUn.Entry;
   }

}

VOID PrintTable()       /* print out the look-up table */
{
   int i;

   for (i=0; i < 256; i++) {
       if ( !(i % 8) )
           printf("\n %02x - %04x", i, crc_table[i]);
       else
           printf("  %04x", crc_table[i]);
   }
}

unsigned GenerateCRC(Length, TextPtr)
   unsigned Length;
   char   *TextPtr;
{
   int i, index;
   unsigned crc;

   crc = 0;    /* crc starts at zero for each message */

   for (i = 0; i < Length; i++, TextPtr++) {
       index = ( (crc ^ *TextPtr) & 0x00FF);
       crc = ( (crc >> 8) & 0x00FF) ^ crc_table[index];
   }
   return(crc);

}



More information about the Comp.sys.sgi mailing list