|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)c21.c 1.10 (Berkeley/CCI) 8/25/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: goto std; ! 298: } ! 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: if ((pf = p->forw)->op == CBR || ! 308: (pf->op == MOV && (pf = pf->forw)->op == CBR)) ! 309: /* ! 310: ** shll and addl handle the N bit differently ! 311: ** on overflow; avoid N bit CBRs ! 312: */ ! 313: switch (pf->subop) { ! 314: case JLE: case JGE: case JLT: case JGT: ! 315: goto std; ! 316: } ! 317: p->op = ADD; ! 318: strcpy(regs[RT1], regs[RT2]); ! 319: if(equstr(regs[RT2], regs[RT3])) { ! 320: p->subop = U(LONG,OP2); ! 321: regs[RT3][0] = '\0'; ! 322: } else ! 323: p->subop = U(LONG,OP3); ! 324: p->pop = 0; ! 325: newcode(p); ! 326: } ! 327: goto std; ! 328: } ! 329: ! 330: case SHAR: ! 331: case SHR: ! 332: { ! 333: /* bit tests: ! 334: ** shrl A,B,rC \ ! 335: ** bitl $1,rC > jbc A,B,D ! 336: ** jeql D / ! 337: */ ! 338: register struct node *pf; /* forward node */ ! 339: register struct node *pn; /* next node (after pf) */ ! 340: register int extreg; /* reg extracted to */ ! 341: ! 342: splitrand(p); ! 343: if(isreg(regs[RT1]) < 0) goto std; /* alignment */ ! 344: if (!tempreg(regs[RT3],extreg)) goto std; ! 345: if ((pf = p->forw)->op != BIT) goto std; ! 346: if (uses[extreg] && uses[extreg] != pf) goto std; ! 347: splitrand(pf); ! 348: if (regs[RT1][0] != '$') goto std; ! 349: if (getnum(®s[RT1][1]) != 1) goto std; ! 350: if (extreg != isreg(regs[RT2])) goto std; ! 351: if ((pn = pf->forw)->op != CBR) goto std; ! 352: if (pn->subop != JEQ && pn->subop != JNE) goto std; ! 353: delnode(p); delnode(pf); ! 354: pn->subop = (pn->subop == JEQ) ? JBC : JBS; ! 355: for(cp1=p->code; *cp1++!=',';); ! 356: while (*cp1!=',') cp1++; *cp1='\0'; ! 357: pn->code = p->code; pn->pop = NULL; ! 358: uses[extreg] = NULL; nbj++; ! 359: p = pn; ! 360: goto std; ! 361: } ! 362: ! 363: case AND: ! 364: { ! 365: /* unsigned conversion: ! 366: ** cvtbl A,B; andl2 $255,B > movzbl A,B ! 367: ** ! 368: ** also byte- and word-size fields: ! 369: ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B ! 370: ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B ! 371: */ ! 372: char src[C2_ASIZE]; ! 373: register int f; /* field length */ ! 374: register struct node *pb = p->back; /* backward node */ ! 375: ! 376: if (p->subop != U(LONG,OP2)) ! 377: goto std; ! 378: splitrand(p); cp1=regs[RT1]; ! 379: if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff) ! 380: goto std; ! 381: f = f==0xff ? 8 : 16; ! 382: if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR) ! 383: goto std; ! 384: /* save source of ANDL in 'src' */ ! 385: strcpy(src, regs[RT2]); ! 386: splitrand(pb); ! 387: if (!equstr(src,lastrand)) ! 388: goto std; ! 389: if (pb->op==CVT || pb->op==MOVZ) { ! 390: if (!(bitsize[pb->subop&0xF]==f ! 391: && bitsize[pb->subop>>4]>=f)) /* good CVT */ ! 392: goto std; ! 393: strcpy(src, regs[RT1]); ! 394: } else { ! 395: register int boff; /* bit offset */ ! 396: ! 397: if (regs[RT1][0] != '$') goto std; ! 398: if ((boff = getnum(®s[RT1][1])) < 0) goto std; ! 399: if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std; ! 400: if ((boff & (f-1)) != 0) goto std; ! 401: boff = (32-boff-f) / 8; ! 402: if (boff == 0) ! 403: strcpy(src, regs[RT2]); ! 404: else ! 405: sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+", ! 406: regs[RT2]); ! 407: } ! 408: delnode(pb); ! 409: p->op = MOVZ; ! 410: p->subop = U((f==8 ? BYTE : WORD), LONG); ! 411: sprintf(line,"%s,%s",src,lastrand); ! 412: p->pop=0; ! 413: p->code = copy(line); ! 414: goto std; ! 415: } ! 416: ! 417: case CMP: ! 418: { ! 419: /* comparison to -63 to -1: ! 420: ** cmpl r0,$-1 > incl r0 ! 421: ** jeql ... ! 422: ** ! 423: ** cmpl r0,$-63 > addl2 $63,r0 ! 424: ** jeql ... ! 425: */ ! 426: register int num; ! 427: register int reg; ! 428: register struct node *regp = p->back; ! 429: ! 430: if (p->forw->op != CBR) goto std; ! 431: if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; ! 432: splitrand(p); ! 433: if (strncmp(regs[RT2], "$-", 2) != 0) goto std; ! 434: reg = r = isreg(regs[RT1]); ! 435: if (r < 0) goto std; ! 436: if (r < NUSE && uses[r] != 0) goto std; ! 437: if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) ! 438: { ! 439: if (*regp->code != 'r') goto std; ! 440: reg = regp->code[1] - '0'; ! 441: if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) ! 442: goto std; ! 443: } ! 444: if (r >= NUSE) goto std; ! 445: if (reg != r) ! 446: sprintf(regs[RT1], "r%d", reg); ! 447: if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; ! 448: if (num == 1) ! 449: { ! 450: p->op = INC; regs[RT2][0] = '\0'; ! 451: } ! 452: else ! 453: { ! 454: register char *t; ! 455: ! 456: t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; ! 457: p->op = ADD; p->subop = U(p->subop, OP2); ! 458: for (t = ®s[RT1][2]; t[-1] = *t; t++) ; ! 459: } ! 460: p->pop = 0; newcode(p); ! 461: goto std; ! 462: } ! 463: ! 464: case JBR: case JMP: ! 465: clearuse(); ! 466: if ((p->subop&0xF)==RET) { ! 467: switch((p->subop>>4)&0xF) { ! 468: case 2: uses[1]=p; regs[1][0]= -1; ! 469: case 1: uses[0]=p; regs[0][0]= -1; ! 470: } ! 471: break; ! 472: } ! 473: if (p->ref==0) goto std; /* jmp (r0) */ ! 474: /* fall through */ ! 475: case CBR: ! 476: if (p->ref->ref!=0) { ! 477: for (r=NUSE;--r>=0;) ! 478: if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} ! 479: if ((1<<NUSE) & (int)p->ref->ref) useacc=p; ! 480: } ! 481: break; ! 482: case LNF: ! 483: /* lnf a; addf b ==> ldf b; subf a */ ! 484: { register struct node *pf = p->forw; ! 485: if(pf->op==ADDF && p->subop==pf->subop) { ! 486: p->op = LDF; ! 487: p->pop = 0; ! 488: pf->op = SUBF; ! 489: pf->pop = 0; ! 490: cp1 = p->code; ! 491: p->code = pf->code; ! 492: pf->code = cp1; ! 493: p = pf->forw; ! 494: break; ! 495: }} ! 496: case LDF: case LDFD: case CVLF: /* destroy acc */ ! 497: useacc = 0; ! 498: goto std; ! 499: case STF: ! 500: { register struct node *pf; ! 501: if((pf=flops(p)) != p) { ! 502: p = pf; /* usually p->forw; */ ! 503: break; ! 504: }} ! 505: if(ldmov(p)) { ! 506: p = p->forw; ! 507: break; ! 508: } ! 509: if(useacc == 0) ! 510: useacc = p; ! 511: goto std; ! 512: case ADDF: case MULF: /* commutatives - create clients for flops */ ! 513: /* stf a; ldf b; addf a => stf a; ldf a; addf b */ ! 514: { register struct node *pb = p->back; ! 515: register struct node *pbb = pb->back; ! 516: if(pb->op==LDF && pb->subop==p->subop && ! 517: pbb && pbb->op==STF && pbb->subop==p->subop && ! 518: equstr(pbb->code, p->code)) { ! 519: cp1 = p->code; ! 520: p->code = pb->code; ! 521: pb->code = cp1; ! 522: }} ! 523: /* use acc and regs */ ! 524: case CMPF: case CVFL: case SUBF: case DIVF: ! 525: if(useacc == 0) ! 526: useacc = p; ! 527: goto std; ! 528: case TSTF: ! 529: break; ! 530: case PUSHD: ! 531: if(ldmov(p)) { ! 532: p = p->forw; ! 533: break; ! 534: } ! 535: case CVDF: case NEGF: /* use only acc */ ! 536: case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: ! 537: if(useacc == 0) ! 538: useacc = p; ! 539: case EROU: case JSW: ! 540: case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; ! 541: } ! 542: } ! 543: for (p= &first; p!=0; p=p->forw) ! 544: if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ ! 545: } ! 546: ! 547: char * ! 548: byondrd(p) register struct node *p; { ! 549: /* return pointer to register which is "beyond last read/modify operand" */ ! 550: if (has2ops(p)) return(regs[RT3]); ! 551: switch (p->op) { ! 552: case MFPR: ! 553: case PUSHA: ! 554: case TST: case INC: case DEC: case PUSH: ! 555: case LDF: case LNF: case CVLF: case LDFD: ! 556: case ADDF: case SUBF: case MULF: case DIVF: ! 557: case CMPF: ! 558: return(regs[RT2]); ! 559: case MTPR: ! 560: #ifndef EMOD ! 561: case EDIV: ! 562: #endif EMOD ! 563: case CBR: /* must be JBC/JBS */ ! 564: case BIT: case CMP: case CALLS: case CALLF: ! 565: case CMPF2: ! 566: return(regs[RT3]); ! 567: case EMUL: ! 568: case PROBE: ! 569: case MOVBLK: ! 570: case CASE: ! 571: return(regs[RT4]); ! 572: } ! 573: return(lastrand); ! 574: } ! 575: ! 576: struct node * ! 577: bflow(p) ! 578: register struct node *p; ! 579: { ! 580: register char *cp1,*cp2,**preg; ! 581: register int r, fr, dblflg=0; ! 582: int flow= -1; ! 583: struct node *olduse=0, *olduse1=0; ! 584: ! 585: if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 || ! 586: p->op==EMUL) ! 587: dblflg |= 1; /* double dest */ ! 588: if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) ! 589: dblflg |= 2; /* double src */ ! 590: splitrand(p); ! 591: if (p->op!=PUSH && ! 592: #ifndef EMOD ! 593: p->op!=EDIV && ! 594: #endif EMOD ! 595: p->op!=EMUL && ! 596: p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { ! 597: if (equtype(p->subop,regs[r][0]) || ! 598: ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && ! 599: (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || ! 600: p->op==MOVA && compat(LONG, regs[r][0])) { ! 601: register int r2; ! 602: ! 603: if (regs[r][1]!=0) { /* send directly to destination */ ! 604: if (p->op==INC || p->op==DEC) { ! 605: p->op = (p->op==DEC) ? SUB : ADD; ! 606: /* use 2 now, convert to 3 later */ ! 607: p->subop=(OP2<<4)+(p->subop&0xF); ! 608: p->pop=0; ! 609: cp1=lastrand; cp2=regs[RT2]; ! 610: while (*cp2++= *cp1++) /* copy reg */ ! 611: ; ! 612: cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; ! 613: } ! 614: cp1=regs[r]+1; cp2=lastrand; ! 615: if (has2ops(p)) { ! 616: /* use 3 operand form of instruction */ ! 617: p->pop=0; ! 618: p->subop += (OP3-OP2)<<4; ! 619: lastrand = cp2 = regs[RT3]; ! 620: } ! 621: while (*cp2++= *cp1++) ! 622: ; ! 623: if (p->op==MOVA && p->forw->op==PUSH) { ! 624: p->op=PUSHA; ! 625: *regs[RT2]=0; p->pop=0; ! 626: } else if ((p->op==MOV || p->op==CVT) && ! 627: p->forw->op==PUSH) { ! 628: p->op=PUSH; p->subop &= 0xF; ! 629: *regs[RT2]=0; p->pop=0; ! 630: } ! 631: delnode(p->forw); ! 632: if (tempreg(lastrand,r2)) ! 633: uses[r2]=uses[r], uses[r]=0; ! 634: redun3(p); ! 635: newcode(p); redunm++; flow=r; ! 636: } else if (p->op==MOV) { /* superfluous fetch */ ! 637: int nmatch; ! 638: char src[C2_ASIZE]; ! 639: movit: ! 640: for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) ! 641: ; ! 642: splitrand(p->forw); ! 643: if (p->forw->op != INC && p->forw->op != DEC) ! 644: lastrand=byondrd(p->forw); ! 645: nmatch=0; ! 646: for (preg=regs+RT1;*preg!=lastrand;preg++) ! 647: if (r==isreg(*preg)) { ! 648: cp2= *preg; cp1=src; ! 649: while (*cp2++= *cp1++) ! 650: ; ! 651: ++nmatch; ! 652: } ! 653: if (nmatch==1) { ! 654: if (has2ops(p->forw) && equstr(src,regs[RT2])) { ! 655: p->forw->pop=0; ! 656: p->forw->subop += (OP3-OP2)<<4; ! 657: cp1=regs[RT3]; ! 658: *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; ! 659: } ! 660: delnode(p); ! 661: p=p->forw; ! 662: if (tempreg(src,r2)) ! 663: uses[r2]=uses[r], uses[r]=0; ! 664: redun3(p); ! 665: newcode(p); redunm++; ! 666: return(p); /* avoid stale uses[] data */ ! 667: } else ! 668: splitrand(p); ! 669: } ! 670: } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && ! 671: p->forw->subop&0xf && /* if base or index, then forget it */ ! 672: compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) ! 673: goto movit; ! 674: } ! 675: /* adjust 'lastrand' past any 'read' or 'modify' operands. */ ! 676: lastrand=byondrd(p); ! 677: /* a 'write' clobbers the register. */ ! 678: if (tempreg(lastrand,r) || ! 679: (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) { ! 680: /* ! 681: * Writing a dead register is useless, ! 682: * but watch side effects ! 683: */ ! 684: switch (p->op) { ! 685: #ifndef EMOD ! 686: case EDIV: ! 687: #endif EMOD ! 688: case AOBLEQ: case AOBLSS: ! 689: break; ! 690: default: ! 691: /* ! 692: * If no direct uses, check for ! 693: * use of condition codes ! 694: */ ! 695: if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { ! 696: register struct node *q = p; ! 697: ! 698: while ((q = nonlab(q->forw))->op==JBR && ! 699: q->subop==0) ! 700: q=q->ref; /* cc unused, unchanged */ ! 701: if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { ! 702: /* ... and destroyed */ ! 703: preg=regs+RT1; ! 704: while (cp1 = *preg++) { ! 705: if (cp1==lastrand && ! 706: p->op != CLR && ! 707: p->op != CVFL) { ! 708: redunm++; ! 709: delnode(p); ! 710: return(p->forw); ! 711: } ! 712: if (equstr(cp1,lastrand)) ! 713: break; ! 714: } ! 715: } ! 716: } ! 717: flow=r; ! 718: } ! 719: } ! 720: if ((r=flow) >= 0) { ! 721: olduse=uses[r], uses[r]=0; ! 722: *(short *)(regs[r])=0; ! 723: /* if r0 destroyed, dont keep r1 */ ! 724: if (dblflg&1) { ! 725: olduse1=uses[++r], uses[r]=0; ! 726: *(short *)(regs[r])=0; ! 727: } ! 728: } ! 729: /* now look for 'read' or 'modify' (read & write) uses */ ! 730: preg=regs+RT1; ! 731: while (*(cp1= *preg++)) { ! 732: /* check for r */ ! 733: if (lastrand!=cp1 && tempreg(cp1,r)) { ! 734: int isunused; ! 735: if (isunused=(uses[r]==0)) { ! 736: uses[r]=p; ! 737: cp2=regs[r]; *cp2++=p->subop; ! 738: if ((p->op==SHAL || p->op==SHAR || ! 739: p->op==SHL || p->op==SHR) && ! 740: cp1==regs[RT1]) ! 741: cp2[-1] = BYTE; ! 742: if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) ! 743: cp2[-1] = LONG; ! 744: if (p->op==MOVA && cp1==regs[RT2]) ! 745: cp2[-1]=LONG; ! 746: } ! 747: /* ediv/emod's 2nd operand is quad */ ! 748: if (((p->op==EDIV ! 749: #ifdef EMOD ! 750: || p->op==EMOD ! 751: #endif EMOD ! 752: ) && cp1==regs[RT2] || (dblflg&2)) && ! 753: ++r<NUSE && uses[r]==0) { ! 754: if (isunused) ! 755: *cp2=0; ! 756: uses[r]=p; ! 757: cp2=regs[r]; *cp2++=p->subop; ! 758: if (!isunused) ! 759: *cp2=0; ! 760: } ! 761: if (!isunused) ! 762: continue; ! 763: if (p->op==MOV || p->op==PUSH || p->op==CVT || ! 764: p->op==MOVZ || p->op==COM || p->op==NEG || ! 765: p->op==STF) { ! 766: if (p->op!=PUSH) { ! 767: cp1=regs[RT2]; ! 768: if (tempreg(cp1,r)) { ! 769: /* ! 770: * reincarnation!! ! 771: * (as in addl2 r0,r1; ! 772: * movl r1,r0; ret) ! 773: */ ! 774: if (uses[r]==0) ! 775: uses[r]=olduse; ! 776: if ((dblflg&1) && uses[r+1]==0) ! 777: uses[r+1]=olduse1; ! 778: } ! 779: if (p->op!=MOV) ! 780: cp1=0; ! 781: } else ! 782: cp1="-(sp)"; ! 783: if (cp1) ! 784: while (*cp2++= *cp1++) ! 785: ; ! 786: else ! 787: *cp2=0; ! 788: } else ! 789: *cp2=0; ! 790: continue; ! 791: } ! 792: /* check for (r),[r] */ ! 793: do { ! 794: if (*cp1=='(' || *cp1=='[') { /* get register number */ ! 795: char t; ! 796: for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) ! 797: ; ! 798: t= *cp1; *cp1=0; ! 799: if (tempreg(cp2,r) && ! 800: (uses[r]==0 || uses[r]==p)) { ! 801: uses[r]=p; ! 802: regs[r][0] = ! 803: (*--cp2=='[' ? OPX<<4 : OPB<<4); ! 804: regs[r][1] = '\0'; ! 805: } ! 806: *cp1=t; ! 807: } ! 808: } while (*++cp1); ! 809: } ! 810: #ifdef MOVAFASTER ! 811: /* pushax or movax possibility? */ ! 812: cp1=regs[RT1]; ! 813: if (*cp1++=='$' && isstatic(cp1)) { ! 814: if (p->op==MOV && p->subop==LONG) { ! 815: if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { ! 816: cp1=p->code; while (*cp1++!=','); p->code= --cp1; ! 817: } ! 818: p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; ! 819: } else if (p->op==PUSH && p->subop==LONG) { ! 820: p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; ! 821: } else if (p->op==ADD && p->subop==U(LONG,OP3) ! 822: && 0<=(r=isreg(regs[RT2]))) { ! 823: cp1=cp2=p->code; ++cp1; ! 824: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; ! 825: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; ! 826: if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} ! 827: else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} ! 828: if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} ! 829: p->pop=0; ! 830: } ! 831: } ! 832: #endif MOVAFASTER ! 833: return (p); ! 834: } ! 835: ! 836: /* try to eliminate STF's */ ! 837: struct node * ! 838: flops(q) ! 839: register struct node *q; ! 840: { ! 841: register struct node *p; ! 842: register int r; ! 843: ! 844: if(q->op!=STF || !tempreg(q->code,r)) ! 845: return(q); ! 846: if(uses[r]) { ! 847: /* see if anyone destroys acc between us */ ! 848: for(p=q->forw; p!=uses[r]; p=p->forw) ! 849: switch(p->op) { ! 850: case LABEL: ! 851: case LDF: case LNF: case CVLF: case LDFD: ! 852: case CVDF: case NEGF: case ADDF: case SUBF: ! 853: case MULF: case DIVF: case SINF: case COSF: ! 854: case ATANF: case LOGF: case SQRTF: case EXPF: ! 855: return(q); ! 856: } ! 857: again: ! 858: if(q->subop == p->subop) ! 859: switch(p->op) { /* do it in the accumulator */ ! 860: case LDF: /* redundant load */ ! 861: delnode(p); nld++; ! 862: p = p->forw; ! 863: break; ! 864: case LNF: /* stf r; lnf r ==> negf */ ! 865: p->op = NEGF; ! 866: p->pop = 0; ! 867: p->code = 0; ! 868: break; ! 869: case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ ! 870: { register char *s; ! 871: register struct node *p1=p->forw; ! 872: for(s=p->code; *s!=','; s++); ! 873: *s = 0; ! 874: if(isreg(p->code) == r) ! 875: p->code = s+1; ! 876: else { ! 877: if(p1->op != CBR || isreg(s+1) != r) { ! 878: *s = ','; ! 879: return(q); ! 880: } ! 881: if(p1->subop > JNE) { ! 882: p1->subop ^= 1; ! 883: p1->pop = 0; ! 884: nrevbr++; ! 885: } ! 886: } ! 887: p->op = CMPF; ! 888: p->pop = 0; ! 889: } ! 890: break; ! 891: default: ! 892: return(q); ! 893: } ! 894: else if(p->subop==LONG) { ! 895: switch(p->op) { ! 896: case TST: /* stf r; tstl r ==> tstf */ ! 897: p->op = TSTF; ! 898: p->code = 0; ! 899: break; ! 900: /* send directly to destination */ ! 901: case MOV: /* stf r; movl r,x ==> stf x */ ! 902: case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ ! 903: if(q->subop == DOUBLE) { ! 904: register struct node *b = p->back; ! 905: /* assume b's 2nd arg is ok */ ! 906: if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) ! 907: return(q); ! 908: delnode(b); redunm++; ! 909: } ! 910: if(p->op==PUSH) { ! 911: if(q->subop == DOUBLE) { ! 912: p->op = PUSHD; ! 913: p->code = 0; ! 914: } else { ! 915: p->op = q->op; ! 916: p->code = copy("-(sp)"); ! 917: } ! 918: } else { ! 919: p->op = q->op; ! 920: while(*p->code++ != ','); ! 921: } ! 922: break; ! 923: default: ! 924: return(q); ! 925: } ! 926: p->pop = 0; ! 927: p->subop = q->subop; ! 928: } else ! 929: return(q); ! 930: uses[r] = 0; ! 931: if(q->subop == DOUBLE) ! 932: uses[r+1] = 0; ! 933: for(p = p->back; p != q && (!uses[r] || !uses[r+1]); p = p->back) { ! 934: int xr; ! 935: ! 936: splitrand(p); ! 937: if((xr=isreg(regs[RT1])) < 0) ! 938: continue; ! 939: if(!uses[r] && xr == r) ! 940: uses[r] = p; ! 941: else if(q->subop == DOUBLE && !uses[r+1] && xr == r+1) ! 942: uses[r+1] = p; ! 943: } ! 944: if(p = uses[r]) ! 945: goto again; ! 946: return(q->forw); /* DON'T re-scan code with dated uses[] */ ! 947: } ! 948: /* it's a store to reg which isnt used elsewhere */ ! 949: if((p=q->forw)->op == CBR) { ! 950: q->op = TSTF; ! 951: q->pop = 0; ! 952: q->code = 0; ! 953: } else { ! 954: delnode(q); nst++; ! 955: if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { ! 956: if(useacc == p) ! 957: useacc = 0; ! 958: return(p->forw); /* so ldmov can be used on p */ ! 959: } ! 960: } ! 961: return(p); ! 962: } ! 963: ! 964: /* try to change load/store sequences to movl */ ! 965: ldmov(q) ! 966: register struct node *q; ! 967: { ! 968: register struct node *p; ! 969: register char *s, *pcod, *cp; ! 970: char *dlsw(); ! 971: ! 972: p = q->back; ! 973: if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) ! 974: && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) ! 975: return(0); ! 976: pcod = p->code; ! 977: cp = p->code; ! 978: /* prepare args for movl/pushl */ ! 979: if(q->op!=TSTF && q->subop==DOUBLE) { ! 980: if(p->op == LDF) { ! 981: if((s = dlsw(p->code)) == NULL) ! 982: return(0); ! 983: ! 984: strcpy(line, s); ! 985: if(q->op == STF) { ! 986: strcat(line, ","); ! 987: if((s = dlsw(q->code)) == NULL) ! 988: return(0); ! 989: strcat(line, s); ! 990: p->op = MOV; ! 991: } else ! 992: p->op = PUSH; ! 993: } else { /* LDFD */ ! 994: if(q->op == STF) { ! 995: if((s = dlsw(q->code)) == NULL) ! 996: return(0); ! 997: } else ! 998: s = "-(sp)"; ! 999: strcpy(line, s); ! 1000: p->op = CLR; ! 1001: } ! 1002: p->pop = 0; ! 1003: p->subop = LONG; ! 1004: p->code = copy(line); ! 1005: } else ! 1006: { ! 1007: if ((p->op == LDF) && (p->subop == DOUBLE) && ! 1008: (indexa(cp))) return(0); ! 1009: delnode(p); ! 1010: } ! 1011: strcpy(line, pcod); ! 1012: if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ ! 1013: strcat(line, ","); ! 1014: strcat(line, q->code); ! 1015: q->op = MOV; ! 1016: nst++; ! 1017: } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ ! 1018: q->op = TST; ! 1019: else /* ldd x; pushd ==> pushl x+4; pushl x */ ! 1020: q->op = PUSH; ! 1021: q->pop = 0; ! 1022: q->subop = LONG; ! 1023: q->code = copy(line); ! 1024: nld++; ! 1025: return(1); ! 1026: } ! 1027: ! 1028: /* reconstruct the address of l.s.w. of a double operand */ ! 1029: char * ! 1030: dlsw(d) ! 1031: register char *d; ! 1032: { ! 1033: register char *s, *t, *c; ! 1034: register int r; ! 1035: static char lsw[C2_ASIZE]; ! 1036: ! 1037: if(d[0] == '*' || d[0] == '$') ! 1038: return(NULL); ! 1039: if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) ! 1040: return(NULL); ! 1041: t = lsw; ! 1042: if((r=isreg(d)) >= 0) ! 1043: sprintf(t, "r%d", r+1); ! 1044: else { ! 1045: for(s=d; *s && *s!='('; *t++ = *s++) ! 1046: if(*s == '[') ! 1047: return(NULL); ! 1048: if(s!=d) ! 1049: *t++ = '+'; ! 1050: *t++ = '4'; ! 1051: while(*t++ = *s) ! 1052: if(*s++ == '[' ) ! 1053: { ! 1054: return(NULL); ! 1055: } ! 1056: } ! 1057: return(lsw); ! 1058: } ! 1059: checkexpr(p) ! 1060: register char *p; ! 1061: { ! 1062: ! 1063: while(*p && *p != ','){ ! 1064: if ((*p == '+' ) || (*p == '-')) ! 1065: return(1); ! 1066: *p++; ! 1067: } ! 1068: return(0); ! 1069: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.