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
addroreg defined in line 958; never used
adrcon defined in line 462; never used
adrput defined in line 532; used 4 times
callreg defined in line 395; never used
canaddr defined in line 399; used 1 times
cbgen defined in line 739; used 2 times
conput defined in line 466; used 2 times
eobl2 defined in line 17; never used
flshape defined in line 406; never used
gencall defined in line 649; used 2 times
genscall defined in line 644; never used
hardops defined in line 806; used 1 times
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
nextcook defined in line 774; never used
optim2 defined in line 900; used 2 times
popargs defined in line 671; used 1 times
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
special defined in line 937; never used
spsz defined in line 418; used 2 times
szty defined in line 377; used 3 times
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
ccbranches defined in line 691; used 4 times
ioptab defined in line 31; used 1 times
  • in line 51
lbranches defined in line 719; used 1 times
opfunc defined in line 791; used 1 times
respref defined in line 354; never used
revrel declared in line 736; defined in line 734; used 1 times
rnames defined in line 62; used 9 times
rstatus defined in line 72; used 1 times
toff defined in line 103; used 7 times

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
putstr defined in line 3; used 11 times
Last modified: 1991-08-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4071
Valid CSS Valid XHTML 1.0 Strict