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