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