4 * (C) Copyright 1989-1995
12 * - change lkparea to use a_type == 0 as "virgin area" flag
13 * 02-Apr-98 JLH: add code to link 8051 data spaces
22 * The module lkarea.c contains the functions which
23 * create and link together all area definitions read
24 * from the .rel file(s).
26 * lkarea.c contains the following functions:
32 * lkarea.c contains no global variables.
35 /*)Function VOID newarea()
37 * The function newarea() creates and/or modifies area
38 * and areax structures for each A directive read from
39 * the .rel file(s). The function lkparea() is called
40 * to find tha area structure associated with this name.
41 * If the area does not yet exist then a new area
42 * structure is created and linked to any existing
43 * linked area structures. The area flags are copied
44 * into the area flag variable. For each occurence of
45 * an A directive an areax structure is created and
46 * linked to the areax structures associated with this
47 * area. The size of this area section is placed into
48 * the areax structure. The flag value for all subsequent
49 * area definitions for the same area are compared and
50 * flagged as an error if they are not identical.
51 * The areax structure created for every occurence of
52 * an A directive is loaded with a pointer to the base
53 * area structure and a pointer to the associated
54 * head structure. And finally, a pointer to this
55 * areax structure is loaded into the list of areax
56 * structures in the head structure. Refer to lkdata.c
57 * for details of the structures and their linkage.
60 * areax **halp pointer to an array of pointers
61 * int i counter, loop variable, value
63 * int narea number of areas in this head structure
64 * areax * taxp pointer to an areax structure
68 * area *ap Pointer to the current
70 * areax *axp Pointer to the current
72 * head *hp Pointer to the current
74 * int lkerr error flag
77 * Addr_T eval() lkeval.c
78 * VOID exit() c_library
79 * int fprintf() c_library
80 * VOID getid() lklex.c
81 * VOID lkparea() lkarea.c
85 * The area and areax structures are created and
86 * linked with the appropriate head structures.
87 * Failure to allocate area or areax structure
88 * space will terminate the linker. Other internal
89 * errors most likely caused by corrupted .rel
90 * files will also terminate the linker.
94 * Create an area entry.
96 * A xxxxxx size nnnn flags mm
99 * | `------------- axp->a_size
100 * `------------------------- ap->a_id
106 register int i, narea;
120 axp->a_size = eval();
127 while (taxp->a_axp) {
135 /* if (i && (ap->a_flag != i)) { */
136 /* fprintf(stderr, "Conflicting flags in area %8s\n", id); */
141 * Evaluate area address
144 axp->a_addr = eval();
146 * Place pointer in header area list
149 fprintf(stderr, "No header defined\n");
154 for (i=0; i < narea ;++i) {
155 if (halp[i] == NULL) {
160 fprintf(stderr, "Header area list overflow\n");
164 /*)Function VOID lkparea(id)
166 * char * id pointer to the area name string
168 * The function lkparea() searches the linked area structures
169 * for a name match. If the name is not found then an area
170 * structure is created. An areax structure is created and
171 * appended to the areax structures linked to the area structure.
172 * The associated base area and head structure pointers are
173 * loaded into the areax structure.
176 * area * tap pointer to an area structure
177 * areax * taxp pointer to an areax structure
180 * area *ap Pointer to the current
182 * area *areap The pointer to the first
183 * area structure of a linked list
184 * areax *axp Pointer to the current
188 * VOID * new() lksym()
189 * char * strcpy() c_library
190 * int symeq() lksym.c
193 * Area and/or areax structures are created.
194 * Failure to allocate space for created structures
195 * will terminate the linker.
201 register struct area *tap;
202 register struct areax *taxp;
205 axp = (struct areax *) new (sizeof(struct areax));
207 if (symeq(id, ap->a_id)) {
218 ap = (struct area *) new (sizeof(struct area));
230 strncpy(ap->a_id, id, NCPS);
234 /*)Function VOID lnkarea()
236 * The function lnkarea() resolves all area addresses.
237 * The function evaluates each area structure (and all
238 * the associated areax structures) in sequence. The
239 * linking process supports four (4) possible area types:
241 * ABS/OVR - All sections (each individual areax
242 * section) starts at the identical base
243 * area address overlaying all other
244 * areax sections for this area. The
245 * size of the area is largest of the area
248 * ABS/CON - All sections (each individual areax
249 * section) are concatenated with the
250 * first section starting at the base
251 * area address. The size of the area
252 * is the sum of the section sizes.
254 * NOTE: Multiple absolute (ABS) areas are
255 * never concatenated with each other,
256 * thus absolute area A and absolute area
257 * B will overlay each other if they begin
258 * at the same location (the default is
259 * always address 0 for absolute areas).
261 * REL/OVR - All sections (each individual areax
262 * section) starts at the identical base
263 * area address overlaying all other
264 * areax sections for this area. The
265 * size of the area is largest of the area
268 * REL/CON - All sections (each individual areax
269 * section) are concatenated with the
270 * first section starting at the base
271 * area address. The size of the area
272 * is the sum of the section sizes.
274 * NOTE: Relocatable (REL) areas ae always concatenated
275 * with each other, thus relocatable area B
276 * (defined after area A) will follow
277 * relocatable area A independent of the
278 * starting address of area A. Within a
279 * specific area each areax section may be
280 * overlayed or concatenated with other
284 * If a base address for an area is specified then the
285 * area will start at that address. Any relocatable
286 * areas defined subsequently will be concatenated to the
287 * previous relocatable area if it does not have a base
290 * The names s_<areaname> and l_<areaname> are created to
291 * define the starting address and length of each area.
294 * Addr_T rloc ;current relocation address
295 * char temp[] ;temporary string
296 * struct symbol *sp ;symbol structure
299 * area *ap Pointer to the current
301 * area *areap The pointer to the first
302 * area structure of a linked list
305 * int fprintf() c_library
306 * VOID lnksect() lkarea.c
307 * symbol *lkpsym() lksysm.c
308 * char * strncpy() c_library
309 * int symeq() lksysm.c
312 * All area and areax addresses and sizes are
313 * determined and saved in their respective
317 unsigned long codemap[2048];
319 * Resolve all area addresses.
324 Addr_T rloc[4] = {0, 0, 0, 0};
329 /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
332 struct area *abs_ap = NULL;
333 struct area *gs0_ap = NULL;
335 memset(codemap, 0, sizeof(codemap));
337 /* first sort all absolute areas to the front */
339 /* no need to check first area, it's in front anyway */
340 while (ap && ap->a_ap)
342 if (ap->a_ap->a_flag & A_ABS)
343 {/* next area is absolute, move it to front,
344 reversed sequence is no problem for absolutes */
346 ap->a_ap = abs_ap->a_ap;
347 abs_ap->a_ap = areap;
353 /* next accumulate all GSINITx/GSFINAL area sizes
354 into GSINIT so they stay together */
358 if (!strncmp(ap->a_id, "GS", 2))
365 ap->a_size += axp->a_size;
369 gs_size += ap->a_size;
370 if (!strcmp(ap->a_id, "GSINIT0"))
378 gs0_ap->a_size = gs_size;
382 if (ap->a_flag & A_ABS) {
388 /* Determine memory space */
391 if (ap->a_flag & A_CODE) {
394 if (ap->a_flag & A_XDATA) {
397 if (ap->a_flag & A_BIT) {
402 * Relocatable sections
404 if (ap->a_type == 0) { /* JLH */
405 if (ap->a_flag & A_NOLOAD) {
409 ap->a_addr = rloc[ locIndex ];
413 rloc[ locIndex ] = lnksect(ap);
417 * Create symbols called:
418 * s_<areaname> the start address of the area
419 * l_<areaname> the length of the area
422 if (! symeq(ap->a_id, _abs_)) {
423 strncpy(temp+2,ap->a_id,NCPS-2);
427 sp = lkpsym(temp, 1);
428 sp->s_addr = ap->a_addr ;
429 /* sp->s_axp = ap->a_axp; JLH: was NULL; */
433 sp = lkpsym(temp, 1);
434 sp->s_addr = ap->a_size;
440 /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
441 to compute the byte size of BSEG_BYTES: */
442 if (!strcmp(ap->a_id, "BSEG")) {
443 ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
445 else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
446 else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
447 else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
448 else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
449 else if (!strcmp(ap->a_id, "BSEG_BYTES"))
454 /*If upper register banks are not used roll back the relocation counter*/
455 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
467 Addr_T find_empty_space(Addr_T start, Addr_T size)
470 unsigned long mask, b;
476 j = (start + size) >> 5;
477 mask = -(1 << (start & 0x1F));
481 if (codemap[i] & mask)
484 for (b=0x80000000; b!=0; b>>=1, k--)
499 mask &= (1 << ((start + size) & 0x1F)) - 1;
500 if (codemap[i] & mask)
503 for (b=0x80000000; b!=0; b>>=1, k--)
508 start = (a & ~0x1F) + k;
517 Addr_T allocate_space(Addr_T start, Addr_T size, char* id)
523 j = (start + size) >> 5;
524 mask = -(1 << (start & 0x1F));
528 if (codemap[i] & mask)
530 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
532 codemap[i++] |= mask;
536 mask &= (1 << ((start + size) & 0x1F)) - 1;
537 if (codemap[i] & mask)
539 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
545 /*)Function VOID lnksect()
547 * area * tap pointer to an area structure
549 * The function lnksect() is the function called by
550 * lnkarea() to resolve the areax addresses. Refer
551 * to the function lnkarea() for more detail. Pageing
552 * boundary and length errors will be reported by this
556 * Addr_T size size of area
557 * Addr_T addr address of area
558 * areax * taxp pointer to an areax structure
561 * int lkerr error flag
567 * All area and areax addresses and sizes area determined
568 * and linked into the structures.
571 Addr_T lnksect(struct area *tap)
573 register Addr_T size, addr;
574 register struct areax *taxp;
579 /* MB: is this possible for hc08 ??? */
580 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
582 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
587 if (tap->a_flag&A_OVR) {
593 if (taxp->a_size > size)
597 } else if (tap->a_flag & A_ABS) {
602 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id);
603 taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
604 size += taxp->a_size;
609 * Concatenated sections
612 addr = find_empty_space(addr, tap->a_size);
615 //find next unused address now
618 addr = find_empty_space(addr, taxp->a_size);
619 allocate_space(addr, taxp->a_size, tap->a_id);
622 addr += taxp->a_size;
623 size += taxp->a_size;
629 /* MB: is this possible for hc08 ??? */
630 if ((tap->a_flag&A_PAG) && (size > 256)) {
632 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);