home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / mip / allo.c next >
Encoding:
C/C++ Source or Header  |  1979-01-14  |  9.3 KB  |  474 lines

  1. # include "mfile2"
  2.  
  3. NODE resc[3];
  4.  
  5. int busy[REGSZ];
  6.  
  7. int maxa, mina, maxb, minb;
  8.  
  9. allo0(){ /* free everything */
  10.  
  11.     register i;
  12.  
  13.     maxa = maxb = -1;
  14.     mina = minb = 0;
  15.  
  16.     REGLOOP(i){
  17.         busy[i] = 0;
  18.         if( rstatus[i] & STAREG ){
  19.             if( maxa<0 ) mina = i;
  20.             maxa = i;
  21.             }
  22.         if( rstatus[i] & STBREG ){
  23.             if( maxb<0 ) minb = i;
  24.             maxb = i;
  25.             }
  26.         }
  27.     }
  28.  
  29. # define TBUSY 01000
  30.  
  31. allo( p, q ) NODE *p; struct optab *q; {
  32.  
  33.     register n, i, j;
  34.  
  35.     n = q->needs;
  36.     i = 0;
  37.  
  38.     while( n & NACOUNT ){
  39.         resc[i].op = REG;
  40.         resc[i].rval = freereg( p, n&NAMASK );
  41.         resc[i].lval = 0;
  42.         resc[i].name[0] = '\0';
  43.         n -= NAREG;
  44.         ++i;
  45.         }
  46.  
  47.     while( n & NBCOUNT ){
  48.         resc[i].op = REG;
  49.         resc[i].rval = freereg( p, n&NBMASK );
  50.         resc[i].lval = 0;
  51.         resc[i].name[0] = '\0';
  52.         n -= NBREG;
  53.         ++i;
  54.         }
  55.  
  56.     if( n & NTMASK ){
  57.         resc[i].op = OREG;
  58.         resc[i].rval = TMPREG;
  59.         if( p->op == STCALL || p->op == STARG || p->op == UNARY STCALL || p->op == STASG ){
  60.             resc[i].lval = freetemp( (SZCHAR*p->stsize + (SZINT-1))/SZINT );
  61.             }
  62.         else {
  63.             resc[i].lval = freetemp( (n&NTMASK)/NTEMP );
  64.             }
  65.         resc[i].name[0] = '\0';
  66.         resc[i].lval = BITOOR(resc[i].lval);
  67.         ++i;
  68.         }
  69.  
  70.     /* turn off "temporarily busy" bit */
  71.  
  72.     REGLOOP(j){
  73.         busy[j] &= ~TBUSY;
  74.         }
  75.  
  76.     for( j=0; j<i; ++j ) if( resc[j].rval < 0 ) return(0);
  77.     return(1);
  78.  
  79.     }
  80.  
  81. freetemp( k ){ /* allocate k integers worth of temp space */
  82.     /* we also make the convention that, if the number of words is more than 1,
  83.     /* it must be aligned for storing doubles... */
  84.  
  85. # ifndef BACKTEMP
  86.     int t;
  87.  
  88.     if( k>1 ){
  89.         SETOFF( tmpoff, ALDOUBLE );
  90.         }
  91.  
  92.     t = tmpoff;
  93.     tmpoff += k*SZINT;
  94.     if( tmpoff > maxoff ) maxoff = tmpoff;
  95.     if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
  96.     return(t);
  97.  
  98. # else
  99.     tmpoff += k*SZINT;
  100.     if( k>1 ) {
  101.         SETOFF( tmpoff, ALDOUBLE );
  102.         }
  103.     if( tmpoff > maxoff ) maxoff = tmpoff;
  104.     if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
  105.     return( -tmpoff );
  106. # endif
  107.     }
  108.  
  109. freereg( p, n ) NODE *p; {
  110.     /* allocate a register of type n */
  111.     /* p gives the type, if floating */
  112.  
  113.     register j;
  114.  
  115.     /* not general; means that only one register (the result) OK for call */
  116.     if( callop(p->op) ){
  117.         j = callreg(p);
  118.         if( usable( p, n, j ) ) return( j );
  119.         /* have allocated callreg first */
  120.         }
  121.     j = p->rall & ~MUSTDO;
  122.     if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
  123.         return( j );
  124.         }
  125.     if( n&NAMASK ){
  126.         for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
  127.             if( usable(p,n,j) ){
  128.                 return( j );
  129.                 }
  130.             }
  131.         }
  132.     else if( n &NBMASK ){
  133.         for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
  134.             if( usable(p,n,j) ){
  135.                 return(j);
  136.                 }
  137.             }
  138.         }
  139.  
  140.     return( -1 );
  141.     }
  142.  
  143. usable( p, n, r ) NODE *p; {
  144.     /* decide if register r is usable in tree p to satisfy need n */
  145.  
  146.     /* checks, for the moment */
  147.     if( !istreg(r) ) cerror( "usable asked about nontemp register" );
  148.  
  149.     if( busy[r] > 1 ) return(0);
  150.     if( isbreg(r) ){
  151.         if( n&NAMASK ) return(0);
  152.         }
  153.     else {
  154.         if( n & NBMASK ) return(0);
  155.         }
  156.     if( (n&NAMASK) && (szty(p->type) == 2) ){ /* only do the pairing for real regs */
  157.         if( r&01 ) return(0);
  158.         if( !istreg(r+1) ) return( 0 );
  159.         if( busy[r+1] > 1 ) return( 0 );
  160.         if( busy[r] == 0 && busy[r+1] == 0  ||
  161.             busy[r+1] == 0 && shareit( p, r, n ) ||
  162.             busy[r] == 0 && shareit( p, r+1, n ) ){
  163.             busy[r] |= TBUSY;
  164.             busy[r+1] |= TBUSY;
  165.             return(1);
  166.             }
  167.         else return(0);
  168.         }
  169.     if( busy[r] == 0 ) {
  170.         busy[r] |= TBUSY;
  171.         return(1);
  172.         }
  173.  
  174.     /* busy[r] is 1: is there chance for sharing */
  175.     return( shareit( p, r, n ) );
  176.  
  177.     }
  178.  
  179. shareit( p, r, n ) NODE *p; {
  180.     /* can we make register r available by sharing from p
  181.        given that the need is n */
  182.     if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
  183.     if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
  184.     return(0);
  185.     }
  186.  
  187. ushare( p, f, r ) NODE *p; {
  188.     /* can we find a register r to share on the left or right
  189.         (as f=='L' or 'R', respectively) of p */
  190.     p = getlr( p, f );
  191.     if( p->op == UNARY MUL ) p = p->left;
  192.     if( p->op == OREG ){
  193.         if( R2TEST(p->rval) ){
  194.             return( r==R2UPK1(p->rval) || r==R2UPK2(p->rval) );
  195.             }
  196.         else return( r == p->rval );
  197.         }
  198.     if( p->op == REG ){
  199.         return( r == p->rval || ( szty(p->type) == 2 && r==p->rval+1 ) );
  200.         }
  201.     return(0);
  202.     }
  203.  
  204. recl2( p ) register NODE *p; {
  205.     register r = p->rval;
  206.     if( p->op == REG ) rfree( r, p->type );
  207.     else if( p->op == OREG ) {
  208.         if( R2TEST( r ) ) {
  209.             rfree( R2UPK1( r ), PTR+INT );
  210.             rfree( R2UPK2( r ), INT );
  211.             }
  212.         else {
  213.             rfree( r, PTR+INT );
  214.             }
  215.         }
  216.     }
  217.  
  218. int rdebug = 0;
  219.  
  220. rfree( r, t ) TWORD t; {
  221.     /* mark register r free, if it is legal to do so */
  222.     /* t is the type */
  223.  
  224.     if( rdebug ){
  225.         printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
  226.         }
  227.  
  228.     if( istreg(r) ){
  229.         if( --busy[r] < 0 ) cerror( "register overfreed");
  230.         if( szty(t) == 2 ){
  231.             if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
  232.             if( --busy[r+1] < 0 ) cerror( "register overfreed" );
  233.             }
  234.         }
  235.     }
  236.  
  237. rbusy(r,t) TWORD t; {
  238.     /* mark register r busy */
  239.     /* t is the type */
  240.  
  241.     if( rdebug ){
  242.         printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
  243.         }
  244.  
  245.     if( istreg(r) ) ++busy[r];
  246.     if( szty(t) == 2 ){
  247.         if( istreg(r+1) ) ++busy[r+1];
  248.         if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
  249.         }
  250.     }
  251.  
  252. rwprint( rw ){ /* print rewriting rule */
  253.     register i, flag;
  254.     static char * rwnames[] = {
  255.  
  256.         "RLEFT",
  257.         "RRIGHT",
  258.         "RESC1",
  259.         "RESC2",
  260.         "RESC3",
  261.         0,
  262.         };
  263.  
  264.     if( rw == RNULL ){
  265.         printf( "RNULL" );
  266.         return;
  267.         }
  268.  
  269.     if( rw == RNOP ){
  270.         printf( "RNOP" );
  271.         return;
  272.         }
  273.  
  274.     flag = 0;
  275.     for( i=0; rwnames[i]; ++i ){
  276.         if( rw & (1<<i) ){
  277.             if( flag ) printf( "|" );
  278.             ++flag;
  279.             printf( rwnames[i] );
  280.             }
  281.         }
  282.     }
  283.  
  284. reclaim( p, rw, cookie ) NODE *p; {
  285.     register NODE **qq;
  286.     register NODE *q;
  287.     register i;
  288.     NODE *recres[5];
  289.     struct respref *r;
  290.  
  291.     /* get back stuff */
  292.  
  293.     if( rdebug ){
  294.         printf( "reclaim( %o, ", p );
  295.         rwprint( rw );
  296.         printf( ", " );
  297.         prcook( cookie );
  298.         printf( " )\n" );
  299.         }
  300.  
  301.     if( rw == RNOP || ( p->op==FREE && rw==RNULL ) ) return;  /* do nothing */
  302.  
  303.     walkf( p, recl2 );
  304.  
  305.     if( callop(p->op) ){
  306.         /* check that all scratch regs are free */
  307.         callchk(p);  /* ordinarily, this is the same as allchk() */
  308.         }
  309.  
  310.     if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
  311.         tfree(p);
  312.         return;
  313.         }
  314.  
  315.     /* handle condition codes specially */
  316.  
  317.     if( (cookie & FORCC) && (rw&RESCC)) {
  318.         /* result is CC register */
  319.         tfree(p);
  320.         p->op = CCODES;
  321.         p->lval = 0;
  322.         p->rval = 0;
  323.         return;
  324.         }
  325.  
  326.     /* locate results */
  327.  
  328.     qq = recres;
  329.  
  330.     if( rw&RLEFT) *qq++ = getlr(p,'L');
  331.     if( rw&RRIGHT ) *qq++ = getlr(p,'R');
  332.     if( rw&RESC1 ) *qq++ = &resc[0];
  333.     if( rw&RESC2 ) *qq++ = &resc[1];
  334.     if( rw&RESC3 ) *qq++ = &resc[2];
  335.  
  336.     if( qq == recres ){
  337.         cerror( "illegal reclaim");
  338.         }
  339.  
  340.     *qq = NIL;
  341.  
  342.     /* now, select the best result, based on the cookie */
  343.  
  344.     for( r=respref; r->cform; ++r ){
  345.         if( cookie & r->cform ){
  346.             for( qq=recres; (q= *qq) != NIL; ++qq ){
  347.                 if( tshape( q, r->mform ) ) goto gotit;
  348.                 }
  349.             }
  350.         }
  351.  
  352.     /* we can't do it; die */
  353.     cerror( "cannot reclaim");
  354.  
  355.     gotit:
  356.  
  357.     if( p->op == STARG ) p = p->left;  /* STARGs are still STARGS */
  358.  
  359.     q->type = p->type;  /* to make multi-register allocations work */
  360.         /* maybe there is a better way! */
  361.     q = tcopy(q);
  362.  
  363.     tfree(p);
  364.  
  365.     p->op = q->op;
  366.     p->lval = q->lval;
  367.     p->rval = q->rval;
  368.     for( i=0; i<NCHNAM; ++i )
  369.         p->name[i] = q->name[i];
  370.  
  371.     q->op = FREE;
  372.  
  373.     /* if the thing is in a register, adjust the type */
  374.  
  375.     switch( p->op ){
  376.  
  377.     case REG:
  378.         if( !rtyflg ){
  379.             /* the C language requires intermediate results to change type */
  380.             /* this is inefficient or impossible on some machines */
  381.             /* the "T" command in match supresses this type changing */
  382.             if( p->type == CHAR || p->type == SHORT ) p->type = INT;
  383.             else if( p->type == UCHAR || p->type == USHORT ) p->type = UNSIGNED;
  384.             else if( p->type == FLOAT ) p->type = DOUBLE;
  385.             }
  386.         if( ! (p->rall & MUSTDO ) ) return;  /* unless necessary, ignore it */
  387.         i = p->rall & ~MUSTDO;
  388.         if( i & NOPREF ) return;
  389.         if( i != p->rval ){
  390.             if( busy[i] || ( szty(p->type)==2 && busy[i+1] ) ){
  391.                 cerror( "faulty register move" );
  392.                 }
  393.             rbusy( i, p->type );
  394.             rfree( p->rval, p->type );
  395.             rmove( i, p->rval, p->type );
  396.             p->rval = i;
  397.             }
  398.  
  399.     case OREG:
  400.         if( R2TEST(p->rval) ){
  401.             int r1, r2;
  402.             r1 = R2UPK1(p->rval);
  403.             r2 = R2UPK2(p->rval);
  404.             if( (busy[r1]>1 && istreg(r1)) || (busy[r2]>1 && istreg(r2)) ){
  405.                 cerror( "potential register overwrite" );
  406.                 }
  407.             }
  408.         else if( (busy[p->rval]>1) && istreg(p->rval) ) cerror( "potential register overwrite");
  409.         }
  410.  
  411.     }
  412.  
  413. ncopy( q, p ) NODE *p, *q; {
  414.     /* copy the contents of p into q, without any feeling for
  415.        the contents */
  416.     /* this code assume that copying rval and lval does the job;
  417.        in general, it might be necessary to special case the
  418.        operator types */
  419.     register i;
  420.  
  421.     q->op = p->op;
  422.     q->rall = p->rall;
  423.     q->type = p->type;
  424.     q->lval = p->lval;
  425.     q->rval = p->rval;
  426.     for( i=0; i<NCHNAM; ++i ) q->name[i]  = p->name[i];
  427.  
  428.     }
  429.  
  430. NODE *
  431. tcopy( p ) register NODE *p; {
  432.     /* make a fresh copy of p */
  433.  
  434.     register NODE *q;
  435.     register r;
  436.  
  437.     ncopy( q=talloc(), p );
  438.  
  439.     r = p->rval;
  440.     if( p->op == REG ) rbusy( r, p->type );
  441.     else if( p->op == OREG ) {
  442.         if( R2TEST(r) ){
  443.             rbusy( R2UPK1(r), PTR+INT );
  444.             rbusy( R2UPK2(r), INT );
  445.             }
  446.         else {
  447.             rbusy( r, PTR+INT );
  448.             }
  449.         }
  450.  
  451.     switch( optype(q->op) ){
  452.  
  453.     case BITYPE:
  454.         q->right = tcopy(p->right);
  455.     case UTYPE:
  456.         q->left = tcopy(p->left);
  457.         }
  458.  
  459.     return(q);
  460.     }
  461.  
  462. allchk(){
  463.     /* check to ensure that all register are free */
  464.  
  465.     register i;
  466.  
  467.     REGLOOP(i){
  468.         if( istreg(i) && busy[i] ){
  469.             cerror( "register allocation error");
  470.             }
  471.         }
  472.  
  473.     }
  474.