]> git.xonotic.org Git - xonotic/darkplaces.git/blob - prvm_execprogram.h
sys_win: Delete sys_win and conproc. We no longer use these.
[xonotic/darkplaces.git] / prvm_execprogram.h
1 extern cvar_t prvm_garbagecollection_enable;
2 int i;
3 // NEED to reset startst after calling this! startst may or may not be clobbered!
4 #define ADVANCE_PROFILE_BEFORE_JUMP() \
5         prog->xfunction->profile += (st - startst); \
6         if (prvm_statementprofiling.integer || (prvm_coverage.integer & 4)) { \
7                 /* All statements from startst+1 to st have been hit. */ \
8                 while (++startst <= st) { \
9                         if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
10                                 PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
11                 } \
12                 /* Observe: startst now is clobbered (now at st+1)! */ \
13         }
14
15 #ifdef PRVMTIMEPROFILING
16 #define PRE_ERROR() \
17         ADVANCE_PROFILE_BEFORE_JUMP(); \
18         prog->xstatement = st - cached_statements; \
19         tm = Sys_DirtyTime(); \
20         prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
21         startst = st; \
22         starttm = tm
23 #else
24 #define PRE_ERROR() \
25         ADVANCE_PROFILE_BEFORE_JUMP(); \
26         prog->xstatement = st - cached_statements; \
27         startst = st
28 #endif
29
30 // This code isn't #ifdef/#define protectable, don't try.
31
32 #if HAVE_COMPUTED_GOTOS && !(PRVMSLOWINTERPRETER || PRVMTIMEPROFILING)
33   // NOTE: Due to otherwise duplicate labels, only ONE interpreter path may
34   // ever hit this!
35 # define USE_COMPUTED_GOTOS 1
36 #endif
37
38 #if USE_COMPUTED_GOTOS
39   // Must exactly match opcode_e enum in pr_comp.h
40     const static void *dispatchtable[] = {
41         &&handle_OP_DONE,
42         &&handle_OP_MUL_F,
43         &&handle_OP_MUL_V,
44         &&handle_OP_MUL_FV,
45         &&handle_OP_MUL_VF,
46         &&handle_OP_DIV_F,
47         &&handle_OP_ADD_F,
48         &&handle_OP_ADD_V,
49         &&handle_OP_SUB_F,
50         &&handle_OP_SUB_V,
51
52         &&handle_OP_EQ_F,
53         &&handle_OP_EQ_V,
54         &&handle_OP_EQ_S,
55         &&handle_OP_EQ_E,
56         &&handle_OP_EQ_FNC,
57
58         &&handle_OP_NE_F,
59         &&handle_OP_NE_V,
60         &&handle_OP_NE_S,
61         &&handle_OP_NE_E,
62         &&handle_OP_NE_FNC,
63
64         &&handle_OP_LE,
65         &&handle_OP_GE,
66         &&handle_OP_LT,
67         &&handle_OP_GT,
68
69         &&handle_OP_LOAD_F,
70         &&handle_OP_LOAD_V,
71         &&handle_OP_LOAD_S,
72         &&handle_OP_LOAD_ENT,
73         &&handle_OP_LOAD_FLD,
74         &&handle_OP_LOAD_FNC,
75
76         &&handle_OP_ADDRESS,
77
78         &&handle_OP_STORE_F,
79         &&handle_OP_STORE_V,
80         &&handle_OP_STORE_S,
81         &&handle_OP_STORE_ENT,
82         &&handle_OP_STORE_FLD,
83         &&handle_OP_STORE_FNC,
84
85         &&handle_OP_STOREP_F,
86         &&handle_OP_STOREP_V,
87         &&handle_OP_STOREP_S,
88         &&handle_OP_STOREP_ENT,
89         &&handle_OP_STOREP_FLD,
90         &&handle_OP_STOREP_FNC,
91
92         &&handle_OP_RETURN,
93         &&handle_OP_NOT_F,
94         &&handle_OP_NOT_V,
95         &&handle_OP_NOT_S,
96         &&handle_OP_NOT_ENT,
97         &&handle_OP_NOT_FNC,
98         &&handle_OP_IF,
99         &&handle_OP_IFNOT,
100         &&handle_OP_CALL0,
101         &&handle_OP_CALL1,
102         &&handle_OP_CALL2,
103         &&handle_OP_CALL3,
104         &&handle_OP_CALL4,
105         &&handle_OP_CALL5,
106         &&handle_OP_CALL6,
107         &&handle_OP_CALL7,
108         &&handle_OP_CALL8,
109         &&handle_OP_STATE,
110         &&handle_OP_GOTO,
111         &&handle_OP_AND,
112         &&handle_OP_OR,
113
114         &&handle_OP_BITAND,
115         &&handle_OP_BITOR,
116
117         NULL,
118         NULL,
119         NULL,
120         NULL,
121         NULL,
122         NULL,
123         NULL,
124         NULL,
125         NULL,
126         NULL,
127         NULL,
128         NULL,
129         NULL,
130         NULL,
131         NULL,
132         NULL,
133         NULL,
134         NULL,
135         NULL,
136         NULL,
137         NULL,
138         NULL,
139         NULL,
140         NULL,
141         NULL,
142         NULL,
143         NULL,
144         NULL,
145         NULL,
146         NULL,
147         NULL,
148         NULL,
149         NULL,
150         NULL,
151         NULL,
152         NULL,
153         NULL,
154         NULL,
155         NULL,
156         NULL,
157         NULL,
158         NULL,
159         NULL,
160         NULL,
161         NULL,
162         NULL,
163         NULL,
164
165         &&handle_OP_STORE_I,
166
167         NULL,
168         NULL,
169
170         &&handle_OP_ADD_I,
171         &&handle_OP_ADD_FI,
172         &&handle_OP_ADD_IF,
173
174         &&handle_OP_SUB_I,
175         &&handle_OP_SUB_FI,
176         &&handle_OP_SUB_IF,
177         &&handle_OP_CONV_IF,
178         &&handle_OP_CONV_FI,
179
180         NULL,
181         NULL,
182
183         &&handle_OP_LOAD_I,
184         &&handle_OP_STOREP_I,
185
186         NULL,
187         NULL,
188
189         &&handle_OP_BITAND_I,
190         &&handle_OP_BITOR_I,
191
192         &&handle_OP_MUL_I,
193         &&handle_OP_DIV_I,
194         &&handle_OP_EQ_I,
195         &&handle_OP_NE_I,
196
197         NULL,
198         NULL,
199
200         &&handle_OP_NOT_I,
201
202         &&handle_OP_DIV_VF,
203
204         NULL,
205         NULL,
206         NULL,
207         NULL,
208         NULL,
209         NULL,
210         NULL,
211         NULL,
212         NULL,
213         NULL,
214         NULL,
215         NULL,
216
217         &&handle_OP_STORE_P,
218
219         NULL,
220         NULL,
221         NULL,
222         NULL,
223         NULL,
224         NULL,
225         NULL,
226         NULL,
227
228         &&handle_OP_LE_I,
229         &&handle_OP_GE_I,
230         &&handle_OP_LT_I,
231         &&handle_OP_GT_I,
232         
233         &&handle_OP_LE_IF,
234         &&handle_OP_GE_IF,
235         &&handle_OP_LT_IF,
236         &&handle_OP_GT_IF,
237
238         &&handle_OP_LE_FI,
239         &&handle_OP_GE_FI,
240         &&handle_OP_LT_FI,
241         &&handle_OP_GT_FI,
242
243         &&handle_OP_EQ_IF,
244         &&handle_OP_EQ_FI,
245
246         NULL,
247         NULL,
248         NULL,
249         NULL,
250
251         &&handle_OP_MUL_IF,
252         &&handle_OP_MUL_FI,
253         &&handle_OP_MUL_VI,
254
255         NULL,
256
257         &&handle_OP_DIV_IF,
258         &&handle_OP_DIV_FI,
259         &&handle_OP_BITAND_IF,
260         &&handle_OP_BITOR_IF,
261         &&handle_OP_BITAND_FI,
262         &&handle_OP_BITOR_FI,
263         &&handle_OP_AND_I,
264         &&handle_OP_OR_I,
265         &&handle_OP_AND_IF,
266         &&handle_OP_OR_IF,
267         &&handle_OP_AND_FI,
268         &&handle_OP_OR_FI,
269         &&handle_OP_NE_IF,
270         &&handle_OP_NE_FI,
271
272         &&handle_OP_GSTOREP_I,
273         &&handle_OP_GSTOREP_F,
274         &&handle_OP_GSTOREP_ENT,
275         &&handle_OP_GSTOREP_FLD,
276         &&handle_OP_GSTOREP_S,
277         &&handle_OP_GSTOREP_FNC,                
278         &&handle_OP_GSTOREP_V,
279         &&handle_OP_GADDRESS,
280         &&handle_OP_GLOAD_I,
281         &&handle_OP_GLOAD_F,
282         &&handle_OP_GLOAD_FLD,
283         &&handle_OP_GLOAD_ENT,
284         &&handle_OP_GLOAD_S,
285         &&handle_OP_GLOAD_FNC,
286         &&handle_OP_BOUNDCHECK,
287         NULL,
288         NULL,
289         NULL,
290         NULL,
291         &&handle_OP_GLOAD_V
292             };
293 #define DISPATCH_OPCODE() \
294     goto *dispatchtable[(++st)->op]
295 #define HANDLE_OPCODE(opcode) handle_##opcode
296
297     DISPATCH_OPCODE(); // jump to first opcode
298 #else // USE_COMPUTED_GOTOS
299 #define DISPATCH_OPCODE() break
300 #define HANDLE_OPCODE(opcode) case opcode
301
302 #if PRVMSLOWINTERPRETER
303                 {
304                         if (prog->watch_global_type != ev_void)
305                         {
306                                 prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global);
307                                 prog->xstatement = st + 1 - cached_statements;
308                                 PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, g);
309                         }
310                         if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
311                         {
312                                 prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
313                                 prog->xstatement = st + 1 - cached_statements;
314                                 PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, g);
315                         }
316                 }
317 #endif
318
319                 while (1)
320                 {
321                         st++;
322 #endif // USE_COMPUTED_GOTOS
323
324 #if !USE_COMPUTED_GOTOS
325
326 #if PRVMSLOWINTERPRETER
327                         if (prog->trace)
328                                 PRVM_PrintStatement(prog, st);
329                         if (prog->break_statement >= 0)
330                                 if ((st - cached_statements) == prog->break_statement)
331                                 {
332                                         prog->xstatement = st - cached_statements;
333                                         PRVM_Breakpoint(prog, prog->break_stack_index, "Breakpoint hit");
334                                 }
335 #endif
336                         switch (st->op)
337                         {
338 #endif
339                         HANDLE_OPCODE(OP_ADD_F):
340                                 OPC->_float = OPA->_float + OPB->_float;
341                                 DISPATCH_OPCODE();
342                         HANDLE_OPCODE(OP_ADD_V):
343                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
344                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
345                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
346                                 DISPATCH_OPCODE();
347                         HANDLE_OPCODE(OP_SUB_F):
348                                 OPC->_float = OPA->_float - OPB->_float;
349                                 DISPATCH_OPCODE();
350                         HANDLE_OPCODE(OP_SUB_V):
351                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
352                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
353                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
354                                 DISPATCH_OPCODE();
355                         HANDLE_OPCODE(OP_MUL_F):
356                                 OPC->_float = OPA->_float * OPB->_float;
357                                 DISPATCH_OPCODE();
358                         HANDLE_OPCODE(OP_MUL_V):
359                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
360                                 DISPATCH_OPCODE();
361                         HANDLE_OPCODE(OP_MUL_FV):
362                                 tempfloat = OPA->_float;
363                                 OPC->vector[0] = tempfloat * OPB->vector[0];
364                                 OPC->vector[1] = tempfloat * OPB->vector[1];
365                                 OPC->vector[2] = tempfloat * OPB->vector[2];
366                                 DISPATCH_OPCODE();
367                         HANDLE_OPCODE(OP_MUL_VF):
368                                 tempfloat = OPB->_float;
369                                 OPC->vector[0] = tempfloat * OPA->vector[0];
370                                 OPC->vector[1] = tempfloat * OPA->vector[1];
371                                 OPC->vector[2] = tempfloat * OPA->vector[2];
372                                 DISPATCH_OPCODE();
373                         HANDLE_OPCODE(OP_DIV_F):
374                                 if( OPB->_float != 0.0f )
375                                 {
376                                         OPC->_float = OPA->_float / OPB->_float;
377                                 }
378                                 else
379                                 {
380                                         if (developer.integer)
381                                         {
382                                                 PRE_ERROR();
383                                                 VM_Warning(prog, "Attempted division by zero in %s\n", prog->name );
384                                         }
385                                         OPC->_float = 0.0f;
386                                 }
387                                 DISPATCH_OPCODE();
388                         HANDLE_OPCODE(OP_BITAND):
389                                 OPC->_float = (prvm_int_t)OPA->_float & (prvm_int_t)OPB->_float;
390                                 DISPATCH_OPCODE();
391                         HANDLE_OPCODE(OP_BITOR):
392                                 OPC->_float = (prvm_int_t)OPA->_float | (prvm_int_t)OPB->_float;
393                                 DISPATCH_OPCODE();
394                         HANDLE_OPCODE(OP_GE):
395                                 OPC->_float = OPA->_float >= OPB->_float;
396                                 DISPATCH_OPCODE();
397                         HANDLE_OPCODE(OP_LE):
398                                 OPC->_float = OPA->_float <= OPB->_float;
399                                 DISPATCH_OPCODE();
400                         HANDLE_OPCODE(OP_GT):
401                                 OPC->_float = OPA->_float > OPB->_float;
402                                 DISPATCH_OPCODE();
403                         HANDLE_OPCODE(OP_LT):
404                                 OPC->_float = OPA->_float < OPB->_float;
405                                 DISPATCH_OPCODE();
406                         HANDLE_OPCODE(OP_AND):
407                                 OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) && FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add AND_I to be used by fteqcc for anything not a float
408                                 DISPATCH_OPCODE();
409                         HANDLE_OPCODE(OP_OR):
410                                 OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) || FLOAT_IS_TRUE_FOR_INT(OPB->_int); // TODO change this back to float, and add OR_I to be used by fteqcc for anything not a float
411                                 DISPATCH_OPCODE();
412                         HANDLE_OPCODE(OP_NOT_F):
413                                 OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
414                                 DISPATCH_OPCODE();
415                         HANDLE_OPCODE(OP_NOT_V):
416                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
417                                 DISPATCH_OPCODE();
418                         HANDLE_OPCODE(OP_NOT_S):
419                                 OPC->_float = !OPA->string || !*PRVM_GetString(prog, OPA->string);
420                                 DISPATCH_OPCODE();
421                         HANDLE_OPCODE(OP_NOT_FNC):
422                                 OPC->_float = !OPA->function;
423                                 DISPATCH_OPCODE();
424                         HANDLE_OPCODE(OP_NOT_ENT):
425                                 OPC->_float = (OPA->edict == 0);
426                                 DISPATCH_OPCODE();
427                         HANDLE_OPCODE(OP_EQ_F):
428                                 OPC->_float = OPA->_float == OPB->_float;
429                                 DISPATCH_OPCODE();
430                         HANDLE_OPCODE(OP_EQ_V):
431                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
432                                 DISPATCH_OPCODE();
433                         HANDLE_OPCODE(OP_EQ_S):
434                                 OPC->_float = !strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
435                                 DISPATCH_OPCODE();
436                         HANDLE_OPCODE(OP_EQ_E):
437                                 OPC->_float = OPA->_int == OPB->_int;
438                                 DISPATCH_OPCODE();
439                         HANDLE_OPCODE(OP_EQ_FNC):
440                                 OPC->_float = OPA->function == OPB->function;
441                                 DISPATCH_OPCODE();
442                         HANDLE_OPCODE(OP_NE_F):
443                                 OPC->_float = OPA->_float != OPB->_float;
444                                 DISPATCH_OPCODE();
445                         HANDLE_OPCODE(OP_NE_V):
446                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
447                                 DISPATCH_OPCODE();
448                         HANDLE_OPCODE(OP_NE_S):
449                                 OPC->_float = strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
450                                 DISPATCH_OPCODE();
451                         HANDLE_OPCODE(OP_NE_E):
452                                 OPC->_float = OPA->_int != OPB->_int;
453                                 DISPATCH_OPCODE();
454                         HANDLE_OPCODE(OP_NE_FNC):
455                                 OPC->_float = OPA->function != OPB->function;
456                                 DISPATCH_OPCODE();
457
458                 //==================
459                         HANDLE_OPCODE(OP_STORE_F):
460                         HANDLE_OPCODE(OP_STORE_ENT):
461                         HANDLE_OPCODE(OP_STORE_FLD):            // integers
462                         HANDLE_OPCODE(OP_STORE_FNC):            // pointers
463                                 OPB->_int = OPA->_int;
464                                 DISPATCH_OPCODE();
465                         HANDLE_OPCODE(OP_STORE_S):
466                                 // refresh the garbage collection on the string - this guards
467                                 // against a certain sort of repeated migration to earlier
468                                 // points in the scan that could otherwise result in the string
469                                 // being freed for being unused
470                                 if(prvm_garbagecollection_enable.integer)
471                                         PRVM_GetString(prog, OPA->_int);
472                                 OPB->_int = OPA->_int;
473                                 DISPATCH_OPCODE();
474                         HANDLE_OPCODE(OP_STORE_V):
475                                 OPB->ivector[0] = OPA->ivector[0];
476                                 OPB->ivector[1] = OPA->ivector[1];
477                                 OPB->ivector[2] = OPA->ivector[2];
478                                 DISPATCH_OPCODE();
479
480                         HANDLE_OPCODE(OP_STOREP_F):
481                         HANDLE_OPCODE(OP_STOREP_ENT):
482                         HANDLE_OPCODE(OP_STOREP_FLD):           // integers
483                         HANDLE_OPCODE(OP_STOREP_FNC):           // pointers
484                                 if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields)
485                                 {
486                                         if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea)
487                                         {
488                                                 PRE_ERROR();
489                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
490                                                 goto cleanup;
491                                         }
492                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
493                                         {
494                                                 PRE_ERROR();
495                                                 VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
496                                         }
497                                 }
498                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
499                                 ptr->_int = OPA->_int;
500                                 DISPATCH_OPCODE();
501                         HANDLE_OPCODE(OP_STOREP_S):
502                                 if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields)
503                                 {
504                                         if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea)
505                                         {
506                                                 PRE_ERROR();
507                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
508                                                 goto cleanup;
509                                         }
510                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
511                                         {
512                                                 PRE_ERROR();
513                                                 VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
514                                         }
515                                 }
516                                 // refresh the garbage collection on the string - this guards
517                                 // against a certain sort of repeated migration to earlier
518                                 // points in the scan that could otherwise result in the string
519                                 // being freed for being unused
520                                 if(prvm_garbagecollection_enable.integer)
521                                         PRVM_GetString(prog, OPA->_int);
522                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
523                                 ptr->_int = OPA->_int;
524                                 DISPATCH_OPCODE();
525                         HANDLE_OPCODE(OP_STOREP_V):
526                                 if ((prvm_uint_t)OPB->_int - cached_entityfields > (prvm_uint_t)cached_entityfieldsarea_entityfields_3)
527                                 {
528                                         if ((prvm_uint_t)OPB->_int > cached_entityfieldsarea_3)
529                                         {
530                                                 PRE_ERROR();
531                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
532                                                 goto cleanup;
533                                         }
534                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
535                                         {
536                                                 PRE_ERROR();
537                                                 VM_Warning(prog, "Attempted assignment to NULL entity field .%s (%i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
538                                         }
539                                 }
540                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
541                                 ptr->ivector[0] = OPA->ivector[0];
542                                 ptr->ivector[1] = OPA->ivector[1];
543                                 ptr->ivector[2] = OPA->ivector[2];
544                                 DISPATCH_OPCODE();
545
546                         HANDLE_OPCODE(OP_ADDRESS):
547                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
548                                 {
549                                         PRE_ERROR();
550                                         prog->error_cmd("%s attempted to address an out of bounds edict number", prog->name);
551                                         goto cleanup;
552                                 }
553                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
554                                 {
555                                         PRE_ERROR();
556                                         prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, (int)OPB->_int);
557                                         goto cleanup;
558                                 }
559 #if 0
560                                 if (OPA->edict == 0 && !cached_allowworldwrites)
561                                 {
562                                         PRE_ERROR();
563                                         prog->error_cmd("Forbidden assignment to NULL entity in %s", prog->name);
564                                         goto cleanup;
565                                 }
566 #endif
567                                 OPC->_int = OPA->edict * cached_entityfields + OPB->_int;
568                                 DISPATCH_OPCODE();
569
570                         HANDLE_OPCODE(OP_LOAD_F):
571                         HANDLE_OPCODE(OP_LOAD_FLD):
572                         HANDLE_OPCODE(OP_LOAD_ENT):
573                         HANDLE_OPCODE(OP_LOAD_FNC):
574                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
575                                 {
576                                         PRE_ERROR();
577                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
578                                         goto cleanup;
579                                 }
580                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
581                                 {
582                                         PRE_ERROR();
583                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
584                                         goto cleanup;
585                                 }
586                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
587                                 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
588                                 DISPATCH_OPCODE();
589                         HANDLE_OPCODE(OP_LOAD_S):
590                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
591                                 {
592                                         PRE_ERROR();
593                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
594                                         goto cleanup;
595                                 }
596                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
597                                 {
598                                         PRE_ERROR();
599                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
600                                         goto cleanup;
601                                 }
602                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
603                                 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
604                                 // refresh the garbage collection on the string - this guards
605                                 // against a certain sort of repeated migration to earlier
606                                 // points in the scan that could otherwise result in the string
607                                 // being freed for being unused
608                                 if(prvm_garbagecollection_enable.integer)
609                                         PRVM_GetString(prog, OPC->_int);
610                                 DISPATCH_OPCODE();
611
612                         HANDLE_OPCODE(OP_LOAD_V):
613                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
614                                 {
615                                         PRE_ERROR();
616                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
617                                         goto cleanup;
618                                 }
619                                 if ((prvm_uint_t)OPB->_int > cached_entityfields_3)
620                                 {
621                                         PRE_ERROR();
622                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
623                                         goto cleanup;
624                                 }
625                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
626                                 ptr = (prvm_eval_t *)(ed->fields.ip + OPB->_int);
627                                 OPC->ivector[0] = ptr->ivector[0];
628                                 OPC->ivector[1] = ptr->ivector[1];
629                                 OPC->ivector[2] = ptr->ivector[2];
630                                 DISPATCH_OPCODE();
631
632                 //==================
633
634                         HANDLE_OPCODE(OP_IFNOT):
635                                 //spike FIXME -- dp redefined IFNOT[_I] as IFNOT_F, which breaks if(0x80000000)
636                                 //spike FIXME -- you should add separate IFNOT_I/IFNOT_F opcodes and remap IFNOT_I to ITNOT_F in v6 progs for compat.
637                                 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
638                                 // TODO add an "int-if", and change this one to OPA->_float
639                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
640                                 // and entity, string, field values can never have that value
641                                 {
642                                         ADVANCE_PROFILE_BEFORE_JUMP();
643                                         st = cached_statements + st->jumpabsolute - 1;  // offset the st++
644                                         startst = st;
645                                         // no bounds check needed, it is done when loading progs
646                                         if (++jumpcount == 10000000 && prvm_runawaycheck)
647                                         {
648                                                 prog->xstatement = st - cached_statements;
649                                                 PRVM_Profile(prog, 1<<30, 1000000, 0);
650                                                 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
651                                         }
652                                 }
653                                 DISPATCH_OPCODE();
654
655                         HANDLE_OPCODE(OP_IF):
656                                 //spike FIXME -- dp redefined IF[_I] as IF_F
657                                 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
658                                 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
659                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
660                                 // and entity, string, field values can never have that value
661                                 {
662                                         ADVANCE_PROFILE_BEFORE_JUMP();
663                                         st = cached_statements + st->jumpabsolute - 1;  // offset the st++
664                                         startst = st;
665                                         // no bounds check needed, it is done when loading progs
666                                         if (++jumpcount == 10000000 && prvm_runawaycheck)
667                                         {
668                                                 prog->xstatement = st - cached_statements;
669                                                 PRVM_Profile(prog, 1<<30, 0.01, 0);
670                                                 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
671                                         }
672                                 }
673                                 DISPATCH_OPCODE();
674
675                         HANDLE_OPCODE(OP_GOTO):
676                                 ADVANCE_PROFILE_BEFORE_JUMP();
677                                 st = cached_statements + st->jumpabsolute - 1;  // offset the st++
678                                 startst = st;
679                                 // no bounds check needed, it is done when loading progs
680                                 if (++jumpcount == 10000000 && prvm_runawaycheck)
681                                 {
682                                         prog->xstatement = st - cached_statements;
683                                         PRVM_Profile(prog, 1<<30, 0.01, 0);
684                                         prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
685                                 }
686                                 DISPATCH_OPCODE();
687
688                         HANDLE_OPCODE(OP_CALL0):
689                         HANDLE_OPCODE(OP_CALL1):
690                         HANDLE_OPCODE(OP_CALL2):
691                         HANDLE_OPCODE(OP_CALL3):
692                         HANDLE_OPCODE(OP_CALL4):
693                         HANDLE_OPCODE(OP_CALL5):
694                         HANDLE_OPCODE(OP_CALL6):
695                         HANDLE_OPCODE(OP_CALL7):
696                         HANDLE_OPCODE(OP_CALL8):
697 #ifdef PRVMTIMEPROFILING 
698                                 tm = Sys_DirtyTime();
699                                 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
700                                 starttm = tm;
701 #endif
702                                 ADVANCE_PROFILE_BEFORE_JUMP();
703                                 startst = st;
704                                 prog->xstatement = st - cached_statements;
705                                 prog->argc = st->op - OP_CALL0;
706                                 if (!OPA->function)
707                                 {
708                                         prog->error_cmd("NULL function in %s", prog->name);
709                                 }
710
711                                 if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions)
712                                 {
713                                         PRE_ERROR();
714                                         prog->error_cmd("%s attempted CALL outside the program", prog->name);
715                                         goto cleanup;
716                                 }
717
718                                 enterfunc = &prog->functions[OPA->function];
719                                 if (enterfunc->callcount++ == 0 && (prvm_coverage.integer & 1))
720                                         PRVM_FunctionCoverageEvent(prog, enterfunc);
721
722                                 if (enterfunc->first_statement < 0)
723                                 {
724                                         // negative first_statement values are built in functions
725                                         int builtinnumber = -enterfunc->first_statement;
726                                         prog->xfunction->builtinsprofile++;
727                                         if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
728                                         {
729                                                 prog->builtins[builtinnumber](prog);
730 #ifdef PRVMTIMEPROFILING 
731                                                 tm = Sys_DirtyTime();
732                                                 enterfunc->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
733                                                 prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
734                                                 starttm = tm;
735 #endif
736                                                 // builtins may cause ED_Alloc() to be called, update cached variables
737                                                 cached_edictsfields = prog->edictsfields.fp;
738                                                 cached_entityfields = prog->entityfields;
739                                                 cached_entityfields_3 = prog->entityfields - 3;
740                                                 cached_entityfieldsarea = prog->entityfieldsarea;
741                                                 cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields;
742                                                 cached_entityfieldsarea_3 = prog->entityfieldsarea - 3;
743                                                 cached_entityfieldsarea_entityfields_3 = prog->entityfieldsarea - prog->entityfields - 3;
744                                                 cached_max_edicts = prog->max_edicts;
745                                                 // these do not change
746                                                 //cached_statements = prog->statements;
747                                                 //cached_allowworldwrites = prog->allowworldwrites;
748                                                 //cached_flag = prog->flag;
749                                                 // if prog->trace changed we need to change interpreter path
750                                                 if (prog->trace != cachedpr_trace)
751                                                         goto chooseexecprogram;
752                                         }
753                                         else
754                                                 prog->error_cmd("No such builtin #%i in %s. This program is corrupt or incompatible with DarkPlaces (or this version of it)", builtinnumber, prog->name);
755                                 }
756                                 else
757                                         st = cached_statements + PRVM_EnterFunction(prog, enterfunc);
758                                 startst = st;
759                                 DISPATCH_OPCODE();
760
761                         HANDLE_OPCODE(OP_DONE):
762                         HANDLE_OPCODE(OP_RETURN):
763 #ifdef PRVMTIMEPROFILING 
764                                 tm = Sys_DirtyTime();
765                                 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
766                                 starttm = tm;
767 #endif
768                                 ADVANCE_PROFILE_BEFORE_JUMP();
769                                 prog->xstatement = st - cached_statements;
770
771                                 prog->globals.ip[OFS_RETURN  ] = prog->globals.ip[st->operand[0]  ];
772                                 prog->globals.ip[OFS_RETURN+1] = prog->globals.ip[st->operand[0]+1];
773                                 prog->globals.ip[OFS_RETURN+2] = prog->globals.ip[st->operand[0]+2];
774
775                                 st = cached_statements + PRVM_LeaveFunction(prog);
776                                 startst = st;
777                                 if (prog->depth <= exitdepth)
778                                         goto cleanup; // all done
779                                 DISPATCH_OPCODE();
780
781                         HANDLE_OPCODE(OP_STATE):
782                                 if(cached_flag & PRVM_OP_STATE)
783                                 {
784                                         ed = PRVM_PROG_TO_EDICT(PRVM_gameglobaledict(self));
785                                         PRVM_gameedictfloat(ed,nextthink) = PRVM_gameglobalfloat(time) + 0.1;
786                                         PRVM_gameedictfloat(ed,frame) = OPA->_float;
787                                         PRVM_gameedictfunction(ed,think) = OPB->function;
788                                 }
789                                 else
790                                 {
791                                         PRE_ERROR();
792                                         prog->xstatement = st - cached_statements;
793                                         prog->error_cmd("OP_STATE not supported by %s", prog->name);
794                                 }
795                                 DISPATCH_OPCODE();
796
797                         HANDLE_OPCODE(OP_ADD_I):
798                                 OPC->_int = OPA->_int + OPB->_int;
799                                 DISPATCH_OPCODE();
800                         HANDLE_OPCODE(OP_ADD_IF):
801                                 OPC->_float = OPA->_int + (prvm_int_t) OPB->_float;
802                                 DISPATCH_OPCODE();
803                         HANDLE_OPCODE(OP_ADD_FI):
804                                 OPC->_float = OPA->_float + (prvm_vec_t) OPB->_int;
805                                 DISPATCH_OPCODE();
806                         HANDLE_OPCODE(OP_SUB_I):
807                                 OPC->_int = OPA->_int - OPB->_int;
808                                 DISPATCH_OPCODE();
809                         HANDLE_OPCODE(OP_SUB_IF):
810                                 OPC->_float = OPA->_int - (prvm_int_t) OPB->_float;
811                                 DISPATCH_OPCODE();
812                         HANDLE_OPCODE(OP_SUB_FI):
813                                 OPC->_float = OPA->_float - (prvm_vec_t) OPB->_int;
814                                 DISPATCH_OPCODE();
815                         HANDLE_OPCODE(OP_MUL_I):
816                                 OPC->_int = OPA->_int * OPB->_int;
817                                 DISPATCH_OPCODE();
818                         HANDLE_OPCODE(OP_MUL_IF):
819                                 OPC->_float = OPA->_int * (prvm_int_t) OPB->_float;
820                                 DISPATCH_OPCODE();
821                         HANDLE_OPCODE(OP_MUL_FI):
822                                 OPC->_float = OPA->_float * (prvm_vec_t) OPB->_int;
823                                 DISPATCH_OPCODE();
824                         HANDLE_OPCODE(OP_MUL_VI):
825                                 OPC->vector[0] = (prvm_vec_t) OPB->_int * OPA->vector[0];
826                                 OPC->vector[1] = (prvm_vec_t) OPB->_int * OPA->vector[1];
827                                 OPC->vector[2] = (prvm_vec_t) OPB->_int * OPA->vector[2];
828                                 DISPATCH_OPCODE();
829                         HANDLE_OPCODE(OP_DIV_VF):
830                                 {
831                                         float temp = 1.0f / OPB->_float;
832                                         OPC->vector[0] = temp * OPA->vector[0];
833                                         OPC->vector[1] = temp * OPA->vector[1];
834                                         OPC->vector[2] = temp * OPA->vector[2];
835                                 }
836                                 DISPATCH_OPCODE();
837                         HANDLE_OPCODE(OP_DIV_I):
838                                 OPC->_int = OPA->_int / OPB->_int;
839                                 DISPATCH_OPCODE();
840                         HANDLE_OPCODE(OP_DIV_IF):
841                                 OPC->_float = OPA->_int / (prvm_int_t) OPB->_float;
842                                 DISPATCH_OPCODE();
843                         HANDLE_OPCODE(OP_DIV_FI):
844                                 OPC->_float = OPA->_float / (prvm_vec_t) OPB->_int;
845                                 DISPATCH_OPCODE();
846                         HANDLE_OPCODE(OP_CONV_IF):
847                                 OPC->_float = OPA->_int;
848                                 DISPATCH_OPCODE();
849                         HANDLE_OPCODE(OP_CONV_FI):
850                                 OPC->_int = OPA->_float;
851                                 DISPATCH_OPCODE();
852                         HANDLE_OPCODE(OP_BITAND_I):
853                                 OPC->_int = OPA->_int & OPB->_int;
854                                 DISPATCH_OPCODE();
855                         HANDLE_OPCODE(OP_BITOR_I):
856                                 OPC->_int = OPA->_int | OPB->_int;
857                                 DISPATCH_OPCODE();
858                         HANDLE_OPCODE(OP_BITAND_IF):
859                                 OPC->_int = OPA->_int & (prvm_int_t)OPB->_float;
860                                 DISPATCH_OPCODE();
861                         HANDLE_OPCODE(OP_BITOR_IF):
862                                 OPC->_int = OPA->_int | (prvm_int_t)OPB->_float;
863                                 DISPATCH_OPCODE();
864                         HANDLE_OPCODE(OP_BITAND_FI):
865                                 OPC->_int = (prvm_int_t)OPA->_float & OPB->_int;
866                                 DISPATCH_OPCODE();
867                         HANDLE_OPCODE(OP_BITOR_FI):
868                                 OPC->_int = (prvm_int_t)OPA->_float | OPB->_int;
869                                 DISPATCH_OPCODE();
870                         HANDLE_OPCODE(OP_GE_I):
871                                 OPC->_int = OPA->_int >= OPB->_int;
872                                 DISPATCH_OPCODE();
873                         HANDLE_OPCODE(OP_LE_I):
874                                 OPC->_int = OPA->_int <= OPB->_int;
875                                 DISPATCH_OPCODE();
876                         HANDLE_OPCODE(OP_GT_I):
877                                 OPC->_int = OPA->_int > OPB->_int;
878                                 DISPATCH_OPCODE();
879                         HANDLE_OPCODE(OP_LT_I):
880                                 OPC->_int = OPA->_int < OPB->_int;
881                                 DISPATCH_OPCODE();
882                         HANDLE_OPCODE(OP_AND_I):
883                                 OPC->_int = OPA->_int && OPB->_int;
884                                 DISPATCH_OPCODE();
885                         HANDLE_OPCODE(OP_OR_I):
886                                 OPC->_int = OPA->_int || OPB->_int;
887                                 DISPATCH_OPCODE();
888                         HANDLE_OPCODE(OP_GE_IF):
889                                 OPC->_int = (prvm_vec_t)OPA->_int >= OPB->_float;
890                                 DISPATCH_OPCODE();
891                         HANDLE_OPCODE(OP_LE_IF):
892                                 OPC->_int = (prvm_vec_t)OPA->_int <= OPB->_float;
893                                 DISPATCH_OPCODE();
894                         HANDLE_OPCODE(OP_GT_IF):
895                                 OPC->_int = (prvm_vec_t)OPA->_int > OPB->_float;
896                                 DISPATCH_OPCODE();
897                         HANDLE_OPCODE(OP_LT_IF):
898                                 OPC->_int = (prvm_vec_t)OPA->_int < OPB->_float;
899                                 DISPATCH_OPCODE();
900                         HANDLE_OPCODE(OP_AND_IF):
901                                 OPC->_int = (prvm_vec_t)OPA->_int && OPB->_float;
902                                 DISPATCH_OPCODE();
903                         HANDLE_OPCODE(OP_OR_IF):
904                                 OPC->_int = (prvm_vec_t)OPA->_int || OPB->_float;
905                                 DISPATCH_OPCODE();
906                         HANDLE_OPCODE(OP_GE_FI):
907                                 OPC->_int = OPA->_float >= (prvm_vec_t)OPB->_int;
908                                 DISPATCH_OPCODE();
909                         HANDLE_OPCODE(OP_LE_FI):
910                                 OPC->_int = OPA->_float <= (prvm_vec_t)OPB->_int;
911                                 DISPATCH_OPCODE();
912                         HANDLE_OPCODE(OP_GT_FI):
913                                 OPC->_int = OPA->_float > (prvm_vec_t)OPB->_int;
914                                 DISPATCH_OPCODE();
915                         HANDLE_OPCODE(OP_LT_FI):
916                                 OPC->_int = OPA->_float < (prvm_vec_t)OPB->_int;
917                                 DISPATCH_OPCODE();
918                         HANDLE_OPCODE(OP_AND_FI):
919                                 OPC->_int = OPA->_float && (prvm_vec_t)OPB->_int;
920                                 DISPATCH_OPCODE();
921                         HANDLE_OPCODE(OP_OR_FI):
922                                 OPC->_int = OPA->_float || (prvm_vec_t)OPB->_int;
923                                 DISPATCH_OPCODE();
924                         HANDLE_OPCODE(OP_NOT_I):
925                                 OPC->_int = !OPA->_int;
926                                 DISPATCH_OPCODE();
927                         HANDLE_OPCODE(OP_EQ_I):
928                                 OPC->_int = OPA->_int == OPB->_int;
929                                 DISPATCH_OPCODE();
930                         HANDLE_OPCODE(OP_EQ_IF):
931                                 OPC->_int = (prvm_vec_t)OPA->_int == OPB->_float;
932                                 DISPATCH_OPCODE();
933                         HANDLE_OPCODE(OP_EQ_FI):
934                                 OPC->_int = OPA->_float == (prvm_vec_t)OPB->_int;
935                                 DISPATCH_OPCODE();
936                         HANDLE_OPCODE(OP_NE_I):
937                                 OPC->_int = OPA->_int != OPB->_int;
938                                 DISPATCH_OPCODE();
939                         HANDLE_OPCODE(OP_NE_IF):
940                                 OPC->_int = (prvm_vec_t)OPA->_int != OPB->_float;
941                                 DISPATCH_OPCODE();
942                         HANDLE_OPCODE(OP_NE_FI):
943                                 OPC->_int = OPA->_float != (prvm_vec_t)OPB->_int;
944                                 DISPATCH_OPCODE();
945                         HANDLE_OPCODE(OP_STORE_I):
946                         HANDLE_OPCODE(OP_STORE_P):
947                                 OPB->_int = OPA->_int;
948                                 DISPATCH_OPCODE();
949                         HANDLE_OPCODE(OP_STOREP_I):
950 #if PRBOUNDSCHECK
951                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
952                                 {
953                                         PRE_ERROR();
954                                         prog->error_cmd("%s attempted to write to an out of bounds edict", prog->name);
955                                         goto cleanup;
956                                 }
957 #endif
958                                 ptr = (prvm_eval_t *)(prog->edictsfields.ip + OPB->_int);
959                                 ptr->_int = OPA->_int;
960                                 DISPATCH_OPCODE();
961                         HANDLE_OPCODE(OP_LOAD_I):
962 #if PRBOUNDSCHECK
963                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
964                                 {
965                                         PRE_ERROR();
966                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
967                                         goto cleanup;
968                                 }
969                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields.ip)
970                                 {
971                                         PRE_ERROR();
972                                         prog->error_cmd("%s attempted to read an invalid field in an edict", prog->name);
973                                         goto cleanup;
974                                 }
975 #endif
976                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
977                                 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.ip + OPB->_int))->_int;
978                                 DISPATCH_OPCODE();
979
980                         HANDLE_OPCODE(OP_GSTOREP_I):
981                         HANDLE_OPCODE(OP_GSTOREP_F):
982                         HANDLE_OPCODE(OP_GSTOREP_ENT):
983                         HANDLE_OPCODE(OP_GSTOREP_FLD):          // integers
984                         HANDLE_OPCODE(OP_GSTOREP_S):
985                         HANDLE_OPCODE(OP_GSTOREP_FNC):          // pointers
986                                 if (OPB->_int < 0 || OPB->_int >= prog->numglobals)
987                                 {
988                                         PRE_ERROR();
989                                         prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
990                                         goto cleanup;
991                                 }
992                                 prog->globals.ip[OPB->_int] = OPA->_int;
993                                 DISPATCH_OPCODE();
994                         HANDLE_OPCODE(OP_GSTOREP_V):
995                                 if (OPB->_int < 0 || OPB->_int + 2 >= prog->numglobals)
996                                 {
997                                         PRE_ERROR();
998                                         prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
999                                         goto cleanup;
1000                                 }
1001                                 prog->globals.ip[OPB->_int  ] = OPA->ivector[0];
1002                                 prog->globals.ip[OPB->_int+1] = OPA->ivector[1];
1003                                 prog->globals.ip[OPB->_int+2] = OPA->ivector[2];
1004                                 DISPATCH_OPCODE();
1005
1006                         HANDLE_OPCODE(OP_GADDRESS):
1007                                 i = OPA->_int + (prvm_int_t) OPB->_float;
1008                                 if (i < 0 || i >= prog->numglobaldefs)
1009                                 {
1010                                         PRE_ERROR();
1011                                         prog->error_cmd("%s attempted to address an out of bounds global", prog->name);
1012                                         goto cleanup;
1013                                 }
1014                                 OPC->_int = prog->globals.ip[i];
1015                                 DISPATCH_OPCODE();
1016
1017                         HANDLE_OPCODE(OP_GLOAD_I):
1018                         HANDLE_OPCODE(OP_GLOAD_F):
1019                         HANDLE_OPCODE(OP_GLOAD_FLD):
1020                         HANDLE_OPCODE(OP_GLOAD_ENT):
1021                         HANDLE_OPCODE(OP_GLOAD_S):
1022                         HANDLE_OPCODE(OP_GLOAD_FNC):
1023                                 if (OPA->_int < 0 || OPA->_int >= prog->numglobals)
1024                                 {
1025                                         PRE_ERROR();
1026                                         prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1027                                         goto cleanup;
1028                                 }
1029                                 OPC->_int = prog->globals.ip[OPA->_int];
1030                                 DISPATCH_OPCODE();
1031
1032                         HANDLE_OPCODE(OP_GLOAD_V):
1033                                 if (OPA->_int < 0 || OPA->_int + 2 >= prog->numglobals)
1034                                 {
1035                                         PRE_ERROR();
1036                                         prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1037                                         goto cleanup;
1038                                 }
1039                                 OPC->ivector[0] = prog->globals.ip[OPA->_int  ];
1040                                 OPC->ivector[1] = prog->globals.ip[OPA->_int+1];
1041                                 OPC->ivector[2] = prog->globals.ip[OPA->_int+2];
1042                                 DISPATCH_OPCODE();
1043
1044                         HANDLE_OPCODE(OP_BOUNDCHECK):
1045                                 if ((unsigned int)OPA->_int < (unsigned int)st->operand[2] || (unsigned int)OPA->_int >= (unsigned int)st->operand[1])
1046                                 {
1047                                         PRE_ERROR();
1048                                         prog->error_cmd("Progs boundcheck failed in %s, value is < %" PRVM_PRIi " or >= %" PRVM_PRIi, prog->name, OPC->_int, OPB->_int);
1049                                         goto cleanup;
1050                                 }
1051                                 DISPATCH_OPCODE();
1052
1053 #if !USE_COMPUTED_GOTOS
1054                         default:
1055                                 PRE_ERROR();
1056                                 prog->error_cmd("Bad opcode %i in %s. This program is corrupt or incompatible with DarkPlaces (or this version of it)", st->op, prog->name);
1057                                 goto cleanup;
1058                         }
1059 #if PRVMSLOWINTERPRETER
1060                         {
1061                                 if (prog->watch_global_type != ev_void)
1062                                 {
1063                                         prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global);
1064                                         prog->xstatement = st - cached_statements;
1065                                         PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, g);
1066                                 }
1067                                 if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
1068                                 {
1069                                         prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
1070                                         prog->xstatement = st - cached_statements;
1071                                         PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, g);
1072                                 }
1073                         }
1074 #endif
1075                 }
1076 #endif // !USE_COMPUTED_GOTOS
1077
1078 #undef DISPATCH_OPCODE
1079 #undef HANDLE_OPCODE
1080 #undef USE_COMPUTED_GOTOS
1081 #undef PRE_ERROR
1082 #undef ADVANCE_PROFILE_BEFORE_JUMP