diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index b70014d48..1fd3353bf 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,6 +1,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-branch \ libs/gamecode/test/test-bitops \ + libs/gamecode/test/test-callret \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ libs/gamecode/test/test-conv2 \ @@ -48,6 +49,11 @@ libs_gamecode_test_test_bitops_SOURCES= \ libs_gamecode_test_test_bitops_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_bitops_DEPENDENCIES=$(test_gamecode_libs) +libs_gamecode_test_test_callret_SOURCES= \ + libs/gamecode/test/test-callret.c +libs_gamecode_test_test_callret_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_callret_DEPENDENCIES=$(test_gamecode_libs) + libs_gamecode_test_test_conv0_SOURCES= \ libs/gamecode/test/test-conv0.c libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index 9116bb695..07921d847 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -21,6 +21,9 @@ static int verbose = 0; #define num_statements(statements) \ (sizeof (statements) / sizeof (statements[0])) +#define num_functions(functions) \ + (sizeof (functions) / sizeof (functions[0])) + #define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) #define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) @@ -46,4 +49,6 @@ typedef struct { pr_uint_t think; pr_uint_t nextthink; pr_uint_t frame; + bfunction_t *functions; + pr_uint_t num_functions; } test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index ddae815dd..7a565dece 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -88,7 +88,16 @@ setup_test (test_t *test) test_pr.debug_data = &test_pr; test_pr.pr_trace = 1; test_pr.pr_trace_depth = -1; - test_pr.function_table = test_functions; + if (test->num_functions && test->functions) { + test_pr.function_table = calloc ((test->num_functions + 2), + sizeof (bfunction_t)); + memcpy (test_pr.function_table, test_functions, + 2 * sizeof (bfunction_t)); + memcpy (test_pr.function_table + 2, test->functions, + test->num_functions * sizeof (bfunction_t)); + } else { + test_pr.function_table = test_functions; + } pr_uint_t num_globals = test->num_globals; num_globals += test->extra_globals + test->stack_size; @@ -170,6 +179,9 @@ run_test (test_t *test) pr_uint_t num_globals = test->num_globals; num_globals += test->extra_globals + test->stack_size; + if (test->num_functions && test->functions) { + free (test_pr.function_table); + } Sys_Free (test_pr.pr_globals, num_globals * sizeof (pr_type_t)); free (test_pr.pr_statements); diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c new file mode 100644 index 000000000..988f27936 --- /dev/null +++ b/libs/gamecode/test/test-callret.c @@ -0,0 +1,96 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((float)(x)*(float)(x)) +#define pi_6 0x3f060a92 // pi/6 +#define r3_2 0x3f5db3d7 // sqrt(3)/2 +#define f1_2 0x3f000000 // 1/2 +#define f1 0x3f800000 // 1 +#define f2 0x40000000 // 2 +#define shx 0x3f0c4020 // sinh(pi/6) +#define chx 0x3f91f354 // cosh(pi/6) + +#define STK (32 * 4) // stack ptr just after globals + +static pr_ivec4_t float_callret_init[32] = { + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, +}; + +static pr_ivec4_t float_callret_expect[32] = { + // constants + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, + // result + { r3_2, f1_2, chx, shx }, +}; + +static dstatement_t float_callret_statements[] = { + { OP_STORE_A_1, 7, 0, STK }, // save stack pointer for check + { OP_PUSH_A_1, 1, 0, 0 }, + { OP_CALL_B, 2, 0, 8 }, + { OP_LEA_C, STK, 4, STK }, // discard param + { OP_SUB_I_1, 7, STK, 7 }, // check stack restored + { OP_BREAK }, +// cos_sin_cosh_sinh: +// calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously + { OP_WITH, 2, 0, 1 }, // put params into reg 1 + { OP_LEA_C, STK, -24, STK }, // reserve 24 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 +#define x 0 // in parameters float +#define xn 0 // in locals vec4 +#define x2 4 // in locals vec4 +#define ac 8 // in locals vec4 +#define fa 12 // in locals vec4 +#define fi 16 // in locals vec4 +#define c 20 // in locals int + { OP(2, 0, 1, OP_STORE_A_1), xn+1,0, x }, // init xn to [1, x, 0, 0] + { OP(2, 0, 0, OP_STORE_A_1), xn, 0, 4 }, + { OP(2, 0, 2, OP_SWIZZLE_F), xn, 0x0044, xn }, // xn -> [1, x, 1, x] + { OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, 0, 0, 0] + { OP(2, 0, 2, OP_SWIZZLE_F), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x] + { OP(2, 0, 0, OP_STORE_A_1), fa, 0, 4 }, // init factorial + { OP(2, 0, 0, OP_STORE_A_1), fa+1,0, 5 }, + { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0044, fa }, // fa -> [1, 2, 1, 2] + { OP(0, 0, 2, OP_SWIZZLE_F), 4, 0x0000, fi }, // init fi -> [1, 1, 1, 1] + { OP(2, 2, 2, OP_SUB_F_4), ac, ac, ac }, // init acc (output) to 0 + { OP(0, 0, 2, OP_LEA_A), 25, 0, c }, // init count +// loop: + { OP(2, 2, 2, OP_ADD_F_4), ac, xn, ac }, // acc += xn + { OP(2, 2, 2, OP_MUL_F_4), xn, x2, xn }, // xn *= x2 + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 0, 2, OP_LEA_C), c, -1, c }, // dec count + { OP(0, 0, 2, OP_IFA), -7, 0, c }, // count > 0 + { OP(2, 0, 0, OP_RETURN), ac, 0, 4 }, +}; +#undef x +#undef xn +#undef x2 +#undef ac +#undef fa +#undef fi +#undef c + +static bfunction_t callret_functions[] = { + { .first_statement = 6 }, +}; + +test_t tests[] = { + { + .desc = "callret", + .num_globals = num_globals(float_callret_init,float_callret_expect), + .num_statements = num_statements (float_callret_statements), + .statements = float_callret_statements, + .init_globals = (pr_int_t *) float_callret_init, + .expect_globals = (pr_int_t *) float_callret_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, +}; + +#include "main.c"