|
|
1.1 root 1: # ifndef lint
2: static char *sccsid ="@(#)local2.c 1.39 (Berkeley) 5/11/88";
3: # endif
4:
5: # include "pass2.h"
6: # include <ctype.h>
7:
8: # define putstr(s) fputs((s), stdout)
9:
10: # ifdef FORT
11: int ftlab1, ftlab2;
12: # endif
13: /* a lot of the machine dependent parts of the second pass */
14:
15: # define BITMASK(n) ((1L<<n)-1)
16:
17: /*ARGSUSED*/
18: where(c){
19: fprintf( stderr, "%s, line %d: ", filename, lineno );
20: }
21:
22: lineid( l, fn ) char *fn; {
23: /* identify line l and file fn */
24: printf( "# line %d, file %s\n", l, fn );
25: }
26:
27:
28: eobl2(){
29: register OFFSZ spoff; /* offset from stack pointer */
30: #ifndef FORT
31: extern int ftlab1, ftlab2;
32: #endif
33:
34: spoff = maxoff;
35: if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
36: spoff /= SZCHAR;
37: SETOFF(spoff,4);
38: #ifdef FORT
39: #ifndef FLEXNAMES
40: printf( " .set .F%d,%ld\n", ftnno, spoff );
41: #else
42: /* SHOULD BE L%d ... ftnno but must change pc/f77 */
43: printf( " .set LF%d,%ld\n", ftnno, spoff );
44: #endif
45: #else
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: PLUS, "add",
60: MINUS, "sub",
61: MUL, "mul",
62: DIV, "div",
63: OR, "bis",
64: ER, "xor",
65: AND, "bic",
66: -1, "" };
67:
68: hopcode( f, o ){
69: /* output the appropriate string from the above table */
70:
71: register struct hoptab *q;
72:
73: if(asgop(o))
74: o = NOASG o;
75: for( q = ioptab; q->opmask>=0; ++q ){
76: if( q->opmask == o ){
77: printf( "%s%c", q->opstring, tolower(f));
78: return;
79: }
80: }
81: cerror( "no hoptab for %s", opst[o] );
82: }
83:
84: char *
85: rnames[] = { /* keyed to register number tokens */
86:
87: "r0", "r1",
88: "r2", "r3", "r4", "r5",
89: "r6", "r7", "r8", "r9", "r10", "r11",
90: "ap", "fp", "sp", "pc",
91: };
92:
93: int rstatus[] = {
94: SAREG|STAREG, SAREG|STAREG,
95: SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
96: SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
97: SAREG, SAREG, SAREG, SAREG,
98: };
99:
100: tlen(p) NODE *p;
101: {
102: switch(p->in.type) {
103: case CHAR:
104: case UCHAR:
105: return(1);
106:
107: case SHORT:
108: case USHORT:
109: return(SZSHORT/SZCHAR);
110:
111: case DOUBLE:
112: return(SZDOUBLE/SZCHAR);
113:
114: default:
115: return(SZINT/SZCHAR);
116: }
117: }
118:
119: mixtypes(p, q) NODE *p, *q;
120: {
121: register TWORD tp, tq;
122:
123: tp = p->in.type;
124: tq = q->in.type;
125:
126: return( (tp==FLOAT || tp==DOUBLE) !=
127: (tq==FLOAT || tq==DOUBLE) );
128: }
129:
130: prtype(n) NODE *n;
131: {
132: switch (n->in.type)
133: {
134:
135: case DOUBLE:
136: putchar('d');
137: return;
138:
139: case FLOAT:
140: putchar('f');
141: return;
142:
143: case LONG:
144: case ULONG:
145: case INT:
146: case UNSIGNED:
147: putchar('l');
148: return;
149:
150: case SHORT:
151: case USHORT:
152: putchar('w');
153: return;
154:
155: case CHAR:
156: case UCHAR:
157: putchar('b');
158: return;
159:
160: default:
161: if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
162: else {
163: putchar('l');
164: return;
165: }
166: }
167: }
168:
169: zzzcode( p, c ) register NODE *p; {
170: register int m;
171: int val;
172: switch( c ){
173:
174: case 'N': /* logical ops, turned into 0-1 */
175: /* use register given by register 1 */
176: cbgen( 0, m=getlab(), 'I' );
177: deflab( p->bn.label );
178: printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] );
179: deflab( m );
180: return;
181:
182: case 'P':
183: cbgen( p->in.op, p->bn.label, c );
184: return;
185:
186: case 'A':
187: case 'V':
188: sconv( p, c == 'V' );
189: return;
190:
191: case 'G': /* i *= f; asgops with int lhs and float rhs */
192: {
193: register NODE *l, *r, *s;
194: int rt;
195:
196: l = p->in.left;
197: r = p->in.right;
198: s = talloc();
199: rt = r->in.type;
200:
201: s->in.op = SCONV;
202: s->in.left = l;
203: s->in.type = rt;
204: zzzcode(s, 'A');
205: putstr("\n\t");
206:
207: hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
208: putstr("2\t");
209: adrput(r);
210: putchar(',');
211: adrput(resc);
212: putstr("\n\t");
213:
214: s->in.op = ASSIGN;
215: s->in.left = l;
216: s->in.right = resc;
217: s->in.type = l->in.type;
218: zzzcode(s, 'A');
219:
220: s->in.op = FREE;
221: return;
222: }
223:
224: case 'J': /* unsigned DIV/MOD with constant divisors */
225: {
226: register int ck = INAREG;
227: int label1, label2;
228:
229: /* case constant <= 1 is handled by optim() in pass 1 */
230: /* case constant < 0x80000000 is handled in table */
231: switch( p->in.op ) {
232: /* case DIV: handled in optim2() */
233: case MOD:
234: if( p->in.left->in.op == REG &&
235: p->in.left->tn.rval == resc->tn.rval )
236: goto asgmod;
237: label1 = getlab();
238: expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
239: printf("\tjlssu\tL%d\n", label1);
240: expand(p, ck, "\tsubl2\tAR,A1\n");
241: printf("L%d:", label1);
242: break;
243: case ASG DIV:
244: label1 = getlab();
245: label2 = getlab();
246: expand(p, ck, "cmpl\tAL,AR\n");
247: printf("\tjgequ\tL%d\n", label1);
248: expand(p, ck, "\tmovl\t$1,AL\n");
249: printf("\tjbr\tL%d\nL%d:\n", label2, label1);
250: expand(p, ck, "\tclrl\tAL\n");
251: printf("L%d:", label2);
252: break;
253: case ASG MOD:
254: asgmod:
255: label1 = getlab();
256: expand(p, ck, "cmpl\tAL,AR\n");
257: printf("\tjlssu\tL%d\n", label1);
258: expand(p, ck, "\tsubl2\tAR,AL\n");
259: printf("L%d:", label1);
260: break;
261: }
262: return;
263: }
264:
265: case 'B': /* get oreg value in temp register for left shift */
266: {
267: register NODE *r;
268: if (xdebug) eprint(p, 0, &val, &val);
269: r = p->in.right;
270: if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT )
271: putstr("movl");
272: else {
273: putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
274: prtype(r);
275: putchar('l');
276: }
277: return;
278: }
279:
280: case 'C': /* num words pushed on arg stack */
281: {
282: extern int gc_numbytes;
283: extern int xdebug;
284:
285: if (xdebug) printf("->%d<-",gc_numbytes);
286:
287: printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
288: return;
289: }
290:
291: case 'D': /* INCR and DECR */
292: zzzcode(p->in.left, 'A');
293: putchar('\n');
294: putchar('\t');
295:
296: case 'E': /* INCR and DECR, FOREFF */
297: if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
298: {
299: putstr(p->in.op == INCR ? "inc" : "dec");
300: prtype(p->in.left);
301: putchar('\t');
302: adrput(p->in.left);
303: return;
304: }
305: putstr(p->in.op == INCR ? "add" : "sub");
306: prtype(p->in.left);
307: putchar('2');
308: putchar('\t');
309: adrput(p->in.right);
310: putchar(',');
311: adrput(p->in.left);
312: return;
313:
314: case 'F': /* register type of right operand */
315: {
316: register NODE *n;
317: extern int xdebug;
318: register int ty;
319:
320: n = getlr( p, 'R' );
321: ty = n->in.type;
322:
323: if (xdebug) printf("->%d<-", ty);
324:
325: if ( ty==DOUBLE) putchar('d');
326: else if ( ty==FLOAT ) putchar('f');
327: else putchar('l');
328: return;
329: }
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 'Z': /* AND for CC with ICON -- lval is complemented */
345: {
346: register NODE *l, *r;
347:
348: l = getlr( p, 'L' );
349: r = getlr( p, 'R' );
350: m = (1 << tlen(l) * SZCHAR) - 1;
351: r->tn.lval = ~r->tn.lval;
352: if( (l->in.type == CHAR || l->in.type == SHORT) &&
353: (r->tn.lval & ~m) ) {
354: putstr("cvt");
355: prtype(l);
356: putstr("l\t");
357: adrput(l);
358: putchar(',');
359: adrput(resc);
360: putstr("\n\t");
361: resc->tn.type = INT;
362: l = resc;
363: }
364: else if( l->in.type == UCHAR || l->in.type == USHORT )
365: /* remove trash left over from complementing */
366: r->tn.lval &= m;
367: putstr("bit");
368: prtype(l);
369: printf("\t$%ld", r->tn.lval);
370: putchar(',');
371: adrput(l);
372: return;
373: }
374:
375: case 'U': /* 32 - n, for unsigned right shifts */
376: printf("$%d", 32 - p->in.right->tn.lval );
377: return;
378:
379: case 'T': /* rounded structure length for arguments */
380: {
381: int size;
382:
383: size = p->stn.stsize;
384: SETOFF( size, 4);
385: printf("$%d", size);
386: return;
387: }
388:
389: case 'S': /* structure assignment */
390: stasg(p);
391: break;
392:
393: default:
394: cerror( "illegal zzzcode" );
395: }
396: }
397:
398: stasg(p)
399: register NODE *p;
400: {
401: register NODE *l, *r;
402: register size;
403:
404: if( p->in.op == STASG ){
405: l = p->in.left;
406: r = p->in.right;
407:
408: }
409: else if( p->in.op == STARG ){ /* store an arg into a temporary */
410: r = p->in.left;
411: }
412: else cerror( "STASG bad" );
413:
414: if( r->in.op == ICON ) r->in.op = NAME;
415: else if( r->in.op == REG ) r->in.op = OREG;
416: else if( r->in.op != OREG ) cerror( "STASG-r" );
417:
418: size = p->stn.stsize;
419:
420: if( size <= 0 || size > 65535 )
421: cerror("structure size <0=0 or >65535");
422:
423: switch(size) {
424: case 1:
425: putstr(" movb ");
426: break;
427: case 2:
428: putstr(" movw ");
429: break;
430: case 4:
431: putstr(" movl ");
432: break;
433: case 8:
434: putstr(" movq ");
435: break;
436: default:
437: printf(" movc3 $%d,", size);
438: break;
439: }
440: adrput(r);
441: if( p->in.op == STASG ){
442: putchar(',');
443: adrput(l);
444: putchar('\n');
445: }
446: else
447: putstr(",(sp)\n");
448:
449: if( r->in.op == NAME ) r->in.op = ICON;
450: else if( r->in.op == OREG ) r->in.op = REG;
451: }
452:
453: NODE *makearg( ty ) int ty; {
454: register NODE *p, *q;
455:
456: /* build a -(sp) operand */
457: p = talloc();
458: p->in.op = REG;
459: /* the type needn't be right, just consistent */
460: p->in.type = INCREF(ty);
461: p->tn.rval = SP;
462: p->tn.lval = 0;
463: q = talloc();
464: q->in.op = ASG MINUS;
465: q->in.type = INCREF(ty);
466: q->in.left = p;
467: p = talloc();
468: p->in.op = ICON;
469: p->in.type = INT;
470: p->tn.name = "";
471: /* size of floating argument is always 2 */
472: p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR);
473: q->in.right = p;
474: p = talloc();
475: p->in.op = UNARY MUL;
476: p->in.left = q;
477: return( p );
478: }
479:
480: sconv( p, forarg ) register NODE *p; {
481: register NODE *l, *r;
482: int m, val;
483:
484: if (xdebug) eprint(p, 0, &val, &val);
485: r = getlr(p, 'R');
486: if (p->in.op == ASSIGN)
487: l = getlr(p, 'L');
488: else if (p->in.op == SCONV) {
489: m = r->in.type;
490: if (forarg)
491: l = makearg( m );
492: else
493: l = resc;
494: l->in.type = m;
495: r = getlr(p, 'L');
496: }
497: else { /* OPLTYPE */
498: m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
499: if (forarg)
500: l = makearg( m );
501: else
502: l = resc;
503: l->in.type = m;
504: }
505: if (r->in.op == ICON)
506: if (r->in.name[0] == '\0') {
507: if (r->tn.lval == 0 &&
508: (r->in.type == DOUBLE || r->in.type == FLOAT ||
509: !forarg)) {
510: if (r->in.type == FLOAT)
511: r->in.type = DOUBLE;
512: putstr("clr");
513: prtype(l);
514: putchar('\t');
515: adrput(l);
516: goto cleanup;
517: }
518: if (r->tn.lval < 0 && r->tn.lval >= -63) {
519: putstr("mneg");
520: prtype(l);
521: r->tn.lval = -r->tn.lval;
522: goto ops;
523: }
524: if (r->tn.lval < 0)
525: r->in.type = r->tn.lval >= -128 ? CHAR
526: : (r->tn.lval >= -32768 ? SHORT
527: : INT);
528: else if (l->in.type == FLOAT ||
529: l->in.type == DOUBLE)
530: r->in.type = r->tn.lval <= 63 ? INT
531: : (r->tn.lval <= 127 ? CHAR
532: : (r->tn.lval <= 32767 ? SHORT
533: : INT));
534: else
535: r->in.type = r->tn.lval <= 63 ? INT
536: : (r->tn.lval <= 127 ? CHAR
537: : (r->tn.lval <= 255 ? UCHAR
538: : (r->tn.lval <= 32767 ? SHORT
539: : (r->tn.lval <= 65535 ? USHORT
540: : INT))));
541: if (forarg && r->in.type == INT) {
542: putstr("pushl\t");
543: adrput(r);
544: goto cleanup;
545: }
546: }
547: else {
548: if (forarg && tlen(r) == SZINT/SZCHAR) {
549: putstr("pushl\t");
550: adrput(r);
551: goto cleanup;
552: }
553: putstr("moval\t");
554: acon(r);
555: putchar(',');
556: adrput(l);
557: goto cleanup;
558: }
559:
560: if (p->in.op == SCONV &&
561: !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
562: !mixtypes(l, r)) {
563: /*
564: * Because registers must always contain objects
565: * of the same width as INTs, we may have to
566: * perform two conversions to get an INT. Can
567: * the conversions be collapsed into one?
568: */
569: if (m = collapsible(l, r))
570: r->in.type = m;
571: else {
572: /* two steps are required */
573: NODE *x;
574:
575: if (forarg) {
576: x = resc;
577: x->in.type = l->in.type;
578: }
579: else {
580: x = &resc[1];
581: *x = *l;
582: }
583:
584: if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
585: putstr("movz");
586: else
587: putstr("cvt");
588: prtype(r);
589: prtype(x);
590: putchar('\t');
591: adrput(r);
592: putchar(',');
593: adrput(x);
594: putchar('\n');
595: putchar('\t');
596: r = x;
597: }
598: l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
599: }
600:
601: else if ((forarg || l == resc) &&
602: tlen(l) < SZINT/SZCHAR &&
603: mixtypes(l, r)) {
604: /* two steps needed here too */
605: NODE *x;
606:
607: if (forarg) {
608: x = resc;
609: x->in.type = l->in.type;
610: }
611: else {
612: x = &resc[1];
613: *x = *l;
614: }
615: putstr("cvt");
616: prtype(r);
617: prtype(x);
618: putchar('\t');
619: adrput(r);
620: putchar(',');
621: adrput(x);
622: putstr("\n\t");
623: r = x;
624: l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
625: }
626:
627: else if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
628: mixtypes(l, r)) {
629: int label1;
630: NODE *x = NULL;
631:
632: #if defined(FORT) || defined(SPRECC)
633: if (forarg)
634: #else
635: if (forarg || l == resc)
636: #endif
637: {
638: /* compute in register, convert to double when done */
639: x = l;
640: l = resc;
641: l->in.type = x->in.type;
642: }
643:
644: label1 = getlab();
645:
646: putstr("cvtl");
647: prtype(l);
648: putchar('\t');
649: adrput(r);
650: putchar(',');
651: adrput(l);
652: printf("\n\tjgeq\tL%d\n\tadd", label1);
653: prtype(l);
654: putstr("2\t$0");
655: prtype(l);
656: putstr("4.294967296e9,");
657: adrput(l);
658: printf("\nL%d:", label1);
659:
660: #if defined(FORT) || defined(SPRECC)
661: if (!forarg)
662: #else
663: if (!forarg && (l->in.type == DOUBLE || l != resc))
664: #endif
665: goto cleanup;
666: if (x == NULL)
667: cerror("sconv botch");
668: if (l == x) {
669: r = &resc[1];
670: *r = *l;
671: }
672: else {
673: r = l;
674: l = x;
675: }
676: l->in.type = DOUBLE;
677: putstr("\n\t");
678: }
679:
680: else if( (l->in.type == FLOAT || l->in.type == DOUBLE) &&
681: (r->in.type == UCHAR || r->in.type == USHORT) ) {
682: /* skip unnecessary unsigned to floating conversion */
683: #if defined(FORT) || defined(SPRECC)
684: if (forarg)
685: #else
686: if (forarg || l == resc)
687: #endif
688: l->in.type = DOUBLE;
689: putstr("movz");
690: prtype(r);
691: putstr("l\t");
692: adrput(r);
693: putchar(',');
694: adrput(resc);
695: putstr("\n\t");
696: if (l == resc) {
697: r = &resc[1];
698: *r = *l;
699: }
700: else
701: r = resc;
702: r->in.type = INT;
703: }
704:
705: #if defined(FORT) || defined(SPRECC)
706: if (forarg && l->in.type == FLOAT)
707: #else
708: if ((forarg || l == resc) && l->in.type == FLOAT)
709: #endif
710: {
711: /* perform an implicit conversion to double */
712: l->in.type = DOUBLE;
713: if (r->in.type != FLOAT &&
714: r->in.type != CHAR &&
715: r->in.type != SHORT) {
716: /* trim bits from the mantissa */
717: putstr("cvt");
718: prtype(r);
719: putstr("f\t");
720: adrput(r);
721: putchar(',');
722: adrput(resc);
723: putstr("\n\t");
724: if (l == resc) {
725: r = &resc[1];
726: *r = *l;
727: }
728: else
729: r = resc;
730: r->in.type = FLOAT;
731: }
732: }
733:
734: if (!mixtypes(l,r)) {
735: if (tlen(l) == tlen(r)) {
736: if (forarg && tlen(l) == SZINT/SZCHAR) {
737: putstr("pushl\t");
738: adrput(r);
739: goto cleanup;
740: }
741: putstr("mov");
742: #ifdef FORT
743: if (Oflag)
744: prtype(l);
745: else {
746: if (l->in.type == DOUBLE)
747: putchar('q');
748: else if(l->in.type == FLOAT)
749: putchar('l');
750: else
751: prtype(l);
752: }
753: #else
754: prtype(l);
755: #endif FORT
756: goto ops;
757: }
758: else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
759: putstr("movz");
760: else
761: putstr("cvt");
762: }
763: else
764: putstr("cvt");
765: prtype(r);
766: prtype(l);
767: ops:
768: putchar('\t');
769: adrput(r);
770: putchar(',');
771: adrput(l);
772:
773: cleanup:
774: if (forarg)
775: tfree(l);
776: }
777:
778: /*
779: * collapsible(dest, src) -- if a conversion with a register destination
780: * can be accomplished in one instruction, return the type of src
781: * that will do the job correctly; otherwise return 0. Note that
782: * a register must always end up having type INT or UNSIGNED.
783: */
784: int
785: collapsible(dest, src)
786: NODE *dest, *src;
787: {
788: int st = src->in.type;
789: int dt = dest->in.type;
790: int newt = 0;
791:
792: /*
793: * Are there side effects of evaluating src?
794: * If the derived type will not be the same size as src,
795: * we may have to use two steps.
796: */
797: if (tlen(src) > tlen(dest)) {
798: if (tshape(src, STARREG))
799: return (0);
800: if (src->in.op == OREG && R2TEST(src->tn.rval))
801: return (0);
802: }
803:
804: /*
805: * Can we get an object of dest's type by punning src?
806: * Praises be to great Cthulhu for little-endian machines...
807: */
808: if (st == CHAR && dt == USHORT)
809: /*
810: * Special case -- we must sign-extend to 16 bits.
811: */
812: return (0);
813:
814: if (tlen(src) < tlen(dest))
815: newt = st;
816: else
817: newt = dt;
818:
819: return (newt);
820: }
821:
822: rmove( rt, rs, t ) TWORD t; {
823: printf( " %s %s,%s\n",
824: #ifdef FORT
825: !Oflag ? (t==DOUBLE ? "movq" : "movl") :
826: #endif
827: (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
828: rnames[rs], rnames[rt] );
829: }
830:
831: struct respref
832: respref[] = {
833: INTAREG|INTBREG, INTAREG|INTBREG,
834: INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
835: INTEMP, INTEMP,
836: FORARG, FORARG,
837: INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
838: 0, 0 };
839:
840: setregs(){ /* set up temporary registers */
841: fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
842: }
843:
844: /*ARGSUSED*/
845: rewfld( p ) NODE *p; {
846: return(1);
847: }
848:
849: /*ARGSUSED*/
850: callreg(p) NODE *p; {
851: return( R0 );
852: }
853:
854: base( p ) register NODE *p; {
855: register int o = p->in.op;
856:
857: if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */
858: if( o==REG ) return( p->tn.rval );
859: if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
860: return( p->in.left->tn.rval );
861: if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
862: return( p->tn.rval + 0200*1 );
863: if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
864: if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
865: if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
866: && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
867: return( p->in.left->in.left->tn.rval + 0200*(1+2) );
868: if( o==NAME ) return( 100 + 0200*1 );
869: return( -1 );
870: }
871:
872: offset( p, tyl ) register NODE *p; int tyl; {
873:
874: if( tyl==1 &&
875: p->in.op==REG &&
876: (p->in.type==INT || p->in.type==UNSIGNED) )
877: return( p->tn.rval );
878: if( p->in.op==LS &&
879: p->in.left->in.op==REG &&
880: (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
881: p->in.right->in.op==ICON &&
882: p->in.right->in.name[0]=='\0' &&
883: (1<<p->in.right->tn.lval)==tyl)
884: return( p->in.left->tn.rval );
885: if( tyl==2 &&
886: p->in.op==PLUS &&
887: (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
888: p->in.left->in.op==REG &&
889: p->in.right->in.op==REG &&
890: p->in.left->tn.rval==p->in.right->tn.rval )
891: return( p->in.left->tn.rval );
892: return( -1 );
893: }
894:
895: makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
896: register NODE *t;
897: NODE *f;
898:
899: p->in.op = OREG;
900: f = p->in.left; /* have to free this subtree later */
901:
902: /* init base */
903: switch (q->in.op) {
904: case ICON:
905: case REG:
906: case OREG:
907: case NAME:
908: t = q;
909: break;
910:
911: case MINUS:
912: q->in.right->tn.lval = -q->in.right->tn.lval;
913: case PLUS:
914: t = q->in.right;
915: break;
916:
917: case INCR:
918: case ASG MINUS:
919: t = q->in.left;
920: break;
921:
922: case UNARY MUL:
923: t = q->in.left->in.left;
924: break;
925:
926: default:
927: cerror("illegal makeor2");
928: }
929:
930: p->tn.lval = t->tn.lval;
931: #ifndef FLEXNAMES
932: {
933: register int i;
934: for(i=0; i<NCHNAM; ++i)
935: p->in.name[i] = t->in.name[i];
936: }
937: #else
938: p->in.name = t->in.name;
939: #endif
940:
941: /* init offset */
942: p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
943:
944: tfree(f);
945: return;
946: }
947:
948: canaddr( p ) NODE *p; {
949: register int o = p->in.op;
950:
951: if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
952: return(0);
953: }
954:
955: flshape( p ) NODE *p; {
956: register int o = p->in.op;
957:
958: return( o == REG || o == NAME || o == ICON ||
959: (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
960: }
961:
962: /* INTEMP shapes must not contain any temporary registers */
963: shtemp( p ) register NODE *p; {
964: int r;
965:
966: if( p->in.op == STARG ) p = p->in.left;
967:
968: switch (p->in.op) {
969: case REG:
970: return( !istreg(p->tn.rval) );
971: case OREG:
972: r = p->tn.rval;
973: if( R2TEST(r) ) {
974: if( istreg(R2UPK1(r)) )
975: return(0);
976: r = R2UPK2(r);
977: }
978: return( !istreg(r) );
979: case UNARY MUL:
980: p = p->in.left;
981: return( p->in.op != UNARY MUL && shtemp(p) );
982: }
983:
984: if( optype( p->in.op ) != LTYPE ) return(0);
985: return(1);
986: }
987:
988: shumul( p ) register NODE *p; {
989: register int o;
990: extern int xdebug;
991:
992: if (xdebug) {
993: int val;
994: printf("shumul:\n");
995: eprint(p, 0, &val, &val);
996: }
997:
998: o = p->in.op;
999: if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
1000:
1001: if( ( o == INCR || o == ASG MINUS ) &&
1002: ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
1003: p->in.right->in.name[0] == '\0' )
1004: {
1005: switch (p->in.type)
1006: {
1007: case CHAR|PTR:
1008: case UCHAR|PTR:
1009: o = 1;
1010: break;
1011:
1012: case SHORT|PTR:
1013: case USHORT|PTR:
1014: o = 2;
1015: break;
1016:
1017: case INT|PTR:
1018: case UNSIGNED|PTR:
1019: case LONG|PTR:
1020: case ULONG|PTR:
1021: case FLOAT|PTR:
1022: o = 4;
1023: break;
1024:
1025: case DOUBLE|PTR:
1026: o = 8;
1027: break;
1028:
1029: default:
1030: if ( ISPTR(p->in.type) &&
1031: ISPTR(DECREF(p->in.type)) ) {
1032: o = 4;
1033: break;
1034: }
1035: else return(0);
1036: }
1037: return( p->in.right->tn.lval == o ? STARREG : 0);
1038: }
1039:
1040: return( 0 );
1041: }
1042:
1043: adrcon( val ) CONSZ val; {
1044: putchar( '$' );
1045: printf( CONFMT, val );
1046: }
1047:
1048: conput( p ) register NODE *p; {
1049: switch( p->in.op ){
1050:
1051: case ICON:
1052: acon( p );
1053: return;
1054:
1055: case REG:
1056: putstr( rnames[p->tn.rval] );
1057: return;
1058:
1059: default:
1060: cerror( "illegal conput" );
1061: }
1062: }
1063:
1064: /*ARGSUSED*/
1065: insput( p ) NODE *p; {
1066: cerror( "insput" );
1067: }
1068:
1069: upput( p, size ) NODE *p; int size; {
1070: if( size == SZLONG && p->in.op == REG ) {
1071: putstr( rnames[p->tn.rval + 1] );
1072: return;
1073: }
1074: cerror( "upput" );
1075: }
1076:
1077: adrput( p ) register NODE *p; {
1078: register int r;
1079: /* output an address, with offsets, from p */
1080:
1081: if( p->in.op == FLD ){
1082: p = p->in.left;
1083: }
1084: switch( p->in.op ){
1085:
1086: case NAME:
1087: acon( p );
1088: return;
1089:
1090: case ICON:
1091: /* addressable value of the constant */
1092: putchar( '$' );
1093: acon( p );
1094: return;
1095:
1096: case REG:
1097: putstr( rnames[p->tn.rval] );
1098: return;
1099:
1100: case OREG:
1101: r = p->tn.rval;
1102: if( R2TEST(r) ){ /* double indexing */
1103: register int flags;
1104:
1105: flags = R2UPK3(r);
1106: if( flags & 1 ) putchar('*');
1107: if( flags & 4 ) putchar('-');
1108: if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1109: if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
1110: if( flags & 2 ) putchar('+');
1111: printf( "[%s]", rnames[R2UPK2(r)] );
1112: return;
1113: }
1114: if( r == AP ){ /* in the argument region */
1115: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
1116: printf( CONFMT, p->tn.lval );
1117: putstr( "(ap)" );
1118: return;
1119: }
1120: if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1121: printf( "(%s)", rnames[p->tn.rval] );
1122: return;
1123:
1124: case UNARY MUL:
1125: /* STARNM or STARREG found */
1126: if( tshape(p, STARNM) ) {
1127: putchar( '*' );
1128: adrput( p->in.left);
1129: }
1130: else { /* STARREG - really auto inc or dec */
1131: register NODE *q;
1132:
1133: q = p->in.left;
1134: if( q->in.right->tn.lval != tlen(p) )
1135: cerror("adrput: bad auto-increment/decrement");
1136: printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
1137: rnames[q->in.left->tn.rval],
1138: (q->in.op==INCR ? "+" : "") );
1139: p->in.op = OREG;
1140: p->tn.rval = q->in.left->tn.rval;
1141: p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
1142: #ifndef FLEXNAMES
1143: p->in.name[0] = '\0';
1144: #else
1145: p->in.name = "";
1146: #endif
1147: tfree(q);
1148: }
1149: return;
1150:
1151: default:
1152: cerror( "illegal address" );
1153: return;
1154:
1155: }
1156:
1157: }
1158:
1159: acon( p ) register NODE *p; { /* print out a constant */
1160:
1161: if( p->in.name[0] == '\0' )
1162: printf( CONFMT, p->tn.lval);
1163: else {
1164: #ifndef FLEXNAMES
1165: printf( "%.8s", p->in.name );
1166: #else
1167: putstr( p->in.name );
1168: #endif
1169: if( p->tn.lval != 0 ) {
1170: putchar( '+' );
1171: printf( CONFMT, p->tn.lval );
1172: }
1173: }
1174: }
1175:
1176: genscall( p, cookie ) register NODE *p; {
1177: /* structure valued call */
1178: return( gencall( p, cookie ) );
1179: }
1180:
1181: /* tbl */
1182: int gc_numbytes;
1183: /* tbl */
1184:
1185: /*ARGSUSED*/
1186: gencall( p, cookie ) register NODE *p; {
1187: /* generate the call given by p */
1188: register NODE *p1;
1189: register int temp, temp1;
1190: register int m;
1191:
1192: if( p->in.right ) temp = argsize( p->in.right );
1193: else temp = 0;
1194:
1195: if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1196: /* set aside room for structure return */
1197:
1198: if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1199: else temp1 = temp;
1200: }
1201:
1202: if( temp > maxargs ) maxargs = temp;
1203: SETOFF(temp1,4);
1204:
1205: if( p->in.right ){ /* make temp node, put offset in, and generate args */
1206: genargs( p->in.right );
1207: }
1208:
1209: p1 = p->in.left;
1210: if( p1->in.op != ICON ){
1211: if( p1->in.op != REG ){
1212: if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1213: if( p1->in.op != NAME ){
1214: order( p1, INAREG );
1215: }
1216: }
1217: }
1218: }
1219:
1220: /* tbl
1221: setup gc_numbytes so reference to ZC works */
1222:
1223: gc_numbytes = temp&(0x3ff);
1224: /* tbl */
1225:
1226: p->in.op = UNARY CALL;
1227: m = match( p, INTAREG|INTBREG );
1228:
1229: /* compensate for deficiency in 'ret' instruction ... wah,kre */
1230: /* (plus in assignment to gc_numbytes above, for neatness only) */
1231: if (temp >= 1024)
1232: printf(" addl2 $%d,sp\n", (temp&(~0x3ff)));
1233:
1234: return(m != MDONE);
1235: }
1236:
1237: /* tbl */
1238: char *
1239: ccbranches[] = {
1240: "eql",
1241: "neq",
1242: "leq",
1243: "lss",
1244: "geq",
1245: "gtr",
1246: "lequ",
1247: "lssu",
1248: "gequ",
1249: "gtru",
1250: };
1251: /* tbl */
1252:
1253: /*ARGSUSED*/
1254: cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1255:
1256: if( o != 0 && ( o < EQ || o > UGT ) )
1257: cerror( "bad conditional branch: %s", opst[o] );
1258: printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
1259: }
1260:
1261: nextcook( p, cookie ) NODE *p; {
1262: /* we have failed to match p with cookie; try another */
1263: if( cookie == FORREW ) return( 0 ); /* hopeless! */
1264: if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1265: if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1266: return( FORREW );
1267: }
1268:
1269: /*ARGSUSED*/
1270: lastchance( p, cook ) NODE *p; {
1271: /* forget it! */
1272: return(0);
1273: }
1274:
1275: optim2( p ) register NODE *p; {
1276: /* do local tree transformations and optimizations */
1277:
1278: int o;
1279: int i, mask;
1280: register NODE *l, *r;
1281:
1282: switch( o = p->in.op ) {
1283:
1284: case ASG PLUS:
1285: case ASG MINUS:
1286: case ASG MUL:
1287: case ASG OR:
1288: /* simple ASG OPSIMP -- reduce range of constant rhs */
1289: l = p->in.left;
1290: r = p->in.right;
1291: if( tlen(l) < SZINT/SZCHAR &&
1292: r->in.op==ICON && r->in.name[0]==0 ){
1293: mask = (1 << tlen(l) * SZCHAR) - 1;
1294: if( r->tn.lval & (mask & ~(mask >> 1)) )
1295: r->tn.lval |= ~mask;
1296: else
1297: r->tn.lval &= mask;
1298: }
1299: break;
1300:
1301: case AND:
1302: /* commute L and R to eliminate complements and constants */
1303: if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1304: l->in.op == COMPL ) {
1305: p->in.left = p->in.right;
1306: p->in.right = l;
1307: }
1308: /* fall through */
1309:
1310: case ASG AND:
1311: /* change meaning of AND to ~R&L - bic on pdp11/vax */
1312: r = p->in.right;
1313: if( r->in.op==ICON && r->in.name[0]==0 ) {
1314: /* check for degenerate operations */
1315: l = p->in.left;
1316: mask = (1 << tlen(l) * SZCHAR) - 1;
1317: if( o == ASG AND || ISUNSIGNED(r->in.type) ) {
1318: i = ~r->tn.lval & mask;
1319: if( i == 0 ) {
1320: /* redundant mask */
1321: r->in.op = FREE;
1322: ncopy(p, l);
1323: l->in.op = FREE;
1324: break;
1325: }
1326: else if( i == mask )
1327: /* all bits masked off */
1328: goto zero;
1329: r->tn.lval = i;
1330: if( tlen(l) < SZINT/SZCHAR ){
1331: /* sign extend */
1332: if( r->tn.lval & (mask & ~(mask >> 1)) )
1333: r->tn.lval |= ~mask;
1334: else
1335: r->tn.lval &= mask;
1336: }
1337: break;
1338: }
1339: else if( r->tn.lval == mask &&
1340: tlen(l) < SZINT/SZCHAR ) {
1341: /* use movz instead of bic */
1342: r->in.op = SCONV;
1343: r->in.left = l;
1344: r->in.right = 0;
1345: r->in.type = ENUNSIGN(l->in.type);
1346: r->in.su = l->in.su > 1 ? l->in.su : 1;
1347: ncopy(p, r);
1348: p->in.left = r;
1349: p->in.type = INT;
1350: break;
1351: }
1352: /* complement constant */
1353: r->tn.lval = ~r->tn.lval;
1354: }
1355: else if( r->in.op==COMPL ) { /* ~~A => A */
1356: r->in.op = FREE;
1357: p->in.right = r->in.left;
1358: }
1359: else { /* insert complement node */
1360: p->in.right = l = talloc();
1361: l->in.op = COMPL;
1362: l->in.rall = NOPREF;
1363: l->in.type = r->in.type;
1364: l->in.left = r;
1365: l->in.right = NULL;
1366: }
1367: break;
1368:
1369: case SCONV:
1370: l = p->in.left;
1371: #if defined(FORT) || defined(SPRECC)
1372: if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1373: l->in.type == FLOAT || l->in.type == DOUBLE )
1374: return;
1375: #else
1376: if( mixtypes(p, l) ) return;
1377: #endif
1378: if( l->in.op == PCONV )
1379: return;
1380: if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
1381: l->in.type != INT && l->in.type != UNSIGNED )
1382: return;
1383:
1384: /* Only trust it to get it right if the size is the same */
1385: if( tlen(p) != tlen(l) )
1386: return;
1387:
1388: /* clobber conversion */
1389: if( l->in.op != FLD )
1390: l->in.type = p->in.type;
1391: ncopy( p, l );
1392: l->in.op = FREE;
1393:
1394: break;
1395:
1396: case ASSIGN:
1397: /*
1398: * Conversions are equivalent to assignments;
1399: * when the two operations are combined,
1400: * we can sometimes zap the conversion.
1401: */
1402: r = p->in.right;
1403: l = p->in.left;
1404: if ( r->in.op == SCONV &&
1405: !mixtypes(l, r) &&
1406: l->in.op != FLD &&
1407: tlen(l) == tlen(r) ) {
1408: p->in.right = r->in.left;
1409: r->in.op = FREE;
1410: }
1411: break;
1412:
1413: case ULE:
1414: case ULT:
1415: case UGE:
1416: case UGT:
1417: p->in.op -= (UGE-GE);
1418: if( degenerate(p) )
1419: break;
1420: p->in.op += (UGE-GE);
1421: break;
1422:
1423: case EQ:
1424: case NE:
1425: case LE:
1426: case LT:
1427: case GE:
1428: case GT:
1429: if( p->in.left->in.op == SCONV &&
1430: p->in.right->in.op == SCONV ) {
1431: l = p->in.left;
1432: r = p->in.right;
1433: if( l->in.type == DOUBLE &&
1434: l->in.left->in.type == FLOAT &&
1435: r->in.left->in.type == FLOAT ) {
1436: /* nuke the conversions */
1437: p->in.left = l->in.left;
1438: p->in.right = r->in.left;
1439: l->in.op = FREE;
1440: r->in.op = FREE;
1441: }
1442: /* more? */
1443: }
1444: (void) degenerate(p);
1445: break;
1446:
1447: case DIV:
1448: if( p->in.right->in.op == ICON &&
1449: p->in.right->tn.name[0] == '\0' &&
1450: ISUNSIGNED(p->in.right->in.type) &&
1451: (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
1452: /* easy to do here, harder to do in zzzcode() */
1453: p->in.op = UGE;
1454: break;
1455: }
1456: case MOD:
1457: case ASG DIV:
1458: case ASG MOD:
1459: /*
1460: * optimize DIV and MOD
1461: *
1462: * basically we spot UCHAR and USHORT and try to do them
1463: * as signed ints... apparently div+mul+sub is always
1464: * faster than ediv for finding MOD on the VAX, when
1465: * full unsigned MOD isn't needed.
1466: *
1467: * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
1468: * are faster for unsigned dividend and a constant divisor
1469: * in the right range (.5 to 1 of dividend's range for the
1470: * first, .333+ to .5 for the second). full unsigned is
1471: * already done cmp+sub in the appropriate case; the
1472: * other cases are less common and require more ambition.
1473: */
1474: if( degenerate(p) )
1475: break;
1476: l = p->in.left;
1477: r = p->in.right;
1478: if( !ISUNSIGNED(r->in.type) ||
1479: tlen(l) >= SZINT/SZCHAR ||
1480: !(tlen(r) < SZINT/SZCHAR ||
1481: (r->in.op == ICON && r->tn.name[0] == '\0')) )
1482: break;
1483: if( r->in.op == ICON )
1484: r->tn.type = INT;
1485: else {
1486: NODE *t = talloc();
1487: t->in.left = r;
1488: r = t;
1489: r->in.op = SCONV;
1490: r->in.type = INT;
1491: r->in.right = 0;
1492: p->in.right = r;
1493: }
1494: if( o == DIV || o == MOD ) {
1495: NODE *t = talloc();
1496: t->in.left = l;
1497: l = t;
1498: l->in.op = SCONV;
1499: l->in.type = INT;
1500: l->in.right = 0;
1501: p->in.left = l;
1502: }
1503: /* handle asgops in table */
1504: break;
1505:
1506: case RS:
1507: case ASG RS:
1508: case LS:
1509: case ASG LS:
1510: /* pick up degenerate shifts */
1511: l = p->in.left;
1512: r = p->in.right;
1513: if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
1514: break;
1515: i = r->tn.lval;
1516: if( i < 0 )
1517: /* front end 'fixes' this? */
1518: if( o == LS || o == ASG LS )
1519: o += (RS-LS);
1520: else
1521: o += (LS-RS);
1522: if( (o == RS || o == ASG RS) &&
1523: !ISUNSIGNED(l->in.type) )
1524: /* can't optimize signed right shifts */
1525: break;
1526: if( o == LS ) {
1527: if( i < SZINT )
1528: break;
1529: }
1530: else {
1531: if( i < tlen(l) * SZCHAR )
1532: break;
1533: }
1534: zero:
1535: if( !asgop( o ) )
1536: if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1537: /* no side effects */
1538: tfree(l);
1539: ncopy(p, r);
1540: r->in.op = FREE;
1541: p->tn.lval = 0;
1542: }
1543: else {
1544: p->in.op = COMOP;
1545: r->tn.lval = 0;
1546: }
1547: else {
1548: p->in.op = ASSIGN;
1549: r->tn.lval = 0;
1550: }
1551: break;
1552: }
1553: }
1554:
1555: degenerate(p) register NODE *p; {
1556: int o;
1557: int result, i;
1558: int lower, upper;
1559: register NODE *l, *r;
1560:
1561: /*
1562: * try to keep degenerate comparisons with constants
1563: * out of the table.
1564: */
1565: r = p->in.right;
1566: l = p->in.left;
1567: if( r->in.op != ICON ||
1568: r->tn.name[0] != '\0' ||
1569: tlen(l) >= tlen(r) )
1570: return (0);
1571: switch( l->in.type ) {
1572: case CHAR:
1573: lower = -(1 << SZCHAR - 1);
1574: upper = (1 << SZCHAR - 1) - 1;
1575: break;
1576: case UCHAR:
1577: lower = 0;
1578: upper = (1 << SZCHAR) - 1;
1579: break;
1580: case SHORT:
1581: lower = -(1 << SZSHORT - 1);
1582: upper = (1 << SZSHORT - 1) - 1;
1583: break;
1584: case USHORT:
1585: lower = 0;
1586: upper = (1 << SZSHORT) - 1;
1587: break;
1588: default:
1589: cerror("unsupported type in degenerate()");
1590: }
1591: i = r->tn.lval;
1592: switch( o = p->in.op ) {
1593: case DIV:
1594: case ASG DIV:
1595: case MOD:
1596: case ASG MOD:
1597: /* DIV and MOD work like EQ */
1598: case EQ:
1599: case NE:
1600: if( lower == 0 && (unsigned) i > upper )
1601: result = o == NE;
1602: else if( i < lower || i > upper )
1603: result = o == NE;
1604: else
1605: return (0);
1606: break;
1607: case LT:
1608: case GE:
1609: if( lower == 0 && (unsigned) i > upper )
1610: result = o == LT;
1611: else if( i <= lower )
1612: result = o != LT;
1613: else if( i > upper )
1614: result = o == LT;
1615: else
1616: return (0);
1617: break;
1618: case LE:
1619: case GT:
1620: if( lower == 0 && (unsigned) i >= upper )
1621: result = o == LE;
1622: else if( i < lower )
1623: result = o != LE;
1624: else if( i >= upper )
1625: result = o == LE;
1626: else
1627: return (0);
1628: break;
1629: default:
1630: cerror("unknown op in degenerate()");
1631: }
1632:
1633: if( o == MOD || o == ASG MOD ) {
1634: r->in.op = FREE;
1635: ncopy(p, l);
1636: l->in.op = FREE;
1637: }
1638: else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1639: /* no side effects */
1640: tfree(l);
1641: ncopy(p, r);
1642: r->in.op = FREE;
1643: p->tn.lval = result;
1644: }
1645: else {
1646: if( o == ASG DIV )
1647: p->in.op = ASSIGN;
1648: else {
1649: p->in.op = COMOP;
1650: r->tn.type = INT;
1651: }
1652: r->tn.lval = result;
1653: }
1654: if( logop(o) )
1655: p->in.type = INT;
1656:
1657: return (1);
1658: }
1659:
1660: /* added by jwf */
1661: struct functbl {
1662: int fop;
1663: TWORD ftype;
1664: char *func;
1665: } opfunc[] = {
1666: DIV, TANY, "udiv",
1667: MOD, TANY, "urem",
1668: ASG DIV, TANY, "audiv",
1669: ASG MOD, TANY, "aurem",
1670: 0, 0, 0 };
1671:
1672: hardops(p) register NODE *p; {
1673: /* change hard to do operators into function calls. */
1674: register NODE *q;
1675: register struct functbl *f;
1676: register o;
1677: NODE *old,*temp;
1678:
1679: o = p->in.op;
1680: if( ! (optype(o)==BITYPE &&
1681: (ISUNSIGNED(p->in.left->in.type) ||
1682: ISUNSIGNED(p->in.right->in.type))) )
1683: return;
1684:
1685: for( f=opfunc; f->fop; f++ ) {
1686: if( o==f->fop ) goto convert;
1687: }
1688: return;
1689:
1690: convert:
1691: if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
1692: /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
1693: /* save a subroutine call -- use at most 5 instructions */
1694: return;
1695: if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
1696: /* optim2() will modify the op into an ordinary int op */
1697: return;
1698: if( asgop( o ) ) {
1699: old = NIL;
1700: switch( p->in.left->in.op ){
1701: case FLD:
1702: q = p->in.left->in.left;
1703: /*
1704: * rewrite (lval.fld /= rval); as
1705: * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1706: * else the compiler will evaluate lval twice.
1707: */
1708: if( q->in.op == UNARY MUL ){
1709: /* first allocate a temp storage */
1710: temp = talloc();
1711: temp->in.op = OREG;
1712: temp->tn.rval = TMPREG;
1713: temp->tn.lval = BITOOR(freetemp(1));
1714: temp->in.type = INCREF(p->in.type);
1715: #ifdef FLEXNAMES
1716: temp->in.name = "";
1717: #else
1718: temp->in.name[0] = '\0';
1719: #endif
1720: old = q->in.left;
1721: q->in.left = temp;
1722: }
1723: /* fall thru ... */
1724:
1725: case REG:
1726: case NAME:
1727: case OREG:
1728: /* change ASG OP to a simple OP */
1729: q = talloc();
1730: q->in.op = NOASG p->in.op;
1731: q->in.rall = NOPREF;
1732: q->in.type = p->in.type;
1733: q->in.left = tcopy(p->in.left);
1734: q->in.right = p->in.right;
1735: p->in.op = ASSIGN;
1736: p->in.right = q;
1737: p = q;
1738: f -= 2; /* Note: this depends on the table order */
1739: /* on the right side only - replace *temp with
1740: *(temp = &lval), build the assignment node */
1741: if( old ){
1742: temp = q->in.left->in.left; /* the "*" node */
1743: q = talloc();
1744: q->in.op = ASSIGN;
1745: q->in.left = temp->in.left;
1746: q->in.right = old;
1747: q->in.type = old->in.type;
1748: #ifdef FLEXNAMES
1749: q->in.name = "";
1750: #else
1751: q->in.name[0] = '\0';
1752: #endif
1753: temp->in.left = q;
1754: }
1755: break;
1756:
1757: case UNARY MUL:
1758: /* avoid doing side effects twice */
1759: q = p->in.left;
1760: p->in.left = q->in.left;
1761: q->in.op = FREE;
1762: break;
1763:
1764: default:
1765: cerror( "hardops: can't compute & LHS" );
1766: }
1767: }
1768:
1769: /* build comma op for args to function */
1770: q = talloc();
1771: q->in.op = CM;
1772: q->in.rall = NOPREF;
1773: q->in.type = INT;
1774: q->in.left = p->in.left;
1775: q->in.right = p->in.right;
1776: p->in.op = CALL;
1777: p->in.right = q;
1778:
1779: /* put function name in left node of call */
1780: p->in.left = q = talloc();
1781: q->in.op = ICON;
1782: q->in.rall = NOPREF;
1783: q->in.type = INCREF( FTN + p->in.type );
1784: #ifndef FLEXNAMES
1785: strcpy( q->in.name, f->func );
1786: #else
1787: q->in.name = f->func;
1788: #endif
1789: q->tn.lval = 0;
1790: q->tn.rval = 0;
1791:
1792: }
1793:
1794: zappost(p) NODE *p; {
1795: /* look for ++ and -- operators and remove them */
1796:
1797: register int o, ty;
1798: register NODE *q;
1799: o = p->in.op;
1800: ty = optype( o );
1801:
1802: switch( o ){
1803:
1804: case INCR:
1805: case DECR:
1806: q = p->in.left;
1807: p->in.right->in.op = FREE; /* zap constant */
1808: ncopy( p, q );
1809: q->in.op = FREE;
1810: return;
1811:
1812: }
1813:
1814: if( ty == BITYPE ) zappost( p->in.right );
1815: if( ty != LTYPE ) zappost( p->in.left );
1816: }
1817:
1818: fixpre(p) NODE *p; {
1819:
1820: register int o, ty;
1821: o = p->in.op;
1822: ty = optype( o );
1823:
1824: switch( o ){
1825:
1826: case ASG PLUS:
1827: p->in.op = PLUS;
1828: break;
1829: case ASG MINUS:
1830: p->in.op = MINUS;
1831: break;
1832: }
1833:
1834: if( ty == BITYPE ) fixpre( p->in.right );
1835: if( ty != LTYPE ) fixpre( p->in.left );
1836: }
1837:
1838: /*ARGSUSED*/
1839: NODE * addroreg(l) NODE *l;
1840: /* OREG was built in clocal()
1841: * for an auto or formal parameter
1842: * now its address is being taken
1843: * local code must unwind it
1844: * back to PLUS/MINUS REG ICON
1845: * according to local conventions
1846: */
1847: {
1848: cerror("address of OREG taken");
1849: /*NOTREACHED*/
1850: }
1851:
1852:
1853:
1854: # ifndef ONEPASS
1855: main( argc, argv ) char *argv[]; {
1856: return( mainp2( argc, argv ) );
1857: }
1858: # endif
1859:
1860: strip(p) register NODE *p; {
1861: NODE *q;
1862:
1863: /* strip nodes off the top when no side effects occur */
1864: for( ; ; ) {
1865: switch( p->in.op ) {
1866: case SCONV: /* remove lint tidbits */
1867: q = p->in.left;
1868: ncopy( p, q );
1869: q->in.op = FREE;
1870: break;
1871: /* could probably add a few more here */
1872: default:
1873: return;
1874: }
1875: }
1876: }
1877:
1878: myreader(p) register NODE *p; {
1879: strip( p ); /* strip off operations with no side effects */
1880: canon( p ); /* expands r-vals for fields */
1881: walkf( p, hardops ); /* convert ops to function calls */
1882: walkf( p, optim2 );
1883: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.