mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 06:10:56 +00:00
pr_comp.h:
- new opcodes for pointers progs.h: - prototype PR_Check_Opcodes pr_edict.c: - move the static bounds checking to PR_Check_Opcodes in pr_opcode.c pr_exec.c: - vector instruction cleanup - temporarily nuke bounds checking from storep.* - move base of address results from pr->edicts to pr->pr_globals - implement new pointer related instructions - nuke proposed global pointer instructions (not flexible enough) pr_opcode.c: - add new pointer instuctions - re-implement static bounds/invalid opcode checking. no more multiple case statements to keep track of.
This commit is contained in:
parent
08a211385f
commit
5bf5278c2b
5 changed files with 187 additions and 281 deletions
|
@ -172,6 +172,35 @@ typedef enum {
|
|||
|
||||
OP_MOD_F,
|
||||
OP_MOD_I,
|
||||
|
||||
OP_LOADB_F,
|
||||
OP_LOADB_V,
|
||||
OP_LOADB_S,
|
||||
OP_LOADB_ENT,
|
||||
OP_LOADB_FLD,
|
||||
OP_LOADB_FNC,
|
||||
OP_LOADB_I,
|
||||
OP_LOADB_P,
|
||||
|
||||
OP_STOREB_F,
|
||||
OP_STOREB_V,
|
||||
OP_STOREB_S,
|
||||
OP_STOREB_ENT,
|
||||
OP_STOREB_FLD,
|
||||
OP_STOREB_FNC,
|
||||
OP_STOREB_I,
|
||||
OP_STOREB_P,
|
||||
|
||||
OP_ADDRESS_F,
|
||||
OP_ADDRESS_V,
|
||||
OP_ADDRESS_S,
|
||||
OP_ADDRESS_ENT,
|
||||
OP_ADDRESS_FLD,
|
||||
OP_ADDRESS_FNC,
|
||||
OP_ADDRESS_I,
|
||||
OP_ADDRESS_P,
|
||||
|
||||
OP_LEA,
|
||||
} pr_opcode_e;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -75,6 +75,7 @@ void PR_LoadProgs (progs_t *pr, const char *progsname);
|
|||
void PR_LoadStrings (progs_t *pr);
|
||||
void PR_LoadDebug (progs_t *pr);
|
||||
edict_t *PR_InitEdicts (progs_t *pr, int num_edicts);
|
||||
void PR_Check_Opcodes (progs_t *pr);
|
||||
|
||||
void PR_Profile_f (void);
|
||||
|
||||
|
|
|
@ -1180,7 +1180,6 @@ void
|
|||
PR_LoadProgs (progs_t * pr, const char *progsname)
|
||||
{
|
||||
int i;
|
||||
dstatement_t *st;
|
||||
|
||||
PR_LoadProgsFile (pr, progsname);
|
||||
if (!pr->progs)
|
||||
|
@ -1209,159 +1208,7 @@ PR_LoadProgs (progs_t * pr, const char *progsname)
|
|||
|
||||
PR_LoadDebug (pr);
|
||||
|
||||
// LordHavoc: bounds check anything static
|
||||
for (i = 0, st = pr->pr_statements;
|
||||
i < pr->progs->numstatements;
|
||||
i++, st++) {
|
||||
switch (st->op) {
|
||||
case OP_IF:
|
||||
case OP_IFNOT:
|
||||
if (st->a >= pr->progs->numglobals
|
||||
|| (short)st->b + i < 0
|
||||
|| (short)st->b + i >= pr->progs->numstatements)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
case OP_GOTO:
|
||||
if ((short)st->a + i < 0
|
||||
|| (short)st->a + i >= pr->progs->numstatements)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds GOTO (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
// global global global
|
||||
case OP_ADD_F:
|
||||
case OP_ADD_V:
|
||||
case OP_SUB_F:
|
||||
case OP_SUB_V:
|
||||
case OP_MUL_F:
|
||||
case OP_MUL_V:
|
||||
case OP_MUL_FV:
|
||||
case OP_MUL_VF:
|
||||
case OP_DIV_F:
|
||||
case OP_BITAND:
|
||||
case OP_BITOR:
|
||||
case OP_ADD_S:
|
||||
case OP_GE_S:
|
||||
case OP_LE_S:
|
||||
case OP_GT_S:
|
||||
case OP_LT_S:
|
||||
case OP_GE:
|
||||
case OP_LE:
|
||||
case OP_GT:
|
||||
case OP_LT:
|
||||
case OP_AND:
|
||||
case OP_OR:
|
||||
case OP_EQ_F:
|
||||
case OP_EQ_V:
|
||||
case OP_EQ_S:
|
||||
case OP_EQ_E:
|
||||
case OP_EQ_FNC:
|
||||
case OP_NE_F:
|
||||
case OP_NE_V:
|
||||
case OP_NE_S:
|
||||
case OP_NE_E:
|
||||
case OP_NE_FNC:
|
||||
case OP_ADDRESS:
|
||||
case OP_LOAD_F:
|
||||
case OP_LOAD_FLD:
|
||||
case OP_LOAD_ENT:
|
||||
case OP_LOAD_S:
|
||||
case OP_LOAD_FNC:
|
||||
case OP_LOAD_V:
|
||||
case OP_ADD_I:
|
||||
case OP_SUB_I:
|
||||
case OP_MUL_I:
|
||||
case OP_DIV_I:
|
||||
case OP_MOD_I:
|
||||
case OP_MOD_F:
|
||||
case OP_BITAND_I:
|
||||
case OP_BITOR_I:
|
||||
case OP_GE_I:
|
||||
case OP_LE_I:
|
||||
case OP_GT_I:
|
||||
case OP_LT_I:
|
||||
case OP_AND_I:
|
||||
case OP_OR_I:
|
||||
case OP_NOT_I:
|
||||
case OP_EQ_I:
|
||||
case OP_NE_I:
|
||||
case OP_LOAD_I:
|
||||
case OP_CONV_IF:
|
||||
case OP_CONV_FI:
|
||||
case OP_BITXOR_F:
|
||||
case OP_BITXOR_I:
|
||||
case OP_BITNOT_F:
|
||||
case OP_BITNOT_I:
|
||||
case OP_SHL_F:
|
||||
case OP_SHR_F:
|
||||
case OP_SHL_I:
|
||||
case OP_SHR_I:
|
||||
if (st->a >= pr->progs->numglobals
|
||||
|| st->b >= pr->progs->numglobals
|
||||
|| st->c >= pr->progs->numglobals)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds global index (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
// global none global
|
||||
case OP_NOT_F:
|
||||
case OP_NOT_V:
|
||||
case OP_NOT_S:
|
||||
case OP_NOT_FNC:
|
||||
case OP_NOT_ENT:
|
||||
if (st->a >= pr->progs->numglobals
|
||||
|| st->c >= pr->progs->numglobals)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds global index (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
// 2 globals
|
||||
case OP_STOREP_F:
|
||||
case OP_STOREP_ENT:
|
||||
case OP_STOREP_FLD:
|
||||
case OP_STOREP_S:
|
||||
case OP_STOREP_FNC:
|
||||
case OP_STORE_F:
|
||||
case OP_STORE_ENT:
|
||||
case OP_STORE_FLD:
|
||||
case OP_STORE_S:
|
||||
case OP_STORE_FNC:
|
||||
case OP_STATE:
|
||||
case OP_STOREP_V:
|
||||
case OP_STORE_V:
|
||||
case OP_STORE_I:
|
||||
case OP_STOREP_I:
|
||||
if (st->a >= pr->progs->numglobals
|
||||
|| st->b >= pr->progs->numglobals)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds global index (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
// 1 global
|
||||
case OP_CALL0:
|
||||
case OP_CALL1:
|
||||
case OP_CALL2:
|
||||
case OP_CALL3:
|
||||
case OP_CALL4:
|
||||
case OP_CALL5:
|
||||
case OP_CALL6:
|
||||
case OP_CALL7:
|
||||
case OP_CALL8:
|
||||
case OP_DONE:
|
||||
case OP_RETURN:
|
||||
if (st->a >= pr->progs->numglobals)
|
||||
PR_Error
|
||||
(pr, "PR_LoadProgs: out of bounds global index (statement %d)\n",
|
||||
i);
|
||||
break;
|
||||
default:
|
||||
PR_Error (pr, "PR_LoadProgs: unknown opcode %d at statement %d\n",
|
||||
st->op, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_Check_Opcodes (pr);
|
||||
}
|
||||
|
||||
edict_t *
|
||||
|
|
|
@ -251,6 +251,7 @@ void
|
|||
PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||
{
|
||||
int exitdepth, profile, startprofile;
|
||||
int pointer;
|
||||
dfunction_t *f, *newf;
|
||||
dstatement_t *st;
|
||||
edict_t *ed;
|
||||
|
@ -289,9 +290,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
OPC.float_var = OPA.float_var + OPB.float_var;
|
||||
break;
|
||||
case OP_ADD_V:
|
||||
OPC.vector_var[0] = OPA.vector_var[0] + OPB.vector_var[0];
|
||||
OPC.vector_var[1] = OPA.vector_var[1] + OPB.vector_var[1];
|
||||
OPC.vector_var[2] = OPA.vector_var[2] + OPB.vector_var[2];
|
||||
VectorAdd (OPA.vector_var, OPB.vector_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_ADD_S:
|
||||
{
|
||||
|
@ -309,28 +308,19 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
OPC.float_var = OPA.float_var - OPB.float_var;
|
||||
break;
|
||||
case OP_SUB_V:
|
||||
OPC.vector_var[0] = OPA.vector_var[0] - OPB.vector_var[0];
|
||||
OPC.vector_var[1] = OPA.vector_var[1] - OPB.vector_var[1];
|
||||
OPC.vector_var[2] = OPA.vector_var[2] - OPB.vector_var[2];
|
||||
VectorSubtract (OPA.vector_var, OPB.vector_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_MUL_F:
|
||||
OPC.float_var = OPA.float_var * OPB.float_var;
|
||||
break;
|
||||
case OP_MUL_V:
|
||||
OPC.float_var =
|
||||
OPA.vector_var[0] * OPB.vector_var[0] +
|
||||
OPA.vector_var[1] * OPB.vector_var[1] +
|
||||
OPA.vector_var[2] * OPB.vector_var[2];
|
||||
OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
|
||||
break;
|
||||
case OP_MUL_FV:
|
||||
OPC.vector_var[0] = OPA.float_var * OPB.vector_var[0];
|
||||
OPC.vector_var[1] = OPA.float_var * OPB.vector_var[1];
|
||||
OPC.vector_var[2] = OPA.float_var * OPB.vector_var[2];
|
||||
VectorScale (OPB.vector_var, OPA.float_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_MUL_VF:
|
||||
OPC.vector_var[0] = OPB.float_var * OPA.vector_var[0];
|
||||
OPC.vector_var[1] = OPB.float_var * OPA.vector_var[1];
|
||||
OPC.vector_var[2] = OPB.float_var * OPA.vector_var[2];
|
||||
VectorScale (OPA.vector_var, OPB.float_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_DIV_F:
|
||||
OPC.float_var = OPA.float_var / OPB.float_var;
|
||||
|
@ -452,9 +442,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
OPB.integer_var = OPA.integer_var;
|
||||
break;
|
||||
case OP_STORE_V:
|
||||
OPB.vector_var[0] = OPA.vector_var[0];
|
||||
OPB.vector_var[1] = OPA.vector_var[1];
|
||||
OPB.vector_var[2] = OPA.vector_var[2];
|
||||
VectorCopy (OPA.vector_var, OPB.vector_var);
|
||||
break;
|
||||
|
||||
case OP_STOREP_F:
|
||||
|
@ -463,40 +451,16 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
case OP_STOREP_S:
|
||||
case OP_STOREP_FNC: // pointers
|
||||
case OP_STOREP_I:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0 || OPB.integer_var + 4 >
|
||||
pr->pr_edictareasize)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to write to an out of "
|
||||
"bounds edict\n");
|
||||
return;
|
||||
}
|
||||
if (pr_boundscheck->int_val && (OPB.integer_var %
|
||||
pr->pr_edict_size <
|
||||
((byte *) & (*pr->edicts)->v -
|
||||
(byte *) * pr->edicts))) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to write to an engine "
|
||||
"edict field\n");
|
||||
return;
|
||||
}
|
||||
ptr = (pr_type_t*)((int)*pr->edicts + OPB.integer_var);
|
||||
//FIXME put bounds checking back
|
||||
ptr = pr->pr_globals + OPB.integer_var;
|
||||
ptr->integer_var = OPA.integer_var;
|
||||
break;
|
||||
case OP_STOREP_V:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0 || OPB.integer_var + 12 >
|
||||
pr->pr_edictareasize)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to write to an out of "
|
||||
"bounds edict\n");
|
||||
return;
|
||||
}
|
||||
ptr = (pr_type_t*)((int)*pr->edicts + OPB.integer_var);
|
||||
ptr->vector_var[0] = OPA.vector_var[0];
|
||||
ptr->vector_var[1] = OPA.vector_var[1];
|
||||
ptr->vector_var[2] = OPA.vector_var[2];
|
||||
//FIXME put bounds checking back
|
||||
ptr = pr->pr_globals + OPB.integer_var;
|
||||
VectorCopy (OPA.vector_var, ptr->vector_var);
|
||||
break;
|
||||
|
||||
case OP_ADDRESS:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPA.entity_var < 0 || OPA.entity_var >=
|
||||
|
@ -521,9 +485,19 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
return;
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
OPC.integer_var = (int) &ed->v[OPB.integer_var] -
|
||||
(int) *pr->edicts;
|
||||
OPC.integer_var = &ed->v[OPB.integer_var] - pr->pr_globals;
|
||||
break;
|
||||
case OP_ADDRESS_F:
|
||||
case OP_ADDRESS_V:
|
||||
case OP_ADDRESS_S:
|
||||
case OP_ADDRESS_ENT:
|
||||
case OP_ADDRESS_FLD:
|
||||
case OP_ADDRESS_FNC:
|
||||
case OP_ADDRESS_I:
|
||||
case OP_ADDRESS_P:
|
||||
OPC.integer_var = st->a;
|
||||
break;
|
||||
|
||||
case OP_LOAD_F:
|
||||
case OP_LOAD_FLD:
|
||||
case OP_LOAD_ENT:
|
||||
|
@ -569,6 +543,50 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC));
|
||||
break;
|
||||
|
||||
case OP_LOADB_F:
|
||||
case OP_LOADB_S:
|
||||
case OP_LOADB_ENT:
|
||||
case OP_LOADB_FLD:
|
||||
case OP_LOADB_FNC:
|
||||
case OP_LOADB_I:
|
||||
case OP_LOADB_P:
|
||||
//FIXME put bounds checking in
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
ptr = pr->pr_globals + pointer;
|
||||
OPC.integer_var = ptr->integer_var;
|
||||
break;
|
||||
case OP_LOADB_V:
|
||||
//FIXME put bounds checking in
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
ptr = pr->pr_globals + pointer;
|
||||
VectorCopy (ptr->vector_var, OPC.vector_var);
|
||||
break;
|
||||
|
||||
case OP_LEA:
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
OPC.integer_var = pointer;
|
||||
break;
|
||||
|
||||
case OP_STOREB_F:
|
||||
case OP_STOREB_S:
|
||||
case OP_STOREB_ENT:
|
||||
case OP_STOREB_FLD:
|
||||
case OP_STOREB_FNC:
|
||||
case OP_STOREB_I:
|
||||
case OP_STOREB_P:
|
||||
//FIXME put bounds checking in
|
||||
pointer = OPB.integer_var + OPC.integer_var;
|
||||
ptr = pr->pr_globals + pointer;
|
||||
ptr->integer_var = OPA.integer_var;
|
||||
break;
|
||||
case OP_STOREB_V:
|
||||
//FIXME put bounds checking in
|
||||
pointer = OPB.integer_var + OPC.integer_var;
|
||||
ptr = pr->pr_globals + pointer;
|
||||
VectorCopy (OPA.vector_var, ptr->vector_var);
|
||||
break;
|
||||
|
||||
// ==================
|
||||
case OP_IFNOT:
|
||||
if (!OPA.integer_var)
|
||||
|
@ -643,10 +661,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
case OP_DIV_VF:
|
||||
{
|
||||
float temp = 1.0f / OPB.float_var;
|
||||
|
||||
OPC.vector_var[0] = temp * OPA.vector_var[0];
|
||||
OPC.vector_var[1] = temp * OPA.vector_var[1];
|
||||
OPC.vector_var[2] = temp * OPA.vector_var[2];
|
||||
VectorScale (OPA.vector_var, temp, OPC.vector_var);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
@ -707,78 +722,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
|
||||
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
|
||||
/*
|
||||
case OP_GSTOREP_I:
|
||||
case OP_GSTOREP_F:
|
||||
case OP_GSTOREP_ENT:
|
||||
case OP_GSTOREP_FLD: // integers
|
||||
case OP_GSTOREP_S:
|
||||
case OP_GSTOREP_FNC: // pointers
|
||||
if (pr_boundscheck->int_val && (OPB.integer_var < 0 ||
|
||||
OPB.integer_var >= pr->pr_globaldefs)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to write to an invalid "
|
||||
"indexed global\n");
|
||||
return;
|
||||
}
|
||||
pr->pr_globals[OPB.integer_var] = OPA.float_var;
|
||||
break;
|
||||
case OP_GSTOREP_V:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPB.integer_var < 0 || OPB.integer_var + 2 >=
|
||||
pr->pr_globaldefs)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to write to an invalid "
|
||||
"indexed global\n");
|
||||
return;
|
||||
}
|
||||
pr->pr_globals[OPB.integer_var] = OPA.vector_var[0];
|
||||
pr->pr_globals[OPB.integer_var + 1] = OPA.vector_var[1];
|
||||
pr->pr_globals[OPB.integer_var + 2] = OPA.vector_var[2];
|
||||
break;
|
||||
|
||||
case OP_GADDRESS:
|
||||
i = OPA.integer_var + (int) OPB.float_var;
|
||||
if (pr_boundscheck->int_val
|
||||
&& (i < 0 || i >= pr->pr_globaldefs)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to address an out of "
|
||||
"bounds global\n");
|
||||
return;
|
||||
}
|
||||
OPC.float_var = pr->pr_globals[i];
|
||||
break;
|
||||
|
||||
case OP_GLOAD_I:
|
||||
case OP_GLOAD_F:
|
||||
case OP_GLOAD_FLD:
|
||||
case OP_GLOAD_ENT:
|
||||
case OP_GLOAD_S:
|
||||
case OP_GLOAD_FNC:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPA.integer_var < 0 || OPA.integer_var >=
|
||||
pr->pr_globaldefs)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"indexed global\n");
|
||||
return;
|
||||
}
|
||||
OPC.float_var = pr->pr_globals[OPA.integer_var];
|
||||
break;
|
||||
|
||||
case OP_GLOAD_V:
|
||||
if (pr_boundscheck->int_val
|
||||
&& (OPA.integer_var < 0 || OPA.integer_var + 2 >=
|
||||
pr->pr_globaldefs)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"indexed global\n");
|
||||
return;
|
||||
}
|
||||
OPC.vector_var[0] = pr->pr_globals[OPA.integer_var];
|
||||
OPC.vector_var[1] = pr->pr_globals[OPA.integer_var + 1];
|
||||
OPC.vector_var[2] = pr->pr_globals[OPA.integer_var + 2];
|
||||
break;
|
||||
|
||||
case OP_BOUNDCHECK:
|
||||
if (OPA.integer_var < 0 || OPA.integer_var >= st->b) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
|
|
|
@ -42,6 +42,7 @@ static const char rcsid[] =
|
|||
|
||||
#include "QF/hash.h"
|
||||
#include "QF/pr_comp.h"
|
||||
#include "QF/progs.h"
|
||||
|
||||
hashtab_t *opcode_table;
|
||||
|
||||
|
@ -90,8 +91,28 @@ opcode_t pr_opcodes[] = {
|
|||
{".", "load.fld", OP_LOAD_FLD, false, ev_entity, ev_field, ev_field, PROG_ID_VERSION},
|
||||
{".", "load.fnc", OP_LOAD_FNC, false, ev_entity, ev_field, ev_func, PROG_ID_VERSION},
|
||||
|
||||
{".", "loadb.f", OP_LOADB_F, false, ev_pointer, ev_integer, ev_float, PROG_VERSION},
|
||||
{".", "loadb.v", OP_LOADB_V, false, ev_pointer, ev_integer, ev_vector, PROG_VERSION},
|
||||
{".", "loadb.s", OP_LOADB_S, false, ev_pointer, ev_integer, ev_string, PROG_VERSION},
|
||||
{".", "loadb.ent", OP_LOADB_ENT, false, ev_pointer, ev_integer, ev_entity, PROG_VERSION},
|
||||
{".", "loadb.fld", OP_LOADB_FLD, false, ev_pointer, ev_integer, ev_field, PROG_VERSION},
|
||||
{".", "loadb.fnc", OP_LOADB_FNC, false, ev_pointer, ev_integer, ev_func, PROG_VERSION},
|
||||
{".", "loadb.i", OP_LOADB_I, false, ev_pointer, ev_integer, ev_integer, PROG_VERSION},
|
||||
{".", "loadb.p", OP_LOADB_P, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
|
||||
|
||||
{".", "address", OP_ADDRESS, false, ev_entity, ev_field, ev_pointer, PROG_ID_VERSION},
|
||||
|
||||
{"&", "address.f", OP_ADDRESS_F, false, ev_float, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.v", OP_ADDRESS_V, false, ev_vector, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.s", OP_ADDRESS_S, false, ev_string, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.ent", OP_ADDRESS_ENT, false, ev_entity, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.fld", OP_ADDRESS_FLD, false, ev_field, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.fnc", OP_ADDRESS_FNC, false, ev_func, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.i", OP_ADDRESS_I, false, ev_integer, ev_void, ev_pointer, PROG_VERSION},
|
||||
{"&", "address.p", OP_ADDRESS_P, false, ev_pointer, ev_void, ev_pointer, PROG_VERSION},
|
||||
|
||||
{"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
|
||||
|
||||
{"=", "store.f", OP_STORE_F, true, ev_float, ev_float, ev_void, PROG_ID_VERSION},
|
||||
{"=", "store.v", OP_STORE_V, true, ev_vector, ev_vector, ev_void, PROG_ID_VERSION},
|
||||
{"=", "store.s", OP_STORE_S, true, ev_string, ev_string, ev_void, PROG_ID_VERSION},
|
||||
|
@ -106,6 +127,15 @@ opcode_t pr_opcodes[] = {
|
|||
{"=", "storep.fld", OP_STOREP_FLD, true, ev_field, ev_pointer, ev_void, PROG_ID_VERSION},
|
||||
{"=", "storep.fnc", OP_STOREP_FNC, true, ev_func, ev_pointer, ev_void, PROG_ID_VERSION},
|
||||
|
||||
{"=", "storeb.f", OP_STOREB_F, true, ev_float, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.v", OP_STOREB_V, true, ev_vector, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.s", OP_STOREB_S, true, ev_string, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.ent", OP_STOREB_ENT, true, ev_entity, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.fld", OP_STOREB_FLD, true, ev_field, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.fnc", OP_STOREB_FNC, true, ev_func, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.i", OP_STOREB_I, true, ev_integer, ev_pointer, ev_integer, PROG_VERSION},
|
||||
{"=", "storeb.p", OP_STOREB_P, true, ev_pointer, ev_pointer, ev_integer, PROG_VERSION},
|
||||
|
||||
{"<RETURN>", "return", OP_RETURN, false, ev_void, ev_void, ev_void, PROG_ID_VERSION},
|
||||
|
||||
{"!", "not.f", OP_NOT_F, false, ev_float, ev_void, ev_integer, PROG_ID_VERSION},
|
||||
|
@ -208,3 +238,59 @@ PR_Opcode_Init (void)
|
|||
Hash_Add (opcode_table, op);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset)
|
||||
{
|
||||
int address = st - pr->pr_statements;
|
||||
|
||||
address += offset - 1;
|
||||
if (address < 0 || address >= pr->progs->numstatements)
|
||||
PR_Error (pr, "PR_Check_Opcodes: invalid branch (statement %d: %s)\n",
|
||||
st - pr->pr_statements, op->opname);
|
||||
}
|
||||
|
||||
static inline void
|
||||
check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
|
||||
unsigned short operand)
|
||||
{
|
||||
if (type == ev_void && operand) {
|
||||
if (st->op != OP_RETURN && st->op != OP_DONE) //FIXME need better "not used flags"
|
||||
PR_Error (pr, "PR_Check_Opcodes: non-zero global index in void operand (statement %d: %s)\n", st - pr->pr_statements, op->opname);
|
||||
} else if (operand >= pr->progs->numglobals) {
|
||||
PR_Error (pr, "PR_Check_Opcodes: out of bounds global index (statement %d: %s)\n", st - pr->pr_statements, op->opname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PR_Check_Opcodes (progs_t *pr)
|
||||
{
|
||||
opcode_t *op;
|
||||
dstatement_t *st;
|
||||
|
||||
for (st = pr->pr_statements;
|
||||
st - pr->pr_statements < pr->progs->numstatements;
|
||||
st++) {
|
||||
op = PR_Opcode (st->op);
|
||||
if (!op) {
|
||||
PR_Error (pr,
|
||||
"PR_Check_Opcodes: unknown opcode %d at statement %d\n",
|
||||
st->op, st - pr->pr_statements);
|
||||
}
|
||||
switch (st->op) {
|
||||
case OP_IF:
|
||||
case OP_IFNOT:
|
||||
check_global (pr, st, op, op->type_a, st->a);
|
||||
check_branch (pr, st, op, st->b);
|
||||
break;
|
||||
case OP_GOTO:
|
||||
check_branch (pr, st, op, st->a);
|
||||
break;
|
||||
default:
|
||||
check_global (pr, st, op, op->type_a, st->a);
|
||||
check_global (pr, st, op, op->type_b, st->b);
|
||||
check_global (pr, st, op, op->type_c, st->c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue