xref: /original-bsd/usr.bin/pascal/px/interp.c (revision 6884d44a)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)interp.c	5.7 (Berkeley) 02/05/91";
9 #endif not lint
10 
11 #include <math.h>
12 #include <signal.h>
13 #include "whoami.h"
14 #include "vars.h"
15 #include "objfmt.h"
16 #include "h02opcs.h"
17 #include "machdep.h"
18 #include "libpc.h"
19 
20 /*
21  * program variables
22  */
23 union display _display;
24 struct dispsave	*_dp;
25 long	_lino = 0;
26 int	_argc;
27 char	**_argv;
28 long	_mode;
29 long	_runtst = (long)TRUE;
30 bool	_nodump = FALSE;
31 long	_stlim = 500000;
32 long	_stcnt = 0;
33 long	_seed = 1;
34 #ifdef ADDR32
35 char	*_minptr = (char *)0x7fffffff;
36 #endif ADDR32
37 #ifdef ADDR16
38 char	*_minptr = (char *)0xffff;
39 #endif ADDR16
40 char	*_maxptr = (char *)0;
41 long	*_pcpcount = (long *)0;
42 long	_cntrs = 0;
43 long	_rtns = 0;
44 
45 /*
46  * standard files
47  */
48 char		_inwin, _outwin, _errwin;
49 struct iorechd	_err = {
50 	&_errwin,		/* fileptr */
51 	0,			/* lcount  */
52 	0x7fffffff,		/* llimit  */
53 	stderr,			/* fbuf    */
54 	FILNIL,			/* fchain  */
55 	STDLVL,			/* flev    */
56 	"Message file",		/* pfname  */
57 	FTEXT | FWRITE | EOFF,	/* funit   */
58 	2,			/* fblk    */
59 	1			/* fsize   */
60 };
61 struct iorechd	output = {
62 	&_outwin,		/* fileptr */
63 	0,			/* lcount  */
64 	0x7fffffff,		/* llimit  */
65 	stdout,			/* fbuf    */
66 	ERR,			/* fchain  */
67 	STDLVL,			/* flev    */
68 	"standard output",	/* pfname  */
69 	FTEXT | FWRITE | EOFF,	/* funit   */
70 	1,			/* fblk    */
71 	1			/* fsize   */
72 };
73 struct iorechd	input = {
74 	&_inwin,		/* fileptr */
75 	0,			/* lcount  */
76 	0x7fffffff,		/* llimit  */
77 	stdin,			/* fbuf    */
78 	OUTPUT,			/* fchain  */
79 	STDLVL,			/* flev    */
80 	"standard input",	/* pfname  */
81 	FTEXT|FREAD|SYNC|EOLN,	/* funit   */
82 	0,			/* fblk    */
83 	1			/* fsize   */
84 };
85 
86 /*
87  * file record variables
88  */
89 long		_filefre = PREDEF;
90 struct iorechd	_fchain = {
91 	0, 0, 0, 0,		/* only use fchain field */
92 	INPUT			/* fchain  */
93 };
94 struct iorec	*_actfile[MAXFILES] = {
95 	INPUT,
96 	OUTPUT,
97 	ERR
98 };
99 
100 /*
101  * stuff for pdx to watch what the interpreter is doing.
102  * The .globl is #ifndef DBX since it breaks DBX to have a global
103  * asm label in the middle of a function (see _loopaddr: below).
104  */
105 
106 union progcntr pdx_pc;
107 #ifndef DBX
108 asm(".globl _loopaddr");
109 #endif DBX
110 
111 /*
112  * Px profile array
113  */
114 #ifdef PROFILE
115 long _profcnts[NUMOPS];
116 #endif PROFILE
117 
118 /*
119  * debugging variables
120  */
121 #ifdef PXDEBUG
122 char opc[10];
123 long opcptr = 9;
124 #endif PXDEBUG
125 
126 void
127 interpreter(base)
128 	char *base;
129 {
130 	/* register */ union progcntr pc;	/* interpreted program cntr */
131 	struct iorec *curfile;		/* active file */
132 	register struct blockmark *stp;	/* active stack frame ptr */
133 	/*
134 	 * the following variables are used as scratch
135 	 */
136 	register char *tcp;
137 	register short *tsp;
138 	register long tl, tl1, tl2, tl3;
139 	char *tcp2;
140 	long tl4;
141 	double td, td1;
142 	struct sze8 t8;
143 	register short *tsp1;
144 	long *tlp;
145 	char *tcp1;
146 	bool tb;
147 	struct blockmark *tstp;
148 	register struct formalrtn *tfp;
149 	struct iorec **ip;
150 	int mypid;
151 	int ti, ti2;
152 	short ts;
153 	FILE *tf;
154 	/* register */ union progcntr stack;	/* Interpreted stack */
155 
156 	mypid = getpid();
157 
158 	/*
159 	 * Setup sets up any hardware specific parameters before
160 	 * starting the interpreter. Typically this is macro- or inline-
161 	 * replaced by "machdep.h" or interp.sed.
162 	 */
163 	setup();
164 	/*
165 	 * necessary only on systems which do not initialize
166 	 * memory to zero
167 	 */
168 	for (ip = &_actfile[3]; ip < &_actfile[MAXFILES]; *ip++ = FILNIL)
169 		/* void */;
170 	/*
171 	 * set up global environment, then ``call'' the main program
172 	 */
173 	STACKALIGN(tl, 2 * sizeof(struct iorec *));
174 	_display.frame[0].locvars = pushsp(tl);
175 	_display.frame[0].locvars += 2 * sizeof(struct iorec *);
176 	*(struct iorec **)(_display.frame[0].locvars + OUTPUT_OFF) = OUTPUT;
177 	*(struct iorec **)(_display.frame[0].locvars + INPUT_OFF) = INPUT;
178 	STACKALIGN(tl, sizeof(struct blockmark));
179 	stp = (struct blockmark *)pushsp(tl);
180 	_dp = &_display.frame[0];
181 	pc.cp = base;
182 
183 	for(;;) {
184 #		ifdef PXDEBUG
185 		if (++opcptr == 10)
186 			opcptr = 0;
187 		opc[opcptr] = *pc.ucp;
188 #		endif PXDEBUG
189 #		ifdef PROFILE
190 		_profcnts[*pc.ucp]++;
191 #		endif PROFILE
192 
193 		/*
194 		 * Save away the program counter to a fixed location for pdx.
195 		 */
196 		pdx_pc = pc;
197 
198 		/*
199 		 * Having the label below makes dbx not work
200 		 * to debug this interpreter,
201 		 * since it thinks a new function called loopaddr()
202 		 * has started here, and it won't display the local
203 		 * variables of interpreter().  You have to compile
204 		 * -DDBX to avoid this problem...
205 		 */
206 #		ifndef DBX
207 	;asm("_loopaddr:");
208 #		endif DBX
209 
210 		switch (*pc.ucp++) {
211 		case O_BPT:			/* breakpoint trap */
212 			PFLUSH();
213 			kill(mypid, SIGILL);
214 			pc.ucp--;
215 			continue;
216 		case O_NODUMP:
217 			_nodump = TRUE;
218 			/* and fall through */
219 		case O_BEG:
220 			_dp += 1;		/* enter local scope */
221 			stp->odisp = *_dp;	/* save old display value */
222 			tl = *pc.ucp++;		/* tl = name size */
223 			stp->entry = pc.hdrp;	/* pointer to entry info */
224 			tl1 = pc.hdrp->framesze;/* tl1 = size of frame */
225 			_lino = pc.hdrp->offset;
226 			_runtst = pc.hdrp->tests;
227 			disableovrflo();
228 			if (_runtst)
229 				enableovrflo();
230 			pc.cp += (int)tl;	/* skip over proc hdr info */
231 			stp->file = curfile;	/* save active file */
232 			STACKALIGN(tl2, tl1);
233 			tcp = pushsp(tl2);	/* tcp = new top of stack */
234 			if (_runtst)		/* zero stack frame */
235 				blkclr(tcp, tl1);
236 			tcp += (int)tl1;	/* offsets of locals are neg */
237 			_dp->locvars = tcp;	/* set new display pointer */
238 			_dp->stp = stp;
239 			stp->tos = pushsp((long)0); /* set tos pointer */
240 			continue;
241 		case O_END:
242 			PCLOSE(_dp->locvars);	/* flush & close local files */
243 			stp = _dp->stp;
244 			curfile = stp->file;	/* restore old active file */
245 			*_dp = stp->odisp;	/* restore old display entry */
246 			if (_dp == &_display.frame[1])
247 				return;		/* exiting main proc ??? */
248 			_lino = stp->lino;	/* restore lino, pc, dp */
249 			pc.cp = stp->pc;
250 			_dp = stp->dp;
251 			_runtst = stp->entry->tests;
252 			disableovrflo();
253 			if (_runtst)
254 				enableovrflo();
255 			STACKALIGN(tl, stp->entry->framesze);
256 			STACKALIGN(tl1, sizeof(struct blockmark));
257 			popsp(tl +		/* pop local vars */
258 			     tl1 +		/* pop stack frame */
259 			     stp->entry->nargs);/* pop parms */
260 			continue;
261 		case O_CALL:
262 			tl = *pc.cp++;
263 			PCLONGVAL(tl1);
264 			tcp = base + tl1 + sizeof(short);/* new entry point */
265 			GETLONGVAL(tl1, tcp);
266 			tcp = base + tl1;
267 			STACKALIGN(tl1, sizeof(struct blockmark));
268 			stp = (struct blockmark *)pushsp(tl1);
269 			stp->lino = _lino;	/* save lino, pc, dp */
270 			stp->pc = pc.cp;
271 			stp->dp = _dp;
272 			_dp = &_display.frame[tl]; /* set up new display ptr */
273 			pc.cp = tcp;
274 			continue;
275 		case O_FCALL:
276 			pc.cp++;
277  			tcp = popaddr(); /* ptr to display save area */
278 			tfp = (struct formalrtn *)popaddr();
279 			STACKALIGN(tl, sizeof(struct blockmark));
280 			stp = (struct blockmark *)pushsp(tl);
281 			stp->lino = _lino;	/* save lino, pc, dp */
282 			stp->pc = pc.cp;
283 			stp->dp = _dp;
284 			pc.cp = (char *)(tfp->fentryaddr);/* new entry point */
285 			_dp = &_display.frame[tfp->fbn];/* new display ptr */
286  			blkcpy(&_display.frame[1], tcp,
287 				tfp->fbn * sizeof(struct dispsave));
288 			blkcpy(&tfp->fdisp[0], &_display.frame[1],
289 				tfp->fbn * sizeof(struct dispsave));
290 			continue;
291 		case O_FRTN:
292 			tl = *pc.cp++;		/* tl = size of return obj */
293 			if (tl == 0)
294 				tl = *pc.usp++;
295 			tcp = pushsp((long)(0));
296 			tfp = *(struct formalrtn **)(tcp + tl);
297  			tcp1 = *(char **)
298  			    (tcp + tl + sizeof(struct formalrtn *));
299 			if (tl != 0) {
300 				blkcpy(tcp, tcp + sizeof(struct formalrtn *)
301 				    + sizeof(char *), tl);
302 			}
303 			STACKALIGN(tl,
304 				sizeof(struct formalrtn *) + sizeof (char *));
305  			popsp(tl);
306  			blkcpy(tcp1, &_display.frame[1],
307 			    tfp->fbn * sizeof(struct dispsave));
308 			continue;
309 		case O_FSAV:
310 			tfp = (struct formalrtn *)popaddr();
311 			tfp->fbn = *pc.cp++;	/* blk number of routine */
312 			PCLONGVAL(tl);
313 			tcp = base + tl + sizeof(short);/* new entry point */
314 			GETLONGVAL(tl, tcp);
315 			tfp->fentryaddr = (long (*)())(base + tl);
316 			blkcpy(&_display.frame[1], &tfp->fdisp[0],
317 				tfp->fbn * sizeof(struct dispsave));
318 			pushaddr(tfp);
319 			continue;
320 		case O_SDUP2:
321 			pc.cp++;
322 			tl = pop2();
323 			push2((short)(tl));
324 			push2((short)(tl));
325 			continue;
326 		case O_SDUP4:
327 			pc.cp++;
328 			tl = pop4();
329 			push4(tl);
330 			push4(tl);
331 			continue;
332 		case O_TRA:
333 			pc.cp++;
334 			pc.cp += *pc.sp;
335 			continue;
336 		case O_TRA4:
337 			pc.cp++;
338 			PCLONGVAL(tl);
339 			pc.cp = base + tl;
340 			continue;
341 		case O_GOTO:
342 			tstp = _display.frame[*pc.cp++].stp; /* ptr to
343 								exit frame */
344 			PCLONGVAL(tl);
345 			pc.cp = base + tl;
346 			stp = _dp->stp;
347 			while (tstp != stp) {
348 				if (_dp == &_display.frame[1])
349 					ERROR("Active frame not found in non-local goto\n", 0); /* exiting prog ??? */
350 				PCLOSE(_dp->locvars); /* close local files */
351 				curfile = stp->file;  /* restore active file */
352 				*_dp = stp->odisp;    /* old display entry */
353 				_dp = stp->dp;	      /* restore dp */
354 				stp = _dp->stp;
355 			}
356 			/* pop locals, stack frame, parms, and return values */
357 			popsp((long)(stp->tos - pushsp((long)(0))));
358 			continue;
359 		case O_LINO:
360 			if (_dp->stp->tos != pushsp((long)(0)))
361 				ERROR("Panic: stack not empty between statements\n");
362 			_lino = *pc.cp++;	/* set line number */
363 			if (_lino == 0)
364 				_lino = *pc.sp++;
365 			if (_runtst) {
366 				LINO();		/* inc statement count */
367 				continue;
368 			}
369 			_stcnt++;
370 			continue;
371 		case O_PUSH:
372 			tl = *pc.cp++;
373 			if (tl == 0)
374 				PCLONGVAL(tl);
375 			STACKALIGN(tl1, -tl);
376 			tcp = pushsp(tl1);
377 			if (_runtst)
378 				blkclr(tcp, tl1);
379 			continue;
380 		case O_IF:
381 			pc.cp++;
382 			if (pop2()) {
383 				pc.sp++;
384 				continue;
385 			}
386 			pc.cp += *pc.sp;
387 			continue;
388 		case O_REL2:
389 			tl = pop2();
390 			tl1 = pop2();
391 			goto cmplong;
392 		case O_REL24:
393 			tl = pop2();
394 			tl1 = pop4();
395 			goto cmplong;
396 		case O_REL42:
397 			tl = pop4();
398 			tl1 = pop2();
399 			goto cmplong;
400 		case O_REL4:
401 			tl = pop4();
402 			tl1 = pop4();
403 		cmplong:
404 			switch (*pc.cp++) {
405 			case releq:
406 				push2(tl1 == tl);
407 				continue;
408 			case relne:
409 				push2(tl1 != tl);
410 				continue;
411 			case rellt:
412 				push2(tl1 < tl);
413 				continue;
414 			case relgt:
415 				push2(tl1 > tl);
416 				continue;
417 			case relle:
418 				push2(tl1 <= tl);
419 				continue;
420 			case relge:
421 				push2(tl1 >= tl);
422 				continue;
423 			default:
424 				ERROR("Panic: bad relation %d to REL4*\n",
425 				    *(pc.cp - 1));
426 				continue;
427 			}
428 		case O_RELG:
429 			tl2 = *pc.cp++;		/* tc has jump opcode */
430 			tl = *pc.usp++;		/* tl has comparison length */
431 			STACKALIGN(tl1, tl);	/* tl1 has arg stack length */
432 			tcp = pushsp((long)(0));/* tcp pts to first arg */
433 			switch (tl2) {
434 			case releq:
435 				tb = RELEQ(tl, tcp + tl1, tcp);
436 				break;
437 			case relne:
438 				tb = RELNE(tl, tcp + tl1, tcp);
439 				break;
440 			case rellt:
441 				tb = RELSLT(tl, tcp + tl1, tcp);
442 				break;
443 			case relgt:
444 				tb = RELSGT(tl, tcp + tl1, tcp);
445 				break;
446 			case relle:
447 				tb = RELSLE(tl, tcp + tl1, tcp);
448 				break;
449 			case relge:
450 				tb = RELSGE(tl, tcp + tl1, tcp);
451 				break;
452 			default:
453 				ERROR("Panic: bad relation %d to RELG*\n", tl2);
454 				break;
455 			}
456 			popsp(tl1 << 1);
457 			push2((short)(tb));
458 			continue;
459 		case O_RELT:
460 			tl2 = *pc.cp++;		/* tc has jump opcode */
461 			tl1 = *pc.usp++;	/* tl1 has comparison length */
462 			tcp = pushsp((long)(0));/* tcp pts to first arg */
463 			switch (tl2) {
464 			case releq:
465 				tb = RELEQ(tl1, tcp + tl1, tcp);
466 				break;
467 			case relne:
468 				tb = RELNE(tl1, tcp + tl1, tcp);
469 				break;
470 			case rellt:
471 				tb = RELTLT(tl1, tcp + tl1, tcp);
472 				break;
473 			case relgt:
474 				tb = RELTGT(tl1, tcp + tl1, tcp);
475 				break;
476 			case relle:
477 				tb = RELTLE(tl1, tcp + tl1, tcp);
478 				break;
479 			case relge:
480 				tb = RELTGE(tl1, tcp + tl1, tcp);
481 				break;
482 			default:
483 				ERROR("Panic: bad relation %d to RELT*\n", tl2);
484 				break;
485 			}
486 			STACKALIGN(tl, tl1);
487 			popsp(tl << 1);
488 			push2((short)(tb));
489 			continue;
490 		case O_REL28:
491 			td = pop2();
492 			td1 = pop8();
493 			goto cmpdbl;
494 		case O_REL48:
495 			td = pop4();
496 			td1 = pop8();
497 			goto cmpdbl;
498 		case O_REL82:
499 			td = pop8();
500 			td1 = pop2();
501 			goto cmpdbl;
502 		case O_REL84:
503 			td = pop8();
504 			td1 = pop4();
505 			goto cmpdbl;
506 		case O_REL8:
507 			td = pop8();
508 			td1 = pop8();
509 		cmpdbl:
510 			switch (*pc.cp++) {
511 			case releq:
512 				push2(td1 == td);
513 				continue;
514 			case relne:
515 				push2(td1 != td);
516 				continue;
517 			case rellt:
518 				push2(td1 < td);
519 				continue;
520 			case relgt:
521 				push2(td1 > td);
522 				continue;
523 			case relle:
524 				push2(td1 <= td);
525 				continue;
526 			case relge:
527 				push2(td1 >= td);
528 				continue;
529 			default:
530 				ERROR("Panic: bad relation %d to REL8*\n",
531 				    *(pc.cp - 1));
532 				continue;
533 			}
534 		case O_AND:
535 			pc.cp++;
536 			tl = pop2();
537 			tl1 = pop2();
538 			push2(tl1 & tl);
539 			continue;
540 		case O_OR:
541 			pc.cp++;
542 			tl = pop2();
543 			tl1 = pop2();
544 			push2(tl1 | tl);
545 			continue;
546 		case O_NOT:
547 			pc.cp++;
548 			tl = pop2();
549 			push2(tl ^ 1);
550 			continue;
551 		case O_AS2:
552 			pc.cp++;
553 			tl = pop2();
554 			*(short *)popaddr() = tl;
555 			continue;
556 		case O_AS4:
557 			pc.cp++;
558 			tl = pop4();
559 			*(long *)popaddr() = tl;
560 			continue;
561 		case O_AS24:
562 			pc.cp++;
563 			tl = pop2();
564 			*(long *)popaddr() = tl;
565 			continue;
566 		case O_AS42:
567 			pc.cp++;
568 			tl = pop4();
569 			*(short *)popaddr() = tl;
570 			continue;
571 		case O_AS21:
572 			pc.cp++;
573 			tl = pop2();
574 			*popaddr() = tl;
575 			continue;
576 		case O_AS41:
577 			pc.cp++;
578 			tl = pop4();
579 			*popaddr() = tl;
580 			continue;
581 		case O_AS28:
582 			pc.cp++;
583 			tl = pop2();
584 			*(double *)popaddr() = tl;
585 			continue;
586 		case O_AS48:
587 			pc.cp++;
588 			tl = pop4();
589 			*(double *)popaddr() = tl;
590 			continue;
591 		case O_AS8:
592 			pc.cp++;
593 			t8 = popsze8();
594 			*(struct sze8 *)popaddr() = t8;
595 			continue;
596 		case O_AS:
597 			tl = *pc.cp++;
598 			if (tl == 0)
599 				tl = *pc.usp++;
600 			STACKALIGN(tl1, tl);
601 			tcp = pushsp((long)(0));
602 			blkcpy(tcp, *(char **)(tcp + tl1), tl);
603 			popsp(tl1 + sizeof(char *));
604 			continue;
605 		case O_VAS:
606 			pc.cp++;
607 			tl = pop4();
608 			tcp1 = popaddr();
609 			tcp = popaddr();
610 			blkcpy(tcp1, tcp, tl);
611 			continue;
612 		case O_INX2P2:
613 			tl = *pc.cp++;		/* tl has shift amount */
614 			tl1 = pop2();
615 			tl1 = (tl1 - *pc.sp++) << tl;
616 			tcp = popaddr();
617 			pushaddr(tcp + tl1);
618 			continue;
619 		case O_INX4P2:
620 			tl = *pc.cp++;		/* tl has shift amount */
621 			tl1 = pop4();
622 			tl1 = (tl1 - *pc.sp++) << tl;
623 			tcp = popaddr();
624 			pushaddr(tcp + tl1);
625 			continue;
626 		case O_INX2:
627 			tl = *pc.cp++;		/* tl has element size */
628 			if (tl == 0)
629 				tl = *pc.usp++;
630 			tl1 = pop2();		/* index */
631 			tl2 = *pc.sp++;
632 			tcp = popaddr();
633 			pushaddr(tcp + (tl1 - tl2) * tl);
634 			tl = *pc.usp++;
635 			if (_runtst)
636 				SUBSC(tl1, tl2, tl); /* range check */
637 			continue;
638 		case O_INX4:
639 			tl = *pc.cp++;		/* tl has element size */
640 			if (tl == 0)
641 				tl = *pc.usp++;
642 			tl1 = pop4();		/* index */
643 			tl2 = *pc.sp++;
644 			tcp = popaddr();
645 			pushaddr(tcp + (tl1 - tl2) * tl);
646 			tl = *pc.usp++;
647 			if (_runtst)
648 				SUBSC(tl1, tl2, tl); /* range check */
649 			continue;
650 		case O_VINX2:
651 			pc.cp++;
652 			tl = pop2();		/* tl has element size */
653 			tl1 = pop2();		/* upper bound */
654 			tl2 = pop2();		/* lower bound */
655 			tl3 = pop2();		/* index */
656 			tcp = popaddr();
657 			pushaddr(tcp + (tl3 - tl2) * tl);
658 			if (_runtst)
659 				SUBSC(tl3, tl2, tl1); /* range check */
660 			continue;
661 		case O_VINX24:
662 			pc.cp++;
663 			tl = pop2();		/* tl has element size */
664 			tl1 = pop2();		/* upper bound */
665 			tl2 = pop2();		/* lower bound */
666 			tl3 = pop4();		/* index */
667 			tcp = popaddr();
668 			pushaddr(tcp + (tl3 - tl2) * tl);
669 			if (_runtst)
670 				SUBSC(tl3, tl2, tl1); /* range check */
671 			continue;
672 		case O_VINX42:
673 			pc.cp++;
674 			tl = pop4();		/* tl has element size */
675 			tl1 = pop4();		/* upper bound */
676 			tl2 = pop4();		/* lower bound */
677 			tl3 = pop2();		/* index */
678 			tcp = popaddr();
679 			pushaddr(tcp + (tl3 - tl2) * tl);
680 			if (_runtst)
681 				SUBSC(tl3, tl2, tl1); /* range check */
682 			continue;
683 		case O_VINX4:
684 			pc.cp++;
685 			tl = pop4();		/* tl has element size */
686 			tl1 = pop4();		/* upper bound */
687 			tl2 = pop4();		/* lower bound */
688 			tl3 = pop4();		/* index */
689 			tcp = popaddr();
690 			pushaddr(tcp + (tl3 - tl2) * tl);
691 			if (_runtst)
692 				SUBSC(tl3, tl2, tl1); /* range check */
693 			continue;
694 		case O_OFF:
695 			tl = *pc.cp++;
696 			if (tl == 0)
697 				tl = *pc.usp++;
698 			tcp = popaddr();
699 			pushaddr(tcp + tl);
700 			continue;
701 		case O_NIL:
702 			pc.cp++;
703 			tcp = popaddr();
704 			NIL(tcp);
705 			pushaddr(tcp);
706 			continue;
707 		case O_ADD2:
708 			pc.cp++;
709 			tl = pop2();
710 			tl1 = pop2();
711 			push4(tl1 + tl);
712 			continue;
713 		case O_ADD4:
714 			pc.cp++;
715 			tl = pop4();
716 			tl1 = pop4();
717 			push4(tl1 + tl);
718 			continue;
719 		case O_ADD24:
720 			pc.cp++;
721 			tl = pop2();
722 			tl1 = pop4();
723 			push4(tl1 + tl);
724 			continue;
725 		case O_ADD42:
726 			pc.cp++;
727 			tl = pop4();
728 			tl1 = pop2();
729 			push4(tl1 + tl);
730 			continue;
731 		case O_ADD28:
732 			pc.cp++;
733 			tl = pop2();
734 			td = pop8();
735 			push8(td + tl);
736 			continue;
737 		case O_ADD48:
738 			pc.cp++;
739 			tl = pop4();
740 			td = pop8();
741 			push8(td + tl);
742 			continue;
743 		case O_ADD82:
744 			pc.cp++;
745 			td = pop8();
746 			td1 = pop2();
747 			push8(td1 + td);
748 			continue;
749 		case O_ADD84:
750 			pc.cp++;
751 			td = pop8();
752 			td1 = pop4();
753 			push8(td1 + td);
754 			continue;
755 		case O_SUB2:
756 			pc.cp++;
757 			tl = pop2();
758 			tl1 = pop2();
759 			push4(tl1 - tl);
760 			continue;
761 		case O_SUB4:
762 			pc.cp++;
763 			tl = pop4();
764 			tl1 = pop4();
765 			push4(tl1 - tl);
766 			continue;
767 		case O_SUB24:
768 			pc.cp++;
769 			tl = pop2();
770 			tl1 = pop4();
771 			push4(tl1 - tl);
772 			continue;
773 		case O_SUB42:
774 			pc.cp++;
775 			tl = pop4();
776 			tl1 = pop2();
777 			push4(tl1 - tl);
778 			continue;
779 		case O_SUB28:
780 			pc.cp++;
781 			tl = pop2();
782 			td = pop8();
783 			push8(td - tl);
784 			continue;
785 		case O_SUB48:
786 			pc.cp++;
787 			tl = pop4();
788 			td = pop8();
789 			push8(td - tl);
790 			continue;
791 		case O_SUB82:
792 			pc.cp++;
793 			td = pop8();
794 			td1 = pop2();
795 			push8(td1 - td);
796 			continue;
797 		case O_SUB84:
798 			pc.cp++;
799 			td = pop8();
800 			td1 = pop4();
801 			push8(td1 - td);
802 			continue;
803 		case O_MUL2:
804 			pc.cp++;
805 			tl = pop2();
806 			tl1 = pop2();
807 			push4(tl1 * tl);
808 			continue;
809 		case O_MUL4:
810 			pc.cp++;
811 			tl = pop4();
812 			tl1 = pop4();
813 			push4(tl1 * tl);
814 			continue;
815 		case O_MUL24:
816 			pc.cp++;
817 			tl = pop2();
818 			tl1 = pop4();
819 			push4(tl1 * tl);
820 			continue;
821 		case O_MUL42:
822 			pc.cp++;
823 			tl = pop4();
824 			tl1 = pop2();
825 			push4(tl1 * tl);
826 			continue;
827 		case O_MUL28:
828 			pc.cp++;
829 			tl = pop2();
830 			td = pop8();
831 			push8(td * tl);
832 			continue;
833 		case O_MUL48:
834 			pc.cp++;
835 			tl = pop4();
836 			td = pop8();
837 			push8(td * tl);
838 			continue;
839 		case O_MUL82:
840 			pc.cp++;
841 			td = pop8();
842 			td1 = pop2();
843 			push8(td1 * td);
844 			continue;
845 		case O_MUL84:
846 			pc.cp++;
847 			td = pop8();
848 			td1 = pop4();
849 			push8(td1 * td);
850 			continue;
851 		case O_ABS2:
852 		case O_ABS4:
853 			pc.cp++;
854 			tl = pop4();
855 			push4(tl >= 0 ? tl : -tl);
856 			continue;
857 		case O_ABS8:
858 			pc.cp++;
859 			td = pop8();
860 			push8(td >= 0.0 ? td : -td);
861 			continue;
862 		case O_NEG2:
863 			pc.cp++;
864 			ts = -pop2();
865 			push4((long)ts);
866 			continue;
867 		case O_NEG4:
868 			pc.cp++;
869 			tl = -pop4();
870 			push4(tl);
871 			continue;
872 		case O_NEG8:
873 			pc.cp++;
874 			td = -pop8();
875 			push8(td);
876 			continue;
877 		case O_DIV2:
878 			pc.cp++;
879 			tl = pop2();
880 			tl1 = pop2();
881 			push4(tl1 / tl);
882 			continue;
883 		case O_DIV4:
884 			pc.cp++;
885 			tl = pop4();
886 			tl1 = pop4();
887 			push4(tl1 / tl);
888 			continue;
889 		case O_DIV24:
890 			pc.cp++;
891 			tl = pop2();
892 			tl1 = pop4();
893 			push4(tl1 / tl);
894 			continue;
895 		case O_DIV42:
896 			pc.cp++;
897 			tl = pop4();
898 			tl1 = pop2();
899 			push4(tl1 / tl);
900 			continue;
901 		case O_MOD2:
902 			pc.cp++;
903 			tl = pop2();
904 			tl1 = pop2();
905 			push4(tl1 % tl);
906 			continue;
907 		case O_MOD4:
908 			pc.cp++;
909 			tl = pop4();
910 			tl1 = pop4();
911 			push4(tl1 % tl);
912 			continue;
913 		case O_MOD24:
914 			pc.cp++;
915 			tl = pop2();
916 			tl1 = pop4();
917 			push4(tl1 % tl);
918 			continue;
919 		case O_MOD42:
920 			pc.cp++;
921 			tl = pop4();
922 			tl1 = pop2();
923 			push4(tl1 % tl);
924 			continue;
925 		case O_ADD8:
926 			pc.cp++;
927 			td = pop8();
928 			td1 = pop8();
929 			push8(td1 + td);
930 			continue;
931 		case O_SUB8:
932 			pc.cp++;
933 			td = pop8();
934 			td1 = pop8();
935 			push8(td1 - td);
936 			continue;
937 		case O_MUL8:
938 			pc.cp++;
939 			td = pop8();
940 			td1 = pop8();
941 			push8(td1 * td);
942 			continue;
943 		case O_DVD8:
944 			pc.cp++;
945 			td = pop8();
946 			td1 = pop8();
947 			push8(td1 / td);
948 			continue;
949 		case O_STOI:
950 			pc.cp++;
951 			ts = pop2();
952 			push4((long)ts);
953 			continue;
954 		case O_STOD:
955 			pc.cp++;
956 			td = pop2();
957 			push8(td);
958 			continue;
959 		case O_ITOD:
960 			pc.cp++;
961 			td = pop4();
962 			push8(td);
963 			continue;
964 		case O_ITOS:
965 			pc.cp++;
966 			tl = pop4();
967 			push2((short)tl);
968 			continue;
969 		case O_DVD2:
970 			pc.cp++;
971 			td = pop2();
972 			td1 = pop2();
973 			push8(td1 / td);
974 			continue;
975 		case O_DVD4:
976 			pc.cp++;
977 			td = pop4();
978 			td1 = pop4();
979 			push8(td1 / td);
980 			continue;
981 		case O_DVD24:
982 			pc.cp++;
983 			td = pop2();
984 			td1 = pop4();
985 			push8(td1 / td);
986 			continue;
987 		case O_DVD42:
988 			pc.cp++;
989 			td = pop4();
990 			td1 = pop2();
991 			push8(td1 / td);
992 			continue;
993 		case O_DVD28:
994 			pc.cp++;
995 			td = pop2();
996 			td1 = pop8();
997 			push8(td1 / td);
998 			continue;
999 		case O_DVD48:
1000 			pc.cp++;
1001 			td = pop4();
1002 			td1 = pop8();
1003 			push8(td1 / td);
1004 			continue;
1005 		case O_DVD82:
1006 			pc.cp++;
1007 			td = pop8();
1008 			td1 = pop2();
1009 			push8(td1 / td);
1010 			continue;
1011 		case O_DVD84:
1012 			pc.cp++;
1013 			td = pop8();
1014 			td1 = pop4();
1015 			push8(td1 / td);
1016 			continue;
1017 		case O_RV1:
1018 			tcp = _display.raw[*pc.ucp++];
1019 			push2((short)(*(tcp + *pc.sp++)));
1020 			continue;
1021 		case O_RV14:
1022 			tcp = _display.raw[*pc.ucp++];
1023 			push4((long)(*(tcp + *pc.sp++)));
1024 			continue;
1025 		case O_RV2:
1026 			tcp = _display.raw[*pc.ucp++];
1027 			push2(*(short *)(tcp + *pc.sp++));
1028 			continue;
1029 		case O_RV24:
1030 			tcp = _display.raw[*pc.ucp++];
1031 			push4((long)(*(short *)(tcp + *pc.sp++)));
1032 			continue;
1033 		case O_RV4:
1034 			tcp = _display.raw[*pc.ucp++];
1035 			push4(*(long *)(tcp + *pc.sp++));
1036 			continue;
1037 		case O_RV8:
1038 			tcp = _display.raw[*pc.ucp++];
1039 			pushsze8(*(struct sze8 *)(tcp + *pc.sp++));
1040 			continue;
1041 		case O_RV:
1042 			tcp = _display.raw[*pc.ucp++];
1043 			tcp += *pc.sp++;
1044 			tl = *pc.usp++;
1045 			STACKALIGN(tl1, tl);
1046 			tcp1 = pushsp(tl1);
1047 			blkcpy(tcp, tcp1, tl);
1048 			continue;
1049 		case O_LV:
1050 			tcp = _display.raw[*pc.ucp++];
1051 			pushaddr(tcp + *pc.sp++);
1052 			continue;
1053 		case O_LRV1:
1054 			tcp = _display.raw[*pc.ucp++];
1055 			PCLONGVAL(tl);
1056 			push2((short)(*(tcp + tl)));
1057 			continue;
1058 		case O_LRV14:
1059 			tcp = _display.raw[*pc.ucp++];
1060 			PCLONGVAL(tl);
1061 			push4((long)(*(tcp + tl)));
1062 			continue;
1063 		case O_LRV2:
1064 			tcp = _display.raw[*pc.ucp++];
1065 			PCLONGVAL(tl);
1066 			push2(*(short *)(tcp + tl));
1067 			continue;
1068 		case O_LRV24:
1069 			tcp = _display.raw[*pc.ucp++];
1070 			PCLONGVAL(tl);
1071 			push4((long)(*(short *)(tcp + tl)));
1072 			continue;
1073 		case O_LRV4:
1074 			tcp = _display.raw[*pc.ucp++];
1075 			PCLONGVAL(tl);
1076 			push4(*(long *)(tcp + tl));
1077 			continue;
1078 		case O_LRV8:
1079 			tcp = _display.raw[*pc.ucp++];
1080 			PCLONGVAL(tl);
1081 			pushsze8(*(struct sze8 *)(tcp + tl));
1082 			continue;
1083 		case O_LRV:
1084 			tcp = _display.raw[*pc.ucp++];
1085 			PCLONGVAL(tl);
1086 			tcp += tl;
1087 			tl = *pc.usp++;
1088 			STACKALIGN(tl1, tl);
1089 			tcp1 = pushsp(tl1);
1090 			blkcpy(tcp, tcp1, tl);
1091 			continue;
1092 		case O_LLV:
1093 			tcp = _display.raw[*pc.ucp++];
1094 			PCLONGVAL(tl);
1095 			pushaddr(tcp + tl);
1096 			continue;
1097 		case O_IND1:
1098 			pc.cp++;
1099 			ts = *popaddr();
1100 			push2(ts);
1101 			continue;
1102 		case O_IND14:
1103 			pc.cp++;
1104 			ti = *popaddr();
1105 			push4((long)ti);
1106 			continue;
1107 		case O_IND2:
1108 			pc.cp++;
1109 			ts = *(short *)(popaddr());
1110 			push2(ts);
1111 			continue;
1112 		case O_IND24:
1113 			pc.cp++;
1114 			ts = *(short *)(popaddr());
1115 			push4((long)ts);
1116 			continue;
1117 		case O_IND4:
1118 			pc.cp++;
1119 			tl = *(long *)(popaddr());
1120 			push4(tl);
1121 			continue;
1122 		case O_IND8:
1123 			pc.cp++;
1124 			t8 = *(struct sze8 *)(popaddr());
1125 			pushsze8(t8);
1126 			continue;
1127 		case O_IND:
1128 			tl = *pc.cp++;
1129 			if (tl == 0)
1130 				tl = *pc.usp++;
1131 			tcp = popaddr();
1132 			STACKALIGN(tl1, tl);
1133 			tcp1 = pushsp(tl1);
1134 			blkcpy(tcp, tcp1, tl);
1135 			continue;
1136 		case O_CON1:
1137 			push2((short)(*pc.cp++));
1138 			continue;
1139 		case O_CON14:
1140 			push4((long)(*pc.cp++));
1141 			continue;
1142 		case O_CON2:
1143 			pc.cp++;
1144 			push2(*pc.sp++);
1145 			continue;
1146 		case O_CON24:
1147 			pc.cp++;
1148 			push4((long)(*pc.sp++));
1149 			continue;
1150 		case O_CON4:
1151 			pc.cp++;
1152 			PCLONGVAL(tl);
1153 			push4(tl);
1154 			continue;
1155 		case O_CON8:
1156 			pc.cp++;
1157 			tcp = pushsp(sizeof(double));
1158 			blkcpy(pc.cp, tcp, sizeof(double));
1159 			pc.dbp++;
1160 			continue;
1161 		case O_CON:
1162 			tl = *pc.cp++;
1163 			if (tl == 0)
1164 				tl = *pc.usp++;
1165 			STACKALIGN(tl1, tl);
1166 			tcp = pushsp(tl1);
1167 			blkcpy(pc.cp, tcp, tl);
1168 			pc.cp += (int)tl;
1169 			continue;
1170 		case O_CONG:
1171 			tl = *pc.cp++;
1172 			if (tl == 0)
1173 				tl = *pc.usp++;
1174 			STACKALIGN(tl1, tl);
1175 			tcp = pushsp(tl1);
1176 			blkcpy(pc.cp, tcp, tl1);
1177 			pc.cp += (int)((tl + 2) & ~1);
1178 			continue;
1179 		case O_LVCON:
1180 			tl = *pc.cp++;
1181 			if (tl == 0)
1182 				tl = *pc.usp++;
1183 			pushaddr(pc.cp);
1184 			tl = (tl + 1) & ~1;
1185 			pc.cp += (int)tl;
1186 			continue;
1187 		case O_RANG2:
1188 			tl = *pc.cp++;
1189 			if (tl == 0)
1190 				tl = *pc.sp++;
1191 			tl1 = pop2();
1192 			push2((short)(RANG4(tl1, tl, (long)(*pc.sp++))));
1193 			continue;
1194 		case O_RANG42:
1195 			tl = *pc.cp++;
1196 			if (tl == 0)
1197 				tl = *pc.sp++;
1198 			tl1 = pop4();
1199 			push4(RANG4(tl1, tl, (long)(*pc.sp++)));
1200 			continue;
1201 		case O_RSNG2:
1202 			tl = *pc.cp++;
1203 			if (tl == 0)
1204 				tl = *pc.sp++;
1205 			tl1 = pop2();
1206 			push2((short)(RSNG4(tl1, tl)));
1207 			continue;
1208 		case O_RSNG42:
1209 			tl = *pc.cp++;
1210 			if (tl == 0)
1211 				tl = *pc.sp++;
1212 			tl1 = pop4();
1213 			push4(RSNG4(tl1, tl));
1214 			continue;
1215 		case O_RANG4:
1216 			tl = *pc.cp++;
1217 			if (tl == 0)
1218 				PCLONGVAL(tl);
1219 			tl1 = pop4();
1220 			PCLONGVAL(tl2);
1221 			push4(RANG4(tl1, tl, tl2));
1222 			continue;
1223 		case O_RANG24:
1224 			tl = *pc.cp++;
1225 			if (tl == 0)
1226 				PCLONGVAL(tl);
1227 			tl1 = pop2();
1228 			PCLONGVAL(tl2);
1229 			push2((short)(RANG4(tl1, tl, tl2)));
1230 			continue;
1231 		case O_RSNG4:
1232 			tl = *pc.cp++;
1233 			if (tl == 0)
1234 				PCLONGVAL(tl);
1235 			tl1 = pop4();
1236 			push4(RSNG4(tl1, tl));
1237 			continue;
1238 		case O_RSNG24:
1239 			tl = *pc.cp++;
1240 			if (tl == 0)
1241 				PCLONGVAL(tl);
1242 			tl1 = pop2();
1243 			push2((short)(RSNG4(tl1, tl)));
1244 			continue;
1245 		case O_STLIM:
1246 			pc.cp++;
1247 			tl = pop4();
1248 			STLIM(tl);
1249 			continue;
1250 		case O_LLIMIT:
1251 			pc.cp++;
1252 			tcp = popaddr();
1253 			tl = pop4();
1254 			LLIMIT(tcp, tl);
1255 			continue;
1256 		case O_BUFF:
1257 			BUFF((long)(*pc.cp++));
1258 			continue;
1259 		case O_HALT:
1260 			pc.cp++;
1261 			if (_nodump == TRUE)
1262 				psexit(0);
1263 			fputs("\nCall to procedure halt\n", stderr);
1264 			backtrace("Halted");
1265 			psexit(0);
1266 			continue;
1267 		case O_PXPBUF:
1268 			pc.cp++;
1269 			PCLONGVAL(tl);
1270 			_cntrs = tl;
1271 			PCLONGVAL(tl);
1272 			_rtns = tl;
1273 			NEW(&_pcpcount, (_cntrs + 1) * sizeof(long));
1274 			blkclr(_pcpcount, (_cntrs + 1) * sizeof(long));
1275 			continue;
1276 		case O_COUNT:
1277 			pc.cp++;
1278 			_pcpcount[*pc.usp++]++;
1279 			continue;
1280 		case O_CASE1OP:
1281 			tl = *pc.cp++;		/* tl = number of cases */
1282 			if (tl == 0)
1283 				tl = *pc.usp++;
1284 			tsp = pc.sp + tl;	/* ptr to end of jump table */
1285 			tcp = (char *)tsp;	/* tcp = ptr to case values */
1286 			tl1 = pop2();		/* tl1 = element to find */
1287 			for(; tl > 0; tl--)	/* look for element */
1288 				if (tl1 == *tcp++)
1289 					break;
1290 			if (tl == 0)		/* default case => error */
1291 				CASERNG(tl1);
1292 			pc.cp += *(tsp - tl);
1293 			continue;
1294 		case O_CASE2OP:
1295 			tl = *pc.cp++;		/* tl = number of cases */
1296 			if (tl == 0)
1297 				tl = *pc.usp++;
1298 			tsp = pc.sp + tl;	/* ptr to end of jump table */
1299 			tsp1 = tsp;		/* tsp1 = ptr to case values */
1300 			tl1 = (unsigned short)pop2();/* tl1 = element to find */
1301 			for(; tl > 0; tl--)	/* look for element */
1302 				if (tl1 == *tsp++)
1303 					break;
1304 			if (tl == 0)		/* default case => error */
1305 				CASERNG(tl1);
1306 			pc.cp += *(tsp1 - tl);
1307 			continue;
1308 		case O_CASE4OP:
1309 			tl = *pc.cp++;		/* tl = number of cases */
1310 			if (tl == 0)
1311 				tl = *pc.usp++;
1312 			tsp1 = pc.sp + tl;	/* ptr to end of jump table */
1313 			tlp = (long *)tsp1;	/* tlp = ptr to case values */
1314 			tl1 = pop4();		/* tl1 = element to find */
1315 			for(; tl > 0; tl--) {	/* look for element */
1316 				GETLONGVAL(tl2, tlp++);
1317 				if (tl1 == tl2)
1318 					break;
1319 			}
1320 			if (tl == 0)		/* default case => error */
1321 				CASERNG(tl1);
1322 			pc.cp += *(tsp1 - tl);
1323 			continue;
1324 		case O_ADDT:
1325 			tl = *pc.cp++;		/* tl has comparison length */
1326 			if (tl == 0)
1327 				tl = *pc.usp++;
1328 			tcp = pushsp((long)(0));/* tcp pts to first arg */
1329 			ADDT(tcp + tl, tcp + tl, tcp, tl >> 2);
1330 			popsp(tl);
1331 			continue;
1332 		case O_SUBT:
1333 			tl = *pc.cp++;		/* tl has comparison length */
1334 			if (tl == 0)
1335 				tl = *pc.usp++;
1336 			tcp = pushsp((long)(0));/* tcp pts to first arg */
1337 			SUBT(tcp + tl, tcp + tl, tcp, tl >> 2);
1338 			popsp(tl);
1339 			continue;
1340 		case O_MULT:
1341 			tl = *pc.cp++;		/* tl has comparison length */
1342 			if (tl == 0)
1343 				tl = *pc.usp++;
1344 			tcp = pushsp((long)(0));/* tcp pts to first arg */
1345 			MULT(tcp + tl, tcp + tl, tcp, tl >> 2);
1346 			popsp(tl);
1347 			continue;
1348 		case O_INCT:
1349 			tl = *pc.cp++;		/* tl has number of args */
1350 			if (tl == 0)
1351 				tl = *pc.usp++;
1352 			tb = INCT();
1353 			popsp(tl*sizeof(long));
1354 			push2((short)(tb));
1355 			continue;
1356 		case O_CTTOT:
1357 			tl = *pc.cp++;		/* tl has number of args */
1358 			if (tl == 0)
1359 				tl = *pc.usp++;
1360 			tl1 = tl * sizeof(long);	/* Size of all args */
1361 			tcp = pushsp((long)(0)) + tl1; /* tcp pts to result */
1362 			tl1 = pop4();		/* Pop the 4 fixed args */
1363 			tl2 = pop4();
1364 			tl3 = pop4();
1365 			tl4 = pop4();
1366 			tcp2 = pushsp((long)0);	/* tcp2 -> data values */
1367 			CTTOTA(tcp, tl1, tl2, tl3, tl4, tcp2);
1368 			popsp(tl*sizeof(long) - 4*sizeof(long)); /* Pop data */
1369 			continue;
1370 		case O_CARD:
1371 			tl = *pc.cp++;		/* tl has comparison length */
1372 			if (tl == 0)
1373 				tl = *pc.usp++;
1374 			tcp = pushsp((long)(0));/* tcp pts to set */
1375 			tl1 = CARD(tcp, tl);
1376 			popsp(tl);
1377 			push2((short)(tl1));
1378 			continue;
1379 		case O_IN:
1380 			tl = *pc.cp++;		/* tl has comparison length */
1381 			if (tl == 0)
1382 				tl = *pc.usp++;
1383 			tl1 = pop4();		/* tl1 is the element */
1384 			tcp = pushsp((long)(0));/* tcp pts to set */
1385 			tl2 = *pc.sp++;	/* lower bound */
1386 			tb = IN(tl1, tl2, (long)(*pc.usp++), tcp);
1387 			popsp(tl);
1388 			push2((short)(tb));
1389 			continue;
1390 		case O_ASRT:
1391 			pc.cp++;
1392 			tl = pop4();
1393 			tcp = popaddr();
1394 			ASRTS(tl, tcp);
1395 			continue;
1396 		case O_FOR1U:
1397 			tl1 = *pc.cp++;		/* tl1 loop branch */
1398 			if (tl1 == 0)
1399 				tl1 = *pc.sp++;
1400 			tcp = popaddr();	/* tcp = ptr to index var */
1401 			tl = pop4();		/* tl upper bound */
1402 			if (*tcp == tl)		/* loop is done, fall through */
1403 				continue;
1404 			*tcp += 1;		/* inc index var */
1405 			pc.cp += tl1;		/* return to top of loop */
1406 			continue;
1407 		case O_FOR2U:
1408 			tl1 = *pc.cp++;		/* tl1 loop branch */
1409 			if (tl1 == 0)
1410 				tl1 = *pc.sp++;
1411 			tsp = (short *)popaddr(); /* tsp = ptr to index var */
1412 			tl = pop4();		/* tl upper bound */
1413 			if (*tsp == tl)		/* loop is done, fall through */
1414 				continue;
1415 			*tsp += 1;		/* inc index var */
1416 			pc.cp += tl1;		/* return to top of loop */
1417 			continue;
1418 		case O_FOR4U:
1419 			tl1 = *pc.cp++;		/* tl1 loop branch */
1420 			if (tl1 == 0)
1421 				tl1 = *pc.sp++;
1422 			tlp = (long *)popaddr(); /* tlp = ptr to index var */
1423 			tl = pop4();		/* tl upper bound */
1424 			if (*tlp == tl)		/* loop is done, fall through */
1425 				continue;
1426 			*tlp += 1;		/* inc index var */
1427 			pc.cp += tl1;		/* return to top of loop */
1428 			continue;
1429 		case O_FOR1D:
1430 			tl1 = *pc.cp++;		/* tl1 loop branch */
1431 			if (tl1 == 0)
1432 				tl1 = *pc.sp++;
1433 			tcp = popaddr();	/* tcp = ptr to index var */
1434 			tl = pop4();		/* tl upper bound */
1435 			if (*tcp == tl)		/* loop is done, fall through */
1436 				continue;
1437 			*tcp -= 1;		/* dec index var */
1438 			pc.cp += tl1;		/* return to top of loop */
1439 			continue;
1440 		case O_FOR2D:
1441 			tl1 = *pc.cp++;		/* tl1 loop branch */
1442 			if (tl1 == 0)
1443 				tl1 = *pc.sp++;
1444 			tsp = (short *)popaddr(); /* tsp = ptr to index var */
1445 			tl = pop4();		/* tl upper bound */
1446 			if (*tsp == tl)		/* loop is done, fall through */
1447 				continue;
1448 			*tsp -= 1;		/* dec index var */
1449 			pc.cp += tl1;		/* return to top of loop */
1450 			continue;
1451 		case O_FOR4D:
1452 			tl1 = *pc.cp++;		/* tl1 loop branch */
1453 			if (tl1 == 0)
1454 				tl1 = *pc.sp++;
1455 			tlp = (long *)popaddr(); /* tlp = ptr to index var */
1456 			tl = pop4();		/* tl upper bound */
1457 			if (*tlp == tl)		/* loop is done, fall through */
1458 				continue;
1459 			*tlp -= 1;		/* dec index var */
1460 			pc.cp += tl1;		/* return to top of loop */
1461 			continue;
1462 		case O_READE:
1463 			pc.cp++;
1464 			PCLONGVAL(tl);
1465 			push2((short)(READE(curfile, base + tl)));
1466 			continue;
1467 		case O_READ4:
1468 			pc.cp++;
1469 			push4(READ4(curfile));
1470 			continue;
1471 		case O_READC:
1472 			pc.cp++;
1473 			push2((short)(READC(curfile)));
1474 			continue;
1475 		case O_READ8:
1476 			pc.cp++;
1477 			push8(READ8(curfile));
1478 			continue;
1479 		case O_READLN:
1480 			pc.cp++;
1481 			READLN(curfile);
1482 			continue;
1483 		case O_EOF:
1484 			pc.cp++;
1485 			tcp = popaddr();
1486 			push2((short)(TEOF(tcp)));
1487 			continue;
1488 		case O_EOLN:
1489 			pc.cp++;
1490 			tcp = popaddr();
1491 			push2((short)(TEOLN(tcp)));
1492 			continue;
1493 		case O_WRITEC:
1494 			pc.cp++;
1495 			ti = popint();
1496 			tf = popfile();
1497 			if (_runtst) {
1498 				WRITEC(curfile, ti, tf);
1499 				continue;
1500 			}
1501 			fputc(ti, tf);
1502 			continue;
1503 		case O_WRITES:
1504 			pc.cp++;		/* Skip arg size */
1505 			tf = popfile();
1506 			ti = popint();
1507 			ti2 = popint();
1508 			tcp2 = popaddr();
1509 			if (_runtst) {
1510 				WRITES(curfile, tf, ti, ti2, tcp2);
1511 				continue;
1512 			}
1513 			fwrite(tf, ti, ti2, tcp2);
1514 			continue;
1515 		case O_WRITEF:
1516 			tf = popfile();
1517 			tcp = popaddr();
1518 			tcp2 = pushsp((long)0);	/* Addr of printf's args */
1519 			if (_runtst) {
1520 				VWRITEF(curfile, tf, tcp, tcp2);
1521 			} else {
1522 				vfprintf(tf, tcp, tcp2);
1523 			}
1524 			popsp((long)
1525 			    (*pc.cp++) - (sizeof (FILE *)) - sizeof (char *));
1526 			continue;
1527 		case O_WRITLN:
1528 			pc.cp++;
1529 			if (_runtst) {
1530 				WRITLN(curfile);
1531 				continue;
1532 			}
1533 			fputc('\n', ACTFILE(curfile));
1534 			continue;
1535 		case O_PAGE:
1536 			pc.cp++;
1537 			if (_runtst) {
1538 				PAGE(curfile);
1539 				continue;
1540 			}
1541 			fputc('', ACTFILE(curfile));
1542 			continue;
1543 		case O_NAM:
1544 			pc.cp++;
1545 			tl = pop4();
1546 			PCLONGVAL(tl1);
1547 			pushaddr(NAM(tl, base + tl1));
1548 			continue;
1549 		case O_MAX:
1550 			tl = *pc.cp++;
1551 			if (tl == 0)
1552 				tl = *pc.usp++;
1553 			tl1 = pop4();
1554 			if (_runtst) {
1555 				push4(MAX(tl1, tl, (long)(*pc.usp++)));
1556 				continue;
1557 			}
1558 			tl1 -= tl;
1559 			tl = *pc.usp++;
1560 			push4(tl1 > tl ? tl1 : tl);
1561 			continue;
1562 		case O_MIN:
1563 			tl = *pc.cp++;
1564 			if (tl == 0)
1565 				tl = *pc.usp++;
1566 			tl1 = pop4();
1567 			push4(tl1 < tl ? tl1 : tl);
1568 			continue;
1569 		case O_UNIT:
1570 			pc.cp++;
1571 			curfile = UNIT(popaddr());
1572 			continue;
1573 		case O_UNITINP:
1574 			pc.cp++;
1575 			curfile = INPUT;
1576 			continue;
1577 		case O_UNITOUT:
1578 			pc.cp++;
1579 			curfile = OUTPUT;
1580 			continue;
1581 		case O_MESSAGE:
1582 			pc.cp++;
1583 			PFLUSH();
1584 			curfile = ERR;
1585 			continue;
1586 		case O_PUT:
1587 			pc.cp++;
1588 			PUT(curfile);
1589 			continue;
1590 		case O_GET:
1591 			pc.cp++;
1592 			GET(curfile);
1593 			continue;
1594 		case O_FNIL:
1595 			pc.cp++;
1596 			tcp = popaddr();
1597 			pushaddr(FNIL(tcp));
1598 			continue;
1599 		case O_DEFNAME:
1600 			pc.cp++;
1601 			tcp2 = popaddr();
1602 			tcp = popaddr();
1603 			tl = pop4();
1604 			tl2 = pop4();
1605 			DEFNAME((struct iorec *)tcp2, tcp, tl, tl2);
1606 			continue;
1607 		case O_RESET:
1608 			pc.cp++;
1609 			tcp2 = popaddr();
1610 			tcp = popaddr();
1611 			tl = pop4();
1612 			tl2 = pop4();
1613 			RESET((struct iorec *)tcp2, tcp, tl, tl2);
1614 			continue;
1615 		case O_REWRITE:
1616 			pc.cp++;
1617 			tcp2 = popaddr();
1618 			tcp = popaddr();
1619 			tl = pop4();
1620 			tl2 = pop4();
1621 			REWRITE((struct iorec *)tcp2, tcp, tl, tl2);
1622 			continue;
1623 		case O_FILE:
1624 			pc.cp++;
1625 			pushaddr(ACTFILE(curfile));
1626 			continue;
1627 		case O_REMOVE:
1628 			pc.cp++;
1629 			tcp = popaddr();
1630 			tl = pop4();
1631 			REMOVE(tcp, tl);
1632 			continue;
1633 		case O_FLUSH:
1634 			pc.cp++;
1635 			tcp = popaddr();
1636 			FLUSH((struct iorec *)tcp);
1637 			continue;
1638 		case O_PACK:
1639 			pc.cp++;
1640 			tl = pop4();
1641 			tcp = popaddr();
1642 			tcp2 = popaddr();
1643 			tl1 = pop4();
1644 			tl2 = pop4();
1645 			tl3 = pop4();
1646 			tl4 = pop4();
1647 			PACK(tl, tcp, tcp2, tl1, tl2, tl3, tl4);
1648 			continue;
1649 		case O_UNPACK:
1650 			pc.cp++;
1651 			tl = pop4();
1652 			tcp = popaddr();
1653 			tcp2 = popaddr();
1654 			tl1 = pop4();
1655 			tl2 = pop4();
1656 			tl3 = pop4();
1657 			tl4 = pop4();
1658 			UNPACK(tl, tcp, tcp2, tl1, tl2, tl3, tl4);
1659 			continue;
1660 		case O_ARGC:
1661 			pc.cp++;
1662 			push4((long)_argc);
1663 			continue;
1664 		case O_ARGV:
1665 			tl = *pc.cp++;		/* tl = size of char array */
1666 			if (tl == 0)
1667 				tl = *pc.usp++;
1668 			tcp = popaddr();	/* tcp = addr of char array */
1669 			tl1 = pop4();		/* tl1 = argv subscript */
1670 			ARGV(tl1, tcp, tl);
1671 			continue;
1672 		case O_CLCK:
1673 			pc.cp++;
1674 			push4(CLCK());
1675 			continue;
1676 		case O_WCLCK:
1677 			pc.cp++;
1678 			push4(time(0));
1679 			continue;
1680 		case O_SCLCK:
1681 			pc.cp++;
1682 			push4(SCLCK());
1683 			continue;
1684 		case O_NEW:
1685 			tl = *pc.cp++;		/* tl = size being new'ed */
1686 			if (tl == 0)
1687 				tl = *pc.usp++;
1688 			tcp = popaddr();	/* ptr to ptr being new'ed */
1689 			NEW(tcp, tl);
1690 			if (_runtst) {
1691 				blkclr(*((char **)(tcp)), tl);
1692 			}
1693 			continue;
1694 		case O_DISPOSE:
1695 			tl = *pc.cp++;		/* tl = size being disposed */
1696 			if (tl == 0)
1697 				tl = *pc.usp++;
1698 			tcp = popaddr();	/* ptr to ptr being disposed */
1699 			DISPOSE(tcp, tl);
1700 			*(char **)tcp = (char *)0;
1701 			continue;
1702 		case O_DFDISP:
1703 			tl = *pc.cp++;		/* tl = size being disposed */
1704 			if (tl == 0)
1705 				tl = *pc.usp++;
1706 			tcp = popaddr();	/* ptr to ptr being disposed */
1707 			DFDISPOSE(tcp, tl);
1708 			*(char **)tcp = (char *)0;
1709 			continue;
1710 		case O_DATE:
1711 			pc.cp++;
1712 			DATE(popaddr());
1713 			continue;
1714 		case O_TIME:
1715 			pc.cp++;
1716 			TIME(popaddr());
1717 			continue;
1718 		case O_UNDEF:
1719 			pc.cp++;
1720 			td = pop8();
1721 			push2((short)(0));
1722 			continue;
1723 		case O_ATAN:
1724 			pc.cp++;
1725 			td = pop8();
1726 			if (_runtst) {
1727 				push8(ATAN(td));
1728 				continue;
1729 			}
1730 			push8(atan(td));
1731 			continue;
1732 		case O_COS:
1733 			pc.cp++;
1734 			td = pop8();
1735 			if (_runtst) {
1736 				push8(COS(td));
1737 				continue;
1738 			}
1739 			push8(cos(td));
1740 			continue;
1741 		case O_EXP:
1742 			pc.cp++;
1743 			td = pop8();
1744 			if (_runtst) {
1745 				push8(EXP(td));
1746 				continue;
1747 			}
1748 			push8(exp(td));
1749 			continue;
1750 		case O_LN:
1751 			pc.cp++;
1752 			td = pop8();
1753 			if (_runtst) {
1754 				push8(LN(td));
1755 				continue;
1756 			}
1757 			push8(log(td));
1758 			continue;
1759 		case O_SIN:
1760 			pc.cp++;
1761 			td = pop8();
1762 			if (_runtst) {
1763 				push8(SIN(td));
1764 				continue;
1765 			}
1766 			push8(sin(td));
1767 			continue;
1768 		case O_SQRT:
1769 			pc.cp++;
1770 			td = pop8();
1771 			if (_runtst) {
1772 				push8(SQRT(td));
1773 				continue;
1774 			}
1775 			push8(sqrt(td));
1776 			continue;
1777 		case O_CHR2:
1778 		case O_CHR4:
1779 			pc.cp++;
1780 			tl = pop4();
1781 			if (_runtst) {
1782 				push2((short)(CHR(tl)));
1783 				continue;
1784 			}
1785 			push2((short)tl);
1786 			continue;
1787 		case O_ODD2:
1788 		case O_ODD4:
1789 			pc.cp++;
1790 			tl = pop4();
1791 			push2((short)(tl & 1));
1792 			continue;
1793 		case O_SUCC2:
1794 			tl = *pc.cp++;
1795 			if (tl == 0)
1796 				tl = *pc.sp++;
1797 			tl1 = pop4();
1798 			if (_runtst) {
1799 				push2((short)(SUCC(tl1, tl, (long)(*pc.sp++))));
1800 				continue;
1801 			}
1802 			push2((short)(tl1 + 1));
1803 			pc.sp++;
1804 			continue;
1805 		case O_SUCC24:
1806 			tl = *pc.cp++;
1807 			if (tl == 0)
1808 				tl = *pc.sp++;
1809 			tl1 = pop4();
1810 			if (_runtst) {
1811 				push4(SUCC(tl1, tl, (long)(*pc.sp++)));
1812 				continue;
1813 			}
1814 			push4(tl1 + 1);
1815 			pc.sp++;
1816 			continue;
1817 		case O_SUCC4:
1818 			tl = *pc.cp++;
1819 			if (tl == 0)
1820 				PCLONGVAL(tl);
1821 			tl1 = pop4();
1822 			if (_runtst) {
1823 				PCLONGVAL(tl2);
1824 				push4(SUCC(tl1, tl, (long)(tl2)));
1825 				continue;
1826 			}
1827 			push4(tl1 + 1);
1828 			pc.lp++;
1829 			continue;
1830 		case O_PRED2:
1831 			tl = *pc.cp++;
1832 			if (tl == 0)
1833 				tl = *pc.sp++;
1834 			tl1 = pop4();
1835 			if (_runtst) {
1836 				push2((short)(PRED(tl1, tl, (long)(*pc.sp++))));
1837 				continue;
1838 			}
1839 			push2((short)(tl1 - 1));
1840 			pc.sp++;
1841 			continue;
1842 		case O_PRED24:
1843 			tl = *pc.cp++;
1844 			if (tl == 0)
1845 				tl = *pc.sp++;
1846 			tl1 = pop4();
1847 			if (_runtst) {
1848 				push4(PRED(tl1, tl, (long)(*pc.sp++)));
1849 				continue;
1850 			}
1851 			push4(tl1 - 1);
1852 			pc.sp++;
1853 			continue;
1854 		case O_PRED4:
1855 			tl = *pc.cp++;
1856 			if (tl == 0)
1857 				PCLONGVAL(tl);
1858 			tl1 = pop4();
1859 			if (_runtst) {
1860 				PCLONGVAL(tl2);
1861 				push4(PRED(tl1, tl, (long)(tl2)));
1862 				continue;
1863 			}
1864 			push4(tl1 - 1);
1865 			pc.lp++;
1866 			continue;
1867 		case O_SEED:
1868 			pc.cp++;
1869 			tl = pop4();
1870 			push4(SEED(tl));
1871 			continue;
1872 		case O_RANDOM:
1873 			pc.cp++;
1874 			td = pop8();		/* Argument is ignored */
1875 			push8(RANDOM());
1876 			continue;
1877 		case O_EXPO:
1878 			pc.cp++;
1879 			td = pop8();
1880 			push4(EXPO(td));
1881 			continue;
1882 		case O_SQR2:
1883 		case O_SQR4:
1884 			pc.cp++;
1885 			tl = pop4();
1886 			push4(tl * tl);
1887 			continue;
1888 		case O_SQR8:
1889 			pc.cp++;
1890 			td = pop8();
1891 			push8(td * td);
1892 			continue;
1893 		case O_ROUND:
1894 			pc.cp++;
1895 			td = pop8();
1896 			push4(ROUND(td));
1897 			continue;
1898 		case O_TRUNC:
1899 			pc.cp++;
1900 			td = pop8();
1901 			push4(TRUNC(td));
1902 			continue;
1903 		default:
1904 			ERROR("Panic: bad op code\n");
1905 			continue;
1906 		}
1907 	}
1908 }
1909