|
|
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.