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