1 /*
2 	#FILENAME#
3 
4 	#DESCRIPTION#
5 
6 	Copyright (C) 2001 #AUTHOR#
7 
8 	Author: #AUTHOR#
9 	Date: #DATE#
10 
11 	This program is free software; you can redistribute it and/or
12 	modify it under the terms of the GNU General Public License
13 	as published by the Free Software Foundation; either version 2
14 	of the License, or (at your option) any later version.
15 
16 	This program is distributed in the hope that it will be useful,
17 	but WITHOUT ANY WARRANTY; without even the implied warranty of
18 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 	See the GNU General Public License for more details.
21 
22 	You should have received a copy of the GNU General Public License
23 	along with this program; if not, write to:
24 
25 		Free Software Foundation, Inc.
26 		59 Temple Place - Suite 330
27 		Boston, MA  02111-1307, USA
28 
29 */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 
34 #ifdef HAVE_STRING_H
35 # include "string.h"
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include "strings.h"
39 #endif
40 
41 #include "QF/cvar.h"
42 #include "QF/hash.h"
43 #include "QF/pr_comp.h"
44 #include "QF/progs.h"
45 #include "QF/sys.h"
46 
47 hashtab_t *opcode_table;
48 
49 VISIBLE int pr_type_size[ev_type_count] = {
50 	1,			// ev_void
51 	1,			// ev_string
52 	1,			// ev_float
53 	3,			// ev_vector
54 	1,			// ev_entity
55 	1,			// ev_field
56 	1,			// ev_func
57 	1,			// ev_pointer
58 	4,			// ev_quat
59 	1,			// ev_integer
60 	1,			// ev_uinteger
61 	0,			// ev_short        value in opcode
62 };
63 
64 VISIBLE const char *pr_type_name[ev_type_count] = {
65 	"void",
66 	"string",
67 	"float",
68 	"vector",
69 	"entity",
70 	"field",
71 	"function",
72 	"pointer",
73 	"quaternion",
74 	"integer",
75 	"uinteger",
76 	"short",
77 	"invalid",
78 };
79 
80 // default format is "%Ga, %Gb, %gc"
81 // V  global_string, contents, void
82 // G  global_string, contents
83 // g  global_string, no contents
84 // s  as short
85 // O  address + short
86 // P  function parameter
87 // F  function (must come before any P)
88 // R  return value
89 // E  entity + field (%Eab)
90 //
91 // a  operand a
92 // b  operand b
93 // c  operand c
94 // x  place holder for P (padding)
95 // 0-7 parameter index (for P)
96 VISIBLE opcode_t pr_opcodes[] = {
97 	{"<DONE>", "done", OP_DONE, false,	// OP_DONE is actually the same as
98 	 ev_entity, ev_field, ev_void,		// OP_RETURN, the types are bogus
99 	 PROG_ID_VERSION,
100 	 "%Va",
101 	},
102 
103 	{"*", "mul.f", OP_MUL_F, false,
104 	 ev_float, ev_float, ev_float,
105 	 PROG_ID_VERSION,
106 	},
107 	{"*", "mul.v", OP_MUL_V, false,
108 	 ev_vector, ev_vector, ev_float,
109 	 PROG_ID_VERSION,
110 	},
111 	{"*", "mul.fv", OP_MUL_FV, false,
112 	 ev_float, ev_vector, ev_vector,
113 	 PROG_ID_VERSION,
114 	},
115 	{"*", "mul.vf", OP_MUL_VF, false,
116 	 ev_vector, ev_float, ev_vector,
117 	 PROG_ID_VERSION,
118 	},
119 	{"*", "mul.q", OP_MUL_Q, false,
120 	 ev_quat, ev_quat, ev_quat,
121 	 PROG_VERSION,
122 	},
123 	{"*", "mul.fq", OP_MUL_FQ, false,
124 	 ev_float, ev_quat, ev_quat,
125 	 PROG_VERSION,
126 	},
127 	{"*", "mul.qf", OP_MUL_QF, false,
128 	 ev_quat, ev_float, ev_quat,
129 	 PROG_VERSION,
130 	},
131 	{"*", "mul.qv", OP_MUL_QV, false,
132 	 ev_quat, ev_vector, ev_vector,
133 	 PROG_VERSION,
134 	},
135 
136 	{"~", "conj.q", OP_CONJ_Q, false,
137 	 ev_quat, ev_invalid, ev_quat,
138 	 PROG_VERSION,
139 	 "%Ga, %gc",
140 	},
141 
142 	{"/", "div.f", OP_DIV_F, false,
143 	 ev_float, ev_float, ev_float,
144 	 PROG_ID_VERSION,
145 	},
146 
147 	{"+", "add.f", OP_ADD_F, false,
148 	 ev_float, ev_float, ev_float,
149 	 PROG_ID_VERSION,
150 	},
151 	{"+", "add.v", OP_ADD_V, false,
152 	 ev_vector, ev_vector, ev_vector,
153 	 PROG_ID_VERSION,
154 	},
155 	{"+", "add.q", OP_ADD_Q, false,
156 	 ev_quat, ev_quat, ev_quat,
157 	 PROG_VERSION,
158 	},
159 	{"+", "add.s", OP_ADD_S, false,
160 	 ev_string, ev_string, ev_string,
161 	 PROG_VERSION,
162 	},
163 
164 	{"-", "sub.f", OP_SUB_F, false,
165 	 ev_float, ev_float, ev_float,
166 	 PROG_ID_VERSION,
167 	},
168 	{"-", "sub.v", OP_SUB_V, false,
169 	 ev_vector, ev_vector, ev_vector,
170 	 PROG_ID_VERSION,
171 	},
172 	{"-", "sub.q", OP_SUB_Q, false,
173 	 ev_quat, ev_quat, ev_quat,
174 	 PROG_VERSION,
175 	},
176 
177 	{"==", "eq.f", OP_EQ_F, false,
178 	 ev_float, ev_float, ev_integer,
179 	 PROG_ID_VERSION,
180 	},
181 	{"==", "eq.v", OP_EQ_V, false,
182 	 ev_vector, ev_vector, ev_integer,
183 	 PROG_ID_VERSION,
184 	},
185 	{"==", "eq.q", OP_EQ_Q, false,
186 	 ev_quat, ev_quat, ev_integer,
187 	 PROG_VERSION,
188 	},
189 	{"==", "eq.s", OP_EQ_S, false,
190 	 ev_string, ev_string, ev_integer,
191 	 PROG_ID_VERSION,
192 	},
193 	{"==", "eq.e", OP_EQ_E, false,
194 	 ev_entity, ev_entity, ev_integer,
195 	 PROG_ID_VERSION,
196 	},
197 	{"==", "eq.fn", OP_EQ_FN, false,
198 	 ev_func, ev_func, ev_integer,
199 	 PROG_ID_VERSION,
200 	},
201 
202 	{"!=", "ne.f", OP_NE_F, false,
203 	 ev_float, ev_float, ev_integer,
204 	 PROG_ID_VERSION,
205 	},
206 	{"!=", "ne.v", OP_NE_V, false,
207 	 ev_vector, ev_vector, ev_integer,
208 	 PROG_ID_VERSION,
209 	},
210 	{"!=", "ne.q", OP_NE_Q, false,
211 	 ev_quat, ev_quat, ev_integer,
212 	 PROG_VERSION,
213 	},
214 	{"!=", "ne.s", OP_NE_S, false,
215 	 ev_string, ev_string, ev_integer,
216 	 PROG_ID_VERSION,
217 	},
218 	{"!=", "ne.e", OP_NE_E, false,
219 	 ev_entity, ev_entity, ev_integer,
220 	 PROG_ID_VERSION,
221 	},
222 	{"!=", "ne.fn", OP_NE_FN, false,
223 	 ev_func, ev_func, ev_integer,
224 	 PROG_ID_VERSION,
225 	},
226 
227 	{"<=", "le.f", OP_LE_F,	false,
228 	 ev_float, ev_float, ev_integer,
229 	 PROG_ID_VERSION,
230 	},
231 	{">=", "ge.f", OP_GE_F,	false,
232 	 ev_float, ev_float, ev_integer,
233 	 PROG_ID_VERSION,
234 	},
235 	{"<=", "le.s", OP_LE_S,	false,
236 	 ev_string, ev_string, ev_integer,
237 	 PROG_VERSION,
238 	},
239 	{">=", "ge.s", OP_GE_S,	false,
240 	 ev_string, ev_string, ev_integer,
241 	 PROG_VERSION,
242 	},
243 	{"<", "lt.f", OP_LT_F,	false,
244 	 ev_float, ev_float, ev_integer,
245 	 PROG_ID_VERSION,
246 	},
247 	{">", "gt.f", OP_GT_F,	false,
248 	 ev_float, ev_float, ev_integer,
249 	 PROG_ID_VERSION,
250 	},
251 	{"<", "lt.s", OP_LT_S,	false,
252 	 ev_string, ev_string, ev_integer,
253 	 PROG_VERSION,
254 	},
255 	{">", "gt.s", OP_GT_S,	false,
256 	 ev_string, ev_string, ev_integer,
257 	 PROG_VERSION,
258 	},
259 
260 	{".", "load.f", OP_LOAD_F, false,
261 	 ev_entity, ev_field, ev_float,
262 	 PROG_ID_VERSION,
263 	 "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible?
264 	},
265 	{".", "load.v", OP_LOAD_V, false,
266 	 ev_entity, ev_field, ev_vector,
267 	 PROG_ID_VERSION,
268 	 "%Ga.%Gb(%Ec), %gc",
269 	},
270 	{".", "load.q", OP_LOAD_Q, false,
271 	 ev_entity, ev_field, ev_quat,
272 	 PROG_VERSION,
273 	 "%Ga.%Gb(%Ec), %gc",
274 	},
275 	{".", "load.s", OP_LOAD_S, false,
276 	 ev_entity, ev_field, ev_string,
277 	 PROG_ID_VERSION,
278 	 "%Ga.%Gb(%Ec), %gc",
279 	},
280 	{".", "load.ent", OP_LOAD_ENT, false,
281 	 ev_entity, ev_field, ev_entity,
282 	 PROG_ID_VERSION,
283 	 "%Ga.%Gb(%Ec), %gc",
284 	},
285 	{".", "load.fld", OP_LOAD_FLD, false,
286 	 ev_entity, ev_field, ev_field,
287 	 PROG_ID_VERSION,
288 	 "%Ga.%Gb(%Ec), %gc",
289 	},
290 	{".", "load.fn", OP_LOAD_FN, false,
291 	 ev_entity, ev_field, ev_func,
292 	 PROG_ID_VERSION,
293 	 "%Ga.%Gb(%Ec), %gc",
294 	},
295 	{".", "load.i", OP_LOAD_I, false,
296 	 ev_entity, ev_field, ev_integer,
297 	 PROG_VERSION,
298 	 "%Ga.%Gb(%Ec), %gc",
299 	},
300 	{".", "load.p", OP_LOAD_P, false,
301 	 ev_entity, ev_field, ev_pointer,
302 	 PROG_VERSION,
303 	 "%Ga.%Gb(%Ec), %gc",
304 	},
305 
306 	{".", "loadb.f", OP_LOADB_F, false,
307 	 ev_pointer, ev_integer, ev_float,
308 	 PROG_VERSION,
309 	 "*(%Ga + %Gb), %gc",
310 	},
311 	{".", "loadb.v", OP_LOADB_V, false,
312 	 ev_pointer, ev_integer, ev_vector,
313 	 PROG_VERSION,
314 	 "*(%Ga + %Gb), %gc",
315 	},
316 	{".", "loadb.q", OP_LOADB_Q, false,
317 	 ev_pointer, ev_integer, ev_quat,
318 	 PROG_VERSION,
319 	 "*(%Ga + %Gb), %gc",
320 	},
321 	{".", "loadb.s", OP_LOADB_S, false,
322 	 ev_pointer, ev_integer, ev_string,
323 	 PROG_VERSION,
324 	 "*(%Ga + %Gb), %gc",
325 	},
326 	{".", "loadb.ent", OP_LOADB_ENT, false,
327 	 ev_pointer, ev_integer, ev_entity,
328 	 PROG_VERSION,
329 	 "*(%Ga + %Gb), %gc",
330 	},
331 	{".", "loadb.fld", OP_LOADB_FLD, false,
332 	 ev_pointer, ev_integer, ev_field,
333 	 PROG_VERSION,
334 	 "*(%Ga + %Gb), %gc",
335 	},
336 	{".", "loadb.fn", OP_LOADB_FN, false,
337 	 ev_pointer, ev_integer, ev_func,
338 	 PROG_VERSION,
339 	 "*(%Ga + %Gb), %gc",
340 	},
341 	{".", "loadb.i", OP_LOADB_I, false,
342 	 ev_pointer, ev_integer, ev_integer,
343 	 PROG_VERSION,
344 	 "*(%Ga + %Gb), %gc",
345 	},
346 	{".", "loadb.p", OP_LOADB_P, false,
347 	 ev_pointer, ev_integer, ev_pointer,
348 	 PROG_VERSION,
349 	 "*(%Ga + %Gb), %gc",
350 	},
351 
352 	{".", "loadbi.f", OP_LOADBI_F, false,
353 	 ev_pointer, ev_short, ev_float,
354 	 PROG_VERSION,
355 	 "*(%Ga + %sb), %gc",
356 	},
357 	{".", "loadbi.v", OP_LOADBI_V, false,
358 	 ev_pointer, ev_short, ev_vector,
359 	 PROG_VERSION,
360 	 "*(%Ga + %sb), %gc",
361 	},
362 	{".", "loadbi.q", OP_LOADBI_Q, false,
363 	 ev_pointer, ev_short, ev_quat,
364 	 PROG_VERSION,
365 	 "*(%Ga + %sb), %gc",
366 	},
367 	{".", "loadbi.s", OP_LOADBI_S, false,
368 	 ev_pointer, ev_short, ev_string,
369 	 PROG_VERSION,
370 	 "*(%Ga + %sb), %gc",
371 	},
372 	{".", "loadbi.ent", OP_LOADBI_ENT, false,
373 	 ev_pointer, ev_short, ev_entity,
374 	 PROG_VERSION,
375 	 "*(%Ga + %sb), %gc",
376 	},
377 	{".", "loadbi.fld", OP_LOADBI_FLD, false,
378 	 ev_pointer, ev_short, ev_field,
379 	 PROG_VERSION,
380 	 "*(%Ga + %sb), %gc",
381 	},
382 	{".", "loadbi.fn", OP_LOADBI_FN, false,
383 	 ev_pointer, ev_short, ev_func,
384 	 PROG_VERSION,
385 	 "*(%Ga + %sb), %gc",
386 	},
387 	{".", "loadbi.i", OP_LOADBI_I, false,
388 	 ev_pointer, ev_short, ev_integer,
389 	 PROG_VERSION,
390 	 "*(%Ga + %sb), %gc",
391 	},
392 	{".", "loadbi.p", OP_LOADBI_P, false,
393 	 ev_pointer, ev_short, ev_pointer,
394 	 PROG_VERSION,
395 	 "*(%Ga + %sb), %gc",
396 	},
397 
398 	{"&", "address", OP_ADDRESS, false,
399 	 ev_entity, ev_field, ev_pointer,
400 	 PROG_ID_VERSION,
401 	 "%Ga.%Gb(%Ec), %gc",
402 	},
403 
404 	{"&", "address", OP_ADDRESS_VOID, false,
405 	 ev_void, ev_invalid, ev_pointer,
406 	 PROG_VERSION,
407 	 "%Ga, %gc",
408 	},
409 	{"&", "address.f", OP_ADDRESS_F, false,
410 	 ev_float, ev_invalid, ev_pointer,
411 	 PROG_VERSION,
412 	 "%Ga, %gc",
413 	},
414 	{"&", "address.v", OP_ADDRESS_V, false,
415 	 ev_vector, ev_invalid, ev_pointer,
416 	 PROG_VERSION,
417 	 "%Ga, %gc",
418 	},
419 	{"&", "address.q", OP_ADDRESS_Q, false,
420 	 ev_quat, ev_invalid, ev_pointer,
421 	 PROG_VERSION,
422 	 "%Ga, %gc",
423 	},
424 	{"&", "address.s", OP_ADDRESS_S, false,
425 	 ev_string, ev_invalid, ev_pointer,
426 	 PROG_VERSION,
427 	 "%Ga, %gc",
428 	},
429 	{"&", "address.ent", OP_ADDRESS_ENT, false,
430 	 ev_entity, ev_invalid, ev_pointer,
431 	 PROG_VERSION,
432 	 "%Ga, %gc",
433 	},
434 	{"&", "address.fld", OP_ADDRESS_FLD, false,
435 	 ev_field, ev_invalid, ev_pointer,
436 	 PROG_VERSION,
437 	 "%Ga, %gc",
438 	},
439 	{"&", "address.fn", OP_ADDRESS_FN, false,
440 	 ev_func, ev_invalid, ev_pointer,
441 	 PROG_VERSION,
442 	 "%Ga, %gc",
443 	},
444 	{"&", "address.i", OP_ADDRESS_I, false,
445 	 ev_integer, ev_invalid, ev_pointer,
446 	 PROG_VERSION,
447 	 "%Ga, %gc",
448 	},
449 	{"&", "address.p", OP_ADDRESS_P, false,
450 	 ev_pointer, ev_invalid, ev_pointer,
451 	 PROG_VERSION,
452 	 "%Ga, %gc",
453 	},
454 
455 	{"&", "lea", OP_LEA, false,
456 	 ev_pointer, ev_integer, ev_pointer,
457 	 PROG_VERSION,
458 	 "%Ga, %Gb, %gc",
459 	},
460 	{"&", "leai", OP_LEAI, false,
461 	 ev_pointer, ev_short, ev_pointer,
462 	 PROG_VERSION,
463 	 "%Ga, %sb, %gc",
464 	},
465 
466 	{"<CONV>", "conv.if", OP_CONV_IF, false,
467 	 ev_integer, ev_invalid, ev_float,
468 	 PROG_VERSION,
469 	 "%Ga, %gc",
470 	},
471 	{"<CONV>", "conv.fi", OP_CONV_FI, false,
472 	 ev_float, ev_invalid, ev_integer,
473 	 PROG_VERSION,
474 	 "%Ga, %gc",
475 	},
476 
477 	{"=", "store.f", OP_STORE_F, true,
478 	 ev_float, ev_float, ev_invalid,
479 	 PROG_ID_VERSION,
480 	 "%Ga, %gb",
481 	},
482 	{"=", "store.v", OP_STORE_V, true,
483 	 ev_vector, ev_vector, ev_invalid,
484 	 PROG_ID_VERSION,
485 	 "%Ga, %gb",
486 	},
487 	{"=", "store.q", OP_STORE_Q, true,
488 	 ev_quat, ev_quat, ev_invalid,
489 	 PROG_VERSION,
490 	 "%Ga, %gb",
491 	},
492 	{"=", "store.s", OP_STORE_S, true,
493 	 ev_string, ev_string, ev_invalid,
494 	 PROG_ID_VERSION,
495 	 "%Ga, %gb",
496 	},
497 	{"=", "store.ent", OP_STORE_ENT, true,
498 	 ev_entity, ev_entity, ev_invalid,
499 	 PROG_ID_VERSION,
500 	 "%Ga, %gb",
501 	},
502 	{"=", "store.fld", OP_STORE_FLD, true,
503 	 ev_field, ev_field, ev_invalid,
504 	 PROG_ID_VERSION,
505 	 "%Ga, %gb",
506 	},
507 	{"=", "store.fn", OP_STORE_FN, true,
508 	 ev_func, ev_func, ev_invalid,
509 	 PROG_ID_VERSION,
510 	 "%Ga, %gb",
511 	},
512 	{"=", "store.i", OP_STORE_I, true,
513 	 ev_integer, ev_integer, ev_invalid,
514 	 PROG_VERSION,
515 	 "%Ga, %gb",
516 	},
517 	{"=", "store.p", OP_STORE_P, true,
518 	 ev_pointer, ev_pointer, ev_invalid,
519 	 PROG_VERSION,
520 	 "%Ga, %gb",
521 	},
522 
523 	{".=", "storep.f", OP_STOREP_F, true,
524 	 ev_float, ev_pointer, ev_invalid,
525 	 PROG_ID_VERSION,
526 	 "%Ga, *%Gb",
527 	},
528 	{".=", "storep.v", OP_STOREP_V, true,
529 	 ev_vector, ev_pointer, ev_invalid,
530 	 PROG_ID_VERSION,
531 	 "%Ga, *%Gb",
532 	},
533 	{".=", "storep.q", OP_STOREP_Q, true,
534 	 ev_quat, ev_pointer, ev_invalid,
535 	 PROG_VERSION,
536 	 "%Ga, *%Gb",
537 	},
538 	{".=", "storep.s", OP_STOREP_S, true,
539 	 ev_string, ev_pointer, ev_invalid,
540 	 PROG_ID_VERSION,
541 	 "%Ga, *%Gb",
542 	},
543 	{".=", "storep.ent", OP_STOREP_ENT, true,
544 	 ev_entity, ev_pointer, ev_invalid,
545 	 PROG_ID_VERSION,
546 	 "%Ga, *%Gb",
547 	},
548 	{".=", "storep.fld", OP_STOREP_FLD, true,
549 	 ev_field, ev_pointer, ev_invalid,
550 	 PROG_ID_VERSION,
551 	 "%Ga, *%Gb",
552 	},
553 	{".=", "storep.fn", OP_STOREP_FN, true,
554 	 ev_func, ev_pointer, ev_invalid,
555 	 PROG_ID_VERSION,
556 	 "%Ga, *%Gb",
557 	},
558 	{".=", "storep.i", OP_STOREP_I, true,
559 	 ev_integer, ev_pointer, ev_invalid,
560 	 PROG_VERSION,
561 	 "%Ga, *%Gb",
562 	},
563 	{".=", "storep.p", OP_STOREP_P, true,
564 	 ev_pointer, ev_pointer, ev_invalid,
565 	 PROG_VERSION,
566 	 "%Ga, *%Gb",
567 	},
568 
569 	{".=", "storeb.f", OP_STOREB_F, true,
570 	 ev_float, ev_pointer, ev_integer,
571 	 PROG_VERSION,
572 	 "%Ga, *(%Gb + %Gc)",
573 	},
574 	{".=", "storeb.v", OP_STOREB_V, true,
575 	 ev_vector, ev_pointer, ev_integer,
576 	 PROG_VERSION,
577 	 "%Ga, *(%Gb + %Gc)",
578 	},
579 	{".=", "storeb.q", OP_STOREB_Q, true,
580 	 ev_quat, ev_pointer, ev_integer,
581 	 PROG_VERSION,
582 	 "%Ga, *(%Gb + %Gc)",
583 	},
584 	{".=", "storeb.s", OP_STOREB_S, true,
585 	 ev_string, ev_pointer, ev_integer,
586 	 PROG_VERSION,
587 	 "%Ga, *(%Gb + %Gc)",
588 	},
589 	{".=", "storeb.ent", OP_STOREB_ENT, true,
590 	 ev_entity, ev_pointer, ev_integer,
591 	 PROG_VERSION,
592 	 "%Ga, *(%Gb + %Gc)",
593 	},
594 	{".=", "storeb.fld", OP_STOREB_FLD, true,
595 	 ev_field, ev_pointer, ev_integer,
596 	 PROG_VERSION,
597 	 "%Ga, *(%Gb + %Gc)",
598 	},
599 	{".=", "storeb.fn", OP_STOREB_FN, true,
600 	 ev_func, ev_pointer, ev_integer,
601 	 PROG_VERSION,
602 	 "%Ga, *(%Gb + %Gc)",
603 	},
604 	{".=", "storeb.i", OP_STOREB_I, true,
605 	 ev_integer, ev_pointer, ev_integer,
606 	 PROG_VERSION,
607 	 "%Ga, *(%Gb + %Gc)",
608 	},
609 	{".=", "storeb.p", OP_STOREB_P, true,
610 	 ev_pointer, ev_pointer, ev_integer,
611 	 PROG_VERSION,
612 	 "%Ga, *(%Gb + %Gc)",
613 	},
614 
615 	{".=", "storebi.f", OP_STOREBI_F, true,
616 	 ev_float, ev_pointer, ev_short,
617 	 PROG_VERSION,
618 	 "%Ga, *(%Gb + %sc)",
619 	},
620 	{".=", "storebi.v", OP_STOREBI_V, true,
621 	 ev_vector, ev_pointer, ev_short,
622 	 PROG_VERSION,
623 	 "%Ga, *(%Gb + %sc)",
624 	},
625 	{".=", "storebi.q", OP_STOREBI_Q, true,
626 	 ev_quat, ev_pointer, ev_short,
627 	 PROG_VERSION,
628 	 "%Ga, *(%Gb + %sc)",
629 	},
630 	{".=", "storebi.s", OP_STOREBI_S, true,
631 	 ev_string, ev_pointer, ev_short,
632 	 PROG_VERSION,
633 	 "%Ga, *(%Gb + %sc)",
634 	},
635 	{".=", "storebi.ent", OP_STOREBI_ENT, true,
636 	 ev_entity, ev_pointer, ev_short,
637 	 PROG_VERSION,
638 	 "%Ga, *(%Gb + %sc)",
639 	},
640 	{".=", "storebi.fld", OP_STOREBI_FLD, true,
641 	 ev_field, ev_pointer, ev_short,
642 	 PROG_VERSION,
643 	 "%Ga, *(%Gb + %sc)",
644 	},
645 	{".=", "storebi.fn", OP_STOREBI_FN, true,
646 	 ev_func, ev_pointer, ev_short,
647 	 PROG_VERSION,
648 	 "%Ga, *(%Gb + %sc)",
649 	},
650 	{".=", "storebi.i", OP_STOREBI_I, true,
651 	 ev_integer, ev_pointer, ev_short,
652 	 PROG_VERSION,
653 	 "%Ga, *(%Gb + %sc)",
654 	},
655 	{".=", "storebi.p", OP_STOREBI_P, true,
656 	 ev_pointer, ev_pointer, ev_short,
657 	 PROG_VERSION,
658 	 "%Ga, *(%Gb + %sc)",
659 	},
660 
661 	{"<RETURN>", "return", OP_RETURN, false,
662 	 ev_void, ev_invalid, ev_invalid,
663 	 PROG_ID_VERSION,
664 	 "%Ra",
665 	},
666 
667 	{"<RETURN_V>", "return", OP_RETURN_V, false,
668 	 ev_invalid, ev_invalid, ev_invalid,
669 	 PROG_VERSION,
670 	 "",
671 	},
672 
673 	{"!", "not.f", OP_NOT_F, false,
674 	 ev_float, ev_invalid, ev_integer,
675 	 PROG_ID_VERSION,
676 	 "%Ga, %gc",
677 	},
678 	{"!", "not.v", OP_NOT_V, false,
679 	 ev_vector, ev_invalid, ev_integer,
680 	 PROG_ID_VERSION,
681 	 "%Ga, %gc",
682 	},
683 	{"!", "not.q", OP_NOT_Q, false,
684 	 ev_quat, ev_invalid, ev_integer,
685 	 PROG_VERSION,
686 	 "%Ga, %gc",
687 	},
688 	{"!", "not.s", OP_NOT_S, false,
689 	 ev_string, ev_invalid, ev_integer,
690 	 PROG_ID_VERSION,
691 	 "%Ga, %gc",
692 	},
693 	{"!", "not.ent", OP_NOT_ENT, false,
694 	 ev_entity, ev_invalid, ev_integer,
695 	 PROG_ID_VERSION,
696 	 "%Ga, %gc",
697 	},
698 	{"!", "not.fn", OP_NOT_FN, false,
699 	 ev_func, ev_invalid, ev_integer,
700 	 PROG_ID_VERSION,
701 	 "%Ga, %gc",
702 	},
703 	{"!", "not.p", OP_NOT_P, false,
704 	 ev_pointer, ev_invalid, ev_integer,
705 	 PROG_VERSION,
706 	 "%Ga, %gc",
707 	},
708 
709 	{"<IF>", "if", OP_IF, false,
710 	 ev_integer, ev_short, ev_invalid,
711 	 PROG_ID_VERSION,
712 	 "%Ga branch %sb (%Ob)",
713 	},
714 	{"<IFNOT>", "ifnot", OP_IFNOT, false,
715 	 ev_integer, ev_short, ev_invalid,
716 	 PROG_ID_VERSION,
717 	 "%Ga branch %sb (%Ob)",
718 	},
719 	{"<IFBE>", "ifbe", OP_IFBE, true,
720 	 ev_integer, ev_short, ev_invalid,
721 	 PROG_VERSION,
722 	 "%Ga branch %sb (%Ob)",
723 	},
724 	{"<IFB>", "ifb", OP_IFB, true,
725 	 ev_integer, ev_short, ev_invalid,
726 	 PROG_VERSION,
727 	 "%Ga branch %sb (%Ob)",
728 	},
729 	{"<IFAE>", "ifae", OP_IFAE, true,
730 	 ev_integer, ev_short, ev_invalid,
731 	 PROG_VERSION,
732 	 "%Ga branch %sb (%Ob)",
733 	},
734 	{"<IFA>", "ifa", OP_IFA, true,
735 	 ev_integer, ev_short, ev_invalid,
736 	 PROG_VERSION,
737 	 "%Ga branch %sb (%Ob)",
738 	},
739 
740 // calls returns REG_RETURN
741 	{"<CALL0>", "call0", OP_CALL0, false,
742 	 ev_func, ev_invalid, ev_invalid,
743 	 PROG_ID_VERSION,
744 	 "%Fa ()",
745 	},
746 	{"<CALL1>", "call1", OP_CALL1, false,
747 	 ev_func, ev_invalid, ev_invalid,
748 	 PROG_ID_VERSION,
749 	 "%Fa (%P0x)",
750 	},
751 	{"<CALL2>", "call2", OP_CALL2, false,
752 	 ev_func, ev_invalid, ev_invalid,
753 	 PROG_ID_VERSION,
754 	 "%Fa (%P0x, %P1x)",
755 	},
756 	{"<CALL3>", "call3", OP_CALL3, false,
757 	 ev_func, ev_invalid, ev_invalid,
758 	 PROG_ID_VERSION,
759 	 "%Fa (%P0x, %P1x, %P2x)",
760 	},
761 	{"<CALL4>", "call4", OP_CALL4, false,
762 	 ev_func, ev_invalid, ev_invalid,
763 	 PROG_ID_VERSION,
764 	 "%Fa (%P0x, %P1x, %P2x, %P3x)",
765 	},
766 	{"<CALL5>", "call5", OP_CALL5, false,
767 	 ev_func, ev_invalid, ev_invalid,
768 	 PROG_ID_VERSION,
769 	 "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)",
770 	},
771 	{"<CALL6>", "call6", OP_CALL6, false,
772 	 ev_func, ev_invalid, ev_invalid,
773 	 PROG_ID_VERSION,
774 	 "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)",
775 	},
776 	{"<CALL7>", "call7", OP_CALL7, false,
777 	 ev_func, ev_invalid, ev_invalid,
778 	 PROG_ID_VERSION,
779 	 "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)",
780 	},
781 	{"<CALL8>", "call8", OP_CALL8, false,
782 	 ev_func, ev_invalid, ev_invalid,
783 	 PROG_ID_VERSION,
784 	 "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)",
785 	},
786 	{"<RCALL1>", "rcall1", OP_RCALL1, false,
787 	 ev_func, ev_void, ev_invalid,
788 	 PROG_VERSION,
789 	 "%Fa (%P0b)",
790 	},
791 	{"<RCALL2>", "rcall2", OP_RCALL2, false,
792 	 ev_func, ev_void, ev_void,
793 	 PROG_VERSION,
794 	 "%Fa (%P0b, %P1c)",
795 	},
796 	{"<RCALL3>", "rcall3", OP_RCALL3, false,
797 	 ev_func, ev_void, ev_void,
798 	 PROG_VERSION,
799 	 "%Fa (%P0b, %P1c, %P2x)",
800 	},
801 	{"<RCALL4>", "rcall4", OP_RCALL4, false,
802 	 ev_func, ev_void, ev_void,
803 	 PROG_VERSION,
804 	 "%Fa (%P0b, %P1c, %P2x, %P3x)",
805 	},
806 	{"<RCALL5>", "rcall5", OP_RCALL5, false,
807 	 ev_func, ev_void, ev_void,
808 	 PROG_VERSION,
809 	 "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)",
810 	},
811 	{"<RCALL6>", "rcall6", OP_RCALL6, false,
812 	 ev_func, ev_void, ev_void,
813 	 PROG_VERSION,
814 	 "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)",
815 	},
816 	{"<RCALL7>", "rcall7", OP_RCALL7, false,
817 	 ev_func, ev_void, ev_void,
818 	 PROG_VERSION,
819 	 "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)",
820 	},
821 	{"<RCALL8>", "rcall8", OP_RCALL8, false,
822 	 ev_func, ev_void, ev_void,
823 	 PROG_VERSION,
824 	 "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)",
825 	},
826 
827 	{"<STATE>", "state", OP_STATE, false,
828 	 ev_float, ev_func, ev_invalid,
829 	 PROG_ID_VERSION,
830 	 "%Ga, %Gb",
831 	},
832 
833 	{"<STATE>", "state.f", OP_STATE_F, false,
834 	 ev_float, ev_func, ev_float,
835 	 PROG_VERSION,
836 	 "%Ga, %Gb, %Gc",
837 	},
838 
839 	{"<GOTO>", "goto", OP_GOTO, false,
840 	 ev_short, ev_invalid, ev_invalid,
841 	 PROG_ID_VERSION,
842 	 "branch %sa (%Oa)",
843 	},
844 	{"<JUMP>", "jump", OP_JUMP, false,
845 	 ev_integer, ev_invalid, ev_invalid,
846 	 PROG_VERSION,
847 	 "%Ga",
848 	},
849 	{"<JUMPB>", "jumpb", OP_JUMPB, false,
850 	 ev_void, ev_integer, ev_invalid,
851 	 PROG_VERSION,
852 	 "%Ga[%Gb]",
853 	},
854 
855 	{"&&", "and.f", OP_AND, false,
856 	 ev_float, ev_float, ev_integer,
857 	 PROG_ID_VERSION,
858 	},
859 	{"||", "or.f", OP_OR, false,
860 	 ev_float, ev_float, ev_integer,
861 	 PROG_ID_VERSION,
862 	},
863 
864 	{"<<", "shl.f", OP_SHL_F, false,
865 	 ev_float, ev_float, ev_float,
866 	 PROG_VERSION,
867 	},
868 	{">>", "shr.f", OP_SHR_F, false,
869 	 ev_float, ev_float, ev_float,
870 	 PROG_VERSION,
871 	},
872 	{"<<", "shl.i", OP_SHL_I, false,
873 	 ev_integer, ev_integer, ev_integer,
874 	 PROG_VERSION,
875 	},
876 	{">>", "shr.i", OP_SHR_I, false,
877 	 ev_integer, ev_integer, ev_integer,
878 	 PROG_VERSION,
879 	},
880 	{">>", "shr.u", OP_SHR_U, false,
881 	 ev_uinteger, ev_integer, ev_uinteger,
882 	 PROG_VERSION,
883 	},
884 
885 	{"&", "bitand", OP_BITAND, false,
886 	 ev_float, ev_float, ev_float,
887 	 PROG_ID_VERSION,
888 	},
889 	{"|", "bitor", OP_BITOR, false,
890 	 ev_float, ev_float, ev_float,
891 	 PROG_ID_VERSION,
892 	},
893 
894 	{"+", "add.i", OP_ADD_I, false,
895 	 ev_integer, ev_integer, ev_integer,
896 	 PROG_VERSION,
897 	},
898 	{"-", "sub.i", OP_SUB_I, false,
899 	 ev_integer, ev_integer, ev_integer,
900 	 PROG_VERSION,
901 	},
902 	{"*", "mul.i", OP_MUL_I, false,
903 	 ev_integer, ev_integer, ev_integer,
904 	 PROG_VERSION,
905 	},
906 	{"/", "div.i", OP_DIV_I, false,
907 	 ev_integer, ev_integer, ev_integer,
908 	 PROG_VERSION,
909 	},
910 	{"%", "mod.i", OP_MOD_I, false,
911 	 ev_integer, ev_integer, ev_integer,
912 	 PROG_VERSION,
913 	},
914 	{"&", "bitand.i", OP_BITAND_I, false,
915 	 ev_integer, ev_integer, ev_integer,
916 	 PROG_VERSION,
917 	},
918 	{"|", "bitor.i", OP_BITOR_I, false,
919 	 ev_integer, ev_integer, ev_integer,
920 	 PROG_VERSION,
921 	},
922 
923 	{"%", "mod.f", OP_MOD_F, false,
924 	 ev_float, ev_float, ev_float,
925 	 PROG_VERSION,
926 	},
927 
928 	{">=", "ge.i", OP_GE_I, false,
929 	 ev_integer, ev_integer, ev_integer,
930 	 PROG_VERSION,
931 	},
932 	{"<=", "le.i", OP_LE_I, false,
933 	 ev_integer, ev_integer, ev_integer,
934 	 PROG_VERSION,
935 	},
936 	{">", "gt.i", OP_GT_I, false,
937 	 ev_integer, ev_integer, ev_integer,
938 	 PROG_VERSION,
939 	},
940 	{"<", "lt.i", OP_LT_I, false,
941 	 ev_integer, ev_integer, ev_integer,
942 	 PROG_VERSION,
943 	},
944 
945 	{"&&", "and.i", OP_AND_I, false,
946 	 ev_integer, ev_integer, ev_integer,
947 	 PROG_VERSION,
948 	},
949 	{"||", "or.i", OP_OR_I, false,
950 	 ev_integer, ev_integer, ev_integer,
951 	 PROG_VERSION,
952 	},
953 	{"!", "not.i", OP_NOT_I, false,
954 	 ev_integer, ev_invalid, ev_integer,
955 	 PROG_VERSION,
956 	 "%Ga, %gc",
957 	},
958 	{"==", "eq.i", OP_EQ_I, false,
959 	 ev_integer, ev_integer, ev_integer,
960 	 PROG_VERSION,
961 	},
962 	{"!=", "ne.i", OP_NE_I, false,
963 	 ev_integer, ev_integer, ev_integer,
964 	 PROG_VERSION,
965 	},
966 
967 	{">=", "ge.u", OP_GE_U, false,
968 	 ev_uinteger, ev_uinteger, ev_integer,
969 	 PROG_VERSION,
970 	},
971 	{"<=", "le.u", OP_LE_U, false,
972 	 ev_uinteger, ev_uinteger, ev_integer,
973 	 PROG_VERSION,
974 	},
975 	{">", "gt.u", OP_GT_U, false,
976 	 ev_uinteger, ev_uinteger, ev_integer,
977 	 PROG_VERSION,
978 	},
979 	{"<", "lt.u", OP_LT_U, false,
980 	 ev_uinteger, ev_uinteger, ev_integer,
981 	 PROG_VERSION,
982 	},
983 
984 	{"^", "bitxor.f", OP_BITXOR_F, false,
985 	 ev_float, ev_float, ev_float,
986 	 PROG_VERSION,
987 	},
988 	{"~", "bitnot.f", OP_BITNOT_F, false,
989 	 ev_float, ev_invalid, ev_float,
990 	 PROG_VERSION,
991 	 "%Ga, %gc",
992 	},
993 	{"^", "bitxor.i", OP_BITXOR_I, false,
994 	 ev_integer, ev_integer, ev_integer,
995 	 PROG_VERSION,
996 	},
997 	{"~", "bitnot.i", OP_BITNOT_I, false,
998 	 ev_integer, ev_invalid, ev_integer,
999 	 PROG_VERSION,
1000 	 "%Ga, %gc",
1001 	},
1002 
1003 	{">=", "ge.p", OP_GE_P, false,
1004 	 ev_pointer, ev_pointer, ev_integer,
1005 	 PROG_VERSION,
1006 	},
1007 	{"<=", "le.p", OP_LE_P, false,
1008 	 ev_pointer, ev_pointer, ev_integer,
1009 	 PROG_VERSION,
1010 	},
1011 	{">", "gt.p", OP_GT_P, false,
1012 	 ev_pointer, ev_pointer, ev_integer,
1013 	 PROG_VERSION,
1014 	},
1015 	{"<", "lt.p", OP_LT_P, false,
1016 	 ev_pointer, ev_pointer, ev_integer,
1017 	 PROG_VERSION,
1018 	},
1019 	{"==", "eq.p", OP_EQ_P, false,
1020 	 ev_pointer, ev_pointer, ev_integer,
1021 	 PROG_VERSION,
1022 	},
1023 	{"!=", "ne.p", OP_NE_P, false,
1024 	 ev_pointer, ev_pointer, ev_integer,
1025 	 PROG_VERSION,
1026 	},
1027 
1028 	{"<MOVE>", "movei", OP_MOVEI, true,
1029 	 ev_void, ev_short, ev_void,
1030 	 PROG_VERSION,
1031 	 "%Ga, %sb, %gc",
1032 	},
1033 	{"<MOVEP>", "movep", OP_MOVEP, true,
1034 	 ev_pointer, ev_integer, ev_pointer,
1035 	 PROG_VERSION,
1036 	 "%Ga, %Gb, %Gc",
1037 	},
1038 	{"<MOVEP>", "movepi", OP_MOVEPI, true,
1039 	 ev_pointer, ev_short, ev_pointer,
1040 	 PROG_VERSION,
1041 	 "%Ga, %Gb, %Gc",
1042 	},
1043 
1044 	// end of table
1045 	{0},
1046 };
1047 
1048 
1049 static uintptr_t
opcode_get_hash(const void * op,void * unused)1050 opcode_get_hash (const void *op, void *unused)
1051 {
1052 	return ((opcode_t *)op)->opcode;
1053 }
1054 
1055 static int
opcode_compare(const void * _opa,const void * _opb,void * unused)1056 opcode_compare (const void *_opa, const void *_opb, void *unused)
1057 {
1058 	opcode_t   *opa = (opcode_t *)_opa;
1059 	opcode_t   *opb = (opcode_t *)_opb;
1060 
1061 	return opa->opcode == opb->opcode;
1062 }
1063 
1064 opcode_t *
PR_Opcode(pr_short_t opcode)1065 PR_Opcode (pr_short_t opcode)
1066 {
1067 	opcode_t	op;
1068 
1069 	op.opcode = opcode;
1070 	return Hash_FindElement (opcode_table, &op);
1071 }
1072 
1073 VISIBLE void
PR_Opcode_Init(void)1074 PR_Opcode_Init (void)
1075 {
1076 	opcode_t   *op;
1077 
1078 	opcode_table = Hash_NewTable (1021, 0, 0, 0);
1079 	Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare);
1080 
1081 	for (op = pr_opcodes; op->name; op++) {
1082 		Hash_AddElement (opcode_table, op);
1083 	}
1084 }
1085 
1086 static inline void
check_branch(progs_t * pr,dstatement_t * st,opcode_t * op,short offset)1087 check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset)
1088 {
1089 	pr_int_t    address = st - pr->pr_statements;
1090 
1091 	address += offset;
1092 	if (address < 0 || (pr_uint_t) address >= pr->progs->numstatements)
1093 		PR_Error (pr, "PR_Check_Opcodes: invalid branch (statement %ld: %s)",
1094 				  (long)(st - pr->pr_statements), op->opname);
1095 }
1096 
1097 static int
is_vector_parameter_store(progs_t * pr,dstatement_t * st,unsigned short operand)1098 is_vector_parameter_store (progs_t *pr, dstatement_t *st,
1099 						   unsigned short operand)
1100 {
1101 	int         i;
1102 
1103 	if (st->op != OP_STORE_V)
1104 		return 0;
1105 	if (operand != st->a)
1106 		return 0;
1107 	for (i = 0; i < MAX_PARMS; i++)
1108 		if (st->b == pr->pr_params[i] - pr->pr_globals)
1109 			return 1;
1110 	return 0;
1111 }
1112 
1113 #define ISDENORM(x) ((x) && !((x) & 0x7f800000))
1114 
1115 static inline void
check_global(progs_t * pr,dstatement_t * st,opcode_t * op,etype_t type,unsigned short operand,int check_denorm)1116 check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
1117 			  unsigned short operand, int check_denorm)
1118 {
1119 	const char *msg;
1120 	ddef_t     *def;
1121 
1122 	switch (type) {
1123 		case ev_short:
1124 			break;
1125 		case ev_invalid:
1126 			if (operand) {
1127 				msg = "non-zero global index in invalid operand";
1128 				goto error;
1129 			}
1130 			break;
1131 		default:
1132 			if (operand + (unsigned) pr_type_size[type]
1133 				> pr->progs->numglobals) {
1134 				if (operand >= pr->progs->numglobals
1135 					|| !is_vector_parameter_store (pr, st, operand)) {
1136 					msg = "out of bounds global index";
1137 					goto error;
1138 				}
1139 			}
1140 			if (type != ev_float || !check_denorm)
1141 				break;
1142 			if (!ISDENORM (G_INT (pr, operand))
1143 				|| G_UINT(pr, operand) == 0x80000000)
1144 				break;
1145 			if ((def = PR_GlobalAtOfs (pr, operand))
1146 				&& (def->type & ~DEF_SAVEGLOBAL) != ev_float) {
1147 				// FTEqcc uses store.f parameters of most types :/
1148 				break;
1149 			}
1150 			if (!pr->denorm_found) {
1151 				pr->denorm_found = 1;
1152 				if (pr_boundscheck->int_val) {
1153 					Sys_Printf ("DENORMAL floats detected, these progs might "
1154 								"not work. Good luck.\n");
1155 					return;
1156 				}
1157 				msg = "DENORMAL float detected. These progs are probably "
1158 					"using qccx arrays and integers. If just simple arrays "
1159 					"are being used, then they should work, but if "
1160 					"internal.qc is used, they most definitely will NOT. To"
1161 					"allow these progs to be used, set pr_boundscheck to 1.";
1162 				goto error;
1163 			}
1164 			break;
1165 	}
1166 	return;
1167 error:
1168 	PR_PrintStatement (pr, st, 0);
1169 	PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg,
1170 			  (long)(st - pr->pr_statements), op->opname);
1171 }
1172 
1173 static void
check_global_size(progs_t * pr,dstatement_t * st,opcode_t * op,unsigned short size,unsigned short operand)1174 check_global_size (progs_t *pr, dstatement_t *st, opcode_t *op,
1175 				   unsigned short size, unsigned short operand)
1176 {
1177 	const char *msg;
1178 	if (operand + size > pr->progs->numglobals) {
1179 		msg = "out of bounds global index";
1180 		goto error;
1181 	}
1182 	return;
1183 error:
1184 	PR_PrintStatement (pr, st, 0);
1185 	PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg,
1186 			  (long)(st - pr->pr_statements), op->opname);
1187 }
1188 
1189 int
PR_Check_Opcodes(progs_t * pr)1190 PR_Check_Opcodes (progs_t *pr)
1191 {
1192 	opcode_t   *op;
1193 	dstatement_t *st;
1194 	int         state_ok = 0;
1195 	pr_uint_t   i;
1196 
1197 	if (pr->globals.time && pr->globals.self && pr->fields.nextthink != -1
1198 		&& pr->fields.think != -1 && pr->fields.frame != -1)
1199 		state_ok = 1;
1200 
1201 	//FIXME need to decide if I really want to always do static bounds checking
1202 	// the only problem is that it slows progs load a little, but it's the only
1203 	// way to check for qccx' evil
1204 	if (0 && !pr_boundscheck->int_val) {
1205 		for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements;
1206 			 st++, i++) {
1207 			op = PR_Opcode (st->op);
1208 			if (!op) {
1209 				PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at "
1210 						  "statement %ld", st->op,
1211 						  (long)(st - pr->pr_statements));
1212 			}
1213 			if ((st->op == OP_STATE || st->op == OP_STATE_F) && !state_ok) {
1214 				PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields "
1215 						  "or globals", op->opname);
1216 			}
1217 		}
1218 	} else {
1219 		for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements;
1220 			 st++, i++) {
1221 			op = PR_Opcode (st->op);
1222 			if (!op) {
1223 				PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at "
1224 						  "statement %ld", st->op,
1225 						  (long)(st - pr->pr_statements));
1226 			}
1227 			switch (st->op) {
1228 				case OP_IF:
1229 				case OP_IFNOT:
1230 					check_global (pr, st, op, op->type_a, st->a, 1);
1231 					check_branch (pr, st, op, st->b);
1232 					break;
1233 				case OP_GOTO:
1234 					check_branch (pr, st, op, st->a);
1235 					break;
1236 				case OP_DONE:
1237 				case OP_RETURN:
1238 					check_global (pr, st, op, ev_integer, st->a, 1);
1239 					check_global (pr, st, op, ev_void, st->b, 0);
1240 					check_global (pr, st, op, ev_void, st->c, 0);
1241 					break;
1242 				case OP_RCALL1:
1243 					check_global (pr, st, op, ev_void, st->c, 1);
1244 				case OP_RCALL2:
1245 				case OP_RCALL3:
1246 				case OP_RCALL4:
1247 				case OP_RCALL5:
1248 				case OP_RCALL6:
1249 				case OP_RCALL7:
1250 				case OP_RCALL8:
1251 					if (st->op > OP_RCALL1)
1252 						check_global (pr, st, op, ev_integer, st->c, 1);
1253 					check_global (pr, st, op, ev_integer, st->b, 1);
1254 					check_global (pr, st, op, ev_func, st->a, 1);
1255 					break;
1256 				case OP_STATE:
1257 				case OP_STATE_F:
1258 					if (!state_ok) {
1259 						PR_Error (pr, "PR_Check_Opcodes: %s used with missing "
1260 								  "fields or globals", op->opname);
1261 					}
1262 					check_global (pr, st, op, op->type_a, st->a, 1);
1263 					check_global (pr, st, op, op->type_b, st->b, 1);
1264 					check_global (pr, st, op, op->type_c, st->c, 1);
1265 					break;
1266 				case OP_MOVEI:
1267 					check_global_size (pr, st, op, st->b, st->a);
1268 					check_global_size (pr, st, op, st->b, st->c);
1269 					break;
1270 				default:
1271 					check_global (pr, st, op, op->type_a, st->a, 1);
1272 					check_global (pr, st, op, op->type_b, st->b,
1273 								  op->opcode != OP_STORE_F);
1274 					check_global (pr, st, op, op->type_c, st->c, 0);
1275 					break;
1276 			}
1277 		}
1278 	}
1279 	return 1;
1280 }
1281