|
|
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: * the code above and comment below was written by someone ! 138: * who needs a little more experience in the real world. ! 139: * if you wish to do big .aligns, please do so; beware ! 140: * what the loader will do, but so what? ! 141: */ ! 142: if ( (xp->e_xtype != XABS) ! 143: || (xp->e_xvalue < 0) ! 144: || (xp->e_xvalue > 16) ! 145: ) { ! 146: yyerror("Illegal `align' argument"); ! 147: return; ! 148: } ! 149: #ifdef CRINOID ! 150: if (xp->e_xvalue > 2){ ! 151: if (passno == 1){ ! 152: yywarning(".align %d in any segment is NOT preserved by the loader", ! 153: xp->e_xvalue); ! 154: yywarning(".align %d converted to .align 2", ! 155: xp->e_xvalue); ! 156: } ! 157: xp->e_xvalue = 2; ! 158: } ! 159: #endif ! 160: flushfield(NBPW/4); ! 161: if (passno == 1) { ! 162: sp->s_tag = JXALIGN; ! 163: sp->s_jxfear = (1 << xp->e_xvalue) - 1; ! 164: sp->s_type = dotp->e_xtype; ! 165: sp->s_index = dotp-usedot; ! 166: /* ! 167: * We guess that the align will take up at least one ! 168: * byte in the code output. We will correct for this ! 169: * initial high guess when we explode (bump) aligns ! 170: * when we fix the jxxxes. We must do this guess ! 171: * so that the symbol table is sorted correctly ! 172: * and labels declared to fall before the align ! 173: * really get their, instead of guessing zero size ! 174: * and have the label (incorrectly) fall after the jxxx. ! 175: * This is a quirk of our requirement that indices into ! 176: * the code stream point to the next byte following ! 177: * the logical entry in the symbol table ! 178: */ ! 179: dotp->e_xvalue += 1; ! 180: sp->s_value = dotp->e_xvalue; ! 181: njxxx++; ! 182: } else { ! 183: mask = (1 << xp->e_xvalue) - 1; ! 184: while (dotp->e_xvalue & mask){ ! 185: #ifdef UNIX ! 186: outb(0); ! 187: #endif UNIX ! 188: #ifdef VMS ! 189: *vms_obj_ptr++ = -1; ! 190: *vms_obj_ptr++ = 0; ! 191: dotp->e_xvalue += 1; ! 192: #endif VMS ! 193: } ! 194: } ! 195: } ! 196: ! 197: /* ! 198: * Pass 1.5, resolve jxxx instructions and .align in .text ! 199: */ ! 200: jxxxfix() ! 201: { ! 202: register struct symtab *jumpfrom; ! 203: struct symtab **cojumpfrom, *ubjumpfrom; ! 204: register struct symtab *dest; ! 205: register struct symtab *intdest; /*intermediate dest*/ ! 206: register struct symtab **cointdest, *ubintdest; ! 207: ! 208: register struct symtab *tunnel; ! 209: int displ,nchange; ! 210: int badjxalign; /*if jump across an align*/ ! 211: int stillactives; /*if still active jxxxes*/ ! 212: int segno; /*current segment number*/ ! 213: int topono; /*which iteration in the topo sort*/ ! 214: register unsigned char tag; ! 215: /* ! 216: * consider each segment in turn... ! 217: */ ! 218: for (segno = 0; segno < NLOC + NLOC; segno++){ ! 219: badjxalign = 0; /*done on a per segment basis*/ ! 220: /* ! 221: * Do a lazy topological sort. ! 222: */ ! 223: for (topono = 1, nchange = 1; nchange != 0; topono++){ ! 224: #ifdef DEBUG ! 225: if (debug) ! 226: printf("\nSegment %d, topo iteration %d\n", ! 227: segno, topono); ! 228: #endif ! 229: nchange = 0; ! 230: stillactives = 0; ! 231: /* ! 232: * We keep track of one possible tunnel location. ! 233: * A tunnel will eventually be an unconditional ! 234: * branch to the same place that another jxxx ! 235: * will want to branch to. We will turn a ! 236: * branch conditional/unconditional (word) that would ! 237: * have to get bumped because its destination is too ! 238: * far away, into a branch conditional/unconditional ! 239: * byte to the tunnel branch conditional/unconditional. ! 240: * Of course, the tunnel must branch to the same place ! 241: * as we want to go. ! 242: */ ! 243: tunnel = 0; /*initially, no tunnel*/ ! 244: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){ ! 245: tag = jumpfrom->s_tag; ! 246: if (tag <= IGNOREBOUND) ! 247: continue; /*just an ordinary symbol*/ ! 248: if (tag == JXALIGN){ ! 249: tunnel = 0; /*avoid tunneling across a flex alocation*/ ! 250: continue; /*we take care of these later*/ ! 251: } ! 252: if ( jumpfrom->s_jxfear == jbrfsize /*unconditional*/ ! 253: || ( tag == JXINACTIVE /*inactive bumped*/ ! 254: && (jumpfrom->s_jxbump != 0) ! 255: ) ! 256: ) tunnel = jumpfrom; ! 257: if (tag != JXACTIVE) ! 258: continue; ! 259: dest = jumpfrom->s_dest; ! 260: if (jumpfrom->s_index != dest->s_index){ ! 261: yyerror("Intersegment jxxx"); ! 262: continue; ! 263: } ! 264: displ = dest->s_value - jumpfrom->s_value; ! 265: if (displ < MINBYTE || displ > MAXBYTE) { ! 266: /* ! 267: * This is an immediate lose! ! 268: * ! 269: * We first attempt to tunnel ! 270: * by finding an intervening jump that ! 271: * has the same destination. ! 272: * The tunnel is always the first preceeding ! 273: * jxxx instruction, so the displacement ! 274: * to the tunnel is less than zero, and ! 275: * its relative position will be unaffected ! 276: * by future jxxx expansions. ! 277: * ! 278: * No tunnels if doing jumps... ! 279: */ ! 280: if ( (!jxxxJUMP) ! 281: && (jumpfrom->s_jxfear > jbrfsize) ! 282: && (tunnel) ! 283: && (tunnel->s_dest == jumpfrom->s_dest) ! 284: && (tunnel->s_index == jumpfrom->s_index) ! 285: && (tunnel->s_value - jumpfrom->s_value >= ! 286: MINBYTE + jxxxfsize) ! 287: ) { ! 288: /* ! 289: * tunnelling is OK ! 290: */ ! 291: jumpfrom->s_dest = tunnel; ! 292: /* ! 293: * no bumping needed, this ! 294: * is now effectively inactive ! 295: * but must be remembered ! 296: */ ! 297: jumpfrom->s_tag = JXTUNNEL; ! 298: #ifdef DEBUG ! 299: if(debug) ! 300: printf("Tunnel from %s from line %d\n", ! 301: jumpfrom->s_name, lineno); ! 302: #endif ! 303: continue; ! 304: } else { /*tunneling not possible*/ ! 305: /* ! 306: * since this will be turned ! 307: * into a bumped jump, we can ! 308: * use the unconditional jump ! 309: * as a tunnel ! 310: */ ! 311: tunnel = jumpfrom; ! 312: jumpfrom->s_tag = JXNOTYET; ! 313: ++nchange; ! 314: continue; ! 315: } ! 316: } /*end of immediate lose*/ ! 317: /* ! 318: * Do a forward search for an intervening jxxx ! 319: */ ! 320: if (displ >= 0) { ! 321: SEGITERATE(segno, cojumpfrom + 1,0,cointdest, ! 322: intdest, ubintdest, ++){ ! 323: if (intdest->s_value > dest->s_value) ! 324: break; /* beyond destination */ ! 325: if (intdest->s_tag <= JXQUESTIONABLE) ! 326: continue; /*frozen solid*/ ! 327: if (intdest->s_tag == JXALIGN){ ! 328: jumpfrom->s_jxoveralign = 1; ! 329: badjxalign++; ! 330: } ! 331: /* ! 332: * we assume the worst case ! 333: * for unfrozen jxxxxes ! 334: */ ! 335: displ += intdest->s_jxfear; ! 336: } ! 337: if (displ <= MAXBYTE){ ! 338: /* ! 339: * the worst possible conditions ! 340: * can't hurt us, so forget about ! 341: * this jump ! 342: */ ! 343: jumpfrom->s_tag = JXINACTIVE; ! 344: } else { ! 345: stillactives++; ! 346: } ! 347: } else { ! 348: /* ! 349: * backward search for intervening jxxx ! 350: */ ! 351: SEGITERATE(segno, cojumpfrom - 1,1,cointdest, ! 352: intdest, ubintdest, --){ ! 353: if (intdest->s_value <= dest->s_value) ! 354: break; /* beyond destination */ ! 355: if (intdest->s_tag <= JXQUESTIONABLE) ! 356: continue; /*frozen solid*/ ! 357: if (intdest->s_tag == JXALIGN){ ! 358: jumpfrom->s_jxoveralign = 1; ! 359: badjxalign++; ! 360: } ! 361: displ -= intdest->s_jxfear; ! 362: } ! 363: if (displ >= MINBYTE) { ! 364: jumpfrom->s_tag = JXINACTIVE; ! 365: } else { ! 366: stillactives++; ! 367: } ! 368: } /*end of backwards search*/ ! 369: } /*end of iterating through all symbols in this seg*/ ! 370: ! 371: if (nchange == 0) { ! 372: /* ! 373: * Now, if there are still active jxxx entries, ! 374: * we are partially deadlocked. We can leave ! 375: * these jxxx entries in their assumed short jump ! 376: * form, as all initial displacement calcualtions ! 377: * are hanging on unresolved jxxx instructions ! 378: * that might explode into a long form, causing ! 379: * other jxxxes jumping across the first set of ! 380: * jxxxes to explode, etc. ! 381: * However, if a jxxx jumps across a .align, ! 382: * we assume the worst for the deadlock cycle, ! 383: * and resolve all of them towards the long ! 384: * jump. ! 385: * Currently, the C compiler does not produce ! 386: * jumps across aligns, as aligns are only used ! 387: * in data segments, or in text segments to align ! 388: * functions. ! 389: */ ! 390: if (stillactives){ ! 391: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ! 392: ubjumpfrom, ++){ ! 393: if (jumpfrom->s_tag == JXACTIVE){ ! 394: jumpfrom->s_tag = ! 395: badjxalign?JXNOTYET:JXINACTIVE; ! 396: } ! 397: } ! 398: if (badjxalign){ ! 399: jxxxbump(segno, (struct symtab **)0); ! 400: } ! 401: } ! 402: /* ! 403: * Handle all of the .align s ! 404: */ ! 405: SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ! 406: ubjumpfrom, ++){ ! 407: if (jumpfrom->s_tag == JXALIGN){ ! 408: /* ! 409: * Predict the true displacement ! 410: * needed, irregardless of the ! 411: * fact that we guessed 1 ! 412: */ ! 413: displ = (jumpfrom->s_value - 1) & (unsigned)jumpfrom->s_jxfear; ! 414: if (displ == 0){ /*no virtual displacement*/ ! 415: jumpfrom->s_jxfear = -1; ! 416: } else { ! 417: jumpfrom->s_jxfear = (jumpfrom->s_jxfear + 1) - displ; ! 418: /* ! 419: * assert jumpfrom->s_jxfear > 0 ! 420: */ ! 421: if (jumpfrom->s_jxfear == 1){ ! 422: /*our prediction was correct*/ ! 423: continue; ! 424: } ! 425: /* ! 426: * assert jumpfrom->s_jxfear > 1 ! 427: */ ! 428: jumpfrom->s_jxfear -= 1; /*correct guess*/ ! 429: } ! 430: /* ! 431: * assert jumpfrom->s_jxfear = -1, +1...2**n-1 ! 432: */ ! 433: jumpfrom->s_tag = JXNOTYET; /*signal*/ ! 434: jxxxbump(segno, cojumpfrom); ! 435: jumpfrom->s_tag = JXINACTIVE; ! 436: /* ! 437: * Assert jxfrom->jxvalue indexes the first ! 438: * code byte after the added bytes, and ! 439: * has n low order zeroes. ! 440: */ ! 441: } ! 442: } /*end of walking through each segment*/ ! 443: } /*end of no changes */ ! 444: else { /*changes, and still have to try another pass*/ ! 445: jxxxbump(segno, (struct symtab **)0); ! 446: } ! 447: } /*end of doing the topologic sort*/ ! 448: } /*end of iterating through all segments*/ ! 449: } /*end of jxxxfix*/ ! 450: ! 451: /* ! 452: * Go through the symbols in a given segment number, ! 453: * and see which entries are jxxx entries that have ! 454: * been logically "exploded" (expanded), but for which ! 455: * the value of textually following symbols has not been ! 456: * increased ! 457: */ ! 458: ! 459: jxxxbump(segno, starthint) ! 460: int segno; ! 461: struct symtab **starthint; ! 462: { ! 463: register struct symtab **cosp, *sp; ! 464: register struct symtab *ub; ! 465: register int cum_bump; ! 466: register unsigned char tag; ! 467: ! 468: cum_bump = 0; ! 469: SEGITERATE(segno, starthint, 0, cosp, sp, ub, ++){ ! 470: tag = sp->s_tag; ! 471: if (tag == JXNOTYET){ ! 472: #ifdef DEBUG ! 473: if (debug){ ! 474: if (sp->s_dest != 0) ! 475: printf("Explode jump to %s on line %d\n", ! 476: sp->s_dest->s_name, lineno); ! 477: else ! 478: printf("Explode an align!\n"); ! 479: } ! 480: #endif ! 481: sp->s_tag = JXINACTIVE; ! 482: sp->s_jxbump = 1; ! 483: cum_bump += sp->s_jxfear; ! 484: } ! 485: /* ! 486: * Only bump labels and jxxxes. Ignored entries can ! 487: * be incremented, as they are thrown away later on. ! 488: * Stabds are given their final value in the second ! 489: * pass. ! 490: */ ! 491: if (tag >= OKTOBUMP) /*only bump labels and jxxxes and floating stabs*/ ! 492: sp->s_value += cum_bump; ! 493: } ! 494: usedot[segno].e_xvalue += cum_bump; ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.