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

📄 c21.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
			/* If the bit offset is not immediate mode (i.e. $16)			 * then we can't convert it.			 */			if (regs[RT1][0] != '$') goto std;			/* Get the value of the bit offset and if it is < 0			 * then we can't change it.			 */			if ((boff = getnum(&regs[RT1][1])) < 0) goto std;			/* If the bit offset is not on an addressable unit 			 * boundary, then we can't change it			 */			if ((boff % BITS_PER_UNIT) != 0) goto std; /*0001*/			/* Calculate the chunk (addressable unit offset)			 */			coff = boff / BITS_PER_UNIT ;		   /*0001*/			/* If the chunk is not zero and the extract is from			 * a register, then we can't change it since the			 * CVT or MOVZ can only act on the low byte or word			 * of the register. The function isreg returns the			 * register number or -1 if the argument is not a			 * register.			 */			if (coff && (isreg(regs[RT3]) >= 0)) goto std;			/* Determine whether to do a signed (CVT) or unsigned			 * MOVZ operation and if the source is a byte or a			 * word.			 */			p->op = (p->op == EXTV) ? CVT : MOVZ;			p->subop = U((flen == 8 ? BYTE : WORD), LONG);			/* Set up the source operand string in regs[RT1]			 */			if (coff == 0)				/* If the addressable offset is 0 then just				 * copy the source from RT3.				 */				strcpy(regs[RT1], regs[RT3]);			else				/* Change the source operand string to use the				 * chunk.  If the source uses general register				 * addressing generate "coff(Rn)" otherwise 				 * generate "coff+address".				 */				sprintf(regs[RT1], "%d%s%s", coff, 					regs[RT3][0]=='(' ? "":"+",					regs[RT3]);			/* Move the destination from RT4 to RT2 and set the			 * RT3 and RT4 to null strings since we no longer need			 * them to generate the instruction.			 */			strcpy(regs[RT2], regs[RT4]);			regs[RT3][0] = '\0'; regs[RT4][0] = '\0';			p->pop = 0; newcode(p);		}		nchange++;		goto std;	}	case CMP:	{		/* comparison to -63 to -1:		**	cmpl	r0,$-1	>	incl	r0		**	jeql	...		**		**	cmpl	r0,$-63	>	addl2	$63,r0		**	jeql	...		*/		register int	num;		register int	reg;		register struct	node	*regp = p->back;		if (p->forw->op != CBR) goto std;		if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;		splitrand(p);		if (strncmp(regs[RT2], "$-", 2) != 0) goto std;		reg = r = isreg(regs[RT1]);		if (r < 0) goto std;		if (r < NUSE && uses[r] != 0) goto std;		if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)		{			if (*regp->code != 'r') goto std;			reg = regp->code[1] - '0';			if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])				goto std;		}		if (r >= NUSE) goto std;		if (reg != r)			sprintf(regs[RT1], "r%d", reg);		if ((num = getnum(&regs[RT2][2])) <= 0 || num > 63) goto std;		if (num == 1)		{			p->op = INC; regs[RT2][0] = '\0';		}		else		{			register char	*t;			t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;			p->op = ADD; p->subop = U(p->subop, OP2);			for (t = &regs[RT1][2]; t[-1] = *t; t++) ;		}		p->pop = 0; newcode(p);		nchange++;		goto std;	}	case JSB:		if (equstr(p->code,"mcount")) {uses[0]=p; regs[0][0]= -1;}		goto std;	case JBR: case JMP:		clearuse();		if (p->subop==RET || p->subop==RSB) {uses[0]=p; regs[0][0]= -1; break;}		if (p->ref==0) goto std;	/* jmp (r0) */		/* fall through */	case CBR:		if (p->ref->ref!=0) for (r=NUSE;--r>=0;)			if (biti[r] & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}	case EROU: case JSW:	case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;	}	}	for (p= &first; p!=0; p=p->forw)		if (p->op==LABEL || p->op==DLABEL) p->ref=0;	/* erase our tracks */}rmove(){	register struct node *p, *lastp;	register int r;	int r1;	clearreg();	for (p=first.forw; p!=0; p = p->forw) {	lastp=p;	if (debug) {		printf("Regs:\n");		for (r=0; r<NREG; r++)			if (regs[r][0]) {				r1=regs[r][0];				printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);			}		printf("-\n");	}	switch (p->op) {	case CVT:		splitrand(p); goto mov;	case MOV:		splitrand(p);		if ((r = findrand(regs[RT1],p->subop)) >= 0) {			if (r == isreg(regs[RT2]) && p->forw->op!=CBR) {				delnode(p); redunm++; break;			}		}mov:		repladdr(p);		r = isreg(regs[RT1]);		r1 = isreg(regs[RT2]);		dest(regs[RT2],p->subop);		if (r>=0) {			if (r1>=0) savereg(r1, regs[r]+1, p->subop);			else if (p->op!=CVT) savereg(r, regs[RT2], p->subop);		} else if (r1>=0) savereg(r1, regs[RT1], p->subop);		else if (p->op!=CVT) setcon(regs[RT1], regs[RT2], p->subop);		break;/* .rx,.wx */	case MFPR:	case COM:	case NEG:/* .rx,.wx or .rx,.rx,.wx */	case ADD:	case SUB:	case BIC:	case BIS:	case XOR:	case MUL:	case DIV:	case ASH:	case MOVZ:/* .rx,.rx,.rx,.wx */	case EXTV:	case EXTZV:	case INSV:		splitrand(p);		repladdr(p);		dest(lastrand,p->subop);		if (p->op==INSV) ccloc[0]=0;		break;/* .mx or .wx */	case CLR:	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) /* Return pointer to register which is "beyond last read/modify operand" */	register struct node *p;{	if (OP2==(p->subop>>4))		return(regs[RT3]);	switch (p->op) {				/* 1 operand instructions		 */		case JSB:		case TST:		case INC:		case DEC:		case PUSHA:		case PUSH:	return(regs[RT2]);				/* 2 operand instructions 		 */		case MFPR:	/* DLB0004 */		case MTPR:		case BIT:		case CMP:		case CALLS:	return(regs[RT3]);		/* 3 operand instructions		 */		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&regs[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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -