|
|
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, ®list, 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, ®list, 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, ®list, 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.