1 #ifdef PRVMTIMEPROFILING
3 tm = Sys_DoubleTime(); \
4 prog->xfunction->profile += (st - startst); \
5 prog->xfunction->tprofile += (tm - starttm);
8 prog->xfunction->profile += (st - startst);
11 // This code isn't #ifdef/#define protectable, don't try.
17 #if PRVMSLOWINTERPRETER
19 PRVM_PrintStatement(st);
20 prog->statement_profile[st - prog->statements]++;
26 OPC->_float = OPA->_float + OPB->_float;
29 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
30 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
31 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
34 OPC->_float = OPA->_float - OPB->_float;
37 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
38 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
39 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
42 OPC->_float = OPA->_float * OPB->_float;
45 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
48 OPC->vector[0] = OPA->_float * OPB->vector[0];
49 OPC->vector[1] = OPA->_float * OPB->vector[1];
50 OPC->vector[2] = OPA->_float * OPB->vector[2];
53 OPC->vector[0] = OPB->_float * OPA->vector[0];
54 OPC->vector[1] = OPB->_float * OPA->vector[1];
55 OPC->vector[2] = OPB->_float * OPA->vector[2];
58 if( OPB->_float != 0.0f )
60 OPC->_float = OPA->_float / OPB->_float;
64 if (developer.integer)
66 prog->xfunction->profile += (st - startst);
68 prog->xstatement = st - prog->statements;
69 VM_Warning( "Attempted division by zero in %s\n", PRVM_NAME );
75 OPC->_float = (int)OPA->_float & (int)OPB->_float;
78 OPC->_float = (int)OPA->_float | (int)OPB->_float;
81 OPC->_float = OPA->_float >= OPB->_float;
84 OPC->_float = OPA->_float <= OPB->_float;
87 OPC->_float = OPA->_float > OPB->_float;
90 OPC->_float = OPA->_float < OPB->_float;
93 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
96 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
99 OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
102 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
105 OPC->_float = !OPA->string || !*PRVM_GetString(OPA->string);
108 OPC->_float = !OPA->function;
111 OPC->_float = (OPA->edict == 0);
114 OPC->_float = OPA->_float == OPB->_float;
117 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
120 OPC->_float = !strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
123 OPC->_float = OPA->_int == OPB->_int;
126 OPC->_float = OPA->function == OPB->function;
129 OPC->_float = OPA->_float != OPB->_float;
132 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
135 OPC->_float = strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
138 OPC->_float = OPA->_int != OPB->_int;
141 OPC->_float = OPA->function != OPB->function;
147 case OP_STORE_FLD: // integers
149 case OP_STORE_FNC: // pointers
150 OPB->_int = OPA->_int;
153 OPB->ivector[0] = OPA->ivector[0];
154 OPB->ivector[1] = OPA->ivector[1];
155 OPB->ivector[2] = OPA->ivector[2];
160 case OP_STOREP_FLD: // integers
162 case OP_STOREP_FNC: // pointers
163 if (OPB->_int < 0 || OPB->_int + 1 > prog->entityfieldsarea)
166 PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
169 if (OPB->_int < prog->progs->entityfields && !prog->allowworldwrites)
170 VM_Warning("assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
171 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
172 ptr->_int = OPA->_int;
175 if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfieldsarea)
178 PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
181 if (OPB->_int < prog->progs->entityfields && !prog->allowworldwrites)
182 VM_Warning("assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
183 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
184 ptr->ivector[0] = OPA->ivector[0];
185 ptr->ivector[1] = OPA->ivector[1];
186 ptr->ivector[2] = OPA->ivector[2];
190 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
193 PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number", PRVM_NAME);
196 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
199 PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
203 if (OPA->edict == 0 && !prog->allowworldwrites)
206 PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
210 ed = PRVM_PROG_TO_EDICT(OPA->edict);
211 OPC->_int = ed->fields.vp - prog->edictsfields + OPB->_int;
219 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
222 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
225 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
228 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
231 ed = PRVM_PROG_TO_EDICT(OPA->edict);
232 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
236 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
239 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
242 if (OPB->_int < 0 || OPB->_int + 2 >= prog->progs->entityfields)
245 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
248 ed = PRVM_PROG_TO_EDICT(OPA->edict);
249 OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
250 OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
251 OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
257 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
258 // TODO add an "int-if", and change this one to OPA->_float
259 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
260 // and entity, string, field values can never have that value
262 prog->xfunction->profile += (st - startst);
263 st += st->b - 1; // offset the s++
265 // no bounds check needed, it is done when loading progs
266 if (++jumpcount == 10000000 && prvm_runawaycheck)
268 prog->xstatement = st - prog->statements;
269 PRVM_Profile(1<<30, 1000000, 0);
270 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
276 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
277 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
278 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
279 // and entity, string, field values can never have that value
281 prog->xfunction->profile += (st - startst);
282 st += st->b - 1; // offset the s++
284 // no bounds check needed, it is done when loading progs
285 if (++jumpcount == 10000000 && prvm_runawaycheck)
287 prog->xstatement = st - prog->statements;
288 PRVM_Profile(1<<30, 0.01, 0);
289 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
295 prog->xfunction->profile += (st - startst);
296 st += st->a - 1; // offset the s++
298 // no bounds check needed, it is done when loading progs
299 if (++jumpcount == 10000000 && prvm_runawaycheck)
301 prog->xstatement = st - prog->statements;
302 PRVM_Profile(1<<30, 0.01, 0);
303 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
316 #ifdef PRVMTIMEPROFILING
317 tm = Sys_DoubleTime();
318 prog->xfunction->tprofile += (tm - starttm);
321 prog->xfunction->profile += (st - startst);
323 prog->xstatement = st - prog->statements;
324 prog->argc = st->op - OP_CALL0;
326 PRVM_ERROR("NULL function in %s", PRVM_NAME);
328 if(!OPA->function || OPA->function >= (unsigned int)prog->progs->numfunctions)
331 PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
335 newf = &prog->functions[OPA->function];
338 if (newf->first_statement < 0)
340 // negative statements are built in functions
341 int builtinnumber = -newf->first_statement;
342 prog->xfunction->builtinsprofile++;
343 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
345 prog->builtins[builtinnumber]();
346 #ifdef PRVMTIMEPROFILING
347 tm = Sys_DoubleTime();
348 newf->tprofile += (tm - starttm);
349 prog->xfunction->tbprofile += (tm - starttm);
354 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
357 st = prog->statements + PRVM_EnterFunction(newf);
363 #ifdef PRVMTIMEPROFILING
364 tm = Sys_DoubleTime();
365 prog->xfunction->tprofile += (tm - starttm);
368 prog->xfunction->profile += (st - startst);
369 prog->xstatement = st - prog->statements;
371 prog->globals.generic[OFS_RETURN] = prog->globals.generic[(unsigned short) st->a];
372 prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[(unsigned short) st->a+1];
373 prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[(unsigned short) st->a+2];
375 st = prog->statements + PRVM_LeaveFunction();
377 if (prog->depth <= exitdepth)
378 goto cleanup; // all done
379 if (prog->trace != cachedpr_trace)
380 goto chooseexecprogram;
384 if(prog->flag & PRVM_OP_STATE)
386 ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
387 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.nextthink)->_float = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.time)->_float + 0.1;
388 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.frame)->_float = OPA->_float;
389 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.think)->function = OPB->function;
394 prog->xstatement = st - prog->statements;
395 PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
399 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
402 OPC->_int = OPA->_int + OPB->_int;
405 OPC->_int = OPA->_int + (int) OPB->_float;
408 OPC->_float = OPA->_float + (float) OPB->_int;
411 OPC->_int = OPA->_int - OPB->_int;
414 OPC->_int = OPA->_int - (int) OPB->_float;
417 OPC->_float = OPA->_float - (float) OPB->_int;
420 OPC->_int = OPA->_int * OPB->_int;
423 OPC->_int = OPA->_int * (int) OPB->_float;
426 OPC->_float = OPA->_float * (float) OPB->_int;
429 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
430 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
431 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
435 float temp = 1.0f / OPB->_float;
436 OPC->vector[0] = temp * OPA->vector[0];
437 OPC->vector[1] = temp * OPA->vector[1];
438 OPC->vector[2] = temp * OPA->vector[2];
442 OPC->_int = OPA->_int / OPB->_int;
445 OPC->_int = OPA->_int / (int) OPB->_float;
448 OPC->_float = OPA->_float / (float) OPB->_int;
451 OPC->_float = OPA->_int;
454 OPC->_int = OPA->_float;
457 OPC->_int = OPA->_int & OPB->_int;
460 OPC->_int = OPA->_int | OPB->_int;
463 OPC->_int = OPA->_int & (int)OPB->_float;
466 OPC->_int = OPA->_int | (int)OPB->_float;
469 OPC->_float = (int)OPA->_float & OPB->_int;
472 OPC->_float = (int)OPA->_float | OPB->_int;
475 OPC->_float = OPA->_int >= OPB->_int;
478 OPC->_float = OPA->_int <= OPB->_int;
481 OPC->_float = OPA->_int > OPB->_int;
484 OPC->_float = OPA->_int < OPB->_int;
487 OPC->_float = OPA->_int && OPB->_int;
490 OPC->_float = OPA->_int || OPB->_int;
493 OPC->_float = (float)OPA->_int >= OPB->_float;
496 OPC->_float = (float)OPA->_int <= OPB->_float;
499 OPC->_float = (float)OPA->_int > OPB->_float;
502 OPC->_float = (float)OPA->_int < OPB->_float;
505 OPC->_float = (float)OPA->_int && OPB->_float;
508 OPC->_float = (float)OPA->_int || OPB->_float;
511 OPC->_float = OPA->_float >= (float)OPB->_int;
514 OPC->_float = OPA->_float <= (float)OPB->_int;
517 OPC->_float = OPA->_float > (float)OPB->_int;
520 OPC->_float = OPA->_float < (float)OPB->_int;
523 OPC->_float = OPA->_float && (float)OPB->_int;
526 OPC->_float = OPA->_float || (float)OPB->_int;
529 OPC->_float = !OPA->_int;
532 OPC->_float = OPA->_int == OPB->_int;
535 OPC->_float = (float)OPA->_int == OPB->_float;
538 OPC->_float = OPA->_float == (float)OPB->_int;
541 OPC->_float = OPA->_int != OPB->_int;
544 OPC->_float = (float)OPA->_int != OPB->_float;
547 OPC->_float = OPA->_float != (float)OPB->_int;
550 OPB->_int = OPA->_int;
554 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
557 PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
561 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
562 ptr->_int = OPA->_int;
566 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
569 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
572 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
575 PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
579 ed = PRVM_PROG_TO_EDICT(OPA->edict);
580 OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int;
586 case OP_GSTOREP_FLD: // integers
588 case OP_GSTOREP_FNC: // pointers
590 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
593 PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
597 pr_iglobals[OPB->_int] = OPA->_int;
601 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
604 PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
608 pr_iglobals[OPB->_int ] = OPA->ivector[0];
609 pr_iglobals[OPB->_int+1] = OPA->ivector[1];
610 pr_iglobals[OPB->_int+2] = OPA->ivector[2];
614 i = OPA->_int + (int) OPB->_float;
616 if (i < 0 || i >= pr_globaldefs)
619 PRVM_ERROR ("%s Progs attempted to address an out of bounds global", PRVM_NAME);
623 OPC->_int = pr_iglobals[i];
633 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
636 PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
640 OPC->_int = pr_iglobals[OPA->_int];
645 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
648 PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
652 OPC->ivector[0] = pr_iglobals[OPA->_int ];
653 OPC->ivector[1] = pr_iglobals[OPA->_int+1];
654 OPC->ivector[2] = pr_iglobals[OPA->_int+2];
658 if (OPA->_int < 0 || OPA->_int >= st->b)
661 PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
670 PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);