# 2.11BSD#431 - /usr/src/lib/pcc/local2.c

##### Functions

    acon              X
    addroreg          X
    adrcon            X
    adrput            X
    callreg           X
    canaddr           X
    cbgen             X
    conput            X
    eobl2             X
    flshape           X
    gencall           X
    genscall          X
    hardops           X
    hopcode           X
    insput            X
    lastchance        X
    lineid            X
    main              X
    myreader          X
    nextcook          X
    optim2            X
    popargs           X
    rewfld            X
    rmove             X
    setregs           X
    shtemp            X
    shumul            X
    special           X
    spsz              X
    szty              X
    tlen              X
    upput             X
    where             X
    zzzcode           X

##### Variables

    brcase            X
    ccbranches        X
    ioptab            X
    lbranches         X
    opfunc            X
    respref           X
    rnames            X
    rstatus           X
    toff              X

##### Macros

    BITMASK           X
    putstr            X

##### struct's

    functbl           X
    hoptab            X

       1: # include "pass2.h"
       2: extern  int fltused;
       3: #define putstr(s)   fputs((s),stdout)
       4:
       5: /* a lot of the machine dependent parts of the second pass */
       6:
       7: # define BITMASK(n) ((1L<<n)-1)
       8: where(c) {
       9:     fprintf(stderr, "%s, line %d: ", filename, lineno);
      10:     }
      11:
      12: lineid( l, fn ) char *fn; {
      13:     /* identify line l and file fn */
      14:     printf( "/	line %d, file %s\n", l, fn );
      15:     }
      16:
      17: eobl2(){
      18:     OFFSZ spoff;    /* offset from stack pointer */
      19:
      20:     spoff = maxoff;
      21:     if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
      22:     spoff /= SZCHAR;
      23:     SETOFF(spoff,2);
      24:     printf( "	.F%d = %ld.\n", ftnno, spoff );
      25:     if( fltused ) {
      26:         fltused = 0;
      27:         printf( "	.globl	fltused\n" );
      28:         }
      29:     }
      30:
      31: struct hoptab { int opmask; char * opstring; } ioptab[]= {
      32:
      33:     ASG PLUS, "add",
      34:     ASG MINUS, "sub",
      35:     ASG OR, "bis",
      36:     ASG AND,    "bic",
      37:     ASG ER, "xor",
      38:     ASG MUL, "mul",
      39:     ASG DIV, "div",
      40:     ASG MOD, "div",
      41:     ASG LS, "asl",
      42:     ASG RS, "asr",
      43:
      44:     -1, ""    };
      45:
      46: hopcode( f, o ){
      47:     /* output the appropriate string from the above table */
      48:
      49:     register struct hoptab *q;
      50:
      51:     for( q = ioptab;  q->opmask>=0; ++q ){
      52:         if( q->opmask == o ){
      53:             printf( "%s", q->opstring );
      54:             if( f == 'F' ) printf( "f" );
      55:             return;
      56:             }
      57:         }
      58:     cerror( "no hoptab for %s", opst[o] );
      59:     }
      60:
      61: char *
      62: rnames[]= {  /* keyed to register number tokens */
      63:
      64:     "r0", "r1",
      65:     "r2", "r3", "r4",
      66:     "r5", "sp", "pc",
      67:
      68:     "fr0", "fr1", "fr2", "fr3",
      69:     "fr4", "fr5",   /* not accumulators - used for temps */
      70:     };
      71:
      72: int rstatus[] = {
      73:     SAREG|STAREG, SAREG|STAREG,
      74:     SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,   /* use as scratch if not reg var */
      75:     SAREG, SAREG, SAREG,
      76:
      77:     SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG,
      78:     SBREG, SBREG,
      79:     };
      80:
      81: tlen(p) NODE *p;
      82: {
      83:     switch(p->in.type) {
      84:         case CHAR:
      85:         case UCHAR:
      86:             return(1);
      87:
      88:         case LONG:
      89:         case ULONG:
      90:         case FLOAT:
      91:             return(4);
      92:
      93:         case DOUBLE:
      94:             return(8);
      95:
      96:         default:
      97:             return(2);
      98:         }
      99:     }
     100: NODE *brnode;
     101: int brcase;
     102:
     103: int toff = 0; /* number of stack locations used for args */
     104:
     105: zzzcode( p, c ) NODE *p; {
     106:     register m;
     107:     switch( c ){
     108:
     109:     case 'B':   /* output b if type is byte */
     110:         if( p->in.type == CHAR || p->in.type == UCHAR ) printf( "b" );
     111:         return;
     112:
     113:     case 'N':  /* logical ops, turned into 0-1 */
     114:         /* use register given by register 1 */
     115:         cbgen( 0, m=getlab(), 'I' );
     116:         deflab( p->bn.label );
     117:         printf( "	clr	%s\n", rnames[getlr( p, '1' )->tn.rval] );
     118:         if( p->in.type == LONG || p->in.type == ULONG )
     119:             printf( "	clr	%s\n", rnames[getlr(p, '1')->tn.rval + 1] );
     120:         deflab( m );
     121:         return;
     122:
     123:     case 'I':
     124:     case 'F':
     125:         cbgen( p->in.op, p->bn.label, c );
     126:         return;
     127:
     128:     case 'A':
     129:     case 'C':
     130:         /* logical operators for longs
     131: 		   defer comparisons until branch occurs */
     132:
     133:         brnode = tcopy( p );
     134:         brcase = c;
     135:         return;
     136:
     137:     case 'H':  /* fix up unsigned shifts */
     138:         {   register NODE *q;
     139:             register r, l;
     140:             TWORD t;
     141:
     142:             if( p->in.op == ASG LS ) return;
     143:             if( p->in.op != ASG RS ) cerror( "ZH bad" );
     144:             if( p->in.left->in.op != REG ) cerror( "SH left bad" );
     145:
     146:             r = p->in.left->tn.rval;
     147:             t = p->in.left->in.type;
     148:             l = (t==LONG || t == ULONG );
     149:
     150:             if( t != UNSIGNED && t != UCHAR && t != ULONG ) return;  /* signed is ok */
     151:
     152:             /* there are three cases:  right side is a constant,
     153: 				and has the shift value; right side is
     154: 				a temporary reg, and has the - shift value,
     155: 				and right side is something else: A1 has the
     156: 				- shift value then */
     157:
     158:             /* in the case where the value is known (rhs a constant),
     159: 				the mask is just computed and put out... */
     160:
     161:             if( p->in.right->in.op == ICON ){
     162:                 int s;
     163:                 s = p->in.right->tn.lval;
     164:                 if( l ){
     165:                     if( s >= 16 ){
     166:                         printf( "	clr	r%d\n", r );
     167:                         s -= 16;
     168:                         ++r;
     169:                         }
     170:                     }
     171:                 if( s >= 16 ) printf( "	clr	r%d\n", r );
     172:                 else {
     173:                     m = 0100000;
     174:                     m >>= s;  /* sign extends... */
     175:                     m <<= 1;
     176:                     printf( "	bic	$%o,r%d\n", m, r );
     177:                     }
     178:                 return;
     179:                 }
     180:
     181:             /* general case */
     182:
     183:             if( istnode( p->in.right ) ) q = p->in.right;
     184:             else q = getlr( p, '1' );  /* where -shift is stored */
     185:
     186:             /* first, we store the shifted value on the stack */
     187:             printf( "	mov	r%d,-(sp)\n", r );
     188:             if( l ) printf( "	mov	r%d,-(sp)\n", r+1 );
     189:
     190:             /* now, make a mask */
     191:
     192:             printf( "	mov	$100000,r%d\n", r );
     193:             if( l ) printf( "	clr	r%d\n", r+1 );
     194:
     195:             /* shift (arithmetically ) */
     196:             if( l ) expand( q, RNOP, "	ashc	AR" );
     197:             else expand( q, RNOP, "	ash	AR" );
     198:             printf( ",r%d\n", r );
     199:
     200:             if( l ) printf( "	ashc	$1,r%d\n", r );
     201:             else printf( "	asl	r%d\n", r );
     202:
     203:             /* now, we have a mask: use it to clear sp, and reload */
     204:
     205:             if( l ){
     206:                 printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r+1, r+1 );
     207:                 }
     208:             printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r, r );
     209:             /* whew! */
     210:             return;
     211:             }
     212:
     213:     case 'V':
     214:         /* sign extend or not -- register is one less than the
     215: 		   left descendent */
     216:
     217:         m = p->in.left->tn.rval - 1;
     218:
     219:         if( ISUNSIGNED(p->in.type) ){
     220:             printf( "	clr	r%d\n", m );
     221:             }
     222:         else {
     223:             printf( "	sxt	r%d\n", m );
     224:             }
     225:         return;
     226:
     227:         /* stack management macros */
     228:     case '-':
     229:         if( toff ++ ) printf( "-" );
     230:         printf( "(sp)" );
     231:         return;
     232:
     233:     case '4':
     234:         if( toff == 0 ) ++toff;  /* can't push doubles that way */
     235:         printf( "-(sp)" );
     236:         toff += 4;
     237:         return;
     238:
     239:     case '~':
     240:         /* complimented CR */
     241:         p->in.right->tn.lval = ~p->in.right->tn.lval;
     242:         conput( getlr( p, 'R' ) );
     243:         p->in.right->tn.lval = ~p->in.right->tn.lval;
     244:         return;
     245:
     246:     case 'M':
     247:         /* negated CR */
     248:         p->in.right->tn.lval = -p->in.right->tn.lval;
     249:         conput( getlr( p, 'R' ) );
     250:         p->in.right->tn.lval = -p->in.right->tn.lval;
     251:         return;
     252:
     253:     case 'L':  /* INIT for long constants */
     254:         {
     255:             unsigned hi, lo;
     256:             lo = p->in.left->tn.lval & BITMASK(SZINT);
     257:             hi = ( p->in.left->tn.lval >> SZINT ) & BITMASK(SZINT);
     258:             printf( "	%o; %o\n", hi, lo );
     259:             return;
     260:         }
     261:
     262:     case 'T':
     263:         /* Truncate longs for type conversions:
     264: 		    LONG|ULONG -> CHAR|UCHAR|INT|UNSIGNED
     265: 		   increment offset to second word */
     266:
     267:         m = p->in.type;
     268:         p = p->in.left;
     269:         switch( p->in.op ){
     270:         case NAME:
     271:         case OREG:
     272:             p->tn.lval += SZINT/SZCHAR;
     273:             return;
     274:         case REG:
     275:             rfree( p->tn.rval, p->in.type );
     276:             p->tn.rval += 1;
     277:             p->in.type = m;
     278:             rbusy( p->tn.rval, p->in.type );
     279:             return;
     280:         default:
     281:             cerror( "Illegal ZT type conversion" );
     282:             return;
     283:
     284:             }
     285:
     286:     case 'U':
     287:         /* same as AL for exp under U* */
     288:         if( p->in.left->in.op == UNARY MUL ) {
     289:             adrput( getlr( p->in.left, 'L' ) );
     290:             return;
     291:             }
     292:         cerror( "Illegal ZU" );
     293:         /* NO RETURN */
     294:
     295:     case 'W':   /* structure size */
     296:         if( p->in.op == STASG )
     297:             printf( "%d", p->stn.stsize);
     298:         else    cerror( "Not a structure" );
     299:         return;
     300:
     301:     case 'S':  /* structure assignment */
     302:         {
     303:             register NODE *l, *r;
     304:             register size, count;
     305:
     306:             if( p->in.op == STASG ){
     307:                 l = p->in.left;
     308:                 r = p->in.right;
     309:                 }
     310:             else if( p->in.op == STARG ){  /* store an arg onto the stack */
     311:                 r = p->in.left;
     312:                 }
     313:             else cerror( "STASG bad" );
     314:
     315:             if( r->in.op == ICON ) r->in.op = NAME;
     316:             else if( r->in.op == REG ) r->in.op = OREG;
     317:             else if( r->in.op != OREG ) cerror( "STASG-r" );
     318:
     319:             size = p->stn.stsize;
     320:             count = size / 2;
     321:
     322:             r->tn.lval += size;
     323:             if( p->in.op == STASG ) l->tn.lval += size;
     324:
     325:             while( count-- ){ /* simple load/store loop */
     326:                 r->tn.lval -= 2;
     327:                 expand( r, FOREFF, "	mov	AR," );
     328:                 if( p->in.op == STASG ){
     329:                     l->tn.lval -= 2;
     330:                     expand( l, FOREFF, "AR\n" );
     331:                     }
     332:                 else {
     333:                     printf( "-(sp)\n" );
     334:                     }
     335:
     336:                 }
     337:
     338:             if( r->in.op == NAME ) r->in.op = ICON;
     339:             else if( r->in.op == OREG ) r->in.op = REG;
     340:
     341:             }
     342:         break;
     343:
     344:     default:
     345:         cerror( "illegal zzzcode" );
     346:         }
     347:     }
     348:
     349: rmove( rt, rs, t ) TWORD t; {
     350:     printf( "	%s	%s,%s\n", (t==FLOAT||t==DOUBLE)?"movf":"mov", rnames[rs], rnames[rt] );
     351:     }
     352:
     353: struct respref
     354: respref[] = {
     355:     INTAREG|INTBREG,    INTAREG|INTBREG,
     356:     INAREG|INBREG,  INAREG|INBREG|SOREG|STARREG|SNAME|STARNM|SCON,
     357:     INTEMP, INTEMP,
     358:     FORARG, FORARG,
     359:     INTAREG,    SOREG|SNAME,
     360:     0,  0 };
     361:
     362: setregs(){ /* set up temporary registers */
     363:     register i;
     364:
     365:     /* use any unused variable registers as scratch registers */
     366:     fregs = maxtreg>=MINRVAR ? maxtreg + 1 : MINRVAR;
     367:     if( xdebug ){
     368:         /* -x changes number of free regs to 2, -xx to 3, etc. */
     369:         if( (xdebug+1) < fregs ) fregs = xdebug+1;
     370:         }
     371:     /* NOTE: for pdp11 fregs <= 4 for float regs */
     372:     if( fregs > 4 ) fregs = 4;
     373:     for( i=MINRVAR; i<=MAXRVAR; i++ )
     374:         rstatus[i] = i<fregs ? SAREG|STAREG : SAREG;
     375:     }
     376:
     377: szty(t) TWORD t; { /* size, in words, needed to hold thing of type t */
     378:     /* really is the number of registers to hold type t */
     379:     switch( t ) {
     380:
     381:     case LONG:
     382:     case ULONG:
     383:         return( SZLONG/SZINT );
     384:
     385:     default:
     386:         return(1);
     387:
     388:         }
     389:     }
     390:
     391: rewfld( p ) NODE *p; {
     392:     return(1);
     393:     }
     394:
     395: callreg(p) NODE *p; {
     396:     return( (p->in.type==DOUBLE||p->in.type==FLOAT) ? FR0 : R0 );
     397:     }
     398:
     399: canaddr( p ) NODE *p; {
     400:     register int o = p->in.op;
     401:
     402:     if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
     403:     return(0);
     404:     }
     405:
     406: flshape( p ) register NODE *p; {
     407:     register o = p->in.op;
     408:     if( o==NAME || o==REG || o==ICON || o==OREG ) return( 1 );
     409:     return( o==UNARY MUL && shumul(p->in.left)==STARNM );
     410:     }
     411:
     412: shtemp( p ) register NODE *p; {
     413:     if( p->in.op == UNARY MUL ) p = p->in.left;
     414:     if( p->in.op == REG || p->in.op == OREG ) return( !istreg( p->tn.rval ) );
     415:     return( p->in.op == NAME || p->in.op == ICON );
     416:     }
     417:
     418: spsz( t, v ) TWORD t; CONSZ v; {
     419:
     420:     /* is v the size to increment something of type t */
     421:
     422:     if( !ISPTR(t) ) return( 0 );
     423:     t = DECREF(t);
     424:
     425:     if( ISPTR(t) ) return( v == 2 );
     426:
     427:     switch( t ){
     428:
     429:     case UCHAR:
     430:     case CHAR:
     431:         return( v == 1 );
     432:
     433:     case INT:
     434:     case UNSIGNED:
     435:         return( v == 2 );
     436:
     437:     case FLOAT:
     438:         return( v == 4 );
     439:
     440:     case DOUBLE:
     441:         return( v == 8 );
     442:         }
     443:
     444:     return( 0 );
     445:     }
     446:
     447: shumul( p ) register NODE *p; {
     448:     register o;
     449:
     450:     o = p->in.op;
     451:     if( o == NAME || o == OREG || o == ICON ) return( STARNM );
     452:
     453:     if( ( o == INCR || o == ASG MINUS ) &&
     454:         ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
     455:         p->in.right->in.name[0] == '\0' &&
     456:         spsz( p->in.left->in.type, p->in.right->tn.lval ) )
     457:         return( STARREG );
     458:
     459:     return( 0 );
     460:     }
     461:
     462: adrcon( val ) CONSZ val; {
     463:     printf( CONFMT, val );
     464:     }
     465:
     466: conput( p ) register NODE *p; {
     467:     switch( p->in.op ){
     468:
     469:     case ICON:
     470:         acon( p );
     471:         return;
     472:
     473:     case REG:
     474:         putstr( rnames[p->tn.rval] );
     475:         return;
     476:
     477:     default:
     478:         cerror( "illegal conput" );
     479:         }
     480:     }
     481:
     482: insput( p ) NODE *p; {
     483:     cerror( "insput" );
     484:     }
     485:
     486: upput( p ) NODE *p; {
     487:     /* output the address of the second word in the
     488: 	   pair pointed to by p (for LONGs)*/
     489:     CONSZ save;
     490:
     491:     if( p->in.op == FLD ){
     492:         p = p->in.left;
     493:         }
     494:
     495:     save = p->tn.lval;
     496:     switch( p->in.op ){
     497:
     498:     case NAME:
     499:         p->tn.lval += SZINT/SZCHAR;
     500:         acon( p );
     501:         break;
     502:
     503:     case ICON:
     504:         /* addressable value of the constant */
     505:         p->tn.lval &= BITMASK(SZINT);
     506:         putstr( "$" );
     507:         acon( p );
     508:         break;
     509:
     510:     case REG:
     511:         putstr( rnames[p->tn.rval+1] );
     512:         break;
     513:
     514:     case OREG:
     515:         p->tn.lval += SZINT/SZCHAR;
     516:         if( p->tn.rval == R5 ){  /* in the argument region */
     517:             if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
     518:             }
     519:         if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p );
     520:         printf( "(%s)", rnames[p->tn.rval] );
     521:         break;
     522:
     523:     default:
     524:         cerror( "illegal upper address" );
     525:         break;
     526:
     527:         }
     528:     p->tn.lval = save;
     529:
     530:     }
     531:
     532: adrput( p ) register NODE *p; {
     533:     /* output an address, with offsets, from p */
     534:
     535:     if( p->in.op == FLD ){
     536:         p = p->in.left;
     537:         }
     538:     switch( p->in.op ){
     539:
     540:     case NAME:
     541:         acon( p );
     542:         return;
     543:
     544:     case ICON:
     545:         /* addressable value of the constant */
     546:         if( szty( p->in.type ) == 2 ) {
     547:             /* print the high order value */
     548:             CONSZ save;
     549:             save = p->tn.lval;
     550:             p->tn.lval = ( p->tn.lval >> SZINT ) & BITMASK(SZINT);
     551:             putstr( "$" );
     552:             acon( p );
     553:             p->tn.lval = save;
     554:             return;
     555:             }
     556:         printf( "$" );
     557:         acon( p );
     558:         return;
     559:
     560:     case REG:
     561:         putstr( rnames[p->tn.rval] );
     562:         return;
     563:
     564:     case OREG:
     565:         if( p->tn.rval == R5 ){  /* in the argument region */
     566:             if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
     567:             printf( CONFMT, p->tn.lval );
     568:             putstr( ".(r5)" );
     569:             return;
     570:             }
     571:         if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p );
     572:         printf( "(%s)", rnames[p->tn.rval] );
     573:         return;
     574:
     575:     case UNARY MUL:
     576:         /* STARNM or STARREG found */
     577:         if( tshape(p, STARNM) ) {
     578:             putstr( "*" );
     579:             adrput( p->in.left);
     580:             }
     581:         else {  /* STARREG - really auto inc or dec */
     582:             /* turn into OREG so replacement node will
     583: 			   reflect the value of the expression */
     584:             register i;
     585:             register NODE *q, *l;
     586:
     587:             l = p->in.left;
     588:             q = l->in.left;
     589:             p->in.op = OREG;
     590:             p->in.rall = q->in.rall;
     591:             p->tn.lval = q->tn.lval;
     592:             p->tn.rval = q->tn.rval;
     593: #ifndef FLEXNAMES
     594:             for(i=0; i<NCHNAM; ++i)
     595:                 p->in.name[i] = q->in.name[i];
     596: #else
     597:             p->in.name = q->in.name;
     598: #endif
     599:             if( l->in.op == INCR ) {
     600:                 adrput( p );
     601:                 putstr( "+" );
     602:                 p->tn.lval -= l->in.right->tn.lval;
     603:                 }
     604:             else {  /* l->in.op == ASG MINUS */
     605:                 putstr( "-" );
     606:                 adrput( p );
     607:                 }
     608:             tfree( l );
     609:         }
     610:         return;
     611:
     612:     default:
     613:         cerror( "illegal address" );
     614:         return;
     615:
     616:         }
     617:
     618:     }
     619:
     620: acon( p ) register NODE *p; { /* print out a constant */
     621:
     622:     if( p->in.name[0] == '\0' ){    /* constant only */
     623:         printf( CONFMT, p->tn.lval);
     624:         printf( "." );
     625:         }
     626:     else if( p->tn.lval == 0 ) {    /* name only */
     627: #ifndef FLEXNAMES
     628:         printf( "%.8s", p->in.name );
     629: #else
     630:         putstr( p->in.name );
     631: #endif
     632:         }
     633:     else {              /* name + offset */
     634: #ifndef FLEXNAMES
     635:         printf( "%.8s+", p->in.name );
     636: #else
     637:         putstr( p->in.name );
     638: #endif
     639:         printf( CONFMT, p->tn.lval );
     640:         printf( "." );
     641:         }
     642:     }
     643:
     644: genscall( p, cookie ) register NODE *p; {
     645:     /* structure valued call */
     646:     return( gencall( p, cookie ) );
     647:     }
     648:
     649: gencall( p, cookie ) register NODE *p; {
     650:     /* generate the call given by p */
     651:     register temp;
     652:     register m;
     653:
     654:     if( p->in.right ) temp = argsize( p->in.right );
     655:     else temp = 0;
     656:
     657:     if( p->in.right ){ /* generate args */
     658:         genargs( p->in.right );
     659:         }
     660:
     661:     if( !shltype( p->in.left->in.op, p->in.left ) ) {
     662:         order( p->in.left, INAREG|SOREG );
     663:         }
     664:
     665:     p->in.op = UNARY CALL;
     666:     m = match( p, INTAREG|INTBREG );
     667:     popargs( temp );
     668:     return(m != MDONE);
     669:     }
     670:
     671: popargs( size ) register size; {
     672:     /* pop arguments from stack */
     673:
     674:     toff -= size/2;
     675:     if( toff == 0 && size >= 2 ) size -= 2;
     676:     switch( size ) {
     677:     case 0:
     678:         break;
     679:     case 2:
     680:         printf( "	tst	(sp)+\n" );
     681:         break;
     682:     case 4:
     683:         printf( "	cmp	(sp)+,(sp)+\n" );
     684:         break;
     685:     default:
     686:         printf( "	add	$%d.,sp\n", size);
     687:         }
     688:     }
     689:
     690: char *
     691: ccbranches[] = {
     692:     "	jeq	L%d\n",
     693:     "	jne	L%d\n",
     694:     "	jle	L%d\n",
     695:     "	jlt	L%d\n",
     696:     "	jge	L%d\n",
     697:     "	jgt	L%d\n",
     698:     "	jlos	L%d\n",
     699:     "	jlo	L%d\n",
     700:     "	jhis	L%d\n",
     701:     "	jhi	L%d\n",
     702:     };
     703:
     704: /*	long branch table
     705:
     706:    This table, when indexed by a logical operator,
     707:    selects a set of three logical conditions required
     708:    to generate long comparisons and branches.  A zero
     709:    entry indicates that no branch is required.
     710:    E.G.:  The <= operator would generate:
     711: 	cmp	AL,AR
     712: 	jlt	lable	/ 1st entry LT -> lable
     713: 	jgt	1f	/ 2nd entry GT -> 1f
     714: 	cmp	UL,UR
     715: 	jlos	lable	/ 3rd entry ULE -> lable
     716:    1:
     717:  */
     718:
     719: int lbranches[][3] = {
     720:     /*EQ*/  0,  NE, EQ,
     721:     /*NE*/  NE, 0,  NE,
     722:     /*LE*/  LT, GT, ULE,
     723:     /*LT*/  LT, GT, ULT,
     724:     /*GE*/  GT, LT, UGE,
     725:     /*GT*/  GT, LT, UGT,
     726:     /*ULE*/ ULT,    UGT,    ULE,
     727:     /*ULT*/ ULT,    UGT,    ULT,
     728:     /*UGE*/ UGT,    ULT,    UGE,
     729:     /*UGT*/ UGT,    ULT,    UGT,
     730:     };
     731:
     732: /* logical relations when compared in reverse order (cmp R,L) */
     733: #ifndef ONEPASS
     734: short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
     735: #else
     736: extern short revrel[];
     737: #endif
     738:
     739: cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
     740:     register *plb;
     741:     int lab1f;
     742:
     743:     if( o == 0 ) printf( "	jbr	L%d\n", lab );
     744:     else    if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
     745:     else {
     746:         switch( brcase ) {
     747:
     748:         case 'A':
     749:         case 'C':
     750:             plb = lbranches[ o-EQ ];
     751:             lab1f = getlab();
     752:             expand( brnode, FORCC, brcase=='C' ? "\tcmp\tAL,AR\n" : "\ttst\tAR\n" );
     753:             if( *plb != 0 )
     754:                 printf( ccbranches[*plb-EQ], lab);
     755:             if( *++plb != 0 )
     756:                 printf( ccbranches[*plb-EQ], lab1f);
     757:             expand( brnode, FORCC, brcase=='C' ? "\tcmp\tUL,UR\n" : "\ttst\tUR\n" );
     758:             printf( ccbranches[*++plb-EQ], lab);
     759:             deflab( lab1f );
     760:             reclaim( brnode, RNULL, 0 );
     761:             break;
     762:
     763:         default:
     764:             if( mode=='F' ) o = revrel[ o-EQ ];
     765:             printf( ccbranches[o-EQ], lab );
     766:             break;
     767:             }
     768:
     769:         brcase = 0;
     770:         brnode = 0;
     771:         }
     772:     }
     773:
     774: nextcook( p, cookie ) NODE *p; {
     775:     /* we have failed to match p with cookie; try another */
     776:     if( cookie == FORREW ) return( 0 );  /* hopeless! */
     777:     if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
     778:     if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
     779:     return( FORREW );
     780:     }
     781:
     782: lastchance( p, cook ) NODE *p; {
     783:     /* forget it! */
     784:     return(0);
     785:     }
     786:
     787: struct functbl {
     788:     int fop;
     789:     TWORD ftype;
     790:     char *func;
     791:     } opfunc[] = {
     792:     MUL,        LONG,   "lmul",
     793:     DIV,        LONG,   "ldiv",
     794:     MOD,        LONG,   "lrem",
     795:     ASG MUL,    LONG,   "almul",
     796:     ASG DIV,    LONG,   "aldiv",
     797:     ASG MOD,    LONG,   "alrem",
     798:     MUL,        ULONG,  "lmul",
     799:     DIV,        ULONG,  "uldiv",
     800:     MOD,        ULONG,  "ulrem",
     801:     ASG MUL,    ULONG,  "almul",
     802:     ASG DIV,    ULONG,  "auldiv",
     803:     ASG MOD,    ULONG,  "aulrem",
     804:     0,  0,  0 };
     805:
     806: hardops(p)  register NODE *p; {
     807:     /* change hard to do operators into function calls.
     808: 	   for pdp11 do long * / %	*/
     809:     register NODE *q;
     810:     register struct functbl *f;
     811:     register o;
     812:     register TWORD t;
     813:
     814:     o = p->in.op;
     815:     t = p->in.type;
     816:     if( t!=LONG && t!=ULONG ) return;
     817:
     818:     for( f=opfunc; f->fop; f++ ) {
     819:         if( o==f->fop && t==f->ftype ) goto convert;
     820:         }
     821:     return;
     822:
     823:     /* need address of left node for ASG OP */
     824:     /* WARNING - this won't work for long in a REG */
     825:     convert:
     826:     if( asgop( o ) ) {
     827:         switch( p->in.left->in.op ) {
     828:
     829:         case UNARY MUL: /* convert to address */
     830:             p->in.left->in.op = FREE;
     831:             p->in.left = p->in.left->in.left;
     832:             break;
     833:
     834:         case NAME:  /* convert to ICON pointer */
     835:             p->in.left->in.op = ICON;
     836:             p->in.left->in.type = INCREF( p->in.left->in.type );
     837:             break;
     838:
     839:         case OREG:  /* convert OREG to address */
     840:             p->in.left->in.op = REG;
     841:             p->in.left->in.type = INCREF( p->in.left->in.type );
     842:             if( p->in.left->tn.lval != 0 ) {
     843:                 q = talloc();
     844:                 q->in.op = PLUS;
     845:                 q->in.rall = NOPREF;
     846:                 q->in.type = p->in.left->in.type;
     847:                 q->in.left = p->in.left;
     848:                 q->in.right = talloc();
     849:
     850:                 q->in.right->in.op = ICON;
     851:                 q->in.right->in.rall = NOPREF;
     852:                 q->in.right->in.type = INT;
     853: #ifdef  FLEXNAMES
     854:                 q->in.right->in.name = "";
     855: #else
     856:                 q->in.right->in.name[0] = '\0';
     857: #endif
     858:                 q->in.right->tn.lval = p->in.left->tn.lval;
     859:                 q->in.right->tn.rval = 0;
     860:
     861:                 p->in.left->tn.lval = 0;
     862:                 p->in.left = q;
     863:                 }
     864:             break;
     865:
     866:         default:
     867:             cerror( "Bad address for hard ops" );
     868:             /* NO RETURN */
     869:
     870:             }
     871:         }
     872:
     873:     /* build comma op for args to function */
     874:     q = talloc();
     875:     q->in.op = CM;
     876:     q->in.rall = NOPREF;
     877:     q->in.type = INT;
     878:     q->in.left = p->in.left;
     879:     q->in.right = p->in.right;
     880:     p->in.op = CALL;
     881:     p->in.right = q;
     882:
     883:     /* put function name in left node of call */
     884:     p->in.left = q = talloc();
     885:     q->in.op = ICON;
     886:     q->in.rall = NOPREF;
     887:     q->in.type = INCREF( FTN + p->in.type );
     888: #ifndef FLEXNAMES
     889:     strcpy( q->in.name, f->func );
     890: #else
     891:     q->in.name = f->func;
     892: #endif
     893:     q->tn.lval = 0;
     894:     q->tn.rval = 0;
     895:
     896:     return;
     897:
     898:     }
     899:
     900: optim2( p ) register NODE *p; {
     901:     /* do local tree transformations and optimizations */
     902:
     903:     register NODE *r;
     904:
     905:     switch( p->in.op ) {
     906:
     907:     case AND:
     908:         /* commute L and R to eliminate compliments and constants */
     909:         if( p->in.left->in.op==ICON || p->in.left->in.op==COMPL ) {
     910:             r = p->in.left;
     911:             p->in.left = p->in.right;
     912:             p->in.right = r;
     913:             }
     914:     case ASG AND:
     915:         /* change meaning of AND to ~R&L - bic on pdp11 */
     916:         r = p->in.right;
     917:         if( r->in.op==ICON ) { /* compliment constant */
     918:             r->tn.lval = ~r->tn.lval;
     919:             }
     920:         else if( r->in.op==COMPL ) { /* ~~A => A */
     921:             r->in.op = FREE;
     922:             p->in.right = r->in.left;
     923:             }
     924:         else { /* insert complement node */
     925:             p->in.right = talloc();
     926:             p->in.right->in.op = COMPL;
     927:             p->in.right->in.rall = NOPREF;
     928:             p->in.right->in.type = r->in.type;
     929:             p->in.right->in.left = r;
     930:             p->in.right->in.right = NULL;
     931:             }
     932:         break;
     933:
     934:         }
     935:     }
     936:
     937: special( p, shape ) register NODE *p; {
     938:     /* special shape matching routine */
     939:
     940:     switch( shape ) {
     941:
     942:     case SSCON:
     943:         if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= -128 && p->tn.lval <=127 ) return( 1 );
     944:         break;
     945:
     946:     case SCCON:
     947:         if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= 0 && p->tn.lval <=32767 ) return( 1 );
     948:         break;
     949:
     950:     default:
     951:         cerror( "bad special shape" );
     952:
     953:         }
     954:
     955:     return( 0 );
     956:     }
     957:
     958: NODE * addroreg(l) NODE *l;
     959:                 /* OREG was built in clocal()
     960: 				 * for an auto or formal parameter
     961: 				 * now its address is being taken
     962: 				 * local code must unwind it
     963: 				 * back to PLUS/MINUS REG ICON
     964: 				 * according to local conventions
     965: 				 */
     966: {
     967:     cerror("address of OREG taken");
     968:     /*NOTREACHED*/
     969: }
     970:
     971: # ifndef ONEPASS
     972: main( argc, argv ) char *argv[]; {
     973:     return( mainp2( argc, argv ) );
     974:     }
     975: # endif
     976:
     977: myreader(p) register NODE *p; {
     978:     walkf( p, hardops );    /* convert ops to function calls */
     979:     canon( p );     /* expands r-vals for fileds */
     980:     walkf( p, optim2 );
     981:     toff = 0;  /* stack offset swindle */
     982:     }

