]> git.xonotic.org Git - xonotic/darkplaces.git/blob - prvm_execprogram.h
physics: fix and refactor unsticking
[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                                         PRE_ERROR();
381                                         VM_Warning(prog, "Attempted division of %f by zero\n", OPA->_float);
382                                         OPC->_float = 0.0f;
383                                 }
384                                 DISPATCH_OPCODE();
385                         HANDLE_OPCODE(OP_BITAND):
386                                 OPC->_float = (prvm_int_t)OPA->_float & (prvm_int_t)OPB->_float;
387                                 DISPATCH_OPCODE();
388                         HANDLE_OPCODE(OP_BITOR):
389                                 OPC->_float = (prvm_int_t)OPA->_float | (prvm_int_t)OPB->_float;
390                                 DISPATCH_OPCODE();
391                         HANDLE_OPCODE(OP_GE):
392                                 OPC->_float = OPA->_float >= OPB->_float;
393                                 DISPATCH_OPCODE();
394                         HANDLE_OPCODE(OP_LE):
395                                 OPC->_float = OPA->_float <= OPB->_float;
396                                 DISPATCH_OPCODE();
397                         HANDLE_OPCODE(OP_GT):
398                                 OPC->_float = OPA->_float > OPB->_float;
399                                 DISPATCH_OPCODE();
400                         HANDLE_OPCODE(OP_LT):
401                                 OPC->_float = OPA->_float < OPB->_float;
402                                 DISPATCH_OPCODE();
403                         HANDLE_OPCODE(OP_AND):
404                                 OPC->_float = PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int) && PRVM_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
405                                 DISPATCH_OPCODE();
406                         HANDLE_OPCODE(OP_OR):
407                                 OPC->_float = PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int) || PRVM_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
408                                 DISPATCH_OPCODE();
409                         HANDLE_OPCODE(OP_NOT_F):
410                                 OPC->_float = !PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int);
411                                 DISPATCH_OPCODE();
412                         HANDLE_OPCODE(OP_NOT_V):
413                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
414                                 DISPATCH_OPCODE();
415                         HANDLE_OPCODE(OP_NOT_S):
416                                 OPC->_float = !OPA->string || !*PRVM_GetString(prog, OPA->string);
417                                 DISPATCH_OPCODE();
418                         HANDLE_OPCODE(OP_NOT_FNC):
419                                 OPC->_float = !OPA->function;
420                                 DISPATCH_OPCODE();
421                         HANDLE_OPCODE(OP_NOT_ENT):
422                                 OPC->_float = (OPA->edict == 0);
423                                 DISPATCH_OPCODE();
424                         HANDLE_OPCODE(OP_EQ_F):
425                                 OPC->_float = OPA->_float == OPB->_float;
426                                 DISPATCH_OPCODE();
427                         HANDLE_OPCODE(OP_EQ_V):
428                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
429                                 DISPATCH_OPCODE();
430                         HANDLE_OPCODE(OP_EQ_S):
431                                 OPC->_float = !strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
432                                 DISPATCH_OPCODE();
433                         HANDLE_OPCODE(OP_EQ_E):
434                                 OPC->_float = OPA->_int == OPB->_int;
435                                 DISPATCH_OPCODE();
436                         HANDLE_OPCODE(OP_EQ_FNC):
437                                 OPC->_float = OPA->function == OPB->function;
438                                 DISPATCH_OPCODE();
439                         HANDLE_OPCODE(OP_NE_F):
440                                 OPC->_float = OPA->_float != OPB->_float;
441                                 DISPATCH_OPCODE();
442                         HANDLE_OPCODE(OP_NE_V):
443                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
444                                 DISPATCH_OPCODE();
445                         HANDLE_OPCODE(OP_NE_S):
446                                 OPC->_float = strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
447                                 DISPATCH_OPCODE();
448                         HANDLE_OPCODE(OP_NE_E):
449                                 OPC->_float = OPA->_int != OPB->_int;
450                                 DISPATCH_OPCODE();
451                         HANDLE_OPCODE(OP_NE_FNC):
452                                 OPC->_float = OPA->function != OPB->function;
453                                 DISPATCH_OPCODE();
454
455                 //==================
456                         HANDLE_OPCODE(OP_STORE_F):
457                         HANDLE_OPCODE(OP_STORE_ENT):
458                         HANDLE_OPCODE(OP_STORE_FLD):            // integers
459                         HANDLE_OPCODE(OP_STORE_FNC):            // pointers
460                                 OPB->_int = OPA->_int;
461                                 DISPATCH_OPCODE();
462                         HANDLE_OPCODE(OP_STORE_S):
463                                 // refresh the garbage collection on the string - this guards
464                                 // against a certain sort of repeated migration to earlier
465                                 // points in the scan that could otherwise result in the string
466                                 // being freed for being unused
467                                 if(prvm_garbagecollection_enable.integer)
468                                         PRVM_GetString(prog, OPA->_int);
469                                 OPB->_int = OPA->_int;
470                                 DISPATCH_OPCODE();
471                         HANDLE_OPCODE(OP_STORE_V):
472                                 OPB->ivector[0] = OPA->ivector[0];
473                                 OPB->ivector[1] = OPA->ivector[1];
474                                 OPB->ivector[2] = OPA->ivector[2];
475                                 DISPATCH_OPCODE();
476
477                         HANDLE_OPCODE(OP_STOREP_F):
478                         HANDLE_OPCODE(OP_STOREP_ENT):
479                         HANDLE_OPCODE(OP_STOREP_FLD):           // integers
480                         HANDLE_OPCODE(OP_STOREP_FNC):           // pointers
481                                 if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields)
482                                 {
483                                         if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea)
484                                         {
485                                                 PRE_ERROR();
486                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
487                                                 goto cleanup;
488                                         }
489                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
490                                         {
491                                                 PRE_ERROR();
492                                                 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
493                                         }
494                                 }
495                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
496                                 ptr->_int = OPA->_int;
497                                 DISPATCH_OPCODE();
498                         HANDLE_OPCODE(OP_STOREP_S):
499                                 if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields)
500                                 {
501                                         if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea)
502                                         {
503                                                 PRE_ERROR();
504                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
505                                                 goto cleanup;
506                                         }
507                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
508                                         {
509                                                 PRE_ERROR();
510                                                 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
511                                         }
512                                 }
513                                 // refresh the garbage collection on the string - this guards
514                                 // against a certain sort of repeated migration to earlier
515                                 // points in the scan that could otherwise result in the string
516                                 // being freed for being unused
517                                 if(prvm_garbagecollection_enable.integer)
518                                         PRVM_GetString(prog, OPA->_int);
519                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
520                                 ptr->_int = OPA->_int;
521                                 DISPATCH_OPCODE();
522                         HANDLE_OPCODE(OP_STOREP_V):
523                                 if ((prvm_uint_t)OPB->_int - cached_entityfields > (prvm_uint_t)cached_entityfieldsarea_entityfields_3)
524                                 {
525                                         if ((prvm_uint_t)OPB->_int > cached_entityfieldsarea_3)
526                                         {
527                                                 PRE_ERROR();
528                                                 prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
529                                                 goto cleanup;
530                                         }
531                                         if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
532                                         {
533                                                 PRE_ERROR();
534                                                 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
535                                         }
536                                 }
537                                 ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
538                                 ptr->ivector[0] = OPA->ivector[0];
539                                 ptr->ivector[1] = OPA->ivector[1];
540                                 ptr->ivector[2] = OPA->ivector[2];
541                                 DISPATCH_OPCODE();
542
543                         HANDLE_OPCODE(OP_ADDRESS):
544                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
545                                 {
546                                         PRE_ERROR();
547                                         prog->error_cmd("%s attempted to address an out of bounds edict number", prog->name);
548                                         goto cleanup;
549                                 }
550                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
551                                 {
552                                         PRE_ERROR();
553                                         prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, (int)OPB->_int);
554                                         goto cleanup;
555                                 }
556 #if 0
557                                 if (OPA->edict == 0 && !cached_allowworldwrites)
558                                 {
559                                         PRE_ERROR();
560                                         prog->error_cmd("Forbidden assignment to world (edictnum 0) in %s", prog->name);
561                                         goto cleanup;
562                                 }
563 #endif
564                                 OPC->_int = OPA->edict * cached_entityfields + OPB->_int;
565                                 DISPATCH_OPCODE();
566
567                         HANDLE_OPCODE(OP_LOAD_F):
568                         HANDLE_OPCODE(OP_LOAD_FLD):
569                         HANDLE_OPCODE(OP_LOAD_ENT):
570                         HANDLE_OPCODE(OP_LOAD_FNC):
571                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
572                                 {
573                                         PRE_ERROR();
574                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
575                                         goto cleanup;
576                                 }
577                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
578                                 {
579                                         PRE_ERROR();
580                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
581                                         goto cleanup;
582                                 }
583                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
584                                 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
585                                 DISPATCH_OPCODE();
586                         HANDLE_OPCODE(OP_LOAD_S):
587                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
588                                 {
589                                         PRE_ERROR();
590                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
591                                         goto cleanup;
592                                 }
593                                 if ((prvm_uint_t)OPB->_int >= cached_entityfields)
594                                 {
595                                         PRE_ERROR();
596                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
597                                         goto cleanup;
598                                 }
599                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
600                                 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
601                                 // refresh the garbage collection on the string - this guards
602                                 // against a certain sort of repeated migration to earlier
603                                 // points in the scan that could otherwise result in the string
604                                 // being freed for being unused
605                                 if(prvm_garbagecollection_enable.integer)
606                                         PRVM_GetString(prog, OPC->_int);
607                                 DISPATCH_OPCODE();
608
609                         HANDLE_OPCODE(OP_LOAD_V):
610                                 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
611                                 {
612                                         PRE_ERROR();
613                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
614                                         goto cleanup;
615                                 }
616                                 if ((prvm_uint_t)OPB->_int > cached_entityfields_3)
617                                 {
618                                         PRE_ERROR();
619                                         prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int);
620                                         goto cleanup;
621                                 }
622                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
623                                 ptr = (prvm_eval_t *)(ed->fields.ip + OPB->_int);
624                                 OPC->ivector[0] = ptr->ivector[0];
625                                 OPC->ivector[1] = ptr->ivector[1];
626                                 OPC->ivector[2] = ptr->ivector[2];
627                                 DISPATCH_OPCODE();
628
629                 //==================
630
631                         HANDLE_OPCODE(OP_IFNOT):
632                                 //spike FIXME -- dp redefined IFNOT[_I] as IFNOT_F, which breaks if(0x80000000)
633                                 //spike FIXME -- you should add separate IFNOT_I/IFNOT_F opcodes and remap IFNOT_I to ITNOT_F in v6 progs for compat.
634                                 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
635                                 // TODO add an "int-if", and change this one to OPA->_float
636                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
637                                 // and entity, string, field values can never have that value
638                                 {
639                                         ADVANCE_PROFILE_BEFORE_JUMP();
640                                         st = cached_statements + st->jumpabsolute - 1;  // offset the st++
641                                         startst = st;
642                                         // no bounds check needed, it is done when loading progs
643                                         if (++jumpcount == 10000000 && prvm_runawaycheck)
644                                         {
645                                                 prog->xstatement = st - cached_statements;
646                                                 PRVM_Profile(prog, 1<<30, 1000000, 0);
647                                                 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
648                                         }
649                                 }
650                                 DISPATCH_OPCODE();
651
652                         HANDLE_OPCODE(OP_IF):
653                                 //spike FIXME -- dp redefined IF[_I] as IF_F
654                                 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
655                                 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
656                                 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
657                                 // and entity, string, field values can never have that value
658                                 {
659                                         ADVANCE_PROFILE_BEFORE_JUMP();
660                                         st = cached_statements + st->jumpabsolute - 1;  // offset the st++
661                                         startst = st;
662                                         // no bounds check needed, it is done when loading progs
663                                         if (++jumpcount == 10000000 && prvm_runawaycheck)
664                                         {
665                                                 prog->xstatement = st - cached_statements;
666                                                 PRVM_Profile(prog, 1<<30, 0.01, 0);
667                                                 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
668                                         }
669                                 }
670                                 DISPATCH_OPCODE();
671
672                         HANDLE_OPCODE(OP_GOTO):
673                                 ADVANCE_PROFILE_BEFORE_JUMP();
674                                 st = cached_statements + st->jumpabsolute - 1;  // offset the st++
675                                 startst = st;
676                                 // no bounds check needed, it is done when loading progs
677                                 if (++jumpcount == 10000000 && prvm_runawaycheck)
678                                 {
679                                         prog->xstatement = st - cached_statements;
680                                         PRVM_Profile(prog, 1<<30, 0.01, 0);
681                                         prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
682                                 }
683                                 DISPATCH_OPCODE();
684
685                         HANDLE_OPCODE(OP_CALL0):
686                         HANDLE_OPCODE(OP_CALL1):
687                         HANDLE_OPCODE(OP_CALL2):
688                         HANDLE_OPCODE(OP_CALL3):
689                         HANDLE_OPCODE(OP_CALL4):
690                         HANDLE_OPCODE(OP_CALL5):
691                         HANDLE_OPCODE(OP_CALL6):
692                         HANDLE_OPCODE(OP_CALL7):
693                         HANDLE_OPCODE(OP_CALL8):
694 #ifdef PRVMTIMEPROFILING 
695                                 tm = Sys_DirtyTime();
696                                 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
697                                 starttm = tm;
698 #endif
699                                 ADVANCE_PROFILE_BEFORE_JUMP();
700                                 startst = st;
701                                 prog->xstatement = st - cached_statements;
702                                 prog->argc = st->op - OP_CALL0;
703                                 if (!OPA->function)
704                                 {
705                                         prog->error_cmd("NULL function in %s", prog->name);
706                                 }
707
708                                 if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions)
709                                 {
710                                         PRE_ERROR();
711                                         prog->error_cmd("%s attempted CALL outside the program", prog->name);
712                                         goto cleanup;
713                                 }
714
715                                 enterfunc = &prog->functions[OPA->function];
716                                 if (enterfunc->callcount++ == 0 && (prvm_coverage.integer & 1))
717                                         PRVM_FunctionCoverageEvent(prog, enterfunc);
718
719                                 if (enterfunc->first_statement < 0)
720                                 {
721                                         // negative first_statement values are built in functions
722                                         int builtinnumber = -enterfunc->first_statement;
723                                         prog->xfunction->builtinsprofile++;
724                                         if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
725                                         {
726                                                 prog->builtins[builtinnumber](prog);
727 #ifdef PRVMTIMEPROFILING 
728                                                 tm = Sys_DirtyTime();
729                                                 enterfunc->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
730                                                 prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
731                                                 starttm = tm;
732 #endif
733                                                 // builtins may cause ED_Alloc() to be called, update cached variables
734                                                 cached_edictsfields = prog->edictsfields.fp;
735                                                 cached_entityfields = prog->entityfields;
736                                                 cached_entityfields_3 = prog->entityfields - 3;
737                                                 cached_entityfieldsarea = prog->entityfieldsarea;
738                                                 cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields;
739                                                 cached_entityfieldsarea_3 = prog->entityfieldsarea - 3;
740                                                 cached_entityfieldsarea_entityfields_3 = prog->entityfieldsarea - prog->entityfields - 3;
741                                                 cached_max_edicts = prog->max_edicts;
742                                                 // these do not change
743                                                 //cached_statements = prog->statements;
744                                                 //cached_allowworldwrites = prog->allowworldwrites;
745                                                 //cached_flag = prog->flag;
746                                                 // if prog->trace changed we need to change interpreter path
747                                                 if (prog->trace != cachedpr_trace)
748                                                         goto chooseexecprogram;
749                                         }
750                                         else
751                                                 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);
752                                 }
753                                 else
754                                         st = cached_statements + PRVM_EnterFunction(prog, enterfunc);
755                                 startst = st;
756                                 DISPATCH_OPCODE();
757
758                         HANDLE_OPCODE(OP_DONE):
759                         HANDLE_OPCODE(OP_RETURN):
760 #ifdef PRVMTIMEPROFILING 
761                                 tm = Sys_DirtyTime();
762                                 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
763                                 starttm = tm;
764 #endif
765                                 ADVANCE_PROFILE_BEFORE_JUMP();
766                                 prog->xstatement = st - cached_statements;
767
768                                 prog->globals.ip[OFS_RETURN  ] = prog->globals.ip[st->operand[0]  ];
769                                 prog->globals.ip[OFS_RETURN+1] = prog->globals.ip[st->operand[0]+1];
770                                 prog->globals.ip[OFS_RETURN+2] = prog->globals.ip[st->operand[0]+2];
771
772                                 st = cached_statements + PRVM_LeaveFunction(prog);
773                                 startst = st;
774                                 if (prog->depth <= exitdepth)
775                                         goto cleanup; // all done
776                                 DISPATCH_OPCODE();
777
778                         HANDLE_OPCODE(OP_STATE):
779                                 if(cached_flag & PRVM_OP_STATE)
780                                 {
781                                         ed = PRVM_PROG_TO_EDICT(PRVM_gameglobaledict(self));
782                                         PRVM_gameedictfloat(ed,nextthink) = PRVM_gameglobalfloat(time) + 0.1;
783                                         PRVM_gameedictfloat(ed,frame) = OPA->_float;
784                                         PRVM_gameedictfunction(ed,think) = OPB->function;
785                                 }
786                                 else
787                                 {
788                                         PRE_ERROR();
789                                         prog->xstatement = st - cached_statements;
790                                         prog->error_cmd("OP_STATE not supported by %s", prog->name);
791                                 }
792                                 DISPATCH_OPCODE();
793
794                         HANDLE_OPCODE(OP_ADD_I):
795                                 OPC->_int = OPA->_int + OPB->_int;
796                                 DISPATCH_OPCODE();
797                         HANDLE_OPCODE(OP_ADD_IF):
798                                 OPC->_float = OPA->_int + (prvm_int_t) OPB->_float;
799                                 DISPATCH_OPCODE();
800                         HANDLE_OPCODE(OP_ADD_FI):
801                                 OPC->_float = OPA->_float + (prvm_vec_t) OPB->_int;
802                                 DISPATCH_OPCODE();
803                         HANDLE_OPCODE(OP_SUB_I):
804                                 OPC->_int = OPA->_int - OPB->_int;
805                                 DISPATCH_OPCODE();
806                         HANDLE_OPCODE(OP_SUB_IF):
807                                 OPC->_float = OPA->_int - (prvm_int_t) OPB->_float;
808                                 DISPATCH_OPCODE();
809                         HANDLE_OPCODE(OP_SUB_FI):
810                                 OPC->_float = OPA->_float - (prvm_vec_t) OPB->_int;
811                                 DISPATCH_OPCODE();
812                         HANDLE_OPCODE(OP_MUL_I):
813                                 OPC->_int = OPA->_int * OPB->_int;
814                                 DISPATCH_OPCODE();
815                         HANDLE_OPCODE(OP_MUL_IF):
816                                 OPC->_float = OPA->_int * (prvm_int_t) OPB->_float;
817                                 DISPATCH_OPCODE();
818                         HANDLE_OPCODE(OP_MUL_FI):
819                                 OPC->_float = OPA->_float * (prvm_vec_t) OPB->_int;
820                                 DISPATCH_OPCODE();
821                         HANDLE_OPCODE(OP_MUL_VI):
822                                 OPC->vector[0] = (prvm_vec_t) OPB->_int * OPA->vector[0];
823                                 OPC->vector[1] = (prvm_vec_t) OPB->_int * OPA->vector[1];
824                                 OPC->vector[2] = (prvm_vec_t) OPB->_int * OPA->vector[2];
825                                 DISPATCH_OPCODE();
826                         HANDLE_OPCODE(OP_DIV_VF):
827                                 {
828                                         float temp = 1.0f / OPB->_float;
829                                         OPC->vector[0] = temp * OPA->vector[0];
830                                         OPC->vector[1] = temp * OPA->vector[1];
831                                         OPC->vector[2] = temp * OPA->vector[2];
832                                 }
833                                 DISPATCH_OPCODE();
834                         HANDLE_OPCODE(OP_DIV_I):
835                                 OPC->_int = OPA->_int / OPB->_int;
836                                 DISPATCH_OPCODE();
837                         HANDLE_OPCODE(OP_DIV_IF):
838                                 OPC->_float = OPA->_int / (prvm_int_t) OPB->_float;
839                                 DISPATCH_OPCODE();
840                         HANDLE_OPCODE(OP_DIV_FI):
841                                 OPC->_float = OPA->_float / (prvm_vec_t) OPB->_int;
842                                 DISPATCH_OPCODE();
843                         HANDLE_OPCODE(OP_CONV_IF):
844                                 OPC->_float = OPA->_int;
845                                 DISPATCH_OPCODE();
846                         HANDLE_OPCODE(OP_CONV_FI):
847                                 OPC->_int = OPA->_float;
848                                 DISPATCH_OPCODE();
849                         HANDLE_OPCODE(OP_BITAND_I):
850                                 OPC->_int = OPA->_int & OPB->_int;
851                                 DISPATCH_OPCODE();
852                         HANDLE_OPCODE(OP_BITOR_I):
853                                 OPC->_int = OPA->_int | OPB->_int;
854                                 DISPATCH_OPCODE();
855                         HANDLE_OPCODE(OP_BITAND_IF):
856                                 OPC->_int = OPA->_int & (prvm_int_t)OPB->_float;
857                                 DISPATCH_OPCODE();
858                         HANDLE_OPCODE(OP_BITOR_IF):
859                                 OPC->_int = OPA->_int | (prvm_int_t)OPB->_float;
860                                 DISPATCH_OPCODE();
861                         HANDLE_OPCODE(OP_BITAND_FI):
862                                 OPC->_int = (prvm_int_t)OPA->_float & OPB->_int;
863                                 DISPATCH_OPCODE();
864                         HANDLE_OPCODE(OP_BITOR_FI):
865                                 OPC->_int = (prvm_int_t)OPA->_float | OPB->_int;
866                                 DISPATCH_OPCODE();
867                         HANDLE_OPCODE(OP_GE_I):
868                                 OPC->_int = OPA->_int >= OPB->_int;
869                                 DISPATCH_OPCODE();
870                         HANDLE_OPCODE(OP_LE_I):
871                                 OPC->_int = OPA->_int <= OPB->_int;
872                                 DISPATCH_OPCODE();
873                         HANDLE_OPCODE(OP_GT_I):
874                                 OPC->_int = OPA->_int > OPB->_int;
875                                 DISPATCH_OPCODE();
876                         HANDLE_OPCODE(OP_LT_I):
877                                 OPC->_int = OPA->_int < OPB->_int;
878                                 DISPATCH_OPCODE();
879                         HANDLE_OPCODE(OP_AND_I):
880                                 OPC->_int = OPA->_int && OPB->_int;
881                                 DISPATCH_OPCODE();
882                         HANDLE_OPCODE(OP_OR_I):
883                                 OPC->_int = OPA->_int || OPB->_int;
884                                 DISPATCH_OPCODE();
885                         HANDLE_OPCODE(OP_GE_IF):
886                                 OPC->_int = (prvm_vec_t)OPA->_int >= OPB->_float;
887                                 DISPATCH_OPCODE();
888                         HANDLE_OPCODE(OP_LE_IF):
889                                 OPC->_int = (prvm_vec_t)OPA->_int <= OPB->_float;
890                                 DISPATCH_OPCODE();
891                         HANDLE_OPCODE(OP_GT_IF):
892                                 OPC->_int = (prvm_vec_t)OPA->_int > OPB->_float;
893                                 DISPATCH_OPCODE();
894                         HANDLE_OPCODE(OP_LT_IF):
895                                 OPC->_int = (prvm_vec_t)OPA->_int < OPB->_float;
896                                 DISPATCH_OPCODE();
897                         HANDLE_OPCODE(OP_AND_IF):
898                                 OPC->_int = (prvm_vec_t)OPA->_int && OPB->_float;
899                                 DISPATCH_OPCODE();
900                         HANDLE_OPCODE(OP_OR_IF):
901                                 OPC->_int = (prvm_vec_t)OPA->_int || OPB->_float;
902                                 DISPATCH_OPCODE();
903                         HANDLE_OPCODE(OP_GE_FI):
904                                 OPC->_int = OPA->_float >= (prvm_vec_t)OPB->_int;
905                                 DISPATCH_OPCODE();
906                         HANDLE_OPCODE(OP_LE_FI):
907                                 OPC->_int = OPA->_float <= (prvm_vec_t)OPB->_int;
908                                 DISPATCH_OPCODE();
909                         HANDLE_OPCODE(OP_GT_FI):
910                                 OPC->_int = OPA->_float > (prvm_vec_t)OPB->_int;
911                                 DISPATCH_OPCODE();
912                         HANDLE_OPCODE(OP_LT_FI):
913                                 OPC->_int = OPA->_float < (prvm_vec_t)OPB->_int;
914                                 DISPATCH_OPCODE();
915                         HANDLE_OPCODE(OP_AND_FI):
916                                 OPC->_int = OPA->_float && (prvm_vec_t)OPB->_int;
917                                 DISPATCH_OPCODE();
918                         HANDLE_OPCODE(OP_OR_FI):
919                                 OPC->_int = OPA->_float || (prvm_vec_t)OPB->_int;
920                                 DISPATCH_OPCODE();
921                         HANDLE_OPCODE(OP_NOT_I):
922                                 OPC->_int = !OPA->_int;
923                                 DISPATCH_OPCODE();
924                         HANDLE_OPCODE(OP_EQ_I):
925                                 OPC->_int = OPA->_int == OPB->_int;
926                                 DISPATCH_OPCODE();
927                         HANDLE_OPCODE(OP_EQ_IF):
928                                 OPC->_int = (prvm_vec_t)OPA->_int == OPB->_float;
929                                 DISPATCH_OPCODE();
930                         HANDLE_OPCODE(OP_EQ_FI):
931                                 OPC->_int = OPA->_float == (prvm_vec_t)OPB->_int;
932                                 DISPATCH_OPCODE();
933                         HANDLE_OPCODE(OP_NE_I):
934                                 OPC->_int = OPA->_int != OPB->_int;
935                                 DISPATCH_OPCODE();
936                         HANDLE_OPCODE(OP_NE_IF):
937                                 OPC->_int = (prvm_vec_t)OPA->_int != OPB->_float;
938                                 DISPATCH_OPCODE();
939                         HANDLE_OPCODE(OP_NE_FI):
940                                 OPC->_int = OPA->_float != (prvm_vec_t)OPB->_int;
941                                 DISPATCH_OPCODE();
942                         HANDLE_OPCODE(OP_STORE_I):
943                         HANDLE_OPCODE(OP_STORE_P):
944                                 OPB->_int = OPA->_int;
945                                 DISPATCH_OPCODE();
946                         HANDLE_OPCODE(OP_STOREP_I):
947 #if PRBOUNDSCHECK
948                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
949                                 {
950                                         PRE_ERROR();
951                                         prog->error_cmd("%s attempted to write to an out of bounds edict", prog->name);
952                                         goto cleanup;
953                                 }
954 #endif
955                                 ptr = (prvm_eval_t *)(prog->edictsfields.ip + OPB->_int);
956                                 ptr->_int = OPA->_int;
957                                 DISPATCH_OPCODE();
958                         HANDLE_OPCODE(OP_LOAD_I):
959 #if PRBOUNDSCHECK
960                                 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
961                                 {
962                                         PRE_ERROR();
963                                         prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
964                                         goto cleanup;
965                                 }
966                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields.ip)
967                                 {
968                                         PRE_ERROR();
969                                         prog->error_cmd("%s attempted to read an invalid field in an edict", prog->name);
970                                         goto cleanup;
971                                 }
972 #endif
973                                 ed = PRVM_PROG_TO_EDICT(OPA->edict);
974                                 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.ip + OPB->_int))->_int;
975                                 DISPATCH_OPCODE();
976
977                         HANDLE_OPCODE(OP_GSTOREP_I):
978                         HANDLE_OPCODE(OP_GSTOREP_F):
979                         HANDLE_OPCODE(OP_GSTOREP_ENT):
980                         HANDLE_OPCODE(OP_GSTOREP_FLD):          // integers
981                         HANDLE_OPCODE(OP_GSTOREP_S):
982                         HANDLE_OPCODE(OP_GSTOREP_FNC):          // pointers
983                                 if (OPB->_int < 0 || OPB->_int >= prog->numglobals)
984                                 {
985                                         PRE_ERROR();
986                                         prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
987                                         goto cleanup;
988                                 }
989                                 prog->globals.ip[OPB->_int] = OPA->_int;
990                                 DISPATCH_OPCODE();
991                         HANDLE_OPCODE(OP_GSTOREP_V):
992                                 if (OPB->_int < 0 || OPB->_int + 2 >= prog->numglobals)
993                                 {
994                                         PRE_ERROR();
995                                         prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
996                                         goto cleanup;
997                                 }
998                                 prog->globals.ip[OPB->_int  ] = OPA->ivector[0];
999                                 prog->globals.ip[OPB->_int+1] = OPA->ivector[1];
1000                                 prog->globals.ip[OPB->_int+2] = OPA->ivector[2];
1001                                 DISPATCH_OPCODE();
1002
1003                         HANDLE_OPCODE(OP_GADDRESS):
1004                                 i = OPA->_int + (prvm_int_t) OPB->_float;
1005                                 if (i < 0 || i >= prog->numglobaldefs)
1006                                 {
1007                                         PRE_ERROR();
1008                                         prog->error_cmd("%s attempted to address an out of bounds global", prog->name);
1009                                         goto cleanup;
1010                                 }
1011                                 OPC->_int = prog->globals.ip[i];
1012                                 DISPATCH_OPCODE();
1013
1014                         HANDLE_OPCODE(OP_GLOAD_I):
1015                         HANDLE_OPCODE(OP_GLOAD_F):
1016                         HANDLE_OPCODE(OP_GLOAD_FLD):
1017                         HANDLE_OPCODE(OP_GLOAD_ENT):
1018                         HANDLE_OPCODE(OP_GLOAD_S):
1019                         HANDLE_OPCODE(OP_GLOAD_FNC):
1020                                 if (OPA->_int < 0 || OPA->_int >= prog->numglobals)
1021                                 {
1022                                         PRE_ERROR();
1023                                         prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1024                                         goto cleanup;
1025                                 }
1026                                 OPC->_int = prog->globals.ip[OPA->_int];
1027                                 DISPATCH_OPCODE();
1028
1029                         HANDLE_OPCODE(OP_GLOAD_V):
1030                                 if (OPA->_int < 0 || OPA->_int + 2 >= prog->numglobals)
1031                                 {
1032                                         PRE_ERROR();
1033                                         prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1034                                         goto cleanup;
1035                                 }
1036                                 OPC->ivector[0] = prog->globals.ip[OPA->_int  ];
1037                                 OPC->ivector[1] = prog->globals.ip[OPA->_int+1];
1038                                 OPC->ivector[2] = prog->globals.ip[OPA->_int+2];
1039                                 DISPATCH_OPCODE();
1040
1041                         HANDLE_OPCODE(OP_BOUNDCHECK):
1042                                 if ((unsigned int)OPA->_int < (unsigned int)st->operand[2] || (unsigned int)OPA->_int >= (unsigned int)st->operand[1])
1043                                 {
1044                                         PRE_ERROR();
1045                                         prog->error_cmd("Progs boundcheck failed in %s, value is < %" PRVM_PRIi " or >= %" PRVM_PRIi, prog->name, OPC->_int, OPB->_int);
1046                                         goto cleanup;
1047                                 }
1048                                 DISPATCH_OPCODE();
1049
1050 #if !USE_COMPUTED_GOTOS
1051                         default:
1052                                 PRE_ERROR();
1053                                 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);
1054                                 goto cleanup;
1055                         }
1056 #if PRVMSLOWINTERPRETER
1057                         {
1058                                 if (prog->watch_global_type != ev_void)
1059                                 {
1060                                         prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global);
1061                                         prog->xstatement = st - cached_statements;
1062                                         PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, g);
1063                                 }
1064                                 if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
1065                                 {
1066                                         prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
1067                                         prog->xstatement = st - cached_statements;
1068                                         PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, g);
1069                                 }
1070                         }
1071 #endif
1072                 }
1073 #endif // !USE_COMPUTED_GOTOS
1074
1075 #undef DISPATCH_OPCODE
1076 #undef HANDLE_OPCODE
1077 #undef USE_COMPUTED_GOTOS
1078 #undef PRE_ERROR
1079 #undef ADVANCE_PROFILE_BEFORE_JUMP