|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)su.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:
11: /*
12: * from order.c
13: */
14:
15:
16: extern int mina, maxa, minb, maxb; /* imported from allo.c */
17: int failsafe;
18: extern toff, maxtoff;
19:
20: # define iscnode(p) (p->in.op==REG && iscreg(p->tn.rval))
21:
22: # define max(x,y) ((x)<(y)?(y):(x))
23: # define min(x,y) ((x)<(y)?(x):(y))
24:
25:
26: sucomp( p ) register NODE *p;
27: {
28:
29: /* set the su field in the node to the sethi-ullman
30: number, or local equivalent */
31:
32: register o, t;
33: register nr;
34: register u, tt;
35: register NODE *r, *l;
36: SUTYPE sul, sur;
37: SUTYPE tempsu;
38: static SUTYPE zed = { 0,0,0,0 };
39:
40: p->in.su = zed;
41: switch(t = optype( o=p->in.op)) {
42: case LTYPE:
43: return;
44: case UTYPE:
45: sucomp(p->in.left);
46: break;
47: case BITYPE:
48: sucomp(p->in.left);
49: sucomp(p->in.right);
50: r = p->in.right;
51: sur = r->in.su ;
52: break;
53: }
54: l = p->in.left;
55: sul = l->in.su;
56: nr = szty( tt = p->in.type );
57:
58: switch ( o ){
59: case ASG ER:
60: /* exclusive-or -- not generally computable to-memory */
61: if ( r->tn.op != ICON ) goto reg_reg_asg;
62: /* fall through */
63:
64: case ASG PLUS:
65: case ASG MINUS:
66: case ASG AND:
67: case ASG OR:
68: /* these may be done directly at memory -- looks like = */
69: if ( tt == FLOAT || tt == DOUBLE ) {
70: goto float_asop;
71: }
72: /* fall through */
73:
74: case ASSIGN:
75: /* usually, compute rhs into a register, compute lhs, store */
76: /* could do it backwards if lhs is hairier */
77: if (SUSUM( sur ) > SUSUM( sul )){
78: /* p->in.su = max( sur, sul+nr); */
79: sur.d = max( sur.d, sul.d+nr );
80: sur.a = max( sur.a, sul.a );
81: }else{
82: /* p->in.su = max( sur+1, sul); */
83: if(l->in.op == FLD) {
84: sur.d = max(max(sur.d, sul.d),2);
85: } else {
86: sur.d = max(sur.d, sul.d);
87: }
88: sur.a = max( sur.a+1, sul.a);
89: }
90: sur.f = max( sur.f, sul.f);
91: p->in.su = sur;
92: return;
93:
94: case STASG:
95: /* compute two addresses, then use up to three more registrers */
96: /* p->in.su = max( 3, 1+max(sul,sur)); */
97: sur.d = 1+max( sur.d, sul.d );
98: t = max( sur.a, sul.a );
99: sur.a = max( 2, t );
100: p->in.su = sur;
101: return;
102:
103: case UNARY MUL:
104: if (shumul(p->in.left))
105: return;
106: /* most other unary ops handled in default case */
107: sul.a = max( sul.a, 1); /* 1 address register to * through */
108: p->in.su = sul;
109: return;
110:
111: case CALL:
112: case UNARY CALL:
113: case STCALL:
114: case UNARY STCALL:
115: p->in.su = fregs;
116: return;
117:
118: case ASG RS:
119: case ASG LS:
120: /* if the rhs is not a small contant, this is a reg-reg op */
121: if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){
122: /* looks like a unary op */
123: sul.d += nr;
124: p->in.su = sul;
125: return;
126: }
127: /* fall through */
128: case ASG MUL:
129: case ASG DIV:
130: case ASG MOD:
131: /* compute rhs, compute lhs (or vice versa), get lhs value, op */
132: if ( tt == FLOAT || tt == DOUBLE ) {
133: goto float_asop;
134: }
135: reg_reg_asg:
136: t = SUSUM(sul)?1:0; /* number regs needed to store lhs address */
137: /* want at least 2 regs + lhs address */
138: /* if lhs is complicated, will always compute it into a reg FIRST */
139: /* p->in.su = max( t+2*nr, min(t+sur, nr+sul)); */
140: /* if (sul)
141: /* u = max( sul, t+sur );
142: /* else
143: /* u = sur;
144: /* p->in.su = max( u, t+2*nr);
145: */
146: if (SUSUM(sul)){
147: sur.d = max( sur.d, sul.d );
148: sur.a = max( sur.a+t, sul.a );
149: }
150: sur.d = max( sur.d , 2*nr );
151: sur.a = max( sur.a , t );
152: sur.f = 0;
153: p->in.su = sur;
154: return;
155:
156: case PLUS:
157: case AND:
158: case OR:
159: case ER:
160: /* commutable memory-register ops */
161: if ( tt == FLOAT || tt == DOUBLE ) {
162: goto float_asop;
163: }
164: if (l->in.op != REG && SUSUM(sul) < SUSUM(sur)){
165: p->in.right = l;
166: p->in.left = r;
167: l = r;
168: r = p->in.right;
169: sul = sur;
170: sur = r->in.su ;
171: }
172: goto reg_mem_op;
173:
174: case EQ:
175: case NE:
176: case LE:
177: case GE:
178: case GT:
179: case LT:
180: case UGT:
181: case UGE:
182: case ULT:
183: case ULE:
184: tt = l->in.type;
185: nr = szty( tt );
186: /* fall through */
187: case MINUS:
188: case INCR:
189: case DECR:
190: if ( tt == FLOAT || tt == DOUBLE ) {
191: float_asop:
192: if (use68881) {
193: nr = 1;
194: if (!SUTEST(sur)
195: && (r->in.op != REG || !isbreg(r->tn.rval))){
196: /* rhs is cheap */
197: sul.f = max( sul.f, nr );
198: p->in.su = sul;
199: return;
200: }
201: /* compute rhs, lhs (or vice versa) do op */
202: if (SUGT(sur, sul)){
203: /*
204: * value of rhs, value of lhs,
205: * reg-reg op
206: */
207: /* p->in.su = max( sur, sul+nr ); */
208: if (commuteop(o) && !SUTEST(sul)
209: && (l->in.op != REG || !isbreg(l->tn.rval))){
210: u = max( sul.f, nr );
211: } else {
212: u = nr + max( sul.f, nr );
213: }
214: sur.d = max( sur.d, sul.d );
215: sur.a = max( sur.a, sul.a );
216: sur.f = max( sur.f, u );
217: } else {
218: /* p->in.su = max( sul, sur+1 ); */
219: if (r->in.op == UNARY MUL){
220: /*
221: * address of rhs, value of lhs,
222: * op from memory
223: */
224: sur.d = max( sur.d, sul.d );
225: sur.a = max( sur.a, sul.a+1 );
226: sur.f = max( sul.f, sur.f+1 );
227: } else {
228: /*
229: * value of lhs, value of rhs,
230: * reg-reg-op
231: */
232: sur.d = max( sul.d, sur.d );
233: sur.a = max( sul.a, sur.a );
234: sur.f = max( sul.f+1, sur.f+1 );
235: }
236: }
237: p->in.su = sur;
238: return;
239: }
240: /*
241: * floating operations are calls.
242: * They always take ALL the registers.
243: * SIMPLE FIRST APPROXIMATION HERE.
244: * evaluate rhs first: if lhs
245: * costs, then may need an extra temp.
246: */
247: if (SUTEST(sur) && SUTEST(sul) )
248: u = max( sur.d, sul.d+nr);
249: else
250: u = max( sur.d, sul.d );
251: tempsu.d = max( u, fregs.d );
252:
253: u = max( sur.a, sul.a );
254: tempsu.a = max( u, fregs.a );
255: tempsu.f = 0;
256: p->in.su = tempsu;
257: return;
258: }
259: reg_mem_op:
260: /* memory-register ops */
261:
262: /*
263: * if rhs is direct, then the op is very cheap.
264: * But if rhs is an address register, only integer
265: * addition and subtraction are cheap.
266: */
267: if (SUSUM(sur) == 0) {
268: int cheap = 1;
269: if (r->in.op == REG && isbreg(r->tn.rval)) {
270: switch(o) {
271: case PLUS:
272: case MINUS:
273: case ASG PLUS:
274: case ASG MINUS:
275: if (tt == CHAR || tt == UCHAR) {
276: /* can't use addr regs in byte adds and subs */
277: cheap = 0;
278: }
279: break;
280: default:
281: /* can't use addr regs for other ops, period */
282: cheap = 0;
283: break;
284: }
285: }
286: if (cheap) {
287: sul.d = max(sul.d, nr);
288: p->in.su = sul;
289: return;
290: }
291: }
292: /* else must compute rhs, lhs (or vice versa) do op */
293: if (SUGT(sul, sur)) {
294: /* lhs, rhs, reg-reg op */
295: /* p->in.su = max( sul, sur+nr ); */
296: u = nr + max( sur.d , nr );
297: sur.d = max( sul.d, u );
298: sur.a = max( sur.a, sul.a );
299: } else {
300: /* p->in.su = max( sul, sur+1 ); */
301: if (r->in.op == UNARY MUL){
302: /* address of rhs, value of lhs, op from memory */
303: sur.d = max( sur.d, sul.d );
304: sur.a = max( sur.a, sul.a+1 );
305: } else if (SUGT(sur,sul)) {
306: /* value of rhs, value of lhs, reg-reg-op */
307: sur.d = max( sur.d, sul.d+nr );
308: sur.a = max( sur.a, sul.a );
309: } else {
310: /* value of lhs, value of rhs, reg-reg-op */
311: sur.d = max( sul.d, sur.d+nr );
312: sur.a = max( sul.a, sur.a );
313: }
314: }
315: sur.f = 0;
316: p->in.su = sur;
317: /* is there an easier way to do this? */
318: return;
319:
320: case RS:
321: case LS:
322: /* looks like a unary op if rhs is small */
323: if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){
324: /* looks like a unary op */
325: sul.d = max( sul.d, nr);
326: p->in.su = sul;
327: return;
328: }
329: /* fall through */
330: case MUL:
331: case DIV:
332: case MOD:
333: if ( tt == FLOAT || tt == DOUBLE ) {
334: goto float_asop;
335: }
336: reg_reg_op:
337: /* register-register ops */
338: /* must do one and then the other */
339: /* commutability not an issue here */
340: /* need at least two register sets */
341: if ( SUGT( sul, sur ) ){
342: t = max( sul.d, sur.d+nr );
343: } else {
344: t = max( sul.d+nr, sur.d );
345: }
346: sul.d = max( 2*nr, t);
347: sul.a = max( sul.a, sur.a );
348: sul.f = max( sul.f, sur.f );
349: p->in.su = sul;
350: return;
351:
352: case NAME:
353: case REG:
354: case OREG:
355: case ICON:
356: case FCON:
357: return; /* su is zero */
358:
359: case SCONV:
360: if (!ezsconv(p)){
361: sul.d = max( sul.d, fregs.d);
362: sul.a = max( sul.a, fregs.a);
363: } else if (use68881
364: && (ISFLOATING(tt) || ISFLOATING(l->in.type))) {
365: sul.f = max( sul.f, 1 );
366: sul.d = max( sul.d, 1 );
367: } else {
368: sul.d = max( sul.d, nr); /* normal unary */
369: }
370: p->in.su = sul;
371: break;
372:
373: case FAINT:
374: case FANINT:
375: case FNINT:
376: /* float=>integer conversion */
377: if (use68881) {
378: sul.d = max(sul.d, 1);
379: sul.f = max(sul.f, 1);
380: } else {
381: /* must do subroutine call */
382: sul.d = max(sul.d, fregs.d);
383: sul.a = max(sul.a, fregs.a);
384: }
385: p->in.su = sul;
386: break;
387:
388: case CHK:
389: /*
390: * this is actually a ternary operation:
391: * the expression to be checked,
392: * the lower bound,
393: * the upper bound.
394: * if the upper and lower bounds are constant, then
395: * cost is the cost of the expression, which must
396: * always be evaluated into a data register. We
397: * may have to evaluate the bounds, too, and this
398: * costs more.
399: * we will try to use the 68010's chk instruction.
400: * failing that, we will use the 68020's chk2 instruction.
401: * lacking that, use compare-and-branch code.
402: */
403: if (chk_ovfl){
404: /*
405: * assume we have to evaluate each of the bounds &
406: * at the same time hold the expression.
407: */
408: sur.d = max( r->in.left->in.su.d, r->in.right->in.su.d);
409: sur.a = max( r->in.left->in.su.a, r->in.right->in.su.a);
410: sur.f = max( r->in.left->in.su.f, r->in.right->in.su.f);
411: p->in.su.d = max( sul.d, nr+sur.d );
412: p->in.su.a = max( sul.a, sur.a );
413: p->in.su.f = max( sul.f, sur.f );
414: } else {
415: p->in.su = sul;
416: }
417: break;
418:
419: default:
420: if ( t == BITYPE ){
421: /* random binary operators */
422: /* choose largest */
423: t = max( sur.d, sul.d );
424: sur.d = max( t, nr );
425: sur.a = max( sur.a, sul.a );
426: sur.f = max( sur.f, sul.f );
427: p->in.su = sur;
428: return;
429: }
430: /* must be unary */
431: if (dope[o]&INTRFLG) {
432: /* fortran intrinsics */
433: if (use68881) {
434: sul.f = max(sul.f, 1);
435: } else {
436: /* must do subroutine call */
437: sul.d = max(sul.d, fregs.d);
438: sul.a = max(sul.a, fregs.a);
439: }
440: } else {
441: /* random unary op */
442: sul.d = max( sul.d, nr);
443: if (use68881 && ISFLOATING(tt)) {
444: sul.f = max( sul.f, 1 );
445: }
446: }
447: p->in.su = sul;
448: }
449: }
450:
451: int radebug = 0;
452:
453: mkrall( p, r ) register NODE *p;
454: {
455: /* insure that the use of p gets done with register r; in effect, */
456: /* simulate offstar */
457:
458: if( p->in.op == FLD ){
459: p->in.left->in.rall = p->in.rall;
460: p = p->in.left;
461: }
462:
463: if( p->in.op != UNARY MUL ) return; /* no more to do */
464: p = p->in.left;
465: if( p->in.op == UNARY MUL ){
466: p->in.rall = r;
467: p = p->in.left;
468: }
469: if( p->in.op == PLUS && p->in.right->in.op == ICON ){
470: p->in.rall = r;
471: p = p->in.left;
472: }
473: rallo( p, r );
474: }
475:
476: rallo( p, down ) NODE *p;
477: {
478: /* do register allocation */
479: register o, type, down1, down2, ty;
480: NODE *p2;
481:
482: again:
483: if( radebug ) printf( "rallo( %o, %d )\n", p, down );
484:
485: down2 = NOPREF;
486: p->in.rall = down;
487: down1 = ( down &= ~MUSTDO );
488:
489: ty = optype( o = p->in.op );
490: type = p->in.type;
491:
492:
493: switch( o ) {
494: case UNARY MUL:
495: down1 = NOPREF;
496: break;
497:
498: case ASSIGN:
499: down1 = NOPREF;
500: down2 = down;
501: break;
502:
503: case ASG MUL:
504: case ASG DIV:
505: case ASG MOD:
506:
507: case MUL:
508: case DIV:
509: case MOD:
510: switch(type){
511: case FLOAT:
512: if (use68881 || usesky) break;
513: down1 = D0|MUSTDO;
514: down2 = D1|MUSTDO;
515: break;
516: case INT:
517: case UNSIGNED:
518: if (use68020) break;
519: down1 = D0|MUSTDO;
520: down2 = D1|MUSTDO;
521: break;
522: case DOUBLE:
523: if (use68881 || usesky) break;
524: down1 = D0|MUSTDO;
525: break;
526: default:
527: if (ISPTR(type)){
528: /* this is the result of (char *)(a*b) */
529: /* treat as an unsigned or int */
530: if (use68020) break;
531: down1 = D0|MUSTDO;
532: down2 = D1|MUSTDO;
533: }
534: break;
535: }
536: break;
537:
538: case EQ:
539: case NE:
540: case GT:
541: case GE:
542: case LT:
543: case LE:
544: type = p->in.left->in.type;
545: /* fall through */
546: case PLUS:
547: case MINUS:
548: case ASG PLUS:
549: case ASG MINUS:
550: if (use68881 || usesky) break;
551: switch (type){
552: case FLOAT:
553: down1 = D0|MUSTDO;
554: down2 = D1|MUSTDO;
555: break;
556: case DOUBLE:
557: down1 = D0|MUSTDO;
558: break;
559: }
560: break;
561:
562: case NOT:
563: case ANDAND:
564: case OROR:
565: down1 = NOPREF;
566: break;
567:
568: case SCONV: /* float, fix, single, or double */
569: if (use68881 || usesky) break;
570: if (ezsconv(p)) break;
571: down1 = D0|MUSTDO;
572: break;
573:
574: case FORCE:
575: down1 = D0|MUSTDO;
576: break;
577:
578: case FNINT: /* float=>int conversion, use biased rounding */
579: if (use68881) break;
580: down1 = D0|MUSTDO;
581: break;
582:
583: default:
584: if ((dope[o]&INTRFLG) && !use68881) {
585: /* fortran intrinsics */
586: down1 = D0|MUSTDO;
587: }
588: }
589:
590: recur:
591: if( ty == BITYPE ) rallo( p->in.right, down2 );
592: else if( ty == LTYPE ) return;
593: /* else do tail-recursion */
594: p = p->in.left;
595: down = down1;
596: goto again;
597:
598: }
599:
600: stoasg( p, o ) register NODE *p;
601: {
602: /* should the assignment op p be stored,
603: given that it lies as the right operand of o
604: (or the left, if o==UNARY MUL) */
605: /*
606: if( p->in.op == INCR || p->in.op == DECR ) return;
607: if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG);
608: */
609: return( shltype(p->in.left->in.op, p->in.left ) );
610: }
611:
612: deltest( p ) register NODE *p;
613: {
614: /* should we delay the INCR or DECR operation p */
615: # ifndef MULTILEVEL
616: if( p->in.op == INCR && p->in.left->in.op == REG && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
617: /* STARREG */
618: return( 0 );
619: }
620: # else
621: if( mlmatch(p,DEFINCDEC,INCR) && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
622: /* STARREG */
623: return( 0 );
624: }
625: #endif
626: p = p->in.left;
627: return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG );
628: }
629: mkadrs(p) register NODE *p;
630: {
631: register o;
632:
633: o = p->in.op;
634:
635: if( asgop(o) ){
636: if( !SUGT( p->in.right->in.su , p->in.left->in.su )){
637: if( p->in.left->in.op == UNARY MUL ){
638: if( SUTEST( p->in.left->in.su ) )
639: SETSTO( p->in.left->in.left, INTEMP );
640: else {
641: if (SUTEST( p->in.right->in.su ) )
642: SETSTO( p->in.right, INTEMP );
643: else
644: cerror( "store finds both sides trivial" );
645: }
646: }
647: else if( p->in.left->in.op == FLD
648: && p->in.left->in.left->in.op == UNARY MUL ){
649: SETSTO( p->in.left->in.left->in.left, INTEMP );
650: } else {
651: /* should be only structure assignment */
652: SETSTO( p->in.left, INTEMP );
653: }
654: }
655: else SETSTO( p->in.right, INTEMP );
656: } else {
657: if( SUGT( p->in.left->in.su , p->in.right->in.su )){
658: SETSTO( p->in.left, INTEMP );
659: } else {
660: SETSTO( p->in.right, INTEMP );
661: }
662: }
663: }
664:
665:
666: notoff( t, r, off, cp) CONSZ off; char *cp;
667: {
668: /* is it legal to make an OREG or NAME entry which has an
669: /* offset of off, (from a register of r), if the
670: /* resulting thing had type t */
671:
672: /* yes */
673: if (use68020 && isbreg(r))
674: return(0);
675: if ( off>=-32768 && off<=32767
676: && (cp == NULL || *cp=='\0') && r>=A0 && r<=SP )
677: return(0);
678: return(1); /* NO */
679: }
680:
681: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
682:
683: #define nncon(p)\
684: ((p)->in.op == ICON && ((p)->tn.name == NULL || (p)->tn.name[0] == '\0'))
685:
686: /*
687: * Compile an array index expression, exploiting
688: * scaled indexing if possible. Assume an index
689: * register is known to be available.
690: */
691: do_index(p)
692: register NODE *p;
693: {
694: register NODE *rp,*lp;
695: int count;
696:
697: switch(p->in.op) {
698: case REG:
699: return;
700: case MUL:
701: /*
702: * at least one front-end doesn't do this...
703: */
704: rp = p->in.right;
705: if (nncon(rp)) {
706: count = -1;
707: switch(rp->tn.lval) {
708: case 1:
709: count = 0;
710: break;
711: case 2:
712: count = 1;
713: break;
714: case 4:
715: count = 2;
716: break;
717: case 8:
718: count = 3;
719: break;
720: }
721: if (count >= 0) {
722: p->in.op = LS;
723: rp->tn.lval = count;
724: /*
725: * reset type, because MULS
726: * changes shorts to longs, but
727: * ASL doesn't!
728: */
729: p->in.type = p->in.left->in.type;
730: goto leftshift;
731: }
732: }
733: break;
734: case LS:
735: leftshift:
736: rp = p->in.right;
737: lp = p->in.left;
738: if ( lp->in.op == SCONV && lp->in.type == INT ) {
739: if ( lp->in.left->in.type == CHAR ) {
740: /*
741: * we only need convert bytes to shorts.
742: */
743: lp->in.type = SHORT;
744: p->in.type = SHORT;
745: }
746: else if ( use68020 && lp->in.left->in.type == SHORT
747: && lp->in.rall == NOPREF ) {
748: /*
749: * on the 68020, a conversion from short
750: * to int below a scale by 2,4, or 8 is
751: * subsumed into the addressing modes
752: */
753: p->in.left = lp->in.left;
754: lp->in.op = FREE;
755: lp = p->in.left;
756: p->in.type = lp->in.type;
757: }
758: } /* lp->in.op == SCONV */
759: if (use68020 && nncon(rp) && rp->tn.lval >= 0
760: && rp->tn.lval <= 3){
761: /*
762: * on the 68020, scaling by 2, 4, or 8 is also free
763: */
764: if (lp->in.op != REG || p->in.rall != NOPREF) {
765: lp->in.rall = p->in.rall;
766: order(lp,INTAREG|INAREG|INTBREG|INBREG);
767: }
768: return;
769: }
770: break;
771: case SCONV:
772: if (p->in.type == INT) {
773: lp = p->in.left;
774: if (lp->in.type == CHAR) {
775: /*
776: * we only need convert bytes to shorts.
777: */
778: p->in.type = SHORT;
779: } /* char */
780: else if (lp->in.type == SHORT && p->in.rall == NOPREF) {
781: /*
782: * conversions from short to int
783: * are done by the addressing modes
784: */
785: *p = *lp;
786: lp->in.op = FREE;
787: } /* short */
788: } /* type == INT */
789: break;
790: } /* switch */
791: order(p, INTAREG|INAREG|INTBREG|INBREG);
792: } /* do_index */
793:
794: /*
795: * is this expression a register or a
796: * sign-extending conversion of one?
797: */
798: static int
799: regsconv(p)
800: NODE *p;
801: {
802: NODE *lp;
803:
804: if (p->in.op == REG)
805: return(1);
806: if (p->in.op == SCONV && p->in.type == INT) {
807: lp = p->in.left;
808: if ( (lp->in.type == SHORT || lp->in.type == CHAR)
809: && lp->in.op == REG )
810: return(1);
811: }
812: return(0);
813: }
814:
815: /*
816: * is this already a legal index?
817: */
818: int
819: isindex(p)
820: register NODE *p;
821: {
822: register rval;
823: NODE *rp;
824:
825: if (use68020) {
826: if (p->in.op == MUL) {
827: rp = p->in.right;
828: if (nncon(rp)) {
829: switch(rp->tn.lval) {
830: case 1:
831: case 2:
832: case 4:
833: case 8:
834: return(regsconv(p->in.left));
835: } /* switch */
836: } /* nncon */
837: return(0);
838: } /* MUL */
839: if (p->in.op == LS) {
840: rp = p->in.right;
841: if (nncon(rp)
842: && (rp->tn.lval >= 0 && rp->tn.lval <= 3))
843: return(regsconv(p->in.left));
844: return(0);
845: } /* LS */
846: } /* use68020 */
847: return(regsconv(p));
848: }
849:
850: /*
851: * is p a signed byte constant ? This really asks whether p is
852: * permissible in a (base+disp+index) expression. On the 68020,
853: * anything is permissible, including relocatables.
854: */
855:
856: static int
857: isbcon(p, t)
858: register NODE *p;
859: TWORD t;
860: {
861: int maxoff;
862: if (p == NIL)
863: return 0;
864: if (p->in.op == ICON) {
865: if (use68020)
866: return(1);
867: maxoff = ((BTYPE(t) == DOUBLE) ? 123 : 127);
868: if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff)
869: return(1);
870: }
871: return(0);
872: }
873:
874: /*
875: * Is p a signed short constant ? This really asks whether p
876: * is permissible in a (base+disp) expression. On the 68020,
877: * anything is permissible, including relocatables.
878: */
879:
880: static int
881: isscon(p, t)
882: register NODE *p;
883: TWORD t;
884: {
885: int maxoff;
886: if (p == NIL)
887: return 0;
888: if (p->in.op == ICON) {
889: if (use68020)
890: return(1);
891: maxoff = ((BTYPE(t) == DOUBLE) ? 32763 : 32767);
892: if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff)
893: return(1);
894: }
895: return(0);
896: }
897:
898: #define isbregnode(p) ((p)->in.op == REG && isbreg((p)->tn.rval))
899:
900: /*
901: * Is a register available for indexing? This depends
902: * on context larger than the immediate expression,
903: * represented by the 'failsafe' flag. (cf., order.c)
904: * Note that we should not ask this unless it we are
905: * fairly sure we WANT to use double indexing.
906: */
907: static int
908: can_index(p, base, index)
909: NODE *p, *base, *index;
910: {
911: if (isindex(index)) /* already got one */
912: return(1);
913: failsafe |= ((p->in.rall == D0) || (p->in.rall == D1));
914: if (failsafe) {
915: /*
916: * We need d0, d1, or both for something; don't tie
917: * either one up.
918: */
919: if (!isbregnode(base) || istreg(base->tn.rval)) {
920: /*
921: * need a scratch register for the base, too.
922: */
923: return(0); /* forget it! */
924: }
925: if(!rewrite_rall(index,1)) {
926: return(0);
927: }
928: }
929: return(1);
930: }
931:
932: /*
933: * Compile memory reference expressions, attempting to make the best
934: * use of the target machine's addressing modes. The overall plan
935: * is to put the expression into a canonical form, then select and
936: * compile a suitable subtree based on availability of registers,
937: * offset limitations, and support from the architecture. A goal
938: * is not to evaluate any more of the tree than is necessary.
939: *
940: * On entry, we assume we have been given the left branch of a UNARY MUL,
941: * not the UNARY MUL itself.
942: *
943: * When done, we must guarantee that the resulting tree can be turned
944: * into an OREG.
945: */
946:
947: offstar( p )
948: register NODE *p;
949: {
950: register NODE *lp, *rp;
951:
952: if ( (p->in.rall&MUSTDO)
953: || (p->in.op != PLUS && p->in.op != MINUS ) ) {
954: /* No chance to index */
955: if ( p->in.op != REG || !isbreg(p->tn.rval) ) {
956: failsafe = 0;
957: order(p, INTBREG|INBREG);
958: }
959: return;
960: }
961: /*
962: * exp is (<exp> [+-] <exp>)
963: */
964: lp = p->in.left;
965: rp = p->in.right;
966: if (!ISPTR(lp->in.type)) {
967: /*
968: * put the pointer on the left
969: */
970: p->in.right = lp;
971: p->in.left = rp;
972: lp = p->in.left;
973: rp = p->in.right;
974: }
975: /*
976: * u-page hack, for the kernel boys: for example,
977: * (*((struct u *) 0x4000)).u_dent.d_name[i++] = *cp;
978: */
979: if (nncon(lp) && isscon(lp) && tlen(rp) == (SZINT/SZCHAR)) {
980: /*
981: * swap base part and index part,
982: * then diddle the types
983: */
984: TWORD temp;
985: p->in.right = lp;
986: p->in.left = rp;
987: lp = p->in.left;
988: rp = p->in.right;
989: temp = lp->in.type;
990: lp->in.type = rp->in.type;
991: rp->in.type = temp;
992: }
993: /*
994: * map (<exp> - <icon>) to (<exp> + <-icon>)
995: */
996: if (p->in.op == MINUS && nncon(rp)) {
997: p->in.op = PLUS;
998: rp->tn.lval = -(rp->tn.lval);
999: }
1000: /*
1001: * map ( (<exp> - <icon> ) [+-] <exp> )
1002: * to ( (<exp> + <-icon>) [+-] <exp> )
1003: */
1004: if (lp->in.op == MINUS && nncon(lp->in.right)) {
1005: lp->in.op = PLUS;
1006: lp->in.right->tn.lval = -(lp->in.right->tn.lval);
1007: }
1008: /*
1009: * At this point, any subtractions must be done explicitly.
1010: */
1011: if ( p->in.op == MINUS ) {
1012: failsafe = 0;
1013: order(p, INTBREG|INBREG);
1014: return;
1015: }
1016: if ( lp->in.op == PLUS ) {
1017:
1018: /*
1019: * map (<index> + <base>) + <exp>
1020: * to (<base> + <index>) + <exp>
1021: */
1022: if ( !ISPTR(lp->in.left->in.type) ) {
1023: NODE *q = lp->in.left;
1024: lp->in.left = lp->in.right;
1025: lp->in.right = q;
1026: }
1027:
1028: /*
1029: * map (<base> + <index>) + <bcon>
1030: * to (<base> + <bcon>) + <index>
1031: */
1032: if ( isbcon(rp) && !isbcon(lp->in.right) ) {
1033: NODE *q = lp->in.right;
1034: lp->in.right = rp;
1035: rp = p->in.right = q;
1036: }
1037:
1038: /*
1039: * Now we evaluate the expression, or enough of it so
1040: * that the remainder can be handled by an addressing mode.
1041: */
1042: if (isbcon(lp->in.right, p->in.type)) {
1043: /*
1044: * pattern is ( <base exp> + <bcon> ) + <index>
1045: * where <bcon> is in [-127..127] for the 68010,
1046: * or any integral constant on the 68020.
1047: */
1048: NODE *llp = lp->in.left;
1049: if (SUTEST(llp->in.su) && SUTEST(rp->in.su)) {
1050: /*
1051: * don't bother;
1052: * both <base> and <index> are messy.
1053: */
1054: goto punt;
1055: }
1056: if (SUGT(rp->in.su, llp->in.su)){
1057: /*
1058: * Index is more expensive than base.
1059: * Do it first, unless you have to bend
1060: * over backwards to do it.
1061: */
1062: if (can_index(p,llp,rp)) {
1063: do_index(rp); /* breg@(disp,index) */
1064: if (!isbregnode(llp)) {
1065: order(llp, INTBREG|INBREG);
1066: }
1067: return;
1068: }
1069: goto punt;
1070: }
1071: /*
1072: * try for index
1073: */
1074: if (can_index(p,llp,rp)) {
1075: /*
1076: * evaluate base into a <breg>
1077: */
1078: if (!isbregnode(llp)) {
1079: order(llp, INTBREG|INBREG);
1080: }
1081: /*
1082: * evaluate <index> into a register
1083: */
1084: do_index(rp); /* breg@(disp, index) */
1085: return;
1086: }
1087: /*
1088: * can't index; instead,
1089: * rewrite as ( <base>+<index> ) + <bcon>
1090: */
1091: punt: llp = lp->in.right;
1092: lp->in.right = rp;
1093: p->in.right = llp;
1094: failsafe = 0;
1095: order(lp, INTBREG|INBREG); /* breg@(disp) */
1096: return;
1097: } /* (<base> + <bcon>) + <index> */
1098: } /* lp == PLUS */
1099:
1100: /*
1101: * At this point, the expression is of the form
1102: * <base part> + <index part>
1103: */
1104: if (SUTEST(lp->in.su) && SUTEST(rp->in.su)) {
1105: /*
1106: * both <base> and <index> are messy.
1107: */
1108: failsafe = 0;
1109: order(p, INTBREG|INBREG); /* breg@ */
1110: return;
1111: }
1112: if ( SUGT(rp->in.su, lp->in.su) ) {
1113: /*
1114: * index is more expensive than base.
1115: * Do it first, unless you have to bend
1116: * over backwards to do it.
1117: */
1118: if (can_index(p,lp,rp)) {
1119: do_index(rp);
1120: if (!isbregnode(lp)){
1121: order(lp, INTBREG|INBREG);
1122: }
1123: return; /* base@(index)*/
1124: }
1125: failsafe = 0;
1126: order(p, INTBREG|INBREG); /* base@ */
1127: return;
1128: }
1129: /*
1130: * try to make a breg@(disp) operand
1131: */
1132: if ( isscon(rp) ) {
1133: failsafe = 0;
1134: if (!isbregnode(lp)) {
1135: order(lp, INTBREG|INBREG);
1136: }
1137: return; /* breg@(disp) */
1138: }
1139: /*
1140: * Do base first.
1141: */
1142: if ( !isbregnode(lp) ) {
1143: order(lp, INTBREG|INBREG);
1144: }
1145: if ( istnode(lp) && tshape(rp, SCON|SNAME|SOREG|STARNM) ) {
1146: /*
1147: * pattern is <temp reg> + <mem operand>
1148: * indexing doesn't buy us anything.
1149: */
1150: failsafe = 0;
1151: order(p, INTBREG|INBREG); /* base@ */
1152: return;
1153: }
1154: if ( can_index(p,lp,rp) ) {
1155: do_index(rp); /* base@(index) */
1156: return;
1157: }
1158: /*
1159: * "Either this man is dead, or my watch has stopped."
1160: */
1161: failsafe = 0;
1162: order(p, INTBREG|INBREG); /* base@ */
1163: }
1164:
1165: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1166:
1167: int crslab = 2000000; /* 68k */
1168:
1169: getlab()
1170: {
1171: return( crslab++ );
1172: }
1173:
1174: deflab( l )
1175: {
1176: print_label(l);
1177: }
1178:
1179: #define mkmask(reg,mask) (busy[reg] ? ((mask) | (1<<(reg))) : (mask))
1180:
1181: genargs( p ) register NODE *p;
1182: {
1183: register NODE *pasg;
1184: register inc;
1185: register align;
1186: register size;
1187: register TWORD type;
1188: int padflag;
1189:
1190: /* generate code for the arguments */
1191:
1192: /* first, do the arguments on the right */
1193: while( p->in.op == CM ){
1194: genargs( p->in.right );
1195: p->in.op = FREE;
1196: p = p->in.left;
1197: }
1198:
1199: if( p->in.op == STARG ){ /* structure valued argument */
1200: /*
1201: * We are stacking arguments in anticipation of a
1202: * call.
1203: * The strategy will be to push words on the
1204: * stack (being careful of alignment problems)
1205: * in open code. A dbra loop is too hard here.
1206: */
1207: size = p->stn.stsize;
1208: if( p->in.left->in.op == ICON ){
1209: p->in.op = FREE;
1210: p= p->in.left;
1211: p->in.op = NAME;
1212: }
1213: else {
1214: /* make it look beautiful... */
1215: p->in.op = UNARY MUL;
1216: canon( p ); /* turn it into an oreg */
1217: if( p->in.op != OREG ){
1218: offstar( p->in.left );
1219: canon( p );
1220: if( p->in.op != OREG ){
1221: offstar( p->in.left );
1222: canon( p );
1223: if( p->in.op != OREG ) cerror( "stuck starg" );
1224: }
1225: }
1226: }
1227:
1228: if (size > 16) {
1229: /*
1230: * big structure argument. In its infinite wisdom,
1231: * Pascal passes array value parameters like this.
1232: * Twenty-two on the vomit meter.
1233: */
1234: int count;
1235: int residue;
1236: short regmask;
1237: int savetemp;
1238:
1239: if (size&1) size++; /* assumes ALSTACK = 16 */
1240: toff += size;
1241: if (toff > maxtoff) maxtoff = toff;
1242: count = size / sizeof(long);
1243: residue = size % sizeof(long);
1244: /*
1245: * a0 = &(actual argument);
1246: */
1247: if (p->in.op == OREG && !R2TEST(p->tn.rval)
1248: && (p->tn.name == NULL || p->tn.name[0] == '\0')
1249: && p->tn.lval == 0) {
1250: p->in.op = REG;
1251: }
1252: if (p->in.op == REG) {
1253: if (p->tn.rval != A0)
1254: expand(p, RNOP, " movl AR,a0\n");
1255: } else {
1256: expand(p, RNOP, " lea AR,a0\n");
1257: }
1258: /*
1259: * allocate and copy to top of stack
1260: */
1261: if (size > 0x7fff) {
1262: printf(" subl #%d,sp\n", size);
1263: } else {
1264: printf(" lea sp@(-%d),sp\n", size);
1265: }
1266: print_str(" movl sp,a1\n");
1267: if (count > 0x7fff) {
1268: printf(" movl #%d,d0\n", count-1);
1269: print_str("1: movl a0@+,a1@+\n");
1270: print_str(" dbra d0,1b\n");
1271: print_str(" clrw d0\n");
1272: print_str(" subql #1,d0\n");
1273: print_str(" jcc 1b\n");
1274: } else {
1275: printf(" movw #%d,d0\n", count-1);
1276: print_str("1: movl a0@+,a1@+\n");
1277: print_str(" dbra d0,1b\n");
1278: }
1279: switch(residue) {
1280: case 1:
1281: print_str(" movb a0@+,a1@+\n");
1282: break;
1283: case 2:
1284: print_str(" movw a0@+,a1@+\n");
1285: break;
1286: case 3:
1287: print_str(" movw a0@+,a1@+\n");
1288: print_str(" movb a0@+,a1@+\n");
1289: break;
1290: default:
1291: break;
1292: }
1293: reclaim(p,RNULL,0);
1294: return;
1295: } /* big structure */
1296:
1297: p->tn.lval += size;
1298: /*
1299: * arguments must be at least sizeof(int) big around here.
1300: * force size up to it.
1301: */
1302: padflag = (size <= 2 ) ;
1303: #ifdef FORT
1304: /* PASCAL ONLY */
1305: if (size & 1){
1306: /*
1307: * size is odd: last byte is peculiar.
1308: * movb to stack is magic.
1309: */
1310: size -= 1;
1311: p->tn.lval -=1;
1312: expand( p, RNOP,"\tmovb\tAR,sp@-\n" );
1313: toff += 2;
1314: if (toff > maxtoff) maxtoff = toff;
1315: }
1316: #endif FORT
1317: toff += size;
1318: if (toff > maxtoff) maxtoff = toff;
1319: for( ; size>0; size -= inc ){
1320: inc = (size>2) ? 4 : 2;
1321: p->tn.lval -= inc;
1322: expand( p, RNOP,(inc==4)?"\tmovl\tAR,sp@-\n":"\tmovw\tAR,sp@-\n" );
1323: }
1324: if (padflag){
1325: print_str(" subql #2,sp\n");
1326: toff += 2;
1327: if (toff > maxtoff) maxtoff = toff;
1328: }
1329: reclaim(p,RNULL,0);
1330: return;
1331: }
1332:
1333: /* ordinary case */
1334: order( p, FORARG );
1335: }
1336:
1337: argsize( p ) register NODE *p;
1338: {
1339: register t, s;
1340: t = 0;
1341: if( p->in.op == CM ){
1342: t = argsize( p->in.left );
1343: p = p->in.right;
1344: }
1345: switch (p->in.type){
1346: case FLOAT:
1347: #ifdef FLOATMATH
1348: if (FLOATMATH>1){
1349: SETOFF( t, ALFLOAT/SZCHAR );
1350: return( t+(SZFLOAT/SZCHAR) );
1351: }
1352: #endif FLOATMATH
1353: /* else fall through */
1354: case DOUBLE:
1355: SETOFF( t, ALDOUBLE/SZCHAR );
1356: return( t+(SZDOUBLE/SZCHAR) );
1357: }
1358: if( p->in.op == STARG ){
1359: SETOFF( t, ALSTRUCT/SZCHAR ); /* alignment */
1360: s = p->stn.stsize; /* size */
1361: s += (s & 1); /* PASCAL ONLY */
1362: if (s < SZINT/SZCHAR)
1363: s = SZINT/SZCHAR;
1364: return( s+t );
1365: } else {
1366: SETOFF( t, ALSTACK/SZCHAR );
1367: return( t+(SZINT/SZCHAR) );
1368: }
1369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.