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 : \
66 // well, the last change removed all #ifs - I'll still keep them
67 #define PRVMBOUNDSCHECK 1
69 #define PTR_ptr3(from, off, access) \
70 if (PTR_ISGBL(from)) \
72 ptrval_t p = PTR_VALUE(from) + (off); \
73 if (p < 0 || p + (access)*PTR_size > GLOBALSIZE) \
75 prog->xfunction->profile += (st - startst); \
76 prog->xstatement = st - prog->statements; \
77 PRVM_ERROR("%s attempted to access an out of bounds global (%i)", PRVM_NAME, (int)p); \
80 ptr = (prvm_eval_t*)((int *)prog->globals.generic + p); \
82 else if (PTR_ISMEM(from)) \
84 ptrval_t p = PTR_VALUE(from) + (off); \
85 if (p < 0 || p + (access)*PTR_size > 0 /* TODO: FILL IN */) \
87 prog->xfunction->profile += (st - startst); \
88 prog->xstatement = st - prog->statements; \
89 PRVM_ERROR("%s attempted to access out of bounds memory (%i)", PRVM_NAME, (int)p); \
92 ptr = (prvm_eval_t*)((int *)0 /* TODO: FILL IN*/ + p /* TODO: REMOVE: */ * 0); \
96 ptrval_t p = PTR_VALUE(from) + (off); \
97 if (p < 0 || p + (access)*PTR_size > prog->entityfieldsarea) \
99 prog->xfunction->profile += (st - startst); \
100 prog->xstatement = st - prog->statements; \
101 PRVM_ERROR("%s attempted to access an out of bounds edict field (%i)", PRVM_NAME, (int)p); \
104 ptr = (prvm_eval_t*)((int *)prog->edictsfields + p); \
105 if (p < prog->progs->entityfields && !prog->allowworldwrites) \
106 Con_DPrintf("WARNING: assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(p)->s_name), (int)p, PRVM_NAME); \
110 #define PTR_ptr3(from, off, access) \
111 if (PTR_ISGBL(from)) \
113 ptrval_t p = PTR_VALUE(from) + (off); \
114 ptr = (prvm_eval_t *)((int*)prog->globals.generic + p); \
116 else if (PTR_ISMEM(from)) \
118 ptrval_t p = PTR_VALUE(from) + (off); \
119 ptr = (prvm_eval_t *)((int*)0 /* TODO: FILL IN*/ + p /* TODO: REMOVE: */ * 0); \
123 ptrval_t p = PTR_VALUE(from) + (off); \
124 ptr = (prvm_eval_t *)((int*)prog->edictsfields + p); \
127 #define PTR_ptr2(from, off) PTR_ptr3(from, off, 1)
128 #define PTR_ptr(from) PTR_ptr3(from, 0, 1)
130 typedef long ptrval_t;
132 // This code isn't #ifdef/#define protectable, don't try.
133 prvm_eval_t *swtch = NULL;
135 ptrval_t ptrvalA, ptrvalB, ptrvalC;
136 ptrvalA = 0; // get rid of the unused-warning for now
143 #if PRVMSLOWINTERPRETER
145 PRVM_PrintStatement(st);
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];
303 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
305 prog->xfunction->profile += (st - startst);
306 prog->xstatement = st - prog->statements;
307 PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number", PRVM_NAME);
310 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
312 prog->xfunction->profile += (st - startst);
313 prog->xstatement = st - prog->statements;
314 PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
318 if (OPA->edict == 0 && !prog->allowworldwrites)
320 prog->xfunction->profile += (st - startst);
321 prog->xstatement = st - prog->statements;
322 PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
326 ed = PRVM_PROG_TO_EDICT(OPA->edict);
327 OPC->_int = PTR_FLD(((int *)ed->fields.vp + OPB->_int) - (int *)prog->edictsfields);
337 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
339 prog->xfunction->profile += (st - startst);
340 prog->xstatement = st - prog->statements;
341 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
344 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
346 prog->xfunction->profile += (st - startst);
347 prog->xstatement = st - prog->statements;
348 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
352 ed = PRVM_PROG_TO_EDICT(OPA->edict);
353 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
358 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
360 prog->xfunction->profile += (st - startst);
361 prog->xstatement = st - prog->statements;
362 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
365 if (OPB->_int < 0 || OPB->_int + 2 >= prog->progs->entityfields)
367 prog->xfunction->profile += (st - startst);
368 prog->xstatement = st - prog->statements;
369 PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
373 ed = PRVM_PROG_TO_EDICT(OPA->edict);
374 OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
375 OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
376 OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
382 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
383 // TODO add an "int-if", and change this one to OPA->_float
384 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
385 // and entity, string, field values can never have that value
387 prog->xfunction->profile += (st - startst);
388 st += st->b - 1; // offset the s++
391 // no bounds check needed, it is done when loading progs
397 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
398 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
399 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
400 // and entity, string, field values can never have that value
402 prog->xfunction->profile += (st - startst);
403 st += st->b - 1; // offset the s++
412 prog->xfunction->profile += (st - startst);
413 st += st->b - 1; // offset the s++
422 prog->xfunction->profile += (st - startst);
423 st += st->b - 1; // offset the s++
425 // no bounds check needed, it is done when loading progs
431 prog->xfunction->profile += (st - startst);
432 st += st->a - 1; // offset the s++
434 // no bounds check needed, it is done when loading progs
438 // CALLxH used and tested, they do work!
446 PRVM_G_VECTOR(OFS_PARM1)[0] = OPC->vector[0];
447 PRVM_G_VECTOR(OFS_PARM1)[1] = OPC->vector[1];
448 PRVM_G_VECTOR(OFS_PARM1)[2] = OPC->vector[2];
450 PRVM_G_VECTOR(OFS_PARM0)[0] = OPB->vector[0];
451 PRVM_G_VECTOR(OFS_PARM0)[1] = OPB->vector[1];
452 PRVM_G_VECTOR(OFS_PARM0)[2] = OPB->vector[2];
463 prog->xfunction->profile += (st - startst);
465 prog->xstatement = st - prog->statements;
467 if (st->op >= OP_CALL1H && st->op <= OP_CALL8H)
468 prog->argc = st->op - (OP_CALL1H-1);
470 prog->argc = st->op - OP_CALL0;
472 PRVM_ERROR("NULL function in %s", PRVM_NAME);
474 if(!OPA->function || OPA->function >= (unsigned int)prog->progs->numfunctions)
476 prog->xfunction->profile += (st - startst);
477 prog->xstatement = st - prog->statements; // we better stay on the previously executed statement
478 PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
482 newf = &prog->functions[OPA->function];
485 if (newf->first_statement < 0)
487 // negative statements are built in functions
488 int builtinnumber = -newf->first_statement;
489 prog->xfunction->builtinsprofile++;
490 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
491 prog->builtins[builtinnumber]();
493 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
496 st = prog->statements + PRVM_EnterFunction(newf);
502 prog->xfunction->profile += (st - startst);
503 prog->xstatement = st - prog->statements;
505 prog->globals.generic[OFS_RETURN] = prog->globals.generic[(unsigned short) st->a];
506 prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[(unsigned short) st->a+1];
507 prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[(unsigned short) st->a+2];
509 st = prog->statements + PRVM_LeaveFunction();
511 if (prog->depth <= exitdepth)
512 goto cleanup; // all done
513 if (prog->trace != cachedpr_trace)
514 goto chooseexecprogram;
518 if(prog->flag & PRVM_OP_STATE)
520 ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
521 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.nextthink)->_float = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.time)->_float + 0.1;
522 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.frame)->_float = OPA->_float;
523 PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.think)->function = OPB->function;
527 prog->xfunction->profile += (st - startst);
528 prog->xstatement = st - prog->statements;
529 PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
533 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
536 OPC->_int = OPA->_int + OPB->_int;
539 OPC->_int = OPA->_int + (int) OPB->_float;
542 OPC->_float = OPA->_float + (float) OPB->_int;
545 OPC->_int = OPA->_int - OPB->_int;
548 OPC->_int = OPA->_int - (int) OPB->_float;
551 OPC->_float = OPA->_float - (float) OPB->_int;
554 OPC->_int = OPA->_int * OPB->_int;
557 OPC->_int = OPA->_int * (int) OPB->_float;
560 OPC->_float = OPA->_float * (float) OPB->_int;
563 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
564 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
565 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
569 float temp = 1.0f / OPB->_float;
570 OPC->vector[0] = temp * OPA->vector[0];
571 OPC->vector[1] = temp * OPA->vector[1];
572 OPC->vector[2] = temp * OPA->vector[2];
576 OPC->_int = OPA->_int / OPB->_int;
579 OPC->_int = OPA->_int / (int) OPB->_float;
582 OPC->_float = OPA->_float / (float) OPB->_int;
585 OPB->_float = OPA->_int;
588 OPB->_int = OPA->_float;
591 OPC->_int = OPA->_int & OPB->_int;
594 OPC->_int = OPA->_int | OPB->_int;
597 OPC->_int = OPA->_int & (int)OPB->_float;
600 OPC->_int = OPA->_int | (int)OPB->_float;
603 OPC->_float = (int)OPA->_float & OPB->_int;
606 OPC->_float = (int)OPA->_float | OPB->_int;
609 OPC->_float = OPA->_int >= OPB->_int;
612 OPC->_float = OPA->_int <= OPB->_int;
615 OPC->_float = OPA->_int > OPB->_int;
618 OPC->_float = OPA->_int < OPB->_int;
621 OPC->_float = OPA->_int && OPB->_int;
624 OPC->_float = OPA->_int || OPB->_int;
627 OPC->_float = (float)OPA->_int >= OPB->_float;
630 OPC->_float = (float)OPA->_int <= OPB->_float;
633 OPC->_float = (float)OPA->_int > OPB->_float;
636 OPC->_float = (float)OPA->_int < OPB->_float;
639 OPC->_float = (float)OPA->_int && OPB->_float;
642 OPC->_float = (float)OPA->_int || OPB->_float;
645 OPC->_float = OPA->_float >= (float)OPB->_int;
648 OPC->_float = OPA->_float <= (float)OPB->_int;
651 OPC->_float = OPA->_float > (float)OPB->_int;
654 OPC->_float = OPA->_float < (float)OPB->_int;
657 OPC->_float = OPA->_float && (float)OPB->_int;
660 OPC->_float = OPA->_float || (float)OPB->_int;
663 OPC->_float = !OPA->_int;
666 OPC->_float = OPA->_int == OPB->_int;
669 OPC->_float = (float)OPA->_int == OPB->_float;
672 OPC->_float = OPA->_float == (float)OPB->_int;
675 OPC->_float = OPA->_int != OPB->_int;
678 OPC->_float = (float)OPA->_int != OPB->_float;
681 OPC->_float = OPA->_float != (float)OPB->_int;
685 ptr->_int = OPA->_int;
689 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
691 prog->xfunction->profile += (st - startst);
692 prog->xstatement = st - prog->statements;
693 PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
696 if (OPB->_int < 0 || OPB->_int >= prog->progs->entityfields)
698 prog->xfunction->profile += (st - startst);
699 prog->xstatement = st - prog->statements;
700 PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
704 ed = PRVM_PROG_TO_EDICT(OPA->edict);
705 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
713 ptr = (prvm_eval_t *)(&OPA->_int + OPB->_int);
715 if (!PTR_ISVALID(ptr))
717 prog->xfunction->profile += (st - startst);
718 prog->xstatement = st - prog->statements;
719 PRVM_ERROR ("%s Progs attempted to read from an out of bounds address (%i)", PRVM_NAME, OPB->_int);
723 OPC->_int = ptr->_int;
727 ptr = (prvm_eval_t *)(&OPA->_int + OPB->_int);
729 if (!PTR_ISVALID(ptr))
731 prog->xfunction->profile += (st - startst);
732 prog->xstatement = st - prog->statements;
733 PRVM_ERROR ("%s Progs attempted to read from an out of bounds address (%i)", PRVM_NAME, OPB->_int);
737 OPC->vector[0] = ptr->vector[0];
738 OPC->vector[1] = ptr->vector[1];
739 OPC->vector[2] = ptr->vector[2];
742 if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
744 prog->xfunction->profile += (st - startst);
745 prog->xstatement = st - prog->statements;
746 PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
751 case OP_RAND0: // random number between 0 and 1
752 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0,1);
754 case OP_RAND1: // random number between 0 and OPA
755 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0,OPA->_float);
757 case OP_RAND2: // random number between OPA and OPB
758 if(OPA->_float < OPB->_float)
759 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(OPA->_float, OPB->_float);
761 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(OPB->_float, OPA->_float);
763 case OP_RANDV0: // random vector between 0 and 1
764 PRVM_G_VECTOR(OFS_RETURN)[0] = lhrandom(0,1);
765 PRVM_G_VECTOR(OFS_RETURN)[1] = lhrandom(0,1);
766 PRVM_G_VECTOR(OFS_RETURN)[2] = lhrandom(0,1);
768 case OP_RANDV1: // random vector between 0 and OPA
769 PRVM_G_VECTOR(OFS_RETURN)[0] = lhrandom(0,OPA->vector[0]);
770 PRVM_G_VECTOR(OFS_RETURN)[1] = lhrandom(0,OPA->vector[1]);
771 PRVM_G_VECTOR(OFS_RETURN)[2] = lhrandom(0,OPA->vector[2]);
773 case OP_RANDV2: // random vector between OPA and OPB
776 for(i = 0; i < 3; ++i)
778 if(OPA->vector[i] < OPB->vector[i])
779 PRVM_G_VECTOR(OFS_RETURN)[i] = lhrandom(OPA->vector[i], OPB->vector[i]);
781 PRVM_G_VECTOR(OFS_RETURN)[i] = lhrandom(OPB->vector[i], OPA->vector[i]);
796 prog->xfunction->profile += (st - startst);
798 st += st->b - 1; // offset the s++
806 if(swtch->_float == OPA->_float)
809 prog->xfunction->profile += (st - startst);
817 if(swtch->_int == OPA->_int)
820 prog->xfunction->profile += (st - startst);
826 if(swtch->_int == OPA->_int)
829 prog->xfunction->profile += (st - startst);
833 // switch(string) case "string" ->
834 // one of them may be null, not both
835 if((!swtch->_int && PRVM_GetString(OPA->string)) || (!OPA->_int && PRVM_GetString(swtch->string)))
837 if(!strcmp(PRVM_GetString(swtch->string), PRVM_GetString(OPA->string)))
840 prog->xfunction->profile += (st - startst);
846 if(swtch->vector[0] == OPA->vector[0] &&
847 swtch->vector[1] == OPA->vector[1] &&
848 swtch->vector[2] == OPA->vector[2])
851 prog->xfunction->profile += (st - startst);
857 PRVM_ERROR("OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
867 if(swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
874 PRVM_ERROR("OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
879 OPC->_float = (float)OPA->_int;
882 OPC->_int = (int)(OPA->_float);
886 OPC->_float = (float)(ptr->_int);
890 OPC->_int = (int)(ptr->_float);
895 OPC->_float = (ptr->_float += OPA->_float);
898 PTR_ptr3(OPB->_int, 0, 3);
899 OPC->vector[0] = (ptr->vector[0] += OPA->vector[0]);
900 OPC->vector[1] = (ptr->vector[1] += OPA->vector[1]);
901 OPC->vector[2] = (ptr->vector[2] += OPA->vector[2]);
906 OPC->_float = (ptr->_float -= OPA->_float);
909 PTR_ptr3(OPB->_int, 0, 3);
910 OPC->vector[0] = (ptr->vector[0] -= OPA->vector[0]);
911 OPC->vector[1] = (ptr->vector[1] -= OPA->vector[1]);
912 OPC->vector[2] = (ptr->vector[2] -= OPA->vector[2]);
917 OPC->_float = (ptr->_float *= OPA->_float);
921 PTR_ptr3(OPB->_int, 0, 3);
922 OPC->vector[0] = (ptr->vector[0] -= OPA->_float);
923 OPC->vector[1] = (ptr->vector[1] -= OPA->_float);
924 OPC->vector[2] = (ptr->vector[2] -= OPA->_float);
929 OPC->_float = (ptr->_float /= OPA->_float);
933 if(!OPA->string || !PRVM_GetString(OPA->string))
937 if(OPA->string && PRVM_GetString(OPA->string))
941 case OP_GLOBALADDRESS:
942 OPC->_int = ((&(OPA->_int) + OPB->_int) - (int*)prog->globals.generic);
944 if (OPC->_int < 0 || OPC->_int + 4 > GLOBALSIZE)
946 prog->xfunction->profile += (st - startst);
947 prog->xstatement = st - prog->statements;
948 PRVM_ERROR("%s attempted to address an invalid global (%i)", PRVM_NAME, OPC->_int);
952 OPC->_int = PTR_GBL(OPC->_int);
956 // NOTE: dp pointers are no pointers as in byte-offsets, but item-offsets
958 // I hope this is never used as an optimization for "A = B + C * 4" :P
959 OPC->_int = OPA->_int + OPB->_int*1;
962 case OP_ADD_SF: //(char*)c = (char*)a + (float)b
963 OPC->_int = OPA->_int + (int)OPB->_float;
965 case OP_SUB_S: //(float)c = (char*)a - (char*)b
966 OPC->_int = OPA->_int - OPB->_int;
975 PTR_ptr2(OPA->_int, OPB->_int);
976 OPC->_int = ptr->_int;
979 PTR_ptr3(OPA->_int, OPB->_int, 3);
980 OPC->vector[0] = ptr->vector[0];
981 OPC->vector[1] = ptr->vector[1];
982 OPC->vector[2] = ptr->vector[2];
985 // not wanted, keeping it in this comment for now though, because...
990 // ... because this could still be reconsidered, after all it only loads
992 PTR_ptr2(OPA->_int, (int)OPB->_float);
993 OPC->_int = ptr->_int;
998 OPC->_int = OPA->_int ^ OPB->_int;
1001 OPC->_int = OPA->_int >> OPB->_int;
1004 OPC->_int = OPA->_int << OPB->_int;
1007 // hexen2 opcodes.. afaik fteqcc shouldn't use those
1010 CStateOp(prog, OPA->_float, OPB->_float, newf);
1014 CWStateOp(prog, OPA->_float, OPB->_float, newf);
1018 ThinkTimeOp(prog, PRVM_PROG_TO_EDICT(OPA->edict), OPB->_float);
1022 prog->xfunction->profile += (st - startst);
1023 prog->xstatement = st - prog->statements;
1025 if(st->op < OP_NUMOPS)
1026 PRVM_ERROR("Instruction %i: %s\n", st->op, prvm_opnames[st->op]);
1027 PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);