|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)sdi.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: #include "as.h" ! 10: ! 11: /* ! 12: * module to handle span-dependent instructions, e.g. jbr ! 13: * see CACM Vol 21 No 4 April 1978 for a description of the ! 14: * algorithm for resolving sdi's between the 1st and 2nd pass ! 15: */ ! 16: ! 17: #define SQUID( x ) ( ((x)==C_TEXT)||(rflag && ((x) != C_BSS)) ) ! 18: #define INFINITY 0x7fffffff /* larger than any address */ ! 19: ! 20: struct sdi { /* information for span dependent instructions (sdi's) */ ! 21: struct sdi *sdi_next; /* next sdi in list */ ! 22: long int sdi_loc; /* location of the sdi */ ! 23: union{ ! 24: struct sym_bkt *sdi_Sym;/* symbol part of the sdi address */ ! 25: int *sdi_Add; ! 26: }su; ! 27: #define sdi_sym su.sdi_Sym ! 28: #define sdi_address su.sdi_Add ! 29: long int sdi_off; /* offset part of the sdi address */ ! 30: short sdi_leng; /* actual length of the sdi */ ! 31: long int sdi_base; /* origin of the span of the sdi */ ! 32: short sdi_flags; /* bits: is/was it a ddi? */ ! 33: # if EBUG ! 34: unsigned sdi_lineno; ! 35: # endif EBUG ! 36: } *sdi_list; /* linked list of descriptors */ ! 37: ! 38: struct sdi *ddi_list; ! 39: ! 40: /* sdi_flag bit */ ! 41: #define SDI_TYPE 7 /* SDI4, SDI6, SDI8, SDIP */ ! 42: #define SDI_DDI 010 ! 43: #define SDI_EXTERN 020 ! 44: ! 45: /* SDI4, SDI6, SDI8, SDIP, SDIX, SDIL */ ! 46: static int glen[] = { 4, 6, 8, 4, 6, 4 }; ! 47: ! 48: ! 49: /* grab a new sdi descriptor off of the free list; allocate space ! 50: * for a new free list if necessary ! 51: * stolen from the symbol-table manager ! 52: * We keep the sdi and ddi lists separate because: ! 53: * 1) we want to keep locality in the sdi list ! 54: * 2) we want to give back the ddi list ! 55: */ ! 56: ! 57: #define SEGALLOC 100 ! 58: static ! 59: struct seglist { int allocsize, nalloced; struct sdi *nextfree, *head; char *segname;} ! 60: sdilist = { SEGALLOC, 0, NULL, NULL, "sdi" }, ! 61: ddilist = { SEGALLOC, 0, NULL, NULL, "ddi" }; ! 62: ! 63: static long total_delta = 0; ! 64: ! 65: struct sdi * ! 66: sdi_alloc(s) ! 67: register struct seglist *s; ! 68: { ! 69: register struct sdi *sdp, *sdi_free; ! 70: register int i; ! 71: ! 72: if ((sdp = s->nextfree) != NULL) ! 73: s->nextfree = sdp->sdi_next; ! 74: else { ! 75: sdp = (struct sdi *)calloc(s->allocsize,sizeof(struct sdi)); ! 76: if (sdp == NULL) sys_error("%s storage exceeded\n", s->segname); ! 77: sdp->sdi_next = s->head; ! 78: s->head = sdp++; ! 79: sdi_free = NULL; ! 80: for (i = s->allocsize-2; i--;) { ! 81: sdp->sdi_next = sdi_free; ! 82: sdi_free = sdp++; ! 83: } ! 84: s->nextfree = sdi_free; ! 85: s->allocsize *= 2; ! 86: } ! 87: s->nalloced++; ! 88: return(sdp); ! 89: } ! 90: ! 91: void ! 92: sdi_free(s) ! 93: register struct seglist *s; ! 94: { ! 95: register struct sdi *t, *u; ! 96: u = s->head; ! 97: while (u != NULL){ ! 98: t = u->sdi_next; ! 99: free(u); ! 100: u = t; ! 101: } ! 102: s->head = NULL; ! 103: s->nextfree = NULL; ! 104: s->allocsize = SEGALLOC; ! 105: s->nalloced = 0; ! 106: } ! 107: ! 108: /* ! 109: * short-lived data structure ! 110: * used just for sorting the destination addresses, and keeping pointers ! 111: * to the corresponding sdi's. ! 112: */ ! 113: struct sdi_destpair { struct sdi *user; int address; }; ! 114: ! 115: int * destlist; ! 116: int destsize; ! 117: ! 118: sort_destpair( a, b ) ! 119: struct sdi_destpair *a, *b; ! 120: { ! 121: return a->address - b->address; ! 122: } ! 123: ! 124: /* ! 125: * reformulate the base/span representation as follows: ! 126: * for each sdi, form a pair: a pointer to the sdi structure and ! 127: * the destination address (relative to the text base). ! 128: * Sort on destination address, then re-form as an integer array ! 129: * into which point the sdi structures. The array can be segmented ! 130: * to speed up processing it. ! 131: */ ! 132: make_destlist() ! 133: { ! 134: struct sdi_destpair *darray; ! 135: register struct sdi_destpair *dp; ! 136: register struct sdi *s, *d; ! 137: register int *a; ! 138: register ndest = 0; ! 139: register lastaddr, newaddr; ! 140: int ddidelta; ! 141: ! 142: if ( sdilist.nalloced==0 ) return; /* empty list */ ! 143: if ((darray = (struct sdi_destpair *)calloc( sdilist.nalloced , sizeof( struct sdi_destpair))) == NULL) ! 144: sys_error("cannot allocate intermediate structure"); ! 145: for (s=sdi_list, dp = darray; s; s = s->sdi_next){ ! 146: if (s->sdi_loc == -1 ) continue; ! 147: if (s->sdi_sym == NULL){ ! 148: dp->address = s->sdi_off; ! 149: dp++ -> user = s; ! 150: ndest++; ! 151: } ! 152: } ! 153: if (destsize=ndest){ ! 154: qsort( darray, ndest, sizeof (struct sdi_destpair), sort_destpair ); ! 155: destlist = a = (int *)calloc( ndest, sizeof a[0] ); ! 156: if (a==NULL) ! 157: sys_error("cannot allocate intermediate structure"); ! 158: dp = darray; ! 159: *a = lastaddr = dp->address; ! 160: dp++ ->user->sdi_address = a++; ! 161: while (--ndest > 0){ ! 162: if (lastaddr == (newaddr = dp->address)){ ! 163: /* pick up the occasional duplicate destination address */ ! 164: a--; ! 165: destsize--; ! 166: }else ! 167: *a = lastaddr = newaddr; ! 168: dp++ ->user->sdi_address = a++; ! 169: } ! 170: } ! 171: free( darray ); ! 172: /* ! 173: * this is the part I hate. ! 174: * sweep through the sdi list and the dest list in parallel. ! 175: * for each sdi that was a ddi, subtract 2 from all destinations ! 176: * above the base address of the s(d)di. At the same time, ! 177: * sweep through the ddi list and subtract the shrinkage size ! 178: * from all destinations above the base address of the ddi. ! 179: * These are corrective factors we must apply because of initially ! 180: * assuming that all ddi's would be long. The base addresses of ! 181: * the sdi's have already been fixed by the routine resolve_ddi. ! 182: */ ! 183: if (destsize){ ! 184: a = destlist; ! 185: ndest = destsize; ! 186: s = sdi_list; ! 187: d = ddi_list; ! 188: ddidelta = 0; ! 189: while(ndest--){ ! 190: newaddr = *a; ! 191: while( s != NULL && s->sdi_loc < newaddr ){ ! 192: if (s->sdi_flags & SDI_DDI) ! 193: ddidelta += 2; ! 194: s = s->sdi_next; ! 195: } ! 196: while( d != NULL && d->sdi_loc < newaddr ){ ! 197: ddidelta += d->sdi_flags; ! 198: d = d->sdi_next; ! 199: } ! 200: *a++ -= ddidelta; ! 201: } ! 202: } ! 203: } ! 204: ! 205: /* ! 206: * routine to create a sdi descriptor and insert it into the list ! 207: */ ! 208: makesdi(op, base, flavor) ! 209: struct oper *op;/* the operand of the sdi */ ! 210: long int base; /* origin of the the initial span of the sdi, to be */ ! 211: /* corrected between pass1 and pass2 by subtracting */ ! 212: /* from the value of the symbol of the operand */ ! 213: /* i.e. 0 for resolving short absolute address modes */ ! 214: /* Dot[+increment] for PC relative addresses */ ! 215: { ! 216: register struct sdi *s, **p; ! 217: register int loc; ! 218: static long lastloc = INFINITY; /* you wanna see hackery? */ ! 219: static struct sdi * lastsdi; /* we got hackery */ ! 220: ! 221: if (!op ){ /* put the procedure boundary: .proc */ ! 222: if (Oflag) return; ! 223: s = sdi_alloc(&sdilist); ! 224: s->sdi_loc = -1; ! 225: for ( p = lastsdi ? &(lastsdi->sdi_next) : &sdi_list; ! 226: *p; ! 227: p = &(*p)->sdi_next ); ! 228: s->sdi_next = *p; ! 229: *p = s; ! 230: return; ! 231: } ! 232: if (op->flags_o&O_COMPLEX) /* not a simple address */ ! 233: return(0); ! 234: s = sdi_alloc(&sdilist); ! 235: s->sdi_loc = dot; /* future bug here */ ! 236: s->sdi_flags = flavor; ! 237: s->sdi_sym = op->sym_o; ! 238: s->sdi_off = op->value_o-op->sym_o->value_s; /* collect offset-from-label */ ! 239: s->sdi_base = base; ! 240: s->sdi_leng = 2; /* shortest length */ ! 241: # if EBUG ! 242: s->sdi_lineno = line_no; ! 243: # endif EBUG ! 244: loc = dot; ! 245: for ( p = (loc < lastloc) ? &sdi_list : &(lastsdi->sdi_next); ! 246: *p; ! 247: p = &(*p)->sdi_next) ! 248: if (loc < (*p)->sdi_loc) ! 249: break; ! 250: s->sdi_next = *p; ! 251: *p = s; ! 252: lastloc = loc; ! 253: lastsdi = s; ! 254: return(2); /* return the current length */ ! 255: } ! 256: ! 257: /* ! 258: * resolve sdi's between pass1 and pass2 ! 259: * basic algorithm is to repeatedly look for sdi that must use the ! 260: * long form, and update the span of other sdi's. ! 261: * When this terminates, all remaining sdi's can use the short form ! 262: */ ! 263: sdi_resolve() ! 264: { ! 265: register struct sdi *s; ! 266: register struct sym_bkt *p; ! 267: register int t; ! 268: struct sdi *first, *end, *q; ! 269: long loc, big_delta = 0; ! 270: int *dest, *start; ! 271: int changed; ! 272: int csect_offsets[5]; ! 273: ! 274: csect_offsets[C_UNDEF] = 0; ! 275: csect_offsets[C_TEXT ] = 0; ! 276: csect_offsets[C_DATA ] = tsize; ! 277: csect_offsets[C_DATA1] = tsize + dsize; ! 278: csect_offsets[C_DATA2] = tsize + dsize + d1size; ! 279: ! 280: for (s = sdi_list; s && s->sdi_loc == -1; s = s->sdi_next ); ! 281: sdi_list = s; /* get rid of .proc at the beginning */ ! 282: ! 283: for (s = sdi_list; s; s = s->sdi_next) { ! 284: if (s->sdi_loc == -1) continue; ! 285: p = s->sdi_sym; ! 286: if (SQUID(p->csect_s) && (p->attr_s & S_DEF)){ ! 287: s->sdi_off += p->value_s + csect_offsets[p->csect_s]; ! 288: s->sdi_sym = NULL; ! 289: } else ! 290: s->sdi_flags |= SDI_EXTERN; ! 291: } ! 292: ddi_resolve(); ! 293: make_destlist(); ! 294: ! 295: for (first = sdi_list; first; ) { ! 296: for (s=first; s && s->sdi_loc != -1; s=s->sdi_next ) ! 297: end = s; /* find last sdi in this procedure */ ! 298: for (s=end->sdi_next; s && s->sdi_loc == -1; s=s->sdi_next ); ! 299: if (s) ! 300: loc = s->sdi_loc + total_delta; ! 301: else ! 302: loc = INFINITY; ! 303: if (destsize) { ! 304: for (dest = destlist; ! 305: *dest <= loc && dest < destlist + destsize; ! 306: dest++ ); ! 307: start = --dest; /* last label before 'end' */ ! 308: } ! 309: do { ! 310: changed = 0; ! 311: for (s = first; s && s->sdi_loc!=-1 ; s = s->sdi_next) { ! 312: if ((t = sdi_len(s) - s->sdi_leng) > 0) { ! 313: big_delta += t; ! 314: longsdi(s, t, first, start); ! 315: changed = 1; ! 316: } else if (t < 0) { ! 317: sys_error("Pathological sdi\n"); ! 318: } ! 319: } ! 320: } while (changed); ! 321: ! 322: for (s=end->sdi_next; s && s->sdi_loc == -1; s=s->sdi_next ); ! 323: first = s; ! 324: end->sdi_next = first; /* get rid of boundary .proc */ ! 325: for (q = first; q; q = q->sdi_next ) ! 326: q->sdi_base += big_delta; ! 327: if (destsize) ! 328: for ( dest = destlist + destsize - 1; dest > start; dest-- ) ! 329: *dest += big_delta; ! 330: total_delta += big_delta; ! 331: big_delta = 0; ! 332: } ! 333: } ! 334: ! 335: /* ! 336: * update sdi list assuming the specified sdi must be long ! 337: */ ! 338: longsdi(s, delta, first, start ) ! 339: register struct sdi *s, *first; ! 340: register int delta; ! 341: int * start; ! 342: { ! 343: register struct sdi *t; ! 344: register long loc; ! 345: register int *dest; ! 346: ! 347: s->sdi_leng += delta; /* update the length of this sdi */ ! 348: /* get the real location of the sdi */ ! 349: loc = s->sdi_loc + sdi_inc( s->sdi_loc, first); ! 350: for (t = s->sdi_next; t && t->sdi_loc != -1; t = t->sdi_next) ! 351: t->sdi_base += delta; ! 352: if (destsize){ ! 353: for ( dest = start; *dest > loc && dest >= destlist; dest-- ) ! 354: *dest += delta; ! 355: } ! 356: } ! 357: ! 358: /* ! 359: * compute the length of the specified sdi by looking at the possible choices ! 360: */ ! 361: sdi_len(s) ! 362: register struct sdi *s; ! 363: { ! 364: struct bchoice { int len; int lbound, ubound; }; ! 365: static struct bchoice bsdi68[] = { ! 366: { 2, -128, 127 }, ! 367: { 4, -32768, 32767 }, ! 368: { 0, 0, 0 }, ! 369: }; ! 370: static struct bchoice bsdi4[] = { ! 371: { 2, -128, 127 }, ! 372: { 0, 0, 0 }, ! 373: }; ! 374: static struct bchoice bsdip[] = { ! 375: { 2, -32768, 32767 }, ! 376: { 0, 0, 0 }, ! 377: }; ! 378: /* SDI4, SDI6, SDI8, SDIP, */ ! 379: static struct bchoice *blists[] = { bsdi4, bsdi68, bsdi68, bsdip, }; ! 380: /* SDIX and SDIL are never span-dependent, so are not in this table! */ ! 381: ! 382: register struct bchoice *b; ! 383: register span; ! 384: ! 385: span = *s->sdi_address - s->sdi_base; ! 386: if (!(s->sdi_flags&SDI_EXTERN)){ ! 387: for (b = blists[ s->sdi_flags&SDI_TYPE ]; b->len; b++ ) ! 388: if ( b->lbound <= span && span <= b->ubound) ! 389: return(b->len); ! 390: } ! 391: /* only the most general case will do */ ! 392: return(glen[s->sdi_flags&SDI_TYPE]); ! 393: } ! 394: ! 395: /* ! 396: * return the total number of extra bytes due to long sdi's before ! 397: * the specified offset ! 398: */ ! 399: sdi_inc(offset, first) ! 400: struct sdi *first; ! 401: register long offset; ! 402: { ! 403: register struct sdi *s; ! 404: register int total; ! 405: ! 406: if (first) { ! 407: s = first; ! 408: total = total_delta; ! 409: } else { ! 410: s = sdi_list; ! 411: total = 0; ! 412: } ! 413: for (; s; s = s->sdi_next) { ! 414: if (s->sdi_loc == -1 ) continue; ! 415: if (offset <= s->sdi_loc) ! 416: break; ! 417: total += s->sdi_leng - 2; ! 418: if (s->sdi_flags&SDI_DDI){ ! 419: total -= 2; ! 420: } ! 421: } ! 422: for (s = ddi_list ; s; s = s->sdi_next) { ! 423: if (offset <= s->sdi_loc) ! 424: break; ! 425: total -= s->sdi_flags; /* if its still on the list, it shrank */ ! 426: } ! 427: return(total); ! 428: } ! 429: ! 430: /* ! 431: * We are given an array of pointers to symbol-table entries for ! 432: * text labels, sorted by location. Update these by the changes in the ! 433: * sdi's. This used to be done by repeated calls to sdi_inc(), but this ! 434: * was obscenely expensive. Now that we have the lists sorted the same way, ! 435: * we should be able to compute this incrementally. Of course, there was ! 436: * the extra overhead of sorting the symbol list in the first place. ! 437: */ ! 438: sdi_sym_update( symp, nsyms ) ! 439: register struct sym_bkt **symp; ! 440: register int nsyms; ! 441: { ! 442: register struct sdi *sdi; ! 443: register struct sdi *ddi; ! 444: register curloc, curdelta; ! 445: register symloc, curddi; ! 446: curdelta = 0; ! 447: ! 448: if (nsyms==0) return; ! 449: if ((sdi = sdi_list) == NULL) ! 450: curloc = INFINITY; ! 451: else ! 452: curloc = sdi->sdi_loc; ! 453: if ((ddi = ddi_list) == NULL) ! 454: curddi = INFINITY; ! 455: else ! 456: curddi = ddi->sdi_loc; ! 457: while (nsyms--){ ! 458: symloc = (*symp)->value_s; ! 459: while (symloc > curloc){ ! 460: curdelta += sdi->sdi_leng - 2; ! 461: if (sdi->sdi_flags&SDI_DDI){ ! 462: curdelta -= 2; ! 463: } ! 464: if ((sdi = sdi->sdi_next) == NULL){ ! 465: curloc = INFINITY; ! 466: } else { ! 467: curloc = sdi->sdi_loc; ! 468: } ! 469: } ! 470: while (symloc > curddi){ ! 471: curdelta -= ddi->sdi_flags ; /* if on ddi list, it shrank */ ! 472: if ((ddi = ddi->sdi_next) == NULL){ ! 473: curddi = INFINITY; ! 474: } else { ! 475: curddi = ddi->sdi_loc; ! 476: } ! 477: } ! 478: (*symp++)->value_s = symloc + curdelta; ! 479: } ! 480: } ! 481: ! 482: /* ! 483: * Data-dependent instructions ! 484: * are those whose length we may not be able to ascertain at first pass, ! 485: * but which we would like to address in the most effecient manner. ! 486: * Determining their length could, in full generality, be an iterative ! 487: * process, but I think we can make some useful simplifications that ! 488: * will do most of what we desire in one pass over our intermediate ! 489: * data structure. The gross structure will mimic the sdi code above. ! 490: * The instructions we are dealing with here have three forms: ! 491: * long absolute, word absolute, and PC-relative. Thus, there are ! 492: * two lengths of addressing extensions: two bytes and four bytes. ! 493: */ ! 494: ! 495: /* ! 496: * Statistically, ALL data references are long. Thus it makes little ! 497: * sense to follow the sdi strategy of assuming the shortest form until ! 498: * proven otherwise. Since the ddi list is only looked at once, we ! 499: * don't have to maintain the data structures required by the sdi algorithm. ! 500: * In fact, once we've decided that a reference is long, we can take it ! 501: * entirely off the list, if we make this assumption. ! 502: */ ! 503: makeddi(op, base, flavor, wrtflg ) ! 504: struct oper *op;/* the operand of the sdi */ ! 505: long int base; /* origin of the the initial span of the sdi, to be */ ! 506: /* corrected between pass1 and pass2 by subtracting */ ! 507: /* from the value of the symbol of the operand */ ! 508: /* i.e. 0 for resolving short absolute address modes */ ! 509: /* Dot[+increment] for PC relative addresses */ ! 510: int flavor; /* form of ddi: usually SDIP, but for index SDIX, or SDIL for link*/ ! 511: int wrtflg; /* 0 => not memory write destination: PC-relative ok */ ! 512: /* 1 => memory write destination: PC-relative NOT ok */ ! 513: { ! 514: register struct sdi *s, **p; ! 515: register int loc; ! 516: static long lastloc = INFINITY; /* you wanna see hackery? */ ! 517: static struct sdi * lastddi; /* we got hackery */ ! 518: ! 519: if (op->flags_o&O_COMPLEX) /* not a simple address */ ! 520: return(0); ! 521: s = sdi_alloc( &ddilist ); ! 522: s->sdi_loc = dot; /* soon to be a bug */ ! 523: s->sdi_sym = op->sym_o; ! 524: s->sdi_off = op->value_o; ! 525: s->sdi_base = base; ! 526: s->sdi_leng = 4; /* assumed length */ ! 527: s->sdi_flags = flavor; ! 528: # if EBUG ! 529: s->sdi_lineno = line_no; ! 530: # endif EBUG ! 531: if (wrtflg) s->sdi_flags |= SDI_DDI; ! 532: loc = dot; ! 533: ! 534: for ( p = (loc < lastloc) ? &ddi_list : &(lastddi->sdi_next); ! 535: *p; ! 536: p = &(*p)->sdi_next) ! 537: if (loc < (*p)->sdi_loc) ! 538: break; ! 539: s->sdi_next = *p; ! 540: lastloc = loc; ! 541: lastddi = s; ! 542: *p = s; ! 543: return(flavor==SDI6?6:4); /* return the current length */ ! 544: } ! 545: ! 546: ! 547: ddi_resolve() ! 548: { ! 549: register struct sdi *s, **spp, *q; ! 550: register struct sym_bkt *p; ! 551: register int t; ! 552: ! 553: spp = &ddi_list; ! 554: while (s = *spp){ ! 555: p = s->sdi_sym; ! 556: switch (s->sdi_flags){ ! 557: case SDIP: ! 558: if (SQUID(p->csect_s ) && (p->attr_s & S_DEF) ){ ! 559: /* this looks like a job for PC@() */ ! 560: /* fill out the sdi structure, and ! 561: insert it in the sdi list */ ! 562: register struct sdi **pp; ! 563: struct sdi *newsdi; ! 564: ! 565: s->sdi_off += p->value_s; ! 566: s->sdi_sym = NULL; ! 567: /* take ourselves off of ddi list */ ! 568: *spp = s->sdi_next; ! 569: /* ! 570: * here's the tricky part: ! 571: * all the addresses in our lists assume this ! 572: * address has length four. We will now change ! 573: * them so it appears to have length two. ! 574: */ ! 575: shortddi( s, 2 ); ! 576: s->sdi_flags = SDI_DDI|SDIP; ! 577: /* now put ourselves in the sdi list */ ! 578: for (pp = &sdi_list; *pp; pp = &(*pp)->sdi_next) ! 579: if (s->sdi_loc < (*pp)->sdi_loc) ! 580: break; ! 581: newsdi = sdi_alloc(&sdilist); ! 582: *newsdi = *s; ! 583: newsdi->sdi_next = *pp; ! 584: *pp = newsdi; ! 585: /* fix addresses on sdi list, too */ ! 586: newsdi->sdi_leng -= 2; ! 587: for ( q= newsdi->sdi_next; q; q = q->sdi_next ) ! 588: q->sdi_base -= 2; ! 589: /* sdi routines will fix it up later */ ! 590: continue; ! 591: } ! 592: /* else fall through */ ! 593: case SDIP|SDI_DDI: ! 594: case SDI4: ! 595: case SDI4|SDI_DDI: ! 596: if ((p->attr_s & S_DEF) && p->csect_s == C_UNDEF) { ! 597: /* try on a short absolute */ ! 598: t = p->value_s + s->sdi_off; ! 599: if (t >= -32768 && t <= 32767 ){ ! 600: shortddi( s, 2 ); ! 601: spp = &s->sdi_next; ! 602: continue; ! 603: } ! 604: ! 605: } ! 606: /* else it does not shrink -- take off list */ ! 607: break; ! 608: case SDI6: ! 609: case SDI6|SDI_DDI: ! 610: /* ! 611: * Index mode. ! 612: */ ! 613: /* Write bit only confuses us: delete it */ ! 614: s->sdi_flags = SDI6; ! 615: if ((p->attr_s & S_DEF) && p->csect_s == C_UNDEF){ ! 616: /* try very short, then just plain short */ ! 617: t = p->value_s + s->sdi_off; ! 618: if ( t >= -128 && t <= 127 ){ ! 619: /* shrinks much */ ! 620: shortddi( s, 4 ); ! 621: spp = &s->sdi_next; ! 622: continue; ! 623: } else if (t >= -32768 && t <= 32767 ){ ! 624: /* shrinks some */ ! 625: shortddi( s, 2 ); ! 626: spp = &s->sdi_next; ! 627: continue; ! 628: } ! 629: } ! 630: /* else it does not shrink -- take off list */ ! 631: break; ! 632: case SDIX: ! 633: case SDIX|SDI_DDI: ! 634: /* ! 635: * should be displacement mode, but will be ! 636: * index mode with supressed indexing if the ! 637: * displacement is too big. ! 638: */ ! 639: /* FALL THROUGH */ ! 640: case SDIL: ! 641: /* ! 642: * link instruction: looks like SDIP, but is not ! 643: * PC-relative. ! 644: */ ! 645: /* Write bit only confuses us: delete it */ ! 646: s->sdi_flags &= SDI_TYPE; ! 647: if ((p->attr_s & S_DEF) && p->csect_s == C_UNDEF){ ! 648: /* try short */ ! 649: t = p->value_s + s->sdi_off; ! 650: if (t >= -32768 && t <= 32767 ){ ! 651: /* shrinks */ ! 652: shortddi( s, glen[s->sdi_flags&SDI_TYPE] - 2 ); ! 653: spp = &s->sdi_next; ! 654: continue; ! 655: } ! 656: } ! 657: /* else it does not shrink -- take off list */ ! 658: break; ! 659: } ! 660: /* take ddi off the list */ ! 661: *spp = s->sdi_next; ! 662: } ! 663: if (ddi_list == NULL){ ! 664: sdi_free(&ddilist); /* all gone */ ! 665: } else { ! 666: register int cursdi; ! 667: /* ! 668: * Sweep through ddi list and sdi list in parallel, ! 669: * fixing up sdi base-addresses. ! 670: */ ! 671: s = ddi_list; ! 672: t = 0; ! 673: q = sdi_list; ! 674: while (q != NULL){ ! 675: cursdi = q->sdi_base; ! 676: while ( s != NULL && s->sdi_base < cursdi ){ ! 677: t += s->sdi_flags; ! 678: s = s->sdi_next; ! 679: } ! 680: q->sdi_base -= t; ! 681: q = q->sdi_next; ! 682: } ! 683: } ! 684: } ! 685: ! 686: shortddi( s, d ) ! 687: register struct sdi *s; ! 688: register d; ! 689: { ! 690: /* ! 691: * A ddi shrank! Adjust all lists accordingly. ! 692: */ ! 693: register struct sdi *t; ! 694: register loc = s->sdi_loc+sdi_inc( s->sdi_loc, NULL); ! 695: ! 696: s->sdi_flags = d; /* how much I shrank */ ! 697: for (t = ddi_list; t; t = t->sdi_next) ! 698: if (t != s && t->sdi_base > loc) ! 699: t->sdi_base -= d; ! 700: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.