# include "mfile2.h" #ifndef NHALF #define NHALF 0x800 #endif #ifndef RKLET #define RKLET 0x1000 #endif #ifndef RXLET #define RXLET 0x2000 #endif NODE resc[NRGS]; int busy[NRGS]; # define TBUSY 0100 allo0() { /* free everything */ register i; for( i=0; ineeds; rw = q->rewrite; if( rdebug > 1 ) printf( "allo( %d, %d ), needs = 0x%x\n", p-node, q->stinline, q->needs ); i = 0; while( n & ( QCOUNT | PCOUNT | NCOUNT ) ) { if ( n & QCOUNT ) { j = freequad ( p, n ,rw ); if(rw & RXLET) rw &= ~RXLET; busy[j] |= TBUSY; busy[j+1] |= TBUSY; busy[j+2] |= TBUSY; busy[j+3] |= TBUSY; n -= 0x100; k = 4; } else if( n & PCOUNT ) { j = freepair( p, n , rw); if(rw & RXLET) rw &= ~RXLET; busy[j] |= TBUSY; busy[j+1] |= TBUSY; n -= 0x10; k = 2; } else if ( n & NCOUNT ) { j = freereg( p, n ); busy[j] |= TBUSY; n -= 1; k = 1; } presc = &resc[i]; presc->in.op = REG; presc->tn.rval = j; /* presc->tn.type = ( k == 4 ) ? TDOUBLE : ( k == 2 ) ? TLONG : TSHORT; */ presc->tn.type = p->in.type; presc->tn.lval = 0; presc->bn.label = k; ++i; } /* turn off "temporarily busy" bit */ for( j=0; j 1 ) { for( j=0; j1 ) { SETOFF( tmpoff, ALDOUBLE ); } t = tmpoff; tmpoff += k*SZINT; if( tmpoff > maxtemp ) maxtemp = tmpoff; return(t); # else tmpoff += k*SZINT; if( k>1 ) { SETOFF( tmpoff, ALDOUBLE ); } if( tmpoff > maxtemp ) maxtemp = tmpoff; return( -tmpoff ); # endif } # ifdef STACK /* for stack machines, totally disable the register allocation */ freereg( p, n ) NODE *p; { return( 0 ); } freepair( p, n ) NODE *p; { cerror( "pairs on a stack machine?" ); } rbusy( r, t ) TWORD t; { } rfree( r, t ) TWORD t; { } regrcl( p ) NODE *p; { } # else freepair( p, n, rw ) register NODE *p; register n ; int rw; { /* allocate a register pair */ /* p gives the type */ register j; register t = optype( p->tn.op ); if( callop(p->in.op) ) { j = callreg(p); if( j&1 ) cerror( "callreg returns bad pair" ); if( usable( p, n, j ) && usable( p, n, j+1) ) return( j ); /* have allocated callreg first */ } if ( rw & RXLET ) { if ( usable ( p, n, 2) && usable (p, n, 3) ) return ( 2 ); cerror ( "RXLET bad pair allocation"); } if( n ) { if( (n&LPREF) && (j = shared( getlt( p, t ) ) ) >= 0 ) { j = ( NHALF & rw ) ? j & 0xe : j; if ( j & 1 ) cerror("illegal pair LPREF"); if( usable( p, n, j ) && usable( p, n, j+1) ) return( j ); } if( (n&RPREF) && (j = shared( getrt( p, t ) ) ) >= 0 && usable( p, n, j ) && usable( p, n, j+1) ) return( j ); for( j=2; jtn.op ); if( callop(p->in.op) ) { j = callreg(p); if( j ) cerror( "callreg returns bad pair" ); if( usable( p, n, j ) && usable( p, n, j+1) && usable(p,n, j+2 ) && usable( p, n, j+3) ) return( j ); /* have allocated callreg first */ } if ( rw & RXLET ) { if( usable(p,n,0) && usable(p,n,1) && usable(p,n,2) && usable (p,n,3) ) return ( 0 ); cerror ("RXLET bad quad allocation"); } if( n ) { if( (n&LPREF) && (j = shared( getlt( p, t ) ) ) >= 0) { j = ( rw & NHALF ) ? j & 0xc : j; if ( j & 0x3 ) cerror ( "illegal quad LPREF"); if( usable( p, n, j ) && usable ( p, n, j+1 ) && usable(p,n,j+2) && usable(p,n,j+3) ) return( j ); } if( (n&RPREF) && (j = shared( getrt( p, t ) ) ) >= 0 && usable( p, n, j ) && usable ( p, n, j+1 ) && usable(p,n,j+2) && usable(p,n,j+3) ) return( j ); for( j=0; jtn.op ); if( callop(p->in.op) ) { j = callreg(p); if( usable( p, n, j ) ) return( j ); /* have allocated callreg first */ } if( n ) { if( (n&LPREF) && (j = shared( getlt( p, t ) ) ) >= 0 && usable( p, n, j ) ) return( j ); if( (n&RPREF) && (j = shared( getrt( p, t ) ) ) >= 0 && usable( p, n, j ) ) return( j ); for( j=2; jtn.op) == REG ) { r = p->tn.rval; if( r >= NRGS ) return( -1 ); if( rdebug ) { printf( "preference for R%d\n", r ); } return( r ); } /* we look for shared regs under unary-like ops */ switch( optype( o ) ) { case BITYPE: /* look for simple cases */ /* look only on the left */ case UTYPE: return( shared( p->in.left ) ); } return( -1 ); } usable( p, n, r ) register NODE *p; register n,r; { /* decide if register r is usable in tree p to satisfy need n */ if( r>= NRGS || (busy[r] & TBUSY) ) return( 0 ); if( busy[r] > 1 ) { /* ** uerror( "register %d too busy", r ); */ return( 0 ); } if( busy[r] == 0 ) return(1); /* busy[r] is 1: is there chance for sharing */ return( shareit( p, r, n ) ); } shareit( p, r, n ) register NODE *p; register r,n; { /* can we make register r available by sharing from p ** given that the need is n */ register int t = optype(p->tn.op); if( (n&LSHARE) && ushare( getlt( p, t ), r ) ) return(1); if( (n&RSHARE) && ushare( getrt( p, t ), r ) ) return(1); return(0); } ushare( p, r ) register NODE *p; register r; { /* can we find register r to share in p */ if( p->in.op == REG ) { /**** if( typlen ( p->tn.type ) == 4 && r==(p->tn.rval+1) ) return( 1 ); if( typlen ( p->tn.type ) == 8 && ( r > (p->tn.rval) && r <= (p->tn.rval+3) ) ) return( 1 ); return( r == p->tn.rval ); ********/ if ( r >= p->tn.rval && r < p->tn.rval + p->bn.label )return(1); } switch( optype( p->tn.op ) ) { case BITYPE: if( ushare( p->in.right, r ) ) return( 1 ); case UTYPE: if( ushare( p->in.left, r ) ) return( 1 ); } return(0); } regrcl( p ) register NODE *p; { /* free registers in the tree (or fragment) p */ register r; if( !p ) return; r = p->tn.rval; if( p->in.op == REG ) rfree( r, p->bn.label ); switch( optype( p->tn.op ) ) { case BITYPE: regrcl( p->in.right ); /* explict assignment to regs not accounted for */ if( asgop(p->tn.op) && p->in.left->tn.op == REG ) break; case UTYPE: regrcl( p->in.left ); } } rfree( r, n ) register int n; register r; { register i; /* mark register r free, if it is legal to do so */ /* t is the type */ r &= 0xf; #ifndef NODBG if( rdebug ) { printf( "rfree( R%d , lenght=%d)\n", r, n); } #endif if( istreg(r) ) { for ( i = n ; i ; --i ){ if( !istreg(r+i-1) ) cerror ( "register to big" ) ; if( --busy[r+i-1] < 0 ) cerror ( "register overfreed %d" ,r+i-1); } } } rbusy(r, n ) register r; register n; { register i; /* mark register r busy */ r &= 0xf; #ifndef NODBG if( rdebug ) { printf( "rbusy( R%d, length=%d ) \n", r, n); } #endif if( istreg(r) ) { for ( i = n ; i ; --i ){ if( !istreg(r+i-1) ) cerror ( "register to big" ) ; ++busy[r+i-1] ; } } } # endif rwprint( rw ) register rw; { /* print rewriting rule */ register i, flag; static char * rwnames[] = { "RLEFT", "RRIGHT", "RESC1", "RESC2", "RESC3", "RESC4", "RESCC", "RNOP", "RNULL", "RHIGHT", "RLOW", 0, }; if( rw == RNULL ) { printf( "RNULL" ); return; } flag = 0; for( i=0; rwnames[i]; ++i ) { if( rw & (1< 1) printf("reclaim inputtype = 0x%x\n",p->tn.type); /* special cases... */ if( (o=p->tn.op) == COMOP ) { /* LHS has already been freed; don't free again */ regrcl( p->in.right ); } else regrcl( p ); if( (o==FREE && rw==RNULL) || rw==RNOP ) return; if( callop(o) ) { /* check that all scratch regs are free */ callchk(p); /* ordinarily, this is the same as allchk() */ } if( rw == RNULL || (goal&FOREFF) ) { /* totally clobber, leave nothing */ tfree(p); return; } /* handle condition codes specially */ if( (goal & FORCC) && (rw&RESCC)) { /* result is CC register */ tfree(p); p->in.op = CCODES; p->tn.lval = 0; p->tn.rval = 0; return; } q = 0; if ( rw&RRIGHT ) { q = getr( p ); q->tn.type = p->tn.type; } else { int k; if( rw & RLEFT) { q = getl (p); q->tn.type = p->tn.type; k=1 ;} else if( rw&RESC1 ) q = &resc[0]; else if( rw&RESC2 ) q = &resc[1]; else if( rw&RESC3 ) q = &resc[2]; else if( rw&RESC4 ) q = &resc[3]; else cerror( "illegal reclaim, op %s", opst[p->tn.op]); if ( q->tn.op == REG ) { if( q->tn.rval < 8 ) k = q->bn.label / 2 ; if ( k == 0 && (rw & (RHIGHT | RLOW))) cerror( "illegal half register"); if ( k ) { if (rw&RHIGHT ) { q->bn.label = k; } if (rw&RLOW ) { q->tn.rval += k; if ( q->tn.rval < 8 ) q->bn.label = k; if ( RKLET & rw && k == 2 ) q->bn.label = 1; } } /* Halbieren der Reclaims */ if ( q->in.type & TCHAR ) q->in.type = (~TCHAR & q->in.type) | TSHORT ; if ( q->in.type == TUCHAR ) q->in.type = (~TUCHAR & q->in.type) | TUSHORT; if (( rw&RLOW) && (rw&RLEFT) ) q->in.type = TINT; } if ( rdebug > 1 ) { printf ( "reclaim type = 0x%x\n",q->in.type); } } if( o == STARG ) p = p->in.left; /* STARGs are still STARGS */ q = tcopy(q); tfree(p); *p = *q; /* make the result replace the original */ q->in.op = FREE; } NODE * tcopy( p ) register NODE *p; { /* make a fresh copy of p */ register NODE *q; register r; q=talloc(); *q = *p; r = p->tn.rval; if( p->in.op == REG ) rbusy( r, p->bn.label ); switch( optype(q->in.op) ) { case BITYPE: q->in.right = tcopy(p->in.right); case UTYPE: q->in.left = tcopy(p->in.left); } return(q); } allchk() { /* check to ensure that all register are free */ register i; for( i=0; itn.op == CM ) { t = argsize( p->in.left ); p = p->in.right; } if( p->tn.type & (TDOUBLE|TFLOAT) ) { SETOFF( t, ALDOUBLE ); t += SZDOUBLE; } else if( p->tn.type & (TLONG|TULONG) ) { SETOFF( t, ALLONG ); t += SZLONG; } else if( p->tn.type & TPOINT ) { SETOFF( t, ALPOINT ); t += SZPOINT; } else if( p->tn.type & TSTRUCT ) { SETOFF( t, p->stn.stalign ); /* alignment */ t += p->stn.stsize; /* size */ } else { SETOFF( t, ALINT ); t += SZINT; } return( t ); }