bounds check function calls, and entity indexes in LOAD instructions
[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 = OPA->_float && OPB->_float;
86                                 break;
87                         case OP_OR:
88                                 OPC->_float = OPA->_float || OPB->_float;
89                                 break;
90                         case OP_NOT_F:
91                                 OPC->_float = !OPA->_float;
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 + 4 > prog->edictareasize)
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                                 ptr = (prvm_eval_t *)((unsigned char *)prog->edictsfields + OPB->_int);
165                                 ptr->_int = OPA->_int;
166                                 break;
167                         case OP_STOREP_V:
168 #if PRVMBOUNDSCHECK
169                                 if (OPB->_int < 0 || OPB->_int + 12 > prog->edictareasize)
170                                 {
171                                         prog->xfunction->profile += (st - startst);
172                                         prog->xstatement = st - prog->statements;
173                                         PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
174                                         goto cleanup;
175                                 }
176 #endif
177                                 ptr = (prvm_eval_t *)((unsigned char *)prog->edictsfields + OPB->_int);
178                                 ptr->ivector[0] = OPA->ivector[0];
179                                 ptr->ivector[1] = OPA->ivector[1];
180                                 ptr->ivector[2] = OPA->ivector[2];
181                                 break;
182
183                         case OP_ADDRESS:
184 #if PRVMBOUNDSCHECK
185                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
186                                 {
187                                         prog->xfunction->profile += (st - startst);
188                                         prog->xstatement = st - prog->statements;
189                                         PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
190                                         goto cleanup;
191                                 }
192 #endif
193                                 if (OPA->edict == 0 && !prog->allowworldwrites)
194                                 {
195                                         prog->xfunction->profile += (st - startst);
196                                         prog->xstatement = st - prog->statements;
197                                         PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
198                                         goto cleanup;
199                                 }
200                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
201                                 OPC->_int = (unsigned char *)((int *)ed->fields.vp + OPB->_int) - (unsigned char *)prog->edictsfields;
202                                 break;
203
204                         case OP_LOAD_F:
205                         case OP_LOAD_FLD:
206                         case OP_LOAD_ENT:
207                         case OP_LOAD_S:
208                         case OP_LOAD_FNC:
209 #if PRVMBOUNDSCHECK
210                                 if (OPA->edict < 0 || OPA->edict >= prog->edictareasize)
211                                 {
212                                         prog->xfunction->profile += (st - startst);
213                                         prog->xstatement = st - prog->statements;
214                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
215                                         goto cleanup;
216                                 }
217                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->progs->entityfields))
218                                 {
219                                         prog->xfunction->profile += (st - startst);
220                                         prog->xstatement = st - prog->statements;
221                                         PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
222                                         goto cleanup;
223                                 }
224 #endif
225                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
226                                 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->_int;
227                                 break;
228
229                         case OP_LOAD_V:
230 #if PRVMBOUNDSCHECK
231                                 if (OPA->edict < 0 || OPA->edict >= prog->edictareasize)
232                                 {
233                                         prog->xfunction->profile += (st - startst);
234                                         prog->xstatement = st - prog->statements;
235                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
236                                         goto cleanup;
237                                 }
238                                 if (OPB->_int < 0 || OPB->_int + 2 >= prog->progs->entityfields)
239                                 {
240                                         prog->xfunction->profile += (st - startst);
241                                         prog->xstatement = st - prog->statements;
242                                         PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
243                                         goto cleanup;
244                                 }
245 #endif
246                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
247                                 OPC->ivector[0] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[0];
248                                 OPC->ivector[1] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[1];
249                                 OPC->ivector[2] = ((prvm_eval_t *)((int *)ed->fields.vp + OPB->_int))->ivector[2];
250                                 break;
251
252                 //==================
253
254                         case OP_IFNOT:
255                                 if (!OPA->_float)
256                                 // TODO add an "int-ifnot"
257                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
258                                 // and entity, string, field values can never have that value
259                                 {
260                                         prog->xfunction->profile += (st - startst);
261                                         st += st->b - 1;        // offset the s++
262                                         startst = st;
263                                         // no bounds check needed, it is done when loading progs
264 #if PRVMRUNAWAYCHECK
265                                         if (++jumpcount == 10000000)
266                                         {
267                                                 prog->xstatement = st - prog->statements;
268                                                 PRVM_Profile(1<<30, 1000000);
269                                                 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
270                                         }
271 #endif
272                                 }
273                                 break;
274
275                         case OP_IF:
276                                 if (OPA->_float)
277                                 // TODO add an "int-if"
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 PRVMRUNAWAYCHECK
286                                         if (++jumpcount == 10000000)
287                                         {
288                                                 prog->xstatement = st - prog->statements;
289                                                 PRVM_Profile(1<<30, 1000000);
290                                                 PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
291                                         }
292 #endif
293                                 }
294                                 break;
295
296                         case OP_GOTO:
297                                 prog->xfunction->profile += (st - startst);
298                                 st += st->a - 1;        // offset the s++
299                                 startst = st;
300                                 // no bounds check needed, it is done when loading progs
301 #if PRVMRUNAWAYCHECK
302                                 if (++jumpcount == 10000000)
303                                 {
304                                         prog->xstatement = st - prog->statements;
305                                         PRVM_Profile(1<<30, 1000000);
306                                         PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
307                                 }
308 #endif
309                                 break;
310
311                         case OP_CALL0:
312                         case OP_CALL1:
313                         case OP_CALL2:
314                         case OP_CALL3:
315                         case OP_CALL4:
316                         case OP_CALL5:
317                         case OP_CALL6:
318                         case OP_CALL7:
319                         case OP_CALL8:
320                                 prog->xfunction->profile += (st - startst);
321                                 startst = st;
322                                 prog->xstatement = st - prog->statements;
323                                 prog->argc = st->op - OP_CALL0;
324                                 if (!OPA->function)
325                                         PRVM_ERROR("NULL function in %s", PRVM_NAME);
326
327 #if PRVMBOUNDSCHECK
328                                 if(!OPA->function || OPA->function >= (unsigned int)prog->progs->numfunctions)
329                                 {
330                                         prog->xfunction->profile += (st - startst);
331                                         prog->xstatement = st - prog->statements; // we better stay on the previously executed statement
332                                         PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
333                                         goto cleanup;
334                                 }
335 #endif
336
337                                 newf = &prog->functions[OPA->function];
338                                 newf->callcount++;
339
340                                 if (newf->first_statement < 0)
341                                 {
342                                         // negative statements are built in functions
343                                         int builtinnumber = -newf->first_statement;
344                                         prog->xfunction->builtinsprofile++;
345                                         if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
346                                                 prog->builtins[builtinnumber]();
347                                         else
348                                                 PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
349                                 }
350                                 else
351                                         st = prog->statements + PRVM_EnterFunction(newf);
352                                 startst = st;
353                                 break;
354
355                         case OP_DONE:
356                         case OP_RETURN:
357                                 prog->xfunction->profile += (st - startst);
358                                 prog->xstatement = st - prog->statements;
359
360                                 prog->globals.generic[OFS_RETURN] = prog->globals.generic[(unsigned short) st->a];
361                                 prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[(unsigned short) st->a+1];
362                                 prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[(unsigned short) st->a+2];
363
364                                 st = prog->statements + PRVM_LeaveFunction();
365                                 startst = st;
366                                 if (prog->depth <= exitdepth)
367                                         goto cleanup; // all done
368                                 if (prog->trace != cachedpr_trace)
369                                         goto chooseexecprogram;
370                                 break;
371
372                         case OP_STATE:
373                                 if(prog->flag & PRVM_OP_STATE)
374                                 {
375                                         ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
376                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.nextthink)->_float = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.time)->_float + 0.1;
377                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.frame)->_float = OPA->_float;
378                                         PRVM_EDICTFIELDVALUE(ed,prog->fieldoffsets.think)->function = OPB->function;
379                                 }
380                                 else
381                                 {
382                                         prog->xfunction->profile += (st - startst);
383                                         prog->xstatement = st - prog->statements;
384                                         PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
385                                 }
386                                 break;
387
388 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
389 /*
390                         case OP_ADD_I:
391                                 OPC->_int = OPA->_int + OPB->_int;
392                                 break;
393                         case OP_ADD_IF:
394                                 OPC->_int = OPA->_int + (int) OPB->_float;
395                                 break;
396                         case OP_ADD_FI:
397                                 OPC->_float = OPA->_float + (float) OPB->_int;
398                                 break;
399                         case OP_SUB_I:
400                                 OPC->_int = OPA->_int - OPB->_int;
401                                 break;
402                         case OP_SUB_IF:
403                                 OPC->_int = OPA->_int - (int) OPB->_float;
404                                 break;
405                         case OP_SUB_FI:
406                                 OPC->_float = OPA->_float - (float) OPB->_int;
407                                 break;
408                         case OP_MUL_I:
409                                 OPC->_int = OPA->_int * OPB->_int;
410                                 break;
411                         case OP_MUL_IF:
412                                 OPC->_int = OPA->_int * (int) OPB->_float;
413                                 break;
414                         case OP_MUL_FI:
415                                 OPC->_float = OPA->_float * (float) OPB->_int;
416                                 break;
417                         case OP_MUL_VI:
418                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
419                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
420                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
421                                 break;
422                         case OP_DIV_VF:
423                                 {
424                                         float temp = 1.0f / OPB->_float;
425                                         OPC->vector[0] = temp * OPA->vector[0];
426                                         OPC->vector[1] = temp * OPA->vector[1];
427                                         OPC->vector[2] = temp * OPA->vector[2];
428                                 }
429                                 break;
430                         case OP_DIV_I:
431                                 OPC->_int = OPA->_int / OPB->_int;
432                                 break;
433                         case OP_DIV_IF:
434                                 OPC->_int = OPA->_int / (int) OPB->_float;
435                                 break;
436                         case OP_DIV_FI:
437                                 OPC->_float = OPA->_float / (float) OPB->_int;
438                                 break;
439                         case OP_CONV_IF:
440                                 OPC->_float = OPA->_int;
441                                 break;
442                         case OP_CONV_FI:
443                                 OPC->_int = OPA->_float;
444                                 break;
445                         case OP_BITAND_I:
446                                 OPC->_int = OPA->_int & OPB->_int;
447                                 break;
448                         case OP_BITOR_I:
449                                 OPC->_int = OPA->_int | OPB->_int;
450                                 break;
451                         case OP_BITAND_IF:
452                                 OPC->_int = OPA->_int & (int)OPB->_float;
453                                 break;
454                         case OP_BITOR_IF:
455                                 OPC->_int = OPA->_int | (int)OPB->_float;
456                                 break;
457                         case OP_BITAND_FI:
458                                 OPC->_float = (int)OPA->_float & OPB->_int;
459                                 break;
460                         case OP_BITOR_FI:
461                                 OPC->_float = (int)OPA->_float | OPB->_int;
462                                 break;
463                         case OP_GE_I:
464                                 OPC->_float = OPA->_int >= OPB->_int;
465                                 break;
466                         case OP_LE_I:
467                                 OPC->_float = OPA->_int <= OPB->_int;
468                                 break;
469                         case OP_GT_I:
470                                 OPC->_float = OPA->_int > OPB->_int;
471                                 break;
472                         case OP_LT_I:
473                                 OPC->_float = OPA->_int < OPB->_int;
474                                 break;
475                         case OP_AND_I:
476                                 OPC->_float = OPA->_int && OPB->_int;
477                                 break;
478                         case OP_OR_I:
479                                 OPC->_float = OPA->_int || OPB->_int;
480                                 break;
481                         case OP_GE_IF:
482                                 OPC->_float = (float)OPA->_int >= OPB->_float;
483                                 break;
484                         case OP_LE_IF:
485                                 OPC->_float = (float)OPA->_int <= OPB->_float;
486                                 break;
487                         case OP_GT_IF:
488                                 OPC->_float = (float)OPA->_int > OPB->_float;
489                                 break;
490                         case OP_LT_IF:
491                                 OPC->_float = (float)OPA->_int < OPB->_float;
492                                 break;
493                         case OP_AND_IF:
494                                 OPC->_float = (float)OPA->_int && OPB->_float;
495                                 break;
496                         case OP_OR_IF:
497                                 OPC->_float = (float)OPA->_int || OPB->_float;
498                                 break;
499                         case OP_GE_FI:
500                                 OPC->_float = OPA->_float >= (float)OPB->_int;
501                                 break;
502                         case OP_LE_FI:
503                                 OPC->_float = OPA->_float <= (float)OPB->_int;
504                                 break;
505                         case OP_GT_FI:
506                                 OPC->_float = OPA->_float > (float)OPB->_int;
507                                 break;
508                         case OP_LT_FI:
509                                 OPC->_float = OPA->_float < (float)OPB->_int;
510                                 break;
511                         case OP_AND_FI:
512                                 OPC->_float = OPA->_float && (float)OPB->_int;
513                                 break;
514                         case OP_OR_FI:
515                                 OPC->_float = OPA->_float || (float)OPB->_int;
516                                 break;
517                         case OP_NOT_I:
518                                 OPC->_float = !OPA->_int;
519                                 break;
520                         case OP_EQ_I:
521                                 OPC->_float = OPA->_int == OPB->_int;
522                                 break;
523                         case OP_EQ_IF:
524                                 OPC->_float = (float)OPA->_int == OPB->_float;
525                                 break;
526                         case OP_EQ_FI:
527                                 OPC->_float = OPA->_float == (float)OPB->_int;
528                                 break;
529                         case OP_NE_I:
530                                 OPC->_float = OPA->_int != OPB->_int;
531                                 break;
532                         case OP_NE_IF:
533                                 OPC->_float = (float)OPA->_int != OPB->_float;
534                                 break;
535                         case OP_NE_FI:
536                                 OPC->_float = OPA->_float != (float)OPB->_int;
537                                 break;
538                         case OP_STORE_I:
539                                 OPB->_int = OPA->_int;
540                                 break;
541                         case OP_STOREP_I:
542 #if PRBOUNDSCHECK
543                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
544                                 {
545                                         prog->xfunction->profile += (st - startst);
546                                         prog->xstatement = st - prog->statements;
547                                         PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
548                                         goto cleanup;
549                                 }
550 #endif
551                                 ptr = (prvm_eval_t *)((unsigned char *)prog->edictsfields + OPB->_int);
552                                 ptr->_int = OPA->_int;
553                                 break;
554                         case OP_LOAD_I:
555 #if PRBOUNDSCHECK
556                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
557                                 {
558                                         prog->xfunction->profile += (st - startst);
559                                         prog->xstatement = st - prog->statements;
560                                         PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
561                                         goto cleanup;
562                                 }
563                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
564                                 {
565                                         prog->xfunction->profile += (st - startst);
566                                         prog->xstatement = st - prog->statements;
567                                         PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
568                                         goto cleanup;
569                                 }
570 #endif
571                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
572                                 OPC->_int = ((prvm_eval_t *)((int *)ed->v + OPB->_int))->_int;
573                                 break;
574
575                         case OP_GSTOREP_I:
576                         case OP_GSTOREP_F:
577                         case OP_GSTOREP_ENT:
578                         case OP_GSTOREP_FLD:            // integers
579                         case OP_GSTOREP_S:
580                         case OP_GSTOREP_FNC:            // pointers
581 #if PRBOUNDSCHECK
582                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
583                                 {
584                                         prog->xfunction->profile += (st - startst);
585                                         prog->xstatement = st - prog->statements;
586                                         PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
587                                         goto cleanup;
588                                 }
589 #endif
590                                 pr_iglobals[OPB->_int] = OPA->_int;
591                                 break;
592                         case OP_GSTOREP_V:
593 #if PRBOUNDSCHECK
594                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
595                                 {
596                                         prog->xfunction->profile += (st - startst);
597                                         prog->xstatement = st - prog->statements;
598                                         PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
599                                         goto cleanup;
600                                 }
601 #endif
602                                 pr_iglobals[OPB->_int  ] = OPA->ivector[0];
603                                 pr_iglobals[OPB->_int+1] = OPA->ivector[1];
604                                 pr_iglobals[OPB->_int+2] = OPA->ivector[2];
605                                 break;
606
607                         case OP_GADDRESS:
608                                 i = OPA->_int + (int) OPB->_float;
609 #if PRBOUNDSCHECK
610                                 if (i < 0 || i >= pr_globaldefs)
611                                 {
612                                         prog->xfunction->profile += (st - startst);
613                                         prog->xstatement = st - prog->statements;
614                                         PRVM_ERROR ("%s Progs attempted to address an out of bounds global", PRVM_NAME);
615                                         goto cleanup;
616                                 }
617 #endif
618                                 OPC->_int = pr_iglobals[i];
619                                 break;
620
621                         case OP_GLOAD_I:
622                         case OP_GLOAD_F:
623                         case OP_GLOAD_FLD:
624                         case OP_GLOAD_ENT:
625                         case OP_GLOAD_S:
626                         case OP_GLOAD_FNC:
627 #if PRBOUNDSCHECK
628                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
629                                 {
630                                         prog->xfunction->profile += (st - startst);
631                                         prog->xstatement = st - prog->statements;
632                                         PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
633                                         goto cleanup;
634                                 }
635 #endif
636                                 OPC->_int = pr_iglobals[OPA->_int];
637                                 break;
638
639                         case OP_GLOAD_V:
640 #if PRBOUNDSCHECK
641                                 if (OPA->_int < 0 || OPA->_int + 2 >= 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->ivector[0] = pr_iglobals[OPA->_int  ];
650                                 OPC->ivector[1] = pr_iglobals[OPA->_int+1];
651                                 OPC->ivector[2] = pr_iglobals[OPA->_int+2];
652                                 break;
653
654                         case OP_BOUNDCHECK:
655                                 if (OPA->_int < 0 || OPA->_int >= st->b)
656                                 {
657                                         prog->xfunction->profile += (st - startst);
658                                         prog->xstatement = st - prog->statements;
659                                         PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
660                                         goto cleanup;
661                                 }
662                                 break;
663
664 */
665
666                         default:
667                                 prog->xfunction->profile += (st - startst);
668                                 prog->xstatement = st - prog->statements;
669                                 PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);
670                                 goto cleanup;
671                         }
672                 }
673