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 printf
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 + 3 >= 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", PRVM_NAME);
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);
364 /* add instruction count to function profile count */
365 GLOBAL(OFS_RETURN)->ivector[0] = OPA->ivector[0];
366 GLOBAL(OFS_RETURN)->ivector[1] = OPA->ivector[1];
367 GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
369 st = prog->code + PROG_LEAVEFUNCTION();
370 if (!prog->stack_count)
378 /* LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized */
381 OPC->_int = OPA->_int + OPB->_int;
384 OPC->_int = OPA->_int + (int) OPB->_float;
387 OPC->_float = OPA->_float + (float) OPB->_int;
390 OPC->_int = OPA->_int - OPB->_int;
393 OPC->_int = OPA->_int - (int) OPB->_float;
396 OPC->_float = OPA->_float - (float) OPB->_int;
399 OPC->_int = OPA->_int * OPB->_int;
402 OPC->_int = OPA->_int * (int) OPB->_float;
405 OPC->_float = OPA->_float * (float) OPB->_int;
408 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
409 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
410 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
414 float temp = 1.0f / OPB->_float;
415 OPC->vector[0] = temp * OPA->vector[0];
416 OPC->vector[1] = temp * OPA->vector[1];
417 OPC->vector[2] = temp * OPA->vector[2];
421 OPC->_int = OPA->_int / OPB->_int;
424 OPC->_int = OPA->_int / (int) OPB->_float;
427 OPC->_float = OPA->_float / (float) OPB->_int;
430 OPC->_float = OPA->_int;
433 OPC->_int = OPA->_float;
436 OPC->_int = OPA->_int & OPB->_int;
439 OPC->_int = OPA->_int | OPB->_int;
441 case INSTR_BITAND_IF:
442 OPC->_int = OPA->_int & (int)OPB->_float;
445 OPC->_int = OPA->_int | (int)OPB->_float;
447 case INSTR_BITAND_FI:
448 OPC->_float = (int)OPA->_float & OPB->_int;
451 OPC->_float = (int)OPA->_float | OPB->_int;
454 OPC->_float = OPA->_int >= OPB->_int;
457 OPC->_float = OPA->_int <= OPB->_int;
460 OPC->_float = OPA->_int > OPB->_int;
463 OPC->_float = OPA->_int < OPB->_int;
466 OPC->_float = OPA->_int && OPB->_int;
469 OPC->_float = OPA->_int || OPB->_int;
472 OPC->_float = (float)OPA->_int >= OPB->_float;
475 OPC->_float = (float)OPA->_int <= OPB->_float;
478 OPC->_float = (float)OPA->_int > OPB->_float;
481 OPC->_float = (float)OPA->_int < OPB->_float;
484 OPC->_float = (float)OPA->_int && OPB->_float;
487 OPC->_float = (float)OPA->_int || OPB->_float;
490 OPC->_float = OPA->_float >= (float)OPB->_int;
493 OPC->_float = OPA->_float <= (float)OPB->_int;
496 OPC->_float = OPA->_float > (float)OPB->_int;
499 OPC->_float = OPA->_float < (float)OPB->_int;
502 OPC->_float = OPA->_float && (float)OPB->_int;
505 OPC->_float = OPA->_float || (float)OPB->_int;
508 OPC->_float = !OPA->_int;
511 OPC->_float = OPA->_int == OPB->_int;
514 OPC->_float = (float)OPA->_int == OPB->_float;
517 OPC->_float = OPA->_float == (float)OPB->_int;
520 OPC->_float = OPA->_int != OPB->_int;
523 OPC->_float = (float)OPA->_int != OPB->_float;
526 OPC->_float = OPA->_float != (float)OPB->_int;
529 OPB->_int = OPA->_int;
533 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
535 PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
539 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
540 ptr->_int = OPA->_int;
544 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
546 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
549 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
551 PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
555 ed = PRVM_PROG_TO_EDICT(OPA->edict);
556 OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int;
562 PRVM_ERROR("Illegal instruction in %s\n", PRVM_NAME);