|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)local2.c 1.11 (Berkeley) 6/4/87";
3: #endif
4:
5: # include "pass2.h"
6: # include <ctype.h>
7:
8: # define putstr(s) fputs((s), stdout)
9: # define ISCHAR(p) (p->in.type == UCHAR || p->in.type == CHAR)
10:
11: # ifdef FORT
12: int ftlab1, ftlab2;
13: # endif
14: /* a lot of the machine dependent parts of the second pass */
15:
16: # define BITMASK(n) ((1L<<n)-1)
17:
18: # ifndef ONEPASS
19: where(c){
20: fprintf( stderr, "%s, line %d: ", filename, lineno );
21: }
22: # endif
23:
24: lineid( l, fn ) char *fn; {
25: /* identify line l and file fn */
26: printf( "# line %d, file %s\n", l, fn );
27: }
28:
29: int ent_mask;
30:
31: eobl2(){
32: register OFFSZ spoff; /* offset from stack pointer */
33: #ifndef FORT
34: extern int ftlab1, ftlab2;
35: #endif
36:
37: spoff = maxoff;
38: spoff /= SZCHAR;
39: SETOFF(spoff,4);
40: #ifdef FORT
41: #ifndef FLEXNAMES
42: printf( " .set .F%d,%d\n", ftnno, spoff );
43: #else
44: /* SHOULD BE L%d ... ftnno but must change pc/f77 */
45: printf( " .set LF%d,%d\n", ftnno, spoff );
46: #endif
47: printf( " .set LWM%d,0x%x\n", ftnno, ent_mask&0x1ffc|0x1000);
48: #else
49: printf( " .set L%d,0x%x\n", ftnno, ent_mask&0x1ffc);
50: printf( "L%d:\n", ftlab1);
51: if( maxoff > AUTOINIT )
52: printf( " subl3 $%d,fp,sp\n", spoff);
53: printf( " jbr L%d\n", ftlab2);
54: #endif
55: ent_mask = 0;
56: maxargs = -1;
57: }
58:
59: struct hoptab { int opmask; char * opstring; } ioptab[] = {
60:
61: PLUS, "add",
62: MINUS, "sub",
63: MUL, "mul",
64: DIV, "div",
65: MOD, "div",
66: OR, "or",
67: ER, "xor",
68: AND, "and",
69: -1, "" };
70:
71: hopcode( f, o ){
72: /* output the appropriate string from the above table */
73:
74: register struct hoptab *q;
75:
76: if(asgop(o))
77: o = NOASG o;
78: for( q = ioptab; q->opmask>=0; ++q ){
79: if( q->opmask == o ){
80: if(f == 'E')
81: printf( "e%s", q->opstring);
82: else
83: printf( "%s%c", q->opstring, tolower(f));
84: return;
85: }
86: }
87: cerror( "no hoptab for %s", opst[o] );
88: }
89:
90: char *
91: rnames[] = { /* keyed to register number tokens */
92:
93: "r0", "r1",
94: "r2", "r3", "r4", "r5",
95: "r6", "r7", "r8", "r9", "r10", "r11",
96: "r12", "fp", "sp", "pc",
97: };
98:
99: /* output register name and update entry mask */
100: char *
101: rname(r)
102: register int r;
103: {
104:
105: ent_mask |= 1<<r;
106: return(rnames[r]);
107: }
108:
109: int rstatus[] = {
110: SAREG|STAREG, SAREG|STAREG,
111: SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
112: SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
113: SAREG, SAREG, SAREG, SAREG,
114: };
115:
116: tlen(p) NODE *p;
117: {
118: switch(p->in.type) {
119: case CHAR:
120: case UCHAR:
121: return(1);
122:
123: case SHORT:
124: case USHORT:
125: return(2);
126:
127: case DOUBLE:
128: return(8);
129:
130: default:
131: return(4);
132: }
133: }
134:
135: anyfloat(p, q)
136: NODE *p, *q;
137: {
138: register TWORD tp, tq;
139:
140: tp = p->in.type;
141: tq = q->in.type;
142: return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE);
143: }
144:
145: prtype(n) NODE *n;
146: {
147: switch (n->in.type)
148: {
149:
150: case DOUBLE:
151: putchar('d');
152: return;
153:
154: case FLOAT:
155: putchar('f');
156: return;
157:
158: case INT:
159: case UNSIGNED:
160: putchar('l');
161: return;
162:
163: case SHORT:
164: case USHORT:
165: putchar('w');
166: return;
167:
168: case CHAR:
169: case UCHAR:
170: putchar('b');
171: return;
172:
173: default:
174: if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
175: else {
176: putchar('l');
177: return;
178: }
179: }
180: }
181:
182: zzzcode( p, c ) register NODE *p; {
183: register int m;
184: int val;
185: switch( c ){
186:
187: case 'N': /* logical ops, turned into 0-1 */
188: /* use register given by register 1 */
189: cbgen( 0, m=getlab(), 'I' );
190: deflab( p->bn.label );
191: printf( " clrl %s\n", rname(getlr( p, '1' )->tn.rval) );
192: deflab( m );
193: return;
194:
195: case 'P':
196: cbgen( p->in.op, p->bn.label, c );
197: return;
198:
199: case 'A': /* assignment and load (integer only) */
200: {
201: register NODE *l, *r;
202:
203: if (xdebug) eprint(p, 0, &val, &val);
204: r = getlr(p, 'R');
205: if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL) {
206: l = resc;
207: l->in.type = INT;
208: } else
209: l = getlr(p, 'L');
210: if(r->in.type==FLOAT || r->in.type==DOUBLE
211: || l->in.type==FLOAT || l->in.type==DOUBLE)
212: cerror("float in ZA");
213: if (r->in.op == ICON)
214: if(r->in.name[0] == '\0') {
215: if (r->tn.lval == 0) {
216: putstr("clr");
217: prtype(l);
218: putchar('\t');
219: adrput(l);
220: return;
221: }
222: if (r->tn.lval < 0 && r->tn.lval >= -63) {
223: putstr("mneg");
224: prtype(l);
225: r->tn.lval = -r->tn.lval;
226: goto ops;
227: }
228: #ifdef MOVAFASTER
229: } else {
230: putstr("movab\t");
231: acon(r);
232: putchar(',');
233: adrput(l);
234: return;
235: #endif MOVAFASTER
236: }
237:
238: if (l->in.op == REG) {
239: if( tlen(l) < tlen(r) ) {
240: putstr(!ISUNSIGNED(l->in.type)?
241: "cvt": "movz");
242: prtype(l);
243: putchar('l');
244: goto ops;
245: } else
246: l->in.type = INT;
247: }
248: if (tlen(l) == tlen(r)) {
249: putstr("mov");
250: prtype(l);
251: goto ops;
252: } else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
253: putstr("movz");
254: else
255: putstr("cvt");
256: prtype(r);
257: prtype(l);
258: ops:
259: putchar('\t');
260: adrput(r);
261: putchar(',');
262: adrput(l);
263: return;
264: }
265:
266: case 'B': /* get oreg value in temp register for shift */
267: {
268: register NODE *r;
269: if (xdebug) eprint(p, 0, &val, &val);
270: r = p->in.right;
271: if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
272: putstr("movl");
273: else {
274: putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
275: prtype(r);
276: putchar('l');
277: }
278: return;
279: }
280:
281: case 'C': /* num bytes pushed on arg stack */
282: {
283: extern int gc_numbytes;
284: extern int xdebug;
285:
286: if (xdebug) printf("->%d<-",gc_numbytes);
287:
288: printf("call%c $%d",
289: (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s',
290: gc_numbytes+4);
291: /* dont change to double (here's the only place to catch it) */
292: if(p->in.type == FLOAT)
293: rtyflg = 1;
294: return;
295: }
296:
297: case 'D': /* INCR and DECR */
298: zzzcode(p->in.left, 'A');
299: putstr("\n ");
300:
301: case 'E': /* INCR and DECR, FOREFF */
302: if (p->in.right->tn.lval == 1)
303: {
304: putstr(p->in.op == INCR ? "inc" : "dec");
305: prtype(p->in.left);
306: putchar('\t');
307: adrput(p->in.left);
308: return;
309: }
310: putstr(p->in.op == INCR ? "add" : "sub");
311: prtype(p->in.left);
312: putstr("2 ");
313: adrput(p->in.right);
314: putchar(',');
315: adrput(p->in.left);
316: return;
317:
318: case 'F': /* masked constant for fields */
319: printf(ACONFMT, (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf);
320: return;
321:
322: case 'H': /* opcode for shift */
323: if(p->in.op == LS || p->in.op == ASG LS)
324: putstr("shll");
325: else if(ISUNSIGNED(p->in.left->in.type))
326: putstr("shrl");
327: else
328: putstr("shar");
329: return;
330:
331: case 'L': /* type of left operand */
332: case 'R': /* type of right operand */
333: {
334: register NODE *n;
335: extern int xdebug;
336:
337: n = getlr ( p, c);
338: if (xdebug) printf("->%d<-", n->in.type);
339:
340: prtype(n);
341: return;
342: }
343:
344: case 'M': { /* initiate ediv for mod and unsigned div */
345: register char *r;
346: m = getlr(p, '1')->tn.rval;
347: r = rname(m);
348: printf("\tclrl\t%s\n\tmovl\t", r);
349: adrput(p->in.left);
350: printf(",%s\n", rname(m+1));
351: if(!ISUNSIGNED(p->in.type)) { /* should be MOD */
352: m = getlab();
353: printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
354: deflab(m);
355: }
356: return;
357: }
358:
359: case 'T': { /* rounded structure length for arguments */
360: int size = p->stn.stsize;
361: SETOFF( size, 4);
362: printf("movab -%d(sp),sp", size);
363: return;
364: }
365:
366: case 'S': /* structure assignment */
367: stasg(p);
368: break;
369:
370: case 'X': /* multiplication for short and char */
371: if (ISUNSIGNED(p->in.left->in.type))
372: printf("\tmovz");
373: else
374: printf("\tcvt");
375: zzzcode(p, 'L');
376: printf("l\t");
377: adrput(p->in.left);
378: printf(",");
379: adrput(&resc[0]);
380: printf("\n");
381: if (ISUNSIGNED(p->in.right->in.type))
382: printf("\tmovz");
383: else
384: printf("\tcvt");
385: zzzcode(p, 'R');
386: printf("l\t");
387: adrput(p->in.right);
388: printf(",");
389: adrput(&resc[1]);
390: printf("\n");
391: return;
392:
393: case 'U': /* SCONV */
394: case 'V': /* SCONV with FORCC */
395: sconv(p, c == 'V');
396: break;
397:
398: case 'Z':
399: p = p->in.right;
400: switch (p->in.type) {
401: case SHORT: {
402: short w = p->tn.lval;
403: p->tn.lval = w;
404: break;
405: }
406: case CHAR: {
407: char c = p->tn.lval;
408: p->tn.lval = c;
409: break;
410: }
411: }
412: printf("$%d", p->tn.lval);
413: break;
414:
415: default:
416: cerror( "illegal zzzcode" );
417: }
418: }
419:
420: #define MOVB(dst, src, off) { \
421: putstr("\tmovb\t"); upput(src, off); putchar(','); \
422: upput(dst, off); putchar('\n'); \
423: }
424: #define MOVW(dst, src, off) { \
425: putstr("\tmovw\t"); upput(src, off); putchar(','); \
426: upput(dst, off); putchar('\n'); \
427: }
428: #define MOVL(dst, src, off) { \
429: putstr("\tmovl\t"); upput(src, off); putchar(','); \
430: upput(dst, off); putchar('\n'); \
431: }
432: /*
433: * Generate code for a structure assignment.
434: */
435: stasg(p)
436: register NODE *p;
437: {
438: register NODE *l, *r;
439: register int size;
440:
441: switch (p->in.op) {
442: case STASG: /* regular assignment */
443: l = p->in.left;
444: r = p->in.right;
445: break;
446: case STARG: /* place arg on the stack */
447: l = getlr(p, '3');
448: r = p->in.left;
449: break;
450: default:
451: cerror("STASG bad");
452: /*NOTREACHED*/
453: }
454: /*
455: * Pun source for use in code generation.
456: */
457: switch (r->in.op) {
458: case ICON:
459: r->in.op = NAME;
460: break;
461: case REG:
462: r->in.op = OREG;
463: break;
464: default:
465: cerror( "STASG-r" );
466: /*NOTREACHED*/
467: }
468: size = p->stn.stsize;
469: if (size <= 0 || size > 65535)
470: cerror("structure size out of range");
471: /*
472: * Generate optimized code based on structure size
473: * and alignment properties....
474: */
475: switch (size) {
476:
477: case 1:
478: putstr("\tmovb\t");
479: optimized:
480: adrput(r);
481: putchar(',');
482: adrput(l);
483: putchar('\n');
484: break;
485:
486: case 2:
487: if (p->stn.stalign != 2) {
488: MOVB(l, r, SZCHAR);
489: putstr("\tmovb\t");
490: } else
491: putstr("\tmovw\t");
492: goto optimized;
493:
494: case 4:
495: if (p->stn.stalign != 4) {
496: if (p->stn.stalign != 2) {
497: MOVB(l, r, 3*SZCHAR);
498: MOVB(l, r, 2*SZCHAR);
499: MOVB(l, r, 1*SZCHAR);
500: putstr("\tmovb\t");
501: } else {
502: MOVW(l, r, SZSHORT);
503: putstr("\tmovw\t");
504: }
505: } else
506: putstr("\tmovl\t");
507: goto optimized;
508:
509: case 6:
510: if (p->stn.stalign != 2)
511: goto movblk;
512: MOVW(l, r, 2*SZSHORT);
513: MOVW(l, r, 1*SZSHORT);
514: putstr("\tmovw\t");
515: goto optimized;
516:
517: case 8:
518: if (p->stn.stalign == 4) {
519: MOVL(l, r, SZLONG);
520: putstr("\tmovl\t");
521: goto optimized;
522: }
523: /* fall thru...*/
524:
525: default:
526: movblk:
527: /*
528: * Can we ever get a register conflict with R1 here?
529: */
530: putstr("\tmovab\t");
531: if(r->in.op == OREG && r->tn.rval == R1)
532: {
533: adrput(r);
534: printf(",r0\n\tmovab\t");
535: adrput(l);
536: putstr(",r1\n");
537: }
538: else
539: {
540: adrput(l);
541: putstr(",r1\n\tmovab\t");
542: adrput(r);
543: printf(",r0\n");
544: }
545: printf("\tmovl\t$%d,r2\n\tmovblk\n", size);
546: rname(R2);
547: break;
548: }
549: /*
550: * Reverse above pun for reclaim.
551: */
552: if (r->in.op == NAME)
553: r->in.op = ICON;
554: else if (r->in.op == OREG)
555: r->in.op = REG;
556: }
557:
558: /*
559: * Output the address of the second item in the
560: * pair pointed to by p.
561: */
562: upput(p, size)
563: register NODE *p;
564: {
565: CONSZ save;
566:
567: if (p->in.op == FLD)
568: p = p->in.left;
569: switch (p->in.op) {
570:
571: case NAME:
572: case OREG:
573: save = p->tn.lval;
574: p->tn.lval += size/SZCHAR;
575: adrput(p);
576: p->tn.lval = save;
577: break;
578:
579: case REG:
580: if (size == SZLONG) {
581: putstr(rname(p->tn.rval+1));
582: break;
583: }
584: /* fall thru... */
585:
586: default:
587: cerror("illegal upper address op %s size %d",
588: opst[p->tn.op], size);
589: /*NOTREACHED*/
590: }
591: }
592:
593: /*
594: * Generate code for storage conversions.
595: */
596: sconv(p, forcc)
597: NODE *p;
598: {
599: register NODE *l, *r;
600: register wfrom, wto;
601: int oltype;
602:
603: l = getlr(p, '1');
604: oltype = l->in.type, l->in.type = r->in.type;
605: r = getlr(p, 'L');
606: wfrom = tlen(r), wto = tlen(l);
607: if (wfrom == wto) /* e.g. int -> unsigned */
608: goto done;
609: /*
610: * Conversion in registers requires care
611: * as cvt and movz instruction don't work
612: * as expected (they end up as plain mov's).
613: */
614: if (l->in.op == REG && r->in.op == REG) {
615: if ((wfrom < wto && ISUNSIGNED(r->in.type)) ||
616: (wto < wfrom && ISUNSIGNED(l->in.type))) {
617: /* unsigned, mask */
618: if (r->tn.rval != l->tn.rval) {
619: printf("\tandl3\t$%d,", (1<<(wto*SZCHAR))-1);
620: adrput(r);
621: putchar(',');
622: } else
623: printf("\tandl2\t$%d,", (1<<(wto*SZCHAR))-1);
624: adrput(l);
625: } else { /* effect sign-extend */
626: printf("\tpushl\t"); adrput(r);
627: printf("\n\tcvt"); prtype(l);
628: printf("l\t%d(sp),", sizeof (int) - wto); adrput(l);
629: printf("\n\tmovab\t4(sp),sp");
630: }
631: /*
632: * If condition codes are required then we must generate a
633: * test of the appropriate type.
634: */
635: if (forcc) {
636: printf("\n\tcmp");
637: prtype(l);
638: putchar('\t');
639: adrput(l);
640: printf(",$0");
641: }
642: } else {
643: /*
644: * Conversion with at least one parameter in memory.
645: */
646: if (wfrom < wto) { /* expanding datum */
647: if (ISUNSIGNED(r->in.type)) {
648: printf("\tmovz");
649: prtype(r);
650: /*
651: * If target is a register, generate
652: * movz?l so optimizer can compress
653: * argument pushes.
654: */
655: if (l->in.op == REG)
656: putchar('l');
657: else
658: prtype(l);
659: } else {
660: printf("\tcvt");
661: prtype(r), prtype(l);
662: }
663: putchar('\t');
664: adrput(r);
665: } else { /* shrinking dataum */
666: int off = wfrom - wto;
667: if (l->in.op == REG) {
668: printf("\tmovz");
669: prtype(l);
670: putchar('l');
671: } else {
672: printf("\tcvt");
673: prtype(l), prtype(r);
674: }
675: putchar('\t');
676: switch (r->in.op) {
677: case NAME: case OREG:
678: r->tn.lval += off;
679: adrput(r);
680: r->tn.lval -= off;
681: break;
682: case REG: case ICON: case UNARY MUL:
683: adrput(r);
684: break;
685: default:
686: cerror("sconv: bad shrink op");
687: /*NOTREACHED*/
688: }
689: }
690: putchar(',');
691: adrput(l);
692: }
693: putchar('\n');
694: done:
695: l->in.type = oltype;
696: }
697:
698: rmove( rt, rs, t ) TWORD t;{
699: printf( " movl %s,%s\n", rname(rs), rname(rt) );
700: if(t==DOUBLE)
701: printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) );
702: }
703:
704: struct respref
705: respref[] = {
706: INTAREG|INTBREG, INTAREG|INTBREG,
707: INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
708: INTEMP, INTEMP,
709: FORARG, FORARG,
710: INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
711: 0, 0 };
712:
713: setregs(){ /* set up temporary registers */
714: fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */
715: }
716:
717: #ifndef szty
718: szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
719: return(t==DOUBLE ? 2 : 1 );
720: }
721: #endif
722:
723: rewfld( p ) NODE *p; {
724: return(1);
725: }
726:
727: callreg(p) NODE *p; {
728: return( R0 );
729: }
730:
731: base( p ) register NODE *p; {
732: register int o = p->in.op;
733:
734: if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
735: if( o==REG ) return( p->tn.rval );
736: if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
737: return( p->in.left->tn.rval );
738: if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
739: return( p->tn.rval + 0200*1 );
740: return( -1 );
741: }
742:
743: offset( p, tyl ) register NODE *p; int tyl; {
744:
745: if(tyl > 8) return( -1 );
746: if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
747: if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
748: (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
749: && (1<<p->in.right->tn.lval)==tyl))
750: return( p->in.left->tn.rval );
751: return( -1 );
752: }
753:
754: makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
755: register NODE *t;
756: register int i;
757: NODE *f;
758:
759: p->in.op = OREG;
760: f = p->in.left; /* have to free this subtree later */
761:
762: /* init base */
763: switch (q->in.op) {
764: case ICON:
765: case REG:
766: case OREG:
767: t = q;
768: break;
769:
770: case MINUS:
771: q->in.right->tn.lval = -q->in.right->tn.lval;
772: case PLUS:
773: t = q->in.right;
774: break;
775:
776: case UNARY MUL:
777: t = q->in.left->in.left;
778: break;
779:
780: default:
781: cerror("illegal makeor2");
782: }
783:
784: p->tn.lval = t->tn.lval;
785: #ifndef FLEXNAMES
786: for(i=0; i<NCHNAM; ++i)
787: p->in.name[i] = t->in.name[i];
788: #else
789: p->in.name = t->in.name;
790: #endif
791:
792: /* init offset */
793: p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
794:
795: tfree(f);
796: return;
797: }
798:
799: canaddr( p ) NODE *p; {
800: register int o = p->in.op;
801:
802: if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
803: return(0);
804: }
805:
806: #ifndef shltype
807: shltype( o, p ) register NODE *p; {
808: return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
809: }
810: #endif
811:
812: flshape( p ) NODE *p; {
813: register int o = p->in.op;
814:
815: if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
816: return(0);
817: }
818:
819: shtemp( p ) register NODE *p; {
820: if( p->in.op == STARG ) p = p->in.left;
821: return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
822: }
823:
824: shumul( p ) register NODE *p; {
825: register int o;
826: extern int xdebug;
827:
828: if (xdebug) {
829: printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
830: printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
831: }
832:
833: o = p->in.op;
834: if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
835: && p->in.type != PTR+DOUBLE)
836: return( STARNM );
837:
838: return( 0 );
839: }
840:
841: special( p, shape ) register NODE *p; {
842: if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
843: else return(0);
844: }
845:
846: adrcon( val ) CONSZ val; {
847: printf(ACONFMT, val);
848: }
849:
850: conput( p ) register NODE *p; {
851: switch( p->in.op ){
852:
853: case ICON:
854: acon( p );
855: return;
856:
857: case REG:
858: putstr(rname(p->tn.rval));
859: return;
860:
861: default:
862: cerror( "illegal conput" );
863: }
864: }
865:
866: insput( p ) NODE *p; {
867: cerror( "insput" );
868: }
869:
870: adrput( p ) register NODE *p; {
871: register int r;
872: /* output an address, with offsets, from p */
873:
874: if( p->in.op == FLD ){
875: p = p->in.left;
876: }
877: switch( p->in.op ){
878:
879: case NAME:
880: acon( p );
881: return;
882:
883: case ICON:
884: /* addressable value of the constant */
885: putchar('$');
886: acon( p );
887: return;
888:
889: case REG:
890: putstr(rname(p->tn.rval));
891: if(p->in.type == DOUBLE) /* for entry mask */
892: (void) rname(p->tn.rval+1);
893: return;
894:
895: case OREG:
896: r = p->tn.rval;
897: if( R2TEST(r) ){ /* double indexing */
898: register int flags;
899:
900: flags = R2UPK3(r);
901: if( flags & 1 ) putchar('*');
902: if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
903: if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
904: printf( "[%s]", rname(R2UPK2(r)) );
905: return;
906: }
907: if( r == FP && p->tn.lval > 0 ){ /* in the argument region */
908: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
909: printf( CONFMT, p->tn.lval );
910: putstr( "(fp)" );
911: return;
912: }
913: if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
914: printf( "(%s)", rname(p->tn.rval) );
915: return;
916:
917: case UNARY MUL:
918: /* STARNM or STARREG found */
919: if( tshape(p, STARNM) ) {
920: putchar( '*' );
921: adrput( p->in.left);
922: }
923: return;
924:
925: default:
926: cerror( "illegal address" );
927: return;
928:
929: }
930:
931: }
932:
933: acon( p ) register NODE *p; { /* print out a constant */
934:
935: if( p->in.name[0] == '\0' ){
936: printf( CONFMT, p->tn.lval);
937: return;
938: } else {
939: #ifndef FLEXNAMES
940: printf( "%.8s", p->in.name );
941: #else
942: putstr(p->in.name);
943: #endif
944: if (p->tn.lval != 0) {
945: putchar('+');
946: printf(CONFMT, p->tn.lval);
947: }
948: }
949: }
950:
951: genscall( p, cookie ) register NODE *p; {
952: /* structure valued call */
953: return( gencall( p, cookie ) );
954: }
955:
956: genfcall( p, cookie ) register NODE *p; {
957: register NODE *p1;
958: register int m;
959: static char *funcops[6] = {
960: "sin", "cos", "sqrt", "exp", "log", "atan"
961: };
962:
963: /* generate function opcodes */
964: if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
965: (p1 = p->in.left)->in.op==ICON &&
966: p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
967: #ifdef FLEXNAMES
968: p1->in.name++;
969: #else
970: strcpy(p1->in.name, p1->in.name[1]);
971: #endif
972: for(m=0; m<6; m++)
973: if(!strcmp(p1->in.name, funcops[m]))
974: break;
975: if(m >= 6)
976: uerror("no opcode for fortarn function %s", p1->in.name);
977: } else
978: uerror("illegal type of fortarn function");
979: p1 = p->in.right;
980: p->in.op = FORTCALL;
981: if(!canaddr(p1))
982: order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
983: m = match( p, INTAREG|INTBREG );
984: return(m != MDONE);
985: }
986:
987: /* tbl */
988: int gc_numbytes;
989: /* tbl */
990:
991: gencall( p, cookie ) register NODE *p; {
992: /* generate the call given by p */
993: register NODE *p1, *ptemp;
994: register int temp, temp1;
995: register int m;
996:
997: if( p->in.right ) temp = argsize( p->in.right );
998: else temp = 0;
999:
1000: if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1001: /* set aside room for structure return */
1002:
1003: if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1004: else temp1 = temp;
1005: }
1006:
1007: if( temp > maxargs ) maxargs = temp;
1008: SETOFF(temp1,4);
1009:
1010: if( p->in.right ){ /* make temp node, put offset in, and generate args */
1011: ptemp = talloc();
1012: ptemp->in.op = OREG;
1013: ptemp->tn.lval = -1;
1014: ptemp->tn.rval = SP;
1015: #ifndef FLEXNAMES
1016: ptemp->in.name[0] = '\0';
1017: #else
1018: ptemp->in.name = "";
1019: #endif
1020: ptemp->in.rall = NOPREF;
1021: ptemp->in.su = 0;
1022: genargs( p->in.right, ptemp );
1023: ptemp->in.op = FREE;
1024: }
1025:
1026: p1 = p->in.left;
1027: if( p1->in.op != ICON ){
1028: if( p1->in.op != REG ){
1029: if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1030: if( p1->in.op != NAME ){
1031: order( p1, INAREG );
1032: }
1033: }
1034: }
1035: }
1036:
1037: /* tbl
1038: setup gc_numbytes so reference to ZC works */
1039:
1040: gc_numbytes = temp&(0x3ff);
1041:
1042: p->in.op = UNARY CALL;
1043: m = match( p, INTAREG|INTBREG );
1044:
1045: return(m != MDONE);
1046: }
1047:
1048: /* tbl */
1049: char *
1050: ccbranches[] = {
1051: "eql",
1052: "neq",
1053: "leq",
1054: "lss",
1055: "geq",
1056: "gtr",
1057: "lequ",
1058: "lssu",
1059: "gequ",
1060: "gtru",
1061: };
1062: /* tbl */
1063:
1064: cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1065:
1066: if(o != 0 && (o < EQ || o > UGT ))
1067: cerror( "bad conditional branch: %s", opst[o] );
1068: printf( " j%s L%d\n",
1069: o == 0 ? "br" : ccbranches[o-EQ], lab );
1070: }
1071:
1072: nextcook( p, cookie ) NODE *p; {
1073: /* we have failed to match p with cookie; try another */
1074: if( cookie == FORREW ) return( 0 ); /* hopeless! */
1075: if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1076: if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1077: return( FORREW );
1078: }
1079:
1080: lastchance( p, cook ) NODE *p; {
1081: /* forget it! */
1082: return(0);
1083: }
1084:
1085: optim2( p ) register NODE *p; {
1086: # ifdef ONEPASS
1087: /* do local tree transformations and optimizations */
1088: # define RV(p) p->in.right->tn.lval
1089: # define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0)
1090: register int o, i;
1091: register NODE *l, *r;
1092:
1093: switch (o = p->in.op) {
1094:
1095: case DIV: case ASG DIV:
1096: case MOD: case ASG MOD:
1097: /*
1098: * Change unsigned mods and divs to
1099: * logicals (mul is done in mip & c2)
1100: */
1101: if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
1102: (i = ispow2(RV(p))) >= 0) {
1103: if (o == DIV || o == ASG DIV) {
1104: p->in.op = RS;
1105: RV(p) = i;
1106: } else {
1107: p->in.op = AND;
1108: RV(p)--;
1109: }
1110: if (asgop(o))
1111: p->in.op = ASG p->in.op;
1112: }
1113: return;
1114:
1115: case SCONV:
1116: l = p->in.left;
1117: /* clobber conversions w/o side effects */
1118: if (!anyfloat(p, l) && l->in.op != PCONV &&
1119: tlen(p) == tlen(l)) {
1120: if (l->in.op != FLD)
1121: l->in.type = p->in.type;
1122: ncopy(p, l);
1123: l->in.op = FREE;
1124: }
1125: return;
1126:
1127: case ASSIGN:
1128: /*
1129: * Try to zap storage conversions of non-float items.
1130: */
1131: r = p->in.right;
1132: if (r->in.op == SCONV && !anyfloat(r->in.left, r)) {
1133: int wdest, wconv, wsrc;
1134: wdest = tlen(p->in.left);
1135: wconv = tlen(r);
1136: /*
1137: * If size doesn't change across assignment or
1138: * conversion expands src before shrinking again
1139: * due to the assignment, delete conversion so
1140: * code generator can create optimal code.
1141: */
1142: if (wdest == wconv ||
1143: (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
1144: p->in.right = r->in.left;
1145: r->in.op = FREE;
1146: }
1147: }
1148: return;
1149: }
1150: # endif
1151: }
1152:
1153: struct functbl {
1154: int fop;
1155: char *func;
1156: } opfunc[] = {
1157: DIV, "udiv",
1158: ASG DIV, "udiv",
1159: 0
1160: };
1161:
1162: hardops(p) register NODE *p; {
1163: /* change hard to do operators into function calls. */
1164: register NODE *q;
1165: register struct functbl *f;
1166: register int o;
1167: register TWORD t, t1, t2;
1168:
1169: o = p->in.op;
1170:
1171: for( f=opfunc; f->fop; f++ ) {
1172: if( o==f->fop ) goto convert;
1173: }
1174: return;
1175:
1176: convert:
1177: t = p->in.type;
1178: t1 = p->in.left->in.type;
1179: t2 = p->in.right->in.type;
1180:
1181: if (!((ISUNSIGNED(t1) && !(ISUNSIGNED(t2))) ||
1182: ( t2 == UNSIGNED))) return;
1183:
1184: /* need to rewrite tree for ASG OP */
1185: /* must change ASG OP to a simple OP */
1186: if( asgop( o ) ) {
1187: q = talloc();
1188: q->in.op = NOASG ( o );
1189: q->in.rall = NOPREF;
1190: q->in.type = p->in.type;
1191: q->in.left = tcopy(p->in.left);
1192: q->in.right = p->in.right;
1193: p->in.op = ASSIGN;
1194: p->in.right = q;
1195: zappost(q->in.left); /* remove post-INCR(DECR) from new node */
1196: fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */
1197: p = q;
1198:
1199: }
1200: /* turn logicals to compare 0 */
1201: else if( logop( o ) ) {
1202: ncopy(q = talloc(), p);
1203: p->in.left = q;
1204: p->in.right = q = talloc();
1205: q->in.op = ICON;
1206: q->in.type = INT;
1207: #ifndef FLEXNAMES
1208: q->in.name[0] = '\0';
1209: #else
1210: q->in.name = "";
1211: #endif
1212: q->tn.lval = 0;
1213: q->tn.rval = 0;
1214: p = p->in.left;
1215: }
1216:
1217: /* build comma op for args to function */
1218: t1 = p->in.left->in.type;
1219: t2 = 0;
1220: if ( optype(p->in.op) == BITYPE) {
1221: q = talloc();
1222: q->in.op = CM;
1223: q->in.rall = NOPREF;
1224: q->in.type = INT;
1225: q->in.left = p->in.left;
1226: q->in.right = p->in.right;
1227: t2 = p->in.right->in.type;
1228: } else
1229: q = p->in.left;
1230:
1231: p->in.op = CALL;
1232: p->in.right = q;
1233:
1234: /* put function name in left node of call */
1235: p->in.left = q = talloc();
1236: q->in.op = ICON;
1237: q->in.rall = NOPREF;
1238: q->in.type = INCREF( FTN + p->in.type );
1239: #ifndef FLEXNAMES
1240: strcpy( q->in.name, f->func );
1241: #else
1242: q->in.name = f->func;
1243: #endif
1244: q->tn.lval = 0;
1245: q->tn.rval = 0;
1246:
1247: }
1248:
1249: zappost(p) NODE *p; {
1250: /* look for ++ and -- operators and remove them */
1251:
1252: register int o, ty;
1253: register NODE *q;
1254: o = p->in.op;
1255: ty = optype( o );
1256:
1257: switch( o ){
1258:
1259: case INCR:
1260: case DECR:
1261: q = p->in.left;
1262: p->in.right->in.op = FREE; /* zap constant */
1263: ncopy( p, q );
1264: q->in.op = FREE;
1265: return;
1266:
1267: }
1268:
1269: if( ty == BITYPE ) zappost( p->in.right );
1270: if( ty != LTYPE ) zappost( p->in.left );
1271: }
1272:
1273: fixpre(p) NODE *p; {
1274:
1275: register int o, ty;
1276: o = p->in.op;
1277: ty = optype( o );
1278:
1279: switch( o ){
1280:
1281: case ASG PLUS:
1282: p->in.op = PLUS;
1283: break;
1284: case ASG MINUS:
1285: p->in.op = MINUS;
1286: break;
1287: }
1288:
1289: if( ty == BITYPE ) fixpre( p->in.right );
1290: if( ty != LTYPE ) fixpre( p->in.left );
1291: }
1292:
1293: NODE * addroreg(l) NODE *l;
1294: /* OREG was built in clocal()
1295: * for an auto or formal parameter
1296: * now its address is being taken
1297: * local code must unwind it
1298: * back to PLUS/MINUS REG ICON
1299: * according to local conventions
1300: */
1301: {
1302: cerror("address of OREG taken");
1303: }
1304:
1305: # ifndef ONEPASS
1306: main( argc, argv ) char *argv[]; {
1307: return( mainp2( argc, argv ) );
1308: }
1309: # endif
1310:
1311: strip(p) register NODE *p; {
1312: NODE *q;
1313:
1314: /* strip nodes off the top when no side effects occur */
1315: for( ; ; ) {
1316: switch( p->in.op ) {
1317: case SCONV: /* remove lint tidbits */
1318: q = p->in.left;
1319: ncopy( p, q );
1320: q->in.op = FREE;
1321: break;
1322: /* could probably add a few more here */
1323: default:
1324: return;
1325: }
1326: }
1327: }
1328:
1329: myreader(p) register NODE *p; {
1330: strip( p ); /* strip off operations with no side effects */
1331: walkf( p, hardops ); /* convert ops to function calls */
1332: canon( p ); /* expands r-vals for fileds */
1333: walkf( p, optim2 );
1334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.