#### Defined functions

acon defined in line 620; used 8 times

- in line 470, 500, 507, 519, 541, 552-557(2), 571

addroreg defined in line 958; never used
adrcon defined in line 462; never used
adrput defined in line 532; used 4 times

- in line 289, 579, 600, 606

callreg defined in line 395; never used
canaddr defined in line 399; used 1 times

- in /usr/src/lib/pcc/order.c line 457

cbgen defined in line 739; used 2 times

- in line 115, 125

conput defined in line 466; used 2 times

- in line 242, 249

eobl2 defined in line 17; never used
flshape defined in line 406; never used
gencall defined in line 649; used 2 times

- in line 646
- in /usr/src/lib/pcc/mac2defs.h line 51

genscall defined in line 644; never used
hardops defined in line 806; used 1 times

- in line 978

hopcode defined in line 46; never used
insput defined in line 482; never used
lastchance defined in line 782; never used
lineid defined in line 12; never used
main defined in line 972; never used
myreader defined in line 977; used 1 times

- in /usr/src/lib/pcc/mac2defs.h line 61

nextcook defined in line 774; never used
optim2 defined in line 900; used 2 times

- in line 980
- in /usr/src/lib/pcc/mac2defs.h line 62

popargs defined in line 671; used 1 times

- in line 667

