|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)util2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "cpass2.h"
10: #include "ctype.h"
11:
12: /*
13: * garbage ripped out of local2.68, which was huge
14: */
15: # ifdef FORT
16: int ftlab1, ftlab2;
17: # endif
18: /* a lot of the machine dependent parts of the second pass */
19: #ifdef FORT
20: # define fltfun 0
21: #else
22: extern int fltfun;
23: #endif
24:
25: #ifndef ONEPASS /* 2nd pass of (possibly) several compilers */
26: char pcname[]= "pc0"; /* name passed by pc command */
27: int pascal=0; /* = 1 if compiling pascal */
28: #endif
29:
30: # define BITMASK(n) ((1L<<(n))-1)
31:
32: /* output forms for floating point constants */
33: typedef enum {
34: F_hex, F_eformat, F_loworder, F_highorder
35: } Floatform;
36:
37: void adrput();
38: static void fcon();
39: static void dumpfcons();
40:
41: void
42: print_d(value)
43: register int value;
44: {
45: char buffer[8];
46: register char *p= buffer+8;
47: register int i= 0;
48:
49: if (value == 0) {
50: putchar('0');
51: return;
52: }
53: if (value < 0) {
54: putchar('-');
55: value= -value;
56: }
57: if (value <= 32767) {
58: register short v= value;
59: while (v != 0) {
60: *--p= (v % 10) + '0';
61: v /= 10;
62: i++;
63: }
64: } else {
65: while (value != 0) {
66: *--p= (value % 10) + '0';
67: value /= 10;
68: i++;
69: }
70: }
71: for(; i>0; i--)
72: putchar(*p++);
73: }
74:
75: void
76: print_x(value)
77: register unsigned value;
78: {
79: char buffer[8];
80: register char *p= buffer+8;
81: register int i= 0;
82:
83: if (value == 0) {
84: putchar('0');
85: return;
86: }
87: if ((int)value < 0) {
88: value = -value;
89: putchar('-');
90: }
91: while (value != 0) {
92: *--p = "0123456789abcdef"[value & 0xf];
93: value >>= 4;
94: i++;
95: }
96: putchar('0');
97: putchar('x');
98: fwrite(p, 1, i, stdout);
99: }
100:
101: void
102: print_str(s)
103: char *s;
104: {
105: fputs(s, stdout);
106: }
107:
108: void
109: print_str_nl(s)
110: char *s;
111: {
112: puts(s);
113: }
114:
115: void
116: print_str_d(s, d)
117: char *s;
118: int d;
119: {
120: fputs(s, stdout);
121: print_d(d);
122: }
123:
124: void
125: print_str_d_nl(s, d)
126: char *s;
127: int d;
128: {
129: fputs(s, stdout);
130: print_d(d);
131: putchar('\n');
132: }
133:
134: void
135: print_str_str(s1, s2)
136: char *s1, *s2;
137: {
138: fputs(s1, stdout);
139: fputs(s2, stdout);
140: }
141:
142: void
143: print_str_str_nl(s1, s2)
144: char *s1, *s2;
145: {
146: fputs(s1, stdout);
147: puts(s2);
148: }
149:
150: void print_label(l)
151: int l;
152: {
153: putchar('L');
154: print_d(l);
155: putchar(':');
156: }
157:
158: where(c)
159: {
160: fprintf( stderr, "%s, line %d: ", filename, lineno );
161: }
162:
163: lineid( l, fn )
164: char *fn;
165: {
166: /* identify line l and file fn */
167: printf( "| line %d, file %s\n", l, fn );
168: }
169:
170: epr(p)
171: NODE *p;
172: {
173: extern fwalk();
174: fwalk(p, eprint, 0);
175: }
176:
177: int usedregs; /* Flag word for registers used in current routine */
178: int usedfpregs; /* Flag word for floating point registers */
179: int toff, maxtoff;
180:
181: cntbits(i)
182: register int i;
183: {
184: register int j,ans;
185:
186: for (ans=0, j=0; i!=0 && j<16; j++) {
187: if (i&1) ans++;
188: i >>= 1 ;
189: }
190: return(ans);
191: }
192:
193: /*
194: * allocate storage for register save areas
195: * and generate routine epilogs. The d/a register
196: * save area is always the LAST section of an
197: * activation record. A label equated to its offset
198: * is used to create the activation record at runtime.
199: */
200: eobl2()
201: {
202: OFFSZ regsave_off; /* a6-relative offset of areg/dreg save area */
203: OFFSZ fp_regsave_off; /* a6-relative offset of fp reg save area */
204: OFFSZ spoff; /* a6-relative offset of local vars/temps */
205:
206: # ifndef FORT
207: extern int ftlab1, ftlab2;
208: # endif
209:
210: # ifdef FREETEMP
211: spoff = maxoff + maxtemp;
212: # else
213: spoff = maxoff;
214: # endif FREETEMP
215:
216: spoff /= SZCHAR;
217: SETOFF(spoff,sizeof(long));
218: /*
219: * set masks for saving/restoring registers
220: */
221: usedregs &= REGVARMASK;
222: usedfpregs &= FREGVARMASK;
223: /*
224: * allocate storage for register save areas
225: */
226: fp_regsave_off = regsave_off = spoff;
227: if (use68881 && usedfpregs) {
228: fp_regsave_off += (SZEXTENDED/SZCHAR)*cntbits(usedfpregs);
229: regsave_off = fp_regsave_off;
230: }
231: if (usedregs) {
232: regsave_off += (SZLONG/SZCHAR)*cntbits(usedregs);
233: }
234: /*
235: * generate epilogue
236: */
237: printf( "LE%d:\n",ftnno);
238: if (use68881 && usedfpregs) {
239: /*
240: * restore floating point registers.
241: */
242: if (fp_regsave_off > 32767) {
243: /* long offset */
244: if (use68020) {
245: printf(" fmovem a6@(-0x%x:l),#0x%x\n",
246: fp_regsave_off, usedfpregs);
247: } else {
248: /*
249: * 68881 but no 68020; I doubt this will
250: * ever happen, but just in case...
251: */
252: printf(" movl #-0x%x,a0\n",
253: fp_regsave_off);
254: printf(" fmovem a6@(0,a0:l),#0x%x",
255: usedfpregs);
256: }
257: } else {
258: /* short offset */
259: printf(" fmovem a6@(-0x%x),#0x%x\n",
260: fp_regsave_off, usedfpregs);
261: }
262: } /* usedfpregs */
263: if (usedregs) {
264: /*
265: * restore data and address registers
266: */
267: if (regsave_off > 32767) {
268: /* long offset */
269: if (use68020) {
270: printf( " moveml a6@(-0x%x:l),#0x%x\n",
271: regsave_off, usedregs );
272: } else {
273: printf(" movl #-0x%x,a0\n",
274: regsave_off);
275: printf(" moveml a6@(0,a0:l),#0x%x\n",
276: usedregs);
277: }
278: } else {
279: /* short offset */
280: printf( " moveml a6@(-0x%x),#0x%x\n",
281: regsave_off, usedregs );
282: }
283: } /* usedregs */
284: printf( " unlk a6\n rts\n" );
285: printf( " LF%d = %ld\n", ftnno, regsave_off );
286: printf( " LS%d = 0x%x\n", ftnno, usedregs );
287: printf( " LFF%d = %ld\n", ftnno, fp_regsave_off );
288: printf( " LSS%d = 0x%x\n", ftnno, usedfpregs );
289: # ifdef FREETEMP
290: printf(" LT%d = 0x%x\n", ftnno,
291: cntbits(usedregs)*(SZINT/SZCHAR));
292: # endif
293: # ifdef STACKPROBE
294: printf(" LP%d = 0x%x\n", ftnno, maxtoff+8 );
295: # endif
296: maxtoff = 0;
297: usedregs = 0;
298: usedfpregs = 0;
299: dumpfcons();
300: }
301:
302: struct hoptab { int opmask; char * opstring; } ioptab[] = {
303:
304: ASG PLUS, "add",
305: ASG MINUS, "sub",
306: ASG OR, "or",
307: ASG AND, "and",
308: ASG ER, "eor",
309: ASG MUL, "mul",
310: ASG DIV, "div",
311: ASG MOD, "div",
312: ASG LS, "sl",
313: ASG RS, "sr",
314: -1, "" };
315:
316: hopcode( f, o )
317: {
318: /* output the appropriate string from the above table */
319:
320: register struct hoptab *q;
321:
322: for( q = ioptab; q->opmask>=0; ++q ){
323: if( q->opmask == o ){
324: if( f == 'F') putchar('f');
325: printf(q->opstring);
326: return;
327: }
328: }
329: cerror( "no hoptab for %s", opst[o] );
330: }
331:
332: char *
333: rnames[] = { /* keyed to register number tokens */
334: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
335: "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
336: "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7"
337: };
338:
339: int rstatus[] = {
340: SAREG|STAREG, SAREG|STAREG,
341: SAREG|STAREG, SAREG|STAREG,
342: SAREG|STAREG, SAREG|STAREG,
343: SAREG|STAREG, SAREG|STAREG,
344:
345: SBREG|STBREG, SBREG|STBREG,
346: SBREG|STBREG, SBREG|STBREG,
347: SBREG|STBREG, SBREG|STBREG,
348: SBREG, SBREG,
349:
350: SCREG|STCREG, SCREG|STCREG,
351: SCREG|STCREG, SCREG|STCREG,
352: SCREG|STCREG, SCREG|STCREG,
353: SCREG|STCREG, SCREG|STCREG,
354: };
355:
356: tlen(p) NODE *p;
357: {
358: switch(p->in.type) {
359: case CHAR:
360: case UCHAR:
361: return(SZCHAR/SZCHAR);
362:
363: case SHORT:
364: case USHORT:
365: return(SZSHORT/SZCHAR);
366:
367: case DOUBLE:
368: return(SZDOUBLE/SZCHAR);
369:
370: default:
371: return(SZINT/SZCHAR);
372: }
373: }
374:
375:
376: rmove( rt, rs, t )
377: register int rt,rs;
378: {
379: int fsrce, fdest;
380:
381: fsrce = iscreg(rs);
382: fdest = iscreg(rt);
383: if (!fsrce && !fdest) {
384: /*
385: * neither source nor dest is on the coprocessor
386: */
387: if ( t==DOUBLE ){
388: printf(" movl %s,%s\n movl %s,%s\n",
389: rnames[rs], rnames[rt],
390: rnames[rs+1], rnames[rt+1]);
391: markused(rs+1);
392: markused(rt+1);
393: } else {
394: /* the most common case */
395: printf(" movl %s,%s\n",
396: rnames[rs], rnames[rt] );
397: }
398: } else if (fsrce && !fdest) {
399: /*
400: * source is on coprocessor, dest isn't
401: */
402: if (t == DOUBLE) {
403: /* royal pain; must use memory */
404: printf(" fmoved %s,sp@-\n", rnames[rs]);
405: printf(" movl sp@+,%s\n", rnames[rt]);
406: printf(" movl sp@+,%s\n", rnames[rt+1]);
407: markused(rt+1);
408: } else {
409: /* t == FLOAT */
410: printf(" fmoves %s,%s\n",
411: rnames[rs], rnames[rt]);
412: }
413: } else if (!fsrce && fdest) {
414: /*
415: * source isn't on coprocessor, dest is
416: */
417: if (t == DOUBLE) {
418: /* royal pain; must use memory */
419: printf(" movl %s,sp@-\n", rnames[rs+1]);
420: printf(" movl %s,sp@-\n", rnames[rs]);
421: printf(" fmoved sp@+,%s\n", rnames[rt]);
422: markused(rs+1);
423: } else {
424: /* t == FLOAT */
425: printf(" fmoves %s,%s\n",
426: rnames[rs], rnames[rt]);
427: }
428: } else {
429: /*
430: * both regs are on the coprocessor
431: */
432: printf(" fmovex %s,%s\n", rnames[rs], rnames[rt]);
433: }
434: markused(rs);
435: markused(rt);
436: }
437:
438: struct respref
439: respref[] = {
440: INCREG|INTCREG, INCREG|INTCREG,
441: INTAREG|INTBREG,INTAREG|INTBREG,
442: INAREG|INBREG, INAREG|INBREG,
443: INAREG|INBREG, SZERO,
444: INAREG|INBREG, SOREG|STARREG|STARNM|SNAME|SCON,
445: INTEMP, INTEMP,
446: FORARG, FORARG,
447: INTAREG, SOREG|SNAME|SAREG|SBREG,
448: 0, 0 };
449:
450: #ifdef FORT
451: /*
452: * save register variables.
453: * Use labels since we don't know
454: * which ones are being used until
455: * the end of the function.
456: */
457: saveregs()
458: {
459: printf(" link a6,#0\n");
460: printf(" addl #-LF%d,sp\n", ftnno);
461: printf(" moveml #LS%d,sp@\n",ftnno);
462: if (use68881) {
463: /*
464: * save floating registers used for variables
465: */
466: if (use68020) {
467: printf(" fmovem #LSS%d,a6@(-LFF%d:l)\n",
468: ftnno, ftnno);
469: } else {
470: /* 68881 without 68020; unlikely combination */
471: printf(" movl #-LFF%d,a0\n", ftnno);
472: printf(" fmovem #LSS%d,a6@(0,a0:l)\n", ftnno);
473: }
474: }
475: }
476: #endif FORT
477:
478:
479: /*
480: * Set up temporary registers.
481: * Use any left over from register
482: * variable allocation for scratch.
483: */
484:
485: setregs()
486: {
487: register i;
488: int nextdreg;
489: int nextareg;
490: int nextfreg;
491:
492: extern int skybase;
493:
494: nextdreg = NEXTD(maxtreg);
495: nextareg = NEXTA(maxtreg);
496: nextfreg = NEXTF(maxtreg);
497:
498: # ifdef FORT
499: /* reg reserved by iropt for __skybase */
500: skybase = SKYBASE(maxtreg);
501: if (nextdreg == D0)
502: nextdreg = MAX_DVAR;
503: if (nextareg == A0)
504: nextareg = MAX_AVAR;
505: if (nextfreg == FP0)
506: nextfreg = MAX_FVAR;
507: # endif FORT
508:
509: # ifdef FREETEMP
510: tmpoff = 0; /* we number temp regsters differently here */
511: # endif
512:
513: for( i=MIN_DVAR; i<=MAX_DVAR; i++ ){
514: rstatus[i] = i <= nextdreg ? SAREG|STAREG : SAREG;
515: # ifdef FORT
516: if (i > nextdreg)
517: markused(i);
518: # endif
519: }
520: for( i=MIN_AVAR; i<=MAX_AVAR; i++ ){
521: rstatus[i] = i <= nextareg ? SBREG|STBREG : SBREG;
522: # ifdef FORT
523: if (i > nextareg)
524: markused(i);
525: # endif
526: }
527: for( i=MIN_FVAR; i<=MAX_FVAR; i++ ){
528: rstatus[i] = i <= nextfreg ? SCREG|STCREG : SCREG;
529: # ifdef FORT
530: if (i > nextfreg)
531: markused(i);
532: # endif
533: }
534:
535: fregs.d = (nextdreg - D0) + 1;
536: fregs.a = (nextareg - A0) + 1;
537: fregs.f = (nextfreg - FP0) + 1;
538:
539: if( xdebug ){
540: /* -x changes number of free regs to 2, -xx to 3, etc. */
541: if( (xdebug+1) < fregs.f ) fregs.f = xdebug+1;
542: }
543: }
544:
545: shltype( o, p )
546: register o;
547: NODE *p;
548: {
549: return( o== REG || o == NAME || o == ICON || o == OREG || o == FCON
550: || ( o==UNARY MUL && shumul(p->in.left)) );
551: }
552:
553: flshape( p ) register NODE *p;
554: {
555: register o = p->in.op;
556: if( o==NAME || o==REG || o==ICON || o==OREG ) return( 1 );
557: return( o==UNARY MUL && shumul(p->in.left)==STARNM );
558: }
559:
560: shtemp( p ) register NODE *p;
561: {
562: if( p->in.op == UNARY MUL ) p = p->in.left;
563: if( p->in.op == REG )
564: return( !istreg( p->tn.rval ) );
565: if( p->in.op == OREG && !R2TEST(p->tn.rval) )
566: return( !istreg( p->tn.rval ) );
567: return( p->in.op == NAME || p->in.op == ICON );
568: }
569:
570: spsz( t, v ) TWORD t; CONSZ v;
571: {
572:
573: /* is v the size to increment something of type t */
574:
575: if( !ISPTR(t) ) return( 0 );
576: t = DECREF(t);
577:
578: if( ISPTR(t) ) return( v == (SZPOINT/SZCHAR) );
579:
580: switch( t ){
581:
582: case UCHAR:
583: case CHAR:
584: return( v == 1 );
585:
586: case SHORT:
587: case USHORT:
588: return( v == (SZSHORT/SZCHAR) );
589:
590: case INT:
591: case UNSIGNED:
592: case FLOAT:
593: return( v == (SZINT/SZCHAR) );
594:
595: case DOUBLE:
596: return( v == (SZDOUBLE/SZCHAR) );
597: }
598:
599: return( 0 );
600: }
601:
602: indexreg( p ) register NODE *p;
603: {
604: if( p->in.op == REG && p->tn.rval >= A0 && p->tn.rval <= SP ) return(1);
605: return(0);
606: }
607:
608: shumul( p ) register NODE *p;
609: {
610: register o;
611: extern int xdebug;
612:
613: if (xdebug) {
614: printf("\nshumul:op=%d, ", p->in.op);
615: switch (optype(p->in.op)){
616: case BITYPE:
617: printf( " rop=%d, rname=%s, rlval=%D",
618: p->in.right->in.op, p->in.right->in.name,
619: p->in.right->tn.lval);
620: /* fall through */
621: default:
622: printf( "lop=%d, plty=%d ",
623: p->in.left->in.op, p->in.left->in.type );
624: case LTYPE: ; /* do nothing */
625: }
626: putchar('\n');
627: }
628:
629:
630: o = p->in.op;
631: if( indexreg(p) )
632: return( STARNM );
633:
634: if( o == INCR && indexreg(p->in.left) && p->in.right->in.op == ICON &&
635: p->in.right->in.name[0] == '\0' &&
636: spsz( p->in.left->in.type, p->in.right->tn.lval ) )
637: return( STARREG );
638: if( o == ASG MINUS && indexreg(p->in.left) && p->in.right->in.op == ICON &&
639: p->in.right->in.name[0] == '\0' &&
640: spsz( p->in.left->in.type, p->in.right->tn.lval ) )
641: return( STARREG );
642:
643: return( 0 );
644: }
645:
646: adrcon( val ) CONSZ val;
647: {
648: printf( CONFMT, val );
649: }
650:
651: /* put out a floating e-format constant */
652:
653: floatimmed(p)
654: NODE *p;
655: {
656: putchar('#');
657: fcon( p, F_eformat );
658: }
659:
660: conput( p ) register NODE *p;
661: {
662: switch( p->in.op ){
663: case FCON:
664: fcon( p, F_hex );
665: return;
666:
667: case ICON:
668: acon( p );
669: return;
670:
671: default:
672: cerror( "illegal conput" );
673: }
674: }
675:
676: /*
677: * put out an explicit length qualifier. This simplifies
678: * handling of offsets in the 68020 assembler somewhat.
679: */
680: offsize(p)
681: register NODE *p;
682: {
683: if ( p->tn.name[0] != '\0' || p->tn.lval > 32767
684: || p->tn.lval < -32768 ) {
685: printf(":l");
686: }
687: }
688:
689: oregput(p)
690: register NODE *p;
691: {
692: register r;
693:
694: r = p->tn.rval;
695: if (R2TEST(r)) {
696: /*
697: * double indexing
698: */
699: if (use68020) {
700: /*
701: * For 68020, R2UPK3 encodes the following data:
702: * int shortx:1; short index
703: * int ibit:1; memory indirect mode (ignored)
704: * int scale:4; scale factor (1,2,4,8)
705: */
706: register flags;
707: int base, index, scale, shortx, indirect;
708:
709: base = R2UPK1(r);
710: index = R2UPK2(r);
711: markused(base);
712: markused(index);
713: flags = R2UPK3(r);
714: R2UPKFLGS(flags,shortx,indirect,scale);
715: /*
716: * print base register and displacement (if any)
717: */
718: printf(rnames[base]);
719: printf("@(");
720: acon(p); /* base displacement */
721: offsize(p); /* size of displacement */
722: putchar(',');
723: /*
724: * print index register and scale factor. For now,
725: * we assume all indices have been long-extended.
726: */
727: printf(rnames[index]);
728: putchar(':');
729: putchar(shortx? 'w' : 'l');
730: switch(scale) {
731: case 0:
732: case 1:
733: break;
734: case 2:
735: case 4:
736: case 8:
737: printf(":%d",scale);
738: break;
739: default:
740: cerror("illegal scale factor (%d)", scale);
741: /*NOTREACHED*/
742: }
743: putchar(')');
744: } /* use68020 */
745: else {
746: /*
747: * For the 68010, R2UPK3 encodes only whether
748: * a short index is used.
749: */
750: int base, index, flags, shortx, ignored;
751: base = R2UPK1(p->tn.rval);
752: index = R2UPK2(p->tn.rval);
753: flags = R2UPK3(p->tn.rval);
754: R2UPKFLGS(flags,shortx,ignored,ignored);
755: printf( "%s@(%d,%s:%c)",
756: rnames[base], /* breg */
757: p->tn.lval, /* disp */
758: rnames[index], /* xreg */
759: shortx ? 'w' : 'l' ); /* xlen */
760: markused(base);
761: markused(index);
762: }
763: }
764: else {
765: int base = R2UPK2(p->tn.rval);
766: markused(base);
767: printf( rnames[base] );
768: putchar('@');
769: if( p->tn.lval != 0 || p->in.name[0] != '\0' ) {
770: putchar('(');
771: acon( p );
772: if (use68020) offsize( p );
773: putchar(')');
774: } /* if */
775: } /* else */
776: } /* oregput */
777:
778: void
779: upput( p ) register NODE *p;
780: {
781: /* output the address of the second word in the
782: pair pointed to by p (for LONGs)*/
783: CONSZ save;
784: int r;
785:
786: if( p->in.op == FLD ){
787: p = p->in.left;
788: }
789:
790: save = p->tn.lval;
791: switch( p->in.op ){
792:
793: case NAME:
794: p->tn.lval += SZINT/SZCHAR;
795: acon( p );
796: break;
797:
798: case FCON:
799: fcon( p, F_loworder );
800: break;
801:
802: case ICON:
803: /* addressable value of the constant */
804: p->tn.lval &= BITMASK(SZINT);
805: putchar('#');
806: acon( p );
807: break;
808:
809: case REG:
810: r = p->tn.rval+1;
811: if (r >= FP0) {
812: cerror("illegal floating register pair");
813: }
814: print_str(rnames[r] );
815: markused(r);
816: break;
817:
818: case OREG:
819: p->tn.lval += SZINT/SZCHAR;
820: if( R2UPK2(p->tn.rval) == A6 ){ /* in the argument region */
821: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
822: }
823: #ifdef FREETEMP
824: else if( R2UPK2(p->tn.rval) == SP ){ /* in the temp region */
825: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
826: printf( "sp@(LT%d+0x%x)", ftnno, toff+p->tn.lval);
827: p->tn.lval = save;
828: return;
829: }
830: #endif FREETEMP
831: oregput(p);
832: break;
833:
834: case UNARY MUL:
835: if (p->in.left->in.op==INCR){
836: /* rewrite a-la adrput */
837: NODE *q, *l; int i;
838: l = p->in.left;
839: q = l->in.left;
840: p->in.op = OREG;
841: p->in.rall = q->in.rall;
842: p->tn.lval = q->tn.lval;
843: p->tn.rval = q->tn.rval;
844: #ifndef FLEXNAMES
845: for( i=0; i<NCHNAM; i++ )
846: p->in.name[i] = q->in.name[i];
847: #else
848: p->in.name = q->in.name;
849: #endif
850: adrput( p );
851: putchar('+');
852: p->tn.lval -= l->in.right->tn.lval;
853: tfree( l );
854: } else if ( tshape(p, STARNM) ) {
855: adrput( p->in.left );
856: print_str("@(4)");
857: } else {
858: /* p->in.left->in.op==ASG MINUS */
859: /* just put and let adrput rewrite -- VERY carefully */
860: adrput( p->in.left->in.left );
861: print_str( "@-");
862: }
863: break;
864:
865: default:
866: cerror( "illegal upper address" );
867: break;
868:
869: }
870: p->tn.lval = save;
871: }
872:
873: void
874: adrput( p ) register NODE *p;
875: {
876: /* the 68k code saves lval and restores after the switch */
877: register int r;
878: /* output an address, with offsets, from p */
879:
880: if( p->in.op == FLD ){
881: p = p->in.left;
882: }
883: switch( p->in.op ){
884:
885: case NAME:
886: acon( p );
887: return;
888:
889: case FCON:
890: /*
891: * put out floating constant in hex.
892: * Do not use in coprocessor instructions;
893: * use floatimmed(p) instead.
894: */
895: if (p->in.type == FLOAT) {
896: putchar('#');
897: fcon( p, F_hex );
898: } else {
899: fcon( p, F_highorder );
900: }
901: return;
902:
903: case ICON:
904: /* addressable value of the constant */
905: putchar('#');
906: acon( p );
907: return;
908:
909: case REG:
910: r = p->tn.rval;
911: print_str(rnames[r] );
912: markused(r);
913: return;
914:
915: case OREG:
916: if( R2UPK2(p->tn.rval) == A6 ){ /* in the argument region */
917: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
918: }
919: #ifdef FREETEMP
920: else if( R2UPK2(p->tn.rval) == SP ){ /* in the temp region */
921: if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
922: printf( "sp@(LT%d+%d)", ftnno, toff+p->tn.lval);
923: return;
924: }
925: #endif FREETEMP
926: oregput(p);
927: break;
928:
929: case UNARY MUL:
930: /* STARNM or STARREG found */
931: if( tshape(p, STARNM) ) {
932: adrput( p->in.left);
933: putchar('@');
934: }
935: else { /* STARREG - really auto inc or dec */
936: /* turn into OREG so replacement node will
937: reflect the value of the expression */
938: register i;
939: register NODE *q, *l;
940:
941: l = p->in.left;
942: q = l->in.left;
943: if (p->in.type==DOUBLE )
944: if (l->in.op==INCR){
945: /* just do it and let upput rewrite */
946: adrput( q );
947: print_str( "@+");
948: return;
949: }
950: /* else fall through and we rewrite -- VERY carefully */
951: p->in.op = OREG;
952: p->in.rall = q->in.rall;
953: p->tn.lval = q->tn.lval;
954: p->tn.rval = q->tn.rval;
955: #ifndef FLEXNAMES
956: for( i=0; i<NCHNAM; i++ )
957: p->in.name[i] = q->in.name[i];
958: #else
959: p->in.name = q->in.name;
960: #endif
961: if( l->in.op == INCR ) {
962: adrput( p );
963: putchar('+');
964: p->tn.lval -= l->in.right->tn.lval;
965: } else {
966: /* l->in.op == ASG MINUS */
967: adrput( p );
968: putchar('-');
969: }
970: tfree( l );
971: }
972: return;
973:
974: case SCONV:
975: adrput(p->in.left); /* kludge for SFLOAT_SRCE */
976: break;
977:
978: default:
979: cerror( "illegal address" );
980: return;
981:
982: }
983:
984: }
985:
986: acon( p ) register NODE *p;
987: { /* print out a constant */
988:
989: if( p->in.name[0] == '\0' ){
990: print_x(p->tn.lval);
991: }
992: else if( p->tn.lval == 0 ) {
993: #ifndef FLEXNAMES
994: printf( "%.8s", p->in.name );
995: #else
996: print_str(p->in.name );
997: #endif
998: }
999: else {
1000: #ifndef FLEXNAMES
1001: printf( "%.8s+", p->in.name );
1002: #else
1003: print_str(p->in.name ); putchar('+');
1004: #endif
1005: print_x(p->tn.lval );
1006: }
1007: }
1008:
1009: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1010:
1011: /*
1012: * fcon(p, form): output a floating point constant in one of several forms
1013: */
1014:
1015: static int fgetlab();
1016:
1017: static char floatfmt[] = "0r%.9e";
1018: static char doublefmt[] = "0r%.17e";
1019:
1020: static void
1021: fcon( p, form )
1022: register NODE *p;
1023: Floatform form;
1024: {
1025: float x;
1026: long *lp;
1027:
1028: switch(form) {
1029: case F_highorder:
1030: /*
1031: * put out a reference to the highorder word of a
1032: * double constant from the pool
1033: */
1034: printf("L%d", fgetlab(p));
1035: return;
1036: case F_loworder:
1037: /*
1038: * put out a reference to the loworder word of a
1039: * double constant from the pool
1040: */
1041: printf("L%d+4", fgetlab(p));
1042: return;
1043: case F_eformat:
1044: /*
1045: * put out a constant in e-floating point format;
1046: * for coprocessor instructions.
1047: */
1048: if (p->in.type == FLOAT) {
1049: printf(floatfmt, p->fpn.dval);
1050: } else {
1051: printf(doublefmt, p->fpn.dval);
1052: }
1053: return;
1054: case F_hex:
1055: /*
1056: * put out the constant as one or two hex words;
1057: * for initialization.
1058: */
1059: if (p->in.type == FLOAT) {
1060: float x = p->fpn.dval;
1061: lp = (long*)&x;
1062: printf("0x%x", lp[0]);
1063: } else {
1064: lp = (long*)&p->fpn.dval;
1065: printf("0x%x,0x%x", lp[0], lp[1]);
1066: }
1067: return;
1068: }
1069: }
1070:
1071: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1072:
1073: /*
1074: * floating point constant pool -- a data structure that
1075: * associates floating point constants with labels
1076: */
1077:
1078: struct floatcon {
1079: int conlab;
1080: TWORD contype;
1081: double conval;
1082: struct floatcon *left, *right;
1083: };
1084:
1085: static struct floatcon *fconpool; /* the search tree */
1086: static struct floatcon *newfloatcon(); /* floatcon storage allocator */
1087: static int fconlookup(); /* search routine */
1088:
1089: /*
1090: * search for, and create if necessary,
1091: * a label in the floating point constant pool
1092: */
1093:
1094: static int
1095: fgetlab(p)
1096: NODE *p;
1097: {
1098: return(fconlookup(&fconpool, p));
1099: }
1100:
1101: static int
1102: fconlookup(fpp, p)
1103: struct floatcon **fpp;
1104: NODE *p;
1105: {
1106: struct floatcon *fp = *fpp;
1107: if (fp == NULL) {
1108: *fpp = fp = newfloatcon();
1109: fp->conval = p->fpn.dval;
1110: fp->contype = p->fpn.type;
1111: fp->conlab = getlab();
1112: fp->left = NULL;
1113: fp->right = NULL;
1114: return(fp->conlab);
1115: } else if (fp->conval == p->fpn.dval) {
1116: return(fp->conlab);
1117: } else if (fp->conval < p->fpn.dval) {
1118: return(fconlookup(&fp->left, p));
1119: } else {
1120: return(fconlookup(&fp->right,p));
1121: }
1122: }
1123:
1124: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1125:
1126: /*
1127: * storage allocation for the floating point constant pool
1128: */
1129:
1130: #define FCONSEGSIZ 256
1131: struct fconseg {
1132: struct fconseg *nextseg;
1133: struct floatcon *nextcon;
1134: struct floatcon storage[FCONSEGSIZ];
1135: };
1136:
1137: static struct fconseg *curseg = NULL;
1138:
1139: /*
1140: * allocate storage for a
1141: * labeled floating point constant
1142: */
1143: static struct floatcon *
1144: newfloatcon()
1145: {
1146: struct fconseg *newseg;
1147:
1148: if (curseg == NULL
1149: || curseg->nextcon == curseg->storage+FCONSEGSIZ) {
1150: newseg = (struct fconseg*)malloc(sizeof(struct fconseg));
1151: newseg->nextseg = curseg;
1152: curseg = newseg;
1153: curseg->nextcon = curseg->storage;
1154: }
1155: return(curseg->nextcon++);
1156: }
1157:
1158: /*
1159: * emit the floating point constant
1160: * pool to the output stream
1161: */
1162: static void
1163: dumpfcons()
1164: {
1165: register struct floatcon *fp,*nextfree;
1166: struct fconseg *segp, *temp;
1167: long *lp;
1168:
1169: segp = curseg;
1170: while(segp != NULL) {
1171: nextfree = segp->nextcon;
1172: for (fp = segp->storage; fp < nextfree; fp++) {
1173: printf("L%d: .long ", fp->conlab);
1174: if (fp->contype == FLOAT) {
1175: float x = fp->conval;
1176: lp = (long*)&x;
1177: printf("0x%lx", lp[0]);
1178: } else {
1179: lp = (long*)&fp->conval;
1180: printf("0x%lx,0x%lx", lp[0], lp[1]);
1181: }
1182: putchar('\n');
1183: }
1184: temp = segp->nextseg;
1185: free(segp);
1186: segp = temp;
1187: }
1188: curseg = NULL;
1189: fconpool = NULL;
1190: }
1191:
1192: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1193:
1194: genscall( p, cookie ) register NODE *p;
1195: {
1196: /* structure valued call */
1197: return( gencall( p, cookie ) );
1198: }
1199:
1200: gencall( p, cookie ) register NODE *p;
1201: {
1202: /* generate the call given by p */
1203: register args;
1204: register m;
1205:
1206: if( p->in.right ) args = argsize( p->in.right );
1207: else args = 0;
1208:
1209: if( p->in.right ){ /* generate args */
1210: int residue = args % (SZLONG/SZCHAR);
1211: if (residue) {
1212: /*
1213: * pad the argument list out to an
1214: * even number of longwords. This is
1215: * the wrong way to do it, but doing
1216: * it right isn't backwards compatible.
1217: */
1218: printf(" subqw #0x%x,sp\n", residue);
1219: }
1220: genargs( p->in.right );
1221: }
1222:
1223: if( !shltype( p->in.left->in.op, p->in.left ) ) {
1224: order( p->in.left, INBREG|SOREG );
1225: }
1226:
1227: p->in.op = UNARY CALL;
1228: m = match( p, INTAREG|INTBREG );
1229: popargs( args );
1230: return(m != MDONE);
1231: }
1232:
1233: popargs( size ) register size;
1234: {
1235: /* pop arguments from stack */
1236:
1237: if (size==0) return;
1238: /*
1239: * round size up to a multiple of sizeof(long),
1240: * to compensate for the hack in gencall() above.
1241: */
1242: SETOFF(size, (SZLONG/SZCHAR));
1243: toff -= size;
1244: /* huh? if( toff == 0 && size >= 2 ) size -= 2; */
1245: if (size <=8 )
1246: printf( " addqw #0x%x,sp\n", size);
1247: else if (size <(1<<15))
1248: printf( " lea sp@(0x%x),sp\n", size);
1249: else
1250: printf( " addl #0x%x,sp\n", size);
1251: }
1252:
1253:
1254: nextcook( p, cookie )
1255: NODE *p;
1256: register cookie;
1257: {
1258: /* we have failed to match p with cookie; try another */
1259: if ( cookie == FORREW ) return( 0 ); /* hopeless! */
1260: if ( cookie & (INCREG|INTCREG) ) return (INTAREG);
1261: if ( !(cookie&(INTAREG|INTBREG|INTCREG)) )
1262: return( INTAREG|INTBREG|INTCREG );
1263: if ( !(cookie&INTEMP) && asgop(p->in.op) )
1264: return( INTEMP|INAREG|INTAREG|INTBREG|INBREG);
1265: if ( !(cookie&(INTAREG|INAREG)) && p->in.op == CHK )
1266: return(INTAREG|INAREG);
1267: return ( FORREW );
1268: }
1269:
1270: lastchance( p, cook ) NODE *p;
1271: {
1272: /* forget it! */
1273: return(0);
1274: }
1275:
1276:
1277: NODE * addroreg(l)
1278: /*
1279: * OREG was built in clocal()
1280: * for an auto or formal parameter
1281: * now its address is being taken
1282: * local code must unwind it
1283: * back to PLUS/MINUS REG ICON
1284: * according to local conventions
1285: */
1286: {
1287: cerror("address of OREG taken");
1288: }
1289:
1290:
1291:
1292: # ifndef ONEPASS
1293: main( argc, argv ) char *argv[];
1294: {
1295: int v;
1296: if ( strcmp(argv[0],pcname) == 0 )
1297: pascal = 1;
1298: v = mainp2( argc, argv );
1299: floatnote();
1300: exit( v );
1301: }
1302: # endif
1303:
1304: /* return 1 if node is a SCONV from short to int */
1305: isconv( p, t1, t2 )
1306: register NODE *p;
1307: TWORD t1, t2;
1308: {
1309: register v;
1310: if ( p->in.op==SCONV && (p->in.type==INT || p->in.type==UNSIGNED) &&
1311: ((v=p->in.left->in.type)==t1 || v == t2))
1312: return( 1 );
1313: return( 0 );
1314: }
1315:
1316:
1317:
1318: myreader(p) register NODE *p;
1319: {
1320: #ifdef FORT
1321: void unoptim2();
1322: if (!pascal) {
1323: unoptim2(p);
1324: }
1325: #endif FORT
1326: optim2(p);
1327: canon( p ); /* expands r-vals for fields */
1328: toff = 0; /* stack offset swindle */
1329: #ifdef FREETEMP
1330: tmpoff = 0; /* we number temp regsters differently here */
1331: #endif
1332: }
1333:
1334:
1335: special( p, shape ) register NODE *p;
1336: {
1337: /* special shape matching routine */
1338:
1339: switch (shape){
1340: case SPEC_FLD:
1341: /* do-it-yourself multi-level matching */
1342: if (tshape(p,SFLD))
1343: switch( p->in.left->tn.op){
1344: case OREG:
1345: /* if (R2TEST(p->in.left->tn.rval)) return 0; */
1346: case REG:
1347: case ICON:
1348: case NAME:
1349: return(1);
1350: }
1351: return 0;
1352:
1353: case SPEC_FLT:
1354: /* depends on phase of moon */
1355: if (usesky)
1356: return tshape(p,SCON|SAREG|STAREG|SBREG|SOREG|SNAME|STARREG);
1357: else
1358: return tshape(p,SAREG|STAREG) && (p->tn.rval==D0 || p->tn.rval==D1);
1359: case SPEC_DFLT:
1360: /* likewise */
1361: if (usesky)
1362: return tshape(p,SCON|SAREG|STAREG|SBREG|SOREG|SNAME|STARREG);
1363: else
1364: return tshape(p,SCON| SOREG|SNAME|STARREG);
1365:
1366: case SFLOAT_SRCE:
1367: /* source operand of 68881 floating point instruction */
1368: if (p->in.op == SCONV) {
1369: /*
1370: * the 68881 converts signed integral types into
1371: * (extended) floating point format
1372: */
1373: p = p->in.left;
1374: switch(p->in.type) {
1375: case CHAR:
1376: case SHORT:
1377: case INT:
1378: case LONG:
1379: case FLOAT:
1380: /* d-registers, constants, and memory are all ok */
1381: return tshape(p,
1382: SCON|SCREG|STCREG|SAREG|STAREG|SOREG|SNAME|STARNM|STARREG);
1383: case DOUBLE:
1384: /* can't deal with register pairs */
1385: return tshape(p,
1386: SCON|SCREG|STCREG|SOREG|SNAME|STARNM|STARREG);
1387: default:
1388: return(0);
1389: }
1390: }
1391: if (p->in.type == FLOAT) {
1392: /* d-regs, f-registers, or memory */
1393: return tshape(p,
1394: SCON|SCREG|STCREG|SAREG|STAREG|SOREG|SNAME|STARNM|STARREG);
1395: }
1396: /* type == DOUBLE: f-registers or memory only */
1397: return tshape(p, SCON|SCREG|STCREG|SOREG|SNAME|STARNM|STARREG);
1398:
1399: case SPEC_PVT:
1400: /* right subtree of x + y*z ; an idiom from matrix computations */
1401: if (!usesky) return 0;
1402: if (p->in.op != MUL) return 0;
1403: if (tshape(p->in.left,SCON|SAREG|STAREG|SBREG|SOREG|SNAME|STARREG)){
1404: return tshape(p->in.right,
1405: SCON|SAREG|STAREG|SBREG|SOREG|SNAME|STARREG);
1406: }
1407: return 0;
1408:
1409: case SSOREG:
1410: /* someday soon, this will be useful */
1411: return ( p->in.op == OREG && !R2TEST(p->tn.rval) );
1412:
1413: case SBASE:
1414: /* half of a double-oreg */
1415: return ( p->in.op == PLUS
1416: && p->in.left->in.op == REG && isbreg(p->in.left->tn.rval)
1417: && (p=p->in.right)->in.op == ICON && p->tn.name[0] == '\0'
1418: && p->tn.lval >= -127 && p->tn.lval <= 127 );
1419:
1420: case SXREG:
1421: /* the other half */
1422: if ( p->in.op==SCONV
1423: && (p->in.type == INT || p->in.type == UNSIGNED)
1424: && p->in.left->in.type == SHORT )
1425: p = p->in.left;
1426: return ( p->in.op == REG );
1427:
1428: case SNONPOW2:
1429: /*
1430: * constant, NOT a power of 2. This is a kludge to enable
1431: * us to match a template for ASG MOD on the 68020. The
1432: * semantics of the DIVSLL instruction make it impossible
1433: * to return a remainder in the lhs of <reg> %= <ea>, unless
1434: * an extra instruction is generated. Returning the result
1435: * in RESC1 makes the extra instruction unnecessary.
1436: */
1437: return( p->in.op == ICON && (p->tn.lval & p->tn.lval-1) );
1438:
1439: case SAUTOINC:
1440: return( p->in.op == UNARY MUL
1441: && p->in.left->in.op == INCR
1442: && shumul(p->in.left) == STARREG );
1443:
1444: /*
1445: * CHK bounds pair with constant lower bound of 0
1446: */
1447: case SZEROLB:
1448: return( p->in.op == CM
1449: && p->in.left->in.op == ICON
1450: && p->in.left->tn.name == NULL
1451: && p->in.left->tn.lval == 0 );
1452:
1453: case SFZERO:
1454: return( p->in.op == FCON && p->fpn.dval == 0.0 );
1455:
1456: }
1457:
1458: if(p->tn.op != ICON || p->in.name[0] != '\0') return (0);
1459: switch( shape ) {
1460: case SCCON:
1461: return( p->tn.lval>= -128 && p->tn.lval <=127 );
1462: case SICON:
1463: return( p->tn.lval>= 0 && p->tn.lval <=32767 );
1464: case SSCON:
1465: return( p->tn.lval>= -32768 && p->tn.lval <=32767 );
1466: case S8CON:
1467: return( p->tn.lval>= 1 && p->tn.lval <=8 );
1468: default:
1469: cerror( "bad special shape" );
1470: }
1471:
1472: return( 0 );
1473: }
1474:
1475: # ifdef MULTILEVEL
1476: # include "mldec.h"
1477:
1478: struct ml_node mltree[] ={
1479:
1480: DEFINCDEC, INCR, 0,
1481: INCR, SANY, TANY,
1482: OPANY, SAREG|STAREG, TANY,
1483: OPANY, SCON, TANY,
1484:
1485: DEFINCDEC, ASG MINUS, 0,
1486: ASG MINUS, SANY, TANY,
1487: REG, SANY, TANY,
1488: ICON, SANY, TANY,
1489:
1490: TSOREG, 1, 0,
1491: UNARY MUL, SANY, TANY,
1492: REG, SANY, TANY,
1493:
1494: TSOREG, 2, 0,
1495: UNARY MUL, SANY, TANY,
1496: PLUS, SANY, TANY,
1497: REG, SANY, TANY,
1498: ICON, SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT,
1499:
1500: TSOREG, 2, 0,
1501: UNARY MUL, SANY, TANY,
1502: MINUS, SANY, TANY,
1503: REG, SANY, TANY,
1504: ICON, SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT,
1505: 0,0,0};
1506: # endif
1507:
1508: #ifdef FREETEMP
1509: extern unsigned offsz;
1510:
1511: freetemp( k )
1512: {
1513: /* allocate k integers worth of temp space */
1514: /* we also make the convention that, if the number of words is more than 1,
1515: /* it must be aligned for storing doubles... */
1516: /* allocate temps forwards from sp+(saved registers) */
1517:
1518: int t;
1519:
1520: if( k>1 ){
1521: SETOFF( tmpoff, ALDOUBLE );
1522: }
1523: t = tmpoff;
1524: tmpoff += k*SZINT;
1525: if( tmpoff >= offsz )
1526: cerror( "stack overflow" );
1527: if( tmpoff > maxtemp ) maxtemp = tmpoff ;
1528: return(t);
1529:
1530: }
1531: #endif FREETEMP
1532:
1533: #ifdef FORT
1534: void
1535: unoptim2( p ) register NODE *p;
1536: {
1537: /* FORTRAN thinks we can do double operations on float operands */
1538: NODE * double_conv();
1539: switch( optype(p->in.op)){
1540: case BITYPE:
1541: unoptim2(p->in.left);
1542: unoptim2(p->in.right);
1543: if (p->in.type == DOUBLE){
1544: switch (p->in.op) {
1545: case QUEST:
1546: case CM:
1547: case COMOP:
1548: case CALL:
1549: return;
1550: }
1551: if (p->in.right->in.type != DOUBLE)
1552: p->in.right = double_conv(p->in.right);
1553: if (p->in.left->in.type != DOUBLE)
1554: p->in.left = double_conv(p->in.left);
1555: return;
1556: }
1557: if ( logop(p->in.op) ){
1558: if (p->in.left->in.type==DOUBLE && p->in.right->in.type != DOUBLE)
1559: p->in.right = double_conv(p->in.right);
1560: if (p->in.right->in.type==DOUBLE && p->in.left->in.type != DOUBLE)
1561: p->in.left = double_conv(p->in.left);
1562: }
1563: return;
1564: case UTYPE:
1565: unoptim2(p->in.left);
1566: if (p->in.type == DOUBLE ){
1567: switch( p->in.op ){
1568: case UNARY MUL:
1569: case UNARY CALL:
1570: case SCONV:
1571: return;
1572: }
1573: if (p->in.left->in.type != DOUBLE)
1574: p->in.left = double_conv(p->in.left);
1575: }
1576: return;
1577: case LTYPE: return;
1578: }
1579: }
1580: #endif FORT
1581:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.