|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #include <stdio.h>
3: #include "as.h"
4: #include "assyms.h"
5:
6: #define JBR 0x11
7: #define BRW 0x31
8:
9: /*
10: * The number of bytes to add if the jxxx must be "exploded"
11: * into the long form
12: */
13: #define JBRFSIZE 1 /*goes to brw*/
14: #define JXXXFSIZE 3 /*goes to brb, brw <byte> <byte> */
15:
16: /*
17: * These variables are filled by asscan.c with the
18: * last name encountered (a pointer buried in the intermediate file),
19: * and the last jxxx symbol table entry encountered.
20: */
21: struct symtab *lastnam;
22: struct symtab *lastjxxx;
23:
24: /*
25: * Handle jxxx instructions
26: */
27: ijxout(op,ap,nact)
28: struct arg *ap;
29: {
30: if (passno == 1){
31: /*
32: * READ THIS BEFORE LOOKING AT jxxxfix()
33: *
34: * Record the jxxx in a special symbol table entry
35: */
36: register struct symtab *jumpfrom;
37:
38: /*
39: * We assume the MINIMAL length
40: */
41: putins(op,ap,nact);
42: jumpfrom = lastjxxx;
43: jumpfrom->tag = JXACTIVE;
44: jumpfrom->jxbump = 0;
45: if (op == JBR)
46: jumpfrom->jxfear = JBRFSIZE;
47: else
48: jumpfrom->jxfear = JXXXFSIZE;
49: #ifdef DJXXX
50: jumpfrom->jxline = lineno;
51: #endif
52: if (lastnam == 0)
53: yyerror("jxxx destination not a label");
54: jumpfrom->dest = lastnam;
55: jumpfrom->type = dotp->xtype; /*only TEXT or DATA*/
56: jumpfrom->index = dotp-usedot;
57: /*
58: * value ALWAYS (ALWAYS!!!) indexes the next instruction
59: * after the jump, even in the jump must be exploded
60: * (bumped)
61: */
62: jumpfrom->value = dotp->xvalue;
63: njxxx++;
64: } else {/* pass2, resolve */
65: /*
66: * READ THIS AFTER LOOKING AT jxxxfix()
67: */
68: register long oxvalue;
69: register struct exp *xp;
70: register struct symtab *tunnel;
71: register struct arg *aplast;
72:
73: aplast = ap + nact - 1;
74: xp = aplast->xp;
75: if (lastjxxx->tag == JXTUNNEL){
76: lastjxxx->tag = JXINACTIVE;
77: tunnel = lastjxxx->dest;
78: xp->xvalue = tunnel->value /*index of instruction following*/
79: - 3 /* size of brw + word*/
80: + ( ( (tunnel->jxfear == JBRFSIZE) &&
81: (tunnel->jxbump == 0))?1:0);
82: /*non bumped branch byteis only 2 back*/
83: }
84: if (lastjxxx->jxbump == 0){ /*wasn't bumped, so is short form*/
85: putins(op, ap, nact);
86: } else {
87: if (op != JBR){ /*branch reverse conditional byte over
88: branch unconditional word*/
89: oxvalue = xp->xvalue;
90: xp->xvalue = lastjxxx->value;
91: putins(op^1, ap, nact);
92: xp->xvalue = oxvalue;
93: }
94: putins(BRW, aplast, 1);
95: }
96: }
97: } /*end of ijxout*/
98:
99: jalign(xp, sp)
100: register struct exp *xp;
101: register struct symtab *sp;
102: {
103: register int mask;
104: if (xp->xtype != XABS || xp->xvalue < 0 || xp->xvalue > 16) {
105: yyerror("Illegal `align' argument");
106: return;
107: }
108: flushfield(NBPW/4);
109: if (passno == 1) {
110: sp->tag = JXALIGN;
111: sp->jxfear = (1 << xp->xvalue) - 1;
112: #ifdef DJXXX
113: sp->jxline = lineno;
114: #endif
115: sp->type = dotp->xtype;
116: sp->index = dotp-usedot;
117: /*
118: * We guess that the align will take up at least one
119: * byte in the code output. We will correct for this
120: * initial high guess when we explode (bump) aligns
121: * when we fix the jxxxes. We must do this guess
122: * so that the symbol table is sorted correctly
123: * and labels declared to fall before the align
124: * really get their, instead of guessing zero size
125: * and have the label (incorrectly) fall after the jxxx.
126: * This is a quirk of our requirement that indices into
127: * the code stream point to the next byte following
128: * the logical entry in the symbol table
129: */
130: dotp->xvalue += 1;
131: sp->value = dotp->xvalue;
132: njxxx++;
133: } else {
134: mask = (1 << xp->xvalue) - 1;
135: while (dotp->xvalue & mask){
136: outb(0);
137: }
138: }
139: }
140:
141: /*
142: * Pass 1.5, resolve jxxx instructions and .align in .text
143: */
144: jxxxfix()
145: {
146: register struct symtab *jumpfrom;
147: struct symtab **cojumpfrom, *ubjumpfrom;
148: register struct symtab *dest;
149: register struct symtab *intdest; /*intermediate dest*/
150: register struct symtab **cointdest, *ubintdest;
151:
152: register struct symtab *tunnel;
153: int displ,nchange;
154: int badjxalign; /*if jump across an align*/
155: int stillactives; /*if still active jxxxes*/
156: int segno; /*current segment number*/
157: int topono; /*which iteration in the topo sort*/
158: register unsigned char tag;
159: /*
160: * consider each segment in turn...
161: */
162: for (segno = 0; segno < NLOC + NLOC; segno++){
163: badjxalign = 0; /*done on a per segment basis*/
164: /*
165: * Do a lazy topological sort.
166: */
167: for (topono = 1, nchange = 1; nchange != 0; topono++){
168: #ifdef DEBUG
169: if (debug)
170: printf("\nSegment %d, topo iteration %d\n",
171: segno, topono);
172: #endif
173: nchange = 0;
174: stillactives = 0;
175: /*
176: * We keep track of one possible tunnel location.
177: * A tunnel will eventually be an unconditional
178: * branch to the same place that another jxxx
179: * will want to branch to. We will turn a
180: * branch conditional/unconditional (word) that would
181: * have to get bumped because its destination is too
182: * far away, into a branch conditional/unconditional
183: * byte to the tunnel branch conditional/unconditional.
184: * Of course, the tunnel must branch to the same place
185: * as we want to go.
186: */
187: tunnel = 0; /*initially, no tunnel*/
188: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){
189: tag = jumpfrom->tag;
190: if (tag <= IGNOREBOUND)
191: continue; /*just an ordinary symbol*/
192: if (tag == JXALIGN){
193: tunnel = 0; /*avoid tunneling across a flex alocation*/
194: continue; /*we take care of these later*/
195: }
196: if ( jumpfrom->jxfear == JBRFSIZE /*unconditional*/
197: || ( tag == JXINACTIVE /*inactive bumped*/
198: && (jumpfrom->jxbump != 0)
199: )
200: ) tunnel = jumpfrom;
201: if (tag != JXACTIVE)
202: continue;
203: dest = jumpfrom->dest;
204: if (jumpfrom->index != dest->index){
205: yyerror("Intersegment jxxx");
206: continue;
207: }
208: displ = dest->value - jumpfrom->value;
209: if (displ < MINBYTE || displ > MAXBYTE) {
210: /*
211: * This is an immediate lose!
212: *
213: * We first attempt to tunnel
214: * by finding an intervening jump that
215: * has the same destination.
216: * The tunnel is always the first preceeding
217: * jxxx instruction, so the displacement
218: * to the tunnel is less than zero, and
219: * its relative position will be unaffected
220: * by future jxxx expansions.
221: */
222: if ( (jumpfrom->jxfear > JBRFSIZE)
223: && (tunnel)
224: && (tunnel->dest == jumpfrom->dest)
225: && (tunnel->index == jumpfrom->index)
226: && (tunnel->value - jumpfrom->value >=
227: MINBYTE + JXXXFSIZE)
228: ) {
229: /*
230: * tunnelling is OK
231: */
232: jumpfrom->dest = tunnel;
233: /*
234: * no bumping needed, this
235: * is now effectively inactive
236: * but must be remembered
237: */
238: jumpfrom->tag = JXTUNNEL;
239: #ifdef DEBUG
240: if(debug)
241: printf("Tunnel from %s from line %d\n",
242: jumpfrom->name, lineno);
243: #endif
244: #ifdef METRIC
245: jxxxtunnel++;
246: #endif
247: continue;
248: } else { /*tunneling not possible*/
249: /*
250: * since this will be turned
251: * into a bumped jump, we can
252: * use the unconditional jump
253: * as a tunnel
254: */
255: tunnel = jumpfrom;
256: jumpfrom->tag = JXNOTYET;
257: ++nchange;
258: continue;
259: }
260: } /*end of immediate lose*/
261: /*
262: * Do a forward search for an intervening jxxx
263: */
264: if (displ >= 0) {
265: SEGITERATE(segno, cojumpfrom + 1,0,cointdest,
266: intdest, ubintdest, ++){
267: if (intdest->value > dest->value)
268: break; /* beyond destination */
269: if (intdest->tag <= JXQUESTIONABLE)
270: continue; /*frozen solid*/
271: if (intdest->tag == JXALIGN){
272: jumpfrom->jxoveralign = 1;
273: badjxalign++;
274: }
275: /*
276: * we assume the worst case
277: * for unfrozen jxxxxes
278: */
279: displ += intdest->jxfear;
280: }
281: if (displ <= MAXBYTE){
282: /*
283: * the worst possible conditions
284: * can't hurt us, so forget about
285: * this jump
286: */
287: jumpfrom->tag = JXINACTIVE;
288: } else {
289: stillactives++;
290: }
291: } else {
292: /*
293: * backward search for intervening jxxx
294: */
295: SEGITERATE(segno, cojumpfrom - 1,1,cointdest,
296: intdest, ubintdest, --){
297: if (intdest->value <= dest->value)
298: break; /* beyond destination */
299: if (intdest->tag <= JXQUESTIONABLE)
300: continue; /*frozen solid*/
301: if (intdest->tag == JXALIGN){
302: jumpfrom->jxoveralign = 1;
303: badjxalign++;
304: }
305: displ -= intdest->jxfear;
306: }
307: if (displ >= MINBYTE) {
308: jumpfrom->tag = JXINACTIVE;
309: } else {
310: stillactives++;
311: }
312: } /*end of backwards search*/
313: } /*end of iterating through all symbols in this seg*/
314:
315: if (nchange == 0) {
316: /*
317: * Now, if there are still active jxxx entries,
318: * we are partially deadlocked. We can leave
319: * these jxxx entries in their assumed short jump
320: * form, as all initial displacement calcualtions
321: * are hanging on unresolved jxxx instructions
322: * that might explode into a long form, causing
323: * other jxxxes jumping across the first set of
324: * jxxxes to explode, etc.
325: * However, if a jxxx jumps across a .align,
326: * we assume the worst for the deadlock cycle,
327: * and resolve all of them towards the long
328: * jump.
329: * Currently, the C compiler does not produce
330: * jumps across aligns, as aligns are only used
331: * in data segments, or in text segments to align
332: * functions.
333: */
334: if (stillactives){
335: #ifdef METRIC
336: jxdeadlock++;
337: #endif
338: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
339: ubjumpfrom, ++){
340: if (jumpfrom->tag == JXACTIVE){
341: jumpfrom->tag =
342: badjxalign?JXNOTYET:JXINACTIVE;
343: }
344: }
345: if (badjxalign){
346: jxxxbump(segno, 0);
347: #ifdef METRIC
348: nbadjxsegs++;
349: #endif
350: }
351: }
352: /*
353: * Handle all of the .align s
354: */
355: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
356: ubjumpfrom, ++){
357: if (jumpfrom->tag == JXALIGN){
358: /*
359: * Predict the true displacement
360: * needed, irregardless of the
361: * fact that we guessed 1
362: */
363: displ = (jumpfrom->value - 1) & (unsigned)jumpfrom->jxfear;
364: if (displ == 0){ /*no virtual displacement*/
365: jumpfrom->jxfear = -1;
366: } else {
367: jumpfrom->jxfear = (jumpfrom->jxfear + 1) - displ;
368: /*
369: * assert jumpfrom->jxfear > 0
370: */
371: if (jumpfrom->jxfear == 1){
372: /*our prediction was correct*/
373: continue;
374: }
375: /*
376: * assert jumpfrom->jxfear > 1
377: */
378: jumpfrom->jxfear -= 1; /*correct guess*/
379: }
380: /*
381: * assert jumpfrom->jxfear = -1, +1...2**n-1
382: */
383: jumpfrom->tag = JXNOTYET; /*signal*/
384: jxxxbump(segno, cojumpfrom);
385: jumpfrom->tag = JXINACTIVE;
386: /*
387: * Assert jxfrom->jxvalue indexes the first
388: * code byte after the added bytes, and
389: * has n low order zeroes.
390: */
391: }
392: } /*end of walking through each segment*/
393: } /*end of no changes */
394: else { /*changes, and still have to try another pass*/
395: jxxxbump(segno, 0);
396: }
397: } /*end of doing the topologic sort*/
398: } /*end of iterating through all segments*/
399: } /*end of jxxxfix*/
400:
401: /*
402: * Go through the symbols in a given segment number,
403: * and see which entries are jxxx entries that have
404: * been logically "exploded" (expanded), but for which
405: * the value of textually following symbols has not been
406: * increased
407: */
408:
409: jxxxbump(segno, starthint)
410: int segno;
411: struct symtab **starthint;
412: {
413: register struct symtab **cosp, *sp;
414: register struct symtab *ub;
415: register int cum_bump;
416: register unsigned char tag;
417:
418: #ifdef METRIC
419: jxxxiterate++;
420: #endif
421: cum_bump = 0;
422: SEGITERATE(segno, starthint, 0, cosp, sp, ub, ++){
423: tag = sp->tag;
424: if (tag == JXNOTYET){
425: #ifdef DEBUG
426: if (debug){
427: if (sp->dest != 0)
428: printf("Explode jump to %s on line %d\n",
429: sp->dest->name, lineno);
430: else
431: printf("Explode an align!\n");
432: }
433: #endif
434: sp->tag = JXINACTIVE;
435: sp->jxbump = 1;
436: cum_bump += sp->jxfear;
437: }
438: /*
439: * Only bump labels and jxxxes. Ignored entries can
440: * be incremented, as they are thrown away later on.
441: * Stabds are given their final value in the second
442: * pass.
443: */
444: if (tag >= OKTOBUMP) /*only bump labels and jxxxes and floating stabs*/
445: sp->value += cum_bump;
446: }
447: usedot[segno].xvalue += cum_bump;
448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.