Annotation of researchv9/jerq/sgs/ld/regions.c, revision 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.