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