Allow testsuite to pass on big endian
authorJim Thoenen <the.resident@gmail.com>
Mon, 3 Feb 2014 01:24:59 +0000 (19:24 -0600)
committerJim Thoenen <the.resident@gmail.com>
Tue, 11 Feb 2014 02:31:54 +0000 (20:31 -0600)
Move the progs header and body byteswapping into util functions and
call those functions when either reading or writing the progs.

code.c
exec.c
gmqcc.h
util.c

diff --git a/code.c b/code.c
index 540093f74457d77bb342cfc7955e12b0931508e9..ddfbb977f2b1dd6b451d4d4d3becc4426de1dea7 100644 (file)
--- a/code.c
+++ b/code.c
@@ -260,59 +260,18 @@ static void code_create_header(code_t *code, prog_header_t *code_header, const c
     }
 
     /* ensure all data is in LE format */
-    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));
+    util_swap_header(code_header);
 
     /*
      * These are not part of the header but we ensure LE format here to save on duplicated
      * code.
      */
 
-    for (i = 0; i < vec_size(code->statements); ++i) {
-        util_endianswap(&code->statements[i].opcode,    1, sizeof(code->statements[i].opcode));
-        util_endianswap(&code->statements[i].o1,        1, sizeof(code->statements[i].o1));
-        util_endianswap(&code->statements[i].o2,        1, sizeof(code->statements[i].o2));
-        util_endianswap(&code->statements[i].o3,        1, sizeof(code->statements[i].o3));
-    }
-
-    for (i = 0; i < vec_size(code->defs); ++i) {
-        util_endianswap(&code->defs[i].type,   1, sizeof(code->defs[i].type));
-        util_endianswap(&code->defs[i].offset, 1, sizeof(code->defs[i].offset));
-        util_endianswap(&code->defs[i].name,   1, sizeof(code->defs[i].name));
-    }
-
-    for (i = 0; i < vec_size(code->fields); ++i) {
-        util_endianswap(&code->fields[i].type,   1, sizeof(code->fields[i].type));
-        util_endianswap(&code->fields[i].offset, 1, sizeof(code->fields[i].offset));
-        util_endianswap(&code->fields[i].name,   1, sizeof(code->fields[i].name));
-    }
-
-    for (i = 0; i < vec_size(code->functions); ++i) {
-        util_endianswap(&code->functions[i].entry,         1, sizeof(code->functions[i].entry));
-        util_endianswap(&code->functions[i].firstlocal,    1, sizeof(code->functions[i].firstlocal));
-        util_endianswap(&code->functions[i].locals,        1, sizeof(code->functions[i].locals));
-        util_endianswap(&code->functions[i].profile,       1, sizeof(code->functions[i].profile));
-        util_endianswap(&code->functions[i].name,          1, sizeof(code->functions[i].name));
-        util_endianswap(&code->functions[i].file,          1, sizeof(code->functions[i].file));
-        util_endianswap(&code->functions[i].nargs,         1, sizeof(code->functions[i].nargs));
-        /* Don't swap argsize[] - it's just a byte array, which Quake uses only as such. */
-    }
-
-    util_endianswap(code->globals, vec_size(code->globals), sizeof(int32_t));
-
+    util_swap_statements (code->statements);
+    util_swap_defs_fields(code->defs);
+    util_swap_defs_fields(code->fields);
+    util_swap_functions  (code->functions);
+    util_swap_globals    (code->globals);
 
     if (!OPTS_OPTION_BOOL(OPTION_QUIET)) {
         if (lnofile)
diff --git a/exec.c b/exec.c
index d4e75b82e8b580394a8d0300ead3705b1364486f..0bf9fdf4c484c8363dfedb89da0e7e17cd06c71b 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -66,6 +66,8 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
         return NULL;
     }
 
+    util_swap_header(&header);
+
     if (!skipversion && header.version != 6) {
         loaderror("header says this is a version %i progs, we need version 6\n", header.version);
         fs_file_close(file);
@@ -114,6 +116,12 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
     read_data1(strings);
     read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
 
+    util_swap_statements (prog->code);
+    util_swap_defs_fields(prog->defs);
+    util_swap_defs_fields(prog->fields);
+    util_swap_functions  (prog->functions);
+    util_swap_globals    (prog->globals);
+
     fs_file_close(file);
 
     /* profile counters */
diff --git a/gmqcc.h b/gmqcc.h
index 97f0e4d1774be599c661fe409e18cf1e7522f853..34c0ed8ff60833d5a667f83b68bfd04a3d29f28d 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -627,6 +627,11 @@ enum {
 /* TODO: elide */
 extern const char *util_instr_str[VINSTR_END];
 
+void util_swap_header     (prog_header_t              *code_header);
+void util_swap_statements (prog_section_statement_t   *statements);
+void util_swap_defs_fields(prog_section_both_t        *section);
+void util_swap_functions  (prog_section_function_t    *functions);
+void util_swap_globals    (int32_t                    *globals);
 
 typedef float    qcfloat_t;
 typedef int32_t  qcint_t;
diff --git a/util.c b/util.c
index e634186bd0b56efcf4c1d4c83abcd41202fe5dfe..a1d105aedc215bb22f2402eb10e88a6d970ec38f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -85,8 +85,8 @@ const char *util_instr_str[VINSTR_END] = {
             d[l] = (v << 32) | (v >> 32);
         }
         */
-        l *= 2;
         size_t i;
+        l *= 2;
         for (i = 0; i < l; i += 2) {
             uint32_t v1 = d[i];
             d[i] = d[i+1];
@@ -129,6 +129,64 @@ void util_endianswap(void *_data, size_t count, unsigned int typesize) {
 #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(&section[i].type,   1, sizeof(section[i].type));
+        util_endianswap(&section[i].offset, 1, sizeof(section[i].offset));
+        util_endianswap(&section[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.