1: #
   2: /*
   3:  *  C compiler
   4:  */
   5: 
   6: #include "c1.h"
   7: 
   8: max(a, b)
   9: {
  10:     if (a>b)
  11:         return(a);
  12:     return(b);
  13: }
  14: 
  15: degree(at)
  16: struct tnode *at;
  17: {
  18:     register struct tnode *t, *t1;
  19: 
  20:     if ((t=at)==0 || t->op==0)
  21:         return(0);
  22:     if (t->op == CON)
  23:         return(-3);
  24:     if (t->op == AMPER)
  25:         return(-2);
  26:     if (t->op==ITOL) {
  27:         if ((t1 = isconstant(t)) && (t1->value>=0 || t1->type==UNSIGN))
  28:             return(-2);
  29:         if ((t1=t->tr1)->type==UNSIGN && opdope[t1->op]&LEAF)
  30:             return(-1);
  31:     }
  32:     if ((opdope[t->op] & LEAF) != 0) {
  33:         if (t->type==CHAR || t->type==FLOAT)
  34:             return(1);
  35:         return(0);
  36:     }
  37:     return(t->degree);
  38: }
  39: 
  40: pname(ap, flag)
  41: struct tnode *ap;
  42: {
  43:     register i;
  44:     register struct tnode *p;
  45:     struct { int intx[2]; };
  46: 
  47:     p = ap;
  48: loop:
  49:     switch(p->op) {
  50: 
  51:     case LCON:
  52:         printf("$%o", flag>10? p->lvalue.intx[1]:p->lvalue.intx[0]);
  53:         return;
  54: 
  55:     case SFCON:
  56:     case CON:
  57:         printf("$");
  58:         psoct(p->value);
  59:         return;
  60: 
  61:     case FCON:
  62:         printf("L%d", (p->value>0? p->value: -p->value));
  63:         return;
  64: 
  65:     case NAME:
  66:         i = p->offset;
  67:         if (flag>10)
  68:             i =+ 2;
  69:         if (i) {
  70:             psoct(i);
  71:             if (p->class!=OFFS)
  72:                 putchar('+');
  73:             if (p->class==REG)
  74:                 regerr();
  75:         }
  76:         switch(p->class) {
  77: 
  78:         case SOFFS:
  79:         case XOFFS:
  80:             pbase(p);
  81: 
  82:         case OFFS:
  83:             printf("(r%d)", p->regno);
  84:             return;
  85: 
  86:         case EXTERN:
  87:         case STATIC:
  88:             pbase(p);
  89:             return;
  90: 
  91:         case REG:
  92:             printf("r%d", p->nloc);
  93:             return;
  94: 
  95:         }
  96:         error("Compiler error: pname");
  97:         return;
  98: 
  99:     case AMPER:
 100:         putchar('$');
 101:         p = p->tr1;
 102:         if (p->op==NAME && p->class==REG)
 103:             regerr();
 104:         goto loop;
 105: 
 106:     case AUTOI:
 107:         printf("(r%d)%c", p->nloc, flag==1?0:'+');
 108:         return;
 109: 
 110:     case AUTOD:
 111:         printf("%c(r%d)", flag==2?0:'-', p->nloc);
 112:         return;
 113: 
 114:     case STAR:
 115:         p = p->tr1;
 116:         putchar('*');
 117:         goto loop;
 118: 
 119:     }
 120:     error("pname called illegally");
 121: }
 122: 
 123: regerr()
 124: {
 125:     error("Illegal use of register");
 126: }
 127: 
 128: pbase(ap)
 129: struct tnode *ap;
 130: {
 131:     register struct tnode *p;
 132: 
 133:     p = ap;
 134:     if (p->class==SOFFS || p->class==STATIC)
 135:         printf("L%d", p->nloc);
 136:     else
 137:         printf("%.8s", &(p->nloc));
 138: }
 139: 
 140: xdcalc(ap, nrleft)
 141: struct tnode *ap;
 142: {
 143:     register struct tnode *p;
 144:     register d;
 145: 
 146:     p = ap;
 147:     d = dcalc(p, nrleft);
 148:     if (d<20 && p->type==CHAR) {
 149:         if (nrleft>=1)
 150:             d = 20;
 151:         else
 152:             d = 24;
 153:     }
 154:     return(d);
 155: }
 156: 
 157: dcalc(ap, nrleft)
 158: struct tnode *ap;
 159: {
 160:     register struct tnode *p, *p1;
 161: 
 162:     if ((p=ap)==0)
 163:         return(0);
 164:     switch (p->op) {
 165: 
 166:     case NAME:
 167:         if (p->class==REG)
 168:             return(9);
 169: 
 170:     case AMPER:
 171:     case FCON:
 172:     case LCON:
 173:     case AUTOI:
 174:     case AUTOD:
 175:         return(12);
 176: 
 177:     case CON:
 178:     case SFCON:
 179:         if (p->value==0)
 180:             return(4);
 181:         if (p->value==1)
 182:             return(5);
 183:         if (p->value > 0)
 184:             return(8);
 185:         return(12);
 186: 
 187:     case STAR:
 188:         p1 = p->tr1;
 189:         if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD)
 190:             if (p->type!=LONG)
 191:                 return(12);
 192:     }
 193:     if (p->type==LONG)
 194:         nrleft--;
 195:     return(p->degree <= nrleft? 20: 24);
 196: }
 197: 
 198: notcompat(ap, ast, op)
 199: struct tnode *ap;
 200: {
 201:     register at, st;
 202:     register struct tnode *p;
 203: 
 204:     p = ap;
 205:     at = p->type;
 206:     st = ast;
 207:     if (st==0)      /* word, byte */
 208:         return(at!=CHAR && at!=INT && at!=UNSIGN && at<PTR);
 209:     if (st==1)      /* word */
 210:         return(at!=INT && at!=UNSIGN && at<PTR);
 211:     if (st==9 && (at&XTYPE))
 212:         return(0);
 213:     st =- 2;
 214:     if ((at&(~(TYPE+XTYPE))) != 0)
 215:         at = 020;
 216:     if ((at&(~TYPE)) != 0)
 217:         at = at&TYPE | 020;
 218:     if (st==FLOAT && at==DOUBLE)
 219:         at = FLOAT;
 220:     if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR)
 221:         return(0);
 222:     return(st != at);
 223: }
 224: 
 225: prins(op, c, itable)
 226: struct instab *itable;
 227: {
 228:     register struct instab *insp;
 229:     register char *ip;
 230: 
 231:     for (insp=itable; insp->op != 0; insp++) {
 232:         if (insp->op == op) {
 233:             ip = c? insp->str2: insp->str1;
 234:             if (ip==0)
 235:                 break;
 236:             printf("%s", ip);
 237:             return;
 238:         }
 239:     }
 240:     error("No match' for op %d", op);
 241: }
 242: 
 243: collcon(ap)
 244: struct tnode *ap;
 245: {
 246:     register op;
 247:     register struct tnode *p;
 248: 
 249:     p = ap;
 250:     if (p->op==STAR) {
 251:         if (p->type==LONG+PTR) /* avoid *x(r); *x+2(r) */
 252:             return(0);
 253:         p = p->tr1;
 254:     }
 255:     if (p->op==PLUS) {
 256:         op = p->tr2->op;
 257:         if (op==CON || op==AMPER)
 258:             return(1);
 259:     }
 260:     return(0);
 261: }
 262: 
 263: isfloat(at)
 264: struct tnode *at;
 265: {
 266:     register struct tnode *t;
 267: 
 268:     t = at;
 269:     if ((opdope[t->op]&RELAT)!=0)
 270:         t = t->tr1;
 271:     if (t->type==FLOAT || t->type==DOUBLE) {
 272:         nfloat = 1;
 273:         return('f');
 274:     }
 275:     return(0);
 276: }
 277: 
 278: oddreg(t, areg)
 279: struct tnode *t;
 280: {
 281:     register reg;
 282: 
 283:     reg = areg;
 284:     if (!isfloat(t)) {
 285:         if (opdope[t->op]&RELAT) {
 286:             if (t->tr1->type==LONG)
 287:                 return((reg+1) & ~01);
 288:             return(reg);
 289:         }
 290:         switch(t->op) {
 291:         case LLSHIFT:
 292:         case ASLSHL:
 293:             return((reg+1)&~01);
 294: 
 295:         case DIVIDE:
 296:         case MOD:
 297:         case ASDIV:
 298:         case ASMOD:
 299:         case PTOI:
 300:         case ULSH:
 301:         case ASULSH:
 302:             reg++;
 303: 
 304:         case TIMES:
 305:         case ASTIMES:
 306:             return(reg|1);
 307:         }
 308:     }
 309:     return(reg);
 310: }
 311: 
 312: arlength(t)
 313: {
 314:     if (t>=PTR)
 315:         return(2);
 316:     switch(t) {
 317: 
 318:     case INT:
 319:     case CHAR:
 320:     case UNSIGN:
 321:         return(2);
 322: 
 323:     case LONG:
 324:         return(4);
 325: 
 326:     case FLOAT:
 327:     case DOUBLE:
 328:         return(8);
 329:     }
 330:     return(1024);
 331: }
 332: 
 333: /*
 334:  * Strings for switch code.
 335:  */
 336: 
 337: char    dirsw[] {"\
 338: cmp	r0,$%o\n\
 339: jhi	L%d\n\
 340: asl	r0\n\
 341: jmp	*L%d(r0)\n\
 342: .data\n\
 343: L%d:\
 344: " };
 345: 
 346: char    hashsw[] {"\
 347: mov	r0,r1\n\
 348: clr	r0\n\
 349: div	$%o,r0\n\
 350: asl	r1\n\
 351: jmp	*L%d(r1)\n\
 352: .data\n\
 353: L%d:\
 354: "};
 355: 
 356: /*
 357:  * If the unsigned casts below won't compile,
 358:  * try using the calls to lrem and ldiv.
 359:  */
 360: 
 361: pswitch(afp, alp, deflab)
 362: struct swtab *afp, *alp;
 363: {
 364:     int ncase, i, j, tabs, worst, best, range;
 365:     register struct swtab *swp, *fp, *lp;
 366:     int *poctab;
 367: 
 368:     fp = afp;
 369:     lp = alp;
 370:     if (fp==lp) {
 371:         printf("jbr	L%d\n", deflab);
 372:         return;
 373:     }
 374:     isn++;
 375:     if (sort(fp, lp))
 376:         return;
 377:     ncase = lp-fp;
 378:     lp--;
 379:     range = lp->swval - fp->swval;
 380:     /* direct switch */
 381:     if (range>0 && range <= 3*ncase) {
 382:         if (fp->swval)
 383:             printf("sub	$%o,r0\n", fp->swval);
 384:         printf(dirsw, range, deflab, isn, isn);
 385:         isn++;
 386:         for (i=fp->swval; ; i++) {
 387:             if (i==fp->swval) {
 388:                 printf("L%d\n", fp->swlab);
 389:                 if (fp==lp)
 390:                     break;
 391:                 fp++;
 392:             } else
 393:                 printf("L%d\n", deflab);
 394:         }
 395:         printf(".text\n");
 396:         return;
 397:     }
 398:     /* simple switch */
 399:     if (ncase<10) {
 400:         for (fp = afp; fp<=lp; fp++)
 401:             breq(fp->swval, fp->swlab);
 402:         printf("jbr	L%d\n", deflab);
 403:         return;
 404:     }
 405:     /* hash switch */
 406:     best = 077777;
 407:     poctab = getblk(((ncase+2)/2) * sizeof(*poctab));
 408:     for (i=ncase/4; i<=ncase/2; i++) {
 409:         for (j=0; j<i; j++)
 410:             poctab[j] = 0;
 411:         for (swp=fp; swp<=lp; swp++)
 412:             /* lrem(0, swp->swval, i) */
 413:             poctab[(unsigned)swp->swval%i]++;
 414:         worst = 0;
 415:         for (j=0; j<i; j++)
 416:             if (poctab[j]>worst)
 417:                 worst = poctab[j];
 418:         if (i*worst < best) {
 419:             tabs = i;
 420:             best = i*worst;
 421:         }
 422:     }
 423:     i = isn++;
 424:     printf(hashsw, tabs, i, i);
 425:     isn++;
 426:     for (i=0; i<tabs; i++)
 427:         printf("L%d\n", isn+i);
 428:     printf(".text\n");
 429:     for (i=0; i<tabs; i++) {
 430:         printf("L%d:", isn++);
 431:         for (swp=fp; swp<=lp; swp++) {
 432:             /* lrem(0, swp->swval, tabs) */
 433:             if ((unsigned)swp->swval%tabs == i) {
 434:                 /* ldiv(0, swp->swval, tabs) */
 435:                 breq((unsigned)swp->swval/tabs, swp->swlab);
 436:             }
 437:         }
 438:         printf("jbr	L%d\n", deflab);
 439:     }
 440: }
 441: 
 442: breq(v, l)
 443: {
 444:     if (v==0)
 445:         printf("tst	r0\n");
 446:     else
 447:         printf("cmp	r0,$%o\n", v);
 448:     printf("jeq	L%d\n", l);
 449: }
 450: 
 451: sort(afp, alp)
 452: struct swtab *afp, *alp;
 453: {
 454:     register struct swtab *cp, *fp, *lp;
 455:     int intch, t;
 456: 
 457:     fp = afp;
 458:     lp = alp;
 459:     while (fp < --lp) {
 460:         intch = 0;
 461:         for (cp=fp; cp<lp; cp++) {
 462:             if (cp->swval == cp[1].swval) {
 463:                 error("Duplicate case (%d)", cp->swval);
 464:                 return(1);
 465:             }
 466:             if (cp->swval > cp[1].swval) {
 467:                 intch++;
 468:                 t = cp->swval;
 469:                 cp->swval = cp[1].swval;
 470:                 cp[1].swval = t;
 471:                 t = cp->swlab;
 472:                 cp->swlab = cp[1].swlab;
 473:                 cp[1].swlab = t;
 474:             }
 475:         }
 476:         if (intch==0)
 477:             break;
 478:     }
 479:     return(0);
 480: }
 481: 
 482: ispow2(atree)
 483: {
 484:     register int d;
 485:     register struct tnode *tree;
 486: 
 487:     tree = atree;
 488:     if (!isfloat(tree) && tree->tr2->op==CON) {
 489:         d = tree->tr2->value;
 490:         if (d>1 && (d&(d-1))==0)
 491:             return(d);
 492:     }
 493:     return(0);
 494: }
 495: 
 496: pow2(atree)
 497: struct tnode *atree;
 498: {
 499:     register int d, i;
 500:     register struct tnode *tree;
 501: 
 502:     tree = atree;
 503:     if (d = ispow2(tree)) {
 504:         for (i=0; (d=>>1)!=0; i++);
 505:         tree->tr2->value = i;
 506:         switch (tree->op) {
 507: 
 508:         case TIMES:
 509:             tree->op = LSHIFT;
 510:             break;
 511: 
 512:         case ASTIMES:
 513:             tree->op = ASLSH;
 514:             break;
 515: 
 516:         case DIVIDE:
 517:             tree->op = ULSH;
 518:             tree->tr2->value = -i;
 519:             break;
 520: 
 521:         case ASDIV:
 522:             tree->op = ASULSH;
 523:             tree->tr2->value = -i;
 524:             break;
 525: 
 526:         case MOD:
 527:             tree->op = AND;
 528:             tree->tr2->value = (1<<i)-1;
 529:             break;
 530: 
 531:         case ASMOD:
 532:             tree->op = ASAND;
 533:             tree->tr2->value = (1<<i)-1;
 534:             break;
 535: 
 536:         default:
 537:             error("pow2 botch");
 538:         }
 539:         tree = optim(tree);
 540:     }
 541:     return(tree);
 542: }
 543: 
 544: cbranch(atree, albl, cond, areg)
 545: struct tnode *atree;
 546: {
 547:     int l1, op;
 548:     register lbl, reg;
 549:     register struct tnode *tree;
 550: 
 551:     lbl = albl;
 552:     reg = areg;
 553: again:
 554:     if ((tree=atree)==0)
 555:         return;
 556:     switch(tree->op) {
 557: 
 558:     case LOGAND:
 559:         if (cond) {
 560:             cbranch(tree->tr1, l1=isn++, 0, reg);
 561:             cbranch(tree->tr2, lbl, 1, reg);
 562:             label(l1);
 563:         } else {
 564:             cbranch(tree->tr1, lbl, 0, reg);
 565:             cbranch(tree->tr2, lbl, 0, reg);
 566:         }
 567:         return;
 568: 
 569:     case LOGOR:
 570:         if (cond) {
 571:             cbranch(tree->tr1, lbl, 1, reg);
 572:             cbranch(tree->tr2, lbl, 1, reg);
 573:         } else {
 574:             cbranch(tree->tr1, l1=isn++, 1, reg);
 575:             cbranch(tree->tr2, lbl, 0, reg);
 576:             label(l1);
 577:         }
 578:         return;
 579: 
 580:     case EXCLA:
 581:         cbranch(tree->tr1, lbl, !cond, reg);
 582:         return;
 583: 
 584:     case SEQNC:
 585:         rcexpr(tree->tr1, efftab, reg);
 586:         atree = tree->tr2;
 587:         goto again;
 588: 
 589:     case ITOL:
 590:         tree = tree->tr1;
 591:         break;
 592:     }
 593:     op = tree->op;
 594:     if (opdope[op]&RELAT
 595:      && tree->tr1->op==ITOL && tree->tr2->op==ITOL) {
 596:         tree->tr1 = tree->tr1->tr1;
 597:         tree->tr2 = tree->tr2->tr1;
 598:         if (op>=LESSEQ && op<=GREAT
 599:          && (tree->tr1->type==UNSIGN || tree->tr2->type==UNSIGN))
 600:             tree->op = op = op+LESSEQP-LESSEQ;
 601:     }
 602:     if (tree->type==LONG
 603:       || opdope[op]&RELAT&&tree->tr1->type==LONG) {
 604:         longrel(tree, lbl, cond, reg);
 605:         return;
 606:     }
 607:     rcexpr(tree, cctab, reg);
 608:     op = tree->op;
 609:     if ((opdope[op]&RELAT)==0)
 610:         op = NEQUAL;
 611:     else {
 612:         l1 = tree->tr2->op;
 613:         if ((l1==CON || l1==SFCON) && tree->tr2->value==0)
 614:             op =+ 200;      /* special for ptr tests */
 615:         else
 616:             op = maprel[op-EQUAL];
 617:     }
 618:     if (isfloat(tree))
 619:         printf("cfcc\n");
 620:     branch(lbl, op, !cond);
 621: }
 622: 
 623: branch(lbl, aop, c)
 624: {
 625:     register op;
 626: 
 627:     if(op=aop)
 628:         prins(op, c, branchtab);
 629:     else
 630:         printf("jbr");
 631:     printf("\tL%d\n", lbl);
 632: }
 633: 
 634: longrel(atree, lbl, cond, reg)
 635: struct tnode *atree;
 636: {
 637:     int xl1, xl2, xo, xz;
 638:     register int op, isrel;
 639:     register struct tnode *tree;
 640: 
 641:     if (reg&01)
 642:         reg++;
 643:     reorder(&atree, cctab, reg);
 644:     tree = atree;
 645:     isrel = 0;
 646:     if (opdope[tree->op]&RELAT) {
 647:         isrel++;
 648:         op = tree->op;
 649:     } else
 650:         op = NEQUAL;
 651:     if (!cond)
 652:         op = notrel[op-EQUAL];
 653:     xl1 = xlab1;
 654:     xl2 = xlab2;
 655:     xo = xop;
 656:     xlab1 = lbl;
 657:     xlab2 = 0;
 658:     xop = op;
 659:     xz = xzero;
 660:     xzero = !isrel || tree->tr2->op==ITOL && tree->tr2->tr1->op==CON
 661:         && tree->tr2->tr1->value==0;
 662:     if (tree->op==ANDN) {
 663:         tree->op = TAND;
 664:         tree->tr2 = optim(tnode(COMPL, LONG, tree->tr2));
 665:     }
 666:     if (cexpr(tree, cctab, reg) < 0) {
 667:         reg = rcexpr(tree, regtab, reg);
 668:         printf("ashc	$0,r%d\n", reg);
 669:         branch(xlab1, op, 0);
 670:     }
 671:     xlab1 = xl1;
 672:     xlab2 = xl2;
 673:     xop = xo;
 674:     xzero = xz;
 675: }
 676: 
 677: /*
 678:  * Tables for finding out how best to do long comparisons.
 679:  * First dimen is whether or not the comparison is with 0.
 680:  * Second is which test: e.g. a>b->
 681:  *	cmp	a,b
 682:  *	bgt	YES		(first)
 683:  *	blt	NO		(second)
 684:  *	cmp	a+2,b+2
 685:  *	bhi	YES		(third)
 686:  *  NO:	...
 687:  * Note some tests may not be needed.
 688:  */
 689: char    lrtab[2][3][6] {
 690:     0,  NEQUAL, LESS,   LESS,   GREAT,  GREAT,
 691:     NEQUAL, 0,  GREAT,  GREAT,  LESS,   LESS,
 692:     EQUAL,  NEQUAL, LESSEQP,LESSP,  GREATQP,GREATP,
 693: 
 694:     0,  NEQUAL, LESS,   LESS,   GREATEQ,GREAT,
 695:     NEQUAL, 0,  GREAT,  0,  0,  LESS,
 696:     EQUAL,  NEQUAL, EQUAL,  0,  0,  NEQUAL,
 697: };
 698: 
 699: xlongrel(f)
 700: {
 701:     register int op, bno;
 702: 
 703:     op = xop;
 704:     if (f==0) {
 705:         if (bno = lrtab[xzero][0][op-EQUAL])
 706:             branch(xlab1, bno, 0);
 707:         if (bno = lrtab[xzero][1][op-EQUAL]) {
 708:             xlab2 = isn++;
 709:             branch(xlab2, bno, 0);
 710:         }
 711:         if (lrtab[xzero][2][op-EQUAL]==0)
 712:             return(1);
 713:     } else {
 714:         branch(xlab1, lrtab[xzero][2][op-EQUAL], 0);
 715:         if (xlab2)
 716:             label(xlab2);
 717:     }
 718:     return(0);
 719: }
 720: 
 721: label(l)
 722: {
 723:     printf("L%d:", l);
 724: }
 725: 
 726: popstk(a)
 727: {
 728:     switch(a) {
 729: 
 730:     case 0:
 731:         return;
 732: 
 733:     case 2:
 734:         printf("tst	(sp)+\n");
 735:         return;
 736: 
 737:     case 4:
 738:         printf("cmp	(sp)+,(sp)+\n");
 739:         return;
 740:     }
 741:     printf("add	$%o,sp\n", a);
 742: }
 743: 
 744: error(s, p1, p2, p3, p4, p5, p6)
 745: {
 746: 
 747:     nerror++;
 748:     fprintf(stderr, "%d: ", line);
 749:     fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
 750:     putc('\n', stderr);
 751: }
 752: 
 753: psoct(an)
 754: {
 755:     register int n, sign;
 756: 
 757:     sign = 0;
 758:     if ((n = an) < 0) {
 759:         n = -n;
 760:         sign = '-';
 761:     }
 762:     printf("%c%o", sign, n);
 763: }
 764: 
 765: /*
 766:  * Read in an intermediate file.
 767:  */
 768: #define STKS    100
 769: getree()
 770: {
 771:     struct tnode *expstack[STKS];
 772:     register struct tnode **sp;
 773:     register t, op;
 774:     static char s[9];
 775:     struct swtab *swp;
 776:     double atof();
 777:     char numbuf[64];
 778:     struct tname *np;
 779:     struct xtname *xnp;
 780:     struct ftconst *fp;
 781:     struct lconst *lp;
 782:     struct fasgn *sap;
 783:     int lbl, cond, lbl2, lbl3;
 784: 
 785:     curbase = funcbase;
 786:     sp = expstack;
 787:     for (;;) {
 788:         if (sp >= &expstack[STKS])
 789:             error("Stack overflow botch");
 790:         op = geti();
 791:         if ((op&0177400) != 0177000) {
 792:             error("Intermediate file error");
 793:             exit(1);
 794:         }
 795:         lbl = 0;
 796:         switch(op =& 0377) {
 797: 
 798:     case SINIT:
 799:         printf("%o\n", geti());
 800:         break;
 801: 
 802:     case EOFC:
 803:         return;
 804: 
 805:     case BDATA:
 806:         if (geti() == 1) {
 807:             printf(".byte ");
 808:             for (;;)  {
 809:                 printf("%o", geti());
 810:                 if (geti() != 1)
 811:                     break;
 812:                 printf(",");
 813:             }
 814:             printf("\n");
 815:         }
 816:         break;
 817: 
 818:     case PROG:
 819:         printf(".text\n");
 820:         break;
 821: 
 822:     case DATA:
 823:         printf(".data\n");
 824:         break;
 825: 
 826:     case BSS:
 827:         printf(".bss\n");
 828:         break;
 829: 
 830:     case SYMDEF:
 831:         outname(s);
 832:         printf(".globl%s%.8s\n", s[0]?"	":"", s);
 833:         sfuncr.nloc = 0;
 834:         break;
 835: 
 836:     case RETRN:
 837:         printf("jmp	cret\n");
 838:         break;
 839: 
 840:     case CSPACE:
 841:         t = outname(s);
 842:         printf(".comm	%.8s,%o\n", t, geti());
 843:         break;
 844: 
 845:     case SSPACE:
 846:         printf(".=.+%o\n", (t=geti()));
 847:         totspace += (unsigned)t;
 848:         break;
 849: 
 850:     case EVEN:
 851:         printf(".even\n");
 852:         break;
 853: 
 854:     case SAVE:
 855:         printf("jsr	r5,csv\n");
 856:         break;
 857: 
 858:     case SETSTK:
 859:         t = geti()-6;
 860:         if (t==2)
 861:             printf("tst	-(sp)\n");
 862:         else if (t != 0)
 863:             printf("sub	$%o,sp\n", t);
 864:         break;
 865: 
 866:     case PROFIL:
 867:         t = geti();
 868:         printf("mov	$L%d,r0\njsr	pc,mcount\n", t);
 869:         printf(".bss\nL%d:.=.+2\n.text\n", t);
 870:         break;
 871: 
 872:     case SNAME:
 873:         t = outname(s);
 874:         printf("~%s=L%d\n", t+1, geti());
 875:         break;
 876: 
 877:     case ANAME:
 878:         t = outname(s);
 879:         printf("~%s=%o\n", t+1, geti());
 880:         break;
 881: 
 882:     case RNAME:
 883:         t = outname(s);
 884:         printf("~%s=r%d\n", t+1, geti());
 885:         break;
 886: 
 887:     case SWIT:
 888:         t = geti();
 889:         line = geti();
 890:         curbase = funcbase;
 891:         while(swp=getblk(sizeof(*swp)), swp->swlab = geti())
 892:             swp->swval = geti();
 893:         pswitch(funcbase, swp, t);
 894:         break;
 895: 
 896:     case C3BRANCH:      /* for fortran [sic] */
 897:         lbl = geti();
 898:         lbl2 = geti();
 899:         lbl3 = geti();
 900:         goto xpr;
 901: 
 902:     case CBRANCH:
 903:         lbl = geti();
 904:         cond = geti();
 905: 
 906:     case EXPR:
 907:     xpr:
 908:         line = geti();
 909:         if (sp != &expstack[1]) {
 910:             error("Expression input botch");
 911:             exit(1);
 912:         }
 913:         nstack = 0;
 914:         *sp = optim(*--sp);
 915:         if (op==CBRANCH)
 916:             cbranch(*sp, lbl, cond, 0);
 917:         else if (op==EXPR)
 918:             rcexpr(*sp, efftab, 0);
 919:         else {
 920:             if ((*sp)->type==LONG) {
 921:                 rcexpr(tnode(RFORCE, (*sp)->type, *sp), efftab, 0);
 922:                 printf("ashc	$0,r0\n");
 923:             } else {
 924:                 rcexpr(*sp, cctab, 0);
 925:                 if (isfloat(*sp))
 926:                     printf("cfcc\n");
 927:             }
 928:             printf("jgt	L%d\n", lbl3);
 929:             printf("jlt	L%d\njbr	L%d\n", lbl, lbl2);
 930:         }
 931:         curbase = funcbase;
 932:         break;
 933: 
 934:     case NAME:
 935:         t = geti();
 936:         if (t==EXTERN) {
 937:             np = getblk(sizeof(*xnp));
 938:             np->type = geti();
 939:             outname(np->name);
 940:         } else {
 941:             np = getblk(sizeof(*np));
 942:             np->type = geti();
 943:             np->nloc = geti();
 944:         }
 945:         np->op = NAME;
 946:         np->class = t;
 947:         np->regno = 0;
 948:         np->offset = 0;
 949:         *sp++ = np;
 950:         break;
 951: 
 952:     case CON:
 953:         t = geti();
 954:         *sp++ = tconst(geti(), t);
 955:         break;
 956: 
 957:     case LCON:
 958:         geti(); /* ignore type, assume long */
 959:         t = geti();
 960:         op = geti();
 961:         if (t==0 && op>=0 || t == -1 && op<0) {
 962:             *sp++ = tnode(ITOL, LONG, tconst(op, INT));
 963:             break;
 964:         }
 965:         lp = getblk(sizeof(*lp));
 966:         lp->op = LCON;
 967:         lp->type = LONG;
 968:         lp->lvalue = ((long)t<<16) + (unsigned)op;  /* nonportable */
 969:         *sp++ = lp;
 970:         break;
 971: 
 972:     case FCON:
 973:         t = geti();
 974:         outname(numbuf);
 975:         fp = getblk(sizeof(*fp));
 976:         fp->op = FCON;
 977:         fp->type = t;
 978:         fp->value = isn++;
 979:         fp->fvalue = atof(numbuf);
 980:         *sp++ = fp;
 981:         break;
 982: 
 983:     case FSEL:
 984:         *sp = tnode(FSEL, geti(), *--sp, NULL);
 985:         t = geti();
 986:         (*sp++)->tr2 = tnode(COMMA, INT, tconst(geti(), INT), tconst(t, INT));
 987:         break;
 988: 
 989:     case STRASG:
 990:         sap = getblk(sizeof(*sap));
 991:         sap->op = STRASG;
 992:         sap->type = geti();
 993:         sap->mask = geti();
 994:         sap->tr1 = *--sp;
 995:         sap->tr2 = NULL;
 996:         *sp++ = sap;
 997:         break;
 998: 
 999:     case NULLOP:
1000:         *sp++ = tnode(0, 0, NULL, NULL);
1001:         break;
1002: 
1003:     case LABEL:
1004:         label(geti());
1005:         break;
1006: 
1007:     case NLABEL:
1008:         t = outname(s);
1009:         printf("%.8s:\n", t, t);
1010:         break;
1011: 
1012:     case RLABEL:
1013:         t = outname(s);
1014:         printf("%.8s:\n~~%s:\n", t, t+1);
1015:         break;
1016: 
1017:     case BRANCH:
1018:         branch(geti(), 0);
1019:         break;
1020: 
1021:     case SETREG:
1022:         nreg = geti()-1;
1023:         break;
1024: 
1025:     default:
1026:         if (opdope[op]&BINARY) {
1027:             if (sp < &expstack[1]) {
1028:                 error("Binary expression botch");
1029:                 exit(1);
1030:             }
1031:             t = *--sp;
1032:             *sp++ = tnode(op, geti(), *--sp, t);
1033:         } else
1034:             sp[-1] = tnode(op, geti(), sp[-1]);
1035:         break;
1036:     }
1037:     }
1038: }
1039: 
1040: geti()
1041: {
1042:     register i;
1043: 
1044:     i = getchar();
1045:     i += getchar()<<8;
1046:     return(i);
1047: }
1048: 
1049: outname(s)
1050: {
1051:     register char *p, c;
1052:     register n;
1053: 
1054:     p = s;
1055:     n = 0;
1056:     while (c = getchar()) {
1057:         *p++ = c;
1058:         n++;
1059:     }
1060:     do {
1061:         *p++ = 0;
1062:     } while (n++ < 8);
1063:     return(s);
1064: }
1065: 
1066: strasg(atp)
1067: struct fasgn *atp;
1068: {
1069:     register struct tnode *tp;
1070:     register nwords, i;
1071: 
1072:     nwords = atp->mask/sizeof(int);
1073:     tp = atp->tr1;
1074:     if (tp->op != ASSIGN) {
1075:         if (tp->op==RFORCE) {   /* function return */
1076:             if (sfuncr.nloc==0) {
1077:                 sfuncr.nloc = isn++;
1078:                 printf(".bss\nL%d:.=.+%o\n.text\n", sfuncr.nloc, nwords*sizeof(int));
1079:             }
1080:             atp->tr1 = tnode(ASSIGN, STRUCT, &sfuncr, tp->tr1);
1081:             strasg(atp);
1082:             printf("mov	$L%d,r0\n", sfuncr.nloc);
1083:             return;
1084:         }
1085:         if (tp->op==CALL) {
1086:             rcexpr(tp, efftab, 0);
1087:             return;
1088:         }
1089:         error("Illegal structure operation");
1090:         return;
1091:     }
1092:     tp->tr2 = strfunc(tp->tr2);
1093:     if (nwords==1)
1094:         setype(tp, INT);
1095:     else if (nwords==sizeof(int))
1096:         setype(tp, LONG);
1097:     else {
1098:         if (tp->tr1->op!=NAME && tp->tr1->op!=STAR
1099:          || tp->tr2->op!=NAME && tp->tr2->op!=STAR) {
1100:             error("unimplemented structure assignment");
1101:             return;
1102:         }
1103:         tp->tr1 = tnode(AMPER, STRUCT+PTR, tp->tr1);
1104:         tp->tr2 = tnode(AMPER, STRUCT+PTR, tp->tr2);
1105:         tp->op = STRSET;
1106:         tp->type = STRUCT+PTR;
1107:         tp = optim(tp);
1108:         rcexpr(tp, efftab, 0);
1109:         if (nwords < 7) {
1110:             for (i=0; i<nwords; i++)
1111:                 printf("mov	(r1)+,(r0)+\n");
1112:             return;
1113:         }
1114:         if (nreg<=1)
1115:             printf("mov	r2,-(sp)\n");
1116:         printf("mov	$%o,r2\n", nwords);
1117:         printf("L%d:mov	(r1)+,(r0)+\ndec\tr2\njne\tL%d\n", isn, isn);
1118:         isn++;
1119:         if (nreg<=1)
1120:             printf("mov	(sp)+,r2\n");
1121:         return;
1122:     }
1123:     rcexpr(tp, efftab, 0);
1124: }
1125: 
1126: setype(p, t)
1127: register struct tnode *p;
1128: register t;
1129: {
1130: 
1131:     for (;; p = p->tr1) {
1132:         p->type = t;
1133:         if (p->op==AMPER)
1134:             t = decref(t);
1135:         else if (p->op==STAR)
1136:             t = incref(t);
1137:         else if (p->op==ASSIGN)
1138:             setype(p->tr2, t);
1139:         else if (p->op!=PLUS)
1140:             break;
1141:     }
1142: }
1143: 
1144: /*
1145:  * Reduce the degree-of-reference by one.
1146:  * e.g. turn "ptr-to-int" into "int".
1147:  */
1148: decref(at)
1149: {
1150:     register t;
1151: 
1152:     t = at;
1153:     if ((t & ~TYPE) == 0) {
1154:         error("Illegal indirection");
1155:         return(t);
1156:     }
1157:     return((t>>TYLEN) & ~TYPE | t&TYPE);
1158: }
1159: 
1160: /*
1161:  * Increase the degree of reference by
1162:  * one; e.g. turn "int" to "ptr-to-int".
1163:  */
1164: incref(t)
1165: {
1166:     return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
1167: }

