]> icculus.org git repositories - divverent/darkplaces.git/blob - prvm_execprogram.h
reworked animcache code to store information in ent->animcache_vertex3f
[divverent/darkplaces.git] / prvm_execprogram.h
1
2 // This code isn't #ifdef/#define protectable, don't try.
3
4                 while (1)
5                 {
6                         st++;
7
8 #if PRVMTRACE
9                         PRVM_PrintStatement(st);
10 #endif
11 #if PRVMSTATEMENTPROFILING
12                         prog->statement_profile[st - prog->statements]++;
13 #endif
14
15                         switch (st->op)
16                         {
17                         case OP_ADD_F:
18                                 OPC->_float = OPA->_float + OPB->_float;
19                                 break;
20                         case OP_ADD_V:
21                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
22                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
23                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
24                                 break;
25                         case OP_SUB_F:
26                                 OPC->_float = OPA->_float - OPB->_float;
27                                 break;
28                         case OP_SUB_V:
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];
32                                 break;
33                         case OP_MUL_F:
34                                 OPC->_float = OPA->_float * OPB->_float;
35                                 break;
36                         case OP_MUL_V:
37                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
38                                 break;
39                         case OP_MUL_FV:
40                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
41                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
42                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
43                                 break;
44                         case OP_MUL_VF:
45                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
46                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
47                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
48                                 break;
49                         case OP_DIV_F:
50                                 if( OPB->_float != 0.0f )
51                                 {
52                                         OPC->_float = OPA->_float / OPB->_float;
53                                 }
54                                 else
55                                 {
56                                         if( developer.integer >= 1 )
57                                         {
58                                                 prog->xfunction->profile += (st - startst);
59                                                 startst = st;
60                                                 prog->xstatement = st - prog->statements;
61                                                 VM_Warning( "Attempted division by zero in %s\n", PRVM_NAME );
62                                         }
63                                         OPC->_float = 0.0f;
64                                 }
65                                 break;
66                         case OP_BITAND:
67                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
68                                 break;
69                         case OP_BITOR:
70                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
71                                 break;
72                         case OP_GE:
73                                 OPC->_float = OPA->_float >= OPB->_float;
74                                 break;
75                         case OP_LE:
76                                 OPC->_float = OPA->_float <= OPB->_float;
77                                 break;
78                         case OP_GT:
79                                 OPC->_float = OPA->_float > OPB->_float;
80                                 break;
81                         case OP_LT:
82                                 OPC->_float = OPA->_float < OPB->_float;
83                                 break;
84                         case OP_AND:
85                                 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
86                                 break;
87                         case OP_OR:
88                                 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
89                                 break;
90                         case OP_NOT_F:
91                                 OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
92                                 break;
93                         case OP_NOT_V:
94                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
95                                 break;
96                         case OP_NOT_S:
97                                 OPC->_float = !OPA->string || !*PRVM_GetString(OPA->string);
98                                 break;
99                         case OP_NOT_FNC:
100                                 OPC->_float = !OPA->function;
101                                 break;
102                         case OP_NOT_ENT:
103                                 OPC->_float = (OPA->edict == 0);
104                                 break;
105                         case OP_EQ_F:
106                                 OPC->_float = OPA->_float == OPB->_float;
107                                 break;
108                         case OP_EQ_V:
109                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
110                                 break;
111                         case OP_EQ_S:
112                                 OPC->_float = !strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
113                                 break;
114                         case OP_EQ_E:
115                                 OPC->_float = OPA->_int == OPB->_int;
116                                 break;
117                         case OP_EQ_FNC:
118                                 OPC->_float = OPA->function == OPB->function;
119                                 break;
120                         case OP_NE_F:
121                                 OPC->_float = OPA->_float != OPB->_float;
122                                 break;
123                         case OP_NE_V:
124                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
125                                 break;
126                         case OP_NE_S:
127                                 OPC->_float = strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
128                                 break;
129                         case OP_NE_E:
130                                 OPC->_float = OPA->_int != OPB->_int;
131                                 break;
132                         case OP_NE_FNC:
133                                 OPC->_float = OPA->function != OPB->function;
134                                 break;
135
136                 //==================
137                         case OP_STORE_F:
138                         case OP_STORE_ENT:
139                         case OP_STORE_FLD:              // integers
140                         case OP_STORE_S:
141                         case OP_STORE_FNC:              // pointers
142                                 OPB->_int = OPA->_int;
143                                 break;
144                         case OP_STORE_V:
145                                 OPB->ivector[0] = OPA->ivector[0];
146                                 OPB->ivector[1] = OPA->ivector[1];
147                                 OPB->ivector[2] = OPA->ivector[2];
148                                 break;
149
150                         case OP_STOREP_F:
151                         case OP_STOREP_ENT:
152                         case OP_STOREP_FLD:             // integers
153                         case OP_STOREP_S:
154                         case OP_STOREP_FNC:             // pointers
155 #if PRVMBOUNDSCHECK
156                                 if (OPB->_int < 0 || OPB->_int + 1 > prog->entityfieldsarea)
157                                 {
158                                         prog->xfunction->profile += (st - startst);
159                                         prog->xstatement = st - prog->statements;
160                                         PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
161                                         goto cleanup;
162                                 }
163 #endif
164                                 if (OPB->_int < prog->progs->entityfields && !prog->allowworldwrites)
165                                         Con_DPrintf("WARNING: assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
166                                 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
167                                 ptr->_int = OPA->_int;
168                                 break;
169                         case OP_STOREP_V:
170 #if PRVMBOUNDSCHECK
171                                 if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfieldsarea)
172                                 {
173                                         prog->xfunction->profile += (st - startst);
174                                         prog->xstatement = st - prog->statements;
175                                         PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
176                                         goto cleanup;
177                                 }
178 #endif
179                                 if (OPB->_int < prog->progs->entityfields && !prog->allowworldwrites)
180                                         Con_DPrintf("WARNING: assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
181                                 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
182                                 ptr->ivector[0] = OPA->ivector[0];
183                                 ptr->ivector[1] = OPA->ivector[1];
184                                 ptr->ivector[2] = OPA->ivector[2];
185                                 break;
186
187                         case OP_ADDRESS:
188 #if PRVMBOUNDSCHECK
189                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
190                                 {
191                                         prog->xfunction->profile += (st - startst);
192                                         prog->xstatement = st - prog->statements;
193                                         PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number", PRVM_NAME);
194                                         goto cleanup;
195                                 }
196                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
197                                 {
198                                         prog->xfunction->profile += (st - startst);
199                                         prog->xstatement = st - prog->statements;
200                                         PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
201                                         goto cleanup;
202                                 }
203 #endif
204 #if 0
205                                 if (OPA->edict == 0 && !prog->allowworldwrites)
206                                 {
207                                         prog->xfunction->profile += (st - startst);
208                                         prog->xstatement = st - prog->statements;
209                                         PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
210                                         goto cleanup;
211                                 }
212 #endif
213                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
214                                 OPC->_int = ed->fields.vp - prog->edictsfields + OPB->_int;
215                                 break;
216
217                         case OP_LOAD_F:
218                         case OP_LOAD_FLD:
219                         case OP_LOAD_ENT:
220                         case OP_LOAD_S:
221                         case OP_LOAD_FNC:
222 #if PRVMBOUNDSCHECK
223                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
224                                 {
225                                         prog->xfunction->profile += (st - startst);
226                                         prog->xstatement = st - prog->statements;
227                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
228                                         goto cleanup;
229                                 }
230                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
231                                 {
232                                         prog->xfunction->profile += (st - startst);
233                                         prog->xstatement = st - prog->statements;
234                                         PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
235                                         goto cleanup;
236                                 }
237 #endif
238                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
239                                 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
240                                 break;
241
242                         case OP_LOAD_V:
243 #if PRVMBOUNDSCHECK
244                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
245                                 {
246                                         prog->xfunction->profile += (st - startst);
247                                         prog->xstatement = st - prog->statements;
248                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
249                                         goto cleanup;
250                                 }
251                                 if (OPB->_int < 0 || OPB->_int + 2 >= prog->progs->entityfields)
252                                 {
253                                         prog->xfunction->profile += (st - startst);
254                                         prog->xstatement = st - prog->statements;
255                                         PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
256                                         goto cleanup;
257                                 }
258 #endif
259                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
260                                 OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
261                                 OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
262                                 OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
263                                 break;
264
265                 //==================
266
267                         case OP_IFNOT:
268                                 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
269                                 // TODO add an "int-if", and change this one to OPA->_float
270                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
271                                 // and entity, string, field values can never have that value
272                                 {
273                                         prog->xfunction->profile += (st - startst);
274                                         st += st->b - 1;        // offset the s++
275                                         startst = st;
276                                         // no bounds check needed, it is done when loading progs
277 #if PRVMRUNAWAYCHECK
278                                         if (++jumpcount == 10000000)
279                                         {
280                                                 prog->xstatement = st - prog->statements;
281                                                 PRVM_Profile(1<<30, 1000000, 0);
282                                                 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
283                                         }
284 #endif
285                                 }
286                                 break;
287
288                         case OP_IF:
289                                 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
290                                 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
291                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
292                                 // and entity, string, field values can never have that value
293                                 {
294                                         prog->xfunction->profile += (st - startst);
295                                         st += st->b - 1;        // offset the s++
296                                         startst = st;
297                                         // no bounds check needed, it is done when loading progs
298 #if PRVMRUNAWAYCHECK
299                                         if (++jumpcount == 10000000)
300                                         {
301                                                 prog->xstatement = st - prog->statements;
302                                                 PRVM_Profile(1<<30, 1000000, 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);
304                                         }
305 #endif
306                                 }
307                                 break;
308
309                         case OP_GOTO:
310                                 prog->xfunction->profile += (st - startst);
311                                 st += st->a - 1;        // offset the s++
312                                 startst = st;
313                                 // no bounds check needed, it is done when loading progs
314 #if PRVMRUNAWAYCHECK
315                                 if (++jumpcount == 10000000)
316                                 {
317                                         prog->xstatement = st - prog->statements;
318                                         PRVM_Profile(1<<30, 1000000, 0);
319                                         PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
320                                 }
321 #endif
322                                 break;
323
324                         case OP_CALL0:
325                         case OP_CALL1:
326                         case OP_CALL2:
327                         case OP_CALL3:
328                         case OP_CALL4:
329                         case OP_CALL5:
330                         case OP_CALL6:
331                         case OP_CALL7:
332                         case OP_CALL8:
333                                 prog->xfunction->profile += (st - startst);
334                                 startst = st;
335                                 prog->xstatement = st - prog->statements;
336                                 prog->argc = st->op - OP_CALL0;
337                                 if (!OPA->function)
338                                         PRVM_ERROR("NULL function in %s", PRVM_NAME);
339
340 #if PRVMBOUNDSCHECK
341                                 if(!OPA->function || OPA->function >= (unsigned int)prog->progs->numfunctions)
342                                 {
343                                         prog->xfunction->profile += (st - startst);
344                                         prog->xstatement = st - prog->statements; // we better stay on the previously executed statement
345                                         PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
346                                         goto cleanup;
347                                 }
348 #endif
349
350                                 newf = &prog->functions[OPA->function];
351                                 newf->callcount++;
352
353                                 if (newf->first_statement < 0)
354                                 {
355                                         // negative statements are built in functions
356                                         int builtinnumber = -newf->first_statement;
357                                         prog->xfunction->builtinsprofile++;
358                                         if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
359                                                 prog->builtins[builtinnumber]();
360                                         else
361                                                 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
362                                 }
363                                 else
364                                         st = prog->statements + PRVM_EnterFunction(newf);
365                                 startst = st;
366                                 break;
367
368                         case OP_DONE:
369                         case OP_RETURN:
370                                 prog->xfunction->profile += (st - startst);
371                                 prog->xstatement = st - prog->statements;
372
373                                 prog->globals.generic[OFS_RETURN] = prog->globals.generic[(unsigned short) st->a];
374                                 prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[(unsigned short) st->a+1];
375                                 prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[(unsigned short) st->a+2];
376
377                                 st = prog->statements + PRVM_LeaveFunction();
378                                 startst = st;
379                                 if (prog->depth <= exitdepth)
380                                         goto cleanup; // all done
381                                 if (prog->trace != cachedpr_trace)
382                                         goto chooseexecprogram;
383                                 break;
384
385                         case OP_STATE:
386                                 if(prog->flag & PRVM_OP_STATE)
387                                 {
388                                         ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
389                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.nextthink)->_float = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.time)->_float + 0.1;
390                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.frame)->_float = OPA->_float;
391                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.think)->function = OPB->function;
392                                 }
393                                 else
394                                 {
395                                         prog->xfunction->profile += (st - startst);
396                                         prog->xstatement = st - prog->statements;
397                                         PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
398                                 }
399                                 break;
400
401 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
402 /*
403                         case OP_ADD_I:
404                                 OPC->_int = OPA->_int + OPB->_int;
405                                 break;
406                         case OP_ADD_IF:
407                                 OPC->_int = OPA->_int + (int) OPB->_float;
408                                 break;
409                         case OP_ADD_FI:
410                                 OPC->_float = OPA->_float + (float) OPB->_int;
411                                 break;
412                         case OP_SUB_I:
413                                 OPC->_int = OPA->_int - OPB->_int;
414                                 break;
415                         case OP_SUB_IF:
416                                 OPC->_int = OPA->_int - (int) OPB->_float;
417                                 break;
418                         case OP_SUB_FI:
419                                 OPC->_float = OPA->_float - (float) OPB->_int;
420                                 break;
421                         case OP_MUL_I:
422                                 OPC->_int = OPA->_int * OPB->_int;
423                                 break;
424                         case OP_MUL_IF:
425                                 OPC->_int = OPA->_int * (int) OPB->_float;
426                                 break;
427                         case OP_MUL_FI:
428                                 OPC->_float = OPA->_float * (float) OPB->_int;
429                                 break;
430                         case OP_MUL_VI:
431                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
432                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
433                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
434                                 break;
435                         case OP_DIV_VF:
436                                 {
437                                         float temp = 1.0f / OPB->_float;
438                                         OPC->vector[0] = temp * OPA->vector[0];
439                                         OPC->vector[1] = temp * OPA->vector[1];
440                                         OPC->vector[2] = temp * OPA->vector[2];
441                                 }
442                                 break;
443                         case OP_DIV_I:
444                                 OPC->_int = OPA->_int / OPB->_int;
445                                 break;
446                         case OP_DIV_IF:
447                                 OPC->_int = OPA->_int / (int) OPB->_float;
448                                 break;
449                         case OP_DIV_FI:
450                                 OPC->_float = OPA->_float / (float) OPB->_int;
451                                 break;
452                         case OP_CONV_IF:
453                                 OPC->_float = OPA->_int;
454                                 break;
455                         case OP_CONV_FI:
456                                 OPC->_int = OPA->_float;
457                                 break;
458                         case OP_BITAND_I:
459                                 OPC->_int = OPA->_int & OPB->_int;
460                                 break;
461                         case OP_BITOR_I:
462                                 OPC->_int = OPA->_int | OPB->_int;
463                                 break;
464                         case OP_BITAND_IF:
465                                 OPC->_int = OPA->_int & (int)OPB->_float;
466                                 break;
467                         case OP_BITOR_IF:
468                                 OPC->_int = OPA->_int | (int)OPB->_float;
469                                 break;
470                         case OP_BITAND_FI:
471                                 OPC->_float = (int)OPA->_float & OPB->_int;
472                                 break;
473                         case OP_BITOR_FI:
474                                 OPC->_float = (int)OPA->_float | OPB->_int;
475                                 break;
476                         case OP_GE_I:
477                                 OPC->_float = OPA->_int >= OPB->_int;
478                                 break;
479                         case OP_LE_I:
480                                 OPC->_float = OPA->_int <= OPB->_int;
481                                 break;
482                         case OP_GT_I:
483                                 OPC->_float = OPA->_int > OPB->_int;
484                                 break;
485                         case OP_LT_I:
486                                 OPC->_float = OPA->_int < OPB->_int;
487                                 break;
488                         case OP_AND_I:
489                                 OPC->_float = OPA->_int && OPB->_int;
490                                 break;
491                         case OP_OR_I:
492                                 OPC->_float = OPA->_int || OPB->_int;
493                                 break;
494                         case OP_GE_IF:
495                                 OPC->_float = (float)OPA->_int >= OPB->_float;
496                                 break;
497                         case OP_LE_IF:
498                                 OPC->_float = (float)OPA->_int <= OPB->_float;
499                                 break;
500                         case OP_GT_IF:
501                                 OPC->_float = (float)OPA->_int > OPB->_float;
502                                 break;
503                         case OP_LT_IF:
504                                 OPC->_float = (float)OPA->_int < OPB->_float;
505                                 break;
506                         case OP_AND_IF:
507                                 OPC->_float = (float)OPA->_int && OPB->_float;
508                                 break;
509                         case OP_OR_IF:
510                                 OPC->_float = (float)OPA->_int || OPB->_float;
511                                 break;
512                         case OP_GE_FI:
513                                 OPC->_float = OPA->_float >= (float)OPB->_int;
514                                 break;
515                         case OP_LE_FI:
516                                 OPC->_float = OPA->_float <= (float)OPB->_int;
517                                 break;
518                         case OP_GT_FI:
519                                 OPC->_float = OPA->_float > (float)OPB->_int;
520                                 break;
521                         case OP_LT_FI:
522                                 OPC->_float = OPA->_float < (float)OPB->_int;
523                                 break;
524                         case OP_AND_FI:
525                                 OPC->_float = OPA->_float && (float)OPB->_int;
526                                 break;
527                         case OP_OR_FI:
528                                 OPC->_float = OPA->_float || (float)OPB->_int;
529                                 break;
530                         case OP_NOT_I:
531                                 OPC->_float = !OPA->_int;
532                                 break;
533                         case OP_EQ_I:
534                                 OPC->_float = OPA->_int == OPB->_int;
535                                 break;
536                         case OP_EQ_IF:
537                                 OPC->_float = (float)OPA->_int == OPB->_float;
538                                 break;
539                         case OP_EQ_FI:
540                                 OPC->_float = OPA->_float == (float)OPB->_int;
541                                 break;
542                         case OP_NE_I:
543                                 OPC->_float = OPA->_int != OPB->_int;
544                                 break;
545                         case OP_NE_IF:
546                                 OPC->_float = (float)OPA->_int != OPB->_float;
547                                 break;
548                         case OP_NE_FI:
549                                 OPC->_float = OPA->_float != (float)OPB->_int;
550                                 break;
551                         case OP_STORE_I:
552                                 OPB->_int = OPA->_int;
553                                 break;
554                         case OP_STOREP_I:
555 #if PRBOUNDSCHECK
556                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
557                                 {
558                                         prog->xfunction->profile += (st - startst);
559                                         prog->xstatement = st - prog->statements;
560                                         PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
561                                         goto cleanup;
562                                 }
563 #endif
564                                 ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
565                                 ptr->_int = OPA->_int;
566                                 break;
567                         case OP_LOAD_I:
568 #if PRBOUNDSCHECK
569                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
570                                 {
571                                         prog->xfunction->profile += (st - startst);
572                                         prog->xstatement = st - prog->statements;
573                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
574                                         goto cleanup;
575                                 }
576                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
577                                 {
578                                         prog->xfunction->profile += (st - startst);
579                                         prog->xstatement = st - prog->statements;
580                                         PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
581                                         goto cleanup;
582                                 }
583 #endif
584                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
585                                 OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int;
586                                 break;
587
588                         case OP_GSTOREP_I:
589                         case OP_GSTOREP_F:
590                         case OP_GSTOREP_ENT:
591                         case OP_GSTOREP_FLD:            // integers
592                         case OP_GSTOREP_S:
593                         case OP_GSTOREP_FNC:            // pointers
594 #if PRBOUNDSCHECK
595                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
596                                 {
597                                         prog->xfunction->profile += (st - startst);
598                                         prog->xstatement = st - prog->statements;
599                                         PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
600                                         goto cleanup;
601                                 }
602 #endif
603                                 pr_iglobals[OPB->_int] = OPA->_int;
604                                 break;
605                         case OP_GSTOREP_V:
606 #if PRBOUNDSCHECK
607                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
608                                 {
609                                         prog->xfunction->profile += (st - startst);
610                                         prog->xstatement = st - prog->statements;
611                                         PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
612                                         goto cleanup;
613                                 }
614 #endif
615                                 pr_iglobals[OPB->_int  ] = OPA->ivector[0];
616                                 pr_iglobals[OPB->_int+1] = OPA->ivector[1];
617                                 pr_iglobals[OPB->_int+2] = OPA->ivector[2];
618                                 break;
619
620                         case OP_GADDRESS:
621                                 i = OPA->_int + (int) OPB->_float;
622 #if PRBOUNDSCHECK
623                                 if (i < 0 || i >= pr_globaldefs)
624                                 {
625                                         prog->xfunction->profile += (st - startst);
626                                         prog->xstatement = st - prog->statements;
627                                         PRVM_ERROR ("%s Progs attempted to address an out of bounds global", PRVM_NAME);
628                                         goto cleanup;
629                                 }
630 #endif
631                                 OPC->_int = pr_iglobals[i];
632                                 break;
633
634                         case OP_GLOAD_I:
635                         case OP_GLOAD_F:
636                         case OP_GLOAD_FLD:
637                         case OP_GLOAD_ENT:
638                         case OP_GLOAD_S:
639                         case OP_GLOAD_FNC:
640 #if PRBOUNDSCHECK
641                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
642                                 {
643                                         prog->xfunction->profile += (st - startst);
644                                         prog->xstatement = st - prog->statements;
645                                         PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
646                                         goto cleanup;
647                                 }
648 #endif
649                                 OPC->_int = pr_iglobals[OPA->_int];
650                                 break;
651
652                         case OP_GLOAD_V:
653 #if PRBOUNDSCHECK
654                                 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
655                                 {
656                                         prog->xfunction->profile += (st - startst);
657                                         prog->xstatement = st - prog->statements;
658                                         PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
659                                         goto cleanup;
660                                 }
661 #endif
662                                 OPC->ivector[0] = pr_iglobals[OPA->_int  ];
663                                 OPC->ivector[1] = pr_iglobals[OPA->_int+1];
664                                 OPC->ivector[2] = pr_iglobals[OPA->_int+2];
665                                 break;
666
667                         case OP_BOUNDCHECK:
668                                 if (OPA->_int < 0 || OPA->_int >= st->b)
669                                 {
670                                         prog->xfunction->profile += (st - startst);
671                                         prog->xstatement = st - prog->statements;
672                                         PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
673                                         goto cleanup;
674                                 }
675                                 break;
676
677 */
678
679                         default:
680                                 prog->xfunction->profile += (st - startst);
681                                 prog->xstatement = st - prog->statements;
682                                 PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);
683                                 goto cleanup;
684                         }
685                 }
686