diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index b3d26d62f..748fdb635 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -21,7 +21,12 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c -noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) $(swizzle_py) +noinst_PYTHON += \ + $(opcodes_py) \ + $(convert_py) \ + ${extend_py} \ + $(hops_py) \ + $(swizzle_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc @@ -34,6 +39,9 @@ libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} convert_py = $(srcdir)/libs/gamecode/convert.py pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc +extend_py = $(srcdir)/libs/gamecode/extend.py +pr_extend_cinc = $(top_builddir)/libs/gamecode/pr_extend.cinc + hops_py = $(srcdir)/libs/gamecode/hops.py pr_hops_cinc = $(top_builddir)/libs/gamecode/pr_hops.cinc @@ -45,6 +53,7 @@ BUILT_SOURCES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ $(pr_convert_cinc) \ + $(pr_extend_cinc) \ $(pr_hops_cinc) \ $(pr_swizzle32_cinc) \ $(pr_swizzle64_cinc) @@ -53,6 +62,7 @@ CLEANFILES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ $(pr_convert_cinc) \ + $(pr_extend_cinc) \ $(pr_hops_cinc) \ $(pr_swizzle32_cinc) \ $(pr_swizzle64_cinc) @@ -70,6 +80,10 @@ $(pr_convert_cinc): $(convert_py) $(V_PY)$(PYTHON) $(convert_py) table > $(pr_convert_cinc).t && \ $(am__mv) $(pr_convert_cinc).t $(pr_convert_cinc) +$(pr_extend_cinc): $(extend_py) + $(V_PY)$(PYTHON) $(extend_py) table > $(pr_extend_cinc).t && \ + $(am__mv) $(pr_extend_cinc).t $(pr_extend_cinc) + $(pr_hops_cinc): $(hops_py) $(V_PY)$(PYTHON) $(hops_py) table > $(pr_hops_cinc).t && \ $(am__mv) $(pr_hops_cinc).t $(pr_hops_cinc) diff --git a/libs/gamecode/extend.py b/libs/gamecode/extend.py new file mode 100644 index 000000000..99aa9ed81 --- /dev/null +++ b/libs/gamecode/extend.py @@ -0,0 +1,77 @@ +print("""// encoding is teemmm +// t = 0: 32-bit, t = 1: 64-bit +// e = 00: 0 +// e = 01: 1.0 +// e = 10: copy (1-n, 2-4, otherwise 0) +// e = 11: -1.0 +// mmm = 000: 1 -> 2 +// mmm = 001: 1 -> 3 +// mmm = 010: 1 -> 4 +// mmm = 011: 2 -> 3 +// mmm = 100: 2 -> 4 +// mmm = 101: 3 -> 4 +// mmm = 110: reserved +// mmm = 111: reserved +""") + +types = [ + ["ivec2", "ivec3", "ivec4", "ivec3", "ivec4", "ivec4"], + ["lvec2", "lvec3", "lvec4", "lvec3", "lvec4", "lvec4"], +] + +src_types = [ + ["int", "int", "int", "ivec2", "ivec2", "ivec3"], + ["long", "long", "long", "lvec2", "lvec2", "lvec3"], +] + +extend = [ + ["0", "INT32_C(0x3f800000)", "0", "INT32_C(0xbf800000)"], + ["0", "INT64_C(0x3ff0000000000000)", "0", "INT64_C(0xbff0000000000000)"], +] + +def case_str(type, ext, mode): + case = (type << 5) | (ext << 3) | (mode) + return f"case {case:03o}:" + +def dst_str(type, ext, mode): + return f"OPC({types[type][mode]})" + +def cast_str(type, ext, mode): + return f"(pr_{types[type][mode]}_t)" + +def init_str(type, ext, mode): + ext_str = extend[type][ext] + src = f"OPA({src_types[type][mode]})" + if mode == 0: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}" + elif mode == 1: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}, {ext_str}" + elif mode == 2: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}, {ext_str}, {ext_str}" + elif mode == 3: + return f"{src}[0], {src}[1], {ext_str}" + elif mode == 4: + if ext == 2: + return f"{src}[0], {src}[1], {src}[0], {src}[1]" + else: + return f"{src}[0], {src}[1], {ext_str}, {ext_str}" + elif mode == 5: + return f"{src}[0], {src}[1], {src}[2], {ext_str}" + +for type in range(2): + for ext in range(4): + for mode in range(6): # 6, 7 are reserved + case = case_str(type, ext, mode) + dst = dst_str(type, ext, mode) + cast = cast_str(type, ext, mode) + init = init_str(type, ext, mode) + if mode in [1, 3]: + print(f"{case} VectorSet({init}, {dst}); break;"); + else: + print(f"{case} {dst} = {cast} {{ {init} }}; break;"); diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 4ec39a71f..79e1949d9 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -34,7 +34,7 @@ bitmap_txt = """ 1 1111 10oo fbitops 1 1111 1100 convert (conversion mode in st->b) 1 1111 1101 with (mode in st->a, value in st->b, reg in st->c) -1 1111 1110 +1 1111 1110 extend 1 1111 1111 hops """ @@ -204,6 +204,14 @@ fbitops_formats = { ], }, } +extend_formats = { + "opcode": "OP_EXTEND", + "mnemonic": "extend", + "opname": "extend", + "format": "%Ga %Hb %gc", + "widths": "-1, 0, -1", + "types": "ev_void, ev_short, ev_void", +} hops_formats = { "opcode": "OP_HOPS", "mnemonic": "hops", @@ -566,6 +574,7 @@ group_map = { "compare2": compare2_formats, "constant": constant_formats, "convert": convert_formats, + "extend": extend_formats, "fbitops": fbitops_formats, "hops": hops_formats, "jump": jump_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index e8c4f2551..cab230ad6 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2835,7 +2835,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_WITH: pr_with (pr, st); break; - // 1110 spare + case OP_EXTEND: + switch (st->b) { +#include "libs/gamecode/pr_extend.cinc" + default: + PR_RunError (pr, "invalid extend code: %04o", st->b); + } + break; #define OP_hop2(vec, op) ((vec)[0] op (vec)[1]) #define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2]) #define OP_hop4(vec, op) ((vec)[0] op (vec)[1] op (vec)[2] op (vec)[3]) @@ -2843,8 +2849,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) switch (st->b) { #include "libs/gamecode/pr_hops.cinc" default: - PR_RunError (pr, "invalid hops code: %04o", - st->b); + PR_RunError (pr, "invalid hops code: %04o", st->b); } break; default: diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 2cfd9fbf9..dfccd91ae 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -11,6 +11,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv6 \ libs/gamecode/test/test-conv7 \ libs/gamecode/test/test-double \ + libs/gamecode/test/test-extend \ libs/gamecode/test/test-float \ libs/gamecode/test/test-hops \ libs/gamecode/test/test-int \ @@ -101,6 +102,11 @@ libs_gamecode_test_test_double_SOURCES= \ libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_double_DEPENDENCIES=$(test_gamecode_libs) +libs_gamecode_test_test_extend_SOURCES= \ + libs/gamecode/test/test-extend.c +libs_gamecode_test_test_extend_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_extend_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_float_SOURCES= \ libs/gamecode/test/test-float.c libs_gamecode_test_test_float_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-extend.c b/libs/gamecode/test/test-extend.c new file mode 100644 index 000000000..bd05ab394 --- /dev/null +++ b/libs/gamecode/test/test-extend.c @@ -0,0 +1,223 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define _ -6.259853398707798e+18 // 0xdeadbeef + +static pr_vec4_t float_extend_init[] = { + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { 2, 3, 4, 5 }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, +}; + +static pr_vec4_t float_extend_expect[] = { + { 5, 0, _, _ }, + { 4, 0, 0, _ }, + { 3, 0, 0, 0 }, + { 4, 5, 0, _ }, + { 2, 3, 0, 0 }, + { 3, 4, 5, 0 }, + { 2, 3, 4, 5 }, + { _, _, 4, 1 }, + { _, 3, 1, 1 }, + { 2, 1, 1, 1 }, + { _, 4, 5, 1 }, + { 2, 3, 1, 1 }, + { 2, 3, 4, 1 }, + { _, _, _, _ }, + { 5, 5, _, _ }, + { 4, 4, 4, _ }, + { 3, 3, 3, 3 }, + { 4, 5, 0, _ }, + { 2, 3, 2, 3 }, + { 3, 4, 5, 0 }, + { _, _, _, _ }, + { _, _, 4, -1 }, + { _, 3, -1, -1 }, + { 2, -1, -1, -1 }, + { _, 4, 5, -1 }, + { 2, 3, -1, -1 }, + { 2, 3, 4, -1 }, + { _, _, _, _ }, +}; + +static dstatement_t float_extend_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 0, 28, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 56, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 84, 3 }, + + { OP(0, 0, 0, OP_EXTEND), 27, 000, 0 }, + { OP(0, 0, 0, OP_EXTEND), 26, 001, 4 }, + { OP(0, 0, 0, OP_EXTEND), 25, 002, 8 }, + { OP(0, 0, 0, OP_EXTEND), 26, 003, 12 }, + { OP(0, 0, 0, OP_EXTEND), 24, 004, 16 }, + { OP(0, 0, 0, OP_EXTEND), 25, 005, 20 }, + + { OP(0, 0, 1, OP_EXTEND), 26, 010, 2 }, + { OP(0, 0, 1, OP_EXTEND), 25, 011, 5 }, + { OP(0, 0, 1, OP_EXTEND), 24, 012, 8 }, + { OP(0, 0, 1, OP_EXTEND), 26, 013, 13 }, + { OP(0, 0, 1, OP_EXTEND), 24, 014, 16 }, + { OP(0, 0, 1, OP_EXTEND), 24, 015, 20 }, + + { OP(0, 0, 2, OP_EXTEND), 27, 020, 0 }, + { OP(0, 0, 2, OP_EXTEND), 26, 021, 4 }, + { OP(0, 0, 2, OP_EXTEND), 25, 022, 8 }, + { OP(0, 0, 2, OP_EXTEND), 26, 023, 12 }, + { OP(0, 0, 2, OP_EXTEND), 24, 024, 16 }, + { OP(0, 0, 2, OP_EXTEND), 25, 025, 20 }, + + { OP(0, 0, 3, OP_EXTEND), 26, 030, 2 }, + { OP(0, 0, 3, OP_EXTEND), 25, 031, 5 }, + { OP(0, 0, 3, OP_EXTEND), 24, 032, 8 }, + { OP(0, 0, 3, OP_EXTEND), 26, 033, 13 }, + { OP(0, 0, 3, OP_EXTEND), 24, 034, 16 }, + { OP(0, 0, 3, OP_EXTEND), 24, 035, 20 }, +}; + +#undef _ +#define _ -1.1885959257070704e+148 // 0xdeadbeefdeadbeef + +static pr_dvec4_t double_extend_init[] = { + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { 2, 3, 4, 5 }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, +}; + +static pr_dvec4_t double_extend_expect[] = { + { 5, 0, _, _ }, + { 4, 0, 0, _ }, + { 3, 0, 0, 0 }, + { 4, 5, 0, _ }, + { 2, 3, 0, 0 }, + { 3, 4, 5, 0 }, + { 2, 3, 4, 5 }, + { _, _, 4, 1 }, + { _, 3, 1, 1 }, + { 2, 1, 1, 1 }, + { _, 4, 5, 1 }, + { 2, 3, 1, 1 }, + { 2, 3, 4, 1 }, + { _, _, _, _ }, + { 5, 5, _, _ }, + { 4, 4, 4, _ }, + { 3, 3, 3, 3 }, + { 4, 5, 0, _ }, + { 2, 3, 2, 3 }, + { 3, 4, 5, 0 }, + { _, _, _, _ }, + { _, _, 4, -1 }, + { _, 3, -1, -1 }, + { 2, -1, -1, -1 }, + { _, 4, 5, -1 }, + { 2, 3, -1, -1 }, + { 2, 3, 4, -1 }, + { _, _, _, _ }, +}; + +static dstatement_t double_extend_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 0, 56, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 112, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 168, 3 }, + + { OP(0, 0, 0, OP_EXTEND), 54, 040, 0 }, + { OP(0, 0, 0, OP_EXTEND), 52, 041, 8 }, + { OP(0, 0, 0, OP_EXTEND), 50, 042, 16 }, + { OP(0, 0, 0, OP_EXTEND), 52, 043, 24 }, + { OP(0, 0, 0, OP_EXTEND), 48, 044, 32 }, + { OP(0, 0, 0, OP_EXTEND), 50, 045, 40 }, + + { OP(0, 0, 1, OP_EXTEND), 52, 050, 4 }, + { OP(0, 0, 1, OP_EXTEND), 50, 051, 10 }, + { OP(0, 0, 1, OP_EXTEND), 48, 052, 16 }, + { OP(0, 0, 1, OP_EXTEND), 52, 053, 26 }, + { OP(0, 0, 1, OP_EXTEND), 48, 054, 32 }, + { OP(0, 0, 1, OP_EXTEND), 48, 055, 40 }, + + { OP(0, 0, 2, OP_EXTEND), 54, 060, 0 }, + { OP(0, 0, 2, OP_EXTEND), 52, 061, 8 }, + { OP(0, 0, 2, OP_EXTEND), 50, 062, 16 }, + { OP(0, 0, 2, OP_EXTEND), 52, 063, 24 }, + { OP(0, 0, 2, OP_EXTEND), 48, 064, 32 }, + { OP(0, 0, 2, OP_EXTEND), 50, 065, 40 }, + + { OP(0, 0, 3, OP_EXTEND), 52, 070, 4 }, + { OP(0, 0, 3, OP_EXTEND), 50, 071, 10 }, + { OP(0, 0, 3, OP_EXTEND), 48, 072, 16 }, + { OP(0, 0, 3, OP_EXTEND), 52, 073, 26 }, + { OP(0, 0, 3, OP_EXTEND), 48, 074, 32 }, + { OP(0, 0, 3, OP_EXTEND), 48, 075, 40 }, +}; + +test_t tests[] = { + { + .desc = "float extend", + .num_globals = num_globals(float_extend_init,float_extend_expect), + .num_statements = num_statements (float_extend_statements), + .statements = float_extend_statements, + .init_globals = (pr_int_t *) float_extend_init, + .expect_globals = (pr_int_t *) float_extend_expect, + }, + { + .desc = "double extend", + .num_globals = num_globals(double_extend_init,double_extend_expect), + .num_statements = num_statements (double_extend_statements), + .statements = double_extend_statements, + .init_globals = (pr_int_t *) double_extend_init, + .expect_globals = (pr_int_t *) double_extend_expect, + }, +}; + +#include "main.c"