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