|
|
1.1 root 1: # include "cpass2.h"
2: #ifndef lint
3: static char sccsid[] = "@(#)order.c 1.1 86/02/03 Copyr 1985 Sun Micro";
4: #endif
5:
6: /*
7: * Copyright (c) 1985 by Sun Microsystems, Inc.
8: */
9:
10: /*
11: * order.c -- conditionally included 680X0 version
12: */
13:
14:
15: int fltused = 0;
16: int floatmath = 0;
17:
18: SUTYPE fregs;
19:
20: extern int mina, maxa, minb, maxb; /* imported from allo.c */
21: extern int toff, maxtoff;
22:
23: int maxargs = { -1 };
24:
25: static SUTYPE zed = { 0,0,0,0 };
26:
27: int failsafe; /* very disgusting: see offstar() for use */
28:
29: # define SAFETY( a, reg, b ) \
30: {if ((reg & MUSTDO) && find_mustdo( a , reg )) {rewrite_rall( b, 1 );} }
31: # define iscnode(p) ((p)->in.op==REG && iscreg((p)->tn.rval))
32:
33: # define max(x,y) ((x)<(y)?(y):(x))
34: # define min(x,y) ((x)<(y)?(x):(y))
35:
36: # define divmulop(o) (dope[o]&(DIVFLG|MULFLG))
37:
38:
39: NODE *
40: double_conv( p ) register NODE *p;
41: {
42: NODE *q = talloc();
43: q->in.op = SCONV;
44: q->in.type = DOUBLE;
45: q->in.left = p;
46: q->in.rall = p->in.rall;
47: if (use68881) {
48: q->in.su.d = max( p->in.su.d, 1 );
49: q->in.su.a = 0;
50: q->in.su.f = max( p->in.su.f, 1 );
51: } else {
52: p->in.rall = MUSTDO|D0;
53: q->in.su.d = max( p->in.su.d, fregs.d );
54: q->in.su.a = max( p->in.su.a, fregs.a );
55: q->in.su.f = max( p->in.su.f, fregs.f );
56: }
57: return q;
58: }
59:
60: setincr( p ) register NODE *p;
61: {
62: return( 0 );
63: }
64:
65: niceuty( p ) register NODE *p;
66: {
67: return( p->in.op == UNARY MUL && p->in.type != FLOAT &&
68: shumul( p->in.left) == STARNM );
69: }
70:
71: setconv( p, cookie )
72: NODE *p;
73: {
74: register NODE *lp;
75: TWORD t;
76:
77: lp = p->in.left;
78: switch(p->in.type) {
79: case FLOAT:
80: case DOUBLE:
81: /* convert from something nice to something icky */
82: if ( use68881 ) {
83: if (p->in.type == DOUBLE && iscnode(lp)) {
84: /*
85: * no code necessary -- floating point
86: * regs are always in extended format
87: */
88: TWORD t = p->in.type;
89: *p = *lp;
90: p->in.type = t;
91: lp->in.op = FREE;
92: return(1);
93: }
94: if (ISFLOATING(lp->in.type)) {
95: /*
96: * float => double, or vice versa
97: */
98: order(lp, INCREG|INTCREG|INTEMP);
99: return(1);
100: }
101: if (ISUNSIGNED(lp->in.type)) {
102: /*
103: * the 68881 doesn't deal with unsigned types;
104: * convert the unsigned operand to INT.
105: */
106: register NODE *q;
107: q = talloc();
108: q->in.op = SCONV;
109: q->in.type = INT;
110: q->in.left = lp;
111: q->in.rall = lp->in.rall;
112: q->in.su.d = 1;
113: q->in.su.a = 0;
114: q->in.su.f = 0;
115: p->in.left = lp = q;
116: }
117: break;
118: }
119: failsafe = 1;
120: break;
121: default:
122: /* check for inverse (floating type => fixed type) */
123: if (lp->in.type == FLOAT || lp->in.type == DOUBLE) {
124: if (use68881) {
125: order(lp, INCREG|INTCREG|INTEMP);
126: return(1);
127: }
128: failsafe = 1;
129: }
130: break;
131: }
132: if (cookie!=(INBREG|INTBREG))
133: cookie = (INAREG|INTAREG|INBREG|INTBREG);
134: cookie |= INTEMP;
135: order( p->in.left, cookie );
136: return 1;
137: }
138:
139: /*
140: * deal properly with the operand of a unary operator.
141: */
142: int
143: setunary(p, cookie)
144: NODE *p;
145: {
146: NODE *lp;
147:
148: lp = p->in.left;
149: if (use68881 && ISFLOATING(lp->in.type)) {
150: switch(p->in.op) {
151: case FCOS:
152: case FSIN:
153: case FTAN:
154: case FACOS:
155: case FASIN:
156: case FATAN:
157: case FCOSH:
158: case FSINH:
159: case FTANH:
160: case FEXP:
161: case F10TOX:
162: case F2TOX:
163: case FLOGN:
164: case FLOG10:
165: case FLOG2:
166: case FSQR:
167: case FSQRT:
168: case FAINT:
169: case FANINT:
170: floatsrce(lp);
171: return(1);
172: case FNINT:
173: order(lp, INCREG|INTCREG);
174: return(1);
175: case UNARY MINUS:
176: case FABS:
177: /* don't use the 81 unless we have to */
178: order(lp, INAREG|INCREG);
179: return(1);
180: default:
181: break;
182: }
183: }
184: order(lp, INAREG|INBREG|INCREG);
185: return(1);
186: }
187:
188: /*
189: * put p into a form acceptable as a 68881 source operand.
190: */
191: static
192: floatsrce(p)
193: register NODE *p;
194: {
195: if (p->in.op == SCONV) {
196: /*
197: * the 68881 converts signed ints, float, and double
198: * to internal (extended) format automatically.
199: */
200: switch(p->in.left->in.type) {
201: case CHAR:
202: case SHORT:
203: case INT:
204: case LONG:
205: case FLOAT:
206: case DOUBLE:
207: p = p->in.left;
208: break;
209: default:
210: /* must do the conversion explicitly */
211: order(p->in.left, INAREG|INTAREG|INTEMP);
212: break;
213: }
214: }
215: switch(p->in.op) {
216: case UNARY MUL:
217: /* just make it addressable */
218: offstar(p->in.left);
219: break;
220: case REG:
221: /* coprocessor cannot access address registers */
222: if (isbreg(p->tn.rval)) {
223: order(p, INTAREG|INAREG);
224: }
225: break;
226: default:
227: /* lacking any better ideas, put it in a register */
228: if (SUTEST(p->in.su)) {
229: if (ISFLOATING(p->in.type)) {
230: order(p, INCREG|INTCREG|INTEMP);
231: } else {
232: order(p, INAREG|INTAREG|INTEMP);
233: }
234: }
235: break;
236: }
237: }
238:
239: setbin( p, cook ) register NODE *p;
240: {
241: register NODE *r, *l;
242: NODE *p2, *q, *t;
243: SUTYPE sur, sul;
244: SUTYPE qcost, pcost;
245: extern short revrel[]; /* for logic ops */
246: int cookie, i;
247:
248: r = p->in.right;
249: l = p->in.left;
250: sur = r->in.su;
251: sul = l->in.su;
252:
253: cookie = cook;
254: if (cookie!=(INBREG|INTBREG))
255: cookie = (INAREG|INTAREG|INBREG|INTBREG);
256: cookie |= INTEMP;
257: /* if this is one of the constrained operators, rewrite as op= */
258: switch( p->in.op ){
259: case GT:
260: case GE:
261: case LT:
262: case LE:
263: case EQ:
264: case NE:
265: if (l->in.type != FLOAT && l->in.type != DOUBLE)
266: break;
267: if (use68881) {
268: /*
269: * figure out what, if anything, is
270: * already in a coprocessor reg
271: */
272: int lhs,rhs;
273: lhs = iscnode(l);
274: rhs = iscnode(r);
275: /*
276: * logical ops require one operand to
277: * be in a coprocessor register. table.c
278: * expects the register on the left.
279: */
280: if ( !lhs ) {
281: /* lhs is not in a coprocessor reg */
282: if ( !rhs ) {
283: /* rhs isn't either; do harder one */
284: if (SUGT(sur, sul)
285: && !tshape(r, SFLOAT_SRCE)) {
286: order(r, INCREG|INTCREG);
287: rhs = 1;
288: } else {
289: order(l, INCREG|INTCREG);
290: lhs = 1;
291: }
292: }
293: if (rhs) {
294: /* rhs is, lhs isn't */
295: int temp;
296: p->in.op = revrel[p->in.op - EQ];
297: p->in.left = r;
298: p->in.right = l;
299: r = l;
300: l = p->in.left;
301: temp = rhs;
302: rhs = lhs;
303: lhs = temp;
304: }
305: }
306: /*
307: * lhs is in a coprocessor reg
308: */
309: if ( !rhs ) {
310: /*
311: * rhs isn't, and doesn't need to be
312: */
313: floatsrce(r);
314: } /* !rhs */
315: return(1);
316: } /* use68881 */
317:
318: /*
319: * evaluate most expensive side first. If
320: * cheaper size has non-zero cost, may have
321: * to put first intermediate result in a temp.
322: * Actually, this should not be a problem, if
323: * the su-stuff worked.
324: */
325: /* set variable "i" if we do anything here */
326: i = 0;
327: if( SUGT( sul, sur ) && !(istnode(l)&&l->tn.rval==D0) ){
328: /* do lhs first if it is the more expensive */
329: l->in.rall = MUSTDO|D0;
330: SAFETY( r , MUSTDO|D0, l);
331: order( l, INTAREG);
332: i++;
333: }
334: if ( r->in.type == DOUBLE ){
335: /* must be addressable */
336: if ( !tshape( r, SNAME|SOREG|STARNM)){
337: r->in.rall = NOPREF;
338: order( r, INTEMP );
339: i++;
340: }
341: } else {
342: if( !(istnode(r) && r->tn.rval == D1) ){
343: r->in.rall = MUSTDO|D1;
344: SAFETY( l , MUSTDO|D1, r);
345: order( r, INTAREG);
346: i++;
347: }
348: }
349: if( !(istnode(l) && l->tn.rval == D0) ){
350: /* do lhs after if it is the less expensive */
351: l->in.rall = MUSTDO|D0;
352: order( l, INTAREG);
353: i++;
354: }
355: if (i)
356: return 1;
357: break ; /* didn't accomplish anything -- fall into general case */
358: case PLUS:
359: case MINUS:
360: if( p->in.type == FLOAT || p->in.type == DOUBLE ){
361: float_ops:
362: /*
363: * evaluate most expensive side first. If
364: * cheaper size has non-zero cost, may have
365: * to put first intermediate result in a temp.
366: * Actually, this should not be a problem, if
367: * the su-stuff worked.
368: */
369: if (r->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){
370: r = p->in.right = double_conv(r);
371: }
372: if (l->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){
373: l = p->in.left = double_conv(l);
374: }
375: /*----------------------------*/
376: if (use68881) {
377: /*
378: * figure out what, if anything, is
379: * already in a coprocessor reg. The
380: * lhs must be a temporary.
381: */
382: int lhs,rhs;
383: lhs = (istnode(l) && iscreg(l->tn.rval));
384: rhs = (iscnode(r));
385: /*
386: * dyadic ops require one operand to
387: * be in a coprocessor register. table.c
388: * expects the register on the left.
389: */
390: if ( !lhs ) {
391: /* lhs is not in a temp coprocessor reg */
392: if ( !rhs ) {
393: /* rhs isn't either; do harder one */
394: if (SUGT(sur, sul)
395: && !tshape(r, SFLOAT_SRCE)) {
396: floatsrce(r);
397: rhs = iscnode(r);
398: } else {
399: order(l, INTCREG);
400: lhs = 1;
401: }
402: }
403: if ( rhs && !lhs && istnode(r)
404: && (p->in.op == PLUS || p->in.op == MUL) ) {
405: /*
406: * rhs is in a writable coprocessor
407: * reg, lhs isn't, and op is commutable
408: */
409: int temp;
410: p->in.left = r;
411: p->in.right = l;
412: r = l;
413: l = p->in.left;
414: temp = rhs;
415: rhs = lhs;
416: lhs = temp;
417: }
418: if (!lhs) {
419: order(l, INTCREG);
420: lhs = 1;
421: }
422: }
423: /*
424: * lhs is in a writable coprocessor reg
425: */
426: if ( !rhs ) {
427: /*
428: * rhs isn't, and doesn't need to be
429: */
430: floatsrce(r);
431: }
432: p->in.op = ASG p->in.op;
433: return(1);
434: } /* use68881 */
435:
436: if (usesky) {
437: if ( p->in.op == PLUS ) {
438: /*
439: * look for expressions of
440: * the form (x + y*z), which the
441: * sky board does in a single
442: * operation.
443: */
444: if ( l->in.op == MUL && r->in.op != MUL ) {
445: l = r;
446: r = p->in.left;
447: p->in.left = l;
448: p->in.right = r;
449: }
450: if (r->in.op == MUL) {
451: /*
452: * Don't even go near it
453: * unless x,y, or z comes for free.
454: */
455: if (!SUTEST(l->in.su)) {
456: l = r->in.left;
457: r = r->in.right;
458: } else if (!SUTEST(r->in.left->in.su)) {
459: r = r->in.right;
460: } else if (!SUTEST(r->in.right->in.su)) {
461: r = r->in.left;
462: }
463: }
464: }
465: for( i=0; i<2; i++ ){
466: if (SUGT( l->in.su, r->in.su )){
467: p2 = l; q = r;
468: }else if (SUTEST( r->in.su )){
469: p2 = r; q = l;
470: }else break;
471: if (p2->in.op==UNARY MUL
472: && rewrite_b_rall(p2->in.left, 1)){
473: /* try to offstar, but not into a1 */
474: failsafe = find_mustdo( q, MUSTDO|D0 );
475: offstar(p2->in.left);
476: } else {
477: if ( !find_mustdo( q, MUSTDO|D0) ||
478: rewrite_rall(p2, i) )
479: order( p2, INTAREG| INTBREG| INTEMP );
480: else
481: order( p2, INTEMP );
482: }
483: /* set su to zero here */
484: p2->in.su = zed;
485: } /* for */
486: } else {
487: /*
488: * do it in software
489: */
490: if (p->in.type == FLOAT){
491: /* assume rall's set up already */
492: for( i=0; i<2; i++ ){
493: if (SUGT( l->in.su, r->in.su )){
494: p2 = l; q = r;
495: }else if (SUTEST( r->in.su )){
496: p2 = r; q = l;
497: }else break;
498: SAFETY( q, D0|MUSTDO, p2 );
499: failsafe = 1;
500: order( p2, INTAREG|INTBREG );
501: p2->in.su = zed;
502: }
503: /* are no-cost, but may be wrong */
504: if (!istnode(l) || l->tn.rval != D0)
505: order( l, INTAREG );
506: } else {
507: /* this case is the least symmetric */
508: /* basically, must rewrite lhs as d0/d1 */
509: /* but if rhs is hard, do it first */
510: if (!istnode(l) || l->tn.rval != D0){
511: if (SUTEST( sur )){
512: if (r->in.op == UNARY MUL
513: && ( !SUTEST(sul) || rewrite_b_rall( r->in.left, 0)) ){
514: failsafe = 1;
515: offstar( r->in.left );
516: } else {
517: order( r, INTEMP );
518: }
519: }
520: failsafe = 1;
521: order( l, INTAREG );
522: }
523: }
524: p->in.op = ASG p->in.op ; /* gag */
525: }
526: /*----------------------------*/
527: #ifdef FLOATMATH
528: if (!FLOATMATH)
529: #endif
530: p->in.type = DOUBLE;
531: return 1; /* order(): try again */
532: } else if (ISPTR(p->in.type)){
533: /*
534: * cute hack: we can add a short into an address register
535: * without extending it first.
536: */
537: if ( isconv( l, SHORT, -1) && p->in.op==PLUS ){
538: /* un-canonical form -- flip it */
539: p->in.left = r;
540: p->in.right = r =l;
541: l = p->in.left;
542: }
543: if ( isconv( r, SHORT, -1 ) ){
544: /*
545: * if this is being evaluated into an address
546: * register or for argument, delete the conversion
547: */
548: if ( (cook==FORARG || (cook&(INBREG|INTBREG)
549: && !(cook&~(INBREG|INTBREG))))
550: && l->tn.op==REG
551: && tshape( r->in.left, SAREG|STAREG|SBREG|STBREG|SNAME|SOREG|STARREG) ){
552: if (cook==FORARG && r->in.left->tn.op != REG){
553: order( r->in.left, INAREG|INTAREG|INBREG|INTBREG );
554: }
555: /* lhs should be in an address register,
556: and should be writeable if SCONV operand
557: is not a register */
558: if (!isbreg(l->tn.rval)
559: || !istreg(l->tn.rval) && r->in.left->in.op != REG) {
560: order( l, INBREG|INTBREG );
561: }
562: p->in.right = r->in.left;
563: r->in.op = FREE;
564: return 1;
565: } else if (p->in.op == PLUS) {
566: /* otherwise, we were better off the other way */
567: /* flip back */
568: p->in.left = r;
569: p->in.right = r =l;
570: l = p->in.left;
571: }
572: }
573: }
574: break;
575: case MUL:
576: case DIV:
577: case MOD:
578: if( p->in.type == FLOAT || p->in.type == DOUBLE ){
579: goto float_ops;
580: }
581: if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type))
582:
583: break;
584: if(use68020)
585: break;
586: d0_d1:
587: /* copied from Setasop */
588: sul = l->in.su;
589: sur = r->in.su;
590: /* use q to designate the more expensive side, p2 the cheaper */
591: if (!SUGT(sur, sul)){
592: q = l; p2 = r; pcost = sur;
593: } else {
594: q = r; p2 = l; pcost = sul;
595: }
596: if( SUTEST(sul) && SUTEST(sur) ){
597: SAFETY( p2, q->in.rall, q );
598: }
599:
600: /* do code emission, most expensive side first */
601: if (!istnode( q ) ){
602: order( q, INAREG|INTAREG);
603: }
604: if ( SUTEST( pcost ) && !istnode( p2 )){
605: order( p2 ,INAREG|INTAREG);
606: }
607: if ( !istnode( l ) || l->tn.rval != D0 ){
608: l->tn.rall = MUSTDO | D0;
609: order( l, INTAREG);
610: }
611: if (logop(p->in.op)){
612: if ( !istnode( r )||r->tn.rval != D1 ){
613: r->tn.rall = MUSTDO | D1;
614: order( r, INTAREG);
615: }
616: } else {
617: if ( SUTEST( sur ) && (!istnode( r )||r->tn.rval != D1)){
618: r->tn.rall = MUSTDO | D1;
619: order( r, INTAREG);
620: }
621: p->in.op = ASG p->in.op;
622: }
623: return 1; /* go try 'gain */
624: case CHK:
625: /*
626: * the rhs of a CHK operator is an ordered pair
627: * of integers. We load the lhs first, regardless
628: * of what the bounds cost, since both the bounds
629: * and the lhs must be in hand simultaneously.
630: */
631: if (!istnode(l) || !isareg(l->tn.lval)) {
632: SAFETY(r, MUSTDO|D0, l);
633: order(l, INTAREG|INAREG);
634: return(1);
635: }
636: return(0);
637: } /* switch */
638:
639: if( !SUTEST( r->in.su ) ){
640: /* rhs is addressable */
641: if( logop( p->in.op ) ){
642: if ( l->in.op==UNARY MUL
643: && l->in.type!=FLOAT && shumul(l->in.left)!=STARREG ) {
644: offstar( l->in.left );
645: } else if ( !(l->in.op==REG && isareg(l->tn.rval))) {
646: /* lhs is not in a data register */
647: switch (l->in.type) {
648: case FLOAT:
649: case DOUBLE:
650: /* lhs must be in d0/d1 */
651: if (r->in.op == REG && r->tn.rval == D0) {
652: goto reverse;
653: }
654: break;
655: case CHAR:
656: case UCHAR:
657: /* bytes cannot be in address registers */
658: if (l->in.op == REG && isbreg(l->tn.rval)) {
659: break;
660: }
661: /* fall through */
662: default:
663: reverse:
664: if ( r->in.op == REG && isareg(r->tn.rval)
665: && !SUTEST(l->in.su) ) {
666: /*
667: * rhs is in a data register, lhs
668: * isn't, and doesn't have to be
669: */
670: p->in.left = r;
671: p->in.right = l;
672: p->in.op = revrel[p->in.op - EQ];
673: return(1);
674: }
675: }
676: order( l, cookie );
677: } else {
678: /*
679: * if here, must be a logical operator for 0-1 value
680: * and we don't have 2 registers, as we would prefer
681: */
682: int m;
683: cbranch( p, -1, m=getlab() );
684: p->in.op = CCODES;
685: p->bn.label = m;
686: order( p, INTAREG );
687: }
688: return( 1 );
689: }
690: if ( !istnode( l ) ){
691: if (commuteop(p->in.op) && istnode(r)) {
692: /* commutative op - put temp node on the left */
693: p->in.right = l;
694: p->in.left = r;
695: } else {
696: order( l, cookie&(INTAREG|INTBREG) );
697: return( 1 );
698: }
699: }
700: if ( divmulop(p->in.op) && r->in.op == REG
701: && isbreg(r->tn.rval)) {
702: order( r, INAREG|INTAREG );
703: return( 1 );
704: }
705: /* rewrite */
706: return( 0 );
707: }
708: /* now, rhs is complicated */
709: /* do the harder side first */
710: /* be careful of D0, D1 usage */
711:
712: if (SUGT(l->in.su, r->in.su)) {
713: /* lhs first; put into register */
714: SAFETY(r, MUSTDO|D0, l);
715: order(l, cookie&(INTAREG|INTBREG));
716: return( 1 );
717: }
718: /* try to make rhs addressable */
719: if(r->in.op == UNARY MUL) {
720: failsafe = find_mustdo( l, D0|MUSTDO) ;
721: if (l->in.su.d >= nfree(STAREG)) {
722: /* lhs needs all available d-registers;
723: do not use double indexing */
724: failsafe |= 1;
725: }
726: offstar( r->in.left );
727: return(1);
728: }
729: if (SUGT(r->in.su , l->in.su)){
730: /* rhs first; put into register */
731: SAFETY( l, MUSTDO|D0, r);
732: /* anything goes on rhs */
733: order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
734: return( 1 );
735: }
736: if (!istnode(l)) {
737: SAFETY(r, MUSTDO|D0, l);
738: order(l, cookie&(INTAREG|INTBREG));
739: return( 1 );
740: }
741: if (!istnode(r)) {
742: SAFETY(l, MUSTDO|D0, r);
743: order(r, INTAREG|INAREG|INTBREG|INBREG|INTEMP);
744: return( 1 );
745: }
746: /* rewrite */
747: return( 0 );
748: }
749:
750: setstr( p, cook ) register NODE *p;
751: {
752: /* structure assignment */
753: if (p->in.right->in.op != REG){
754: order( p->in.right, INTBREG );
755: return(1);
756: }
757: p = p->in.left;
758: if ( p->in.op != NAME && p->in.op != OREG ){
759: if ( p->in.op != UNARY MUL ) cerror( "bad setstr");
760: order( p->in.left, INTBREG );
761: return( 1 );
762: }
763: if( p->in.op == OREG && !R2TEST(p->tn.rval) && istreg(p->tn.rval)
764: && p->tn.lval == 0){
765: /* cheat -- rewrite this as a REG */
766: p->in.op = REG;
767: return (1);
768: }
769: #ifdef FORT
770: /* Pascal does struct assignment of things that ain't structs!! */
771: if (ISARY(p->in.type)){
772: p->in.type = STRTY;
773: return(1);
774: }
775: #endif
776: return( 0 );
777: }
778:
779: setasg( p , cookie )
780: register NODE *p;
781: {
782: /* setup for assignment operator */
783: register NODE *r, *l;
784: int failsave = failsafe;
785:
786: r = p->in.right;
787: l = p->in.left;
788:
789: if ( !SUGT( r->in.su , l->in.su )) goto do_lhs;
790: /* if ((p->in.type == DOUBLE || p->in.type == FLOAT)
791: /* && iscnode(p->in.right)){
792: /* order( p->in.right, INAREG|SOREG|SNAME|SCON );
793: /* return 1;
794: /* }
795: */
796: if( SUTEST( r->in.su ) && r->in.op != REG ){
797: failsafe |= SUTEST( l->in.su ); /* conservative guess */
798: if( r->in.op == UNARY MUL ){
799: offstar( r->in.left );
800: }else{
801: if (p->in.type == DOUBLE && r->in.type == FLOAT)
802: p->in.right = r = double_conv( r );
803: if (!use68020 || !use68881) {
804: /*
805: * more goddamn complications from register parameters:
806: * if the lhs needs D0 for a multiply, for instance,
807: * then we must be careful not to
808: * evaluate the rhs into D0.
809: */
810: SAFETY( l, MUSTDO|D0, r );
811: }
812: order( r, INAREG|INBREG|INCREG|SOREG|SNAME|SCON );
813: }
814: failsafe = failsave;
815: return(1);
816: }
817: do_lhs:
818: if( l->in.op == UNARY MUL )
819: if (!tshape( l, STARREG|STARNM )
820: || p->in.type == DOUBLE){
821: /* sorry, we're too feeble to *P++ with double pointers */
822: failsafe |= SUTEST( r->in.su ); /* conservative guess */
823: failsafe |= r->tn.su.d >= fregs.d;
824: offstar( l->in.left );
825: failsafe = failsave;
826: return(1);
827: }
828: if (l->in.op==FLD && l->in.left->in.op==UNARY MUL ){
829: failsafe |= SUTEST( r->in.su ); /* conservative guess */
830: offstar( l->in.left->in.left );
831: failsafe = failsave;
832: return(1);
833: }
834: /* if things are really strange, get rhs into a register */
835: if( r->in.op != REG ) {
836: order( r, INAREG|INBREG|INCREG );
837: failsafe = failsave;
838: return( 1 );
839: }
840: /* for fields, rhs must be in a data register */
841: if( l->in.op == FLD && r->in.op == REG && isbreg(r->tn.rval) ) {
842: order( r, INAREG|INTAREG );
843: failsafe = failsave;
844: return( 1 );
845: }
846: return(0);
847: }
848:
849: find_mustdo( p, regname ) register NODE *p;
850: {
851: /* if there are any ops here that require use of reg regname, return
852: * 1 else return 0;
853: */
854: redo:
855: if (p->in.rall == regname) return 1;
856: if (p->in.type == DOUBLE && p->in.rall == regname-1) return 1;
857: switch( optype(p->in.op) ){
858: case LTYPE: return 0;
859: case BITYPE:
860: if (find_mustdo(p->in.right, regname)) return 1;
861: /* else fall through */
862: }
863: p = p->in.left;
864: goto redo; /* go 'round again */
865: }
866:
867: int
868: rewrite_rall( n, trybreg ) NODE *n;
869: {
870: register int i, reg;
871: register TWORD t = n->in.type;
872:
873: /* find a temporary home for n */
874: reg = -1;
875: for( i = D2; i <= maxa; i++){
876: if( istreg(i) && busy[i] == 0){
877: if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0)))
878: continue; /* too bad */
879: reg = i; break;
880: }
881: }
882: if (reg < 0 && trybreg && t!=CHAR && t!= UCHAR) {
883: /* we are DESPARATE! */
884: for( i = minb; i <= maxb; i++){
885: if( istreg(i) && busy[i] == 0){
886: if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0)))
887: continue; /* too bad */
888: reg = i; break;
889: }
890: }
891: }
892: if ( reg < 0 ) return 0;
893: n->in.rall = (MUSTDO | reg);
894: return 1;
895: }
896:
897: int
898: rewrite_b_rall( n, a0ok )
899: NODE *n;
900: {
901: register int i, reg;
902:
903: /* find a temporary home for n in the b-registers */
904: /* get out of the hair of a0/a1 */
905: reg = -1;
906: for( i = minb+2; i <= maxb; i++){
907: if( istreg(i) && busy[i] == 0){
908: reg = i; break;
909: }
910: }
911: if (reg<0 && a0ok && busy[minb]==0)
912: reg = minb;
913: if ( reg < 0) return 0; /*failure*/
914: n->in.rall = MUSTDO | reg;
915: /* if this is a prospective oreg -- keep going */
916: if (n->in.op == PLUS || n->in.op == MINUS){
917: n = n->in.left;
918: if (n->in.op != REG || !isareg( n->tn.rval ) )
919: n->in.rall = MUSTDO | reg;
920: }
921: return 1;
922: }
923:
924: NODE *
925: hard_rew( p ) register NODE *p;
926: {
927: register NODE *lp, *p2;
928: register int i, reg;
929: /* do rewriting for non-reg lhs of hard op='s */
930:
931: lp = p->in.left;
932: switch(lp->in.op){
933: default:
934: return p;
935: case REG:
936: if(istreg(lp->tn.rval)) return p;
937: case NAME:
938: case OREG:
939: case UNARY MUL:
940: case FLD:
941: break;
942: }
943:
944: if (odebug){
945: printf("hard_rew( %o ):\n", p);
946: fwalk( p, eprint, 0);
947: }
948:
949: if( lp->in.op == UNARY MUL ){
950: NODE *llp = lp->in.left;
951: offstar( llp );
952: if ( llp->in.op == PLUS && llp->in.right->in.op != ICON ) {
953: /* de-index */
954: order(llp, INTBREG|INBREG);
955: }
956: }
957: if( lp->in.op == FLD && lp->in.left->in.op == UNARY MUL ){
958: NODE *lllp = lp->in.left->in.left;
959: offstar( lllp );
960: if ( lllp->in.op == PLUS && lllp->in.right->in.op != ICON ) {
961: /* de-index */
962: order(lllp, INTBREG|INBREG);
963: }
964: }
965: if( lp->in.op == FLD ) lp = lp->in.left;
966:
967: /* mimic code from reader.c */
968: p2 = tcopy( p );
969: p->in.op = ASSIGN;
970: reclaim( p->in.right, RNULL, 0 );
971: p->in.right = p2;
972: canon(p);
973: rallo( p, p->in.rall );
974: lp = p2->in.left;
975: /* if we are doing a floating op, we'll let the caller finish it off */
976: if(p->in.type == DOUBLE || p->in.type == FLOAT)
977: return p2;
978: /* if we must, rewrite rhs, too */
979: if (SUGT( p2->in.right->in.su , lp->in.su )){
980: SAFETY( lp, p2->in.right->in.rall, p2->in.right );
981: order( p2->in.right, INTAREG|INTBREG );
982: }
983: SAFETY( p2->in.right, lp->in.rall, lp );
984: order( lp, INTBREG|INTAREG );
985:
986: return p->in.right;
987: }
988:
989: setasop( p, cookie ) register NODE *p;
990: {
991: /* setup for =ops */
992: register SUTYPE sul, sur;
993: register NODE *r, *l;
994: register NODE *q, *p2;
995: SUTYPE pcost;
996:
997: r = p->in.right;
998: l = p->in.left;
999: sul = l->in.su;
1000: sur = r->in.su;
1001:
1002: switch( p->in.op ){
1003: case ASG PLUS:
1004: case ASG MINUS:
1005: case ASG OR:
1006: case ASG ER:
1007: case ASG AND:
1008: if (p->in.type == FLOAT || p->in.type == DOUBLE ) {
1009: floatops:
1010: /*
1011: * lhs in dreg or AWD, rhs in dreg or AWD.
1012: */
1013:
1014: /*
1015: * if the lhs is not a temp node, then we need to let
1016: * a op= b ; be rewritten as...
1017: * a = (a) op= b;
1018: */
1019: /* HOWEVER!:
1020: * if rhs is expensive, we gotta do it first!
1021: */
1022: if (r->in.type==FLOAT && p->in.type==DOUBLE){
1023: r = p->in.right = double_conv(r);
1024: }
1025:
1026: if (use68881) {
1027: /*
1028: * if lhs is already a coprocessor reg, all
1029: * we have to do is clean up the rhs a little.
1030: */
1031: int rhs = 0;
1032: if (iscnode(l)) {
1033: floatsrce(r);
1034: return(1);
1035: }
1036: if ( SUGT(sur, sul) ) {
1037: /* rhs is hard -- do it first */
1038: floatsrce(r);
1039: rhs = 1;
1040: }
1041: p = hard_rew(p);
1042: l = p->in.left;
1043: r = p->in.right;
1044: if ( istnode(r) && iscreg(r->tn.rval)
1045: && (p->in.op == ASG PLUS || p->in.op == ASG MUL) ) {
1046: /*
1047: * commute -- we can do this because hard_rew
1048: * assigns the result of p to the lhs
1049: */
1050: p->in.left = r;
1051: p->in.right = l;
1052: l = r;
1053: r = p->in.right;
1054: rhs = 0;
1055: } else {
1056: /*
1057: * put lhs in a coprocessor reg
1058: */
1059: order(l, INCREG|INTCREG);
1060: }
1061: /*
1062: * if rhs hasn't been dealt with yet, do it
1063: */
1064: if (!rhs) {
1065: floatsrce(r);
1066: }
1067: return(1);
1068: } /* use68881 */
1069:
1070: if (usesky){
1071: /*
1072: * check for pivot operation ( x += y * z )
1073: * only do if one of x,y,z is free
1074: */
1075: int pivoting = 0;
1076: if (p->in.op == ASG PLUS && r->in.op == MUL) {
1077: if (!SUTEST(sul)) {
1078: setbin(r, INTAREG|INAREG|INTEMP);
1079: return(1);
1080: }
1081: if (!SUTEST(r->in.left->in.su)
1082: || !SUTEST(r->in.right->in.su)) {
1083: pivoting = 1;
1084: }
1085: }
1086: /*
1087: * on the sky board, "op=" ops can be done
1088: * with lhs in memory. However, we must stay
1089: * away from a0/a1.
1090: */
1091: if (SUGT(sur,sul)){
1092: /* must do rhs first */
1093: if (pivoting) {
1094: if (SUTEST(r->in.left->in.su)) {
1095: r = r->in.left;
1096: } else {
1097: r = r->in.right;
1098: }
1099: pivoting = 0;
1100: }
1101: if (r->in.op == UNARY MUL
1102: && rewrite_b_rall(r->in.left, 0)) {
1103: /* make addressable, avoiding a1 */
1104: offstar(r->in.left);
1105: } else if (!find_mustdo(l, MUSTDO|D0)
1106: || rewrite_rall(r, 0)) {
1107: order(r, INAREG|INTAREG|INTEMP);
1108: } else {
1109: order(r, INTEMP);
1110: }
1111: r->in.su = zed;
1112: }
1113: /*
1114: * deal with lhs
1115: */
1116: if (SUTEST(sul)) {
1117: if (l->in.op == UNARY MUL
1118: && rewrite_b_rall( l->in.left, 0 )) {
1119: /* make addressable, avoiding a1 */
1120: offstar( l->in.left );
1121: } else {
1122: /* failing that, try rewriting */
1123: p = hard_rew(p);
1124: l = p->in.left;
1125: r = p->in.right;
1126: if (pivoting) {
1127: if (SUTEST(r->in.left->in.su)) {
1128: r = r->in.left;
1129: } else {
1130: r = r->in.right;
1131: }
1132: pivoting = 0;
1133: }
1134: if (!find_mustdo(r, MUSTDO|D0)
1135: || rewrite_rall(l, 0)) {
1136: order(l, INAREG|INTAREG|INTEMP);
1137: } else {
1138: order(l, INTEMP);
1139: }
1140: }
1141: }
1142: /*
1143: * deal with rhs, if necessary
1144: */
1145: if (pivoting) {
1146: if (SUTEST(r->in.left->in.su)) {
1147: r = r->in.left;
1148: } else {
1149: r = r->in.right;
1150: }
1151: }
1152: if (SUTEST(r->in.su)){
1153: if (r->in.op == UNARY MUL
1154: && rewrite_b_rall(r->in.left, 0)) {
1155: /* make addressable, avoiding a1 */
1156: offstar(r->in.left);
1157: } else {
1158: order(r, INAREG|INTAREG|INTEMP);
1159: }
1160: }
1161: return 1;
1162: } else if ( !istnode(l) ){
1163: if (SUTEST( sur )){
1164: if (!SUTEST(sul) && r->in.type == FLOAT){
1165: r->in.rall = MUSTDO|D1;
1166: order( r, INAREG );
1167: } else {
1168: /* may not want it in a register,
1169: in case lhs needs the register */
1170: if (rewrite_rall(r, 0)){
1171: order( r, INAREG|INTAREG|INBREG|INTBREG|INCREG|INTCREG );
1172: } else {
1173: r->in.rall = NOPREF;
1174: order( r, INTEMP );
1175: }
1176: }
1177: }
1178: /* lhs is either easy or is an address */
1179: /*
1180: * if its an address, we must, unhappily,
1181: * evaluate it AWAY from a0/a1, which will
1182: * be clobbered by the operation.
1183: */
1184: if (l->in.op == UNARY MUL && l->in.left->in.op != REG){
1185: failsafe = 1; /* keep away from d0/d1!! */
1186: if ( rewrite_b_rall( l->in.left, 0 ) )
1187: offstar( l->in.left );
1188: else
1189: order( l->in.left, INTEMP );
1190: } else
1191: l->in.rall = MUSTDO|D0;
1192: /* p->in.op = NOASG p->in.op; */
1193: goto rew_lhs;
1194: }
1195:
1196: if (r->in.type == DOUBLE ){
1197: if ( !tshape( r, SNAME|SOREG|STARNM)){
1198: r->in.rall = NOPREF;
1199: order( r, INTEMP );
1200: }
1201: } else {
1202: if( !(istnode(r) && r->tn.rval == D1) ){
1203: r->in.rall = MUSTDO|D1;
1204: order( r, INTAREG);
1205: }
1206: }
1207: if ( !(istnode(l) && l->tn.rval == D0) ){
1208: l->in.rall = MUSTDO|D0;
1209: order( l, INTAREG);
1210: }
1211:
1212: return 1;
1213: } else if (ISPTR(p->in.type)
1214: && (p->in.op==ASG PLUS || p->in.op==ASG MINUS)
1215: && isconv(r, SHORT, -1)
1216: && l->in.op== REG && isbreg(l->tn.rval)) {
1217: p->in.right = r->in.left;
1218: r->in.op = FREE;
1219: return 1;
1220: } else {
1221: if ((p->in.right->in.op != REG ||
1222: isbreg(p->in.right->tn.rval)) && !SUTEST( sul )) {
1223: order(p->in.right,INAREG|INTAREG);
1224: return(1);
1225: } else break;
1226: }
1227:
1228: case ASG MUL:
1229: case ASG DIV:
1230: case ASG MOD:
1231: /*
1232: * This is difficult: These ops require the lhs in d0 and the
1233: * rhs in d1. This means that whichever side gets evaluated
1234: * first will monopolize one of these strategic registers for
1235: * the whole time the other side is being evaluated. This is
1236: * not acceptable if the less-expensive side ALSO requires
1237: * evaluation of one of these constrained ops. So we must be
1238: * very careful here. First, we assume that there are, indeed,
1239: * enough registers for us to play with, otherwise off-storing
1240: * should already have been taken care of by the wonders of
1241: * portable code generation. So what we'll do is find a free
1242: * register NOT in the set {d0,d1}, and force evaluation of the
1243: * more expensive side into that register, then rewrite the
1244: * requirements for that side. Hold on.
1245: */
1246:
1247: if (p->in.type == FLOAT || p->in.type == DOUBLE)
1248: goto floatops;
1249: if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type))
1250: break;
1251: if(use68020)
1252: break;
1253:
1254: /* we can only do these into d0 */
1255: d0_d1:
1256: /* if things already look optimum, we must already have been this way once */
1257: if (istnode(p->in.left) && !SUTEST( p->in.right->tn.su )){
1258: order( p->in.right, INTAREG );
1259: return 1;
1260: }
1261: p = hard_rew( p );
1262: sul = p->in.left->in.su;
1263: /* use q to designate the more expensive side, p2 the cheaper */
1264: if ( !SUGT( sur, sul )){ q = p->in.left; p2 = p->in.right; pcost = sur; }
1265: else { q = p->in.right; p2 = p->in.left; pcost = sul; }
1266: if( SUTEST( sul ) && SUTEST( sur )){
1267: SAFETY( p2, q->in.rall, q );
1268: }
1269:
1270: /* do code emission, most expensive side first */
1271: if (!istnode( q ) ){
1272: order( q, INAREG|INTAREG);
1273: }
1274: if ( SUTEST( pcost ) && !istnode( p2 )){
1275: order( p2 ,INAREG|INTAREG);
1276: }
1277: if ( !istnode( p->in.left ) || p->in.left->tn.rval != D0 ){
1278: p->in.left->tn.rall = MUSTDO | D0;
1279: order( p->in.left, INTAREG );
1280: }
1281: if ( SUTEST(sur) &&(!istnode(p->in.right)||p->in.right->tn.rval!=D1)){
1282: p->in.right->tn.rall = MUSTDO | D0;
1283: order( p->in.right, INTAREG );
1284: }
1285:
1286: return(1);
1287:
1288: case ASG LS:
1289: case ASG RS:
1290: if (l->in.op != REG){
1291: /* must rewrite as lhs = ((lhs) op= rhs) */
1292: /* if we must, rewrite rhs, too */
1293: if (SUGT( sur , sul)){
1294: SAFETY( l, MUSTDO|D0, r );
1295: order( r, INAREG|INBREG );
1296: }
1297: /* lhs is either easy or is an address */
1298: if (SUTEST( sul )){
1299: if (l->in.op == UNARY MUL)
1300: offstar( l->in.left );
1301: else if (l->in.op == FLD &&
1302: l->in.left->in.op == UNARY MUL)
1303: offstar( l->in.left->in.left);
1304: }
1305: goto rew_lhs;
1306: }
1307: if (r->in.op == REG && isareg(r->tn.rval)
1308: || (r->in.op==ICON && r->tn.lval>=1 && r->tn.lval<=8))
1309: break;
1310: order(r,INAREG|INTAREG);
1311: return(1);
1312:
1313: }
1314:
1315: /*
1316: * What we have here is an asop which could POSSIBLY be done to memory
1317: * if we desire it. Luckily we have the cookie as a parameter to make
1318: * this decision. If we do it to memory, then we just want to evaluate
1319: * the lhs to an address. If we do it for a value, we have to evaluate
1320: * the lhs for a value, then store afterwards.
1321: */
1322: if (SUTEST( sul ) && !SUGT( sur,sul )){
1323: /* since an lhs can only be an address ... */
1324: if (l->in.op == UNARY MUL){
1325: failsafe |= SUTEST( sur ); /* conservative guess */
1326: offstar( l->in.left );
1327: } else if (l->in.op == FLD){
1328: if (l->in.left->in.op == UNARY MUL)
1329: offstar( l->in.left->in.left);
1330: return 0; /* rewrite as something sane */
1331: }
1332: if (cookie&FOREFF){
1333: /* for effect only! */
1334: return 1;
1335: }
1336: /* otherwise, rewrite as (lhs1) = ((lhs2) op= rhs) */
1337: rew_lhs:
1338: ncopy( p2=talloc(), p);
1339: p->in.op = ASSIGN;
1340: p->in.right = p2;
1341: l = p->in.left = tcopy( p2->in.left );
1342: SAFETY( p2->in.right, MUSTDO|D0, p2->in.left );
1343: if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) {
1344: /*
1345: * Beware side effects lurking in lhs. We now
1346: * have two copies -- side effects of one copy must
1347: * be eliminated. Note that (lhs2) will be evaluated first.
1348: */
1349: if (l->in.left->in.op == ASG MINUS) {
1350: /* predecrement -- keep side effect in (lhs2),
1351: delete side effect in (lhs1) */
1352: q = l->in.left;
1353: } else {
1354: /* postincrement -- keep side effect in (lhs1),
1355: delete side effect in (lhs2) */
1356: q = p2->in.left->in.left;
1357: }
1358: l = q->in.left; /* = REG */
1359: r = q->in.right; /* = ICON */
1360: *q = *l;
1361: l->in.op = FREE;
1362: r->in.op = FREE;
1363: }
1364: order( p2->in.left, INAREG|INBREG );
1365: return 1;
1366: }
1367: if( SUTEST( sur )){
1368: /* evaluate rhs into a register, then go try again */
1369: SAFETY( l, MUSTDO|D0, r );
1370: order( r, INAREG|INBREG );
1371: return 1;
1372: }
1373: if (divmulop(p->in.op) && r->in.op == REG && isbreg(r->tn.rval)) {
1374: order(r, INAREG|INTAREG);
1375: return(1);
1376: }
1377: if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) {
1378: goto rew_lhs;
1379: }
1380: return 0;
1381: }
1382:
1383: /*
1384: * returns number of free registers of a given type. This wouldn't
1385: * be necessary if the SU-numbers were strictly followed; however,
1386: * double indexing ties up more registers than sucomp assumes, and
1387: * should not be attempted unless a spare register exists.
1388: */
1389: int
1390: nfree(cookie)
1391: {
1392: register r;
1393: register n;
1394: n = 0;
1395: for (r = 0; r < REGSZ; r++) {
1396: if ((rstatus[r]&cookie) && !busy[r])
1397: n++;
1398: }
1399: return n;
1400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.