Commit | Line | Data |
---|---|---|
cac4f7ea DR |
1 | # |
2 | /* | |
3 | * C compiler | |
4 | */ | |
5 | ||
6 | #include "c1h.c" | |
7 | ||
8 | max(a, b) | |
9 | { | |
10 | if (a>b) | |
11 | return(a); | |
12 | return(b); | |
13 | } | |
14 | ||
15 | degree(at) | |
16 | struct tnode *at; | |
17 | { | |
18 | register struct tnode *t, *t1; | |
19 | ||
20 | if ((t=at)==0 || t->op==0) | |
21 | return(0); | |
22 | if (t->op == CON) | |
23 | return(-3); | |
24 | if (t->op == AMPER) | |
25 | return(-2); | |
26 | if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0) | |
27 | return(-2); | |
28 | if ((opdope[t->op] & LEAF) != 0) { | |
29 | if (t->type==CHAR || t->type==FLOAT) | |
30 | return(1); | |
31 | return(0); | |
32 | } | |
33 | return(t->degree); | |
34 | } | |
35 | ||
36 | pname(ap, flag) | |
37 | struct tnode *ap; | |
38 | { | |
39 | register i; | |
40 | register struct tnode *p; | |
41 | ||
42 | p = ap; | |
43 | loop: | |
44 | switch(p->op) { | |
45 | ||
46 | case SFCON: | |
47 | case CON: | |
48 | printf("$"); | |
49 | psoct(p->value); | |
50 | return; | |
51 | ||
52 | case FCON: | |
53 | printf("L%d", p->value); | |
54 | return; | |
55 | ||
56 | case NAME: | |
57 | i = p->offset; | |
58 | if (flag==2) | |
59 | i =+ 2; | |
60 | if (i) { | |
61 | psoct(i); | |
62 | if (p->class!=OFFS) | |
63 | putchar('+'); | |
64 | if (p->class==REG) | |
65 | regerr(); | |
66 | } | |
67 | switch(p->class) { | |
68 | ||
69 | case SOFFS: | |
70 | case XOFFS: | |
71 | pbase(p); | |
72 | ||
73 | case OFFS: | |
74 | printf("(r%d)", p->regno); | |
75 | return; | |
76 | ||
77 | case EXTERN: | |
78 | case STATIC: | |
79 | pbase(p); | |
80 | return; | |
81 | ||
82 | case REG: | |
83 | printf("r%d", p->nloc); | |
84 | return; | |
85 | ||
86 | } | |
87 | error("Compiler error: pname"); | |
88 | return; | |
89 | ||
90 | case AMPER: | |
91 | putchar('$'); | |
92 | p = p->tr1; | |
93 | if (p->op==NAME && p->class==REG) | |
94 | regerr(); | |
95 | goto loop; | |
96 | ||
97 | case AUTOI: | |
98 | printf("(r%d)%c", p->nloc, flag==1?0:'+'); | |
99 | return; | |
100 | ||
101 | case AUTOD: | |
102 | printf("%c(r%d)", flag==1?0:'-', p->nloc); | |
103 | return; | |
104 | ||
105 | case STAR: | |
106 | p = p->tr1; | |
107 | putchar('*'); | |
108 | goto loop; | |
109 | ||
110 | } | |
111 | error("pname called illegally"); | |
112 | } | |
113 | ||
114 | regerr() | |
115 | { | |
116 | error("Illegal use of register"); | |
117 | } | |
118 | ||
119 | pbase(ap) | |
120 | struct tnode *ap; | |
121 | { | |
122 | register struct tnode *p; | |
123 | ||
124 | p = ap; | |
125 | if (p->class==SOFFS || p->class==STATIC) | |
126 | printf("L%d", p->nloc); | |
127 | else | |
128 | printf("_%.8s", &(p->nloc)); | |
129 | } | |
130 | ||
131 | xdcalc(ap, nrleft) | |
132 | struct tnode *ap; | |
133 | { | |
134 | register struct tnode *p; | |
135 | register d; | |
136 | ||
137 | p = ap; | |
138 | d = dcalc(p, nrleft); | |
139 | if (d<20 && p->type==CHAR) { | |
140 | if (nrleft>=1) | |
141 | d = 20; | |
142 | else | |
143 | d = 24; | |
144 | } | |
145 | return(d); | |
146 | } | |
147 | ||
148 | dcalc(ap, nrleft) | |
149 | struct tnode *ap; | |
150 | { | |
151 | register struct tnode *p, *p1; | |
152 | ||
153 | if ((p=ap)==0) | |
154 | return(0); | |
155 | switch (p->op) { | |
156 | ||
157 | case NAME: | |
158 | if (p->class==REG) | |
159 | return(9); | |
160 | ||
161 | case AMPER: | |
162 | case FCON: | |
163 | case AUTOI: | |
164 | case AUTOD: | |
165 | return(12); | |
166 | ||
167 | case CON: | |
168 | case SFCON: | |
169 | if (p->value==0) | |
170 | return(4); | |
171 | if (p->value==1) | |
172 | return(5); | |
173 | if (p->value > 0) | |
174 | return(8); | |
175 | return(12); | |
176 | ||
177 | case STAR: | |
178 | p1 = p->tr1; | |
179 | if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) | |
180 | if (p->type!=LONG) | |
181 | return(12); | |
182 | } | |
183 | if (p->type==LONG) | |
184 | nrleft--; | |
185 | return(p->degree <= nrleft? 20: 24); | |
186 | } | |
187 | ||
188 | notcompat(ap, ast, op) | |
189 | struct tnode *ap; | |
190 | { | |
191 | register at, st; | |
192 | register struct tnode *p; | |
193 | ||
194 | p = ap; | |
195 | at = p->type; | |
196 | st = ast; | |
197 | if (st==0) /* word, byte */ | |
198 | return(at>CHAR && at<PTR); | |
199 | if (st==1) /* word */ | |
200 | return(at>INT && at<PTR); | |
201 | st =- 2; | |
202 | if ((at&(~(TYPE+XTYPE))) != 0) | |
203 | at = 020; | |
204 | if ((at&(~TYPE)) != 0) | |
205 | at = at&TYPE | 020; | |
206 | if (st==FLOAT && at==DOUBLE) | |
207 | at = FLOAT; | |
208 | if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR) | |
209 | return(0); | |
210 | return(st != at); | |
211 | } | |
212 | ||
213 | prins(op, c, itable) | |
214 | struct instab *itable; | |
215 | { | |
216 | register struct instab *insp; | |
217 | register char *ip; | |
218 | ||
219 | for (insp=itable; insp->op != 0; insp++) { | |
220 | if (insp->op == op) { | |
221 | ip = c? insp->str2: insp->str1; | |
222 | if (ip==0) | |
223 | break; | |
224 | printf("%s", ip); | |
225 | return; | |
226 | } | |
227 | } | |
228 | error("No match' for op %d", op); | |
229 | } | |
230 | ||
231 | collcon(ap) | |
232 | struct tnode *ap; | |
233 | { | |
234 | register op; | |
235 | register struct tnode *p; | |
236 | ||
237 | p = ap; | |
238 | if (p->op==STAR) | |
239 | p = p->tr1; | |
240 | if (p->op==PLUS) { | |
241 | op = p->tr2->op; | |
242 | if (op==CON || op==AMPER) | |
243 | return(1); | |
244 | } | |
245 | return(0); | |
246 | } | |
247 | ||
248 | isfloat(at) | |
249 | struct tnode *at; | |
250 | { | |
251 | register struct tnode *t; | |
252 | ||
253 | t = at; | |
254 | if ((opdope[t->op]&RELAT)!=0) | |
255 | t = t->tr1; | |
256 | if (t->type==FLOAT || t->type==DOUBLE) { | |
257 | nfloat = 1; | |
258 | return('f'); | |
259 | } | |
260 | return(0); | |
261 | } | |
262 | ||
263 | oddreg(t, areg) | |
264 | struct tnode *t; | |
265 | { | |
266 | register reg; | |
267 | ||
268 | reg = areg; | |
269 | if (!isfloat(t)) | |
270 | switch(t->op) { | |
271 | case DIVIDE: | |
272 | case MOD: | |
273 | case ASDIV: | |
274 | case ASMOD: | |
275 | reg++; | |
276 | ||
277 | case TIMES: | |
278 | case ASTIMES: | |
279 | return(reg|1); | |
280 | } | |
281 | return(reg); | |
282 | } | |
283 | ||
284 | arlength(t) | |
285 | { | |
286 | if (t>=PTR) | |
287 | return(2); | |
288 | switch(t) { | |
289 | ||
290 | case INT: | |
291 | case CHAR: | |
292 | return(2); | |
293 | ||
294 | case LONG: | |
295 | return(4); | |
296 | ||
297 | case FLOAT: | |
298 | case DOUBLE: | |
299 | return(8); | |
300 | } | |
301 | return(1024); | |
302 | } | |
303 | ||
304 | /* | |
305 | * Strings for switch code. | |
306 | */ | |
307 | ||
308 | char dirsw[] {"\ | |
309 | cmp r0,$%o\n\ | |
310 | jhi L%d\n\ | |
311 | asl r0\n\ | |
312 | jmp *L%d(r0)\n\ | |
313 | .data\n\ | |
314 | L%d:\ | |
315 | " }; | |
316 | ||
317 | char simpsw[] {"\ | |
318 | mov $L%d,r1\n\ | |
319 | mov r0,L%d\n\ | |
320 | L%d:cmp r0,(r1)+\n\ | |
321 | jne L%d\n\ | |
322 | jmp *L%d-L%d(r1)\n\ | |
323 | .data\n\ | |
324 | L%d:\ | |
325 | "}; | |
326 | ||
327 | char hashsw[] {"\ | |
328 | mov r0,r1\n\ | |
329 | clr r0\n\ | |
330 | div $%o,r0\n\ | |
331 | asl r1\n\ | |
332 | add $L%d,r1\n\ | |
333 | mov r0,*(r1)+\n\ | |
334 | mov (r1)+,r1\n\ | |
335 | L%d:cmp r0,-(r1)\n\ | |
336 | jne L%d\n\ | |
337 | jmp *L%d-L%d(r1)\n\ | |
338 | .data\n\ | |
339 | L%d:\ | |
340 | "}; | |
341 | ||
342 | pswitch(afp, alp, deflab) | |
343 | struct swtab *afp, *alp; | |
344 | { | |
345 | int tlab, ncase, i, j, tabs, worst, best, range; | |
346 | register struct swtab *swp, *fp, *lp; | |
347 | int poctab[swsiz]; | |
348 | ||
349 | fp = afp; | |
350 | lp = alp; | |
351 | if (fp==lp) { | |
352 | printf("jbr L%d\n", deflab); | |
353 | return; | |
354 | } | |
355 | tlab = isn++; | |
356 | if (sort(fp, lp)) | |
357 | return; | |
358 | ncase = lp-fp; | |
359 | lp--; | |
360 | range = lp->swval - fp->swval; | |
361 | /* direct switch */ | |
362 | if (range>0 && range <= 3*ncase) { | |
363 | if (fp->swval) | |
364 | printf("sub $%o,r0\n", fp->swval); | |
365 | printf(dirsw, range, deflab, isn, isn); | |
366 | isn++; | |
367 | for (i=fp->swval; i<=lp->swval; i++) { | |
368 | if (i==fp->swval) { | |
369 | printf("L%d\n", fp->swlab); | |
370 | fp++; | |
371 | } else | |
372 | printf("L%d\n", deflab); | |
373 | } | |
374 | goto esw; | |
375 | } | |
376 | /* simple switch */ | |
377 | if (ncase<8) { | |
378 | i = isn++; | |
379 | j = isn++; | |
380 | printf(simpsw, i, j, isn, isn, j, i, i); | |
381 | isn++; | |
382 | for (; fp<=lp; fp++) | |
383 | printf("%o\n", fp->swval); | |
384 | printf("L%d:..\n", j); | |
385 | for (fp = afp; fp<=lp; fp++) | |
386 | printf("L%d\n", fp->swlab); | |
387 | printf("L%d\n", deflab); | |
388 | goto esw; | |
389 | } | |
390 | /* hash switch */ | |
391 | best = 077777; | |
392 | for (i=ncase/4; i<=ncase/2; i++) { | |
393 | for (j=0; j<i; j++) | |
394 | poctab[j] = 0; | |
395 | for (swp=fp; swp<=lp; swp++) | |
396 | poctab[lrem(0, swp->swval, i)]++; | |
397 | worst = 0; | |
398 | for (j=0; j<i; j++) | |
399 | if (poctab[j]>worst) | |
400 | worst = poctab[j]; | |
401 | if (i*worst < best) { | |
402 | tabs = i; | |
403 | best = i*worst; | |
404 | } | |
405 | } | |
406 | i = isn++; | |
407 | printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn); | |
408 | isn++; | |
409 | for (i=0; i<=tabs; i++) | |
410 | printf("L%d\n", isn+i); | |
411 | for (i=0; i<tabs; i++) { | |
412 | printf("L%d:..\n", isn++); | |
413 | for (swp=fp; swp<=lp; swp++) | |
414 | if (lrem(0, swp->swval, tabs) == i) | |
415 | printf("%o\n", ldiv(0, swp->swval, tabs)); | |
416 | } | |
417 | printf("L%d:", isn++); | |
418 | for (i=0; i<tabs; i++) { | |
419 | printf("L%d\n", deflab); | |
420 | for (swp=fp; swp<=lp; swp++) | |
421 | if (lrem(0, swp->swval, tabs) == i) | |
422 | printf("L%d\n", swp->swlab); | |
423 | } | |
424 | esw: | |
425 | printf(".text\n"); | |
426 | } | |
427 | ||
428 | sort(afp, alp) | |
429 | struct swtab *afp, *alp; | |
430 | { | |
431 | register struct swtab *cp, *fp, *lp; | |
432 | int intch, t; | |
433 | ||
434 | fp = afp; | |
435 | lp = alp; | |
436 | while (fp < --lp) { | |
437 | intch = 0; | |
438 | for (cp=fp; cp<lp; cp++) { | |
439 | if (cp->swval == cp[1].swval) { | |
440 | error("Duplicate case (%d)", cp->swval); | |
441 | return(1); | |
442 | } | |
443 | if (cp->swval > cp[1].swval) { | |
444 | intch++; | |
445 | t = cp->swval; | |
446 | cp->swval = cp[1].swval; | |
447 | cp[1].swval = t; | |
448 | t = cp->swlab; | |
449 | cp->swlab = cp[1].swlab; | |
450 | cp[1].swlab = t; | |
451 | } | |
452 | } | |
453 | if (intch==0) | |
454 | break; | |
455 | } | |
456 | return(0); | |
457 | } | |
458 | ||
459 | ispow2(atree) | |
460 | { | |
461 | register int d; | |
462 | register struct tnode *tree; | |
463 | ||
464 | tree = atree; | |
465 | if (!isfloat(tree) && tree->tr2->op==CON) { | |
466 | d = tree->tr2->value; | |
467 | if (d>1 && (d&(d-1))==0) | |
468 | return(d); | |
469 | } | |
470 | return(0); | |
471 | } | |
472 | ||
473 | pow2(atree) | |
474 | struct tnode *atree; | |
475 | { | |
476 | register int d, i; | |
477 | register struct tnode *tree; | |
478 | ||
479 | tree = atree; | |
480 | if (d = ispow2(tree)) { | |
481 | for (i=0; (d=>>1)!=0; i++); | |
482 | tree->tr2->value = i; | |
483 | d = tree->op; | |
484 | tree->op = d==TIMES? LSHIFT: | |
485 | (d==DIVIDE? RSHIFT: | |
486 | (d==ASTIMES? ASLSH: ASRSH)); | |
487 | tree = optim(tree); | |
488 | } | |
489 | return(tree); | |
490 | } | |
491 | ||
492 | cbranch(atree, albl, cond, areg) | |
493 | struct tnode *atree; | |
494 | { | |
495 | int l1, op; | |
496 | register lbl, reg; | |
497 | register struct tnode *tree; | |
498 | ||
499 | lbl = albl; | |
500 | reg = areg; | |
501 | if ((tree=atree)==0) | |
502 | return; | |
503 | switch(tree->op) { | |
504 | ||
505 | case LOGAND: | |
506 | if (cond) { | |
507 | cbranch(tree->tr1, l1=isn++, 0, reg); | |
508 | cbranch(tree->tr2, lbl, 1, reg); | |
509 | label(l1); | |
510 | } else { | |
511 | cbranch(tree->tr1, lbl, 0, reg); | |
512 | cbranch(tree->tr2, lbl, 0, reg); | |
513 | } | |
514 | return; | |
515 | ||
516 | case LOGOR: | |
517 | if (cond) { | |
518 | cbranch(tree->tr1, lbl, 1, reg); | |
519 | cbranch(tree->tr2, lbl, 1, reg); | |
520 | } else { | |
521 | cbranch(tree->tr1, l1=isn++, 1, reg); | |
522 | cbranch(tree->tr2, lbl, 0, reg); | |
523 | label(l1); | |
524 | } | |
525 | return; | |
526 | ||
527 | case EXCLA: | |
528 | cbranch(tree->tr1, lbl, !cond, reg); | |
529 | return; | |
530 | ||
531 | case COMMA: | |
532 | rcexpr(tree->tr1, efftab, reg); | |
533 | tree = tree->tr2; | |
534 | break; | |
535 | } | |
536 | op = tree->op; | |
537 | if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) { | |
538 | if (tree->type!=LONG) { | |
539 | tree->op = MINUS; | |
540 | tree->type = LONG; | |
541 | tree = optim(tree); | |
542 | } else | |
543 | op = NEQUAL; | |
544 | rcexpr(tree, regtab, 0); | |
545 | printf("ashc $0,r0\n"); | |
546 | branch(lbl, op, !cond); | |
547 | return; | |
548 | } | |
549 | rcexpr(tree, cctab, reg); | |
550 | op = tree->op; | |
551 | if ((opdope[op]&RELAT)==0) | |
552 | op = NEQUAL; | |
553 | else { | |
554 | l1 = tree->tr2->op; | |
555 | if ((l1==CON || l1==SFCON) && tree->tr2->value==0) | |
556 | op =+ 200; /* special for ptr tests */ | |
557 | else | |
558 | op = maprel[op-EQUAL]; | |
559 | } | |
560 | if (isfloat(tree)) | |
561 | printf("cfcc\n"); | |
562 | branch(lbl, op, !cond); | |
563 | } | |
564 | ||
565 | branch(lbl, aop, c) | |
566 | { | |
567 | register op; | |
568 | ||
569 | if(op=aop) | |
570 | prins(op, c, branchtab); | |
571 | else | |
572 | printf("jbr"); | |
573 | printf("\tL%d\n", lbl); | |
574 | } | |
575 | ||
576 | label(l) | |
577 | { | |
578 | printf("L%d:", l); | |
579 | } | |
580 | ||
581 | popstk(a) | |
582 | { | |
583 | switch(a) { | |
584 | ||
585 | case 0: | |
586 | return; | |
587 | ||
588 | case 2: | |
589 | printf("tst (sp)+\n"); | |
590 | return; | |
591 | ||
592 | case 4: | |
593 | printf("cmp (sp)+,(sp)+\n"); | |
594 | return; | |
595 | } | |
596 | printf("add $%o,sp\n", a); | |
597 | } | |
598 | ||
599 | error(s, p1, p2, p3, p4, p5, p6) | |
600 | { | |
601 | register f; | |
602 | extern fout; | |
603 | ||
604 | nerror++; | |
605 | flush(); | |
606 | f = fout; | |
607 | fout = 1; | |
608 | printf("%d: ", line); | |
609 | printf(s, p1, p2, p3, p4, p5, p6); | |
610 | putchar('\n'); | |
611 | flush(); | |
612 | fout = f; | |
613 | } | |
614 | ||
615 | psoct(an) | |
616 | { | |
617 | register int n, sign; | |
618 | ||
619 | sign = 0; | |
620 | if ((n = an) < 0) { | |
621 | n = -n; | |
622 | sign = '-'; | |
623 | } | |
624 | printf("%c%o", sign, n); | |
625 | } | |
626 | ||
627 | /* | |
628 | * Read in an intermediate file. | |
629 | */ | |
630 | getree() | |
631 | { | |
632 | struct tnode *expstack[20]; | |
633 | register struct tnode **sp; | |
634 | register t, op; | |
635 | static char s[9]; | |
636 | struct swtab *swp; | |
637 | ||
638 | spacep = treespace; | |
639 | sp = expstack; | |
640 | for (;;) { | |
641 | if (sp >= &expstack[20]) | |
642 | error("Stack botch"); | |
643 | op = getw(ascbuf); | |
644 | if ((op&0177400) != 0177000) { | |
645 | error("Intermediate file error"); | |
646 | exit(1); | |
647 | } | |
648 | switch(op =& 0377) { | |
649 | ||
650 | case EOF: | |
651 | return; | |
652 | ||
653 | case BDATA: | |
654 | printf(".byte "); | |
655 | seq(','); | |
656 | break; | |
657 | ||
658 | case WDATA: | |
659 | seq(';'); | |
660 | break; | |
661 | ||
662 | case PROG: | |
663 | printf(".text\n"); | |
664 | break; | |
665 | ||
666 | case DATA: | |
667 | printf(".data\n"); | |
668 | break; | |
669 | ||
670 | case BSS: | |
671 | printf(".bss\n"); | |
672 | break; | |
673 | ||
674 | case SYMDEF: | |
675 | printf(".globl _%s\n", outname(s)); | |
676 | break; | |
677 | ||
678 | case RETRN: | |
679 | printf("jmp cret\n"); | |
680 | break; | |
681 | ||
682 | case CSPACE: | |
683 | t = outname(s); | |
684 | printf(".comm _%s,%o\n", t, getw(ascbuf)); | |
685 | break; | |
686 | ||
687 | case SSPACE: | |
688 | printf(".=.+%o\n", getw(ascbuf)); | |
689 | break; | |
690 | ||
691 | case EVEN: | |
692 | printf(".even\n"); | |
693 | break; | |
694 | ||
695 | case SAVE: | |
696 | printf("jsr r5,csv\n"); | |
697 | t = getw(ascbuf)-6; | |
698 | if (t==2) | |
699 | printf("tst -(sp)\n"); | |
700 | else if (t > 2) | |
701 | printf("sub $%o,sp\n", t); | |
702 | break; | |
703 | ||
704 | case PROFIL: | |
705 | t = getw(ascbuf); | |
706 | printf("mov $L%d,r0\njsr pc,mcount\n", t); | |
707 | printf(".bss\nL%d:.=.+2\n.text\n", t); | |
708 | break; | |
709 | ||
710 | case SNAME: | |
711 | t = outname(s); | |
712 | printf("~%s=L%d\n", t, getw(ascbuf)); | |
713 | break; | |
714 | ||
715 | case ANAME: | |
716 | t = outname(s); | |
717 | printf("~%s=%o\n", t, getw(ascbuf)); | |
718 | break; | |
719 | ||
720 | case RNAME: | |
721 | t = outname(s); | |
722 | printf("~%s=r%d\n", t, getw(ascbuf)); | |
723 | break; | |
724 | ||
725 | case SWIT: | |
726 | t = getw(ascbuf); | |
727 | line = getw(ascbuf); | |
728 | swp = treespace; | |
729 | while (swp->swlab = getw(ascbuf)) { | |
730 | swp->swval = getw(ascbuf); | |
731 | swp++; | |
732 | } | |
733 | pswitch(treespace, swp, t); | |
734 | break; | |
735 | ||
736 | case EXPR: | |
737 | line = getw(ascbuf); | |
738 | if (sp != &expstack[1]) { | |
739 | error("Expression input botch\n"); | |
740 | exit(1); | |
741 | } | |
742 | nstack = 0; | |
743 | rcexpr(optim(*--sp), efftab, 0); | |
744 | spacep = treespace; | |
745 | break; | |
746 | ||
747 | case NAME: | |
748 | t = getw(ascbuf); | |
749 | if (t==EXTERN) { | |
750 | t = getw(ascbuf); | |
751 | *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0); | |
752 | outname(&(*sp)->nloc); | |
753 | sp++; | |
754 | break; | |
755 | } | |
756 | *sp = block(3, NAME, 0, 0, t, 0, 0); | |
757 | (*sp)->type = getw(ascbuf); | |
758 | (*sp)->nloc = getw(ascbuf); | |
759 | sp++; | |
760 | break; | |
761 | ||
762 | case CON: | |
763 | case SFCON: | |
764 | case FCON: | |
765 | t = getw(ascbuf); | |
766 | *sp++ = block(1, op, t, 0, getw(ascbuf)); | |
767 | break; | |
768 | ||
769 | case FSEL: | |
770 | t = getw(ascbuf); | |
771 | sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf)); | |
772 | break; | |
773 | ||
774 | case NULL: | |
775 | *sp++ = block(0, 0, 0, 0); | |
776 | break; | |
777 | ||
778 | case CBRANCH: | |
779 | t = getw(ascbuf); | |
780 | sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf)); | |
781 | break; | |
782 | ||
783 | case LABEL: | |
784 | label(getw(ascbuf)); | |
785 | break; | |
786 | ||
787 | case NLABEL: | |
788 | printf("_%s:\n", outname(s)); | |
789 | break; | |
790 | ||
791 | case RLABEL: | |
792 | t = outname(s); | |
793 | printf("_%s:\n~~%s:\n", t, t); | |
794 | break; | |
795 | ||
796 | case BRANCH: | |
797 | branch(getw(ascbuf), 0); | |
798 | break; | |
799 | ||
800 | case SETREG: | |
801 | nreg = getw(ascbuf)-1; | |
802 | break; | |
803 | ||
804 | default: | |
805 | if (opdope[op]&BINARY) { | |
806 | if (sp < &expstack[1]) { | |
807 | error("Binary expression botch"); | |
808 | exit(1); | |
809 | } | |
810 | t = *--sp; | |
811 | *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t); | |
812 | } else { | |
813 | sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]); | |
814 | } | |
815 | break; | |
816 | } | |
817 | } | |
818 | } | |
819 | ||
820 | outname(s) | |
821 | { | |
822 | register char *p, c; | |
823 | register n; | |
824 | ||
825 | p = s; | |
826 | n = 0; | |
827 | while (c = getc(ascbuf)) { | |
828 | *p++ = c; | |
829 | n++; | |
830 | } | |
831 | while (n++ < 8) | |
832 | *p++ = 0; | |
833 | return(s); | |
834 | } | |
835 | ||
836 | seq(c) | |
837 | { | |
838 | register o; | |
839 | ||
840 | if (getw(ascbuf) == 0) | |
841 | return; | |
842 | for (;;) { | |
843 | printf("%o", getw(ascbuf)); | |
844 | if ((o = getw(ascbuf)) != 1) | |
845 | break; | |
846 | printf("%c", c); | |
847 | } | |
848 | printf("\n"); | |
849 | } |