syn68k/test/crc.c
2008-09-26 08:25:10 -06:00

135 lines
4.7 KiB
C

#include "crc.h"
/*
* Algorithm from "Computer Networks" by Andrew S. Tanenbaum pp. 129-132.
*
* Code lifted from ROMlib's crc.c. by mjhostet (with permission), 3/28/93.
* Lookup table added 3/29/93.
*/
#define GEN 0x88108000
#define GEN1 (GEN >> 1)
#define GEN2 (GEN >> 2)
#define GEN3 (GEN >> 3)
#define GEN4 (GEN >> 4)
#define GEN5 (GEN >> 5)
#define GEN6 (GEN >> 6)
#define GEN7 (GEN >> 7)
#if 0
static unsigned long
polydivide(unsigned long l)
{
if (l & 0x80000000)
l ^= GEN;
if (l & 0x40000000)
l ^= GEN1;
if (l & 0x20000000)
l ^= GEN2;
if (l & 0x10000000)
l ^= GEN3;
if (l & 0x08000000)
l ^= GEN4;
if (l & 0x04000000)
l ^= GEN5;
if (l & 0x02000000)
l ^= GEN6;
if (l & 0x01000000)
l ^= GEN7;
return l;
}
#else
static unsigned long
polydivide (unsigned long l)
{
static const unsigned long crc_table[] = {
0x00000000, 0x01102100, 0x02204200, 0x03306300, 0x04408400, 0x0550A500,
0x0660C600, 0x0770E700, 0x08810800, 0x09912900, 0x0AA14A00, 0x0BB16B00,
0x0CC18C00, 0x0DD1AD00, 0x0EE1CE00, 0x0FF1EF00, 0x10123100, 0x11021000,
0x12327300, 0x13225200, 0x1452B500, 0x15429400, 0x1672F700, 0x1762D600,
0x18933900, 0x19831800, 0x1AB37B00, 0x1BA35A00, 0x1CD3BD00, 0x1DC39C00,
0x1EF3FF00, 0x1FE3DE00, 0x20246200, 0x21344300, 0x22042000, 0x23140100,
0x2464E600, 0x2574C700, 0x2644A400, 0x27548500, 0x28A56A00, 0x29B54B00,
0x2A852800, 0x2B950900, 0x2CE5EE00, 0x2DF5CF00, 0x2EC5AC00, 0x2FD58D00,
0x30365300, 0x31267200, 0x32161100, 0x33063000, 0x3476D700, 0x3566F600,
0x36569500, 0x3746B400, 0x38B75B00, 0x39A77A00, 0x3A971900, 0x3B873800,
0x3CF7DF00, 0x3DE7FE00, 0x3ED79D00, 0x3FC7BC00, 0x4048C400, 0x4158E500,
0x42688600, 0x4378A700, 0x44084000, 0x45186100, 0x46280200, 0x47382300,
0x48C9CC00, 0x49D9ED00, 0x4AE98E00, 0x4BF9AF00, 0x4C894800, 0x4D996900,
0x4EA90A00, 0x4FB92B00, 0x505AF500, 0x514AD400, 0x527AB700, 0x536A9600,
0x541A7100, 0x550A5000, 0x563A3300, 0x572A1200, 0x58DBFD00, 0x59CBDC00,
0x5AFBBF00, 0x5BEB9E00, 0x5C9B7900, 0x5D8B5800, 0x5EBB3B00, 0x5FAB1A00,
0x606CA600, 0x617C8700, 0x624CE400, 0x635CC500, 0x642C2200, 0x653C0300,
0x660C6000, 0x671C4100, 0x68EDAE00, 0x69FD8F00, 0x6ACDEC00, 0x6BDDCD00,
0x6CAD2A00, 0x6DBD0B00, 0x6E8D6800, 0x6F9D4900, 0x707E9700, 0x716EB600,
0x725ED500, 0x734EF400, 0x743E1300, 0x752E3200, 0x761E5100, 0x770E7000,
0x78FF9F00, 0x79EFBE00, 0x7ADFDD00, 0x7BCFFC00, 0x7CBF1B00, 0x7DAF3A00,
0x7E9F5900, 0x7F8F7800, 0x80918800, 0x8181A900, 0x82B1CA00, 0x83A1EB00,
0x84D10C00, 0x85C12D00, 0x86F14E00, 0x87E16F00, 0x88108000, 0x8900A100,
0x8A30C200, 0x8B20E300, 0x8C500400, 0x8D402500, 0x8E704600, 0x8F606700,
0x9083B900, 0x91939800, 0x92A3FB00, 0x93B3DA00, 0x94C33D00, 0x95D31C00,
0x96E37F00, 0x97F35E00, 0x9802B100, 0x99129000, 0x9A22F300, 0x9B32D200,
0x9C423500, 0x9D521400, 0x9E627700, 0x9F725600, 0xA0B5EA00, 0xA1A5CB00,
0xA295A800, 0xA3858900, 0xA4F56E00, 0xA5E54F00, 0xA6D52C00, 0xA7C50D00,
0xA834E200, 0xA924C300, 0xAA14A000, 0xAB048100, 0xAC746600, 0xAD644700,
0xAE542400, 0xAF440500, 0xB0A7DB00, 0xB1B7FA00, 0xB2879900, 0xB397B800,
0xB4E75F00, 0xB5F77E00, 0xB6C71D00, 0xB7D73C00, 0xB826D300, 0xB936F200,
0xBA069100, 0xBB16B000, 0xBC665700, 0xBD767600, 0xBE461500, 0xBF563400,
0xC0D94C00, 0xC1C96D00, 0xC2F90E00, 0xC3E92F00, 0xC499C800, 0xC589E900,
0xC6B98A00, 0xC7A9AB00, 0xC8584400, 0xC9486500, 0xCA780600, 0xCB682700,
0xCC18C000, 0xCD08E100, 0xCE388200, 0xCF28A300, 0xD0CB7D00, 0xD1DB5C00,
0xD2EB3F00, 0xD3FB1E00, 0xD48BF900, 0xD59BD800, 0xD6ABBB00, 0xD7BB9A00,
0xD84A7500, 0xD95A5400, 0xDA6A3700, 0xDB7A1600, 0xDC0AF100, 0xDD1AD000,
0xDE2AB300, 0xDF3A9200, 0xE0FD2E00, 0xE1ED0F00, 0xE2DD6C00, 0xE3CD4D00,
0xE4BDAA00, 0xE5AD8B00, 0xE69DE800, 0xE78DC900, 0xE87C2600, 0xE96C0700,
0xEA5C6400, 0xEB4C4500, 0xEC3CA200, 0xED2C8300, 0xEE1CE000, 0xEF0CC100,
0xF0EF1F00, 0xF1FF3E00, 0xF2CF5D00, 0xF3DF7C00, 0xF4AF9B00, 0xF5BFBA00,
0xF68FD900, 0xF79FF800, 0xF86E1700, 0xF97E3600, 0xFA4E5500, 0xFB5E7400,
0xFC2E9300, 0xFD3EB200, 0xFE0ED100, 0xFF1EF000,
};
return l ^ crc_table[l >> 24];
}
#endif
unsigned short
compute_crc (unsigned char *data, long length, unsigned short seed)
{
unsigned long l;
#if 0
if (length == 0)
l = 0;
else if (length == 1)
l = data[0];
else if (length == 2)
l = (data[0] << 8) | data[1];
else
l = (data[0] << 16) | (data[1] << 8) | data[2];
data += 3;
length -= 2;
#else
/* This is spew, but it munges in the seed. */
if (length == 0)
l = seed;
else
l = (seed << 8) | data[0];
data++;
#endif
while (--length > 0)
{
l = (l << 8) | *data++;
l = polydivide(l);
}
l <<= 8;
l = polydivide(l);
l <<= 8;
l = polydivide(l);
return l >> 8;
}