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