home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / pcc / order.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  15.1 KB  |  726 lines

  1. # include "mfile2"
  2.  
  3. int fltused = 0;
  4.  
  5. stoasg( p, o ) register NODE *p; {
  6.     /* should the assignment op p be stored,
  7.        given that it lies as the right operand of o
  8.        (or the left, if o==UNARY MUL) */
  9.     return( shltype(p->left->op, p->left ) );
  10.  
  11.     }
  12.  
  13. deltest( p ) register NODE *p; {
  14.     /* should we delay the INCR or DECR operation p */
  15.     if( p->op == INCR && p->left->op == REG && spsz( p->left->type, p->right->lval ) ){
  16.         /* STARREG */
  17.         return( 0 );
  18.         }
  19.  
  20.     p = p->left;
  21.     if( p->op == UNARY MUL ) p = p->left;
  22.     return( p->op == NAME || p->op == OREG || p->op == REG );
  23.     }
  24.  
  25. mkadrs(p) register NODE *p; {
  26.     register o;
  27.  
  28.     o = p->op;
  29.  
  30.     if( asgop(o) ){
  31.         if( p->left->su >= p->right->su ){
  32.             if( p->left->op == UNARY MUL ){
  33.                 if( p->left->su > 0 )
  34.                     SETSTO( p->left->left, INTEMP );
  35.                 else {
  36.                     if( p->right->su > 0 ) SETSTO( p->right, INTEMP );
  37.                     else cerror( "store finds both sides trivial" );
  38.                     }
  39.                 }
  40.             else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
  41.                 SETSTO( p->left->left->left, INTEMP );
  42.                 }
  43.             else { /* should be only structure assignment */
  44.                 SETSTO( p->left, INTEMP );
  45.                 }
  46.             }
  47.         else SETSTO( p->right, INTEMP );
  48.         }
  49.     else {
  50.         if( p->left->su > p->right->su ){
  51.             SETSTO( p->left, INTEMP );
  52.             }
  53.         else {
  54.             SETSTO( p->right, INTEMP );
  55.             }
  56.         }
  57.     }
  58.  
  59. notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; {
  60.     /* is it legal to make an OREG or NAME entry which has an
  61.     /* offset of off, (from a register of r), if the
  62.     /* resulting thing had type t */
  63.  
  64.     /* return( 1 );  /* NO */
  65.     return(0);  /* YES */
  66.     }
  67.  
  68. # define max(x,y) ((x)<(y)?(y):(x))
  69. # define min(x,y) ((x)<(y)?(x):(y))
  70.  
  71.  
  72. # define ZCHAR 01
  73. # define ZLONG 02
  74. # define ZFLOAT 04
  75.  
  76. zum( p, zap ) register NODE *p; {
  77.     /* zap Sethi-Ullman number for chars, longs, floats */
  78.     /* in the case of longs, only STARNM's are zapped */
  79.     /* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */
  80.  
  81.     register su;
  82.  
  83.     su = p->su;
  84.  
  85.     switch( p->type ){
  86.  
  87.     case CHAR:
  88.     case UCHAR:
  89.         if( !(zap&ZCHAR) ) break;
  90.         if( su == 0 ) p->su = su = 1;
  91.         break;
  92.  
  93.     case LONG:
  94.     case ULONG:
  95.         if( !(zap&ZLONG) ) break;
  96.         if( p->op == UNARY MUL && su == 0 ) p->su = su = 2;
  97.         break;
  98.  
  99.     case FLOAT:
  100.         if( !(zap&ZFLOAT) ) break;
  101.         if( su == 0 ) p->su = su = 1;
  102.  
  103.         }
  104.  
  105.     return( su );
  106.     }
  107.  
  108. sucomp( p ) register NODE *p; {
  109.  
  110.     /* set the su field in the node to the sethi-ullman
  111.        number, or local equivalent */
  112.  
  113.     register o, ty, sul, sur;
  114.     register nr;
  115.  
  116.     ty = optype( o=p->op);
  117.     nr = szty( p->type );
  118.     p->su = 0;
  119.  
  120.     if( ty == LTYPE ) {
  121.         if( p->type==FLOAT ) p->su = 1;
  122.         return;
  123.         }
  124.     else if( ty == UTYPE ){
  125.         switch( o ) {
  126.         case UNARY CALL:
  127.         case UNARY STCALL:
  128.             p->su = fregs;  /* all regs needed */
  129.             return;
  130.  
  131.         case UNARY MUL:
  132.             if( shumul( p->left ) ) return;
  133.  
  134.         default:
  135.             p->su = max( p->left->su, nr);
  136.             return;
  137.             }
  138.         }
  139.  
  140.  
  141.     /* If rhs needs n, lhs needs m, regular su computation */
  142.  
  143.     sul = p->left->su;
  144.     sur = p->right->su;
  145.  
  146.     if( o == ASSIGN ){
  147.         asop:  /* also used for +=, etc., to memory */
  148.         if( sul==0 ){
  149.             /* don't need to worry about the left side */
  150.             p->su = max( sur, nr );
  151.             }
  152.         else {
  153.             /* right, left address, op */
  154.             if( sur == 0 ){
  155.                 /* just get the lhs address into a register, and mov */
  156.                 /* the `nr' covers the case where value is in reg afterwards */
  157.                 p->su = max( sul, nr );
  158.                 }
  159.             else {
  160.                 /* right, left address, op */
  161.                 p->su = max( sur, nr+sul );
  162.                 }
  163.             }
  164.         return;
  165.         }
  166.  
  167.     if( o == CALL || o == STCALL ){
  168.         /* in effect, takes all free registers */
  169.         p->su = fregs;
  170.         return;
  171.         }
  172.  
  173.     if( o == STASG ){
  174.         /* right, then left */
  175.         p->su = max( max( sul+nr, sur), fregs );
  176.         return;
  177.         }
  178.  
  179.     if( logop(o) ){
  180.         /* do the harder side, then the easier side, into registers */
  181.         /* left then right, max(sul,sur+nr) */
  182.         /* right then left, max(sur,sul+nr) */
  183.         /* to hold both sides in regs: nr+nr */
  184.         nr = szty( p->left->type );
  185.         sul = zum( p->left, ZLONG|ZCHAR|ZFLOAT );
  186.         sur = zum( p->right, ZLONG|ZCHAR|ZFLOAT );
  187.         p->su = min( max(sul,sur+nr), max(sur,sul+nr) );
  188.         return;
  189.         }
  190.  
  191.     if( asgop(o) ){
  192.         /* computed by doing right, doing left address, doing left, op, and store */
  193.         switch( o ) {
  194.         case INCR:
  195.         case DECR:
  196.             /* do as binary op */
  197.             break;
  198.  
  199.         case ASG DIV:
  200.         case ASG MOD:
  201.         case ASG MUL:
  202.             if( p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs;
  203.             goto gencase;
  204.  
  205.         case ASG PLUS:
  206.         case ASG MINUS:
  207.         case ASG AND:  /* really bic */
  208.         case ASG OR:
  209.             if( p->type == INT || p->type == UNSIGNED || ISPTR(p->type) ) goto asop;
  210.  
  211.         gencase:
  212.         default:
  213.             sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT );
  214.             if( sur == 0 ){ /* easy case: if addressable,
  215.                 do left value, op, store */
  216.                 if( sul == 0 ) p->su = nr;
  217.                 /* harder: left adr, val, op, store */
  218.                 else p->su = max( sul, nr+1 );
  219.                 }
  220.             else { /* do right, left adr, left value, op, store */
  221.                 if( sul == 0 ){  /* right, left value, op, store */
  222.                     p->su = max( sur, nr+nr );
  223.                     }
  224.                 else {
  225.                     p->su = max( sur, max( sul+nr, 1+nr+nr ) );
  226.                     }
  227.                 }
  228.             return;
  229.             }
  230.         }
  231.  
  232.     switch( o ){
  233.     case ANDAND:
  234.     case OROR:
  235.     case QUEST:
  236.     case COLON:
  237.     case COMOP:
  238.         p->su = max( max(sul,sur), nr);
  239.         return;
  240.         }
  241.  
  242.     if( ( o==DIV || o==MOD || o==MUL )
  243.         && p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs;
  244.     if( o==PLUS || o==MUL || o==OR || o==ER ){
  245.         /* AND is ruined by the hardware */
  246.         /* permute: get the harder on the left */
  247.  
  248.         register rt, lt;
  249.  
  250.         if( istnode( p->left ) || sul > sur ) goto noswap;  /* don't do it! */
  251.  
  252.         /* look for a funny type on the left, one on the right */
  253.  
  254.  
  255.         lt = p->left->type;
  256.         rt = p->right->type;
  257.  
  258.         if( rt == FLOAT && lt == DOUBLE ) goto swap;
  259.  
  260.         if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap;
  261.  
  262.         if( lt==LONG || lt==ULONG ){
  263.             if( rt==LONG || rt==ULONG ){
  264.                 /* if one is a STARNM, swap */
  265.                 if( p->left->op == UNARY MUL && sul==0 ) goto noswap;
  266.                 if( p->right->op == UNARY MUL && p->left->op != UNARY MUL ) goto swap;
  267.                 goto noswap;
  268.                 }
  269.             else if( p->left->op == UNARY MUL && sul == 0 ) goto noswap;
  270.             else goto swap;  /* put long on right, unless STARNM */
  271.             }
  272.  
  273.         /* we are finished with the type stuff now; if one is addressable,
  274.             put it on the right */
  275.         if( sul == 0 && sur != 0 ){
  276.  
  277.             NODE *s;
  278.             int ssu;
  279.  
  280.         swap:
  281.             ssu = sul;  sul = sur; sur = ssu;
  282.             s = p->left;  p->left = p->right; p->right = s;
  283.             }
  284.         }
  285.     noswap:
  286.  
  287.     sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT );
  288.     if( sur == 0 ){
  289.         /* get left value into a register, do op */
  290.         p->su = max( nr, sul );
  291.         }
  292.     else {
  293.         /* do harder into a register, then easier */
  294.         p->su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) );
  295.         }
  296.     }
  297.  
  298. int radebug = 0;
  299.  
  300. mkrall( p, r ) register NODE *p; {
  301.     /* insure that the use of p gets done with register r; in effect, */
  302.     /* simulate offstar */
  303.  
  304.     if( p->op == FLD ){
  305.         p->left->rall = p->rall;
  306.         p = p->left;
  307.         }
  308.  
  309.     if( p->op != UNARY MUL ) return;  /* no more to do */
  310.     p = p->left;
  311.     if( p->op == UNARY MUL ){
  312.         p->rall = r;
  313.         p = p->left;
  314.         }
  315.     if( p->op == PLUS && p->right->op == ICON ){
  316.         p->rall = r;
  317.         p = p->left;
  318.         }
  319.     rallo( p, r );
  320.     }
  321.  
  322. rallo( p, down ) register NODE *p; {
  323.     /* do register allocation */
  324.     register o, type, down1, down2, ty;
  325.  
  326.     if( radebug ) printf( "rallo( %o, %o )\n", p, down );
  327.  
  328.     down2 = NOPREF;
  329.     p->rall = down;
  330.     down1 = ( down &= ~MUSTDO );
  331.  
  332.     ty = optype( o = p->op );
  333.     type = p->type;
  334.  
  335.  
  336.     if( type == DOUBLE || type == FLOAT ){
  337.         if( o == FORCE ) down1 = FR0|MUSTDO;
  338.         ++fltused;
  339.         }
  340.     else switch( o ) {
  341.     case ASSIGN:    
  342.         down1 = NOPREF;
  343.         down2 = down;
  344.         break;
  345.  
  346.     case ASG MUL:
  347.     case ASG DIV:
  348.     case ASG MOD:
  349.         /* keep the addresses out of the hair of (r0,r1) */
  350.         if(fregs == 2 ){
  351.             /* lhs in (r0,r1), nothing else matters */
  352.             down1 = R1|MUSTDO;
  353.             down2 = NOPREF;
  354.             break;
  355.             }
  356.         /* at least 3 regs free */
  357.         /* compute lhs in (r0,r1), address of left in r2 */
  358.         p->left->rall = R1|MUSTDO;
  359.         mkrall( p->left, R2|MUSTDO );
  360.         /* now, deal with right */
  361.         if( fregs == 3 ) rallo( p->right, NOPREF );
  362.         else {
  363.             /* put address of long or value here */
  364.             p->right->rall = R3|MUSTDO;
  365.             mkrall( p->right, R3|MUSTDO );
  366.             }
  367.         return;
  368.  
  369.     case MUL:
  370.     case DIV:
  371.     case MOD:
  372.         rallo( p->left, R1|MUSTDO );
  373.  
  374.         if( fregs == 2 ){
  375.             rallo( p->right, NOPREF );
  376.             return;
  377.             }
  378.         /* compute addresses, stay away from (r0,r1) */
  379.  
  380.         p->right->rall = (fregs==3) ? R2|MUSTDO : R3|MUSTDO ;
  381.         mkrall( p->right, R2|MUSTDO );
  382.         return;
  383.  
  384.     case CALL:
  385.     case STASG:
  386.     case EQ:
  387.     case NE:
  388.     case GT:
  389.     case GE:
  390.     case LT:
  391.     case LE:
  392.     case NOT:
  393.     case ANDAND:
  394.     case OROR:
  395.         down1 = NOPREF;
  396.         break;
  397.  
  398.     case FORCE:    
  399.         down1 = R0|MUSTDO;
  400.         break;
  401.  
  402.         }
  403.  
  404.     if( ty != LTYPE ) rallo( p->left, down1 );
  405.     if( ty == BITYPE ) rallo( p->right, down2 );
  406.  
  407.     }
  408.  
  409. offstar( p ) register NODE *p; {
  410.     /* handle indirections */
  411.  
  412.     if( p->op == UNARY MUL ) p = p->left;
  413.  
  414.     if( p->op == PLUS || p->op == MINUS ){
  415.         if( p->right->op == ICON ){
  416.             order( p->left , INTAREG|INAREG );
  417.             return;
  418.             }
  419.         }
  420.     order( p, INTAREG|INAREG );
  421.     }
  422.  
  423. setincr( p ) NODE *p; {
  424.     return( 0 );    /* for the moment, don't bother */
  425.     }
  426.  
  427. niceuty( p ) register NODE *p; {
  428.     register TWORD t;
  429.  
  430.     return( p->op == UNARY MUL && (t=p->type)!=CHAR &&
  431.         t!= UCHAR && t!= FLOAT &&
  432.         shumul( p->left) != STARREG );
  433.     }
  434. setbin( p ) register NODE *p; {
  435.     register NODE *r, *l;
  436.  
  437.     r = p->right;
  438.     l = p->left;
  439.  
  440.     if( p->right->su == 0 ){ /* rhs is addressable */
  441.         if( logop( p->op ) ){
  442.             if( l->op == UNARY MUL && l->type != FLOAT && shumul( l->left ) != STARREG ) offstar( l->left );
  443.             else order( l, INAREG|INTAREG|INBREG|INTBREG|INTEMP );
  444.             return( 1 );
  445.             }
  446.         if( !istnode( l ) ){
  447.             order( l, INTAREG|INTBREG );
  448.             return( 1 );
  449.             }
  450.         /* rewrite */
  451.         return( 0 );
  452.         }
  453.     /* now, rhs is complicated: must do both sides into registers */
  454.     /* do the harder side first */
  455.  
  456.     if( logop( p->op ) ){
  457.         /* relational: do both sides into regs if need be */
  458.  
  459.         if( r->su > l->su ){
  460.             if( niceuty(r) ){
  461.                 offstar( r->left );
  462.                 return( 1 );
  463.                 }
  464.             else if( !istnode( r ) ){
  465.                 order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
  466.                 return( 1 );
  467.                 }
  468.             }
  469.         if( niceuty(l) ){
  470.             offstar( l->left );
  471.             return( 1 );
  472.             }
  473.         else if( niceuty(r) ){
  474.             offstar( r->left );
  475.             return( 1 );
  476.             }
  477.         else if( !istnode( l ) ){
  478.             order( l, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
  479.             return( 1 );
  480.             }
  481.         if( !istnode( r ) ){
  482.             order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
  483.             return( 1 );
  484.             }
  485.         cerror( "setbin can't deal with %s", opst[p->op] );
  486.         }
  487.  
  488.     /* ordinary operator */
  489.  
  490.     if( !istnode(r) && r->su > l->su ){
  491.         /* if there is a chance of making it addressable, try it... */
  492.         if( niceuty(r) ){
  493.             offstar( r->left );
  494.             return( 1 );  /* hopefully, it is addressable by now */
  495.             }
  496.         order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );  /* anything goes on rhs */
  497.         return( 1 );
  498.         }
  499.     else {
  500.         if( !istnode( l ) ){
  501.             order( l, INTAREG|INTBREG );
  502.             return( 1 );
  503.             }
  504.         /* rewrite */
  505.         return( 0 );
  506.         }
  507.     }
  508.  
  509. setstr( p ) register NODE *p; { /* structure assignment */
  510.     if( p->right->op != REG ){
  511.         order( p->right, INTAREG );
  512.         return(1);
  513.         }
  514.     p = p->left;
  515.     if( p->op != NAME && p->op != OREG ){
  516.         if( p->op != UNARY MUL ) cerror( "bad setstr" );
  517.         order( p->left, INTAREG );
  518.         return( 1 );
  519.         }
  520.     return( 0 );
  521.     }
  522.  
  523. setasg( p ) register NODE *p; {
  524.     /* setup for assignment operator */
  525.  
  526.     if( p->right->su != 0 && p->right->op != REG ) {
  527.         if( p->right->op == UNARY MUL )
  528.             offstar( p->right->left );
  529.         else
  530.             order( p->right, INAREG|INBREG|SOREG|SNAME|SCON );
  531.         return(1);
  532.         }
  533.     if( p->right->op != REG && ( p->type == FLOAT || p->type == DOUBLE ) ) {
  534.         order( p->right, INBREG );
  535.         return(1);
  536.         }
  537.     if( p->left->op == UNARY MUL && !tshape( p->left, STARREG|STARNM ) ){
  538.         offstar( p->left->left );
  539.         return(1);
  540.         }
  541.     if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
  542.         offstar( p->left->left->left );
  543.         return(1);
  544.         }
  545.     /* if things are really strange, get rhs into a register */
  546.     if( p->right->op != REG ){
  547.         order( p->right, INAREG|INBREG );
  548.         return( 1 );
  549.         }
  550.     return(0);
  551.     }
  552.  
  553. setasop( p ) register NODE *p; {
  554.     /* setup for =ops */
  555.     register sul, sur;
  556.     register NODE *q, *p2;
  557.  
  558.     sul = p->left->su;
  559.     sur = p->right->su;
  560.  
  561.     switch( p->op ){
  562.  
  563.     case ASG PLUS:
  564.     case ASG OR:
  565.     case ASG MINUS:
  566.         if( p->type != INT && p->type != UNSIGNED && !ISPTR(p->type) ) break;
  567.         if( p->right->type == CHAR || p->right->type == UCHAR ){
  568.             order( p->right, INAREG );
  569.             return( 1 );
  570.             }
  571.         break;
  572.  
  573.     case ASG ER:
  574.         if( sul == 0 || p->left->op == REG ){
  575.             if( p->left->type == CHAR || p->left->type == UCHAR ) goto rew;  /* rewrite */
  576.             order( p->right, INAREG|INBREG );
  577.             return( 1 );
  578.             }
  579.         goto leftadr;
  580.         }
  581.  
  582.     if( sur == 0 ){
  583.  
  584.     leftadr:
  585.         /* easy case: if addressable, do left value, op, store */
  586.         if( sul == 0 ) goto rew;  /* rewrite */
  587.  
  588.         /* harder; make aleft address, val, op, and store */
  589.  
  590.         if( p->left->op == UNARY MUL ){
  591.             offstar( p->left->left );
  592.             return( 1 );
  593.             }
  594.         if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
  595.             offstar( p->left->left->left );
  596.             return( 1 );
  597.             }
  598.     rew:    /* rewrite, accounting for autoincrement and autodecrement */
  599.  
  600.         q = p->left;
  601.         if( q->op == FLD ) q = q->left;
  602.         if( q->op != UNARY MUL || shumul(q->left) != STARREG ) return(0); /* let reader.c do it */
  603.  
  604.         /* mimic code from reader.c */
  605.  
  606.         p2 = tcopy( p );
  607.         p->op = ASSIGN;
  608.         reclaim( p->right, RNULL, 0 );
  609.         p->right = p2;
  610.  
  611.         /* now, zap INCR on right, ASG MINUS on left */
  612.  
  613.         if( q->left->op == INCR ){
  614.             q = p2->left;
  615.             if( q->op == FLD ) q = q->left;
  616.             if( q->left->op != INCR ) cerror( "bad incr rewrite" );
  617.             }
  618.         else if( q->left->op != ASG MINUS )  cerror( " bad -= rewrite" );
  619.  
  620.         q->left->right->op = FREE;
  621.         q->left->op = FREE;
  622.         q->left = q->left->left;
  623.  
  624.         /* now, resume reader.c rewriting code */
  625.  
  626.         canon(p);
  627.         rallo( p, p->rall );
  628.         order( p2->left, INTBREG|INTAREG );
  629.         order( p2, INTBREG|INTAREG );
  630.         return( 1 );
  631.         }
  632.  
  633.     /* harder case: do right, left address, left value, op, store */
  634.  
  635.     if( p->right->op == UNARY MUL ){
  636.         offstar( p->right->left );
  637.         return( 1 );
  638.         }
  639.     /* sur> 0, since otherwise, done above */
  640.     if( p->right->op == REG ) goto leftadr;  /* make lhs addressable */
  641.     order( p->right, INAREG|INBREG );
  642.     return( 1 );
  643.     }
  644.  
  645. int crslab = 10000;
  646.  
  647. getlab(){
  648.     return( crslab++ );
  649.     }
  650.  
  651. deflab( l ){
  652.     printf( "L%d:\n", l );
  653.     }
  654.  
  655. genargs( p) register NODE *p; {
  656.     register size;
  657.  
  658.     /* generate code for the arguments */
  659.  
  660.     /*  first, do the arguments on the right (last->first) */
  661.     while( p->op == CM ){
  662.         genargs( p->right );
  663.         p->op = FREE;
  664.         p = p->left;
  665.         }
  666.  
  667.     if( p->op == STARG ){ /* structure valued argument */
  668.  
  669.         size = p->stsize;
  670.         if( p->left->op == ICON ){
  671.             /* make into a name node */
  672.             p->op = FREE;
  673.             p= p->left;
  674.             p->op = NAME;
  675.             }
  676.         else {
  677.             /* make it look beautiful... */
  678.             p->op = UNARY MUL;
  679.             canon( p );  /* turn it into an oreg */
  680.             if( p->op != OREG ){
  681.                 offstar( p->left );
  682.                 canon( p );
  683.                 if( p->op != OREG ) cerror( "stuck starg" );
  684.                 }
  685.             }
  686.  
  687.         p->lval += size;  /* end of structure */
  688.         /* put on stack backwards */
  689.         for( ; size>0; size -= 2 ){
  690.             p->lval -= 2;
  691.             expand( p, RNOP, "    mov    AR,Z-\n" );
  692.             }
  693.         reclaim( p, RNULL, 0 );
  694.         return;
  695.         }
  696.  
  697.     /* ordinary case */
  698.  
  699.     order( p, FORARG );
  700.     }
  701.  
  702. argsize( p ) register NODE *p; {
  703.     register t;
  704.     t = 0;
  705.     if( p->op == CM ){
  706.         t = argsize( p->left );
  707.         p = p->right;
  708.         }
  709.     if( p->type == DOUBLE || p->type == FLOAT ){
  710.         SETOFF( t, 2 );
  711.         return( t+8 );
  712.         }
  713.     else if( p->type == LONG || p->type == ULONG ) {
  714.         SETOFF( t, 2);
  715.         return( t+4 );
  716.         }
  717.     else if( p->op == STARG ){
  718.         SETOFF( t, p->stalign );  /* alignment */
  719.         return( t + p->stsize );  /* size */
  720.         }
  721.     else {
  722.         SETOFF( t, 2 );
  723.         return( t+2 );
  724.         }
  725.     }
  726.