DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
prvm_execprogram.h
Go to the documentation of this file.
4// NEED to reset startst after calling this! startst may or may not be clobbered!
5#define ADVANCE_PROFILE_BEFORE_JUMP() \
6 prog->xfunction->profile += (st - startst); \
7 if (prvm_statementprofiling.integer || (prvm_coverage.integer & 4)) { \
8 /* All statements from startst+1 to st have been hit. */ \
9 while (++startst <= st) { \
10 if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
11 PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
12 } \
13 /* Observe: startst now is clobbered (now at st+1)! */ \
14 }
15
16#ifdef PRVMTIMEPROFILING
17#define PRE_ERROR() \
18 ADVANCE_PROFILE_BEFORE_JUMP(); \
19 prog->xstatement = st - cached_statements; \
20 tm = Sys_DirtyTime(); \
21 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
22 startst = st; \
23 starttm = tm
24#else
25#define PRE_ERROR() \
26 ADVANCE_PROFILE_BEFORE_JUMP(); \
27 prog->xstatement = st - cached_statements; \
28 startst = st
29#endif
30
31// This code isn't #ifdef/#define protectable, don't try.
32
33#if HAVE_COMPUTED_GOTOS && !(PRVMSLOWINTERPRETER || PRVMTIMEPROFILING)
34 // NOTE: Due to otherwise duplicate labels, only ONE interpreter path may
35 // ever hit this!
36# define USE_COMPUTED_GOTOS 1
37#endif
38
39#if USE_COMPUTED_GOTOS
40 // Must exactly match opcode_e enum in pr_comp.h
41 static const void *dispatchtable[] = {
42 &&handle_OP_DONE,
43 &&handle_OP_MUL_F,
44 &&handle_OP_MUL_V,
45 &&handle_OP_MUL_FV,
46 &&handle_OP_MUL_VF,
47 &&handle_OP_DIV_F,
48 &&handle_OP_ADD_F,
49 &&handle_OP_ADD_V,
50 &&handle_OP_SUB_F,
51 &&handle_OP_SUB_V,
52
53 &&handle_OP_EQ_F,
54 &&handle_OP_EQ_V,
55 &&handle_OP_EQ_S,
56 &&handle_OP_EQ_E,
57 &&handle_OP_EQ_FNC,
58
59 &&handle_OP_NE_F,
60 &&handle_OP_NE_V,
61 &&handle_OP_NE_S,
62 &&handle_OP_NE_E,
63 &&handle_OP_NE_FNC,
64
65 &&handle_OP_LE_F,
66 &&handle_OP_GE_F,
67 &&handle_OP_LT_F,
68 &&handle_OP_GT_F,
69
70 &&handle_OP_LOAD_F,
71 &&handle_OP_LOAD_V,
72 &&handle_OP_LOAD_S,
73 &&handle_OP_LOAD_ENT,
74 &&handle_OP_LOAD_FLD,
75 &&handle_OP_LOAD_FNC,
76
77 &&handle_OP_ADDRESS,
78
79 &&handle_OP_STORE_F,
80 &&handle_OP_STORE_V,
81 &&handle_OP_STORE_S,
82 &&handle_OP_STORE_ENT,
83 &&handle_OP_STORE_FLD,
84 &&handle_OP_STORE_FNC,
85
86 &&handle_OP_STOREP_F,
87 &&handle_OP_STOREP_V,
88 &&handle_OP_STOREP_S,
89 &&handle_OP_STOREP_ENT,
90 &&handle_OP_STOREP_FLD,
91 &&handle_OP_STOREP_FNC,
92
93 &&handle_OP_RETURN,
94 &&handle_OP_NOT_F,
95 &&handle_OP_NOT_V,
96 &&handle_OP_NOT_S,
97 &&handle_OP_NOT_ENT,
98 &&handle_OP_NOT_FNC,
99 &&handle_OP_IF,
100 &&handle_OP_IFNOT,
101 &&handle_OP_CALL0,
102 &&handle_OP_CALL1,
103 &&handle_OP_CALL2,
104 &&handle_OP_CALL3,
105 &&handle_OP_CALL4,
106 &&handle_OP_CALL5,
107 &&handle_OP_CALL6,
108 &&handle_OP_CALL7,
109 &&handle_OP_CALL8,
110 &&handle_OP_STATE,
111 &&handle_OP_GOTO,
112 &&handle_OP_AND_F,
113 &&handle_OP_OR_F,
114
115 &&handle_OP_BITAND_F,
116 &&handle_OP_BITOR_F,
117
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 NULL,
165
166 &&handle_OP_STORE_I,
167
168 NULL,
169 NULL,
170
171 &&handle_OP_ADD_I,
172 &&handle_OP_ADD_FI,
173 &&handle_OP_ADD_IF,
174
175 &&handle_OP_SUB_I,
176 &&handle_OP_SUB_FI,
177 &&handle_OP_SUB_IF,
178 &&handle_OP_CONV_ITOF,
179 &&handle_OP_CONV_FTOI,
180
181 NULL,
182 NULL,
183
184 &&handle_OP_LOAD_I,
185 &&handle_OP_STOREP_I,
186
187 NULL,
188 NULL,
189
190 &&handle_OP_BITAND_I,
191 &&handle_OP_BITOR_I,
192
193 &&handle_OP_MUL_I,
194 &&handle_OP_DIV_I,
195 &&handle_OP_EQ_I,
196 &&handle_OP_NE_I,
197
198 NULL,
199 NULL,
200
201 &&handle_OP_NOT_I,
202
203 &&handle_OP_DIV_VF,
204
205 NULL,
206 &&handle_OP_RSHIFT_I,
207 &&handle_OP_LSHIFT_I,
208
209 &&handle_OP_GLOBALADDRESS,
210 &&handle_OP_ADD_PIW,
211 &&handle_OP_LOADA_F,
212 &&handle_OP_LOADA_V,
213 &&handle_OP_LOADA_S,
214 &&handle_OP_LOADA_ENT,
215 &&handle_OP_LOADA_FLD,
216 &&handle_OP_LOADA_FNC,
217 &&handle_OP_LOADA_I,
218
219 &&handle_OP_STORE_P,
220 &&handle_OP_LOAD_P,
221
222 &&handle_OP_LOADP_F,
223 &&handle_OP_LOADP_V,
224 &&handle_OP_LOADP_S,
225 &&handle_OP_LOADP_ENT,
226 &&handle_OP_LOADP_FLD,
227 &&handle_OP_LOADP_FNC,
228 &&handle_OP_LOADP_I,
229
230 &&handle_OP_LE_I,
231 &&handle_OP_GE_I,
232 &&handle_OP_LT_I,
233 &&handle_OP_GT_I,
234
235 &&handle_OP_LE_IF,
236 &&handle_OP_GE_IF,
237 &&handle_OP_LT_IF,
238 &&handle_OP_GT_IF,
239
240 &&handle_OP_LE_FI,
241 &&handle_OP_GE_FI,
242 &&handle_OP_LT_FI,
243 &&handle_OP_GT_FI,
244
245 &&handle_OP_EQ_IF,
246 &&handle_OP_EQ_FI,
247
248 NULL,
249 NULL,
250 NULL,
251 NULL,
252
253 &&handle_OP_MUL_IF,
254 &&handle_OP_MUL_FI,
255 &&handle_OP_MUL_VI,
256
257 NULL,
258
259 &&handle_OP_DIV_IF,
260 &&handle_OP_DIV_FI,
261 &&handle_OP_BITAND_IF,
262 &&handle_OP_BITOR_IF,
263 &&handle_OP_BITAND_FI,
264 &&handle_OP_BITOR_FI,
265 &&handle_OP_AND_I,
266 &&handle_OP_OR_I,
267 &&handle_OP_AND_IF,
268 &&handle_OP_OR_IF,
269 &&handle_OP_AND_FI,
270 &&handle_OP_OR_FI,
271 &&handle_OP_NE_IF,
272 &&handle_OP_NE_FI,
273
274 &&handle_OP_GSTOREP_I,
275 &&handle_OP_GSTOREP_F,
276 &&handle_OP_GSTOREP_ENT,
277 &&handle_OP_GSTOREP_FLD,
278 &&handle_OP_GSTOREP_S,
279 &&handle_OP_GSTOREP_FNC,
280 &&handle_OP_GSTOREP_V,
281 &&handle_OP_GLOAD_I,
282 &&handle_OP_GLOAD_F,
283 &&handle_OP_GLOAD_FLD,
284 &&handle_OP_GLOAD_ENT,
285 &&handle_OP_GLOAD_S,
286 &&handle_OP_GLOAD_FNC,
287 &&handle_OP_BOUNDCHECK,
288
289 NULL,
290 NULL,
291 NULL,
292 NULL,
293
294 &&handle_OP_GLOAD_V,
295
296 NULL,
297 NULL,
298
299 NULL,
300 NULL,
301 NULL,
302 NULL,
303
304
305 NULL,
306 NULL,
307
308
309 &&handle_OP_LE_U,
310 &&handle_OP_LT_U,
311 &&handle_OP_DIV_U,
312 &&handle_OP_RSHIFT_U,
313 };
314#define DISPATCH_OPCODE() \
315 goto *dispatchtable[(++st)->op]
316#define HANDLE_OPCODE(opcode) handle_##opcode
317
318 DISPATCH_OPCODE(); // jump to first opcode
319#else // USE_COMPUTED_GOTOS
320#define DISPATCH_OPCODE() break
321#define HANDLE_OPCODE(opcode) case opcode
322
323#if PRVMSLOWINTERPRETER
324 {
325 if (prog->watch_global_type != ev_void)
326 {
327 prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global);
328 prog->xstatement = st + 1 - cached_statements;
329 PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, g);
330 }
331 if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
332 {
333 prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
334 prog->xstatement = st + 1 - cached_statements;
335 PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, g);
336 }
337 }
338#endif
339
340 while (1)
341 {
342 st++;
343#endif // USE_COMPUTED_GOTOS
344
345#if !USE_COMPUTED_GOTOS
346
347#if PRVMSLOWINTERPRETER
348 if (prog->trace)
349 PRVM_PrintStatement(prog, st);
350 if (prog->break_statement >= 0)
351 if ((st - cached_statements) == prog->break_statement)
352 {
353 prog->xstatement = st - cached_statements;
354 PRVM_Breakpoint(prog, prog->break_stack_index, "Breakpoint hit");
355 }
356#endif
357 switch (st->op)
358 {
359#endif
361 OPC->_float = OPA->_float + OPB->_float;
364 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
365 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
366 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
369 OPC->_float = OPA->_float - OPB->_float;
372 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
373 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
374 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
377 OPC->_float = OPA->_float * OPB->_float;
380 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
383 tempfloat = OPA->_float;
384 OPC->vector[0] = tempfloat * OPB->vector[0];
385 OPC->vector[1] = tempfloat * OPB->vector[1];
386 OPC->vector[2] = tempfloat * OPB->vector[2];
389 tempfloat = OPB->_float;
390 OPC->vector[0] = tempfloat * OPA->vector[0];
391 OPC->vector[1] = tempfloat * OPA->vector[1];
392 OPC->vector[2] = tempfloat * OPA->vector[2];
395 if( OPB->_float == 0.0f )
396 {
397 PRE_ERROR();
398 VM_Warning(prog, "Attempted division of %f by zero\n", OPA->_float);
399 if (prvm_gameplayfix_div0is0.integer)
400 {
401 OPC->_float = 0;
403 }
404 }
405 OPC->_float = OPA->_float / OPB->_float;
408 OPC->_float = (prvm_int_t)OPA->_float & (prvm_int_t)OPB->_float;
411 OPC->_float = (prvm_int_t)OPA->_float | (prvm_int_t)OPB->_float;
414 OPC->_float = OPA->_float >= OPB->_float;
417 OPC->_float = OPA->_float <= OPB->_float;
420 OPC->_float = OPA->_float > OPB->_float;
423 OPC->_float = OPA->_float < OPB->_float;
426 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
429 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
432 OPC->_float = !PRVM_FLOAT_IS_TRUE_FOR_INT(OPA->_int);
435 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
438 OPC->_float = !OPA->string || !*PRVM_GetString(prog, OPA->string);
441 OPC->_float = !OPA->function;
444 OPC->_float = (OPA->edict == 0);
447 OPC->_float = OPA->_float == OPB->_float;
450 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
453 OPC->_float = !strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
456 OPC->_float = OPA->_int == OPB->_int;
459 OPC->_float = OPA->function == OPB->function;
462 OPC->_float = OPA->_float != OPB->_float;
465 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
468 OPC->_float = strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
471 OPC->_float = OPA->_int != OPB->_int;
474 OPC->_float = OPA->function != OPB->function;
476
477 //==================
480 HANDLE_OPCODE(OP_STORE_FLD): // integers
481 HANDLE_OPCODE(OP_STORE_FNC): // pointers
482 OPB->_int = OPA->_int;
485 // refresh the garbage collection on the string - this guards
486 // against a certain sort of repeated migration to earlier
487 // points in the scan that could otherwise result in the string
488 // being freed for being unused
490 PRVM_GetString(prog, OPA->_int);
491 OPB->_int = OPA->_int;
494 OPB->ivector[0] = OPA->ivector[0];
495 OPB->ivector[1] = OPA->ivector[1];
496 OPB->ivector[2] = OPA->ivector[2];
498
501 HANDLE_OPCODE(OP_STOREP_FLD): // integers
502 HANDLE_OPCODE(OP_STOREP_FNC): // pointers
503 addr = OPB->_uint + OPC->_uint;
504 if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
505 {
506 // OK entity write.
507 ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
508 }
509 else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_1)
510 {
511 // OK global write.
512 ptr = (prvm_eval_t *)(global1 + ofs);
513 }
514 else if ((ofs = addr - cached_vmentity0start) < cached_entityfields)
515 {
516 if (!cached_allowworldwrites)
517 {
518 PRE_ERROR();
519 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %"PRVM_PRIi"+%"PRVM_PRIi")\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
520 // Perform entity write anyway.
521 }
522 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
523 }
524 else
525 {
526 PRE_ERROR();
527 prog->error_cmd("%s attempted to write to an out of bounds address %"PRVM_PRIu"+%"PRVM_PRIi"", prog->name, OPB->_uint, OPC->_int);
528 goto cleanup;
529 }
530 ptr->_int = OPA->_int;
533 addr = OPB->_uint + OPC->_uint;
534 if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
535 {
536 // OK entity write.
537 ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
538 }
539 else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_1)
540 {
541 // OK global write.
542 ptr = (prvm_eval_t *)(global1 + ofs);
543 }
544 else if ((ofs = addr - cached_vmentity0start) < cached_entityfields)
545 {
546 if (!cached_allowworldwrites)
547 {
548 PRE_ERROR();
549 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %"PRVM_PRIi"+%"PRVM_PRIi")\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
550 // Perform entity write anyway.
551 }
552 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
553 }
554 else
555 {
556 PRE_ERROR();
557 prog->error_cmd("%s attempted to write to an out of bounds address %"PRVM_PRIu"+%"PRVM_PRIi"", prog->name, OPB->_uint, OPC->_int);
558 goto cleanup;
559 }
560 // refresh the garbage collection on the string - this guards
561 // against a certain sort of repeated migration to earlier
562 // points in the scan that could otherwise result in the string
563 // being freed for being unused
565 PRVM_GetString(prog, OPA->_int);
566 ptr->_int = OPA->_int;
569 addr = OPB->_uint + OPC->_uint;
570 if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields_2)
571 {
572 // OK entity write.
573 ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
574 }
575 else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_3)
576 {
577 // OK global write.
578 ptr = (prvm_eval_t *)(global1 + ofs);
579 }
580 else if ((ofs = addr - cached_vmentity0start) < cached_entityfields_2)
581 {
582 if (!cached_allowworldwrites)
583 {
584 PRE_ERROR();
585 VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %"PRVM_PRIi"+%"PRVM_PRIi")\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
586 // Perform entity write anyway.
587 }
588 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
589 }
590 else
591 {
592 PRE_ERROR();
593 prog->error_cmd("%s attempted to write to an out of bounds address %"PRVM_PRIu"+%"PRVM_PRIi"", prog->name, OPB->_uint, OPC->_int);
594 goto cleanup;
595 }
596 ptr->ivector[0] = OPA->ivector[0];
597 ptr->ivector[1] = OPA->ivector[1];
598 ptr->ivector[2] = OPA->ivector[2];
600
602 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
603 {
604 PRE_ERROR();
605 prog->error_cmd("%s attempted to address an out of bounds edict number", prog->name);
606 goto cleanup;
607 }
608 if (OPB->_uint >= cached_entityfields)
609 {
610 PRE_ERROR();
611 prog->error_cmd("%s attempted to address an invalid field (%"PRVM_PRIu") in an edict", prog->name, OPB->_uint);
612 goto cleanup;
613 }
614#if 0
615 if (OPA->edict == 0 && !cached_allowworldwrites)
616 {
617 PRE_ERROR();
618 prog->error_cmd("Forbidden assignment to world (edictnum 0) in %s", prog->name);
619 goto cleanup;
620 }
621#endif
622 OPC->_int = cached_vmentity0start + OPA->edict * cached_entityfields + OPB->_int;
624
630 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
631 {
632 PRE_ERROR();
633 prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
634 goto cleanup;
635 }
636 if (OPB->_uint >= cached_entityfields)
637 {
638 PRE_ERROR();
639 prog->error_cmd("%s attempted to read an invalid field in an edict (%"PRVM_PRIu")", prog->name, OPB->_uint);
640 goto cleanup;
641 }
642 ed = PRVM_PROG_TO_EDICT(OPA->edict);
643 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
646 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
647 {
648 PRE_ERROR();
649 prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
650 goto cleanup;
651 }
652 if (OPB->_uint >= cached_entityfields)
653 {
654 PRE_ERROR();
655 prog->error_cmd("%s attempted to read an invalid field in an edict (%"PRVM_PRIu")", prog->name, OPB->_uint);
656 goto cleanup;
657 }
658 ed = PRVM_PROG_TO_EDICT(OPA->edict);
659 OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int;
660 // refresh the garbage collection on the string - this guards
661 // against a certain sort of repeated migration to earlier
662 // points in the scan that could otherwise result in the string
663 // being freed for being unused
665 PRVM_GetString(prog, OPC->_int);
667
669 if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
670 {
671 PRE_ERROR();
672 prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
673 goto cleanup;
674 }
675 if (OPB->_uint >= cached_entityfields_2)
676 {
677 PRE_ERROR();
678 prog->error_cmd("%s attempted to read an invalid field in an edict (%"PRVM_PRIu")", prog->name, OPB->_uint);
679 goto cleanup;
680 }
681 ed = PRVM_PROG_TO_EDICT(OPA->edict);
682 ptr = (prvm_eval_t *)(ed->fields.ip + OPB->_int);
683 OPC->ivector[0] = ptr->ivector[0];
684 OPC->ivector[1] = ptr->ivector[1];
685 OPC->ivector[2] = ptr->ivector[2];
687
688 //==================
689
691 //spike FIXME -- dp redefined IFNOT[_I] as IFNOT_F, which breaks if(0x80000000)
692 //spike FIXME -- you should add separate IFNOT_I/IFNOT_F opcodes and remap IFNOT_I to ITNOT_F in v6 progs for compat.
693 if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
694 // TODO add an "int-if", and change this one to OPA->_float
695 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
696 // and entity, string, field values can never have that value
697 {
699 st += st->operand[1] - 1; // offset the st++
700 startst = st;
701 // no bounds check needed, it is done when loading progs
702 if (++jumpcount == 10000000 && prvm_runawaycheck)
703 {
704 prog->xstatement = st - cached_statements;
705 PRVM_Profile(prog, 1<<30, 1000000, 0);
706 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
707 }
708 }
710
712 //spike FIXME -- dp redefined IF[_I] as IF_F
713 // TODO: plan is:
714 // - Add IF_F, IFNOT_F.
715 // - Rename this to IF_I, IFNOT_I.
716 // - Add sv_gameplayfix variable to remap IF_I and IFNOT_I to IF_F and IFNOT_F on progs load.
717 // - Define this fix for Nexuiz.
718 // - Add generation of IF_F, IFNOT_F instructions to gmqcc.
719 // - Move Xonotic to that.
720 if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
721 // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
722 // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
723 // and entity, string, field values can never have that value
724 {
726 st += st->operand[1] - 1; // offset the st++
727 startst = st;
728 // no bounds check needed, it is done when loading progs
729 if (++jumpcount == 10000000 && prvm_runawaycheck)
730 {
731 prog->xstatement = st - cached_statements;
732 PRVM_Profile(prog, 1<<30, 0.01, 0);
733 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
734 }
735 }
737
740 st += st->operand[0] - 1; // offset the st++
741 startst = st;
742 // no bounds check needed, it is done when loading progs
743 if (++jumpcount == 10000000 && prvm_runawaycheck)
744 {
745 prog->xstatement = st - cached_statements;
746 PRVM_Profile(prog, 1<<30, 0.01, 0);
747 prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
748 }
750
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
766 startst = st;
767 prog->xstatement = st - cached_statements;
768 prog->argc = st->op - OP_CALL0;
769 if (!OPA->function)
770 {
771 prog->error_cmd("NULL function in %s", prog->name);
772 }
773
774 if(!OPA->function || OPA->function < 0 || OPA->function >= prog->numfunctions)
775 {
776 PRE_ERROR();
777 prog->error_cmd("%s attempted CALL outside the program", prog->name);
778 goto cleanup;
779 }
780
781 enterfunc = &prog->functions[OPA->function];
782 if (enterfunc->callcount++ == 0 && (prvm_coverage.integer & 1))
783 PRVM_FunctionCoverageEvent(prog, enterfunc);
784
785 if (enterfunc->first_statement < 0)
786 {
787 // negative first_statement values are built in functions
788 int builtinnumber = -enterfunc->first_statement;
789 prog->xfunction->builtinsprofile++;
790 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
791 {
792 prog->builtins[builtinnumber](prog);
793#ifdef PRVMTIMEPROFILING
794 tm = Sys_DirtyTime();
795 enterfunc->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
796 prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
797 starttm = tm;
798#endif
799 // builtins may cause ED_Alloc() to be called, update cached variables
801 // these do not change
802 //cached_statements = prog->statements;
803 //cached_allowworldwrites = prog->allowworldwrites;
804 //cached_flag = prog->flag;
805 // if prog->trace changed we need to change interpreter path
806 if (prog->trace != cachedpr_trace)
807 goto chooseexecprogram;
808 }
809 else
810 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);
811 }
812 else
813 st = cached_statements + PRVM_EnterFunction(prog, enterfunc);
814 startst = st;
816
819#ifdef PRVMTIMEPROFILING
820 tm = Sys_DirtyTime();
821 prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
822 starttm = tm;
823#endif
825 prog->xstatement = st - cached_statements;
826
827 prog->globals.ip[OFS_RETURN ] = prog->globals.ip[st->operand[0] ];
828 prog->globals.ip[OFS_RETURN+1] = prog->globals.ip[st->operand[0]+1];
829 prog->globals.ip[OFS_RETURN+2] = prog->globals.ip[st->operand[0]+2];
830
831 st = cached_statements + PRVM_LeaveFunction(prog);
832 startst = st;
833 if (prog->depth <= exitdepth)
834 goto cleanup; // all done
836
838 if(cached_flag & PRVM_OP_STATE)
839 {
842 PRVM_gameedictfloat(ed,frame) = OPA->_float;
843 PRVM_gameedictfunction(ed,think) = OPB->function;
844 }
845 else
846 {
847 PRE_ERROR();
848 prog->xstatement = st - cached_statements;
849 prog->error_cmd("OP_STATE not supported by %s", prog->name);
850 }
852
854 OPC->_int = OPA->_int + OPB->_int;
857 OPC->_float = ((prvm_vec_t) OPA->_int) + OPB->_float;
860 OPC->_float = OPA->_float + (prvm_vec_t) OPB->_int;
863 OPC->_int = OPA->_int - OPB->_int;
866 OPC->_float = ((prvm_vec_t) OPA->_int) - OPB->_float;
869 OPC->_float = OPA->_float - (prvm_vec_t) OPB->_int;
872 OPC->_int = OPA->_int * OPB->_int;
875 OPC->_float = ((prvm_vec_t) OPA->_int) * OPB->_float;
878 OPC->_float = OPA->_float * (prvm_vec_t) OPB->_int;
881 OPC->vector[0] = (prvm_vec_t) OPB->_int * OPA->vector[0];
882 OPC->vector[1] = (prvm_vec_t) OPB->_int * OPA->vector[1];
883 OPC->vector[2] = (prvm_vec_t) OPB->_int * OPA->vector[2];
886 if( OPB->_float == 0.0f )
887 {
888 PRE_ERROR();
889 VM_Warning(prog, "Attempted division of '%f %f %f' by zero\n", OPA->vector[0], OPA->vector[1], OPA->vector[2]);
890 if (prvm_gameplayfix_div0is0.integer)
891 {
892 OPC->vector[0] = 0;
893 OPC->vector[1] = 0;
894 OPC->vector[2] = 0;
896 }
897 }
898 tempfloat = OPB->_float;
899 OPC->vector[0] = OPA->vector[0] / tempfloat;
900 OPC->vector[1] = OPA->vector[1] / tempfloat;
901 OPC->vector[2] = OPA->vector[2] / tempfloat;
904 // NOTE: This also catches the second kind of division that can trap, namely, -2147483648 / -1,
905 // whose result is not representable as int32_t and raises the same CPU exception.
906 if( OPB->_int != 0 && (OPB->_int != -1 || OPA->_int != PRVM_INT_MIN) )
907 {
908 OPC->_int = OPA->_int / OPB->_int;
909 }
910 else
911 {
912 PRE_ERROR();
913 VM_Warning(prog, "Attempted division of %"PRVM_PRIi" by %"PRVM_PRIi"\n", OPA->_int, OPB->_int);
914 OPC->_int = 0;
915 }
918 if( OPB->_float == 0.0f )
919 {
920 PRE_ERROR();
921 VM_Warning(prog, "Attempted division of %"PRVM_PRIi" by zero\n", OPA->_int);
922 if (prvm_gameplayfix_div0is0.integer)
923 {
924 OPC->_float = 0;
926 }
927 }
928 OPC->_float = ((prvm_vec_t) OPA->_int) / OPB->_float;
931 if( OPB->_int == 0 )
932 {
933 PRE_ERROR();
934 VM_Warning(prog, "Attempted division of %f by zero\n", OPA->_float);
935 if (prvm_gameplayfix_div0is0.integer)
936 {
937 OPC->_float = 0;
939 }
940 }
941 OPC->_float = OPA->_float / (prvm_vec_t) OPB->_int;
944 OPC->_float = OPA->_int;
947 OPC->_int = OPA->_float;
950 OPC->_int = OPA->_int & OPB->_int;
953 OPC->_int = OPA->_int | OPB->_int;
956 OPC->_int = OPA->_int & (prvm_int_t)OPB->_float;
959 OPC->_int = OPA->_int | (prvm_int_t)OPB->_float;
962 OPC->_int = (prvm_int_t)OPA->_float & OPB->_int;
965 OPC->_int = (prvm_int_t)OPA->_float | OPB->_int;
968 OPC->_int = OPA->_int >= OPB->_int;
971 OPC->_int = OPA->_int <= OPB->_int;
974 OPC->_int = OPA->_int > OPB->_int;
977 OPC->_int = OPA->_int < OPB->_int;
980 OPC->_int = OPA->_int && OPB->_int;
983 OPC->_int = OPA->_int || OPB->_int;
986 OPC->_int = (prvm_vec_t)OPA->_int >= OPB->_float;
989 OPC->_int = (prvm_vec_t)OPA->_int <= OPB->_float;
992 OPC->_int = (prvm_vec_t)OPA->_int > OPB->_float;
995 OPC->_int = (prvm_vec_t)OPA->_int < OPB->_float;
998 OPC->_int = (prvm_vec_t)OPA->_int && OPB->_float;
1001 OPC->_int = (prvm_vec_t)OPA->_int || OPB->_float;
1004 OPC->_int = OPA->_float >= (prvm_vec_t)OPB->_int;
1007 OPC->_int = OPA->_float <= (prvm_vec_t)OPB->_int;
1010 OPC->_int = OPA->_float > (prvm_vec_t)OPB->_int;
1013 OPC->_int = OPA->_float < (prvm_vec_t)OPB->_int;
1016 OPC->_int = OPA->_float && (prvm_vec_t)OPB->_int;
1019 OPC->_int = OPA->_float || (prvm_vec_t)OPB->_int;
1022 OPC->_int = !OPA->_int;
1025 OPC->_int = OPA->_int == OPB->_int;
1028 OPC->_int = (prvm_vec_t)OPA->_int == OPB->_float;
1031 OPC->_int = OPA->_float == (prvm_vec_t)OPB->_int;
1034 OPC->_int = OPA->_int != OPB->_int;
1037 OPC->_int = (prvm_vec_t)OPA->_int != OPB->_float;
1040 OPC->_int = OPA->_float != (prvm_vec_t)OPB->_int;
1044 OPB->_int = OPA->_int;
1047#if PRBOUNDSCHECK
1048 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
1049 {
1050 PRE_ERROR();
1051 prog->error_cmd("%s attempted to write to an out of bounds edict", prog->name);
1052 goto cleanup;
1053 }
1054#endif
1055 ptr = (prvm_eval_t *)(prog->edictsfields.ip + OPB->_int);
1056 ptr->_int = OPA->_int;
1059#if PRBOUNDSCHECK
1060 if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
1061 {
1062 PRE_ERROR();
1063 prog->error_cmd("%s attempted to read an out of bounds edict number", prog->name);
1064 goto cleanup;
1065 }
1066 if (OPB->_int < 0 || OPB->_int >= progs->entityfields.ip)
1067 {
1068 PRE_ERROR();
1069 prog->error_cmd("%s attempted to read an invalid field in an edict", prog->name);
1070 goto cleanup;
1071 }
1072#endif
1073 ed = PRVM_PROG_TO_EDICT(OPA->edict);
1074 OPC->_int = ((prvm_eval_t *)((int *)ed->fields.ip + OPB->_int))->_int;
1076
1080 HANDLE_OPCODE(OP_GSTOREP_FLD): // integers
1082 HANDLE_OPCODE(OP_GSTOREP_FNC): // pointers
1083 if (OPB->_int <= 0 || OPB->_int >= prog->numglobals)
1084 {
1085 PRE_ERROR();
1086 prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
1087 goto cleanup;
1088 }
1089 prog->globals.ip[OPB->_int] = OPA->_int;
1092 if (OPB->_int <= 0 || OPB->_int + 2 >= prog->numglobals)
1093 {
1094 PRE_ERROR();
1095 prog->error_cmd("%s attempted to write to an invalid indexed global", prog->name);
1096 goto cleanup;
1097 }
1098 prog->globals.ip[OPB->_int ] = OPA->ivector[0];
1099 prog->globals.ip[OPB->_int+1] = OPA->ivector[1];
1100 prog->globals.ip[OPB->_int+2] = OPA->ivector[2];
1102
1109 if (OPA->_int < 0 || OPA->_int >= prog->numglobals)
1110 {
1111 PRE_ERROR();
1112 prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1113 goto cleanup;
1114 }
1115 OPC->_int = prog->globals.ip[OPA->_int];
1117
1119 if (OPA->_int < 0 || OPA->_int + 2 >= prog->numglobals)
1120 {
1121 PRE_ERROR();
1122 prog->error_cmd("%s attempted to read an invalid indexed global", prog->name);
1123 goto cleanup;
1124 }
1125 OPC->ivector[0] = prog->globals.ip[OPA->_int ];
1126 OPC->ivector[1] = prog->globals.ip[OPA->_int+1];
1127 OPC->ivector[2] = prog->globals.ip[OPA->_int+2];
1129
1131 if ((unsigned int)OPA->_int < (unsigned int)st->operand[2] || (unsigned int)OPA->_int >= (unsigned int)st->operand[1])
1132 {
1133 PRE_ERROR();
1134 prog->error_cmd("Progs boundcheck failed in %s, value is < %"PRVM_PRIi" or >= %"PRVM_PRIi"", prog->name, OPC->_int, OPB->_int);
1135 goto cleanup;
1136 }
1138
1139 // FTEQW pointer instructions.
1141 OPC->_int = PRVM_GLOBALSBASE + st->operand[0] + 1 * OPB->_int;
1144 OPC->_int = OPA->_int + 1 * OPB->_int;
1151 ofs = st->operand[0] + OPB->_int;
1152 if (ofs >= cached_vmglobals)
1153 {
1154 PRE_ERROR();
1155 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)st->operand[0], OPB->_int);
1156 goto cleanup;
1157 }
1158 src = (prvm_eval_t *)&globals[ofs];
1159 OPC->_int = src->_int;
1162 ofs = st->operand[0] + OPB->_int;
1163 if (ofs >= cached_vmglobals)
1164 {
1165 PRE_ERROR();
1166 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)st->operand[0], OPB->_int);
1167 goto cleanup;
1168 }
1169 src = (prvm_eval_t *)&globals[ofs];
1170 // refresh the garbage collection on the string - this guards
1171 // against a certain sort of repeated migration to earlier
1172 // points in the scan that could otherwise result in the string
1173 // being freed for being unused
1175 PRVM_GetString(prog, src->_int);
1176 OPC->_int = src->_int;
1179 ofs = st->operand[0] + OPB->_int;
1180 if (ofs >= cached_vmglobals_2)
1181 {
1182 PRE_ERROR();
1183 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)st->operand[0], OPB->_int);
1184 goto cleanup;
1185 }
1186 src = (prvm_eval_t *)&globals[ofs];
1187 OPC->ivector[0] = src->ivector[0];
1188 OPC->ivector[1] = src->ivector[1];
1189 OPC->ivector[2] = src->ivector[2];
1193 HANDLE_OPCODE(OP_LOADP_FLD): // integers
1194 HANDLE_OPCODE(OP_LOADP_FNC): // pointers
1196 addr = OPA->_uint + OPB->_uint;
1197 if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea)
1198 {
1199 // OK entity write.
1200 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
1201 }
1202 else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals)
1203 {
1204 // OK global write.
1205 ptr = (prvm_eval_t *)(globals + ofs);
1206 }
1207 else
1208 {
1209 PRE_ERROR();
1210 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)OPA->_int, OPB->_int);
1211 goto cleanup;
1212 }
1213 OPC->_int = ptr->_int;
1216 addr = OPA->_uint + OPB->_uint;
1217 if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea)
1218 {
1219 // OK entity write.
1220 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
1221 }
1222 else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals)
1223 {
1224 // OK global write.
1225 ptr = (prvm_eval_t *)(globals + ofs);
1226 }
1227 else
1228 {
1229 PRE_ERROR();
1230 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)OPA->_int, OPB->_int);
1231 goto cleanup;
1232 }
1234 PRVM_GetString(prog, ptr->_int);
1235 OPC->_int = ptr->_int;
1238 addr = OPA->_uint + OPB->_uint;
1239 if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea_2)
1240 {
1241 // OK entity write.
1242 ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
1243 }
1244 else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals_2)
1245 {
1246 // OK global write.
1247 ptr = (prvm_eval_t *)(globals + ofs);
1248 }
1249 else
1250 {
1251 PRE_ERROR();
1252 prog->error_cmd("%s attempted to read from an out of bounds address %u+%"PRVM_PRIi"", prog->name, (unsigned int)OPA->_int, OPB->_int);
1253 goto cleanup;
1254 }
1255 OPC->ivector[0] = ptr->ivector[0];
1256 OPC->ivector[1] = ptr->ivector[1];
1257 OPC->ivector[2] = ptr->ivector[2];
1260 OPC->_int = OPA->_int >> OPB->_int;
1263 OPC->_int = OPA->_int << OPB->_int;
1266 OPC->_int = (OPA->_uint <= OPB->_uint);
1269 OPC->_int = (OPA->_uint < OPB->_uint);
1272 if( OPB->_uint != 0 )
1273 {
1274 OPC->_uint = OPA->_uint / OPB->_uint;
1275 }
1276 else
1277 {
1278 PRE_ERROR();
1279 VM_Warning(prog, "Attempted division of %"PRVM_PRIu" by zero\n", OPA->_uint);
1280 OPC->_uint = 0;
1281 }
1284 OPC->_uint = OPA->_uint >> OPB->_uint;
1286
1287#if !USE_COMPUTED_GOTOS
1288 default:
1289 PRE_ERROR();
1290 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);
1291 goto cleanup;
1292 }
1293#if PRVMSLOWINTERPRETER
1294 {
1295 if (prog->watch_global_type != ev_void)
1296 {
1297 prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global);
1298 prog->xstatement = st - cached_statements;
1299 PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, g);
1300 }
1301 if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts)
1302 {
1303 prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field);
1304 prog->xstatement = st - cached_statements;
1305 PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, g);
1306 }
1307 }
1308#endif
1309 }
1310#endif // !USE_COMPUTED_GOTOS
1311
1312#undef DISPATCH_OPCODE
1313#undef HANDLE_OPCODE
1314#undef USE_COMPUTED_GOTOS
1315#undef PRE_ERROR
1316#undef ADVANCE_PROFILE_BEFORE_JUMP
qbool prvm_runawaycheck
Definition prvm_edict.c:60
entity self
float time
float nextthink
float frame
@ OP_SUB_FI
Definition pr_comp.h:168
@ OP_STOREP_S
Definition pr_comp.h:87
@ OP_NE_E
Definition pr_comp.h:66
@ OP_LOADA_ENT
Definition pr_comp.h:196
@ OP_AND_I
Definition pr_comp.h:237
@ OP_LE_FI
Definition pr_comp.h:217
@ OP_ADD_I
Definition pr_comp.h:164
@ OP_GSTOREP_FLD
Definition pr_comp.h:248
@ OP_STORE_V
Definition pr_comp.h:80
@ OP_GSTOREP_FNC
Definition pr_comp.h:250
@ OP_RSHIFT_U
Definition pr_comp.h:276
@ OP_SUB_F
Definition pr_comp.h:56
@ OP_LOAD_ENT
Definition pr_comp.h:75
@ OP_LOAD_F
Definition pr_comp.h:72
@ OP_LT_FI
Definition pr_comp.h:219
@ OP_GE_I
Definition pr_comp.h:210
@ OP_DIV_I
Definition pr_comp.h:181
@ OP_LT_I
Definition pr_comp.h:211
@ OP_IF
Definition pr_comp.h:97
@ OP_LOAD_FLD
Definition pr_comp.h:76
@ OP_MUL_VI
Definition pr_comp.h:229
@ OP_BITOR_F
Definition pr_comp.h:113
@ OP_STOREP_V
Definition pr_comp.h:86
@ OP_GLOAD_ENT
Definition pr_comp.h:256
@ OP_GLOAD_F
Definition pr_comp.h:254
@ OP_EQ_FI
Definition pr_comp.h:222
@ OP_GSTOREP_I
Definition pr_comp.h:245
@ OP_MUL_VF
Definition pr_comp.h:52
@ OP_ADD_IF
Definition pr_comp.h:166
@ OP_GLOAD_FLD
Definition pr_comp.h:255
@ OP_NOT_I
Definition pr_comp.h:186
@ OP_LOADA_I
Definition pr_comp.h:199
@ OP_GSTOREP_F
Definition pr_comp.h:246
@ OP_CALL8
Definition pr_comp.h:107
@ OP_CONV_ITOF
Definition pr_comp.h:170
@ OP_DIV_F
Definition pr_comp.h:53
@ OP_GT_F
Definition pr_comp.h:71
@ OP_DIV_IF
Definition pr_comp.h:231
@ OP_MUL_I
Definition pr_comp.h:180
@ OP_OR_FI
Definition pr_comp.h:242
@ OP_CALL6
Definition pr_comp.h:105
@ OP_ADD_V
Definition pr_comp.h:55
@ OP_STOREP_ENT
Definition pr_comp.h:88
@ OP_STOREP_FNC
Definition pr_comp.h:90
@ OP_AND_IF
Definition pr_comp.h:239
@ OP_CALL5
Definition pr_comp.h:104
@ OP_LOADP_V
Definition pr_comp.h:203
@ OP_NE_FNC
Definition pr_comp.h:67
@ OP_NE_S
Definition pr_comp.h:65
@ OP_BITOR_FI
Definition pr_comp.h:236
@ OP_LT_IF
Definition pr_comp.h:215
@ OP_STORE_P
Definition pr_comp.h:200
@ OP_CONV_FTOI
Definition pr_comp.h:171
@ OP_LOADA_FNC
Definition pr_comp.h:198
@ OP_LOADP_ENT
Definition pr_comp.h:205
@ OP_STORE_I
Definition pr_comp.h:161
@ OP_SUB_V
Definition pr_comp.h:57
@ OP_BITAND_FI
Definition pr_comp.h:235
@ OP_NOT_ENT
Definition pr_comp.h:95
@ OP_GSTOREP_S
Definition pr_comp.h:249
@ OP_GLOAD_I
Definition pr_comp.h:253
@ OP_OR_IF
Definition pr_comp.h:240
@ OP_STOREP_I
Definition pr_comp.h:175
@ OP_DIV_FI
Definition pr_comp.h:232
@ OP_EQ_FNC
Definition pr_comp.h:62
@ OP_LE_U
Definition pr_comp.h:273
@ OP_STOREP_FLD
Definition pr_comp.h:89
@ OP_MUL_FV
Definition pr_comp.h:51
@ OP_LOAD_P
Definition pr_comp.h:201
@ OP_NE_V
Definition pr_comp.h:64
@ OP_STORE_FLD
Definition pr_comp.h:83
@ OP_GLOBALADDRESS
Definition pr_comp.h:191
@ OP_ADD_PIW
Definition pr_comp.h:192
@ OP_CALL1
Definition pr_comp.h:100
@ OP_EQ_I
Definition pr_comp.h:182
@ OP_EQ_V
Definition pr_comp.h:59
@ OP_STORE_ENT
Definition pr_comp.h:82
@ OP_MUL_IF
Definition pr_comp.h:227
@ OP_GSTOREP_ENT
Definition pr_comp.h:247
@ OP_GT_IF
Definition pr_comp.h:216
@ OP_NE_IF
Definition pr_comp.h:243
@ OP_ADD_F
Definition pr_comp.h:54
@ OP_LT_F
Definition pr_comp.h:70
@ OP_RSHIFT_I
Definition pr_comp.h:189
@ OP_LOADP_S
Definition pr_comp.h:204
@ OP_MUL_FI
Definition pr_comp.h:228
@ OP_LOADA_F
Definition pr_comp.h:193
@ OP_GE_F
Definition pr_comp.h:69
@ OP_GE_IF
Definition pr_comp.h:214
@ OP_DIV_U
Definition pr_comp.h:275
@ OP_LE_I
Definition pr_comp.h:209
@ OP_LE_F
Definition pr_comp.h:68
@ OP_LOADP_I
Definition pr_comp.h:208
@ OP_BITAND_F
Definition pr_comp.h:112
@ OP_LE_IF
Definition pr_comp.h:213
@ OP_ADD_FI
Definition pr_comp.h:165
@ OP_GE_FI
Definition pr_comp.h:218
@ OP_AND_F
Definition pr_comp.h:110
@ OP_CALL0
Definition pr_comp.h:99
@ OP_LOADP_FLD
Definition pr_comp.h:206
@ OP_NE_F
Definition pr_comp.h:63
@ OP_NOT_F
Definition pr_comp.h:92
@ OP_STORE_S
Definition pr_comp.h:81
@ OP_LOAD_S
Definition pr_comp.h:74
@ OP_OR_I
Definition pr_comp.h:238
@ OP_CALL4
Definition pr_comp.h:103
@ OP_EQ_E
Definition pr_comp.h:61
@ OP_DIV_VF
Definition pr_comp.h:187
@ OP_STOREP_F
Definition pr_comp.h:85
@ OP_SUB_IF
Definition pr_comp.h:169
@ OP_LSHIFT_I
Definition pr_comp.h:190
@ OP_CALL2
Definition pr_comp.h:101
@ OP_GLOAD_V
Definition pr_comp.h:264
@ OP_MUL_V
Definition pr_comp.h:50
@ OP_GLOAD_S
Definition pr_comp.h:257
@ OP_LOADA_FLD
Definition pr_comp.h:197
@ OP_SUB_I
Definition pr_comp.h:167
@ OP_NE_FI
Definition pr_comp.h:244
@ OP_LOADP_F
Definition pr_comp.h:202
@ OP_STATE
Definition pr_comp.h:108
@ OP_GT_I
Definition pr_comp.h:212
@ OP_LOAD_I
Definition pr_comp.h:174
@ OP_LOADA_V
Definition pr_comp.h:194
@ OP_LOADA_S
Definition pr_comp.h:195
@ OP_CALL3
Definition pr_comp.h:102
@ OP_RETURN
Definition pr_comp.h:91
@ OP_OR_F
Definition pr_comp.h:111
@ OP_ADDRESS
Definition pr_comp.h:78
@ OP_EQ_IF
Definition pr_comp.h:221
@ OP_BITAND_I
Definition pr_comp.h:178
@ OP_EQ_F
Definition pr_comp.h:58
@ OP_DONE
Definition pr_comp.h:48
@ OP_NOT_V
Definition pr_comp.h:93
@ OP_BOUNDCHECK
Definition pr_comp.h:259
@ OP_AND_FI
Definition pr_comp.h:241
@ OP_GSTOREP_V
Definition pr_comp.h:251
@ OP_EQ_S
Definition pr_comp.h:60
@ OP_BITOR_IF
Definition pr_comp.h:234
@ OP_LOAD_FNC
Definition pr_comp.h:77
@ OP_NE_I
Definition pr_comp.h:183
@ OP_GT_FI
Definition pr_comp.h:220
@ OP_NOT_FNC
Definition pr_comp.h:96
@ OP_LOAD_V
Definition pr_comp.h:73
@ OP_GOTO
Definition pr_comp.h:109
@ OP_GLOAD_FNC
Definition pr_comp.h:258
@ OP_BITAND_IF
Definition pr_comp.h:233
@ OP_CALL7
Definition pr_comp.h:106
@ OP_STORE_FNC
Definition pr_comp.h:84
@ OP_LT_U
Definition pr_comp.h:274
@ OP_BITOR_I
Definition pr_comp.h:179
@ OP_MUL_F
Definition pr_comp.h:49
@ OP_LOADP_FNC
Definition pr_comp.h:207
@ OP_NOT_S
Definition pr_comp.h:94
@ OP_STORE_F
Definition pr_comp.h:79
@ OP_IFNOT
Definition pr_comp.h:98
#define OFS_RETURN
Definition pr_comp.h:33
@ ev_void
Definition pr_comp.h:29
#define PRVM_FLOAT_IS_TRUE_FOR_INT(x)
Definition progs.h:35
#define PRVM_gameedictfloat(ed, fieldname)
Definition progsvm.h:160
#define PRVM_gameedictfunction(ed, fieldname)
Definition progsvm.h:164
#define PRVM_OP_STATE
Definition progsvm.h:238
void PRVM_Watchpoint(prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n)
void VM_Warning(prvm_prog_t *prog, const char *fmt,...) DP_FUNC_PRINTF(2)
Definition prvm_cmds.c:25
#define PRVM_gameglobaledict(fieldname)
Definition progsvm.h:168
const char * PRVM_GetString(prvm_prog_t *prog, int num)
void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text)
#define PRVM_gameglobalfloat(fieldname)
Definition progsvm.h:165
#define PRVM_PROG_TO_EDICT(n)
Definition progsvm.h:877
void PRVM_Profile(prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
Definition prvm_exec.c:539
#define PRVM_GLOBALFIELDVALUE(fieldoffset)
Definition progsvm.h:215
mdef_t * PRVM_ED_FieldAtOfs(prvm_prog_t *prog, unsigned int ofs)
Definition prvm_edict.c:357
#define PRVM_EDICTFIELDVALUE(ed, fieldoffset)
Definition progsvm.h:209
cvar_t prvm_coverage
Definition prvm_edict.c:39
cvar_t prvm_gameplayfix_div0is0
Definition prvm_edict.c:57
cvar_t prvm_garbagecollection_enable
Definition prvm_edict.c:48
#define OPC
Definition prvm_exec.c:945
#define OPA
Definition prvm_exec.c:943
#define CACHE_CHANGING(DECLARE)
Definition prvm_exec.c:971
static void PRVM_FunctionCoverageEvent(prvm_prog_t *prog, mfunction_t *func)
Definition prvm_exec.c:919
#define PRVM_GLOBALSBASE
Definition prvm_exec.c:951
static int PRVM_EnterFunction(prvm_prog_t *prog, mfunction_t *f)
Definition prvm_exec.c:799
static int PRVM_LeaveFunction(prvm_prog_t *prog)
Definition prvm_exec.c:845
#define NO_DECLARE(t)
Definition prvm_exec.c:981
static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
Definition prvm_exec.c:329
#define OPB
Definition prvm_exec.c:944
#define PRE_ERROR()
prvm_uint_t ofs
prvm_eval_t * src
prvm_uint_t addr
#define HANDLE_OPCODE(opcode)
#define ADVANCE_PROFILE_BEFORE_JUMP()
#define DISPATCH_OPCODE()
#define FLOAT_IS_TRUE_FOR_INT(x)
Definition qdefs.h:193
#define NULL
Definition qtypes.h:12
uint32_t prvm_uint_t
Definition qtypes.h:57
#define PRVM_PRIu
Definition qtypes.h:59
#define PRVM_INT_MIN
Definition qtypes.h:60
#define PRVM_PRIi
Definition qtypes.h:58
float prvm_vec_t
Definition qtypes.h:55
int32_t prvm_int_t
Definition qtypes.h:56
dp_FragColor g
Definition cvar.h:66
double Sys_DirtyTime(void)
Definition sys_shared.c:417