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