Defined functions

arlength defined in line 312; used 1 times
branch defined in line 623; used 6 times
breq defined in line 442; used 2 times
cbranch defined in line 544; used 10 times
collcon defined in line 243; used 2 times
dcalc defined in line 157; used 7 times
decref defined in line 1148; used 1 times
degree defined in line 15; used 22 times
error defined in line 744; used 13 times
geti defined in line 1040; used 42 times
getree defined in line 769; used 2 times
incref defined in line 1164; used 1 times
isfloat defined in line 263; used 12 times
ispow2 defined in line 482; used 5 times
label defined in line 721; used 4 times
longrel defined in line 634; used 1 times
max defined in line 8; used 8 times
notcompat defined in line 198; used 2 times
oddreg defined in line 278; used 2 times
outname defined in line 1049; used 9 times
pbase defined in line 128; used 2 times
pname defined in line 40; used 3 times
popstk defined in line 726; used 1 times
pow2 defined in line 496; used 3 times
prins defined in line 225; used 2 times
psoct defined in line 753; used 3 times
pswitch defined in line 361; used 1 times
regerr defined in line 123; used 2 times
setype defined in line 1126; used 3 times
sort defined in line 451; used 1 times
strasg defined in line 1066; used 2 times
xdcalc defined in line 140; used 3 times
xlongrel defined in line 699; used 1 times

Defined variables

dirsw defined in line 337; used 1 times
hashsw defined in line 346; used 1 times
lrtab defined in line 689; used 4 times

Defined macros

STKS defined in line 768; used 2 times
Last modified: 1979-05-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2249
Valid CSS Valid XHTML 1.0 Strict