|
|
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.