2 /* Expected variables */
6 #if !defined(QCVM_PROFILE)
7 # define QCVM_PROFILE 0
10 #if !defined(QCVM_TRACE)
14 #if !defined(FLOAT_IS_TRUE_FOR_INT)
15 # define FLOAT_IS_TRUE_FOR_INT(x) ( (x) & 0x7FFFFFFF )
18 #if !defined(PRVM_ERROR)
19 # define PRVM_ERROR prog->vmerror++, printvmerr
22 #if !defined(PRVM_NAME)
23 # define PRVM_NAME (prog->filename)
26 #if !defined(PROG_GETSTRING)
27 # define PROG_GETSTRING(x) prog_getstring(prog, (x))
30 #if !defined(PROG_ENTFIELD)
31 # define PROG_ENTFIELD(x) prog_entfield(prog, (x))
34 #if !defined(PROG_GETEDICT)
35 # define PROG_GETEDICT(x) prog_getedict(prog, (x))
38 #if !defined(PROG_ENTERFUNCTION)
39 # define PROG_ENTERFUNCTION(x) prog_enterfunction(prog, (x))
42 #if !defined(PROG_LEAVEFUNCTION)
43 # define PROG_LEAVEFUNCTION() prog_leavefunction(prog)
46 #define OPA ( (qcany*) (prog->globals + st->o1.u1) )
47 #define OPB ( (qcany*) (prog->globals + st->o2.u1) )
48 #define OPC ( (qcany*) (prog->globals + st->o3.u1) )
49 #define GLOBAL(x) ( (qcany*) (prog->globals + (x)) )
53 prog_section_function *newf;
60 st = prog->code + prog->ip;
64 prog->profile[st - prog->code]++;
68 prog_print_statement(prog, st);
74 OPC->_float = OPA->_float + OPB->_float;
77 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
78 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
79 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
82 OPC->_float = OPA->_float - OPB->_float;
85 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
86 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
87 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
90 OPC->_float = OPA->_float * OPB->_float;
93 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
96 OPC->vector[0] = OPA->_float * OPB->vector[0];
97 OPC->vector[1] = OPA->_float * OPB->vector[1];
98 OPC->vector[2] = OPA->_float * OPB->vector[2];
101 OPC->vector[0] = OPB->_float * OPA->vector[0];
102 OPC->vector[1] = OPB->_float * OPA->vector[1];
103 OPC->vector[2] = OPB->_float * OPA->vector[2];
106 if( OPB->_float != 0.0f )
108 OPC->_float = OPA->_float / OPB->_float;
116 OPC->_float = (int)OPA->_float & (int)OPB->_float;
119 OPC->_float = (int)OPA->_float | (int)OPB->_float;
122 OPC->_float = OPA->_float >= OPB->_float;
125 OPC->_float = OPA->_float <= OPB->_float;
128 OPC->_float = OPA->_float > OPB->_float;
131 OPC->_float = OPA->_float < OPB->_float;
134 /* TODO change this back to float, and add AND_I to be used by fteqcc for anything not a float */
135 OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) && FLOAT_IS_TRUE_FOR_INT(OPB->_int);
138 /* TODO change this back to float, and add AND_I to be used by fteqcc for anything not a float */
139 OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) || FLOAT_IS_TRUE_FOR_INT(OPB->_int);
142 OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
145 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
148 OPC->_float = !OPA->string || !*PROG_GETSTRING(OPA->string);
151 OPC->_float = !OPA->function;
154 OPC->_float = (OPA->edict == 0);
157 OPC->_float = OPA->_float == OPB->_float;
160 OPC->_float = (OPA->vector[0] == OPB->vector[0]) &&
161 (OPA->vector[1] == OPB->vector[1]) &&
162 (OPA->vector[2] == OPB->vector[2]);
165 OPC->_float = !strcmp(PROG_GETSTRING(OPA->string),PROG_GETSTRING(OPB->string));
168 OPC->_float = OPA->_int == OPB->_int;
171 OPC->_float = OPA->function == OPB->function;
174 OPC->_float = OPA->_float != OPB->_float;
177 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
180 OPC->_float = strcmp(PROG_GETSTRING(OPA->string),PROG_GETSTRING(OPB->string));
183 OPC->_float = OPA->_int != OPB->_int;
186 OPC->_float = OPA->function != OPB->function;
189 /*==================*/
191 case INSTR_STORE_ENT:
192 case INSTR_STORE_FLD:
194 case INSTR_STORE_FNC:
195 OPB->_int = OPA->_int;
198 OPB->ivector[0] = OPA->ivector[0];
199 OPB->ivector[1] = OPA->ivector[1];
200 OPB->ivector[2] = OPA->ivector[2];
204 case INSTR_STOREP_ENT:
205 case INSTR_STOREP_FLD:
207 case INSTR_STOREP_FNC:
208 if (OPB->_int < 0 || OPB->_int >= prog->entitydata_count)
210 PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
213 if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
214 PRVM_ERROR("ERROR: assignment to world.%s (field %i) in %s\n", PROG_GETSTRING(PROG_ENTFIELD(OPB->_int)->name), OPB->_int, PRVM_NAME);
215 ptr = (qcany*)(prog->entitydata + OPB->_int);
216 ptr->_int = OPA->_int;
219 if (OPB->_int < 0 || OPB->_int + 2 >= prog->entitydata_count)
221 PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
224 if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
225 PRVM_ERROR("ERROR: assignment to world.%s (field %i) in %s\n", PROG_GETSTRING(PROG_ENTFIELD(OPB->_int)->name), OPB->_int, PRVM_NAME);
226 ptr = (qcany*)(prog->entitydata + OPB->_int);
227 ptr->ivector[0] = OPA->ivector[0];
228 ptr->ivector[1] = OPA->ivector[1];
229 ptr->ivector[2] = OPA->ivector[2];
233 if (OPA->edict < 0 || OPA->edict >= prog->entities)
235 PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number %i", PRVM_NAME, OPA->edict);
238 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
240 PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
244 ed = PROG_GETEDICT(OPA->edict);
245 OPC->_int = ((qcint*)ed) - prog->entitydata;
246 OPC->_int += OPB->_int;
254 if (OPA->edict < 0 || OPA->edict >= prog->entities)
256 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
259 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
261 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
264 ed = PROG_GETEDICT(OPA->edict);
265 OPC->_int = ((qcany*)( ((qcint*)ed) + OPB->_int ))->_int;
269 if (OPA->edict < 0 || OPA->edict >= prog->entities)
271 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
274 if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfields)
276 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
279 ed = PROG_GETEDICT(OPA->edict);
280 OPC->ivector[0] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[0];
281 OPC->ivector[1] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[1];
282 OPC->ivector[2] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[2];
285 /*==================*/
288 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
289 /* TODO add an "int-if", and change this one to OPA->_float
290 although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
291 and entity, string, field values can never have that value
294 st += st->o2.s1 - 1; /* offset the s++ */
295 if (++jumpcount >= maxjumps)
297 PRVM_ERROR("%s runaway loop counter hit limit of %li jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
303 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
305 st += st->o2.s1 - 1; /* offset the s++ */
306 /* no bounds check needed, it is done when loading progs */
307 if (++jumpcount >= maxjumps)
309 PRVM_ERROR("%s runaway loop counter hit limit of %li jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
315 st += st->o1.s1 - 1; /* offset the s++ */
316 /* no bounds check needed, it is done when loading progs */
317 if (++jumpcount == 10000000)
319 PRVM_ERROR("%s runaway loop counter hit limit of %li jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
332 prog->argc = st->opcode - INSTR_CALL0;
334 PRVM_ERROR("NULL function in %s", PRVM_NAME);
336 if(!OPA->function || OPA->function >= (unsigned int)prog->functions_count)
338 PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
342 newf = &prog->functions[OPA->function];
345 prog->statement = (st - prog->code) + 1;
349 /* negative statements are built in functions */
350 int builtinnumber = -newf->entry;
351 if (builtinnumber < prog->builtins_count && prog->builtins[builtinnumber])
353 prog->builtins[builtinnumber](prog);
356 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
359 st = prog->code + PROG_ENTERFUNCTION(newf);
366 /* add instruction count to function profile count */
367 GLOBAL(OFS_RETURN)->ivector[0] = OPA->ivector[0];
368 GLOBAL(OFS_RETURN)->ivector[1] = OPA->ivector[1];
369 GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
371 st = prog->code + PROG_LEAVEFUNCTION();
372 if (!prog->stack_count)
380 /* LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized */
383 OPC->_int = OPA->_int + OPB->_int;
386 OPC->_int = OPA->_int + (int) OPB->_float;
389 OPC->_float = OPA->_float + (float) OPB->_int;
392 OPC->_int = OPA->_int - OPB->_int;
395 OPC->_int = OPA->_int - (int) OPB->_float;
398 OPC->_float = OPA->_float - (float) OPB->_int;
401 OPC->_int = OPA->_int * OPB->_int;
404 OPC->_int = OPA->_int * (int) OPB->_float;
407 OPC->_float = OPA->_float * (float) OPB->_int;
410 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
411 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
412 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
416 float temp = 1.0f / OPB->_float;
417 OPC->vector[0] = temp * OPA->vector[0];
418 OPC->vector[1] = temp * OPA->vector[1];
419 OPC->vector[2] = temp * OPA->vector[2];
423 OPC->_int = OPA->_int / OPB->_int;
426 OPC->_int = OPA->_int / (int) OPB->_float;
429 OPC->_float = OPA->_float / (float) OPB->_int;
432 OPC->_float = OPA->_int;
435 OPC->_int = OPA->_float;
438 OPC->_int = OPA->_int & OPB->_int;
441 OPC->_int = OPA->_int | OPB->_int;
443 case INSTR_BITAND_IF:
444 OPC->_int = OPA->_int & (int)OPB->_float;
447 OPC->_int = OPA->_int | (int)OPB->_float;
449 case INSTR_BITAND_FI:
450 OPC->_float = (int)OPA->_float & OPB->_int;
453 OPC->_float = (int)OPA->_float | OPB->_int;
456 OPC->_float = OPA->_int >= OPB->_int;
459 OPC->_float = OPA->_int <= OPB->_int;
462 OPC->_float = OPA->_int > OPB->_int;
465 OPC->_float = OPA->_int < OPB->_int;
468 OPC->_float = OPA->_int && OPB->_int;
471 OPC->_float = OPA->_int || OPB->_int;
474 OPC->_float = (float)OPA->_int >= OPB->_float;
477 OPC->_float = (float)OPA->_int <= OPB->_float;
480 OPC->_float = (float)OPA->_int > OPB->_float;
483 OPC->_float = (float)OPA->_int < OPB->_float;
486 OPC->_float = (float)OPA->_int && OPB->_float;
489 OPC->_float = (float)OPA->_int || OPB->_float;
492 OPC->_float = OPA->_float >= (float)OPB->_int;
495 OPC->_float = OPA->_float <= (float)OPB->_int;
498 OPC->_float = OPA->_float > (float)OPB->_int;
501 OPC->_float = OPA->_float < (float)OPB->_int;
504 OPC->_float = OPA->_float && (float)OPB->_int;
507 OPC->_float = OPA->_float || (float)OPB->_int;
510 OPC->_float = !OPA->_int;
513 OPC->_float = OPA->_int == OPB->_int;
516 OPC->_float = (float)OPA->_int == OPB->_float;
519 OPC->_float = OPA->_float == (float)OPB->_int;
522 OPC->_float = OPA->_int != OPB->_int;
525 OPC->_float = (float)OPA->_int != OPB->_float;
528 OPC->_float = OPA->_float != (float)OPB->_int;
531 OPB->_int = OPA->_int;
535 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
537 PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
541 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
542 ptr->_int = OPA->_int;
546 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
548 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
551 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
553 PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
557 ed = PRVM_PROG_TO_EDICT(OPA->edict);
558 OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int;
564 PRVM_ERROR("Illegal instruction in %s\n", PRVM_NAME);