Annotation of researchv9/jerq/sgs/ld/regions.c, revision 1.1.1.1

1.1       root        1: static char ID[] = "@(#) regions.c: 1.6 8/15/83";
                      2: 
                      3: #include <stdio.h>
                      4: #include "system.h"
                      5: #include "structs.h"
                      6: #include "extrns.h"
                      7: #include "list.h"
                      8: #include "params.h"
                      9: #include "sgsmacros.h"
                     10: 
                     11: void
                     12: bldreglist()
                     13: {
                     14:        register REGION  *rp;
                     15:        register ANODE *ap;
                     16:        ANODE   *newap,
                     17:                *splitnode();
                     18: /*
                     19:  * Now collate the regions into the available space list
                     20:  */
                     21: 
                     22:        for( rp = (REGION *) reglist.head; rp != NULL; rp = rp->rgnext ) {
                     23:                /*
                     24:                 * Map start of region to an avail space node
                     25:                 */
                     26:                ap = findnode(rp->rgorig, 1);
                     27: 
                     28:                if( (int) ap ==  -1 ) {
                     29:                        lderror(1,0,NULL, "region %.8s outside of configured memory",
                     30:                                rp->rgname);
                     31:                        continue;
                     32:                        }
                     33: 
                     34:                if( ap->adpaddr == rp->rgorig ) {
                     35:                        /*
                     36:                         * Region starts on node boundry
                     37:                         */
                     38:                        rp->rgaddrhd = ap;
                     39:                        }
                     40:                else if( ap->adpaddr < rp->rgorig ) {
                     41:                        /*
                     42:                         * Region starts within avail node
                     43:                         */
                     44:                        rp->rgaddrhd = splitnode(ap,rp->rgorig);
                     45:                        }
                     46:                else {
                     47:                        /*
                     48:                         * Region starts between or before a node
                     49:                         */
                     50:                        if( rp->rgorig+rp->rglength <= ap->adpaddr ) {
                     51:                                lderror(1,0,NULL, "region %.8s is in unconfigured memory",
                     52:                                        rp->rgname);
                     53:                                continue;
                     54:                                }
                     55:                        else
                     56:                                rp->rgaddrhd = ap;
                     57:                        }
                     58: 
                     59:                /*
                     60:                 * Now map the end of the region to an avail space node
                     61:                 */
                     62:                ap = findnode(rp->rgorig+rp->rglength - 1, 0);
                     63:                if( (int) ap  ==  -1 )
                     64:                        /*
                     65:                         * If not found
                     66:                         */
                     67:                        ap = (ANODE *) avlist.tail;
                     68: 
                     69:                if( rp->rgorig+rp->rglength < ap->adpaddr+ap->adsize ) {
                     70:                        /*
                     71:                         * Region ends within the node
                     72:                         */
                     73:                        splitnode(ap, rp->rgorig+rp->rglength);
                     74:                        rp->rgaddrtl = ap;
                     75:                        }
                     76:                else if( rp->rgorig+rp->rglength==ap->adpaddr+ap->adsize ) {
                     77:                        /*
                     78:                         * Region ends at node boundry
                     79:                         */
                     80:                        rp->rgaddrtl = ap;
                     81:                        }
                     82:                else {
                     83:                        /*
                     84:                         * Region ends after ap
                     85:                         */
                     86:                        rp->rgaddrtl = ap;
                     87:                        }
                     88: 
                     89:                /*
                     90:                 * Set region ptrs within address space subsequence to rp
                     91:                 */
                     92:                for( newap = rp->rgaddrhd; newap != rp->rgaddrtl->adnext; newap = newap->adnext )
                     93:                        newap->adregp = rp;
                     94: 
                     95:                }
                     96:  
                     97: }
                     98: /*eject*/
                     99: bld_regions()
                    100: {
                    101: 
                    102: /*
                    103:  * Builds regions for the output sections of a tv load.
                    104:  *
                    105:  * This function does nothing if the user specified REGIONS
                    106:  * directives via an ifile.
                    107:  *
                    108:  * Rule 1: All output sections defined as members of a GROUP
                    109:  *             will go into the same region.
                    110:  * Rule 2: The output sections .data and .bss will go into the same
                    111:  *             region.
                    112:  * Rule 3: All other output sections will go into a separate region
                    113:  *             by itself.
                    114:  */
                    115: 
                    116:        REGION  *rp,            /* working pointer              */
                    117:                *drp,           /* ptr to data/bss region       */
                    118:                *trp,           /* ptr to tv region             */
                    119:                *newregion();
                    120:        OUTSECT *osp,           /* working pointer              */
                    121:                *dosp,          /* ptr to .data output section  */
                    122:                *bosp,          /* ptr to .bss output section   */
                    123:                *tosp;          /* ptr to .tv output section    */
                    124:        long    paddr,          /* phys addr for regions        */
                    125:                vaddr,          /* virtual address              */
                    126:                length;
                    127: 
                    128:        dosp = bosp = tosp = NULL;
                    129: 
                    130: /*
                    131:  * For each output section, build or amend the appropriate region
                    132:  *
                    133:  * The outsclst contains, at this point, entries which correspond to
                    134:  * output GROUPs and independent output sections
                    135:  */
                    136: 
                    137:        for( osp = ((OUTSECT *) outsclst.head); osp != NULL; osp = osp->osnext ) {
                    138:                if(equal(osp->oshdr.s_name,_DATA,8))
                    139:                        dosp = osp;
                    140:                else if(equal(osp->oshdr.s_name,_BSS,8))
                    141:                        bosp = osp;
                    142:                else if(equal(osp->oshdr.s_name,_TV,8))
                    143:                        tosp = osp;
                    144:                else {
                    145:                        /*
                    146:                         * Since every output section is going to be a
                    147:                         * region, we have to align their virtual zeroes
                    148:                         * to a 16-byte boundry.
                    149:                         * 
                    150:                         * That is done by changing the virtual address.
                    151:                         *
                    152:                         * If the resultant section is too big, it is an
                    153:                         * error.
                    154:                         */
                    155:                        paddr = osp->oshdr.s_paddr;
                    156:                        vaddr = paddr & 0xfL;
                    157:                        length = osp->oshdr.s_size;
                    158: 
                    159:                        if( length + vaddr <= REGSIZE ) {       /* size is ok */
                    160:                                rp = newregion(osp->oshdr.s_name);
                    161:                                rp->rgorig = paddr;
                    162:                                rp->rgvaddr = vaddr;
                    163:                                rp->rglength = length;
                    164:                                rp->rgaddrhd = rp->rgaddrtl = findsanode(osp);
                    165:                                if (rp->rgaddrhd)
                    166:                                        rp->rgaddrhd->adregp = rp;
                    167:                                listadd(l_REG, &reglist, rp);
                    168:                                }
                    169:                        else
                    170:                                lderror(1,0,NULL, "default allocation failed: %.8s is too large",
                    171:                                        osp->oshdr.s_name);
                    172:                        }
                    173:                }
                    174: 
                    175: /*
                    176:  * Assign physical address to .data/.bss and .tv regions
                    177:  */
                    178: 
                    179:        if(  dosp  ||   bosp ) {
                    180:                /*
                    181:                 * We don't know which of the two exist, so we
                    182:                 * set both equal if one is NULL.  Then we arrange
                    183:                 * it to look like .data has the lower address for
                    184:                 * simplicity.  We do NOT change the actual addresses.
                    185:                 */
                    186:                if( ! dosp  )
                    187:                        dosp = bosp;
                    188:                else if( ! bosp )
                    189:                        bosp = dosp;
                    190: 
                    191:                paddr = dosp->oshdr.s_paddr;
                    192: 
                    193:                if( bosp->oshdr.s_paddr < paddr ) {
                    194:                        paddr = bosp->oshdr.s_paddr;
                    195:                        osp = bosp;
                    196:                        bosp = dosp;
                    197:                        dosp = osp;
                    198:                        }
                    199: 
                    200:                length = bosp->oshdr.s_size + (bosp->oshdr.s_paddr - paddr);
                    201: 
                    202:                vaddr = paddr & 0xfL;
                    203:                if( (length + vaddr) <= REGSIZE ) {
                    204:                        drp = newregion(".rdata");
                    205:                        drp->rgorig = paddr;
                    206:                        drp->rgvaddr = vaddr;
                    207:                        drp->rglength = length;
                    208:                        drp->rgaddrhd = findsanode(dosp);
                    209:                        drp->rgaddrtl = findsanode(bosp);
                    210:                        if (drp->rgaddrhd)
                    211:                                drp->rgaddrhd->adregp = drp;
                    212:                        if (drp->rgaddrtl)
                    213:                                drp->rgaddrtl->adregp = drp;
                    214:                        listadd(l_REG, &reglist, drp);
                    215:                        }
                    216:                else {
                    217:                        if( bosp != dosp )
                    218:                                lderror(1,0,NULL,
                    219:                                        "default allocation didn't put %.8s and %.8s into same region",
                    220:                                        _DATA, _BSS);
                    221:                        else
                    222:                                lderror(1,0,NULL, "default allocation failed for %.8s",
                    223:                                        dosp->oshdr.s_name);
                    224:                        }
                    225:                }
                    226: 
                    227:        if( tosp != NULL ) {
                    228:                paddr = tosp->oshdr.s_paddr;
                    229:                if( (paddr & 0xfL) != 0L ) {
                    230:                        lderror(2,0,NULL, "internal error: %.8s not aligned",
                    231:                                _TV);
                    232:                        return;
                    233:                        }
                    234: 
                    235:                trp = newregion(".rtv");
                    236:                trp->rgorig = paddr;
                    237:                trp->rgvaddr = 0L;
                    238:                trp->rglength = tosp->oshdr.s_size;
                    239:                trp->rgaddrhd = trp->rgaddrtl = findsanode(tosp);
                    240:                if (trp->rgaddrhd)
                    241:                        trp->rgaddrhd->adregp = trp;
                    242:                listadd(l_REG, &reglist, trp);
                    243:                }
                    244:        else if( aflag )
                    245:                lderror(1,0,NULL, "internal error: %.8s not built",
                    246:                        _TV);
                    247: }
                    248: /*eject*/
                    249: REGION *
                    250: newregion(name)
                    251: char *name;
                    252: {
                    253:        register REGION *rp;
                    254: 
                    255:        rp = (REGION *) myalloc(sizeof(REGION));
                    256: 
                    257:        copy(rp->rgname, name, 8);
                    258: 
                    259:        return(rp);
                    260: }
                    261: 
                    262: add_owner(osp,rp)
                    263: OUTSECT *osp;
                    264: REGION *rp;
                    265: {
                    266:        register ACTITEM *aip;
                    267: 
                    268:        aip = (ACTITEM *) myalloc(sizeof(ACTITEM));
                    269: 
                    270:        aip->dfownr.aitype = AIDFOWNR;
                    271:        aip->dfownr.aioutsec = osp;
                    272:        copy(aip->dfownr.ainamown,rp->rgname,8);
                    273: 
                    274:        listadd(l_AI,&ownlist,aip);
                    275: }
                    276: 
                    277: /*
                    278:  *     The following function [ alc_iand() ] is
                    279:  *     executed only if IANDD && USEREGIONS
                    280:  */
                    281: 
                    282: #if IANDD && USEREGIONS
                    283: 
                    284: alc_iandd()
                    285: {
                    286: 
                    287: /*
                    288:  * Perform the function specified by the "-i" flag:
                    289:  *     generate two regions, one for text (I space) and one for
                    290:  *     data (D space)
                    291:  */
                    292: 
                    293:        REGION  *trp, *drp;
                    294:        ANODE   *ap1, *ap2;
                    295:        MEMTYPE *mp;
                    296:        OUTSECT *sp;
                    297:        short   reg_count, squishable;
                    298:        long    newsize;
                    299: 
                    300: /*
                    301:  * Make sure that there are only two regions
                    302:  */
                    303: 
                    304:        reg_count = 0;
                    305:        for( trp = (REGION *) reglist.head; trp != NULL; trp = trp->rgnext )
                    306:                reg_count++;
                    307:        if(reg_count != 2) {
                    308:                lderror(0,0,NULL, "i flag ignored: %d regions specified",
                    309:                        reg_count);
                    310:                return;
                    311:                }
                    312: 
                    313: /*
                    314:  * Make sure that no memory attribute of T was specified
                    315:  */
                    316: 
                    317:        for( mp = (MEMTYPE *) memlist.head; mp != NULL; mp = mp->mtnext ) {
                    318:                if(mp->mtattr == 4) {
                    319:                        lderror(0,0,NULL, "i flag ignored: text memory specified");
                    320:                        return;
                    321:                        }
                    322:                }
                    323: 
                    324: /*
                    325:  * Allocate all input .text sections into the first region.
                    326:  */
                    327: 
                    328:        trp = (REGION *) reglist.head;
                    329:        for( sp = (OUTSECT *) outsclst.head; sp != NULL; sp = sp->osnext ) {
                    330:                if( equal(sp->oshdr.s_name,_TEXT,8)  &&
                    331:                    (sp->oshdr.s_paddr == -1L) ) {
                    332:                        if(can_alloc(trp->rgaddrhd,trp->rgaddrtl,sp,
                    333:                                        &ap1,&ap2))
                    334:                                do_alloc(ap1,ap2,sp);
                    335:                        else
                    336:                                lderror(1,0,NULL, ".text section won't fit in text region");
                    337:                        }
                    338:                }
                    339: 
                    340: /*
                    341:  * If necessary, see about moving the data regions down to the 
                    342:  * even 4-byte boundry immediately following the end of the
                    343:  * allocated text
                    344:  */
                    345: 
                    346:        drp = trp->rgnext;
                    347:        squishable = 1;
                    348:        if( (drp->rgaddrhd != drp->rgaddrtl)  ||
                    349:             (drp->rgaddrhd->adtype != ADAVAIL) )
                    350:                squishable = 0;
                    351: 
                    352:        if(squishable) {
                    353:                ap2 = drp->rgaddrhd;
                    354:                newsize = 0L;
                    355:                while( (ap2->adprev->adtype == ADAVAIL)  &&
                    356:                      (ap2->adprev->adpaddr + ap2->adprev->adsize == ap2->adpaddr)  &&
                    357:                      (ap2->adprev->adsize != 0) ) {
                    358:                        ap2 = ap2->adprev;
                    359:                        newsize += ap2->adsize;
                    360:                        ap2->adregp = NULL;
                    361:                        }
                    362:                if(newsize > 0L) {
                    363:                        trp->rgaddrtl = ap2->adprev;
                    364:                        trp->rglength -= newsize;
                    365:                        drp->rgaddrhd->adpaddr = ap2->adpaddr;
                    366:                        ap2->adprev->adnext = drp->rgaddrhd;
                    367:                        drp->rgaddrhd->adprev = ap2->adprev;
                    368:                        ap2 = drp->rgaddrhd;
                    369:                        /*
                    370:                         * If the first anode is aligned on a
                    371:                         * 16-byte boundary, the region will
                    372:                         * have a vaddr of zero.  We can't let
                    373:                         * this happen; zero is NULL in C.
                    374:                         *
                    375:                         * Force virtual address to non-zero.
                    376:                         */
                    377:                        if( (ap2->adpaddr & 0xf) == 0 ) {
                    378:                                ap2->adpaddr += 2;
                    379:                                ap2->adsize -= 2;
                    380:                                drp->rglength -= 2;
                    381:                                }
                    382:                        else
                    383:                                if( (ap2->adpaddr & 1) != 0 ) {
                    384:                                        ++ap2->adpaddr;
                    385:                                        --ap2->adsize;
                    386:                                        --drp->rglength;
                    387:                                        }
                    388: 
                    389:                        drp->rgorig = ap2->adpaddr;
                    390:                        drp->rgvaddr = ap2->adpaddr & 0xf;
                    391:                        if( drp->rgvaddr + drp->rglength > REGSIZE )
                    392:                                drp->rglength = REGSIZE - drp->rgvaddr;
                    393:                        }
                    394:                }
                    395: 
                    396: /*
                    397:  * Now allocate .data and .bss into RDATA.
                    398:  */
                    399: 
                    400:        for( sp = (OUTSECT *) outsclst.head; sp != NULL; sp = sp->osnext ) {
                    401:                if( (equal(sp->oshdr.s_name,_DATA,8) || equal(sp->oshdr.s_name,_BSS,8))
                    402:                        && (sp->oshdr.s_paddr == -1L) )
                    403:                        if( can_alloc(drp->rgaddrhd, drp->rgaddrtl, sp, &ap1, &ap2) )
                    404:                                do_alloc(ap1, ap2, sp);
                    405:                        else
                    406:                                lderror(1,0,NULL, "%.8s section won't fit in data region",
                    407:                                        sp->oshdr.s_name);
                    408:                }
                    409: }
                    410: #endif

unix.superglobalmegacorp.com

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