|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "%W% (Berkeley/CCI) %G%"; ! 3: #endif ! 4: ! 5: /* ! 6: * C object code improver-- second part ! 7: */ ! 8: ! 9: #include "c2.h" ! 10: #include <stdio.h> ! 11: #include <ctype.h> ! 12: ! 13: int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */ ! 14: ! 15: redun3(p) register struct node *p; { ! 16: /* check for 3 addr instr which should be 2 addr */ ! 17: if (has3ops(p)) { ! 18: if (equstr(regs[RT1],regs[RT3]) ! 19: && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) { ! 20: register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; ! 21: } ! 22: if (equstr(regs[RT2],regs[RT3])) { ! 23: p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; ! 24: lastrand=regs[RT2]; *regs[RT3]=0; return(1); ! 25: } ! 26: } return(0); ! 27: } ! 28: ! 29: bmove() { ! 30: register struct node *p, *lastp; register char *cp1,*cp2; register int r; ! 31: struct node *flops(); ! 32: ! 33: refcount(); ! 34: for (p=lastp= &first; 0!=(p=p->forw); lastp=p); ! 35: clearreg(); clearuse(); ! 36: for (p=lastp; p!= &first; p=p->back) { ! 37: if (debug) { ! 38: printf("Uses: "); ! 39: if (useacc) ! 40: printf("acc: %s\n",useacc->code? useacc->code:""); ! 41: for (r=0; r<NUSE; r++) if (isused(r)) ! 42: printf("r%d: %s (%d times)\n", ! 43: r, uses[r] && uses[r]->code? uses[r]->code:"", ! 44: usecnt[r]); ! 45: printf("-\n"); ! 46: } ! 47: r=(p->subop>>4)&0xF; ! 48: splitrand(p); ! 49: if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;} ! 50: /* ops that do nothing */ ! 51: if(p->op==MOV && equstr(regs[RT1], regs[RT2])) ! 52: if(p->forw->op!=CBR) { ! 53: delnode(p); redunm++; continue; ! 54: } else { ! 55: p->op=TST; p->pop=0; ! 56: while(*p->code++ != ','); ! 57: redunm++; ! 58: } ! 59: else if((cp1=p->code, *cp1++)=='$' && ! 60: (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') { ! 61: switch((p->code[1]<<8)|ord(p->op)) { ! 62: case (('0'<<8)|ord(ADD)): ! 63: case (('0'<<8)|ord(SUB)): ! 64: case (('-'<<8)|ord(AND)): ! 65: case (('0'<<8)|ord(OR)): ! 66: case (('0'<<8)|ord(XOR)): ! 67: case (('1'<<8)|ord(MUL)): ! 68: case (('1'<<8)|ord(DIV)): ! 69: case (('0'<<8)|ord(SHAL)): ! 70: case (('0'<<8)|ord(SHAR)): ! 71: case (('0'<<8)|ord(SHL)): ! 72: case (('0'<<8)|ord(SHR)): ! 73: if(r == OP2) { ! 74: if(p->forw->op!=CBR) { ! 75: delnode(p); redunm++; continue; ! 76: } else { ! 77: p->op=TST; p->subop&=0xF; p->pop=0; ! 78: while(*p->code++ != ','); ! 79: redunm++; ! 80: } ! 81: } else { /* OP3 or shift */ ! 82: p->op=MOV; p->subop&=0xF; p->pop=0; ! 83: while(*p->code++ != ','); ! 84: p = p->forw; redunm++; continue; ! 85: } ! 86: break; ! 87: case (('0'<<8)|ord(MUL)): ! 88: case (('0'<<8)|ord(AND)): ! 89: p->op=CLR; p->subop&=0xF; p->pop=0; ! 90: while(*p->code++ != ','); ! 91: if(r == OP3) ! 92: while(*p->code++ != ','); ! 93: redunm++; ! 94: } ! 95: } ! 96: switch (p->op) { ! 97: case LABEL: case DLABEL: ! 98: for (r=NUSE; --r>=0;) ! 99: if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r)); ! 100: if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE)); ! 101: break; ! 102: case CALLS: ! 103: case CALLF: ! 104: clearuse(); goto std; ! 105: case NIL: ! 106: clearuse(); break; ! 107: case CVT: ! 108: { long n; ! 109: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; ! 110: if (*cp1++!='$') goto std; splitrand(p); ! 111: n = getnum(®s[RT1][1]); ! 112: if(r==BYTE && (n<-128 || n>127)) goto std; ! 113: if(r==WORD && (n<-32768 || n>32767)) goto std; ! 114: p->op = MOV; p->subop = r; p->pop = 0; ! 115: } goto std; ! 116: ! 117: case SUB: ! 118: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; ! 119: if (*cp1++!='$') goto std; splitrand(p); ! 120: #ifdef MOVAFASTER ! 121: if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ ! 122: char buf[C2_ASIZE]; cp2=buf; *cp2++='-'; ! 123: cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; ! 124: cp1="(fp),"; while (*cp2++= *cp1++); --cp2; ! 125: cp1=regs[RT3]; while (*cp2++= *cp1++); ! 126: p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0; ! 127: } else ! 128: #endif MOVAFASTER ! 129: if (*cp1++=='-' && 0==(r=getnum(cp1)) && ! 130: !checkexpr(cp1)) { ! 131: p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; ! 132: } goto std; ! 133: case ADD: ! 134: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; ! 135: if (*cp1++!='$') goto std; splitrand(p); ! 136: if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw) ! 137: { ! 138: /* address comp: ! 139: ** addl2 $_foo,r0 \ movab _foo[r0],bar ! 140: ** movl r0,bar / ! 141: */ ! 142: register struct node *pnext = p->forw; ! 143: char buf[C2_ASIZE]; ! 144: ! 145: if (pnext->op == MOV && pnext->subop == LONG) ! 146: { ! 147: cp1 = ®s[RT1][1]; cp2 = &buf[0]; ! 148: while (*cp2++ = *cp1++) ; cp2--; ! 149: splitrand(pnext); ! 150: if (r == isreg(regs[RT1])) ! 151: { ! 152: delnode(p); p = pnext; ! 153: p->op = MOVA; p->subop = BYTE; ! 154: p->pop = 0; ! 155: cp1 = regs[RT1]; *cp2++ = '['; ! 156: while (*cp2++ = *cp1++) ; cp2--; ! 157: *cp2++ = ']'; *cp2++ = ','; ! 158: cp1 = regs[RT2]; ! 159: while (*cp2++ = *cp1++) ; ! 160: p->code = copy(buf); ! 161: } ! 162: } ! 163: } ! 164: else ! 165: #ifdef MOVAFASTER ! 166: if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ ! 167: cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; ! 168: cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; ! 169: p->op = MOVA; p->subop = BYTE; p->pop=0; ! 170: } else ! 171: #endif MOVAFASTER ! 172: if (*cp1++=='-' && 0==(r=getnum(cp1)) && ! 173: !checkexpr(cp1)) { ! 174: p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; ! 175: } ! 176: /* fall thru ... */ ! 177: case CASE: ! 178: default: std: ! 179: p=bflow(p); break; ! 180: ! 181: case MUL: ! 182: /* ! 183: ** Change multiplication ! 184: ** by constant powers of 2 to shifts. ! 185: */ ! 186: splitrand(p); ! 187: if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; ! 188: if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std; ! 189: /* mull2 $2,x */ ! 190: if(r == 1 && p->subop == U(LONG, OP2)) { ! 191: strcpy(regs[RT1], regs[RT2]); ! 192: p->op = ADD; p->pop = 0; newcode(p); ! 193: goto std; ! 194: } ! 195: if (p->subop == U(LONG,OP2)) ! 196: strcpy(regs[RT3], regs[RT2]); ! 197: sprintf(regs[RT1], "$%d", r); ! 198: p->op = SHL; p->subop = LONG; ! 199: p->pop = 0; newcode(p); ! 200: goto std; ! 201: ! 202: case SHAL: ! 203: case SHL: ! 204: { ! 205: /* bit tests: ! 206: ** shll A,$1,rC \ ! 207: ** bitl B,rC > jbc A,B,D ! 208: ** jeql D / ! 209: ** ! 210: ** address comp: ! 211: ** shll $1,bar,r0 \ movl bar,r0 ! 212: ** movab _foo[r0] / movaw _foo[r0] ! 213: ** ! 214: ** shll $2,r0,r0 \ moval _foo[r0] ! 215: ** movab _foo[r0] / ! 216: */ ! 217: register struct node *pf; ! 218: register struct node *pn; ! 219: register int shfrom, shto; ! 220: long shcnt; ! 221: char *regfrom; ! 222: ! 223: splitrand(p); ! 224: if (regs[RT1][0] != '$') { ! 225: if(isreg(regs[RT1]) < 0) goto std; /* alignment */ ! 226: if (regs[RT2][0] != '$') goto std; ! 227: if (getnum(®s[RT2][1]) != 1) goto std; ! 228: if (!tempreg(regs[RT3],r)) goto std; ! 229: if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std; ! 230: if (uses[r] && uses[r] != pf) goto std; ! 231: splitrand(pf); ! 232: if (r == isreg(regs[RT1])) cp2 = regs[RT2]; ! 233: else if (r == isreg(regs[RT2])) cp2 = regs[RT1]; ! 234: else goto std; ! 235: if (*cp2 == '$') goto std; ! 236: if ((pn = pf->forw)->op != CBR) goto std; ! 237: if (pn->subop != JEQ && pn->subop != JNE) goto std; ! 238: delnode(p); delnode(pf); ! 239: pn->subop = (pn->subop == JEQ) ? JBC : JBS; ! 240: for(cp1=p->code; *cp1++!=',';); ! 241: while (*cp1++= *cp2++); ! 242: pn->code = p->code; pn->pop = NULL; ! 243: deluse(r); ! 244: nbj++; ! 245: p = pn; ! 246: goto std; ! 247: } ! 248: if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std; ! 249: if ((shfrom = isreg(regs[RT2])) >= 0) ! 250: regfrom = copy(regs[RT2]); ! 251: if (tempreg(regs[RT3],shto)) ! 252: { ! 253: int regnum; ! 254: ! 255: if (uses[shto] != (pf = p->forw)) goto ashadd; ! 256: if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; ! 257: if (pf->subop != BYTE) goto ashadd; ! 258: splitrand(pf); ! 259: if (!indexa(regs[RT1])) goto std; ! 260: cp2 = regs[RT1]; ! 261: if(!isstatic(cp2)) goto std; ! 262: while (*cp2++ != '[') ; ! 263: if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; ! 264: regnum = *cp2++ - '0'; ! 265: if (isdigit(*cp2)) ! 266: { ! 267: if (cp2[1] != ']') goto std; ! 268: regnum *= 10; regnum += *cp2 - '0'; ! 269: } ! 270: if (regnum != shto) goto std; ! 271: if (shfrom >= 0) /* shll $N,r*,r0 */ ! 272: { ! 273: delnode(p); ! 274: p = pf; ! 275: if (shfrom != shto) ! 276: { ! 277: deluse(shto); ! 278: splitrand(pf); ! 279: cp2=regs[RT1]; while (*cp2++!='['); ! 280: cp1=regfrom; while (*cp2++= *cp1++); ! 281: cp2[-1] = ']'; *cp2 = 0; ! 282: newcode(pf); ! 283: } ! 284: } ! 285: else ! 286: { ! 287: p->op = MOV; splitrand(p); ! 288: strcpy(regs[RT1], regs[RT2]); ! 289: strcpy(regs[RT2], regs[RT3]); ! 290: regs[RT3][0] = '\0'; ! 291: p->pop = 0; newcode(p); ! 292: } ! 293: switch (shcnt) ! 294: { ! 295: case 1: pf->subop = WORD; break; ! 296: case 2: pf->subop = LONG; break; ! 297: } ! 298: redunm++; nsaddr++; ! 299: } ! 300: goto std; ! 301: ashadd: ! 302: /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ ! 303: if (shcnt == 1) { ! 304: /* ! 305: ** quickie: ! 306: ** shll $1,A,A > addl2 A,A ! 307: ** shll $1,A,B > addl3 A,A,B ! 308: */ ! 309: p->op = ADD; ! 310: strcpy(regs[RT1], regs[RT2]); ! 311: if(equstr(regs[RT2], regs[RT3])) { ! 312: p->subop = U(LONG,OP2); ! 313: regs[RT3][0] = '\0'; ! 314: } else ! 315: p->subop = U(LONG,OP3); ! 316: p->pop = 0; ! 317: newcode(p); ! 318: } ! 319: goto std; ! 320: } ! 321: ! 322: case SHAR: ! 323: case SHR: ! 324: { ! 325: /* bit tests: ! 326: ** shrl A,B,rC \ ! 327: ** bitl $1,rC > jbc A,B,D ! 328: ** jeql D / ! 329: */ ! 330: register struct node *pf; /* forward node */ ! 331: register struct node *pn; /* next node (after pf) */ ! 332: register int extreg; /* reg extracted to */ ! 333: ! 334: splitrand(p); ! 335: if(isreg(regs[RT1]) < 0) goto std; /* alignment */ ! 336: if (!tempreg(regs[RT3],extreg)) goto std; ! 337: if ((pf = p->forw)->op != BIT) goto std; ! 338: if (uses[extreg] && uses[extreg] != pf) goto std; ! 339: splitrand(pf); ! 340: if (regs[RT1][0] != '$') goto std; ! 341: if (getnum(®s[RT1][1]) != 1) goto std; ! 342: if (extreg != isreg(regs[RT2])) goto std; ! 343: if ((pn = pf->forw)->op != CBR) goto std; ! 344: if (pn->subop != JEQ && pn->subop != JNE) goto std; ! 345: delnode(p); delnode(pf); ! 346: pn->subop = (pn->subop == JEQ) ? JBC : JBS; ! 347: for(cp1=p->code; *cp1++!=',';); ! 348: while (*cp1!=',') cp1++; *cp1='\0'; ! 349: pn->code = p->code; pn->pop = NULL; ! 350: deluse(extreg); nbj++; ! 351: p = pn; ! 352: goto std; ! 353: } ! 354: ! 355: case AND: ! 356: { ! 357: /* unsigned conversion: ! 358: ** cvtbl A,B; andl2 $255,B > movzbl A,B ! 359: ** ! 360: ** also byte- and word-size fields: ! 361: ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B ! 362: ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B ! 363: */ ! 364: char src[C2_ASIZE]; ! 365: register int f; /* field length */ ! 366: register struct node *pb = p->back; /* backward node */ ! 367: ! 368: if (p->subop != U(LONG,OP2)) ! 369: goto std; ! 370: splitrand(p); cp1=regs[RT1]; ! 371: if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff) ! 372: goto std; ! 373: f = f==0xff ? 8 : 16; ! 374: if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR) ! 375: goto std; ! 376: /* save source of ANDL in 'src' */ ! 377: strcpy(src, regs[RT2]); ! 378: splitrand(pb); ! 379: if (!equstr(src,lastrand)) ! 380: goto std; ! 381: if (pb->op==CVT || pb->op==MOVZ) { ! 382: if (!(bitsize[pb->subop&0xF]==f ! 383: && bitsize[pb->subop>>4]>=f)) /* good CVT */ ! 384: goto std; ! 385: strcpy(src, regs[RT1]); ! 386: } else { ! 387: register int boff; /* bit offset */ ! 388: ! 389: if (regs[RT1][0] != '$') goto std; ! 390: if ((boff = getnum(®s[RT1][1])) < 0) goto std; ! 391: if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std; ! 392: if ((boff & (f-1)) != 0) goto std; ! 393: boff = (32-boff-f) / 8; ! 394: if (boff == 0) ! 395: strcpy(src, regs[RT2]); ! 396: else ! 397: sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+", ! 398: regs[RT2]); ! 399: } ! 400: delnode(pb); ! 401: p->op = MOVZ; ! 402: p->subop = U((f==8 ? BYTE : WORD), LONG); ! 403: sprintf(line,"%s,%s",src,lastrand); ! 404: p->pop=0; ! 405: p->code = copy(line); ! 406: goto std; ! 407: } ! 408: ! 409: case CMP: ! 410: { ! 411: /* comparison to -63 to -1: ! 412: ** cmpl r0,$-1 > incl r0 ! 413: ** jeql ... ! 414: ** ! 415: ** cmpl r0,$-63 > addl2 $63,r0 ! 416: ** jeql ... ! 417: */ ! 418: register int num; ! 419: register int reg; ! 420: register struct node *regp = p->back; ! 421: ! 422: if (p->forw->op != CBR) goto std; ! 423: if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; ! 424: splitrand(p); ! 425: if (strncmp(regs[RT2], "$-", 2) != 0) goto std; ! 426: reg = r = isreg(regs[RT1]); ! 427: if (r < 0) goto std; ! 428: if (r < NUSE && uses[r] != 0) goto std; ! 429: if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) ! 430: { ! 431: if (*regp->code != 'r') goto std; ! 432: reg = regp->code[1] - '0'; ! 433: if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) ! 434: goto std; ! 435: } ! 436: if (r >= NUSE) goto std; ! 437: if (reg != r) ! 438: sprintf(regs[RT1], "r%d", reg); ! 439: if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; ! 440: if (num == 1) ! 441: { ! 442: p->op = INC; regs[RT2][0] = '\0'; ! 443: } ! 444: else ! 445: { ! 446: register char *t; ! 447: ! 448: t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; ! 449: p->op = ADD; p->subop = U(p->subop, OP2); ! 450: for (t = ®s[RT1][2]; t[-1] = *t; t++) ; ! 451: } ! 452: p->pop = 0; newcode(p); ! 453: goto std; ! 454: } ! 455: ! 456: case JBR: case JMP: ! 457: clearuse(); ! 458: if ((p->subop&0xF)==RET) { ! 459: switch((p->subop>>4)&0xF) { ! 460: case 2: adduse(1,p); regs[1][0]= -1; ! 461: case 1: adduse(0,p); regs[0][0]= -1; ! 462: } ! 463: break; ! 464: } ! 465: if (p->ref==0) goto std; /* jmp (r0) */ ! 466: /* fall through */ ! 467: case CBR: ! 468: if (p->ref->ref!=0) { ! 469: for (r=NUSE;--r>=0;) ! 470: if ((1<<r) & (int)p->ref->ref) { ! 471: adduse(r,p); regs[r][0]= -1; ! 472: } ! 473: if ((1<<NUSE) & (int)p->ref->ref) useacc=p; ! 474: } ! 475: break; ! 476: case LNF: ! 477: /* lnf a; addf b ==> ldf b; subf a */ ! 478: { register struct node *pf = p->forw; ! 479: if(pf->op==ADDF && p->subop==pf->subop) { ! 480: p->op = LDF; ! 481: p->pop = 0; ! 482: pf->op = SUBF; ! 483: pf->pop = 0; ! 484: cp1 = p->code; ! 485: p->code = pf->code; ! 486: pf->code = cp1; ! 487: p = pf->forw; ! 488: break; ! 489: }} ! 490: case LDF: case LDFD: case CVLF: /* destroy acc */ ! 491: useacc = 0; ! 492: goto std; ! 493: case STF: ! 494: { register struct node *pf; ! 495: if((pf=flops(p)) != p) { ! 496: p = pf; /* usually p->forw; */ ! 497: break; ! 498: }} ! 499: if(ldmov(p)) { ! 500: p = p->forw; ! 501: break; ! 502: } ! 503: if(useacc == 0) ! 504: useacc = p; ! 505: goto std; ! 506: case ADDF: case MULF: /* commutatives - create clients for flops */ ! 507: /* stf a; ldf b; addf a => stf a; ldf a; addf b */ ! 508: { register struct node *pb = p->back; ! 509: register struct node *pbb = pb->back; ! 510: if(pb->op==LDF && pb->subop==p->subop && ! 511: pbb && pbb->op==STF && pbb->subop==p->subop && ! 512: equstr(pbb->code, p->code)) { ! 513: cp1 = p->code; ! 514: p->code = pb->code; ! 515: pb->code = cp1; ! 516: }} ! 517: /* use acc and regs */ ! 518: case CMPF: case CVFL: case SUBF: case DIVF: ! 519: if(useacc == 0) ! 520: useacc = p; ! 521: goto std; ! 522: case TSTF: ! 523: break; ! 524: case PUSHD: ! 525: if(ldmov(p)) { ! 526: p = p->forw; ! 527: break; ! 528: } ! 529: case CVDF: case NEGF: /* use only acc */ ! 530: case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: ! 531: if(useacc == 0) ! 532: useacc = p; ! 533: case EROU: case JSW: ! 534: case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; ! 535: } ! 536: } ! 537: for (p= &first; p!=0; p=p->forw) ! 538: if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ ! 539: } ! 540: ! 541: char * ! 542: byondrd(p) register struct node *p; { ! 543: /* return pointer to register which is "beyond last read/modify operand" */ ! 544: if (has2ops(p)) return(regs[RT3]); ! 545: switch (p->op) { ! 546: case MFPR: ! 547: case PUSHA: ! 548: case TST: case INC: case DEC: case PUSH: ! 549: case LDF: case LNF: case CVLF: case LDFD: ! 550: case ADDF: case SUBF: case MULF: case DIVF: ! 551: case CMPF: ! 552: return(regs[RT2]); ! 553: case MTPR: ! 554: #ifndef EMOD ! 555: case EDIV: ! 556: #endif EMOD ! 557: case CBR: /* must be JBC/JBS */ ! 558: case BIT: case CMP: case CALLS: case CALLF: ! 559: case CMPF2: ! 560: return(regs[RT3]); ! 561: case EMUL: ! 562: case PROBE: ! 563: case MOVBLK: ! 564: case CASE: ! 565: return(regs[RT4]); ! 566: } ! 567: return(lastrand); ! 568: } ! 569: ! 570: struct node * ! 571: bflow(p) ! 572: register struct node *p; ! 573: { ! 574: register char *cp1,*cp2,**preg; ! 575: register int r, fr, dblflg=0; ! 576: int flow= -1; ! 577: struct node *olduse=0, *olduse1=0; ! 578: ! 579: if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4) ! 580: dblflg |= 1; /* double dest */ ! 581: if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) ! 582: dblflg |= 2; /* double src */ ! 583: splitrand(p); ! 584: if (p->op!=PUSH && ! 585: #ifndef EMOD ! 586: p->op!=EDIV && ! 587: #endif EMOD ! 588: p->op!=EMUL && ! 589: p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { ! 590: if (equtype(p->subop,regs[r][0]) || ! 591: ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && ! 592: (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || ! 593: p->op==MOVA && compat(LONG, regs[r][0])) { ! 594: register int r2; ! 595: ! 596: if (regs[r][1]!=0) { /* send directly to destination */ ! 597: if (p->op==INC || p->op==DEC) { ! 598: p->op = (p->op==DEC) ? SUB : ADD; ! 599: /* use 2 now, convert to 3 later */ ! 600: p->subop=(OP2<<4)+(p->subop&0xF); ! 601: p->pop=0; ! 602: cp1=lastrand; cp2=regs[RT2]; ! 603: while (*cp2++= *cp1++) /* copy reg */ ! 604: ; ! 605: cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; ! 606: } ! 607: cp1=regs[r]+1; cp2=lastrand; ! 608: if (has2ops(p)) { ! 609: /* use 3 operand form of instruction */ ! 610: p->pop=0; ! 611: p->subop += (OP3-OP2)<<4; ! 612: lastrand = cp2 = regs[RT3]; ! 613: } ! 614: while (*cp2++= *cp1++) ! 615: ; ! 616: if (p->op==MOVA && p->forw->op==PUSH) { ! 617: p->op=PUSHA; ! 618: *regs[RT2]=0; p->pop=0; ! 619: } else if ((p->op==MOV || p->op==CVT) && ! 620: p->forw->op==PUSH) { ! 621: p->op=PUSH; p->subop &= 0xF; ! 622: *regs[RT2]=0; p->pop=0; ! 623: } ! 624: delnode(p->forw); ! 625: if (tempreg(lastrand,r2)) { ! 626: adduse(r2,uses[r]); /* ZZZ */ ! 627: deluse(r); ! 628: } ! 629: redun3(p); ! 630: newcode(p); redunm++; flow=r; ! 631: } else if (p->op==MOV) { /* superfluous fetch */ ! 632: int nmatch; ! 633: char src[C2_ASIZE]; ! 634: movit: ! 635: for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) ! 636: ; ! 637: splitrand(p->forw); ! 638: if (p->forw->op != INC && p->forw->op != DEC) ! 639: lastrand=byondrd(p->forw); ! 640: nmatch=0; ! 641: for (preg=regs+RT1;*preg!=lastrand;preg++) ! 642: if (r==isreg(*preg)) { ! 643: cp2= *preg; cp1=src; ! 644: while (*cp2++= *cp1++) ! 645: ; ! 646: ++nmatch; ! 647: } ! 648: if (nmatch==1) { ! 649: if (has2ops(p->forw) && equstr(src,regs[RT2])) { ! 650: p->forw->pop=0; ! 651: p->forw->subop += (OP3-OP2)<<4; ! 652: cp1=regs[RT3]; ! 653: *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; ! 654: } ! 655: delnode(p); ! 656: p=p->forw; ! 657: if (tempreg(src,r2)) { ! 658: adduse(r2,uses[r]); /* ZZZ */ ! 659: deluse(r); ! 660: } ! 661: redun3(p); ! 662: newcode(p); redunm++; flow=r; ! 663: } else ! 664: splitrand(p); ! 665: } ! 666: } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && ! 667: p->forw->subop&0xf && /* if base or index, then forget it */ ! 668: compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) ! 669: goto movit; ! 670: } ! 671: /* adjust 'lastrand' past any 'read' or 'modify' operands. */ ! 672: lastrand=byondrd(p); ! 673: /* a 'write' clobbers the register. */ ! 674: if (tempreg(lastrand,r) || ! 675: (has2ops(p) && tempreg(regs[RT2],r) && !isused(r))) { ! 676: /* ! 677: * Writing a dead register is useless, ! 678: * but watch side effects ! 679: */ ! 680: switch (p->op) { ! 681: #ifndef EMOD ! 682: case EDIV: ! 683: #endif EMOD ! 684: case EMUL: ! 685: case AOBLEQ: case AOBLSS: ! 686: break; ! 687: default: ! 688: /* ! 689: * If no direct uses, check for ! 690: * use of condition codes ! 691: */ ! 692: if (!isused(r) && ((dblflg&1)==0 || !isused(r+1))) { ! 693: register struct node *q = p; ! 694: ! 695: while ((q = nonlab(q->forw))->op==JBR && ! 696: q->subop==0) ! 697: q=q->ref; /* cc unused, unchanged */ ! 698: if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { ! 699: /* ... and destroyed */ ! 700: preg=regs+RT1; ! 701: while (cp1 = *preg++) { ! 702: if (cp1==lastrand && ! 703: p->op != CLR && ! 704: p->op != CVFL) { ! 705: redunm++; ! 706: delnode(p); ! 707: return(p->forw); ! 708: } ! 709: if (equstr(cp1,lastrand)) ! 710: break; ! 711: } ! 712: } ! 713: } ! 714: flow=r; ! 715: } ! 716: } ! 717: /* ! 718: * Clobber any registers written, but ! 719: * don't clobber use/reference count. ! 720: */ ! 721: if ((r=flow) >= 0) { ! 722: olduse=uses[r]; deluse(r); ! 723: *(short *)(regs[r])=0; ! 724: /* if r0 destroyed, dont keep r1 */ ! 725: if (dblflg&1) { ! 726: olduse1=uses[++r]; deluse(r); ! 727: *(short *)(regs[r])=0; ! 728: } ! 729: } ! 730: /* now look for 'read' or 'modify' (read & write) uses */ ! 731: preg=regs+RT1; ! 732: while (*(cp1= *preg++)) { ! 733: /* check for r */ ! 734: if (lastrand!=cp1 && tempreg(cp1,r) && uses[r]==0) { ! 735: adduse(r,p); /* ZZZ */ ! 736: cp2=regs[r]; *cp2++=p->subop; ! 737: if ((p->op==SHAL || p->op==SHAR || ! 738: p->op==SHL || p->op==SHR) && ! 739: cp1==regs[RT1]) ! 740: cp2[-1] = BYTE; ! 741: if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) ! 742: cp2[-1] = LONG; ! 743: if (p->op==MOVA && cp1==regs[RT2]) ! 744: cp2[-1]=LONG; ! 745: /* ediv/emod's 2nd operand is quad */ ! 746: if (((p->op==EDIV ! 747: #ifdef EMOD ! 748: || p->op==EMOD ! 749: #endif EMOD ! 750: ) && cp1==regs[RT2] || (dblflg&2)) && ! 751: ++r<NUSE && uses[r]==0) { ! 752: *cp2=0; ! 753: adduse(r,p); /* ZZZ */ ! 754: cp2=regs[r]; *cp2++=p->subop; ! 755: } ! 756: if (p->op==MOV || p->op==PUSH || p->op==CVT || ! 757: p->op==MOVZ || p->op==COM || p->op==NEG || ! 758: p->op==STF) { ! 759: if (p->op!=PUSH) { ! 760: cp1=regs[RT2]; ! 761: if (tempreg(cp1,r)) { ! 762: /* ! 763: * reincarnation!! ! 764: * (as in addl2 r0,r1; ! 765: * movl r1,r0; ret) ! 766: */ ! 767: if (uses[r]==0) ! 768: adduse(r,olduse); ! 769: if ((dblflg&1) && uses[r+1]==0) ! 770: adduse(r+1,olduse1); ! 771: } ! 772: if (p->op!=MOV) ! 773: cp1=0; ! 774: } else ! 775: cp1="-(sp)"; ! 776: if (cp1) ! 777: while (*cp2++= *cp1++) ! 778: ; ! 779: else ! 780: *cp2=0; ! 781: } else ! 782: *cp2=0; ! 783: continue; ! 784: } ! 785: /* check for (r),[r] */ ! 786: do { ! 787: if (*cp1=='(' || *cp1=='[') { /* get register number */ ! 788: char t; ! 789: for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) ! 790: ; ! 791: t= *cp1; *cp1=0; ! 792: if (tempreg(cp2,r)) { ! 793: if (uses[r]==0 || uses[r]==p) { ! 794: adduse(r,p); ! 795: regs[r][0] = (*--cp2=='[' ? ! 796: OPX<<4 : OPB<<4); ! 797: } else ! 798: usecnt[r]++; ! 799: } ! 800: *cp1=t; ! 801: } ! 802: } while (*++cp1); ! 803: } ! 804: #ifdef MOVAFASTER ! 805: /* pushax or movax possibility? */ ! 806: cp1=regs[RT1]; ! 807: if (*cp1++=='$' && isstatic(cp1)) { ! 808: if (p->op==MOV && p->subop==LONG) { ! 809: if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { ! 810: cp1=p->code; while (*cp1++!=','); p->code= --cp1; ! 811: } ! 812: p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; ! 813: } else if (p->op==PUSH && p->subop==LONG) { ! 814: p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; ! 815: } else if (p->op==ADD && p->subop==U(LONG,OP3) ! 816: && 0<=(r=isreg(regs[RT2]))) { ! 817: cp1=cp2=p->code; ++cp1; ! 818: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; ! 819: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; ! 820: if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} ! 821: else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} ! 822: if (uses[r]==0) {adduse(r,p); regs[r][0]=OPX<<4;} ! 823: p->pop=0; ! 824: } ! 825: } ! 826: #endif MOVAFASTER ! 827: return (p); ! 828: } ! 829: ! 830: /* try to eliminate STF's */ ! 831: struct node * ! 832: flops(q) ! 833: register struct node *q; ! 834: { ! 835: register struct node *p; ! 836: register int r; ! 837: ! 838: if(q->op!=STF || !tempreg(q->code,r)) ! 839: return(q); ! 840: if(uses[r]) { ! 841: /* see if anyone destroys acc between us */ ! 842: for(p=q->forw; p!=uses[r]; p=p->forw) ! 843: switch(p->op) { ! 844: case LABEL: ! 845: case LDF: case LNF: case CVLF: case LDFD: ! 846: case CVDF: case NEGF: case ADDF: case SUBF: ! 847: case MULF: case DIVF: case SINF: case COSF: ! 848: case ATANF: case LOGF: case SQRTF: case EXPF: ! 849: return(q); ! 850: } ! 851: ! 852: if(q->subop == p->subop) ! 853: switch(p->op) { /* do it in the accumulator */ ! 854: case LDF: /* redundant load */ ! 855: delnode(p); nld++; ! 856: p = p->forw; ! 857: break; ! 858: case LNF: /* stf r; lnf r ==> negf */ ! 859: p->op = NEGF; ! 860: p->pop = 0; ! 861: p->code = 0; ! 862: break; ! 863: case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ ! 864: { register char *s; ! 865: register struct node *p1=p->forw; ! 866: for(s=p->code; *s!=','; s++); ! 867: *s = 0; ! 868: if(isreg(p->code) == r) ! 869: p->code = s+1; ! 870: else { ! 871: if(p1->op != CBR || isreg(s+1) != r) { ! 872: *s = ','; ! 873: return(q); ! 874: } ! 875: if(p1->subop > JNE) { ! 876: p1->subop ^= 1; ! 877: p1->pop = 0; ! 878: nrevbr++; ! 879: } ! 880: } ! 881: p->op = CMPF; ! 882: p->pop = 0; ! 883: } ! 884: break; ! 885: default: ! 886: return(q); ! 887: } ! 888: else if(p->subop==LONG) { ! 889: switch(p->op) { ! 890: case TST: /* stf r; tstl r ==> tstf */ ! 891: p->op = TSTF; ! 892: p->code = 0; ! 893: break; ! 894: /* send directly to destination */ ! 895: case MOV: /* stf r; movl r,x ==> stf x */ ! 896: case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ ! 897: if(q->subop == DOUBLE) { ! 898: register struct node *b = p->back; ! 899: /* assume b's 2nd arg is ok */ ! 900: if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) ! 901: return(q); ! 902: delnode(b); redunm++; ! 903: } ! 904: if(p->op==PUSH) { ! 905: if(q->subop == DOUBLE) { ! 906: p->op = PUSHD; ! 907: p->code = 0; ! 908: } else { ! 909: p->op = q->op; ! 910: p->code = copy("-(sp)"); ! 911: } ! 912: } else { ! 913: p->op = q->op; ! 914: while(*p->code++ != ','); ! 915: } ! 916: break; ! 917: default: ! 918: return(q); ! 919: } ! 920: p->pop = 0; ! 921: p->subop = q->subop; ! 922: } else ! 923: return(q); ! 924: uses[r] = 0; ! 925: if(q->subop == DOUBLE) ! 926: uses[r+1] = 0; ! 927: { /* undo any effect on uses in the area between p and q, ! 928: * as we are going over it again */ ! 929: register struct node *b; ! 930: for(b=p; b!=q; b=b->back) { ! 931: for(r=0; r<NUSE; r++) { ! 932: if(uses[r] == b) ! 933: uses[r] = 0; ! 934: if(useacc == b) ! 935: useacc = 0; ! 936: } ! 937: } ! 938: } ! 939: return(p->forw); /* make p the next for bflow */ ! 940: } ! 941: /* it's a store to reg which isnt used elsewhere */ ! 942: if((p=q->forw)->op == CBR) { ! 943: q->op = TSTF; ! 944: q->pop = 0; ! 945: q->code = 0; ! 946: } else { ! 947: delnode(q); nst++; ! 948: if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { ! 949: if(useacc == p) ! 950: useacc = 0; ! 951: return(p->forw); /* so ldmov can be used on p */ ! 952: } ! 953: } ! 954: return(p); ! 955: } ! 956: ! 957: /* try to change load/store sequences to movl */ ! 958: ldmov(q) ! 959: register struct node *q; ! 960: { ! 961: register struct node *p; ! 962: register char *s, *pcod, *cp; ! 963: char *dlsw(); ! 964: ! 965: p = q->back; ! 966: if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) ! 967: && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) ! 968: return(0); ! 969: pcod = p->code; ! 970: cp = p->code; ! 971: /* prepare args for movl/pushl */ ! 972: if(q->op!=TSTF && q->subop==DOUBLE) { ! 973: if(p->op == LDF) { ! 974: if((s = dlsw(p->code)) == NULL) ! 975: return(0); ! 976: ! 977: strcpy(line, s); ! 978: if(q->op == STF) { ! 979: strcat(line, ","); ! 980: if((s = dlsw(q->code)) == NULL) ! 981: return(0); ! 982: strcat(line, s); ! 983: p->op = MOV; ! 984: } else ! 985: p->op = PUSH; ! 986: } else { /* LDFD */ ! 987: if(q->op == STF) { ! 988: if((s = dlsw(q->code)) == NULL) ! 989: return(0); ! 990: } else ! 991: s = "-(sp)"; ! 992: strcpy(line, s); ! 993: p->op = CLR; ! 994: } ! 995: p->pop = 0; ! 996: p->subop = LONG; ! 997: p->code = copy(line); ! 998: } else ! 999: { ! 1000: if ((p->op == LDF) && (p->subop == DOUBLE) && ! 1001: (indexa(cp))) return(0); ! 1002: delnode(p); ! 1003: } ! 1004: strcpy(line, pcod); ! 1005: if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ ! 1006: strcat(line, ","); ! 1007: strcat(line, q->code); ! 1008: q->op = MOV; ! 1009: nst++; ! 1010: } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ ! 1011: q->op = TST; ! 1012: else /* ldd x; pushd ==> pushl x+4; pushl x */ ! 1013: q->op = PUSH; ! 1014: q->pop = 0; ! 1015: q->subop = LONG; ! 1016: q->code = copy(line); ! 1017: nld++; ! 1018: return(1); ! 1019: } ! 1020: ! 1021: /* reconstruct the address of l.s.w. of a double operand */ ! 1022: char * ! 1023: dlsw(d) ! 1024: register char *d; ! 1025: { ! 1026: register char *s, *t, *c; ! 1027: register int r; ! 1028: static char lsw[C2_ASIZE]; ! 1029: ! 1030: if(d[0] == '*' || d[0] == '$') ! 1031: return(NULL); ! 1032: if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) ! 1033: return(NULL); ! 1034: t = lsw; ! 1035: if((r=isreg(d)) >= 0) ! 1036: sprintf(t, "r%d", r+1); ! 1037: else { ! 1038: for(s=d; *s && *s!='('; *t++ = *s++) ! 1039: if(*s == '[') ! 1040: return(NULL); ! 1041: if(s!=d) ! 1042: *t++ = '+'; ! 1043: *t++ = '4'; ! 1044: while(*t++ = *s) ! 1045: if(*s++ == '[' ) ! 1046: { ! 1047: return(NULL); ! 1048: } ! 1049: } ! 1050: return(lsw); ! 1051: } ! 1052: checkexpr(p) ! 1053: register char *p; ! 1054: { ! 1055: ! 1056: while(*p && *p != ','){ ! 1057: if ((*p == '+' ) || (*p == '-')) ! 1058: return(1); ! 1059: *p++; ! 1060: } ! 1061: return(0); ! 1062: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.