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