⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c21.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
			}			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 + -