xref: /csrg-svn/old/as.tahoe/asjxxx.c (revision 40586)
1*40586Sbostic /*
2*40586Sbostic  *	Copyright (c) 1982 Regents of the University of California
3*40586Sbostic  */
4*40586Sbostic #ifndef lint
5*40586Sbostic static char sccsid[] = "@(#)asjxxx.c 4.7 6/30/83";
6*40586Sbostic #endif not lint
7*40586Sbostic 
8*40586Sbostic #include	<stdio.h>
9*40586Sbostic #include	"as.h"
10*40586Sbostic #include	"assyms.h"
11*40586Sbostic 
12*40586Sbostic #define	JBR	0x11
13*40586Sbostic #define	BRW	0x13
14*40586Sbostic #define	JMP	0x71
15*40586Sbostic 
16*40586Sbostic /*
17*40586Sbostic  *	The number of bytes to add if the jxxx must be "exploded"
18*40586Sbostic  *	into the long form
19*40586Sbostic  */
20*40586Sbostic #define	JBRDELTA	1	/* brb <byte> ==> brw <byte> <byte> */
21*40586Sbostic #define	JXXXDELTA	3	/* brb <byte> ==> brb <byte> brw <byte> <byte> */
22*40586Sbostic #define	JBRJDELTA	d124	/* brb <byte> ==> jmp L^(pc) <byte>*d124 */
23*40586Sbostic #define	JXXXJDELTA	d124+2	/* brb <byte> ==> brb <byte> jmp L^(pc) <byte>*d124 */
24*40586Sbostic 
25*40586Sbostic int	jbrfsize = JBRDELTA;
26*40586Sbostic int	jxxxfsize = JXXXDELTA;
27*40586Sbostic 
28*40586Sbostic /*
29*40586Sbostic  *	These variables are filled by asscan.c with the
30*40586Sbostic  *	last name encountered (a pointer buried in the intermediate file),
31*40586Sbostic  *	and the last jxxx symbol table entry encountered.
32*40586Sbostic  */
33*40586Sbostic struct 	symtab	*lastnam;
34*40586Sbostic struct	symtab	*lastjxxx;
35*40586Sbostic 
initijxxx()36*40586Sbostic initijxxx()
37*40586Sbostic {
38*40586Sbostic 	jbrfsize = jxxxJUMP ? JBRJDELTA : JBRDELTA;
39*40586Sbostic 	jxxxfsize = jxxxJUMP ? JXXXJDELTA : JXXXDELTA;
40*40586Sbostic 	/*
41*40586Sbostic 	 *	Note: ifjxxxJUMP is set, then we do NOT do any tunnelling;
42*40586Sbostic 	 *	this was too complicated to figure out, and in the first
43*40586Sbostic 	 *	version of the assembler, tunnelling proved to be the hardest
44*40586Sbostic 	 *	to get to work!
45*40586Sbostic 	 */
46*40586Sbostic }
47*40586Sbostic /*
48*40586Sbostic  *	Handle jxxx instructions
49*40586Sbostic  */
ijxout(opcode,ap,nact)50*40586Sbostic ijxout(opcode, ap, nact)
51*40586Sbostic 	u_char	opcode;
52*40586Sbostic 	struct	arg	*ap;
53*40586Sbostic 	int	nact;
54*40586Sbostic {
55*40586Sbostic 	if (passno == 1){
56*40586Sbostic 		/*
57*40586Sbostic 		 *	READ THIS BEFORE LOOKING AT jxxxfix()
58*40586Sbostic 		 *
59*40586Sbostic 		 *	Record the jxxx in a special symbol table entry
60*40586Sbostic 		 */
61*40586Sbostic 		register struct symtab *jumpfrom;
62*40586Sbostic 
63*40586Sbostic 		/*
64*40586Sbostic 		 *	We assume the MINIMAL length
65*40586Sbostic 		 */
66*40586Sbostic 		putins(opcode, ap, nact);
67*40586Sbostic 		jumpfrom = lastjxxx;
68*40586Sbostic 		jumpfrom->s_tag = JXACTIVE;
69*40586Sbostic 		jumpfrom->s_jxbump = 0;
70*40586Sbostic 		if (opcode == JBR)
71*40586Sbostic 			jumpfrom->s_jxfear = jbrfsize;
72*40586Sbostic 		else
73*40586Sbostic 			jumpfrom->s_jxfear = jxxxfsize;
74*40586Sbostic 		if (lastnam == 0)
75*40586Sbostic 			yyerror("jxxx destination not a label");
76*40586Sbostic 		jumpfrom->s_dest = lastnam;
77*40586Sbostic 		jumpfrom->s_type = dotp->e_xtype;	/*only TEXT or DATA*/
78*40586Sbostic 		jumpfrom->s_index = dotp-usedot;
79*40586Sbostic 		/*
80*40586Sbostic 		 *	value ALWAYS (ALWAYS!!!) indexes the next instruction
81*40586Sbostic 		 *	after the jump, even in the jump must be exploded
82*40586Sbostic 		 *	(bumped)
83*40586Sbostic 		 */
84*40586Sbostic 		jumpfrom->s_value = dotp->e_xvalue;
85*40586Sbostic 		njxxx++;
86*40586Sbostic 	} else {/* pass2, resolve */
87*40586Sbostic 		/*
88*40586Sbostic 		 *	READ THIS AFTER LOOKING AT jxxxfix()
89*40586Sbostic 		 */
90*40586Sbostic 		reg	long		oxvalue;
91*40586Sbostic 		reg	struct	exp 	*xp;
92*40586Sbostic 		reg	struct	symtab	*tunnel;
93*40586Sbostic 		reg	struct	arg	*aplast;
94*40586Sbostic 
95*40586Sbostic 		aplast = ap + nact - 1;
96*40586Sbostic 		xp = aplast->a_xp;
97*40586Sbostic 		if (lastjxxx->s_tag == JXTUNNEL){
98*40586Sbostic 			lastjxxx->s_tag = JXINACTIVE;
99*40586Sbostic 			tunnel = lastjxxx->s_dest;
100*40586Sbostic 			xp->e_xvalue = tunnel->s_value	/*index of instruction following*/
101*40586Sbostic 				    - 3			/* size of brw + word*/
102*40586Sbostic 				    + ( ( (tunnel->s_jxfear == jbrfsize) &&
103*40586Sbostic 					  (tunnel->s_jxbump == 0))?1:0);
104*40586Sbostic 							/*non bumped branch byteis only 2 back*/
105*40586Sbostic 		}
106*40586Sbostic 		if (lastjxxx->s_jxbump == 0){	/*wasn't bumped, so is short form*/
107*40586Sbostic 			putins(opcode, ap, nact);
108*40586Sbostic 		} else {
109*40586Sbostic 			if (opcode != JBR){
110*40586Sbostic 				/*
111*40586Sbostic 				 *	branch reverse conditional byte over
112*40586Sbostic 				 *	branch unconditional word
113*40586Sbostic 				 */
114*40586Sbostic 				oxvalue = xp->e_xvalue;
115*40586Sbostic 				xp->e_xvalue = lastjxxx->s_value;
116*40586Sbostic 				putins(opcode^0x10, ap, nact);
117*40586Sbostic 				xp->e_xvalue = oxvalue;
118*40586Sbostic 			}
119*40586Sbostic 			putins(jxxxJUMP ? JMP : BRW, aplast, 1);
120*40586Sbostic 		}
121*40586Sbostic 	}
122*40586Sbostic }
123*40586Sbostic 
jalign(xp,sp)124*40586Sbostic jalign(xp, sp)
125*40586Sbostic 	register struct exp *xp;
126*40586Sbostic 	register struct symtab *sp;
127*40586Sbostic {
128*40586Sbostic 	register	int	mask;
129*40586Sbostic 	/*
130*40586Sbostic 	 *	Problem with .align
131*40586Sbostic 	 *
132*40586Sbostic 	 *	When the loader constructs an executable file from
133*40586Sbostic 	 *	a number of objects, it effectively concatnates
134*40586Sbostic 	 *	together all of the text segments from all objects,
135*40586Sbostic 	 *	and then all of the data segments.
136*40586Sbostic 	 *
137*40586Sbostic 	 *	If we do an align by a large value, we can align
138*40586Sbostic 	 *	within the a.out this assembly produces, but
139*40586Sbostic 	 *	after the loader concatnates, the alignment can't
140*40586Sbostic 	 *	be guaranteed if the objects preceding this one
141*40586Sbostic 	 *	in the load are also aligned to the same size.
142*40586Sbostic 	 *
143*40586Sbostic 	 *	Currently, the loader guarantees full word alignment.
144*40586Sbostic 	 *	So, ridiculous aligns are caught here and converted
145*40586Sbostic 	 *	to a .align 2, if possible.
146*40586Sbostic 	 */
147*40586Sbostic 	if (   ( (xp->e_xtype & XTYPE) != XABS)
148*40586Sbostic 	    || (xp->e_xvalue < 0)
149*40586Sbostic 	    || (xp->e_xvalue > 16)
150*40586Sbostic 	    ) {
151*40586Sbostic 		yyerror("Illegal `align' argument");
152*40586Sbostic 		return;
153*40586Sbostic 	}
154*40586Sbostic 	if (xp->e_xvalue > 2){
155*40586Sbostic 		if (passno == 1){
156*40586Sbostic 			yywarning(".align %d is NOT preserved by the loader",
157*40586Sbostic 				xp->e_xvalue);
158*40586Sbostic 			yywarning(".align %d converted to .align 2",
159*40586Sbostic 				xp->e_xvalue);
160*40586Sbostic 		}
161*40586Sbostic 		xp->e_xvalue = 2;
162*40586Sbostic 	}
163*40586Sbostic 	flushfield(NBPW/4);
164*40586Sbostic 	if (passno == 1) {
165*40586Sbostic 		sp->s_tag = JXALIGN;
166*40586Sbostic 		sp->s_jxfear = (1 << xp->e_xvalue) - 1;
167*40586Sbostic 		sp->s_type = dotp->e_xtype;
168*40586Sbostic 		sp->s_index = dotp-usedot;
169*40586Sbostic 		/*
170*40586Sbostic 		 *	We guess that the align will take up at least one
171*40586Sbostic 		 *	byte in the code output.  We will correct for this
172*40586Sbostic 		 *	initial high guess when we explode (bump) aligns
173*40586Sbostic 		 *	when we fix the jxxxes.  We must do this guess
174*40586Sbostic 		 *	so that the symbol table is sorted correctly
175*40586Sbostic 		 *	and labels declared to fall before the align
176*40586Sbostic 		 *	really get their, instead of guessing zero size
177*40586Sbostic 		 *	and have the label (incorrectly) fall after the jxxx.
178*40586Sbostic 		 *	This is a quirk of our requirement that indices into
179*40586Sbostic 		 *	the code stream point to the next byte following
180*40586Sbostic 		 *	the logical entry in the symbol table
181*40586Sbostic 		 */
182*40586Sbostic 		dotp->e_xvalue += 1;
183*40586Sbostic 		sp->s_value = dotp->e_xvalue;
184*40586Sbostic 		njxxx++;
185*40586Sbostic 	} else {
186*40586Sbostic 		mask = (1 << xp->e_xvalue) - 1;
187*40586Sbostic 		while (dotp->e_xvalue & mask)
188*40586Sbostic 		{
189*40586Sbostic 			Outb(0);
190*40586Sbostic 			if (liston)
191*40586Sbostic 			{
192*40586Sbostic 				*layoutpos++ = '0';
193*40586Sbostic 				*layoutpos++ = '0';
194*40586Sbostic 			}
195*40586Sbostic 		}
196*40586Sbostic 	}
197*40586Sbostic }
198*40586Sbostic 
djalign(xp,sp)199*40586Sbostic djalign(xp, sp)
200*40586Sbostic 	register struct exp *xp;
201*40586Sbostic 	register struct symtab *sp;
202*40586Sbostic {
203*40586Sbostic 	register	int	mask;
204*40586Sbostic 
205*40586Sbostic 	if (   ( (xp->e_xtype & XTYPE) != XABS)
206*40586Sbostic 	    || (xp->e_xvalue < 0)
207*40586Sbostic 	    || (xp->e_xvalue > 16)
208*40586Sbostic 	    ) {
209*40586Sbostic 		yyerror("Illegal `align' argument");
210*40586Sbostic 		return;
211*40586Sbostic 	}
212*40586Sbostic 	if (xp->e_xvalue > 2){
213*40586Sbostic 		if (passno == 1){
214*40586Sbostic 			yywarning(".align %d is NOT preserved by the loader",
215*40586Sbostic 				xp->e_xvalue);
216*40586Sbostic 			yywarning(".align %d converted to .align 2",
217*40586Sbostic 				xp->e_xvalue);
218*40586Sbostic 		}
219*40586Sbostic 		xp->e_xvalue = 2;
220*40586Sbostic 	}
221*40586Sbostic 	flushfield(NBPW/4);
222*40586Sbostic 	mask = (1 << xp->e_xvalue) - 1;
223*40586Sbostic 	if (passno == 1) {
224*40586Sbostic 		sp->s_tag = JXALIGN;
225*40586Sbostic 		sp->s_jxfear = (1 << xp->e_xvalue) - 1;
226*40586Sbostic 		sp->s_type = dotp->e_xtype;
227*40586Sbostic 		sp->s_index = dotp-usedot;
228*40586Sbostic 		while (dotp->e_xvalue & mask)
229*40586Sbostic 			dotp->e_xvalue ++;
230*40586Sbostic 		sp->s_value = dotp->e_xvalue;
231*40586Sbostic 		njxxx++;
232*40586Sbostic 	} else {
233*40586Sbostic 		while (dotp->e_xvalue & mask)
234*40586Sbostic 		{
235*40586Sbostic 			Outb(0);
236*40586Sbostic 			if (liston)
237*40586Sbostic 			{
238*40586Sbostic 				*layoutpos++ = '0';
239*40586Sbostic 				*layoutpos++ = '0';
240*40586Sbostic 			}
241*40586Sbostic 		}
242*40586Sbostic 	}
243*40586Sbostic }
244*40586Sbostic 
245*40586Sbostic 
246*40586Sbostic /*
247*40586Sbostic  *	Pass 1.5, resolve jxxx instructions and .align in .text
248*40586Sbostic  */
jxxxfix()249*40586Sbostic jxxxfix()
250*40586Sbostic {
251*40586Sbostic 	register struct symtab 	*jumpfrom;
252*40586Sbostic 		 struct symtab	**cojumpfrom, *ubjumpfrom;
253*40586Sbostic 	register struct symtab 	*dest;
254*40586Sbostic 	register struct symtab	*intdest;	/*intermediate dest*/
255*40586Sbostic 	register struct symtab	**cointdest, *ubintdest;
256*40586Sbostic 
257*40586Sbostic 	register struct symtab 	*tunnel;
258*40586Sbostic 	 	 int 		displ,nchange;
259*40586Sbostic 		 int		badjxalign;	/*if jump across an align*/
260*40586Sbostic 		 int		stillactives;	/*if still active jxxxes*/
261*40586Sbostic 		 int		segno;		/*current segment number*/
262*40586Sbostic 		 int		topono;		/*which iteration in the topo sort*/
263*40586Sbostic 	register unsigned char	tag;
264*40586Sbostic 	/*
265*40586Sbostic 	 *	consider each segment in turn...
266*40586Sbostic 	 */
267*40586Sbostic 	for (segno = 0; segno < NLOC + NLOC; segno++){
268*40586Sbostic 	    badjxalign = 0;		/*done on a per segment basis*/
269*40586Sbostic 	    /*
270*40586Sbostic 	     *	Do a lazy topological sort.
271*40586Sbostic 	     */
272*40586Sbostic 	    for (topono = 1, nchange = 1; nchange != 0; topono++){
273*40586Sbostic #ifdef lint
274*40586Sbostic 		topno = topno;
275*40586Sbostic #endif lint
276*40586Sbostic #ifdef DEBUG
277*40586Sbostic 		if (debug)
278*40586Sbostic 			printf("\nSegment %d, topo iteration %d\n",
279*40586Sbostic 				segno, topono);
280*40586Sbostic #endif
281*40586Sbostic 		nchange = 0;
282*40586Sbostic 		stillactives = 0;
283*40586Sbostic 		/*
284*40586Sbostic 		 *	We keep track of one possible tunnel location.
285*40586Sbostic 		 *	A tunnel will eventually be an unconditional
286*40586Sbostic 		 *	branch to the same place that another jxxx
287*40586Sbostic 		 *	will want to branch to.  We will turn a
288*40586Sbostic 		 *	branch conditional/unconditional (word) that would
289*40586Sbostic 		 *	have to get bumped because its destination is too
290*40586Sbostic 		 *	far away, into a branch conditional/unconditional
291*40586Sbostic 		 *	byte to the tunnel branch conditional/unconditional.
292*40586Sbostic 		 *	Of course, the tunnel must branch to the same place
293*40586Sbostic 		 *	as we want to go.
294*40586Sbostic 		 */
295*40586Sbostic 		tunnel = 0;	/*initially, no tunnel*/
296*40586Sbostic 		SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){
297*40586Sbostic 			tag = jumpfrom->s_tag;
298*40586Sbostic 			if (tag <= IGNOREBOUND)
299*40586Sbostic 				continue;	/*just an ordinary symbol*/
300*40586Sbostic 			if (tag == JXALIGN){
301*40586Sbostic 				tunnel = 0;	/*avoid tunneling across a flex alocation*/
302*40586Sbostic 				continue;	/*we take care of these later*/
303*40586Sbostic 			}
304*40586Sbostic 			if (   jumpfrom->s_jxfear == jbrfsize	/*unconditional*/
305*40586Sbostic 			    || (   tag == JXINACTIVE		/*inactive bumped*/
306*40586Sbostic 				&& (jumpfrom->s_jxbump != 0)
307*40586Sbostic 			       )
308*40586Sbostic 			   ) tunnel = jumpfrom;
309*40586Sbostic 			if (tag != JXACTIVE)
310*40586Sbostic 				continue;
311*40586Sbostic 			dest = jumpfrom->s_dest;
312*40586Sbostic 			if (jumpfrom->s_index != dest->s_index){
313*40586Sbostic 				yyerror("Intersegment jxxx");
314*40586Sbostic 				continue;
315*40586Sbostic 			}
316*40586Sbostic 			displ = dest->s_value - jumpfrom->s_value;
317*40586Sbostic 			if (displ < MINBYTE || displ > MAXBYTE) {
318*40586Sbostic 				/*
319*40586Sbostic 				 *	This is an immediate lose!
320*40586Sbostic 				 *
321*40586Sbostic 				 *	We first attempt to tunnel
322*40586Sbostic 				 *	by finding an intervening jump that
323*40586Sbostic 				 *	has  the same destination.
324*40586Sbostic 				 *	The tunnel is always the first preceeding
325*40586Sbostic 				 *	jxxx instruction, so the displacement
326*40586Sbostic 				 *	to the tunnel is less than zero, and
327*40586Sbostic 				 *	its relative position will be unaffected
328*40586Sbostic 				 *	by future jxxx expansions.
329*40586Sbostic 				 *
330*40586Sbostic 				 *	No tunnels if doing jumps...
331*40586Sbostic 				 */
332*40586Sbostic 				if (    (!jxxxJUMP)
333*40586Sbostic 				     && (jumpfrom->s_jxfear > jbrfsize)
334*40586Sbostic 				     && (tunnel)
335*40586Sbostic 				     && (tunnel->s_dest == jumpfrom->s_dest)
336*40586Sbostic 				     && (tunnel->s_index == jumpfrom->s_index)
337*40586Sbostic 				     && (tunnel->s_value - jumpfrom->s_value >=
338*40586Sbostic 						MINBYTE + jxxxfsize)
339*40586Sbostic 				   ) {
340*40586Sbostic 						/*
341*40586Sbostic 						 *	tunnelling is OK
342*40586Sbostic 						 */
343*40586Sbostic 						jumpfrom->s_dest = tunnel;
344*40586Sbostic 						/*
345*40586Sbostic 						 * no bumping needed, this
346*40586Sbostic 						 * is now effectively inactive
347*40586Sbostic 						 * but must be remembered
348*40586Sbostic 						 */
349*40586Sbostic 						jumpfrom->s_tag = JXTUNNEL;
350*40586Sbostic #ifdef DEBUG
351*40586Sbostic 						if(debug)
352*40586Sbostic 						printf("Tunnel from %s from line %d\n",
353*40586Sbostic 							FETCHNAME(jumpfrom),
354*40586Sbostic 							lineno);
355*40586Sbostic #endif
356*40586Sbostic 						continue;
357*40586Sbostic 				} else {	/*tunneling not possible*/
358*40586Sbostic 					/*
359*40586Sbostic 					 *	since this will be turned
360*40586Sbostic 					 *	into a bumped jump, we can
361*40586Sbostic 					 *	use the unconditional jump
362*40586Sbostic 					 *	as a tunnel
363*40586Sbostic 					 */
364*40586Sbostic 					tunnel = jumpfrom;
365*40586Sbostic 					jumpfrom->s_tag = JXNOTYET;
366*40586Sbostic 					++nchange;
367*40586Sbostic 					continue;
368*40586Sbostic 				}
369*40586Sbostic 			}	/*end of immediate lose*/
370*40586Sbostic 			/*
371*40586Sbostic 			 *	Do a forward search for an intervening jxxx
372*40586Sbostic 			 */
373*40586Sbostic 			if (displ >= 0) {
374*40586Sbostic 				SEGITERATE(segno, cojumpfrom + 1,0,cointdest,
375*40586Sbostic 						intdest, ubintdest, ++){
376*40586Sbostic 					if (intdest->s_value > dest->s_value)
377*40586Sbostic 						break; /* beyond destination */
378*40586Sbostic 					if (intdest->s_tag <= JXQUESTIONABLE)
379*40586Sbostic 						continue;	/*frozen solid*/
380*40586Sbostic 					if (intdest->s_tag == JXALIGN){
381*40586Sbostic 						jumpfrom->s_jxoveralign = 1;
382*40586Sbostic 						badjxalign++;
383*40586Sbostic 					}
384*40586Sbostic 					/*
385*40586Sbostic 					 *	we assume the worst case
386*40586Sbostic 					 *	for unfrozen jxxxxes
387*40586Sbostic 					 */
388*40586Sbostic 					displ += intdest->s_jxfear;
389*40586Sbostic 				}
390*40586Sbostic 				if (displ <= MAXBYTE){
391*40586Sbostic 					/*
392*40586Sbostic 					 *	the worst possible conditions
393*40586Sbostic 					 *	can't hurt us, so forget about
394*40586Sbostic 					 *	this jump
395*40586Sbostic 					 */
396*40586Sbostic 					jumpfrom->s_tag = JXINACTIVE;
397*40586Sbostic 				} else {
398*40586Sbostic 					stillactives++;
399*40586Sbostic 				}
400*40586Sbostic 			} else {
401*40586Sbostic 			/*
402*40586Sbostic 			 *	backward search for intervening jxxx
403*40586Sbostic 			 */
404*40586Sbostic 				SEGITERATE(segno, cojumpfrom - 1,1,cointdest,
405*40586Sbostic 				  intdest, ubintdest, --){
406*40586Sbostic 					if (intdest->s_value <= dest->s_value)
407*40586Sbostic 						break; /* beyond destination */
408*40586Sbostic 					if (intdest->s_tag <= JXQUESTIONABLE)
409*40586Sbostic 						continue;	/*frozen solid*/
410*40586Sbostic 					if (intdest->s_tag == JXALIGN){
411*40586Sbostic 						jumpfrom->s_jxoveralign = 1;
412*40586Sbostic 						badjxalign++;
413*40586Sbostic 					}
414*40586Sbostic 					displ -= intdest->s_jxfear;
415*40586Sbostic 				}
416*40586Sbostic 				if (displ >= MINBYTE) {
417*40586Sbostic 					jumpfrom->s_tag = JXINACTIVE;
418*40586Sbostic 				} else {
419*40586Sbostic 					stillactives++;
420*40586Sbostic 				}
421*40586Sbostic 			}	/*end of backwards search*/
422*40586Sbostic 		}	/*end of iterating through all symbols in this seg*/
423*40586Sbostic 
424*40586Sbostic 		if (nchange == 0) {
425*40586Sbostic 			/*
426*40586Sbostic 			 *	Now, if there are still active jxxx entries,
427*40586Sbostic 			 *	we are partially deadlocked.  We can leave
428*40586Sbostic 			 *	these jxxx entries in their assumed short jump
429*40586Sbostic 			 *	form, as all initial displacement calcualtions
430*40586Sbostic 			 *	are hanging on unresolved jxxx instructions
431*40586Sbostic 			 *	that might explode into a long form, causing
432*40586Sbostic 			 *	other jxxxes jumping across the first set of
433*40586Sbostic 			 *	jxxxes to explode, etc.
434*40586Sbostic 			 *	However, if a jxxx jumps across a .align,
435*40586Sbostic 			 *	we assume the worst for the deadlock cycle,
436*40586Sbostic 			 *	and resolve all of them towards the long
437*40586Sbostic 			 *	jump.
438*40586Sbostic 			 *	Currently, the C compiler does not produce
439*40586Sbostic 			 *	jumps across aligns, as aligns are only used
440*40586Sbostic 			 *	in data segments, or in text segments to align
441*40586Sbostic 			 *	functions.
442*40586Sbostic 			 */
443*40586Sbostic 			if (stillactives){
444*40586Sbostic 				SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
445*40586Sbostic 				    ubjumpfrom, ++){
446*40586Sbostic 					if (jumpfrom->s_tag == JXACTIVE){
447*40586Sbostic 						jumpfrom->s_tag =
448*40586Sbostic 						  badjxalign?JXNOTYET:JXINACTIVE;
449*40586Sbostic 					}
450*40586Sbostic 				}
451*40586Sbostic 				if (badjxalign){
452*40586Sbostic 					jxxxbump(segno, (struct symtab **)0);
453*40586Sbostic 				}
454*40586Sbostic 			}
455*40586Sbostic 			/*
456*40586Sbostic 			 *	Handle  all of the .align s
457*40586Sbostic 			 */
458*40586Sbostic 			SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
459*40586Sbostic 			   ubjumpfrom, ++){
460*40586Sbostic 			    if (jumpfrom->s_tag == JXALIGN){
461*40586Sbostic 				/*
462*40586Sbostic 				 *	Predict the true displacement
463*40586Sbostic 				 *	needed, irregardless of the
464*40586Sbostic 				 *	fact that we guessed 1
465*40586Sbostic 				 */
466*40586Sbostic 				displ = (jumpfrom->s_value - 1) & (unsigned)jumpfrom->s_jxfear;
467*40586Sbostic 				if (displ == 0){	/*no virtual displacement*/
468*40586Sbostic 					jumpfrom->s_jxfear = -1;
469*40586Sbostic 				} else {
470*40586Sbostic 					jumpfrom->s_jxfear = (jumpfrom->s_jxfear + 1) - displ;
471*40586Sbostic 					/*
472*40586Sbostic 					 *	assert jumpfrom->s_jxfear > 0
473*40586Sbostic 					 */
474*40586Sbostic 					if (jumpfrom->s_jxfear == 1){
475*40586Sbostic 						/*our prediction was correct*/
476*40586Sbostic 						continue;
477*40586Sbostic 					}
478*40586Sbostic 					/*
479*40586Sbostic 					 *	assert jumpfrom->s_jxfear > 1
480*40586Sbostic 					 */
481*40586Sbostic 					jumpfrom->s_jxfear -= 1;	/*correct guess*/
482*40586Sbostic 				}
483*40586Sbostic 				/*
484*40586Sbostic 				 *	assert jumpfrom->s_jxfear = -1, +1...2**n-1
485*40586Sbostic 				 */
486*40586Sbostic 				jumpfrom->s_tag = JXNOTYET;	/*signal*/
487*40586Sbostic 				jxxxbump(segno, cojumpfrom);
488*40586Sbostic 				jumpfrom->s_tag = JXINACTIVE;
489*40586Sbostic 				/*
490*40586Sbostic 				 *	Assert jxfrom->jxvalue indexes the first
491*40586Sbostic 				 *	code byte after the added bytes, and
492*40586Sbostic 				 *	has n low order zeroes.
493*40586Sbostic 				 */
494*40586Sbostic 			  }
495*40586Sbostic 			}	/*end of walking through each segment*/
496*40586Sbostic 	    	}	/*end of no changes */
497*40586Sbostic 		else {	/*changes, and still have to try another pass*/
498*40586Sbostic 			jxxxbump(segno, (struct symtab **)0);
499*40586Sbostic 		}
500*40586Sbostic 	   }	/*end of doing the topologic sort*/
501*40586Sbostic 	}	/*end of iterating through all segments*/
502*40586Sbostic }	/*end of jxxxfix*/
503*40586Sbostic 
504*40586Sbostic /*
505*40586Sbostic  *	Go through the symbols in a given segment number,
506*40586Sbostic  *	and see which entries are jxxx entries that have
507*40586Sbostic  *	been logically "exploded" (expanded), but for which
508*40586Sbostic  *	the value of textually following symbols has not been
509*40586Sbostic  *	increased
510*40586Sbostic  */
511*40586Sbostic 
jxxxbump(segno,starthint)512*40586Sbostic jxxxbump(segno, starthint)
513*40586Sbostic 	int	segno;
514*40586Sbostic 	struct	symtab **starthint;
515*40586Sbostic {
516*40586Sbostic 	register	struct	symtab	**cosp, *sp;
517*40586Sbostic 	register	struct	symtab		*ub;
518*40586Sbostic 	register	int	cum_bump;
519*40586Sbostic 	register	unsigned	char	tag;
520*40586Sbostic 
521*40586Sbostic 	cum_bump = 0;
522*40586Sbostic 	SEGITERATE(segno, starthint, 0, cosp, sp, ub, ++){
523*40586Sbostic 		tag = sp->s_tag;
524*40586Sbostic 		if (tag == JXNOTYET){
525*40586Sbostic #ifdef DEBUG
526*40586Sbostic 			if (debug){
527*40586Sbostic 			if (sp->s_dest != 0)
528*40586Sbostic 				printf("Explode jump to %s on line %d\n",
529*40586Sbostic 					FETCHNAME(sp->s_dest), lineno);
530*40586Sbostic 			else
531*40586Sbostic 				printf("Explode an align!\n");
532*40586Sbostic 			}
533*40586Sbostic #endif
534*40586Sbostic 			sp->s_tag = JXINACTIVE;
535*40586Sbostic 			sp->s_jxbump = 1;
536*40586Sbostic 			cum_bump += sp->s_jxfear;
537*40586Sbostic 		}
538*40586Sbostic 		/*
539*40586Sbostic 		 *	Only bump labels and jxxxes. Ignored entries can
540*40586Sbostic 		 *	be incremented, as they are thrown away later on.
541*40586Sbostic 		 *	Stabds are given their final value in the second
542*40586Sbostic 		 *	pass.
543*40586Sbostic 		 */
544*40586Sbostic 		if (tag >= OKTOBUMP)	/*only bump labels and jxxxes and floating stabs*/
545*40586Sbostic 			sp->s_value += cum_bump;
546*40586Sbostic 	}
547*40586Sbostic 	usedot[segno].e_xvalue += cum_bump;
548*40586Sbostic }
549