Annotation of researchv9/cmd/sun/as/sdi.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.