1: static char sccsid[] = "@(#)c20.c 2.1"; /* SCCS id keyword */ 2: # 3: /* 4: * C object code improver 5: */ 6: 7: #include "c2.h" 8: 9: struct optab optab[] { 10: "jbr", JBR, 11: "jeq", CBR | JEQ<<8, 12: "jne", CBR | JNE<<8, 13: "jle", CBR | JLE<<8, 14: "jge", CBR | JGE<<8, 15: "jlt", CBR | JLT<<8, 16: "jgt", CBR | JGT<<8, 17: "jlo", CBR | JLO<<8, 18: "jhi", CBR | JHI<<8, 19: "jlos", CBR | JLOS<<8, 20: "jhis", CBR | JHIS<<8, 21: "jmp", JMP, 22: ".globl",EROU, 23: "mov", MOV, 24: "clr", CLR, 25: "com", COM, 26: "inc", INC, 27: "dec", DEC, 28: "neg", NEG, 29: "tst", TST, 30: "asr", ASR, 31: "asl", ASL, 32: "sxt", SXT, 33: "cmp", CMP, 34: "add", ADD, 35: "sub", SUB, 36: "bit", BIT, 37: "bic", BIC, 38: "bis", BIS, 39: "mul", MUL, 40: "ash", ASH, 41: "xor", XOR, 42: ".text",TEXT, 43: ".data",DATA, 44: ".bss", BSS, 45: ".even",EVEN, 46: "movf", MOVF, 47: "movof",MOVOF, 48: "movfo",MOVFO, 49: "addf", ADDF, 50: "subf", SUBF, 51: "divf", DIVF, 52: "mulf", MULF, 53: "clrf", CLRF, 54: "cmpf", CMPF, 55: "negf", NEGF, 56: "tstf", TSTF, 57: "cfcc", CFCC, 58: "sob", SOB, 59: "jsr", JSR, 60: ".end", END, 61: 0, 0}; 62: 63: char revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO }; 64: int isn = 20000; 65: int lastseg = -1; 66: 67: main(argc, argv) 68: char **argv; 69: { 70: register int niter, maxiter, isend; 71: extern end; 72: int nflag; 73: 74: if (argc>1 && argv[1][0]=='+') { 75: argc--; 76: argv++; 77: debug++; 78: } 79: nflag = 0; 80: if (argc>1 && argv[1][0]=='-') { 81: argc--; 82: argv++; 83: nflag++; 84: } 85: if (argc>1) { 86: if (freopen(argv[1], "r", stdin) == NULL) { 87: fprintf(stderr, "C2: can't find %s\n", argv[1]); 88: exit(1); 89: } 90: } 91: if (argc>2) { 92: if (freopen(argv[2], "w", stdout) == NULL) { 93: fprintf(stderr, "C2: can't create %s\n", argv[2]); 94: exit(1); 95: } 96: } 97: lasta = firstr = lastr = sbrk(2); 98: maxiter = 0; 99: opsetup(); 100: do { 101: isend = input(); 102: movedat(); 103: niter = 0; 104: do { 105: refcount(); 106: do { 107: iterate(); 108: clearreg(); 109: niter++; 110: } while (nchange); 111: comjump(); 112: rmove(); 113: } while (nchange || jumpsw()); 114: addsob(); 115: output(); 116: if (niter > maxiter) 117: maxiter = niter; 118: lasta = firstr; 119: } while (isend); 120: if (nflag) { 121: fprintf(stderr, "%d iterations\n", maxiter); 122: fprintf(stderr, "%d jumps to jumps\n", nbrbr); 123: fprintf(stderr, "%d inst. after jumps\n", iaftbr); 124: fprintf(stderr, "%d jumps to .+2\n", njp1); 125: fprintf(stderr, "%d redundant labels\n", nrlab); 126: fprintf(stderr, "%d cross-jumps\n", nxjump); 127: fprintf(stderr, "%d code motions\n", ncmot); 128: fprintf(stderr, "%d branches reversed\n", nrevbr); 129: fprintf(stderr, "%d redundant moves\n", redunm); 130: fprintf(stderr, "%d simplified addresses\n", nsaddr); 131: fprintf(stderr, "%d loops inverted\n", loopiv); 132: fprintf(stderr, "%d redundant jumps\n", nredunj); 133: fprintf(stderr, "%d common seqs before jmp's\n", ncomj); 134: fprintf(stderr, "%d skips over jumps\n", nskip); 135: fprintf(stderr, "%d sob's added\n", nsob); 136: fprintf(stderr, "%d redundant tst's\n", nrtst); 137: fprintf(stderr, "%d literals eliminated\n", nlit); 138: fprintf(stderr, "%dK core\n", (((int)lastr+01777)>>10)&077); 139: } 140: exit(0); 141: } 142: 143: input() 144: { 145: register struct node *p, *lastp; 146: register int oper; 147: 148: lastp = &first; 149: for (;;) { 150: oper = getline(); 151: switch (oper&0377) { 152: 153: case LABEL: 154: p = (struct node *)alloc(sizeof first); 155: if (line[0] == 'L') { 156: p->op = LABEL; 157: p->subop = 0; 158: p->labno = getnum(line+1); 159: p->code = 0; 160: } else { 161: p->op = DLABEL; 162: p->subop = 0; 163: p->labno = 0; 164: p->code = copy(1, line); 165: } 166: break; 167: 168: case JBR: 169: case CBR: 170: case JMP: 171: case JSW: 172: p = (struct node *)alloc(sizeof first); 173: p->op = oper&0377; 174: p->subop = oper>>8; 175: if (*curlp=='L' && (p->labno = getnum(curlp+1))) 176: p->code = 0; 177: else { 178: p->labno = 0; 179: p->code = copy(1, curlp); 180: } 181: break; 182: 183: default: 184: p = (struct node *)alloc(sizeof first); 185: p->op = oper&0377; 186: p->subop = oper>>8; 187: p->labno = 0; 188: p->code = copy(1, curlp); 189: break; 190: 191: } 192: p->forw = 0; 193: p->back = lastp; 194: lastp->forw = p; 195: lastp = p; 196: p->ref = 0; 197: if (oper==EROU) 198: return(1); 199: if (oper==END) 200: return(0); 201: } 202: } 203: 204: getline() 205: { 206: register char *lp; 207: register c; 208: 209: lp = line; 210: while ((c = getchar())==' ' || c=='\t') 211: ; 212: do { 213: if (c==':') { 214: *lp++ = 0; 215: return(LABEL); 216: } 217: if (c=='\n') { 218: *lp++ = 0; 219: return(oplook()); 220: } 221: if (lp >= &line[LSIZE-2]) { 222: fprintf(stderr, "C2: Sorry, input line too long\n"); 223: exit(1); 224: } 225: *lp++ = c; 226: } while ((c = getchar()) != EOF); 227: *lp++ = 0; 228: return(END); 229: } 230: 231: getnum(ap) 232: char *ap; 233: { 234: register char *p; 235: register n, c; 236: 237: p = ap; 238: n = 0; 239: while ((c = *p++) >= '0' && c <= '9') 240: n = n*10 + c - '0'; 241: if (*--p != 0) 242: return(0); 243: return(n); 244: } 245: 246: output() 247: { 248: register struct node *t; 249: register struct optab *oper; 250: register int byte; 251: 252: t = &first; 253: while (t = t->forw) switch (t->op) { 254: 255: case END: 256: return; 257: 258: case LABEL: 259: printf("L%d:", t->labno); 260: continue; 261: 262: case DLABEL: 263: printf("%s:", t->code); 264: continue; 265: 266: case TEXT: 267: case DATA: 268: case BSS: 269: lastseg = t->op; 270: 271: default: 272: if ((byte = t->subop) == BYTE) 273: t->subop = 0; 274: for (oper = optab; oper->opstring!=0; oper++) 275: if ((oper->opcode&0377) == t->op 276: && (oper->opcode>>8) == t->subop) { 277: printf("%s", oper->opstring); 278: if (byte==BYTE) 279: printf("b"); 280: break; 281: } 282: if (t->code) { 283: reducelit(t); 284: printf("\t%s\n", t->code); 285: } else if (t->op==JBR || t->op==CBR) 286: printf("\tL%d\n", t->labno); 287: else 288: printf("\n"); 289: continue; 290: 291: case JSW: 292: printf("L%d\n", t->labno); 293: continue; 294: 295: case SOB: 296: printf("sob %s", t->code); 297: if (t->labno) 298: printf(",L%d", t->labno); 299: printf("\n"); 300: continue; 301: 302: case 0: 303: if (t->code) 304: printf("%s", t->code); 305: printf("\n"); 306: continue; 307: } 308: } 309: 310: /* 311: * Notice addresses of the form 312: * $xx,xx(r) 313: * and replace them with (pc),xx(r) 314: * -- Thanx and a tip of the Hatlo hat to Bliss-11. 315: */ 316: reducelit(at) 317: struct node *at; 318: { 319: register char *c1, *c2; 320: char *c2s; 321: register struct node *t; 322: 323: t = at; 324: if (*t->code != '$') 325: return; 326: c1 = t->code; 327: while (*c1 != ',') 328: if (*c1++ == '\0') 329: return; 330: c2s = c1; 331: c1++; 332: if (*c1=='*') 333: c1++; 334: c2 = t->code+1; 335: while (*c1++ == *c2++); 336: if (*--c1!='(' || *--c2!=',') 337: return; 338: t->code = copy(2, "(pc)", c2s); 339: nlit++; 340: } 341: 342: char * 343: copy(na, ap) 344: char *ap; 345: { 346: register char *p, *np; 347: char *onp; 348: register n; 349: 350: p = ap; 351: n = 0; 352: if (*p==0) 353: return(0); 354: do 355: n++; 356: while (*p++); 357: if (na>1) { 358: p = (&ap)[1]; 359: while (*p++) 360: n++; 361: } 362: onp = np = alloc(n); 363: p = ap; 364: while (*np++ = *p++) 365: ; 366: if (na>1) { 367: p = (&ap)[1]; 368: np--; 369: while (*np++ = *p++); 370: } 371: return(onp); 372: } 373: 374: opsetup() 375: { 376: register struct optab *optp, **ophp; 377: register char *p; 378: 379: for (optp = optab; p = optp->opstring; optp++) { 380: ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS]; 381: while (*ophp++) 382: if (ophp > &ophash[OPHS]) 383: ophp = ophash; 384: *--ophp = optp; 385: } 386: } 387: 388: oplook() 389: { 390: register struct optab *optp; 391: register char *lp, *np; 392: static char tmpop[32]; 393: struct optab **ophp; 394: 395: if (line[0]=='\0') { 396: curlp = line; 397: return(0); 398: } 399: np = tmpop; 400: for (lp = line; *lp && *lp!=' ' && *lp!='\t';) 401: *np++ = *lp++; 402: *np++ = 0; 403: while (*lp=='\t' || *lp==' ') 404: lp++; 405: curlp = lp; 406: ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS]; 407: while (optp = *ophp) { 408: np = optp->opstring; 409: lp = tmpop; 410: while (*lp == *np++) 411: if (*lp++ == 0) 412: return(optp->opcode); 413: if (*lp++=='b' && *lp++==0 && *--np==0) 414: return(optp->opcode + (BYTE<<8)); 415: ophp++; 416: if (ophp >= &ophash[OPHS]) 417: ophp = ophash; 418: } 419: if (line[0]=='L') { 420: lp = &line[1]; 421: while (*lp) 422: if (*lp<'0' || *lp++>'9') 423: return(0); 424: curlp = line; 425: return(JSW); 426: } 427: curlp = line; 428: return(0); 429: } 430: 431: refcount() 432: { 433: register struct node *p, *lp; 434: static struct node *labhash[LABHS]; 435: register struct node **hp, *tp; 436: 437: for (hp = labhash; hp < &labhash[LABHS];) 438: *hp++ = 0; 439: for (p = first.forw; p!=0; p = p->forw) 440: if (p->op==LABEL) { 441: labhash[p->labno % LABHS] = p; 442: p->refc = 0; 443: } 444: for (p = first.forw; p!=0; p = p->forw) { 445: if (p->op==JBR || p->op==CBR || p->op==JSW) { 446: p->ref = 0; 447: lp = labhash[p->labno % LABHS]; 448: if (lp==0 || p->labno!=lp->labno) 449: for (lp = first.forw; lp!=0; lp = lp->forw) { 450: if (lp->op==LABEL && p->labno==lp->labno) 451: break; 452: } 453: if (lp) { 454: tp = nonlab(lp)->back; 455: if (tp!=lp) { 456: p->labno = tp->labno; 457: lp = tp; 458: } 459: p->ref = lp; 460: lp->refc++; 461: } 462: } 463: } 464: for (p = first.forw; p!=0; p = p->forw) 465: if (p->op==LABEL && p->refc==0 466: && (lp = nonlab(p))->op && lp->op!=JSW) 467: decref(p); 468: } 469: 470: iterate() 471: { 472: register struct node *p, *rp, *p1; 473: 474: nchange = 0; 475: for (p = first.forw; p!=0; p = p->forw) { 476: if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 477: rp = nonlab(p->ref); 478: if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 479: nbrbr++; 480: p->labno = rp->labno; 481: decref(p->ref); 482: rp->ref->refc++; 483: p->ref = rp->ref; 484: nchange++; 485: } 486: } 487: if (p->op==CBR && (p1 = p->forw)->op==JBR) { 488: rp = p->ref; 489: do 490: rp = rp->back; 491: while (rp->op==LABEL); 492: if (rp==p1) { 493: decref(p->ref); 494: p->ref = p1->ref; 495: p->labno = p1->labno; 496: p1->forw->back = p; 497: p->forw = p1->forw; 498: p->subop = revbr[p->subop]; 499: nchange++; 500: nskip++; 501: } 502: } 503: if (p->op==JBR || p->op==JMP) { 504: while (p->forw && p->forw->op!=LABEL 505: && p->forw->op!=DLABEL 506: && p->forw->op!=EROU && p->forw->op!=END 507: && p->forw->op!=0 && p->forw->op!=DATA) { 508: nchange++; 509: iaftbr++; 510: if (p->forw->ref) 511: decref(p->forw->ref); 512: p->forw = p->forw->forw; 513: p->forw->back = p; 514: } 515: rp = p->forw; 516: while (rp && rp->op==LABEL) { 517: if (p->ref == rp) { 518: p->back->forw = p->forw; 519: p->forw->back = p->back; 520: p = p->back; 521: decref(rp); 522: nchange++; 523: njp1++; 524: break; 525: } 526: rp = rp->forw; 527: } 528: } 529: if (p->op==JBR || p->op==JMP) { 530: xjump(p); 531: p = codemove(p); 532: } 533: } 534: } 535: 536: xjump(p1) 537: register struct node *p1; 538: { 539: register struct node *p2, *p3; 540: 541: if ((p2 = p1->ref)==0) 542: return; 543: for (;;) { 544: while ((p1 = p1->back) && p1->op==LABEL); 545: while ((p2 = p2->back) && p2->op==LABEL); 546: if (!equop(p1, p2) || p1==p2) 547: return; 548: p3 = insertl(p2); 549: p1->op = JBR; 550: p1->subop = 0; 551: p1->ref = p3; 552: p1->labno = p3->labno; 553: p1->code = 0; 554: nxjump++; 555: nchange++; 556: } 557: } 558: 559: struct node * 560: insertl(oldp) 561: register struct node *oldp; 562: { 563: register struct node *lp; 564: 565: if (oldp->op == LABEL) { 566: oldp->refc++; 567: return(oldp); 568: } 569: if (oldp->back->op == LABEL) { 570: oldp = oldp->back; 571: oldp->refc++; 572: return(oldp); 573: } 574: lp = (struct node *)alloc(sizeof first); 575: lp->op = LABEL; 576: lp->subop = 0; 577: lp->labno = isn++; 578: lp->ref = 0; 579: lp->code = 0; 580: lp->refc = 1; 581: lp->back = oldp->back; 582: lp->forw = oldp; 583: oldp->back->forw = lp; 584: oldp->back = lp; 585: return(lp); 586: } 587: 588: struct node * 589: codemove(p) 590: struct node *p; 591: { 592: register struct node *p1, *p2, *p3; 593: struct node *t, *tl; 594: int n; 595: 596: p1 = p; 597: if (p1->op!=JBR || (p2 = p1->ref)==0) 598: return(p1); 599: while (p2->op == LABEL) 600: if ((p2 = p2->back) == 0) 601: return(p1); 602: if (p2->op!=JBR && p2->op!=JMP) 603: goto ivloop; 604: p2 = p2->forw; 605: p3 = p1->ref; 606: while (p3) { 607: if (p3->op==JBR || p3->op==JMP) { 608: if (p1==p3) 609: return(p1); 610: ncmot++; 611: nchange++; 612: p1->back->forw = p2; 613: p1->forw->back = p3; 614: p2->back->forw = p3->forw; 615: p3->forw->back = p2->back; 616: p2->back = p1->back; 617: p3->forw = p1->forw; 618: decref(p1->ref); 619: return(p2); 620: } else 621: p3 = p3->forw; 622: } 623: return(p1); 624: ivloop: 625: if (p1->forw->op!=LABEL) 626: return(p1); 627: p3 = p2 = p2->forw; 628: n = 16; 629: do { 630: if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 631: return(p1); 632: } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 633: do 634: if ((p1 = p1->back) == 0) 635: return(p); 636: while (p1!=p3); 637: p1 = p; 638: tl = insertl(p1); 639: p3->subop = revbr[p3->subop]; 640: decref(p3->ref); 641: p2->back->forw = p1; 642: p3->forw->back = p1; 643: p1->back->forw = p2; 644: p1->forw->back = p3; 645: t = p1->back; 646: p1->back = p2->back; 647: p2->back = t; 648: t = p1->forw; 649: p1->forw = p3->forw; 650: p3->forw = t; 651: p2 = insertl(p1->forw); 652: p3->labno = p2->labno; 653: p3->ref = p2; 654: decref(tl); 655: if (tl->refc<=0) 656: nrlab--; 657: loopiv++; 658: nchange++; 659: return(p3); 660: } 661: 662: comjump() 663: { 664: register struct node *p1, *p2, *p3; 665: 666: for (p1 = first.forw; p1!=0; p1 = p1->forw) 667: if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1) 668: for (p3 = p1->forw; p3!=0; p3 = p3->forw) 669: if (p3->op==JBR && p3->ref == p2) 670: backjmp(p1, p3); 671: } 672: 673: backjmp(ap1, ap2) 674: struct node *ap1, *ap2; 675: { 676: register struct node *p1, *p2, *p3; 677: 678: p1 = ap1; 679: p2 = ap2; 680: for(;;) { 681: while ((p1 = p1->back) && p1->op==LABEL); 682: p2 = p2->back; 683: if (equop(p1, p2)) { 684: p3 = insertl(p1); 685: p2->back->forw = p2->forw; 686: p2->forw->back = p2->back; 687: p2 = p2->forw; 688: decref(p2->ref); 689: p2->labno = p3->labno; 690: p2->ref = p3; 691: nchange++; 692: ncomj++; 693: } else 694: return; 695: } 696: }