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