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