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

📄 asjxxx.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		}	}	/* Didn't find a tunnel.	 */	return((struct symtab *)0);}/* find_tunnel * *	Routine to find a tunnel for a conditional branch so that it *	won't have to be exploded into a branch of the opposite condition *	followed by a branch word.  A tunnel is an unconditional branch *	to the same location as the original conditional branch. */static voidfind_tunnel(segno,starthint,jumpfrom)	int			segno;	struct symtab		**starthint;	register struct symtab	*jumpfrom;{	register struct symtab	*tunnel;	if (jxxxJUMP || UNCONDITIONAL(jumpfrom)) {		/*		 * Don't attempt to find a tunnel.		 */		tunnel = 0;	} else 	if ((jumpfrom->s_dest->s_value - jumpfrom->s_value) >= 0) {		/*		 * The destination is ahead of us.  Assume that the		 * most likely tunnel is ahead of us.		 */		tunnel = search_forward(segno,starthint,jumpfrom);		if (tunnel == 0) {			/*			 * That didn't work so search backwards.			 */			tunnel = search_backward(segno,starthint,jumpfrom);		}	} else {		/* Reverse the search order.		 */		tunnel = search_backward(segno,starthint,jumpfrom);		if (tunnel == 0) {			tunnel = search_forward(segno,starthint,jumpfrom);		}	}	if (tunnel) {		/* Indicate that a tunnel was found.		 */		jumpfrom->s_dest = tunnel;		jumpfrom->s_tag = JXTUNNEL;	} else {		jumpfrom->s_tag = JXNOTYET ;	}#ifdef DEBUG	if (debug)		printf("%cBRANCH(%#8x) to %10s %10s, disp = %4d, value %8d\n",			UNCONDITIONAL(jumpfrom) ? 'U' : 'C',			jumpfrom ,			FETCHNAME( (tunnel ? tunnel : jumpfrom)->s_dest ),			tunnel ? "TUNNEL" : "BUMPED" ,			jumpfrom->s_dest->s_value - jumpfrom->s_value ,			jumpfrom->s_value);#endif}/* CALC_FEAR * * Macro to calculate the amount to be feared from intervening aligns, * jbrs and jxxxs.  Loops backward or forward through the current segment * from the current jbr or jxxx to its destination.  For each questionable * item (JXACTIVE, JXNOTYET, JXALIGN, or JXINACTIVE)  it calls jxxxfear() * to see how many more bytes the item might add to the instruction stream. * * The arguments are: * *	current		This is the current value of the copointer used *			in the enclosing SEGITERATE loop.  It is used to *			determine where in the loop to start. * *	end		This is the destination of the jbr or jxxx and *			determines when the loop terminates. * *	disp		Variable containing the initial displacement or *			distance between the branch and its destination. * *	op		Either + or -. This is used to constuct the correct *			operators for traversing the segment forwards or *			backwards, and to add or subtract the fear to / from *			the displacement. * * This is used in jxxxfix(), look there for more details. */#define CALC_FEAR(current, end, disp, op) \	{ \		register struct symtab *ptr, **co_ptr; \		\		for (co_ptr = (current op 1), ptr = *co_ptr; \		     ptr != end ; \		     ptr = * op/**/op co_ptr \		    ) { \		    	if (ptr->s_tag > JXQUESTIONABLE) { \				disp op= jxxxfear(ptr); \			} \		} \	} /* *	Pass 1.5, resolve jxxx instructions and .align in .text */jxxxfix() {	register struct symtab 	*jumpfrom,				*dest,				**cojumpfrom;		 struct symtab	*ubjumpfrom;	int	segno;		/* current segment number	*/	/*	 *	consider each segment in turn...	 */	for (segno = 0; segno < NLOC + NLOC; segno++){	    /*	     *	Do a lazy topological sort.	     */	    	    register int displ;		/* estimated displacement	*/	    unsigned n_changed;		/* # of jxxx's changed in iteration */	    unsigned n_still_active;	/* # of jxxx's still active */	    struct symtab **co_active;	/* Saved value of cojumpfrom for	    			         * jumpfrom which is still active.					 */#ifdef DEBUG	    int n_iterations=0;	/* # for current segment	*/ #endif	    /* Iterate through the segment, fixing the jbr/jxxx's.	     * Contiune to do this as long as the previous iteration	     * found something to bump, or some were deactivated,	     * but there are still active ones.	     */	    do {#ifdef DEBUG		if (debug) {			printf("\nSegment %d, iteration %d\n",				segno, ++n_iterations);		}#endif		/* Nothing changed or active yet.		 */		n_changed = 0;		n_still_active = 0;		co_active = NULL;		SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){			/* Ignore if not an active jbr/jxxx			 */			if (jumpfrom->s_tag != JXACTIVE) {				continue;			}			/* Find the destination of the jbr/jxxx, and make			 * sure that it is in the same segment.			 */			dest = jumpfrom->s_dest;			if (jumpfrom->s_index != dest->s_index){				yyerror("Intersegment jxxx");				continue;			}			/* Do an intial estimate of the displacement			 * needed for the destination address.			 */			displ = dest->s_value - jumpfrom->s_value;			if ( ! ISBYTE(displ) ) {				/* It is not a byte displacement, so try to				 * prevent the expansion of a jxxx by				 * finding a tunnel, but if this doesn't				 * doesn't work, mark it for expansion.				 */				find_tunnel(segno,cojumpfrom,jumpfrom) ;				/* In either case make note that something				 * has changed.				 */				n_changed++;						} else {				if (displ >= 0) {					/* An unconditional forward branch 					 * also needs to take the alignment					 * following it into account.					 */					if (UNCONDITIONAL(jumpfrom)) {						displ += ALIGN_FEAR;					}					/* It is a forward branch.  Do a 					 * forward search for any intervening					 * jbr's, jxxx's, or align's, as these					 * may affect the actual displacement.					 */					CALC_FEAR(cojumpfrom,dest,displ,+) ;				} else {					/* Do a backward search as above, for					 * a backward branch.					 */					CALC_FEAR(cojumpfrom,dest,displ,-) ;				}				if (ISBYTE(displ)){					/*					 * The displacement will still fit in					 * a byte so this jbr/jxx can be 					 * deactivated.  Note that a jxxx					 * has changed state.					 */					jumpfrom->s_tag = JXINACTIVE;					jumpfrom->s_jxneedalign						= UNCONDITIONAL(jumpfrom);					DEBUG_DEACT(jumpfrom,dest,displ) ;					n_changed++;				} else if (n_changed > 0) {					/* Keep track that a jxxx/jbr is					 * still active.					 */					n_still_active++;				} else if (co_active == NULL) {					/* Remember the first still active					 * jxxx so that we can use it later.					 */					co_active = cojumpfrom;					n_still_active++;				} else if (! UNCONDITIONAL(*co_active)					   && UNCONDITIONAL(jumpfrom)) {										/* Better to bump an unconditional					 * branch than a conditional branch.					 */					co_active = cojumpfrom;					n_still_active++;				} else {					n_still_active++;				}			}		}		if (co_active && n_changed == 0 ) {			/*			 * Nothing changed in this iteration, so force			 * an active jxxx to change into a tunnel or a			 * bumped jxxx.  This may allow us to deactivate			 * some other still active jxxx's.			 */#ifdef DEBUG			if (debug)				fputs("*** Forcing BUMP or TUNNEL ***\n",				      stdout);#endif			find_tunnel(segno,co_active,*co_active);			/*			 * Decrement the number still active, so that we			 * won't do another iteration if that was the only			 * one.			 */			n_still_active--;		}		/* Now go through the segment bumping what needs to be		 * bumped and aligning what can and needs to be aligned.		 * This is done regardless of whether anything changed		 * or is still active, so that the case all aligns will		 * be handled, even if there were no branches.		 */		jxxxbump(segno);		/* End of iterating through all symbols in this		 * segment.  Keep doing it as long as there is anything		 * still active.		 */	    } while (n_still_active > 0) ;#ifdef DEBUG	    if (debug)	    	jxxxcheck(segno);#endif	}}#ifdef DEBUG/* * Debugging routine to check JXXX's and print out debugging info. */jxxxcheck(segno)	int segno;{	register	struct	symtab	**cosp, *sp;	register	struct	symtab		*ub;	/* Iterate through the whole segment.	 */	SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){		switch(sp->s_tag) {		case LABELID:			fprintf(stdout,				"%s, value = %8d\n",					FETCHNAME(sp), sp->s_value);			break;		case JXTUNNEL:			fprintf(stdout,				"TUNNEL(%#8x) to %#10x, disp = %4d, value = %8d\n",				sp,				sp->s_dest,				TUNNEL_ADDR(sp->s_dest) - sp->s_value,				sp->s_value);			break ;		case JXINACTIVE:			if (sp->s_dest == 0) {				fprintf(stdout,					"\tALIGN(%#8x), value = %8d\n",					sp, sp->s_value);				break;			}			fprintf(stdout,				"\t%cBRANCH(%#8x) to %10s, disp = %4d, value = %8d %s\n",				UNCONDITIONAL(sp)?'U':'C',				sp,				FETCHNAME(sp->s_dest),				sp->s_dest->s_value - sp->s_value,				sp->s_value,				sp->s_jxbump ? "BUMPED":"");			if (sp->s_jxneedalign)				fputs(" ERROR needs alignment \n",stdout);			break ;		case JXACTIVE:		case JXNOTYET:			fprintf(stdout,				"BRANCH(%#8x) to %#10x, disp = %4d, value = %8d ERROR tag = %s\n",				sp,				sp->s_dest,				sp->s_dest->s_value - sp->s_value,				sp->s_value,				sp->s_tag==JXACTIVE?"JXACTIVE":"JXNOTYET");			break ;		}	}}#endif/* *	Go through the symbols in a given segment number, *	and see which entries are jxxx entries that have *	been logically "exploded" (expanded), but for which *	the value of textually following symbols has not been *	increased.  Attempt to align as much as we can so that *	that we can (possibly) deactivate jbr/jxxx's in fewer *	iterations.  This may also prevent some jbr/jxxx's *	from being exploded unnecessarily. */jxxxbump(segno)	int	segno;{	register	struct	symtab	**cosp, *sp;	register	struct	symtab		*ub;	register	int		cum_bump;	register	int		align_ok;#ifdef DEBUG	if (debug)		fputs("Bumping\n",stdout);#endif	cum_bump = 0;	/* No cumulative bump yet. */	align_ok = 1;	/* No active jbr/jxxx's yet, so ok to align. */	/* Iterate through the whole segment.	 */	SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){		switch(sp->s_tag) {		case JXACTIVE:			/*			 * Once an active jbr/jxxx has been seen we can			 * no longer do alignment, since it may later be			 * exploded.			 */			align_ok = 0;			/* FALLTHROUGH */		case OKTOBUMP:		case LABELID:		case FLOATINGSTAB:		case IGNOREBOUND:		case OBSOLETE:		case JXQUESTIONABLE:		case JXTUNNEL:			/*			 * Simply add the cumulative bump to these.			 */			sp->s_value += cum_bump;			break;		case JXINACTIVE:			/*			 * Add the cumulative bump then see if we can 			 * (align_ok) or need to (s_jxneedalign) align			 * the instruction following this one.			 */			sp->s_value += cum_bump;			if (align_ok && sp->s_jxneedalign) {				/*				 * Add the amount needed to align the next				 * instruction, but don't change s_value				 * for this instruction, since this will				 * be needed later if this instruction 				 * provides a tunnel.   This also make sense				 * because the alignment actually inserts				 * HALT instructions between this  and the				 * next.				 */				cum_bump += ALIGN(sp->s_value) - sp->s_value;				/* Indicate that this no longer needs 				 * alignment.				 */				sp->s_jxneedalign = 0;			}			break;		case JXNOTYET:			/*			 * This one needs to be bumped, so do it and mark it			 * inactive.  It's s_jxfear is used to bump the 			 * cumulative bump which is then used to bump it's			 * own s_value.			 */			sp->s_tag = JXINACTIVE;			sp->s_jxbump = 1;			cum_bump += sp->s_jxfear;			sp->s_value += cum_bump;			/* We want to align the instruction following the			 * brw or bxxx/brw that this is turning into.  Can			 * it be done now.			 */			if (align_ok) {				/*				 * Yes, so add the alignment factor into				 * the cumulative bump and clear s_jxneedalign				 * to indicate that this has been done.				 */				cum_bump += ALIGN(sp->s_value) - sp->s_value;				sp->s_jxneedalign = 0;			} else {				/* Can't calculate how much alignment needs				 * to be done, so indicate that it should be				 * done in a later call.				 */				sp->s_jxneedalign = 1;			}			break ;		case JXALIGN:			/* 			 * Add any cumulative bump and calculate the alignment			 * needed, if posssible.  If not, it will be done in			 * a later call.			 */			sp->s_value += cum_bump;			if (align_ok) {				/* How many extra bytes are there over the				 * required alignment?  This is caluclated				 * on (sp->s_value - 1) rather than just				 * sp->s_value.  See jalign() for detatils.				 */				int extra = (sp->s_value - 1) & 					      ((unsigned)sp->s_jxfear);				if (extra == 0) {					/*					 * We over estimated, back off to					 * do the alignment.					 */					sp->s_value--;					cum_bump--;				} else {					sp->s_jxfear -= extra ;					sp->s_value += sp->s_jxfear;					cum_bump += sp->s_jxfear;				}				/* Now mark it inactive and indicate that				 * it no longer needs alignment.				 */				sp->s_jxneedalign = 0;				sp->s_tag = JXINACTIVE;			}			break;		}	}	/* Finally bump the location value for the segment.	 */	usedot[segno].e_xvalue += cum_bump;}

⌨️ 快捷键说明

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