/*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014
* Dale Weiler
* Wolfgang Bumiller
*
* SOFTWARE.
*/
#define GMQCC_PLATFORM_HEADER
+#include <stdlib.h>
#include "gmqcc.h"
#include "platform.h"
}
/*
- * Based On:
- * Slicing-by-8 algorithms by Michael E.
- * Kounavis and Frank L. Berry from Intel Corp.
- * http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
- *
- * This code was made to be slightly less confusing with macros, which
- * I suppose is somewhat ironic.
- *
- * The code had to be changed for non reflected on the output register
- * since that's the method Quake uses.
- *
- * The code also had to be changed for CRC16, which is slightly harder
- * since the CRC32 method in the original Intel paper used a different
- * bit order convention.
- *
- * The table can be computed with:
- * u16 table[8][256];
- * for (i = 0; i < 0x100; ++i) {
- * u16 x = i << 8;
- * for (j = 0; j < 8; j++)
- * x = (x << 1) ^ ((x & 0x8000) ? 0x1021 : 0);
- * table[0][i] = x;
- * }
- * for (i = 0; i < 0x100; ++i) {
- * u16 c = (*table)[i];
- * for (j = 1; j < 8; ++j)
- * table[j][i] = c = (*table)[c >> 8] ^ (c << 8));
- * }
+* Based On:
+* Slicing-by-8 algorithms by Michael E.
+* Kounavis and Frank L. Berry from Intel Corp.
+* http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
+*
+* This code was made to be slightly less confusing with macros, which
+* I suppose is somewhat ironic.
+*
+* The code had to be changed for non reflected on the output register
+* since that's the method Quake uses.
+*
+* The code also had to be changed for CRC16, which is slightly harder
+* since the CRC32 method in the original Intel paper used a different
+* bit order convention.
+*
+* Notes about the table:
+* - It's exactly 4K in size
+* - 64 elements fit in a cache line
+* - can do 8 iterations unrolled 8 times for free
+* - The first 256 elements of the table are standard CRC16 table
+*
+* Table can be generated with the following utility:
+*/
+#if 0
+#include <stdio.h>
+#include <stdint.h>
+int main(void) {
+ for (unsigned i = 0; i < 0x100; ++i) {
+ uint16_t x = i << 8;
+ for (int j = 0; j < 8; ++j)
+ x = (x << 1) ^ ((x & 0x8000) ? 0x1021 : 0);
+ tab[0][i] = x;
+ }
+ for (unsigned i = 0; i < 0x100; ++i) {
+ uint16_t c = tab[0][i];
+ for (unsigned j = 1; j < 8; ++j) {
+ c = tab[0][c >> 8] ^ (c << 8);
+ tab[j][i] = c;
+ }
+ }
+ printf("static const uint16_t util_crc16_table[8][256] = {");
+ for (int i = 0; i < 8; ++i) {
+ printf("{\n");
+ for (int j = 0; j < 0x100; ++j) {
+ printf((j & 7) ? " " : " ");
+ printf((j != 0x100-1) ? "0x%04X," : "0x%04X", tab[i][j]);
+ if ((j & 7) == 7)
+ printf("\n");
+ }
+ printf((i != 7) ? "}," : "}");
+ }
+ printf("};\n");
+ return 0;
+}
+#endif
+/*
+ * Non-Reflective version is present as well as a reference.
*
- * Notes about the table:
- * - It's exactly 4K in size
- * - 64 elements fit in a cache line
- * - can do 8 iterations unrolled 8 times for free
- * - The first 256 elements of the table are standard CRC16 table
+ * TODO:
+ * combine the crc16 into u32s and mask off low high for byte order
+ * to make the arrays smaller.
*/
+
static const uint16_t util_crc16_table[8][256] = {{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x5357, 0x1484, 0xDCF1, 0x9B22, 0x5C3A, 0x1BE9, 0xD39C, 0x944F
}};
-uint16_t util_crc16(uint16_t current, const char *k, size_t len) {
- /* keep in register for fast cascade */
+/* Non - Reflected */
+uint16_t util_crc16(uint16_t current, const char *GMQCC_RESTRICT k, size_t len) {
register uint16_t h = current;
/* don't load twice */
- uint8_t *GMQCC_RESTRICT data = (uint8_t *GMQCC_RESTRICT)k;
+ const uint8_t *GMQCC_RESTRICT data = (const uint8_t *GMQCC_RESTRICT)k;
size_t n;
+ /* deal with the first bytes as bytes until we reach an 8 byte boundary */
+ while (len & 7) {
+ h = (uint16_t)(h << 8) ^ (*util_crc16_table)[(h >> 8) ^ *data++];
+ --len;
+ }
+
#define SELECT_BULK(X, MOD) util_crc16_table[(X)][data[7-(X)] ^ (MOD)]
#define SELECT_DATA(X) util_crc16_table[(X)][data[7-(X)]]
SELECT_DATA(4) ^
SELECT_DATA(3) ^
SELECT_DATA(2) ^
- SELECT_DATA(1);
+ SELECT_DATA(1) ^
+ SELECT_DATA(0);
data += 8;
+ len -= 8;
}
+ #undef SELECT_BULK
+ #undef SELECT_DATA
+
/* deal with the rest with the byte method */
- for (n &= 7; n; --n)
+ for (n = len & 7; n; --n)
h = (uint16_t)(h << 8) ^ (*util_crc16_table)[(h >> 8) ^ *data++];
return h;
* modifier is the match to make and the transposition from it, while add is the upper-value that determines the
* transposition from uppercase to lower case.
*/
-static GMQCC_INLINE size_t util_strtransform(const char *in, char *out, size_t outsz, const char *mod, int add) {
+static size_t util_strtransform(const char *in, char *out, size_t outsz, const char *mod, int add) {
size_t sz = 1;
for (; *in && sz < outsz; ++in, ++out, ++sz) {
*out = (*in == mod[0])