quakeforge/libs/gamecode/test/test-callret.c

209 lines
6.4 KiB
C

#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 DB 0xdeadbeef
#define STK (32 * 4) // stack ptr just after globals
static pr_ivec4_t callret_init[32] = {
{ 0, pi_6, 2, 0},
{ f1, f2, 0, 0},
// result
{ DB, DB, DB, DB },
// pre-call with
{ DB, DB, DB, DB },
// post-call with
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
};
static pr_ivec4_t callret_expect[32] = {
// constants
{ 0, pi_6, 2, 0 },
{ f1, f2, 0, 0 },
// result
{ r3_2, f1_2, chx, shx },
// pre-call with: should be all 0 on progs init
{ 0, 0, 0, 0 },
// post-call with; should be restored to pre-call values (in this case,
// progs init)
{ 0, 0, 0, 0 },
{ DB, DB, DB, DB },
};
static dstatement_t callret_statements[] = {
{ OP_WITH, 8, 0, 0 }, // pushregs
{ OP_POP_A_4, 12, 0, 0 },
{ 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_WITH, 8, 0, 0 }, // pushregs
{ OP_POP_A_4, 16, 0, 0 },
{ OP_BREAK },
// cos_sin_cosh_sinh:
// calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously
[32]=
{ 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, ?, ?, ?]
{ 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(2, 0, 2, OP_SWIZZLE_F), fa, 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, 3 }, // size is (c&31)+1
#undef x
#undef xn
#undef x2
#undef ac
#undef fa
#undef fi
#undef c
};
static pr_ivec4_t call32_init[32] = {
{ 0, 2, 0, 0 },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
{ DB, DB, DB, DB },
};
static pr_ivec4_t call32_expect[32] = {
{ 0, 2, 0, 0 },
{ 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 10, 11 },
{ 12, 13, 14, 15 },
{ 16, 17, 18, 19 },
{ 20, 21, 22, 23 },
{ 24, 25, 26, 27 },
{ 28, 29, 30, 31 },
};
static dstatement_t call32_statements[] = {
{ OP_CALL_B, 1, 0, 4 },
{ OP_BREAK },
[32]=
{ OP_LEA_C, STK, -36, STK }, // reserve 36 words on the stack
{ OP_WITH, 2, 0, 2 }, // put locals into reg 2
{ OP(0, 0, 2, OP_LEA_A), 32, 0, 32 }, // init index
{ OP(2, 0, 2, OP_LEA_A), 0, 0, 33 }, // init base to array
//loop:
{ OP(0, 0, 2, OP_IFBE), 4, 0, 32 }, // if index-- > 0
{ OP(2, 0, 2, OP_LEA_C), 32, -1, 32 },
{ OP(2, 2, 2, OP_STORE_D_1), 33, 32, 32 }, // array[index] = index
{ OP(0, 0, 0, OP_JUMP_A), -3, 0, 0 },
{ OP(2, 0, 0, OP_RETURN), 0, 0, 0x1f }, // only bits 0-5 are size
};
static pr_ivec4_t callchain_init[32] = {
{ 0, 2, 3, 4 },
{ DB, DB, DB, DB },
};
static pr_ivec4_t callchain_expect[32] = {
{ 0, 2, 3, 4 },
{ 42, DB, DB, DB },
};
static dstatement_t callchain_statements[] = {
{ OP_CALL_B, 1, 0, 4 },
{ OP_BREAK },
[32]=
{ OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack
{ OP_WITH, 2, 0, 2 }, // put locals into reg 2
{ OP(0, 0, 2, OP_CALL_B), 2, 0, 0 },
{ OP(0, 0, 2, OP_CALL_B), 3, 0, 1 },
{ OP(2, 0, 0, OP_RETURN), 0, 0, 0 },
[64]=
{ OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack
{ OP_WITH, 2, 0, 2 }, // put locals into reg 2
{ OP(0, 0, 2, OP_LEA_A), 42, 0, 0 }, // init value
{ OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, // return value
[96]=
{ OP_RETURN, 0, 0, -1 } // void return
};
static bfunction_t callret_functions[] = {
{ .first_statement = 32 },
{ .first_statement = 64 },
{ .first_statement = 96 },
};
test_t tests[] = {
{
.desc = "callret",
.num_globals = num_globals(callret_init,callret_expect),
.num_statements = num_statements (callret_statements),
.statements = callret_statements,
.init_globals = (pr_int_t *) callret_init,
.expect_globals = (pr_int_t *) callret_expect,
.functions = callret_functions,
.num_functions = num_functions(callret_functions),
.stack_size = 128,
},
{
.desc = "call32",
.num_globals = num_globals(call32_init,call32_expect),
.num_statements = num_statements (call32_statements),
.statements = call32_statements,
.init_globals = (pr_int_t *) call32_init,
.expect_globals = (pr_int_t *) call32_expect,
.functions = callret_functions,
.num_functions = num_functions(callret_functions),
.stack_size = 128,
},
{
.desc = "callchain",
.num_globals = num_globals(callchain_init,callchain_expect),
.num_statements = num_statements (callchain_statements),
.statements = callchain_statements,
.init_globals = (pr_int_t *) callchain_init,
.expect_globals = (pr_int_t *) callchain_expect,
.functions = callret_functions,
.num_functions = num_functions(callret_functions),
.stack_size = 128,
},
};
#include "main.c"