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