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