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