X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=prvm_execprogram.h;h=d9331426cf6e11ee873bf8ab3f34af3f19d6270e;hp=5e94073d6fc09125f972c0682d99a435b0828052;hb=91342dd0a88d002a188418a4b0dd21957e0737b6;hpb=91efd4d4260983eae86f644ff1813cc391d3c27e diff --git a/prvm_execprogram.h b/prvm_execprogram.h index 5e94073d..d9331426 100644 --- a/prvm_execprogram.h +++ b/prvm_execprogram.h @@ -1,13 +1,30 @@ -#ifdef PRVMTIMEPROFILING -#define PreError() \ +extern cvar_t prvm_garbagecollection_enable; +int i; +// NEED to reset startst after calling this! startst may or may not be clobbered! +#define ADVANCE_PROFILE_BEFORE_JUMP() \ + prog->xfunction->profile += (st - startst); \ + if (prvm_statementprofiling.integer || (prvm_coverage.integer & 4)) { \ + /* All statements from startst+1 to st have been hit. */ \ + while (++startst <= st) { \ + if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \ + PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \ + } \ + /* Observe: startst now is clobbered (now at st+1)! */ \ + } + +#ifdef PRVMTIMEPROFILING +#define PRE_ERROR() \ + ADVANCE_PROFILE_BEFORE_JUMP(); \ prog->xstatement = st - cached_statements; \ tm = Sys_DirtyTime(); \ - prog->xfunction->profile += (st - startst); \ - prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; + prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \ + startst = st; \ + starttm = tm #else -#define PreError() \ +#define PRE_ERROR() \ + ADVANCE_PROFILE_BEFORE_JUMP(); \ prog->xstatement = st - cached_statements; \ - prog->xfunction->profile += (st - startst); + startst = st #endif // This code isn't #ifdef/#define protectable, don't try. @@ -95,7 +112,183 @@ &&handle_OP_OR, &&handle_OP_BITAND, - &&handle_OP_BITOR + &&handle_OP_BITOR, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + &&handle_OP_STORE_I, + + NULL, + NULL, + + &&handle_OP_ADD_I, + &&handle_OP_ADD_FI, + &&handle_OP_ADD_IF, + + &&handle_OP_SUB_I, + &&handle_OP_SUB_FI, + &&handle_OP_SUB_IF, + &&handle_OP_CONV_IF, + &&handle_OP_CONV_FI, + + NULL, + NULL, + + &&handle_OP_LOAD_I, + &&handle_OP_STOREP_I, + + NULL, + NULL, + + &&handle_OP_BITAND_I, + &&handle_OP_BITOR_I, + + &&handle_OP_MUL_I, + &&handle_OP_DIV_I, + &&handle_OP_EQ_I, + &&handle_OP_NE_I, + + NULL, + NULL, + + &&handle_OP_NOT_I, + + &&handle_OP_DIV_VF, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + &&handle_OP_STORE_P, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + &&handle_OP_LE_I, + &&handle_OP_GE_I, + &&handle_OP_LT_I, + &&handle_OP_GT_I, + + &&handle_OP_LE_IF, + &&handle_OP_GE_IF, + &&handle_OP_LT_IF, + &&handle_OP_GT_IF, + + &&handle_OP_LE_FI, + &&handle_OP_GE_FI, + &&handle_OP_LT_FI, + &&handle_OP_GT_FI, + + &&handle_OP_EQ_IF, + &&handle_OP_EQ_FI, + + NULL, + NULL, + NULL, + NULL, + + &&handle_OP_MUL_IF, + &&handle_OP_MUL_FI, + &&handle_OP_MUL_VI, + + NULL, + + &&handle_OP_DIV_IF, + &&handle_OP_DIV_FI, + &&handle_OP_BITAND_IF, + &&handle_OP_BITOR_IF, + &&handle_OP_BITAND_FI, + &&handle_OP_BITOR_FI, + &&handle_OP_AND_I, + &&handle_OP_OR_I, + &&handle_OP_AND_IF, + &&handle_OP_OR_IF, + &&handle_OP_AND_FI, + &&handle_OP_OR_FI, + &&handle_OP_NE_IF, + &&handle_OP_NE_FI, + + &&handle_OP_GSTOREP_I, + &&handle_OP_GSTOREP_F, + &&handle_OP_GSTOREP_ENT, + &&handle_OP_GSTOREP_FLD, + &&handle_OP_GSTOREP_S, + &&handle_OP_GSTOREP_FNC, + &&handle_OP_GSTOREP_V, + &&handle_OP_GADDRESS, + &&handle_OP_GLOAD_I, + &&handle_OP_GLOAD_F, + &&handle_OP_GLOAD_FLD, + &&handle_OP_GLOAD_ENT, + &&handle_OP_GLOAD_S, + &&handle_OP_GLOAD_FNC, + &&handle_OP_BOUNDCHECK, + NULL, + NULL, + NULL, + NULL, + &&handle_OP_GLOAD_V }; #define DISPATCH_OPCODE() \ goto *dispatchtable[(++st)->op] @@ -110,15 +303,15 @@ { if (prog->watch_global_type != ev_void) { - prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global); + prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global); prog->xstatement = st + 1 - cached_statements; - PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, f); + PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, g); } if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts) { - prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); + prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); prog->xstatement = st + 1 - cached_statements; - PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, f); + PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, g); } } #endif @@ -133,8 +326,6 @@ #if PRVMSLOWINTERPRETER if (prog->trace) PRVM_PrintStatement(prog, st); - if (prog->statement_profile[st - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) - PRVM_StatementCoverageEvent(prog, prog->xfunction, st - cached_statements); if (prog->break_statement >= 0) if ((st - cached_statements) == prog->break_statement) { @@ -188,9 +379,7 @@ { if (developer.integer) { - prog->xfunction->profile += (st - startst); - startst = st; - prog->xstatement = st - cached_statements; + PRE_ERROR(); VM_Warning(prog, "Attempted division by zero in %s\n", prog->name ); } OPC->_float = 0.0f; @@ -215,13 +404,13 @@ OPC->_float = OPA->_float < OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_AND): - OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) && FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add AND_I to be used by fteqcc for anything not a float + OPC->_float = PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int) && PRVM_FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add AND_I to be used by fteqcc for anything not a float DISPATCH_OPCODE(); HANDLE_OPCODE(OP_OR): - OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) || FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add OR_I to be used by fteqcc for anything not a float + OPC->_float = PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int) || PRVM_FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add OR_I to be used by fteqcc for anything not a float DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NOT_F): - OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int); + OPC->_float = !PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int); DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NOT_V): OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2]; @@ -270,10 +459,18 @@ HANDLE_OPCODE(OP_STORE_F): HANDLE_OPCODE(OP_STORE_ENT): HANDLE_OPCODE(OP_STORE_FLD): // integers - HANDLE_OPCODE(OP_STORE_S): HANDLE_OPCODE(OP_STORE_FNC): // pointers OPB->_int = OPA->_int; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_STORE_S): + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + if(prvm_garbagecollection_enable.integer) + PRVM_GetString(prog, OPA->_int); + OPB->_int = OPA->_int; + DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STORE_V): OPB->ivector[0] = OPA->ivector[0]; OPB->ivector[1] = OPA->ivector[1]; @@ -283,22 +480,45 @@ HANDLE_OPCODE(OP_STOREP_F): HANDLE_OPCODE(OP_STOREP_ENT): HANDLE_OPCODE(OP_STOREP_FLD): // integers - HANDLE_OPCODE(OP_STOREP_S): HANDLE_OPCODE(OP_STOREP_FNC): // pointers if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields) { if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea) { - PreError(); + PRE_ERROR(); prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); goto cleanup; } if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) { - prog->xstatement = st - cached_statements; - VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); + PRE_ERROR(); + VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); + } + } + ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); + ptr->_int = OPA->_int; + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_STOREP_S): + if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields) + { + if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea) + { + PRE_ERROR(); + prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); + goto cleanup; + } + if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) + { + PRE_ERROR(); + VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); } } + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + if(prvm_garbagecollection_enable.integer) + PRVM_GetString(prog, OPA->_int); ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); ptr->_int = OPA->_int; DISPATCH_OPCODE(); @@ -307,14 +527,14 @@ { if ((prvm_uint_t)OPB->_int > cached_entityfieldsarea_3) { - PreError(); + PRE_ERROR(); prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); goto cleanup; } if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) { - prog->xstatement = st - cached_statements; - VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); + PRE_ERROR(); + VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); } } ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); @@ -326,21 +546,21 @@ HANDLE_OPCODE(OP_ADDRESS): if ((prvm_uint_t)OPA->edict >= cached_max_edicts) { - PreError(); - prog->error_cmd("%s Progs attempted to address an out of bounds edict number", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to address an out of bounds edict number", prog->name); goto cleanup; } if ((prvm_uint_t)OPB->_int >= cached_entityfields) { - PreError(); + PRE_ERROR(); prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, (int)OPB->_int); goto cleanup; } #if 0 if (OPA->edict == 0 && !cached_allowworldwrites) { - PreError(); - prog->error_cmd("forbidden assignment to null/world entity in %s", prog->name); + PRE_ERROR(); + prog->error_cmd("Forbidden assignment to NULL entity in %s", prog->name); goto cleanup; } #endif @@ -350,34 +570,55 @@ HANDLE_OPCODE(OP_LOAD_F): HANDLE_OPCODE(OP_LOAD_FLD): HANDLE_OPCODE(OP_LOAD_ENT): - HANDLE_OPCODE(OP_LOAD_S): HANDLE_OPCODE(OP_LOAD_FNC): if ((prvm_uint_t)OPA->edict >= cached_max_edicts) { - PreError(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name); goto cleanup; } if ((prvm_uint_t)OPB->_int >= cached_entityfields) { - PreError(); + PRE_ERROR(); prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int); goto cleanup; } ed = PRVM_PROG_TO_EDICT(OPA->edict); OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_LOAD_S): + if ((prvm_uint_t)OPA->edict >= cached_max_edicts) + { + PRE_ERROR(); + prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name); + goto cleanup; + } + if ((prvm_uint_t)OPB->_int >= cached_entityfields) + { + PRE_ERROR(); + prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int); + goto cleanup; + } + ed = PRVM_PROG_TO_EDICT(OPA->edict); + OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int; + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + if(prvm_garbagecollection_enable.integer) + PRVM_GetString(prog, OPC->_int); + DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LOAD_V): if ((prvm_uint_t)OPA->edict >= cached_max_edicts) { - PreError(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name); goto cleanup; } if ((prvm_uint_t)OPB->_int > cached_entityfields_3) { - PreError(); + PRE_ERROR(); prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int); goto cleanup; } @@ -391,12 +632,14 @@ //================== HANDLE_OPCODE(OP_IFNOT): + //spike FIXME -- dp redefined IFNOT[_I] as IFNOT_F, which breaks if(0x80000000) + //spike FIXME -- you should add separate IFNOT_I/IFNOT_F opcodes and remap IFNOT_I to ITNOT_F in v6 progs for compat. if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int)) // TODO add an "int-if", and change this one to OPA->_float // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero) // and entity, string, field values can never have that value { - prog->xfunction->profile += (st - startst); + ADVANCE_PROFILE_BEFORE_JUMP(); st = cached_statements + st->jumpabsolute - 1; // offset the st++ startst = st; // no bounds check needed, it is done when loading progs @@ -410,12 +653,13 @@ DISPATCH_OPCODE(); HANDLE_OPCODE(OP_IF): + //spike FIXME -- dp redefined IF[_I] as IF_F if(FLOAT_IS_TRUE_FOR_INT(OPA->_int)) // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero) // and entity, string, field values can never have that value { - prog->xfunction->profile += (st - startst); + ADVANCE_PROFILE_BEFORE_JUMP(); st = cached_statements + st->jumpabsolute - 1; // offset the st++ startst = st; // no bounds check needed, it is done when loading progs @@ -429,7 +673,7 @@ DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GOTO): - prog->xfunction->profile += (st - startst); + ADVANCE_PROFILE_BEFORE_JUMP(); st = cached_statements + st->jumpabsolute - 1; // offset the st++ startst = st; // no bounds check needed, it is done when loading progs @@ -455,40 +699,42 @@ prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; starttm = tm; #endif - prog->xfunction->profile += (st - startst); + ADVANCE_PROFILE_BEFORE_JUMP(); startst = st; prog->xstatement = st - cached_statements; prog->argc = st->op - OP_CALL0; if (!OPA->function) + { prog->error_cmd("NULL function in %s", prog->name); + } if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions) { - PreError(); - prog->error_cmd("%s CALL outside the program", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted CALL outside the program", prog->name); goto cleanup; } - newf = &prog->functions[OPA->function]; - if (newf->callcount++ == 0 && (prvm_coverage.integer & 1)) - PRVM_FunctionCoverageEvent(prog, newf); + enterfunc = &prog->functions[OPA->function]; + if (enterfunc->callcount++ == 0 && (prvm_coverage.integer & 1)) + PRVM_FunctionCoverageEvent(prog, enterfunc); - if (newf->first_statement < 0) + if (enterfunc->first_statement < 0) { // negative first_statement values are built in functions - int builtinnumber = -newf->first_statement; + int builtinnumber = -enterfunc->first_statement; prog->xfunction->builtinsprofile++; if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber]) { prog->builtins[builtinnumber](prog); #ifdef PRVMTIMEPROFILING tm = Sys_DirtyTime(); - newf->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; + enterfunc->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; starttm = tm; #endif // builtins may cause ED_Alloc() to be called, update cached variables - cached_edictsfields = prog->edictsfields; + cached_edictsfields = prog->edictsfields.fp; cached_entityfields = prog->entityfields; cached_entityfields_3 = prog->entityfields - 3; cached_entityfieldsarea = prog->entityfieldsarea; @@ -505,10 +751,10 @@ goto chooseexecprogram; } else - prog->error_cmd("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, prog->name); + prog->error_cmd("No such builtin #%i in %s. This program is corrupt or incompatible with DarkPlaces (or this version of it)", builtinnumber, prog->name); } else - st = cached_statements + PRVM_EnterFunction(prog, newf); + st = cached_statements + PRVM_EnterFunction(prog, enterfunc); startst = st; DISPATCH_OPCODE(); @@ -519,7 +765,7 @@ prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; starttm = tm; #endif - prog->xfunction->profile += (st - startst); + ADVANCE_PROFILE_BEFORE_JUMP(); prog->xstatement = st - cached_statements; prog->globals.ip[OFS_RETURN ] = prog->globals.ip[st->operand[0] ]; @@ -542,19 +788,17 @@ } else { - PreError(); + PRE_ERROR(); prog->xstatement = st - cached_statements; prog->error_cmd("OP_STATE not supported by %s", prog->name); } DISPATCH_OPCODE(); -// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized -/* HANDLE_OPCODE(OP_ADD_I): OPC->_int = OPA->_int + OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_ADD_IF): - OPC->_int = OPA->_int + (prvm_int_t) OPB->_float; + OPC->_float = OPA->_int + (prvm_int_t) OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_ADD_FI): OPC->_float = OPA->_float + (prvm_vec_t) OPB->_int; @@ -563,7 +807,7 @@ OPC->_int = OPA->_int - OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_SUB_IF): - OPC->_int = OPA->_int - (prvm_int_t) OPB->_float; + OPC->_float = OPA->_int - (prvm_int_t) OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_SUB_FI): OPC->_float = OPA->_float - (prvm_vec_t) OPB->_int; @@ -572,7 +816,7 @@ OPC->_int = OPA->_int * OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_MUL_IF): - OPC->_int = OPA->_int * (prvm_int_t) OPB->_float; + OPC->_float = OPA->_int * (prvm_int_t) OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_MUL_FI): OPC->_float = OPA->_float * (prvm_vec_t) OPB->_int; @@ -594,7 +838,7 @@ OPC->_int = OPA->_int / OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_DIV_IF): - OPC->_int = OPA->_int / (prvm_int_t) OPB->_float; + OPC->_float = OPA->_int / (prvm_int_t) OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_DIV_FI): OPC->_float = OPA->_float / (prvm_vec_t) OPB->_int; @@ -618,118 +862,119 @@ OPC->_int = OPA->_int | (prvm_int_t)OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_BITAND_FI): - OPC->_float = (prvm_int_t)OPA->_float & OPB->_int; + OPC->_int = (prvm_int_t)OPA->_float & OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_BITOR_FI): - OPC->_float = (prvm_int_t)OPA->_float | OPB->_int; + OPC->_int = (prvm_int_t)OPA->_float | OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GE_I): - OPC->_float = OPA->_int >= OPB->_int; + OPC->_int = OPA->_int >= OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LE_I): - OPC->_float = OPA->_int <= OPB->_int; + OPC->_int = OPA->_int <= OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GT_I): - OPC->_float = OPA->_int > OPB->_int; + OPC->_int = OPA->_int > OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LT_I): - OPC->_float = OPA->_int < OPB->_int; + OPC->_int = OPA->_int < OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_AND_I): - OPC->_float = OPA->_int && OPB->_int; + OPC->_int = OPA->_int && OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_OR_I): - OPC->_float = OPA->_int || OPB->_int; + OPC->_int = OPA->_int || OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GE_IF): - OPC->_float = (prvm_vec_t)OPA->_int >= OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int >= OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LE_IF): - OPC->_float = (prvm_vec_t)OPA->_int <= OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int <= OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GT_IF): - OPC->_float = (prvm_vec_t)OPA->_int > OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int > OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LT_IF): - OPC->_float = (prvm_vec_t)OPA->_int < OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int < OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_AND_IF): - OPC->_float = (prvm_vec_t)OPA->_int && OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int && OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_OR_IF): - OPC->_float = (prvm_vec_t)OPA->_int || OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int || OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GE_FI): - OPC->_float = OPA->_float >= (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float >= (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LE_FI): - OPC->_float = OPA->_float <= (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float <= (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GT_FI): - OPC->_float = OPA->_float > (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float > (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LT_FI): - OPC->_float = OPA->_float < (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float < (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_AND_FI): - OPC->_float = OPA->_float && (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float && (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_OR_FI): - OPC->_float = OPA->_float || (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float || (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NOT_I): - OPC->_float = !OPA->_int; + OPC->_int = !OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_EQ_I): - OPC->_float = OPA->_int == OPB->_int; + OPC->_int = OPA->_int == OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_EQ_IF): - OPC->_float = (prvm_vec_t)OPA->_int == OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int == OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_EQ_FI): - OPC->_float = OPA->_float == (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float == (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NE_I): - OPC->_float = OPA->_int != OPB->_int; + OPC->_int = OPA->_int != OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NE_IF): - OPC->_float = (prvm_vec_t)OPA->_int != OPB->_float; + OPC->_int = (prvm_vec_t)OPA->_int != OPB->_float; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_NE_FI): - OPC->_float = OPA->_float != (prvm_vec_t)OPB->_int; + OPC->_int = OPA->_float != (prvm_vec_t)OPB->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STORE_I): + HANDLE_OPCODE(OP_STORE_P): OPB->_int = OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STOREP_I): #if PRBOUNDSCHECK if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize) { - PreError(); - prog->error_cmd("%s Progs attempted to write to an out of bounds edict", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to write to an out of bounds edict", prog->name); goto cleanup; } #endif - ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int); + ptr = (prvm_eval_t *)(prog->edictsfields.ip + OPB->_int); ptr->_int = OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LOAD_I): #if PRBOUNDSCHECK if (OPA->edict < 0 || OPA->edict >= prog->max_edicts) { - PreError(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name); goto cleanup; } - if (OPB->_int < 0 || OPB->_int >= progs->entityfields) + if (OPB->_int < 0 || OPB->_int >= progs->entityfields.ip) { - PreError(); - prog->error_cmd("%s Progs attempted to read an invalid field in an edict", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an invalid field in an edict", prog->name); goto cleanup; } #endif ed = PRVM_PROG_TO_EDICT(OPA->edict); - OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int; + OPC->_int = ((prvm_eval_t *)((int *)ed->fields.ip + OPB->_int))->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GSTOREP_I): @@ -738,41 +983,35 @@ HANDLE_OPCODE(OP_GSTOREP_FLD): // integers HANDLE_OPCODE(OP_GSTOREP_S): HANDLE_OPCODE(OP_GSTOREP_FNC): // pointers -#if PRBOUNDSCHECK - if (OPB->_int < 0 || OPB->_int >= pr_globaldefs) + if (OPB->_int < 0 || OPB->_int >= prog->numglobals) { - PreError(); - prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name); goto cleanup; } -#endif - pr_iglobals[OPB->_int] = OPA->_int; + prog->globals.ip[OPB->_int] = OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GSTOREP_V): -#if PRBOUNDSCHECK - if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs) + if (OPB->_int < 0 || OPB->_int + 2 >= prog->numglobals) { - PreError(); - prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name); goto cleanup; } -#endif - pr_iglobals[OPB->_int ] = OPA->ivector[0]; - pr_iglobals[OPB->_int+1] = OPA->ivector[1]; - pr_iglobals[OPB->_int+2] = OPA->ivector[2]; + prog->globals.ip[OPB->_int ] = OPA->ivector[0]; + prog->globals.ip[OPB->_int+1] = OPA->ivector[1]; + prog->globals.ip[OPB->_int+2] = OPA->ivector[2]; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GADDRESS): i = OPA->_int + (prvm_int_t) OPB->_float; -#if PRBOUNDSCHECK - if (i < 0 || i >= pr_globaldefs) + if (i < 0 || i >= prog->numglobaldefs) { - PreError(); - prog->error_cmd("%s Progs attempted to address an out of bounds global", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to address an out of bounds global", prog->name); goto cleanup; } -#endif - OPC->_int = pr_iglobals[i]; + OPC->_int = prog->globals.ip[i]; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GLOAD_I): @@ -781,61 +1020,55 @@ HANDLE_OPCODE(OP_GLOAD_ENT): HANDLE_OPCODE(OP_GLOAD_S): HANDLE_OPCODE(OP_GLOAD_FNC): -#if PRBOUNDSCHECK - if (OPA->_int < 0 || OPA->_int >= pr_globaldefs) + if (OPA->_int < 0 || OPA->_int >= prog->numglobals) { - PreError(); - prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an invalid indexed global", prog->name); goto cleanup; } -#endif - OPC->_int = pr_iglobals[OPA->_int]; + OPC->_int = prog->globals.ip[OPA->_int]; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_GLOAD_V): -#if PRBOUNDSCHECK - if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs) + if (OPA->_int < 0 || OPA->_int + 2 >= prog->numglobals) { - PreError(); - prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name); + PRE_ERROR(); + prog->error_cmd("%s attempted to read an invalid indexed global", prog->name); goto cleanup; } -#endif - OPC->ivector[0] = pr_iglobals[OPA->_int ]; - OPC->ivector[1] = pr_iglobals[OPA->_int+1]; - OPC->ivector[2] = pr_iglobals[OPA->_int+2]; + OPC->ivector[0] = prog->globals.ip[OPA->_int ]; + OPC->ivector[1] = prog->globals.ip[OPA->_int+1]; + OPC->ivector[2] = prog->globals.ip[OPA->_int+2]; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_BOUNDCHECK): - if (OPA->_int < 0 || OPA->_int >= st->b) + if ((unsigned int)OPA->_int < (unsigned int)st->operand[2] || (unsigned int)OPA->_int >= (unsigned int)st->operand[1]) { - PreError(); - prog->error_cmd("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", prog->name, st->b, st->c); + PRE_ERROR(); + prog->error_cmd("Progs boundcheck failed in %s, value is < %" PRVM_PRIi " or >= %" PRVM_PRIi, prog->name, OPC->_int, OPB->_int); goto cleanup; } DISPATCH_OPCODE(); -*/ - #if !USE_COMPUTED_GOTOS default: - PreError(); - prog->error_cmd("Bad opcode %i in %s", st->op, prog->name); + PRE_ERROR(); + prog->error_cmd("Bad opcode %i in %s. This program is corrupt or incompatible with DarkPlaces (or this version of it)", st->op, prog->name); goto cleanup; } #if PRVMSLOWINTERPRETER { if (prog->watch_global_type != ev_void) { - prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global); + prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global); prog->xstatement = st - cached_statements; - PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, f); + PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, g); } if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts) { - prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); + prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); prog->xstatement = st - cached_statements; - PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, f); + PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, g); } } #endif @@ -845,6 +1078,5 @@ #undef DISPATCH_OPCODE #undef HANDLE_OPCODE #undef USE_COMPUTED_GOTOS - - -#undef PreError +#undef PRE_ERROR +#undef ADVANCE_PROFILE_BEFORE_JUMP