X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=util.c;h=b1d5c5ba37bc589e89611358fac2fd3c783e727d;hb=b08195e2da48e041a4f027d93e944bc4715169ec;hp=c73b3beec48e6e0455a193bcd7b1d4518401979a;hpb=7011a2ef2ceaf9652cea0b0e61319b338667888b;p=xonotic%2Fgmqcc.git diff --git a/util.c b/util.c index c73b3be..b1d5c5b 100644 --- a/util.c +++ b/util.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014 * Dale Weiler * Wolfgang Bumiller * @@ -22,6 +22,7 @@ * SOFTWARE. */ #define GMQCC_PLATFORM_HEADER +#include #include "gmqcc.h" #include "platform.h" @@ -57,7 +58,7 @@ const char *util_instr_str[VINSTR_END] = { * only required if big endian .. otherwise no need to swap * data. */ -#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG +#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG || PLATFORM_BYTE_ORDER == -1 static GMQCC_INLINE void util_swap16(uint16_t *d, size_t l) { while (l--) { d[l] = (d[l] << 8) | (d[l] >> 8); @@ -85,6 +86,7 @@ const char *util_instr_str[VINSTR_END] = { } */ size_t i; + l *= 2; for (i = 0; i < l; i += 2) { uint32_t v1 = d[i]; d[i] = d[i+1]; @@ -94,73 +96,161 @@ const char *util_instr_str[VINSTR_END] = { } #endif -void util_endianswap(void *_data, size_t length, unsigned int typesize) { +void util_endianswap(void *_data, size_t count, unsigned int typesize) { # if PLATFORM_BYTE_ORDER == -1 /* runtime check */ if (*((char*)&typesize)) return; #else - /* prevent unused warnings */ - (void) _data; - (void) length; - (void) typesize; # if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE + /* prevent unused warnings */ + (void) _data; + (void) count; + (void) typesize; return; # else switch (typesize) { case 1: return; case 2: - util_swap16((uint16_t*)_data, length>>1); + util_swap16((uint16_t*)_data, count); return; case 4: - util_swap32((uint32_t*)_data, length>>2); + util_swap32((uint32_t*)_data, count); return; case 8: - util_swap64((uint32_t*)_data, length>>3); + util_swap64((uint32_t*)_data, count); return; - default: exit(EXIT_FAILURE); /* please blow the fuck up! */ + default: + con_err ("util_endianswap: I don't know how to swap a %u byte structure!\n", typesize); + exit(EXIT_FAILURE); /* please blow the fuck up! */ } # endif #endif } +void util_swap_header(prog_header_t *code_header) { + util_endianswap(&code_header->version, 1, sizeof(code_header->version)); + util_endianswap(&code_header->crc16, 1, sizeof(code_header->crc16)); + util_endianswap(&code_header->statements.offset, 1, sizeof(code_header->statements.offset)); + util_endianswap(&code_header->statements.length, 1, sizeof(code_header->statements.length)); + util_endianswap(&code_header->defs.offset, 1, sizeof(code_header->defs.offset)); + util_endianswap(&code_header->defs.length, 1, sizeof(code_header->defs.length)); + util_endianswap(&code_header->fields.offset, 1, sizeof(code_header->fields.offset)); + util_endianswap(&code_header->fields.length, 1, sizeof(code_header->fields.length)); + util_endianswap(&code_header->functions.offset, 1, sizeof(code_header->functions.offset)); + util_endianswap(&code_header->functions.length, 1, sizeof(code_header->functions.length)); + util_endianswap(&code_header->strings.offset, 1, sizeof(code_header->strings.offset)); + util_endianswap(&code_header->strings.length, 1, sizeof(code_header->strings.length)); + util_endianswap(&code_header->globals.offset, 1, sizeof(code_header->globals.offset)); + util_endianswap(&code_header->globals.length, 1, sizeof(code_header->globals.length)); + util_endianswap(&code_header->entfield, 1, sizeof(code_header->entfield)); +} + +void util_swap_statements(prog_section_statement_t *statements) { + size_t i; + + for (i = 0; i < vec_size(statements); ++i) { + util_endianswap(&statements[i].opcode, 1, sizeof(statements[i].opcode)); + util_endianswap(&statements[i].o1, 1, sizeof(statements[i].o1)); + util_endianswap(&statements[i].o2, 1, sizeof(statements[i].o2)); + util_endianswap(&statements[i].o3, 1, sizeof(statements[i].o3)); + } +} + +void util_swap_defs_fields(prog_section_both_t *section) { + size_t i; + + for (i = 0; i < vec_size(section); ++i) { + util_endianswap(§ion[i].type, 1, sizeof(section[i].type)); + util_endianswap(§ion[i].offset, 1, sizeof(section[i].offset)); + util_endianswap(§ion[i].name, 1, sizeof(section[i].name)); + } +} + +void util_swap_functions(prog_section_function_t *functions) { + size_t i; + + for (i = 0; i < vec_size(functions); ++i) { + util_endianswap(&functions[i].entry, 1, sizeof(functions[i].entry)); + util_endianswap(&functions[i].firstlocal, 1, sizeof(functions[i].firstlocal)); + util_endianswap(&functions[i].locals, 1, sizeof(functions[i].locals)); + util_endianswap(&functions[i].profile, 1, sizeof(functions[i].profile)); + util_endianswap(&functions[i].name, 1, sizeof(functions[i].name)); + util_endianswap(&functions[i].file, 1, sizeof(functions[i].file)); + util_endianswap(&functions[i].nargs, 1, sizeof(functions[i].nargs)); + /* Don't swap argsize[] - it's just a byte array, which Quake uses only as such. */ + } +} + +void util_swap_globals(int32_t *globals) { + util_endianswap(globals, vec_size(globals), sizeof(int32_t)); +} + /* - * 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 +#include +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, @@ -427,14 +517,20 @@ static const uint16_t util_crc16_table[8][256] = {{ 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)]] @@ -445,12 +541,17 @@ uint16_t util_crc16(uint16_t current, const char *k, size_t len) { 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; @@ -460,7 +561,7 @@ uint16_t util_crc16(uint16_t current, const char *k, size_t len) { * 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])