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