X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=prvm_execprogram.h;h=988e913a7b2b525692f5cc1e0b27e496744e6063;hp=b87cfcf91b3fb0e74cb822addd1122754391194b;hb=54c8d13c76444ca7e9d3f65229b5638cc67c3db5;hpb=66c17456052bcd458a64c76802d04618bd464d05 diff --git a/prvm_execprogram.h b/prvm_execprogram.h index b87cfcf9..988e913a 100644 --- a/prvm_execprogram.h +++ b/prvm_execprogram.h @@ -1,6 +1,16 @@ -// NEED to reset startst after calling this! +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) + 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() \ @@ -102,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] @@ -117,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 @@ -140,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) { @@ -275,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]; @@ -288,7 +480,6 @@ 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) { @@ -301,12 +492,36 @@ if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) { PRE_ERROR(); - 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); + 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(); HANDLE_OPCODE(OP_STOREP_V): if ((prvm_uint_t)OPB->_int - cached_entityfields > (prvm_uint_t)cached_entityfieldsarea_entityfields_3) { @@ -319,7 +534,7 @@ if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) { PRE_ERROR(); - 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); + 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); @@ -332,7 +547,7 @@ if ((prvm_uint_t)OPA->edict >= cached_max_edicts) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to address an out of bounds edict number", prog->name); + 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) @@ -345,7 +560,7 @@ if (OPA->edict == 0 && !cached_allowworldwrites) { PRE_ERROR(); - prog->error_cmd("forbidden assignment to null/world entity in %s", prog->name); + prog->error_cmd("Forbidden assignment to NULL entity in %s", prog->name); goto cleanup; } #endif @@ -355,12 +570,11 @@ 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + 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) @@ -372,12 +586,34 @@ 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + 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) @@ -396,6 +632,8 @@ //================== 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) @@ -415,6 +653,7 @@ 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) @@ -472,30 +711,30 @@ if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions) { PRE_ERROR(); - prog->error_cmd("%s CALL outside the program", prog->name); + 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; @@ -512,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(); @@ -555,13 +794,11 @@ } 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; @@ -570,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; @@ -579,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; @@ -601,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; @@ -625,87 +862,88 @@ 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): @@ -713,11 +951,11 @@ if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to write to an out of bounds edict", prog->name); + 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): @@ -725,18 +963,18 @@ if (OPA->edict < 0 || OPA->edict >= prog->max_edicts) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an invalid field in an edict", prog->name); + 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): @@ -745,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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name); + 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name); + 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to address an out of bounds global", prog->name); + 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): @@ -788,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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name); + 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) { PRE_ERROR(); - prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name); + 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]) { PRE_ERROR(); - prog->error_cmd("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", prog->name, st->b, st->c); + 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: PRE_ERROR(); - prog->error_cmd("Bad opcode %i in %s", st->op, prog->name); + 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