18 # define RUNAWAYCHECK() \
20 if (++jumpcount == 10000000) \
22 prog->xstatement = st - prog->statements; \
23 PRVM_Profile(1<<30, 1000000, 0); \
24 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount); \
28 # define RUNAWAYCHECK()
30 #define GLOBALSIZE ((signed)sizeof(*prog->globals.generic)*prog->progs->numglobals)
35 #define PTR_VALUE(x) ((unsigned int)(x) & 0x3FFFFFFF)
38 // [type: 2 bits] [value: 30 bits]
40 // 0 - Entity field area
42 // 2 - Malloc()ed area
45 // s/30/62/ in the following lines:
46 #define PTR_FLD(x) (PTR_VALUE(x))
47 #define PTR_ISFLD(x) ( ((x)>>30) == 0 )
49 #define PTR_GBL(x) (PTR_VALUE(x) | (1<<30))
50 #define PTR_ISGBL(x) ( ((x)>>30) == 1 )
52 #define PTR_MEM(x) (PTR_VALUE(x) | (2<<30))
53 #define PTR_ISMEM(x) ( ((x)>>30) == 2 )
55 #define PTR_size (signed)sizeof(int)
57 #define PTR_ISVALID(x) \
59 ptrvalA = ((int *)(x) - (int *)prog->edictsfields), \
60 ptrvalB = ((int *)(x) - (int *)prog->globals.generic), \
61 ptrvalC = ((int *)(x) - (int *)/* TODO: fill in memory area*/ 0), \
62 (ptrvalA >= 0 && ptrvalA + 1 <= prog->entityfieldsarea) ? 1 : \
63 (ptrvalB >= 0 && ptrvalB + 1 <= GLOBALSIZE) ? 1 : \
64 (ptrvalC >= 0 && ptrvalC + 1 <= /* TODO: fill in memory area size */0) ? 1 : \
68 #define PTR_ptr3(from, off, access) \
69 if (PTR_ISGBL(from)) \
71 ptrval_t p = PTR_VALUE(from) + (off); \
72 if (p < 0 || p + (access)*PTR_size > GLOBALSIZE) \
74 prog->xfunction->profile += (st - startst); \
75 prog->xstatement = st - prog->statements; \
76 PRVM_ERROR("%s attempted to access an out of bounds global (%i)", PRVM_NAME, (int)p); \
79 ptr = (prvm_eval_t*)((int *)prog->globals.generic + p); \
81 else if (PTR_ISMEM(from)) \
83 ptrval_t p = PTR_VALUE(from) + (off); \
84 if (p < 0 || p + (access)*PTR_size > 0 /* TODO: FILL IN */) \
86 prog->xfunction->profile += (st - startst); \
87 prog->xstatement = st - prog->statements; \
88 PRVM_ERROR("%s attempted to access out of bounds memory (%i)", PRVM_NAME, (int)p); \
91 ptr = (prvm_eval_t*)((int *)0 /* TODO: FILL IN*/ + p /* TODO: REMOVE: */ * 0); \
95 ptrval_t p = PTR_VALUE(from) + (off); \
96 if (p < 0 || p + (access)*PTR_size > prog->entityfieldsarea) \
98 prog->xfunction->profile += (st - startst); \
99 prog->xstatement = st - prog->statements; \
100 PRVM_ERROR("%s attempted to access an out of bounds edict field (%i)", PRVM_NAME, (int)p); \
103 ptr = (prvm_eval_t*)((int *)prog->edictsfields + p); \
104 if (p < prog->progs->entityfields && !prog->allowworldwrites) \
105 Con_DPrintf("WARNING: assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(p)->s_name), (int)p, PRVM_NAME); \
109 #define PTR_ptr3(from, off, access) \
110 if (PTR_ISGBL(from)) \
112 ptrval_t p = PTR_VALUE(from) + (off); \
113 ptr = (prvm_eval_t *)((int*)prog->globals.generic + p); \
115 else if (PTR_ISMEM(from)) \
117 ptrval_t p = PTR_VALUE(from) + (off); \
118 ptr = (prvm_eval_t *)((int*)0 /* TODO: FILL IN*/ + p /* TODO: REMOVE: */ * 0); \
122 ptrval_t p = PTR_VALUE(from) + (off); \
123 ptr = (prvm_eval_t *)((int*)prog->edictsfields + p); \
126 #define PTR_ptr2(from, off) PTR_ptr3(from, off, 1)
127 #define PTR_ptr(from) PTR_ptr3(from, 0, 1)
129 typedef long ptrval_t;
131 // This code isn't #ifdef/#define protectable, don't try.
132 prvm_eval_t *swtch = NULL;
134 ptrval_t ptrvalA, ptrvalB, ptrvalC;
135 ptrvalA = 0; // get rid of the unused-warning for now
143 PRVM_PrintStatement(st);
145 #if PRVMSTATEMENTPROFILING
146 prog->statement_profile[st - prog->statements]++;
152 OPC->_float = OPA->_float + OPB->_float;
155 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
156 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
157 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
160 OPC->_float = OPA->_float - OPB->_float;
163 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
164 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
165 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
168 OPC->_float = OPA->_float * OPB->_float;
171 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
174 OPC->vector[0] = OPA->_float * OPB->vector[0];
175 OPC->vector[1] = OPA->_float * OPB->vector[1];
176 OPC->vector[2] = OPA->_float * OPB->vector[2];
179 OPC->vector[0] = OPB->_float * OPA->vector[0];
180 OPC->vector[1] = OPB->_float * OPA->vector[1];
181 OPC->vector[2] = OPB->_float * OPA->vector[2];
184 if( OPB->_float != 0.0f )
186 OPC->_float = OPA->_float / OPB->_float;
190 if (developer.integer)
192 prog->xfunction->profile += (st - startst);
194 prog->xstatement = st - prog->statements;
195 VM_Warning( "Attempted division by zero in %s\n", PRVM_NAME );
201 OPC->_float = (int)OPA->_float & (int)OPB->_float;
204 OPC->_float = (int)OPA->_float | (int)OPB->_float;
207 OPC->_float = OPA->_float >= OPB->_float;
210 OPC->_float = OPA->_float <= OPB->_float;
213 OPC->_float = OPA->_float > OPB->_float;
216 OPC->_float = OPA->_float < OPB->_float;
219 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
222 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
225 OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
228 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
231 OPC->_float = !OPA->string || !*PRVM_GetString(OPA->string);
234 OPC->_float = !OPA->function;
237 OPC->_float = (OPA->edict == 0);
240 OPC->_float = OPA->_float == OPB->_float;
243 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
246 OPC->_float = !strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
249 OPC->_float = OPA->_int == OPB->_int;
252 OPC->_float = OPA->function == OPB->function;
255 OPC->_float = OPA->_float != OPB->_float;
258 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
261 OPC->_float = strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
264 OPC->_float = OPA->_int != OPB->_int;
267 OPC->_float = OPA->function != OPB->function;
273 case OP_STORE_FLD: // integers
275 case OP_STORE_FNC: // pointers
278 OPB->_int = OPA->_int;
281 OPB->ivector[0] = OPA->ivector[0];
282 OPB->ivector[1] = OPA->ivector[1];
283 OPB->ivector[2] = OPA->ivector[2];
288 case OP_STOREP_FLD: // integers
290 case OP_STOREP_FNC: // pointers
293 ptr->_int = OPA->_int;
296 PTR_ptr3(OPB->_int, 0, 3);
297 ptr->ivector[0] = OPA->ivector[0];
298 ptr->ivector[1] = OPA->ivector[1];
299 ptr->ivector[2] = OPA->ivector[2];
304 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
306 prog->xfunction->profile += (st - startst);
307 prog->xstatement = st - prog->statements;
308 PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number", PRVM_NAME);
311 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
313 prog->xfunction->profile += (st - startst);
314 prog->xstatement = st - prog->statements;
315 PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
320 if (OPA->edict == 0 && !prog->allowworldwrites)
322 prog->xfunction->profile += (st - startst);
323 prog->xstatement = st - prog->statements;
324 PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
328 ed = PRVM_PROG_TO_EDICT(OPA->edict);
329 OPC->_int = PTR_FLD(((int *)ed->fields.vp + OPB->_int) - (int *)prog->edictsfields);
339 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
341 prog->xfunction->profile += (st - startst);
342 prog->xstatement = st - prog->statements;
343 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
346 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
348 prog->xfunction->profile += (st - startst);
349 prog->xstatement = st - prog->statements;
350 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
354 ed = PRVM_PROG_TO_EDICT(OPA->edict);
355 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
360 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
362 prog->xfunction->profile += (st - startst);
363 prog->xstatement = st - prog->statements;
364 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
367 if (OPB->_int < 0 || OPB->_int + 2 >= prog->progs->entityfields)
369 prog->xfunction->profile += (st - startst);
370 prog->xstatement = st - prog->statements;
371 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
375 ed = PRVM_PROG_TO_EDICT(OPA->edict);
376 OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
377 OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
378 OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
384 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
385 // TODO add an "int-if", and change this one to OPA->_float
386 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
387 // and entity, string, field values can never have that value
389 prog->xfunction->profile += (st - startst);
390 st += st->b - 1; // offset the s++
393 // no bounds check needed, it is done when loading progs
399 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
400 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
401 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
402 // and entity, string, field values can never have that value
404 prog->xfunction->profile += (st - startst);
405 st += st->b - 1; // offset the s++
414 prog->xfunction->profile += (st - startst);
415 st += st->b - 1; // offset the s++
424 prog->xfunction->profile += (st - startst);
425 st += st->b - 1; // offset the s++
427 // no bounds check needed, it is done when loading progs
433 prog->xfunction->profile += (st - startst);
434 st += st->a - 1; // offset the s++
436 // no bounds check needed, it is done when loading progs
440 // CALLxH used and tested, they do work!
448 PRVM_G_VECTOR(OFS_PARM1)[0] = OPC->vector[0];
449 PRVM_G_VECTOR(OFS_PARM1)[1] = OPC->vector[1];
450 PRVM_G_VECTOR(OFS_PARM1)[2] = OPC->vector[2];
452 PRVM_G_VECTOR(OFS_PARM0)[0] = OPB->vector[0];
453 PRVM_G_VECTOR(OFS_PARM0)[1] = OPB->vector[1];
454 PRVM_G_VECTOR(OFS_PARM0)[2] = OPB->vector[2];
465 prog->xfunction->profile += (st - startst);
467 prog->xstatement = st - prog->statements;
469 if (st->op >= OP_CALL1H && st->op <= OP_CALL8H)
470 prog->argc = st->op - (OP_CALL1H-1);
472 prog->argc = st->op - OP_CALL0;
474 PRVM_ERROR("NULL function in %s", PRVM_NAME);
477 if(!OPA->function || OPA->function >= (unsigned int)prog->progs->numfunctions)
479 prog->xfunction->profile += (st - startst);
480 prog->xstatement = st - prog->statements; // we better stay on the previously executed statement
481 PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
486 newf = &prog->functions[OPA->function];
489 if (newf->first_statement < 0)
491 // negative statements are built in functions
492 int builtinnumber = -newf->first_statement;
493 prog->xfunction->builtinsprofile++;
494 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
495 prog->builtins[builtinnumber]();
497 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
500 st = prog->statements + PRVM_EnterFunction(newf);
506 prog->xfunction->profile += (st - startst);
507 prog->xstatement = st - prog->statements;
509 prog->globals.generic[OFS_RETURN] = prog->globals.generic[(unsigned short) st->a];
510 prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[(unsigned short) st->a+1];
511 prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[(unsigned short) st->a+2];
513 st = prog->statements + PRVM_LeaveFunction();
515 if (prog->depth <= exitdepth)
516 goto cleanup; // all done
517 if (prog->trace != cachedpr_trace)
518 goto chooseexecprogram;
522 if(prog->flag & PRVM_OP_STATE)
524 ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
525 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.nextthink)->_float = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.time)->_float + 0.1;
526 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.frame)->_float = OPA->_float;
527 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.think)->function = OPB->function;
531 prog->xfunction->profile += (st - startst);
532 prog->xstatement = st - prog->statements;
533 PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
537 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
540 OPC->_int = OPA->_int + OPB->_int;
543 OPC->_int = OPA->_int + (int) OPB->_float;
546 OPC->_float = OPA->_float + (float) OPB->_int;
549 OPC->_int = OPA->_int - OPB->_int;
552 OPC->_int = OPA->_int - (int) OPB->_float;
555 OPC->_float = OPA->_float - (float) OPB->_int;
558 OPC->_int = OPA->_int * OPB->_int;
561 OPC->_int = OPA->_int * (int) OPB->_float;
564 OPC->_float = OPA->_float * (float) OPB->_int;
567 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
568 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
569 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
573 float temp = 1.0f / OPB->_float;
574 OPC->vector[0] = temp * OPA->vector[0];
575 OPC->vector[1] = temp * OPA->vector[1];
576 OPC->vector[2] = temp * OPA->vector[2];
580 OPC->_int = OPA->_int / OPB->_int;
583 OPC->_int = OPA->_int / (int) OPB->_float;
586 OPC->_float = OPA->_float / (float) OPB->_int;
589 OPB->_float = OPA->_int;
592 OPB->_int = OPA->_float;
595 OPC->_int = OPA->_int & OPB->_int;
598 OPC->_int = OPA->_int | OPB->_int;
601 OPC->_int = OPA->_int & (int)OPB->_float;
604 OPC->_int = OPA->_int | (int)OPB->_float;
607 OPC->_float = (int)OPA->_float & OPB->_int;
610 OPC->_float = (int)OPA->_float | OPB->_int;
613 OPC->_float = OPA->_int >= OPB->_int;
616 OPC->_float = OPA->_int <= OPB->_int;
619 OPC->_float = OPA->_int > OPB->_int;
622 OPC->_float = OPA->_int < OPB->_int;
625 OPC->_float = OPA->_int && OPB->_int;
628 OPC->_float = OPA->_int || OPB->_int;
631 OPC->_float = (float)OPA->_int >= OPB->_float;
634 OPC->_float = (float)OPA->_int <= OPB->_float;
637 OPC->_float = (float)OPA->_int > OPB->_float;
640 OPC->_float = (float)OPA->_int < OPB->_float;
643 OPC->_float = (float)OPA->_int && OPB->_float;
646 OPC->_float = (float)OPA->_int || OPB->_float;
649 OPC->_float = OPA->_float >= (float)OPB->_int;
652 OPC->_float = OPA->_float <= (float)OPB->_int;
655 OPC->_float = OPA->_float > (float)OPB->_int;
658 OPC->_float = OPA->_float < (float)OPB->_int;
661 OPC->_float = OPA->_float && (float)OPB->_int;
664 OPC->_float = OPA->_float || (float)OPB->_int;
667 OPC->_float = !OPA->_int;
670 OPC->_float = OPA->_int == OPB->_int;
673 OPC->_float = (float)OPA->_int == OPB->_float;
676 OPC->_float = OPA->_float == (float)OPB->_int;
679 OPC->_float = OPA->_int != OPB->_int;
682 OPC->_float = (float)OPA->_int != OPB->_float;
685 OPC->_float = OPA->_float != (float)OPB->_int;
689 ptr->_int = OPA->_int;
693 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
695 prog->xfunction->profile += (st - startst);
696 prog->xstatement = st - prog->statements;
697 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
700 if (OPB->_int < 0 || OPB->_int >= prog->progs->entityfields)
702 prog->xfunction->profile += (st - startst);
703 prog->xstatement = st - prog->statements;
704 PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
708 ed = PRVM_PROG_TO_EDICT(OPA->edict);
709 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
717 ptr = (prvm_eval_t *)(&OPA->_int + OPB->_int);
719 if (!PTR_ISVALID(ptr))
721 prog->xfunction->profile += (st - startst);
722 prog->xstatement = st - prog->statements;
723 PRVM_ERROR ("%s Progs attempted to read from an out of bounds address (%i)", PRVM_NAME, OPB->_int);
727 OPC->_int = ptr->_int;
731 ptr = (prvm_eval_t *)(&OPA->_int + OPB->_int);
733 if (!PTR_ISVALID(ptr))
735 prog->xfunction->profile += (st - startst);
736 prog->xstatement = st - prog->statements;
737 PRVM_ERROR ("%s Progs attempted to read from an out of bounds address (%i)", PRVM_NAME, OPB->_int);
741 OPC->vector[0] = ptr->vector[0];
742 OPC->vector[1] = ptr->vector[1];
743 OPC->vector[2] = ptr->vector[2];
746 if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
748 prog->xfunction->profile += (st - startst);
749 prog->xstatement = st - prog->statements;
750 PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
755 case OP_RAND0: // random number between 0 and 1
756 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0,1);
758 case OP_RAND1: // random number between 0 and OPA
759 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0,OPA->_float);
761 case OP_RAND2: // random number between OPA and OPB
762 if(OPA->_float < OPB->_float)
763 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(OPA->_float, OPB->_float);
765 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(OPB->_float, OPA->_float);
767 case OP_RANDV0: // random vector between 0 and 1
768 PRVM_G_VECTOR(OFS_RETURN)[0] = lhrandom(0,1);
769 PRVM_G_VECTOR(OFS_RETURN)[1] = lhrandom(0,1);
770 PRVM_G_VECTOR(OFS_RETURN)[2] = lhrandom(0,1);
772 case OP_RANDV1: // random vector between 0 and OPA
773 PRVM_G_VECTOR(OFS_RETURN)[0] = lhrandom(0,OPA->vector[0]);
774 PRVM_G_VECTOR(OFS_RETURN)[1] = lhrandom(0,OPA->vector[1]);
775 PRVM_G_VECTOR(OFS_RETURN)[2] = lhrandom(0,OPA->vector[2]);
777 case OP_RANDV2: // random vector between OPA and OPB
780 for(i = 0; i < 3; ++i)
782 if(OPA->vector[i] < OPB->vector[i])
783 PRVM_G_VECTOR(OFS_RETURN)[i] = lhrandom(OPA->vector[i], OPB->vector[i]);
785 PRVM_G_VECTOR(OFS_RETURN)[i] = lhrandom(OPB->vector[i], OPA->vector[i]);
800 prog->xfunction->profile += (st - startst);
802 st += st->b - 1; // offset the s++
810 if(swtch->_float == OPA->_float)
813 prog->xfunction->profile += (st - startst);
821 if(swtch->_int == OPA->_int)
824 prog->xfunction->profile += (st - startst);
830 if(swtch->_int == OPA->_int)
833 prog->xfunction->profile += (st - startst);
837 // switch(string) case "string" ->
838 // one of them may be null, not both
839 if((!swtch->_int && PRVM_GetString(OPA->string)) || (!OPA->_int && PRVM_GetString(swtch->string)))
841 if(!strcmp(PRVM_GetString(swtch->string), PRVM_GetString(OPA->string)))
844 prog->xfunction->profile += (st - startst);
850 if(swtch->vector[0] == OPA->vector[0] &&
851 swtch->vector[1] == OPA->vector[1] &&
852 swtch->vector[2] == OPA->vector[2])
855 prog->xfunction->profile += (st - startst);
861 PRVM_ERROR("OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
871 if(swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
878 PRVM_ERROR("OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
883 OPC->_float = (float)OPA->_int;
886 OPC->_int = (int)(OPA->_float);
890 OPC->_float = (float)(ptr->_int);
894 OPC->_int = (int)(ptr->_float);
899 OPC->_float = (ptr->_float += OPA->_float);
902 PTR_ptr3(OPB->_int, 0, 3);
903 OPC->vector[0] = (ptr->vector[0] += OPA->vector[0]);
904 OPC->vector[1] = (ptr->vector[1] += OPA->vector[1]);
905 OPC->vector[2] = (ptr->vector[2] += OPA->vector[2]);
910 OPC->_float = (ptr->_float -= OPA->_float);
913 PTR_ptr3(OPB->_int, 0, 3);
914 OPC->vector[0] = (ptr->vector[0] -= OPA->vector[0]);
915 OPC->vector[1] = (ptr->vector[1] -= OPA->vector[1]);
916 OPC->vector[2] = (ptr->vector[2] -= OPA->vector[2]);
921 OPC->_float = (ptr->_float *= OPA->_float);
925 PTR_ptr3(OPB->_int, 0, 3);
926 OPC->vector[0] = (ptr->vector[0] -= OPA->_float);
927 OPC->vector[1] = (ptr->vector[1] -= OPA->_float);
928 OPC->vector[2] = (ptr->vector[2] -= OPA->_float);
933 OPC->_float = (ptr->_float /= OPA->_float);
937 if(!OPA->string || !PRVM_GetString(OPA->string))
941 if(OPA->string && PRVM_GetString(OPA->string))
945 case OP_GLOBALADDRESS:
946 OPC->_int = ((&(OPA->_int) + OPB->_int) - (int*)prog->globals.generic);
948 if (OPC->_int < 0 || OPC->_int + 4 > GLOBALSIZE)
950 prog->xfunction->profile += (st - startst);
951 prog->xstatement = st - prog->statements;
952 PRVM_ERROR("%s attempted to address an invalid global (%i)", PRVM_NAME, OPC->_int);
956 OPC->_int = PTR_GBL(OPC->_int);
960 // NOTE: dp pointers are no pointers as in byte-offsets, but item-offsets
962 // I hope this is never used as an optimization for "A = B + C * 4" :P
963 OPC->_int = OPA->_int + OPB->_int*1;
966 case OP_ADD_SF: //(char*)c = (char*)a + (float)b
967 OPC->_int = OPA->_int + (int)OPB->_float;
969 case OP_SUB_S: //(float)c = (char*)a - (char*)b
970 OPC->_int = OPA->_int - OPB->_int;
979 PTR_ptr2(OPA->_int, OPB->_int);
980 OPC->_int = ptr->_int;
983 PTR_ptr3(OPA->_int, OPB->_int, 3);
984 OPC->vector[0] = ptr->vector[0];
985 OPC->vector[1] = ptr->vector[1];
986 OPC->vector[2] = ptr->vector[2];
989 // not wanted, keeping it in this comment for now though, because...
994 // ... because this could still be reconsidered, after all it only loads
996 PTR_ptr2(OPA->_int, (int)OPB->_float);
997 OPC->_int = ptr->_int;
1002 OPC->_int = OPA->_int ^ OPB->_int;
1005 OPC->_int = OPA->_int >> OPB->_int;
1008 OPC->_int = OPA->_int << OPB->_int;
1011 // hexen2 opcodes.. afaik fteqcc shouldn't use those
1014 CStateOp(prog, OPA->_float, OPB->_float, newf);
1018 CWStateOp(prog, OPA->_float, OPB->_float, newf);
1022 ThinkTimeOp(prog, PRVM_PROG_TO_EDICT(OPA->edict), OPB->_float);
1026 prog->xfunction->profile += (st - startst);
1027 prog->xstatement = st - prog->statements;
1029 if(st->op < OP_NUMOPS)
1030 PRVM_ERROR("Instruction %i: %s\n", st->op, prvm_opnames[st->op]);
1031 PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);