📄 c21.c
字号:
case INC: case DEC: splitrand(p); dest(lastrand,p->subop); if (p->op==CLR) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0", p->subop); else setcon("$0", regs[RT1], p->subop); break;/* .rx */ case TST: case PUSH: splitrand(p); lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */ repladdr(p); if (p->op==TST && equstr(lastrand=regs[RT1], ccloc+1) && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop)) &&!source(lastrand)) { delnode(p); p = p->back; nrtst++; nchange++; } setcc(lastrand,p->subop); break;/* .rx,.rx,.rx */ case PROBER: case PROBEW: case CASE: case MOVC3:/* .rx,.rx */ case MTPR: case CALLS: case CMP: case BIT: splitrand(p); /* fool repladdr into doing right number of operands */ if (p->op==CASE || p->op==PROBER || p->op==PROBEW) lastrand=regs[RT4];/* else if (p->op==CMPV || p->op==CMPZV) lastrand=regs[RT4+1]; */ else if (p->op==MOVC3) lastrand=regs[RT1]; else lastrand=regs[RT3]; repladdr(p); if (p->op==CALLS || p->op==MOVC3) clearreg(); if (p->op==BIT) bitopt(p); ccloc[0]=0; break; case CBR: if (p->subop>=JBC) { splitrand(p); if (p->subop<JBCC) lastrand=regs[RT3]; /* 2 operands can be optimized */ else lastrand=regs[RT2]; /* .mb destinations lose */ repladdr(p); } ccloc[0] = 0; break; case JBR: redunbr(p);/* .wx,.bb */ case SOB: default: clearreg(); } }}char *byondrd(p) register struct node *p; {/* return pointer to register which is "beyond last read/modify operand" */ if (OP2==(p->subop>>4)) return(regs[RT3]); switch (p->op) { case MFPR: case JSB: case PUSHA: case TST: case INC: case DEC: case PUSH: return(regs[RT2]); case MTPR: case BIT: case CMP: case CALLS: return(regs[RT3]); case PROBER: case PROBEW: case CASE: case MOVC3: return(regs[RT4]); } return(lastrand);}struct node *bflow(p)register struct node *p;{ register char *cp1,*cp2,**preg; register int r; int flow= -1; struct node *olduse=0; splitrand(p); if (p->op!=PUSH && p->subop && 0<=(r=isreg(lastrand)) && r<NUSE && uses[r]==p->forw) { if (equtype(p->subop,regs[r][0]) || ((p->op==CVT || p->op==MOVZ) && 0xf®s[r][0] && compat(0xf&(p->subop>>4),regs[r][0]))) { register int r2; if (regs[r][1]!=0) {/* send directly to destination */ if (p->op==INC || p->op==DEC) { if (p->op==DEC) p->op=SUB; else p->op=ADD; p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */ p->pop=0; cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */ cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; } cp1=regs[r]+1; cp2=lastrand; if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */ p->pop=0; p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3]; } while (*cp2++= *cp1++); if (p->op==MOVA && p->forw->op==PUSH) { p->op=PUSHA; *regs[RT2]=0; p->pop=0; } else if (p->op==MOV && p->forw->op==PUSH) { p->op=PUSH ; *regs[RT2]=0; p->pop=0; } delnode(p->forw); if (0<=(r2=isreg(lastrand)) && r2<NUSE) { uses[r2]=uses[r]; uses[r]=0; } redun3(p,0); newcode(p); redunm++; flow=r; } else if (p->op==MOV && p->forw->op!=EXTV && p->forw->op!=EXTZV) { /* superfluous fetch */ int nmatch; char src[C2_ASIZE]; movit: cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++); splitrand(p->forw); if (p->forw->op != INC && p->forw->op != DEC) lastrand=byondrd(p->forw); nmatch=0; for (preg=regs+RT1;*preg!=lastrand;preg++) if (r==isreg(*preg)) { cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch; } if (nmatch==1) { if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) { p->forw->pop=0; p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3]; *cp1++='r'; *cp1++=r+'0'; *cp1=0; } delnode(p); p=p->forw; if (0<=(r2=isreg(src)) && r2<NUSE) { uses[r2]=uses[r]; uses[r]=0; } redun3(p,0); newcode(p); redunm++; flow=r; } else splitrand(p); } } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && p->forw->subop&0xf /* if base or index, then forget it */ && compat(p->subop,p->forw->subop) && !source(cp1=regs[RT1]) && !indexa(cp1)) goto movit; } /* adjust 'lastrand' past any 'read' or 'modify' operands. */ lastrand=byondrd(p); /* a 'write' clobbers the register. */ if (0<=(r=isreg(lastrand)) && r<NUSE || OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE && uses[r]==0) { /* writing a dead register is useless, but watch side effects */ switch (p->op) { case ACB: case AOBLEQ: case AOBLSS: case SOBGTR: case SOBGEQ: break; default: if (uses[r]==0) {/* no direct uses, check for use of condition codes */ register struct node *q=p; while ((q=nonlab(q->forw))->combop==JBR) q=q->ref; /* cc unused, unchanged */ if (q->op!=CBR) {/* ... and destroyed */ preg=regs+RT1; while (cp1= *preg++) { if (cp1==lastrand) {redunm++; delnode(p); return(p->forw);} if (source(cp1) || equstr(cp1,lastrand)) break; } } } flow=r; } } if (0<=(r=flow)) {olduse=uses[r]; uses[r]=0; *(short *)(regs[r])=0;} /* these two are here, rather than in bmove(), /* because I decided that it was better to go for 3-address code /* (save time) rather than fancy jbxx (save 1 byte) /* on sequences like bisl2 $64,r0; movl r0,foo */ if (p->op==BIC) {p=bicopt(p); splitrand(p); lastrand=byondrd(p);} if (p->op==BIS) {bixprep(p,JBSS); lastrand=byondrd(p);} /* now look for 'read' or 'modify' (read & write) uses */ preg=regs+RT1; while (*(cp1= *preg++)) { /* check for r */ if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0) { uses[r]=p; cp2=regs[r]; *cp2++=p->subop; if (p->op==ASH && preg==(regs+RT1+1)) cp2[-1]=BYTE; /* stupid DEC */ if (p->op==MOV || p->op==PUSH || p->op==CVT || p->op==MOVZ || p->op==COM || p->op==NEG) { if (p->op==PUSH) cp1="-(sp)"; else { cp1=regs[RT2]; if (0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0) uses[r]=olduse; /* reincarnation!! */ /* as in addl2 r0,r1; movl r1,r0; ret */ if (p->op!=MOV) cp1=0; } if (cp1) while (*cp2++= *cp1++); else *cp2=0; } else *cp2=0; continue; } /* check for (r),(r)+,-(r),[r] */ do if (*cp1=='(' || *cp1=='[') {/* get register number */ char t; cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0; if (0<=(r=isreg(cp2)) && r<NUSE && (uses[r]==0 || uses[r]==p)) { uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4); } *cp1=t; } while (*++cp1); } /* pushax or movax possibility? */ cp1=regs[RT1]; if (*cp1++=='$' && isstatic(cp1) && natural(regs[RT1])) { if (p->combop==T(MOV,LONG)) { if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { cp1=p->code; while (*cp1++!=','); p->code= --cp1; } p->combop=T(MOVA,LONG); ++p->code; p->pop=0; } else if (p->combop==T(PUSH,LONG)) { p->combop=T(PUSHA,LONG); ++p->code; p->pop=0; } else if ((p->combop&0xFFFF)==T(ADD,U(LONG,OP3)) && 0<=(r=isreg(regs[RT2]))) { cp1=cp2=p->code; ++cp1; do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; if (!equstr(regs[RT3],"-(sp)")) p->combop=T(MOVA,BYTE); else {p->combop=T(PUSHA,BYTE); *cp2=0;} if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} p->pop=0; } } return(p);}ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */ register int log; if (n==0 || n&(n-1)) return(-1); log=0; for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}}bitopt(p) register struct node *p; { /* change "bitx $<power_of_2>,a" followed by JEQ or JNE /* into JBC or JBS. watch out for I/O registers. (?) /* assumes that 'splitrand' has already been called. */ register char *cp1,*cp2; int b; cp1=regs[RT1]; cp2=regs[RT2]; if (*cp1++!='$' || !okio(cp2) || p->forw->op!=CBR || p->forw->subop&-2 || 0>(b=ispow2(getnum(cp1))) || p->subop!=BYTE && (source(cp2) || indexa(cp2))) return; if (b>=bitsize[p->subop]) {/* you dummy! */ if (source(cp2)) {/* side effect: auto increment or decrement */ p->pop=0; p->op=TST; --cp1; while (*cp1++= *cp2++); regs[RT2][0]=0; newcode(p); } else delnode(p); p = p->forw; if (p->subop==JEQ) {p->combop=JBR; p->pop=0;} else delnode(p); nchange++; nbj++; return; } if (cp1=p->forw->code) {/* destination is not an internal label */ cp2=regs[RT3]; while (*cp2++= *cp1++); } if (b==0 && (p->subop==LONG || !indexa(regs[RT2]))) {/* JLB optimization, ala BLISS */ cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); cp2=regs[RT2]; cp1=regs[RT3]; while (*cp2++= *cp1++); *(regs[RT3])=0; p->forw->subop += JLBC-JBC; p->forw->pop=0; } else { cp1=regs[RT1]+1; if (b>9) *cp1++= b/10 +'0'; *cp1++= b%10 +'0'; *cp1=0; /* $<bit_number> */ } nbj++; newcode(p); p->combop = p->forw->combop+((JBC-JEQ)<<8); p->labno = p->forw->labno; delnode(p->forw); p->pop=0;}isfield(n) register long n; {/* -1 -> no; else -> position of low bit */ register int pos; register long t; t= ((n-1)|n) +1; if (n!=0 && (0==t || 0==n || 0<=ispow2(t))) { pos=0; while(!(n&1)) {n >>= 1; ++pos;} return(pos); } else return(-1);}bixprep(p,bix) register struct node *p; {/* initial setup, single-bit checking for bisopt, bicopt./* return: 0->don't bother any more; 1->worthwhile trying*/ register char *cp1,*cp2; splitrand(p); cp1=regs[RT1]; cp2=regs[RT2]; if (*cp1++!='$' || 0>(pos=isfield(f=getnum(cp1))) || !okio(cp2) || indexa(cp2) || source(cp2) || !okio(lastrand)) return(0); f |= f-1; if (++f==0) siz=32-pos; else siz=ispow2(f)-pos; if (siz==1 && pos>5 && (p->subop>>4)==OP2 && (p->subop&0xF)!=BYTE && pos<bitsize[p->subop&0xF]) { p->ref = insertl(p->forw); p->combop = CBR | (bix<<8); p->pop=0; p->labno = p->ref->labno; if (pos>9) {*cp1++= pos/10 +'0'; pos %= 10;} *cp1++=pos+'0'; *cp1=0; newcode(p); nbj++; return(0); } return(1);}struct node *bicopt(p) register struct node *p; {/* use field operations or MOVZ if possible. done as part of 'bflow'.*/ register char *cp1,*cp2; int r; char src[C2_ASIZE]; if (!bixprep(p,JBCC)) return(p); if (f==0) {/* the BIC isolates low order bits */ siz=pos; pos=0; if ((p->subop&0xF)==LONG && *(regs[RT2])!='$') {/* result of EXTZV is long */ /* save source of BICL in 'src' */ cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++); if (p->back->op==ASH) {/* try for more */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT3]; if (*cp1++=='$' && *(regs[RT2])!='$' && !indexa(regs[RT2]) && 0>(f=getnum(cp1)) && equstr(src,cp2) && 0<=(r=isreg(cp2)) && r<NUSE) {/* a good ASH */ pos -= f; cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++); delnode(p->back); } } if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; if (equstr(src,cp2) && okio(cp1) && !indexa(cp1) && 0<=(r=isreg(cp2)) && r<NUSE && bitsize[p->back->subop&0xF]>=(pos+siz) && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ cp1=regs[RT1]; cp2=src; while (*cp2++= *cp1++); delnode(p->back); } } /* 'pos', 'siz' known; source of field is in 'src' */ splitrand(p); /* retrieve destination of BICL */ if (siz==8 && pos==0) { p->combop = T(MOVZ,U(BYTE,LONG)); sprintf(line,"%s,%s",src,lastrand); } else { p->combop = T(EXTZV,LONG); sprintf(line,"$%d,$%d,%s,%s",pos,siz,src,lastrand); } p->pop=0; p->code = copy(line); nfield++; return(p); }/* end EXTZV possibility */ }/* end low order bits *//* unfortunately, INSV clears the condition codes, thus cannot be used *//* else {/* see if BICL2 of positive field should be INSV $0 *//* if (p->subop==(LONG | (OP2<<4)) && 6<=(pos+siz)) {/* p->combop = INSV;/* sprintf(line,"$0,$%d,$%d,%s",pos,siz,lastrand);/* p->code = copy(line); nfield++; return(p);/* }/* }*/ return(p);}jumpsw(){ register struct node *p, *p1; register t; int nj; t = 0; nj = 0; for (p=first.forw; p!=0; p = p->forw) p->seq = ++t; for (p=first.forw; p!=0; p = p1) { p1 = p->forw; if (p->op == CBR && p1->op==JBR && p->ref && p1->ref && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) { if (p->ref==p1->ref) continue; p->subop = revbr[p->subop]; p->pop=0; t = p1->ref; p1->ref = p->ref; p->ref = t; t = p1->labno; p1->labno = p->labno; p->labno = t;#ifdef COPYCODE if (p->labno == 0) { t = p1->code; p1->code = p->code; p->code = t; }#endif nrevbr++; nj++; } } return(nj);}addsob(){ register struct node *p, *p1, *p2, *p3; for (p = &first; (p1 = p->forw)!=0; p = p1) { if (p->combop==T(DEC,LONG) && p1->op==CBR) { if (abs(p->seq - p1->ref->seq) > 8) continue; if (p1->subop==JGE || p1->subop==JGT) { if (p1->subop==JGE) p->combop=SOBGEQ; else p->combop=SOBGTR; p->pop=0; p->labno = p1->labno; delnode(p1); nsob++; } } else if (p->combop==T(INC,LONG)) { if (p1->op==LABEL && p1->refc==1 && p1->forw->combop==T(CMP,LONG) && (p2=p1->forw->forw)->combop==T(CBR,JLE) && (p3=p2->ref->back)->combop==JBR && p3->ref==p1 && p3->forw->op==LABEL && p3->forw==p2->ref) { /* change INC LAB: CMP to LAB: INC CMP */ p->back->forw=p1; p1->back=p->back; p->forw=p1->forw; p1->forw->back=p; p->back=p1; p1->forw=p; p1=p->forw; /* adjust beginning value by 1 */ p2=alloc(sizeof first); p2->combop=T(DEC,LONG); p2->pop=0; p2->forw=p3; p2->back=p3->back; p3->back->forw=p2; p3->back=p2; p2->code=p->code; p2->labno=0; } if (p1->combop==T(CMP,LONG) && (p2=p1->forw)->op==CBR) { register char *cp1,*cp2; splitrand(p1); if (!equstr(p->code,regs[RT1])) continue; if (abs(p->seq - p2->ref->seq)<8) {/* inside byte displ range */ if (p2->subop!=JLE) continue; /* * acbl take twice as long as aobleq * so changed to aobleq - dm 1/19/82 */ p->combop=AOBLEQ; cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */ cp2=regs[RT2]; cp1=p->code; while (*cp2++ = *cp1++); /* index */ p->pop=0; newcode(p); p->labno = p2->labno; delnode(p2); delnode(p1); nsob++; } else if (abs(p->seq - p2->ref->seq)>8) {/* outside byte displ range */ if (p2->subop!=JLE) continue; p->combop=T(ACB,LONG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -