📄 c21.c
字号:
} 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 *opr_1 = regs[RT1], *opr_2 = regs[RT2]; register int bit_number; if ((p->forw->combop != T(CBR,JEQ)) && (p->forw->combop != T(CBR,JNE))) /* * If the next operation is not jeql or jneq then it * can't be changed. */ return; if (*opr_1 != '$') /* * If the src is not immediate then don't optimize. */ return; /* Get the value of the mask and convert it to a bit number. */ bit_number = ispow2(getnum(&opr_1[1])); if ( (bit_number < 0) || (bit_number>=bitsize[p->subop])) /* If it is not a power of two, ie. single bit then don't * optimize. If the bit is greater than the highest bit in * the in the entity to be tested, then don't attempt to * optimize, since this might mask a bug in someone's code. * Just let it go through and the assembler will complain. */ return; if ( !okio(opr_2) ) /* * If the operand being tested might be an I/O register, * then do nothing. */ return; if (p->subop == LONG) { /* * Index mode can be used with a LONG operand, only if * this will be converted to a jbl[cs]. */ if ((bit_number != 0) && indexa(opr_2)) { return ; } } else if (source(opr_2)) { /* * Auto{in,de}crement mode can be used only with LONG * operands */ return ; } else if ((p->subop != BYTE) && indexa(opr_2)) { /* * Index mode can be used only with BYTE operands, except * for the case mentioned above. */ return; } /* Now try to optimize. */ if (bit_number==0 && (p->subop==LONG || !indexa(opr_2))) { /* * bitx $1,dst \ * - jlbx dst, label * jxxx label / * * The $1 is thrown away, the dst becomes the first operand * and the label is either the label from the jxxx or an * internally generated label which will be based on the * value in p->forw->labno. */ if (p->forw->code) new_operands(p,"%s,%s",opr_2,p->forw->code); else new_operands(p,"%s",opr_2); p->forw->subop += JLBC-JBC; p->forw->pop=0; } else { /* * bitx $n,dst \ * - jbx $bit_number,dst,label * jxxx label / * * Reformat the operands appropriately. */ if (p->forw->code) new_operands(p, "$%d,%s,%s", bit_number,opr_2,p->forw->code); else new_operands(p,"$%d,%s",bit_number,opr_2); } p->combop = p->forw->combop+((JBC-JEQ)<<8); p->labno = p->forw->labno; delnode(p->forw); p->pop=0; nbj++; }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; return(1);}struct node *bicopt(p) register struct node *p; {/* Try to replace a BICLn instruction with a MOVZxL or EXTZV instruction. If * the BICLn is preceded by an ASH or {CVTxL|MOVZxL} or a {CVTxL|MOVZxl} / * ASH these may also be optimized out. Done as part of 'bflow'. */ register char *cp1,*cp2; register struct node *back; /* previous node */ int r; /* register number */ int deleted = 0 ; /* ASH, CVT, or MOVZ deleted? */ register int mov_src ; /* If non-zero, indicates size of the * MOVZxL which can replace the BICL. */ char src[C2_ASIZE]; /* source of BICL */ /* Do some preliminary tests to see if we can optimize the BIC */ if (!bixprep(p,JBCC)) return(p); if ((f!=0) /* doesn't isolate low order bits */ || (p->subop&0xF)!=LONG /* result isn't long, ie. BICL */ || *(regs[RT2])=='$') /* src of BICL3 is immediate */ return(p); siz=pos; pos=0; /* Save source of BICL */ cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++); /* If the preceding instruction is an ASH see if it can be deleted. */ back = p->back; if (back->op==ASH) {/* try for more */ splitrand(back); cp1=regs[RT1]; cp2=regs[RT3]; if (*cp1++=='$' && okio(regs[RT2]) && okio(cp2) && *(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(back); back = p->back; /* get new previous node */ deleted++; } } /* "pos" and "siz" are known. Find out if we can turn * the BICL into a MOVZxL or an EXTZV. (0002) */ if (pos == 0) { if (siz == 8) mov_src = BYTE; /*MOVZBL*/ else if (siz == 16) mov_src = WORD; /*MOVZWL*/ else mov_src = 0; /*EXTZV */ } else mov_src = 0 ; /*EXTZV */ /* If the previous instruction is now a CVT or a MOVZ * we may be able to delete it. */ if (back->op==CVT || back->op==MOVZ) { /* What is the source operand type for the CVT or MOVZ? */ register int src_type = back->subop & 0xF ; /* Get the operand strings for the instruction */ splitrand(back); cp1=regs[RT1]; /* source operand address */ cp2=regs[RT2]; /* destination " " */ /* We can delete the instruction if: * - dst is the same as src of the BIC * - src isn't in I/O space * - src isn't indexing mode or auto(in|de)crement mode * unless the mov_src is the same as the src_type (0002) * - src isn't a floating point type (0002) * - dst is a usable register * - the bit field fits within the src & dst */ if (equstr(src,cp2) && okio(cp1) && src_type != FFLOAT && src_type != DFLOAT && src_type != GFLOAT && src_type != HFLOAT && ((!indexa(cp1) && !autoid(cp1)) || mov_src == src_type) && 0<=(r=isreg(cp2)) && r<NUSE && bitsize[src_type]>=(pos+siz) && bitsize[back->subop>>4]>=(pos+siz)) { /* We can get rid of the instruction. Use the src of * this instruction for the src of the MOVZ or EXTZV * which replaces it. */ cp1=regs[RT1]; cp2=src; while (*cp2++= *cp1++); delnode(back); deleted++; } } splitrand(p); /* Retrieve destination of BICL into "lastrand". */ if (mov_src) { /* Replace the BICL with a MOVZxL instruction. */ p->combop = T(MOVZ,U(mov_src,LONG)); sprintf(line,"%s,%s",src,lastrand); } else if (deleted) { /* Replace the BICL with an EXTZV instruction. */ p->combop = T(EXTZV,LONG); sprintf(line,"$%d,$%d,%s,%s",pos,siz,src,lastrand); } else /* None of the previous instructions could be deleted, and * replacing a BICL with an EXTZV would not be "optimal". * (0002) */ return(p); p->pop=0; p->code = copy(line); nfield++; 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) {/* outside byte displ range */ if (p2->subop!=JLE) continue; p->combop=T(ACB,LONG); new_operands(p,"%s,$1,%s",regs[RT2],p->code); p->pop=0; p->labno = p2->labno; delnode(p2); delnode(p1); nsob++; } else if (p2->subop==JLE || p2->subop==JLT) { p->combop = (p2->subop==JLE) ? AOBLEQ:AOBLSS; new_operands(p,"%s,%s",regs[RT2],p->code); p->pop=0; p->labno = p2->labno; delnode(p2); delnode(p1); nsob++; } } } }}abs(x){ return(x<0? -x: x);}equop(p1, p2)register struct node *p1;struct node *p2;{ register char *cp1, *cp2; if (p1->combop != p2->combop) return(0); if (p1->op>0 && p1->op<MOV) return(0); if (p1->op==MOVA && p1->labno!=p2->labno) return(0); cp1 = p1->code; cp2 = p2->code; if (cp1==0 && cp2==0) return(1); if (cp1==0 || cp2==0) return(0); while (*cp1 == *cp2++) if (*cp1++ == 0) return(1); return(0);}delnode(p) register struct node *p; { p->back->forw = p->forw; p->forw->back = p->back;}decref(p)register struct node *p;{ if (p && --p->refc <= 0) { nrlab++; delnode(p); }}struct node *nonlab(ap)struct node *ap;{ register struct node *p; p = ap; while (p && p->op==LABEL) p = p->forw; return(p);}clearuse() { register struct node **i; for (i=uses+NUSE; i>uses;) *--i=0;}clearreg() { register short **i; for (i=regs+NREG; i>regs;) **--i=0; conloc[0] = 0; ccloc[0] = 0;}savereg(ai, s, type)register char *s;{ register char *p, *sp; sp = p = regs[ai]; if (source(s)) /* side effects in addressing */ return; /* if any indexing, must be parameter or local */ /* indirection (as in "*-4(fp)") is ok, however */ *p++ = type; while (*p++ = *s) if (*s=='[' || *s++=='(' && *s!='a' && *s!='f') {*sp = 0; return;}}dest(s,type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -