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