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