mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
Implement parameter alignment in the engine
The engine now requires non-v6 progs to store the log2 alignment for the param struct in .param_alignment. PR_EnterFunction is clearer and possibly more efficient.
This commit is contained in:
parent
7a399c956b
commit
f5741a979e
3 changed files with 64 additions and 50 deletions
|
@ -1079,7 +1079,7 @@ typedef struct {
|
||||||
pr_int_t locals;
|
pr_int_t locals;
|
||||||
pr_int_t profile;
|
pr_int_t profile;
|
||||||
pr_int_t numparms;
|
pr_int_t numparms;
|
||||||
uint8_t parm_size[MAX_PARMS];
|
dparmsize_t parm_size[MAX_PARMS];
|
||||||
dfunction_t *descriptor;
|
dfunction_t *descriptor;
|
||||||
builtin_proc func;
|
builtin_proc func;
|
||||||
} bfunction_t;
|
} bfunction_t;
|
||||||
|
@ -1632,6 +1632,7 @@ struct progs_s {
|
||||||
pr_type_t *pr_saved_params;
|
pr_type_t *pr_saved_params;
|
||||||
int pr_saved_argc;
|
int pr_saved_argc;
|
||||||
int pr_param_size; ///< covers both params and return
|
int pr_param_size; ///< covers both params and return
|
||||||
|
int pr_param_alignment; ///< covers both params and return
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// \name edicts
|
/// \name edicts
|
||||||
|
|
|
@ -142,6 +142,21 @@ PR_PopFrame (progs_t *pr)
|
||||||
pr->pr_xtstr = frame->tstr;
|
pr->pr_xtstr = frame->tstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __attribute__((pure)) long
|
||||||
|
align_offset (long offset, dparmsize_t parmsize)
|
||||||
|
{
|
||||||
|
int mask = (1 << parmsize.alignment) - 1;
|
||||||
|
return (offset + mask) & ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_param (pr_type_t *dst, pr_type_t *src, size_t size)
|
||||||
|
{
|
||||||
|
while (size--) {
|
||||||
|
memcpy (dst++, src++, sizeof (pr_type_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Setup the stackframe prior to calling a progs function. Saves all local
|
/** Setup the stackframe prior to calling a progs function. Saves all local
|
||||||
data the called function will trample on and copies the parameters used
|
data the called function will trample on and copies the parameters used
|
||||||
by the function into the function's local data space.
|
by the function into the function's local data space.
|
||||||
|
@ -153,39 +168,44 @@ PR_PopFrame (progs_t *pr)
|
||||||
static void
|
static void
|
||||||
PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
{
|
{
|
||||||
pr_int_t i, j, c, o;
|
pr_int_t i;
|
||||||
pr_int_t k;
|
pr_type_t *dstParams[MAX_PARMS];
|
||||||
pr_int_t count = 0;
|
|
||||||
int size[2] = {0, 0};
|
|
||||||
long paramofs = 0;
|
long paramofs = 0;
|
||||||
long offs;
|
|
||||||
|
|
||||||
PR_PushFrame (pr);
|
PR_PushFrame (pr);
|
||||||
|
|
||||||
if (f->numparms > 0) {
|
if (f->numparms > 0) {
|
||||||
for (i = 0; i < 2 && i < f->numparms; i++) {
|
paramofs = f->parm_start;
|
||||||
paramofs += f->parm_size[i];
|
for (i = 0; i < f->numparms; i++) {
|
||||||
size[i] = f->parm_size[i];
|
paramofs = align_offset (paramofs, f->parm_size[i]);
|
||||||
|
dstParams[i] = pr->pr_globals + paramofs;
|
||||||
|
paramofs += f->parm_size[i].size;
|
||||||
|
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||||
|
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||||
|
f->parm_size[i].size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
count = i;
|
|
||||||
} else if (f->numparms < 0) {
|
} else if (f->numparms < 0) {
|
||||||
for (i = 0; i < 2 && i < -f->numparms - 1; i++) {
|
paramofs = f->parm_start + 2; // argc and argv
|
||||||
paramofs += f->parm_size[i];
|
for (i = 0; i < -f->numparms - 1; i++) {
|
||||||
size[i] = f->parm_size[i];
|
paramofs = align_offset (paramofs, f->parm_size[i]);
|
||||||
|
dstParams[i] = pr->pr_globals + paramofs;
|
||||||
|
paramofs += f->parm_size[i].size;
|
||||||
|
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||||
|
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||||
|
f->parm_size[i].size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (; i < 2; i++) {
|
dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment };
|
||||||
paramofs += pr->pr_param_size;
|
paramofs = align_offset (paramofs, parmsize );
|
||||||
size[i] = pr->pr_param_size;
|
if (i < MAX_PARMS) {
|
||||||
|
dstParams[i] = pr->pr_globals + paramofs;
|
||||||
}
|
}
|
||||||
count = i;
|
for (; i < MAX_PARMS; i++) {
|
||||||
}
|
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||||
|
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||||
for (i = 0; i < count && i < pr->pr_argc; i++) {
|
f->parm_size[i].size);
|
||||||
offs = (pr->pr_params[i] - pr->pr_globals) - f->parm_start;
|
}
|
||||||
if (offs >= 0 && offs < paramofs) {
|
|
||||||
memcpy (pr->pr_real_params[i], pr->pr_params[i],
|
|
||||||
size[i] * sizeof (pr_type_t));
|
|
||||||
pr->pr_params[i] = pr->pr_real_params[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,43 +214,33 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
pr->pr_xstatement = f->first_statement - 1; // offset the st++
|
pr->pr_xstatement = f->first_statement - 1; // offset the st++
|
||||||
|
|
||||||
// save off any locals that the new function steps on
|
// save off any locals that the new function steps on
|
||||||
c = f->locals;
|
if (pr->localstack_used + f->locals > LOCALSTACK_SIZE)
|
||||||
if (pr->localstack_used + c > LOCALSTACK_SIZE)
|
|
||||||
PR_RunError (pr, "PR_EnterFunction: locals stack overflow");
|
PR_RunError (pr, "PR_EnterFunction: locals stack overflow");
|
||||||
|
|
||||||
memcpy (&pr->localstack[pr->localstack_used],
|
memcpy (&pr->localstack[pr->localstack_used],
|
||||||
&pr->pr_globals[f->parm_start],
|
&pr->pr_globals[f->parm_start],
|
||||||
sizeof (pr_type_t) * c);
|
sizeof (pr_type_t) * f->locals);
|
||||||
pr->localstack_used += c;
|
pr->localstack_used += f->locals;
|
||||||
|
|
||||||
if (pr_deadbeef_locals->int_val)
|
if (pr_deadbeef_locals->int_val)
|
||||||
for (k = f->parm_start; k < f->parm_start + c; k++)
|
for (i = f->parm_start; i < f->parm_start + f->locals; i++)
|
||||||
pr->pr_globals[k].integer_var = 0xdeadbeef;
|
pr->pr_globals[i].integer_var = 0xdeadbeef;
|
||||||
|
|
||||||
// copy parameters
|
// copy parameters
|
||||||
o = f->parm_start;
|
|
||||||
if (f->numparms >= 0) {
|
if (f->numparms >= 0) {
|
||||||
for (i = 0; i < f->numparms; i++) {
|
for (i = 0; i < f->numparms; i++) {
|
||||||
for (j = 0; j < f->parm_size[i]; j++) {
|
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
|
||||||
sizeof (pr_type_t));
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_type_t *argc = &pr->pr_globals[o++];
|
pr_type_t *argc = &pr->pr_globals[f->parm_start + 0];
|
||||||
pr_type_t *argv = &pr->pr_globals[o++];
|
pr_type_t *argv = &pr->pr_globals[f->parm_start + 1];
|
||||||
for (i = 0; i < -f->numparms - 1; i++) {
|
for (i = 0; i < -f->numparms - 1; i++) {
|
||||||
for (j = 0; j < f->parm_size[i]; j++) {
|
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
|
||||||
sizeof (pr_type_t));
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
argc->integer_var = pr->pr_argc - i;
|
argc->integer_var = pr->pr_argc - i;
|
||||||
argv->integer_var = o;
|
argv->integer_var = dstParams[i] - pr->pr_globals;
|
||||||
if (i < MAX_PARMS) {
|
if (i < MAX_PARMS) {
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i),
|
memcpy (dstParams[i], &P_INT (pr, i),
|
||||||
(MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t));
|
(MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,19 +249,18 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
static void
|
static void
|
||||||
PR_LeaveFunction (progs_t *pr)
|
PR_LeaveFunction (progs_t *pr)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
bfunction_t *f = pr->pr_xfunction;
|
bfunction_t *f = pr->pr_xfunction;
|
||||||
|
|
||||||
PR_PopFrame (pr);
|
PR_PopFrame (pr);
|
||||||
|
|
||||||
// restore locals from the stack
|
// restore locals from the stack
|
||||||
c = f->locals;
|
pr->localstack_used -= f->locals;
|
||||||
pr->localstack_used -= c;
|
|
||||||
if (pr->localstack_used < 0)
|
if (pr->localstack_used < 0)
|
||||||
PR_RunError (pr, "PR_LeaveFunction: locals stack underflow");
|
PR_RunError (pr, "PR_LeaveFunction: locals stack underflow");
|
||||||
|
|
||||||
memcpy (&pr->pr_globals[f->parm_start],
|
memcpy (&pr->pr_globals[f->parm_start],
|
||||||
&pr->localstack[pr->localstack_used], sizeof (pr_type_t) * c);
|
&pr->localstack[pr->localstack_used],
|
||||||
|
sizeof (pr_type_t) * f->locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
VISIBLE void
|
VISIBLE void
|
||||||
|
|
|
@ -122,6 +122,7 @@ PR_ResolveGlobals (progs_t *pr)
|
||||||
pr->pr_params[6] = &pr->pr_globals[OFS_PARM6];
|
pr->pr_params[6] = &pr->pr_globals[OFS_PARM6];
|
||||||
pr->pr_params[7] = &pr->pr_globals[OFS_PARM7];
|
pr->pr_params[7] = &pr->pr_globals[OFS_PARM7];
|
||||||
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
|
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
|
||||||
|
pr->pr_param_alignment = 0; // log2
|
||||||
} else {
|
} else {
|
||||||
if (!(def = PR_FindGlobal (pr, sym = ".return")))
|
if (!(def = PR_FindGlobal (pr, sym = ".return")))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -134,6 +135,9 @@ PR_ResolveGlobals (progs_t *pr)
|
||||||
if (!(def = PR_FindGlobal (pr, sym = ".param_size")))
|
if (!(def = PR_FindGlobal (pr, sym = ".param_size")))
|
||||||
goto error;
|
goto error;
|
||||||
pr->pr_param_size = G_INT (pr, def->ofs);
|
pr->pr_param_size = G_INT (pr, def->ofs);
|
||||||
|
if (!(def = PR_FindGlobal (pr, sym = ".param_alignment")))
|
||||||
|
goto error;
|
||||||
|
pr->pr_param_alignment = G_INT (pr, def->ofs);
|
||||||
}
|
}
|
||||||
if (pr->pr_saved_params)
|
if (pr->pr_saved_params)
|
||||||
free (pr->pr_saved_params);
|
free (pr->pr_saved_params);
|
||||||
|
|
Loading…
Reference in a new issue