rewfld defined in line 391; never used
rmove defined in line 349; never used
setregs defined in line 362; never used
shtemp defined in line 412; never used
shumul defined in line 447; used 7 times

- in line 402, 409
- in /usr/src/lib/pcc/mac2defs.h line 58
- in /usr/src/lib/pcc/order.c line 142, 479, 489, 649

special defined in line 937; never used
spsz defined in line 418; used 2 times

- in line 456
- in /usr/src/lib/pcc/order.c line 15

szty defined in line 377; used 3 times

- in line 546
- in /usr/src/lib/pcc/order.c line 127, 194

tlen defined in line 81; never used
upput defined in line 486; never used
where defined in line 8; never used
zzzcode defined in line 105; never used

#### Defined variables

brcase defined in line 101; used 5 times

- in line 134, 746, 752-757(2), 769

ccbranches defined in line 691; used 4 times

- in line 754-758(3), 765

ioptab defined in line 31; used 1 times

- in line 51

lbranches defined in line 719; used 1 times

- in line 750

opfunc defined in line 791; used 1 times

- in line 818

respref defined in line 354; never used
revrel declared in line 736; defined in line 734; used 1 times

- in line 764

rnames defined in line 62; used 9 times

- in line 117-119(2), 350(2), 474, 511, 520, 561, 572

rstatus defined in line 72; used 1 times

- in line 374

toff defined in line 103; used 7 times

- in line 229-236(4), 674-675(2), 981

#### Defined struct's

functbl defined in line 787; used 2 times

- in line 810(2)

hoptab defined in line 31; used 2 times

- in line 49(2)

#### Defined macros

BITMASK defined in line 7; used 4 times

- in line 256-257(2), 505, 550

putstr defined in line 3; used 11 times

- in line 474, 506-511(2), 551, 561, 568, 578, 601-605(2), 630, 637

Last modified: 1991-08-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2167 |