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