mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 06:51:47 +00:00
implement Raven's calling convention (rcall: first 2 params in opb and
opc). should give a general speedup to most progs.
This commit is contained in:
parent
be83a5f5c0
commit
762aefc9b1
17 changed files with 125 additions and 10 deletions
|
@ -20,6 +20,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv)
|
|||
for (i = 0; i < argc; i++)
|
||||
pr_argv[i] = PR_SetTempString (pr, argv[1 + i]);
|
||||
pr_argv[i] = 0;
|
||||
PR_RESET_PARAMS (pr);
|
||||
P_INT (pr, 0) = argc;
|
||||
P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv);
|
||||
PR_ExecuteProgram (pr, progs_main);
|
||||
|
|
|
@ -306,6 +306,16 @@ typedef enum {
|
|||
OP_LOADB_Q,
|
||||
OP_LOADBI_Q,
|
||||
OP_ADDRESS_Q,
|
||||
|
||||
OP_RCALL0,
|
||||
OP_RCALL1,
|
||||
OP_RCALL2,
|
||||
OP_RCALL3,
|
||||
OP_RCALL4,
|
||||
OP_RCALL5,
|
||||
OP_RCALL6,
|
||||
OP_RCALL7,
|
||||
OP_RCALL8,
|
||||
} pr_opcode_e;
|
||||
|
||||
typedef struct opcode_s {
|
||||
|
|
|
@ -67,6 +67,16 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(pri
|
|||
*/
|
||||
//@{
|
||||
|
||||
/** Ensure P_* macros point to the right place for passing parameters to progs
|
||||
functions.
|
||||
\param pr pointer to progs_t VM struct
|
||||
*/
|
||||
#define PR_RESET_PARAMS(pr) \
|
||||
do { \
|
||||
(pr)->pr_params[0] = (pr)->pr_real_params[0]; \
|
||||
(pr)->pr_params[1] = (pr)->pr_real_params[1]; \
|
||||
} while (0)
|
||||
|
||||
/** Push an execution frame onto the VM stack. Saves current execution state
|
||||
\param pr pointer to progs_t VM struct
|
||||
*/
|
||||
|
@ -1200,6 +1210,7 @@ struct progs_s {
|
|||
|
||||
pr_type_t *pr_return;
|
||||
pr_type_t *pr_params[MAX_PARMS];
|
||||
pr_type_t *pr_real_params[MAX_PARMS];
|
||||
int pr_param_size; ///< covers both params and return
|
||||
|
||||
int pr_edict_size; ///< in bytes
|
||||
|
|
|
@ -522,6 +522,7 @@ Menu_Draw (view_t *view)
|
|||
*menu_pr_state.globals.time = *con_data.realtime;
|
||||
|
||||
if (menu->draw) {
|
||||
PR_RESET_PARAMS (&menu_pr_state);
|
||||
P_INT (&menu_pr_state, 0) = x;
|
||||
P_INT (&menu_pr_state, 1) = y;
|
||||
PR_ExecuteProgram (&menu_pr_state, menu->draw);
|
||||
|
@ -551,6 +552,7 @@ Menu_Draw (view_t *view)
|
|||
return;
|
||||
item = menu->items[menu->cur_item];
|
||||
if (menu->cursor) {
|
||||
PR_RESET_PARAMS (&menu_pr_state);
|
||||
P_INT (&menu_pr_state, 0) = x + item->x;
|
||||
P_INT (&menu_pr_state, 1) = y + item->y;
|
||||
PR_ExecuteProgram (&menu_pr_state, menu->cursor);
|
||||
|
@ -576,6 +578,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down)
|
|||
if (!menu)
|
||||
return;
|
||||
if (menu->keyevent) {
|
||||
PR_RESET_PARAMS (&menu_pr_state);
|
||||
P_INT (&menu_pr_state, 0) = key;
|
||||
P_INT (&menu_pr_state, 1) = unicode;
|
||||
P_INT (&menu_pr_state, 2) = down;
|
||||
|
@ -586,6 +589,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down)
|
|||
&& menu->items[menu->cur_item]->allkeys) {
|
||||
PR_PushFrame (&menu_pr_state);
|
||||
item = menu->items[menu->cur_item];
|
||||
PR_RESET_PARAMS (&menu_pr_state);
|
||||
P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state,
|
||||
item->text);
|
||||
P_INT (&menu_pr_state, 1) = key;
|
||||
|
@ -613,6 +617,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down)
|
|||
item = menu->items[menu->cur_item];
|
||||
if (item->func) {
|
||||
PR_PushFrame (&menu_pr_state);
|
||||
PR_RESET_PARAMS (&menu_pr_state);
|
||||
P_STRING (&menu_pr_state, 0) =
|
||||
PR_SetTempString (&menu_pr_state, item->text);
|
||||
P_INT (&menu_pr_state, 1) = key;
|
||||
|
|
|
@ -91,6 +91,7 @@ bi_gib_builtin_f (void)
|
|||
for (i = 0; i < GIB_Argc(); i++)
|
||||
pr_list[i].integer_var = PR_SetTempString (builtin->pr, GIB_Argv(i));
|
||||
|
||||
PR_RESET_PARAMS (builtin->pr);
|
||||
P_INT (builtin->pr, 0) = GIB_Argc();
|
||||
P_INT (builtin->pr, 1) = PR_SetPointer (builtin->pr, pr_list);
|
||||
PR_ExecuteProgram (builtin->pr, builtin->func);
|
||||
|
|
|
@ -772,6 +772,21 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
break;
|
||||
|
||||
case OP_RCALL2:
|
||||
case OP_RCALL3:
|
||||
case OP_RCALL4:
|
||||
case OP_RCALL5:
|
||||
case OP_RCALL6:
|
||||
case OP_RCALL7:
|
||||
case OP_RCALL8:
|
||||
pr->pr_params[1] = &OPC;
|
||||
goto op_rcall;
|
||||
case OP_RCALL1:
|
||||
pr->pr_params[1] = pr->pr_real_params[1];
|
||||
op_rcall:
|
||||
pr->pr_params[0] = &OPB;
|
||||
pr->pr_argc = st->op - OP_RCALL1 + 1;
|
||||
goto op_call;
|
||||
case OP_CALL0:
|
||||
case OP_CALL1:
|
||||
case OP_CALL2:
|
||||
|
@ -781,9 +796,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
case OP_CALL6:
|
||||
case OP_CALL7:
|
||||
case OP_CALL8:
|
||||
PR_RESET_PARAMS (pr);
|
||||
pr->pr_argc = st->op - OP_CALL0;
|
||||
op_call:
|
||||
pr->pr_xfunction->profile += profile - startprofile;
|
||||
startprofile = profile;
|
||||
pr->pr_argc = st->op - OP_CALL0;
|
||||
PR_CallFunction (pr, OPA.func_var);
|
||||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
break;
|
||||
|
|
|
@ -822,6 +822,46 @@ opcode_t pr_opcodes[] = {
|
|||
PROG_ID_VERSION,
|
||||
"%Ga",
|
||||
},
|
||||
{"<RCALL1>", "rcall1", OP_RCALL1, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb",
|
||||
},
|
||||
{"<RCALL2>", "rcall2", OP_RCALL2, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL3>", "rcall3", OP_RCALL3, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL4>", "rcall4", OP_RCALL4, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL5>", "rcall5", OP_RCALL5, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL6>", "rcall6", OP_RCALL6, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL7>", "rcall7", OP_RCALL7, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
{"<RCALL8>", "rcall8", OP_RCALL8, false,
|
||||
ev_func, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, %Vb, %Vc",
|
||||
},
|
||||
|
||||
{"<STATE>", "state", OP_STATE, false,
|
||||
ev_float, ev_func, ev_void,
|
||||
|
@ -1231,6 +1271,20 @@ PR_Check_Opcodes (progs_t *pr)
|
|||
check_global (pr, st, op, ev_void, st->b);
|
||||
check_global (pr, st, op, ev_void, st->c);
|
||||
break;
|
||||
case OP_RCALL1:
|
||||
check_global (pr, st, op, ev_void, st->c);
|
||||
case OP_RCALL2:
|
||||
case OP_RCALL3:
|
||||
case OP_RCALL4:
|
||||
case OP_RCALL5:
|
||||
case OP_RCALL6:
|
||||
case OP_RCALL7:
|
||||
case OP_RCALL8:
|
||||
if (st->op > OP_RCALL1)
|
||||
check_global (pr, st, op, ev_integer, st->c);
|
||||
check_global (pr, st, op, ev_integer, st->b);
|
||||
check_global (pr, st, op, ev_func, st->a);
|
||||
break;
|
||||
case OP_STATE:
|
||||
case OP_STATE_F:
|
||||
if (!state_ok) {
|
||||
|
|
|
@ -487,6 +487,7 @@ ED_LoadFromFile (progs_t *pr, const char *data)
|
|||
|
||||
if (pr->edict_parse) {
|
||||
PR_PushFrame (pr);
|
||||
PR_RESET_PARAMS (pr);
|
||||
P_INT (pr, 0) = PR_SetTempString (pr, data);
|
||||
PR_ExecuteProgram (pr, pr->edict_parse);
|
||||
PR_PopFrame (pr);
|
||||
|
|
|
@ -138,6 +138,7 @@ PR_ResolveGlobals (progs_t *pr)
|
|||
goto error;
|
||||
pr->pr_param_size = G_INT (pr, def->ofs);
|
||||
}
|
||||
memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params));
|
||||
if (!pr->globals.time) {
|
||||
if ((def = PR_FindGlobal (pr, "time")))
|
||||
pr->globals.time = &G_FLOAT (pr, def->ofs);
|
||||
|
|
|
@ -98,6 +98,7 @@ static const char *
|
|||
bi_get_key (void *key, void *_ht)
|
||||
{
|
||||
bi_hashtab_t *ht = (bi_hashtab_t *)_ht;
|
||||
PR_RESET_PARAMS (ht->pr);
|
||||
P_INT (ht->pr, 0) = (long) (key);
|
||||
P_INT (ht->pr, 1) = ht->ud;
|
||||
PR_ExecuteProgram (ht->pr, ht->gk);
|
||||
|
@ -108,6 +109,7 @@ static unsigned long
|
|||
bi_get_hash (void *key, void *_ht)
|
||||
{
|
||||
bi_hashtab_t *ht = (bi_hashtab_t *)_ht;
|
||||
PR_RESET_PARAMS (ht->pr);
|
||||
P_INT (ht->pr, 0) = (long) (key);
|
||||
P_INT (ht->pr, 1) = ht->ud;
|
||||
PR_ExecuteProgram (ht->pr, ht->gh);
|
||||
|
@ -118,6 +120,7 @@ static int
|
|||
bi_compare (void *key1, void *key2, void *_ht)
|
||||
{
|
||||
bi_hashtab_t *ht = (bi_hashtab_t *)_ht;
|
||||
PR_RESET_PARAMS (ht->pr);
|
||||
P_INT (ht->pr, 0) = (long) (key1);
|
||||
P_INT (ht->pr, 1) = (long) (key2);
|
||||
P_INT (ht->pr, 2) = ht->ud;
|
||||
|
@ -129,6 +132,7 @@ static void
|
|||
bi_free (void *key, void *_ht)
|
||||
{
|
||||
bi_hashtab_t *ht = (bi_hashtab_t *)_ht;
|
||||
PR_RESET_PARAMS (ht->pr);
|
||||
P_INT (ht->pr, 0) = (long) (key);
|
||||
P_INT (ht->pr, 1) = ht->ud;
|
||||
PR_ExecuteProgram (ht->pr, ht->f);
|
||||
|
|
|
@ -1013,6 +1013,7 @@ rua_obj_msgSend_super (progs_t *pr)
|
|||
PR_GetString (pr, object_get_class_name (pr, self)),
|
||||
PR_GetString (pr, pr->selector_names[_cmd->sel_id]));
|
||||
}
|
||||
pr->pr_params[0] = pr->pr_real_params[0];
|
||||
P_POINTER (pr, 0) = super->self;
|
||||
PR_CallFunction (pr, imp);
|
||||
}
|
||||
|
|
|
@ -892,6 +892,7 @@ SV_SetLocalinfo (const char *key, const char *value)
|
|||
*sv_globals.time = sv.time;
|
||||
*sv_globals.self = 0;
|
||||
PR_PushFrame (&sv_pr_state);
|
||||
PR_RESET_PARAMS (&sv_pr_state);
|
||||
P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key);
|
||||
P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue);
|
||||
P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value);
|
||||
|
|
|
@ -345,6 +345,7 @@ PF_calltimeofday (progs_t * pr)
|
|||
Sys_TimeOfDay (&date);
|
||||
|
||||
PR_PushFrame (&sv_pr_state);
|
||||
PR_RESET_PARAMS (pr);
|
||||
P_FLOAT (pr, 0) = (float) date.sec;
|
||||
P_FLOAT (pr, 1) = (float) date.min;
|
||||
P_FLOAT (pr, 2) = (float) date.hour;
|
||||
|
|
|
@ -858,6 +858,7 @@ SV_Say (qboolean team)
|
|||
|
||||
if (sv_funcs.ChatMessage) {
|
||||
PR_PushFrame (&sv_pr_state);
|
||||
PR_RESET_PARAMS (&sv_pr_state);
|
||||
P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, p);
|
||||
G_FLOAT (&sv_pr_state, 1) = (float) team;
|
||||
|
||||
|
@ -1176,6 +1177,7 @@ SV_SetUserinfo (client_t *client, const char *key, const char *value)
|
|||
PR_PushFrame (&sv_pr_state);
|
||||
*sv_globals.time = sv.time;
|
||||
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, client->edict);
|
||||
PR_RESET_PARAMS (&sv_pr_state);
|
||||
P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key);
|
||||
P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue);
|
||||
P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value);
|
||||
|
@ -1225,6 +1227,7 @@ SV_SetInfo_f (void *unused)
|
|||
if (sv_funcs.UserInfoCallback) {
|
||||
PR_PushFrame (&sv_pr_state);
|
||||
*sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player);
|
||||
PR_RESET_PARAMS (&sv_pr_state);
|
||||
P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key);
|
||||
P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, value);
|
||||
PR_ExecuteProgram (&sv_pr_state, sv_funcs.UserInfoCallback);
|
||||
|
|
|
@ -25,4 +25,4 @@ o CSE optimizations. Hard?
|
|||
o fix local structure used/uninitialized warnings
|
||||
o arrays in entities/structures?
|
||||
o try to reduce memory consumption
|
||||
? pass the first two parms in call->b and call->c
|
||||
X pass the first two parms in call->b and call->c
|
||||
|
|
|
@ -142,12 +142,8 @@ emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b,
|
|||
statement->b = var_b ? var_b->ofs : 0;
|
||||
if (op->type_c == ev_void || op->right_associative) {
|
||||
// ifs, gotos, and assignments don't need vars allocated
|
||||
if (op->type_c == ev_void) {
|
||||
var_c = NULL;
|
||||
statement->c = 0;
|
||||
} else {
|
||||
if (var_c)
|
||||
statement->c = var_c->ofs;
|
||||
}
|
||||
ret = var_a;
|
||||
} else { // allocate result space
|
||||
if (!var_c) {
|
||||
|
@ -205,10 +201,12 @@ emit_function_call (expr_t *e, def_t *dest)
|
|||
def_t *ret;
|
||||
def_t *arg;
|
||||
def_t *p;
|
||||
def_t *a[2] = {0, 0};
|
||||
expr_t *earg;
|
||||
expr_t *parm;
|
||||
opcode_t *op;
|
||||
int count = 0, ind;
|
||||
const char *pref = "";
|
||||
|
||||
for (earg = e->e.expr.e2; earg; earg = earg->next)
|
||||
count++;
|
||||
|
@ -216,6 +214,11 @@ emit_function_call (expr_t *e, def_t *dest)
|
|||
for (earg = e->e.expr.e2; earg; earg = earg->next) {
|
||||
ind--;
|
||||
parm = new_param_expr (get_type (earg), ind);
|
||||
if (options.code.progsversion != PROG_ID_VERSION && ind < 2) {
|
||||
pref = "R";
|
||||
a[ind] = emit_sub_expr (earg, emit_sub_expr (parm, 0));
|
||||
continue;
|
||||
}
|
||||
if (extract_type (parm) == ev_struct) {
|
||||
expr_t *a = assign_expr (parm, earg);
|
||||
a->line = e->line;
|
||||
|
@ -246,9 +249,9 @@ emit_function_call (expr_t *e, def_t *dest)
|
|||
}
|
||||
}
|
||||
}
|
||||
op = opcode_find (va ("<CALL%d>", count), &type_function, &type_void,
|
||||
&type_void);
|
||||
emit_statement (e, op, func, 0, 0);
|
||||
op = opcode_find (va ("<%sCALL%d>", pref, count),
|
||||
&type_function, &type_void, &type_void);
|
||||
emit_statement (e, op, func, a[0], a[1]);
|
||||
|
||||
ret = emit_sub_expr (new_ret_expr (func->type->aux_type), 0);
|
||||
if (dest) {
|
||||
|
|
|
@ -174,6 +174,7 @@ main (int argc, char **argv)
|
|||
main_func = dfunc - pr.pr_functions;
|
||||
else
|
||||
PR_Undefined (&pr, "function", "main");
|
||||
PR_RESET_PARAMS (&pr);
|
||||
P_INT (&pr, 0) = pr_argc;
|
||||
P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv);
|
||||
PR_ExecuteProgram (&pr, main_func);
|
||||
|
|
Loading…
Reference in a new issue