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 * Place pointer in header area list
144 fprintf(stderr, "No header defined\n");
149 for (i=0; i < narea ;++i) {
150 if (halp[i] == NULL) {
155 fprintf(stderr, "Header area list overflow\n");
159 /*)Function VOID lkparea(id)
161 * char * id pointer to the area name string
163 * The function lkparea() searches the linked area structures
164 * for a name match. If the name is not found then an area
165 * structure is created. An areax structure is created and
166 * appended to the areax structures linked to the area structure.
167 * The associated base area and head structure pointers are
168 * loaded into the areax structure.
171 * area * tap pointer to an area structure
172 * areax * taxp pointer to an areax structure
175 * area *ap Pointer to the current
177 * area *areap The pointer to the first
178 * area structure of a linked list
179 * areax *axp Pointer to the current
183 * VOID * new() lksym()
184 * char * strcpy() c_library
185 * int symeq() lksym.c
188 * Area and/or areax structures are created.
189 * Failure to allocate space for created structures
190 * will terminate the linker.
197 register struct area *tap;
198 register struct areax *taxp;
201 axp = (struct areax *) new (sizeof(struct areax));
203 if (symeq(id, ap->a_id)) {
214 ap = (struct area *) new (sizeof(struct area));
226 strncpy(ap->a_id, id, NCPS);
230 /*)Function VOID lnkarea()
232 * The function lnkarea() resolves all area addresses.
233 * The function evaluates each area structure (and all
234 * the associated areax structures) in sequence. The
235 * linking process supports four (4) possible area types:
237 * ABS/OVR - All sections (each individual areax
238 * section) starts at the identical base
239 * area address overlaying all other
240 * areax sections for this area. The
241 * size of the area is largest of the area
244 * ABS/CON - All sections (each individual areax
245 * section) are concatenated with the
246 * first section starting at the base
247 * area address. The size of the area
248 * is the sum of the section sizes.
250 * NOTE: Multiple absolute (ABS) areas are
251 * never concatenated with each other,
252 * thus absolute area A and absolute area
253 * B will overlay each other if they begin
254 * at the same location (the default is
255 * always address 0 for absolute areas).
257 * REL/OVR - All sections (each individual areax
258 * section) starts at the identical base
259 * area address overlaying all other
260 * areax sections for this area. The
261 * size of the area is largest of the area
264 * REL/CON - All sections (each individual areax
265 * section) are concatenated with the
266 * first section starting at the base
267 * area address. The size of the area
268 * is the sum of the section sizes.
270 * NOTE: Relocatable (REL) areas ae always concatenated
271 * with each other, thus relocatable area B
272 * (defined after area A) will follow
273 * relocatable area A independent of the
274 * starting address of area A. Within a
275 * specific area each areax section may be
276 * overlayed or concatenated with other
280 * If a base address for an area is specified then the
281 * area will start at that address. Any relocatable
282 * areas defined subsequently will be concatenated to the
283 * previous relocatable area if it does not have a base
286 * The names s_<areaname> and l_<areaname> are created to
287 * define the starting address and length of each area.
290 * Addr_T rloc ;current relocation address
291 * char temp[] ;temporary string
292 * struct symbol *sp ;symbol structure
295 * area *ap Pointer to the current
297 * area *areap The pointer to the first
298 * area structure of a linked list
301 * int fprintf() c_library
302 * VOID lnksect() lkarea.c
303 * symbol *lkpsym() lksysm.c
304 * char * strncpy() c_library
305 * int symeq() lksysm.c
308 * All area and areax addresses and sizes are
309 * determined and saved in their respective
314 * Resolve all area addresses.
323 /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
327 rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
330 if (ap->a_flag&A_ABS) {
336 /* Determine memory space */
338 if (ap->a_flag & A_CODE) {
341 if (ap->a_flag & A_XDATA) {
344 if (ap->a_flag & A_BIT) {
348 * Relocatable sections
350 if (ap->a_type == 0) { /* JLH */
351 ap->a_addr = rloc[ locIndex ];
355 rloc[ locIndex ] = ap->a_addr + ap->a_size;
359 * Create symbols called:
360 * s_<areaname> the start address of the area
361 * l_<areaname> the length of the area
364 if (! symeq(ap->a_id, _abs_)) {
365 strncpy(temp+2,ap->a_id,NCPS-2);
369 sp = lkpsym(temp, 1);
370 sp->s_addr = ap->a_addr ;
371 /* sp->s_axp = ap->a_axp; JLH: was NULL; */
375 sp = lkpsym(temp, 1);
376 sp->s_addr = ap->a_size;
382 /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
383 to compute the byte size of BSEG_BYTES: */
384 if (!strcmp(ap->a_id, "BSEG")) {
385 ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
387 else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
388 else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
389 else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
390 else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
391 else if (!strcmp(ap->a_id, "BSEG_BYTES"))
396 /*If upper register banks are not used roll back the rellocation counter*/
397 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
408 /*)Function VOID lnksect()
410 * area * tap pointer to an area structure
412 * The function lnksect() is the function called by
413 * lnkarea() to resolve the areax addresses. Refer
414 * to the function lnkarea() for more detail. Pageing
415 * boundary and length errors will be reported by this
419 * Addr_T size size of area
420 * Addr_T addr address of area
421 * areax * taxp pointer to an areax structure
424 * int lkerr error flag
430 * All area and areax addresses and sizes area determined
431 * and linked into the structures.
436 register struct area *tap;
438 register Addr_T size, addr;
439 register struct areax *taxp;
443 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
445 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
449 if (tap->a_flag&A_OVR) {
455 if (taxp->a_size > size)
461 * Concatenated sections
465 addr += taxp->a_size;
466 size += taxp->a_size;
471 if ((tap->a_flag&A_PAG) && (size > 256)) {
473 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
478 void lnksect2 (struct area *tap, int rloc);
481 /*Modified version of the functions for packing variables in internal data memory*/
484 Addr_T rloc[4]={0, 0, 0, 0};
489 struct area *dseg_ap=NULL;
490 struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
492 for(j=0; j<256; j++) idatamap[j]=' ';
497 /* Determine memory space */
498 if (ap->a_flag & A_CODE) locIndex = 1;
499 else if (ap->a_flag & A_XDATA) locIndex = 2;
500 else if (ap->a_flag & A_BIT) locIndex = 3;
503 if (ap->a_flag&A_ABS) /* Absolute sections */
505 lnksect2(ap, locIndex);
507 else /* Relocatable sections */
511 ap->a_addr=rloc[locIndex];
515 lnksect2(ap, locIndex);
516 rloc[locIndex] = ap->a_addr + ap->a_size;
520 * Create symbols called:
521 * s_<areaname> the start address of the area
522 * l_<areaname> the length of the area
525 if (! symeq(ap->a_id, _abs_))
527 strncpy(temp+2,ap->a_id,NCPS-2);
531 sp = lkpsym(temp, 1);
532 sp->s_addr = ap->a_addr ;
534 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
537 sp = lkpsym(temp, 1);
538 sp->s_addr = ap->a_size;
541 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
544 /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
545 to compute the byte size of BSEG_BYTES: */
546 if (!strcmp(ap->a_id, "BSEG"))
548 ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
550 else if (!strcmp(ap->a_id, "DSEG"))
552 dseg_ap=ap; /*Need it later to set its correct size*/
557 /*Compute the size of DSEG*/
562 for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
564 if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
565 if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
568 /*Print the memory map*/
569 fprintf(stderr, "Internal RAM layout:\n"
570 " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
573 if(j%16==0) fprintf(stderr, "\n0x%02x:|", j);
574 fprintf(stderr, "%c|", idatamap[j]);
576 fprintf(stderr, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
580 void lnksect2 (struct area *tap, int rloc)
582 register Addr_T size, addr;
583 register struct areax *taxp;
585 char fchar, dchar='a';
586 char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
587 " in internal RAM for area %s.\n";
591 /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
592 if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
594 if((iram_size<=0)||(iram_size>0x100))
606 if ((tap->a_flag&A_PAG) && (addr & 0xFF))
609 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
614 /*Use a letter to identify each area in the internal RAM layout map*/
617 /**/ if(!strcmp(tap->a_id, "DSEG"))
618 fchar='D'; /*It will be converted to letters 'a' to 'z' latter for each areax*/
619 else if(!strcmp(tap->a_id, "ISEG"))
621 else if(!strcmp(tap->a_id, "SSEG"))
623 else if(!strcmp(tap->a_id, "OSEG"))
625 else if(!strcmp(tap->a_id, "REG_BANK_0"))
627 else if(!strcmp(tap->a_id, "REG_BANK_1"))
629 else if(!strcmp(tap->a_id, "REG_BANK_2"))
631 else if(!strcmp(tap->a_id, "REG_BANK_3"))
633 else if(!strcmp(tap->a_id, "BSEG_BYTES"))
643 if (tap->a_flag&A_OVR) /* Overlayed sections */
647 if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
652 for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
655 else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
657 /*Find the size of the space currently used for this areax overlay*/
658 for(j=0, size=0; j<ramlimit; j++)
659 if(idatamap[j]==fchar) size++;
661 if( (fchar=='S') && (stacksize==0) )
663 /*Search for the largest space available and use it for stack*/
664 for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
668 if((++k)>(int)taxp->a_size) taxp->a_size=k;
675 stacksize=taxp->a_size;
678 /*If more space required, release the previously allocated areax in
679 internal RAM and search for a bigger one*/
680 if((int)taxp->a_size>size)
682 size=(int)taxp->a_size;
684 for(j=0; j<ramlimit; j++)
685 if(idatamap[j]==fchar) idatamap[j]=' ';
687 /*Search for a space large enough in data memory for this overlay areax*/
688 for(j=0, k=0; j<ramlimit; j++)
694 if(k==(int)taxp->a_size) break;
697 if(k==(int)taxp->a_size)
699 taxp->a_addr = j-k+1;
700 if(addr<(unsigned int)ramlimit)
702 for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
707 /*Mark the memory used for overlay*/
708 if(k==(int)taxp->a_size)
710 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
713 /*Set the new size of the data memory area*/
716 else /*Couldn't find a chunk big enough: report the problem.*/
718 tap->a_unaloc=taxp->a_size;
719 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
724 for(j=0; j<ramlimit; j++)
726 if (idatamap[j]==fchar)
735 else /*Overlay areas not in internal ram*/
738 if (taxp->a_size > size) size = taxp->a_size;
743 else /* Concatenated sections */
747 if( (fchar=='D') || (fchar=='I') )
751 /*Search for a space large enough in internal RAM for this areax*/
752 for(j=0, k=0; j<ramlimit; j++)
758 if(k==(int)taxp->a_size) break;
761 if(k==(int)taxp->a_size)
763 taxp->a_addr = j-k+1;
764 if(addr<(unsigned int)ramlimit)
766 for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
771 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
772 idatamap[j]=(fchar=='D')?dchar:fchar;
773 if((taxp->a_size>0)&&(fchar=='D'))dchar++;
774 if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
776 else /*We are in trouble, there is not enough memory for an areax chunk*/
779 addr += taxp->a_size;
780 size += taxp->a_size;
781 tap->a_unaloc+=taxp->a_size;
782 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
792 for(j=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_addr+taxp->a_size)); j++)
797 addr += taxp->a_size;
798 size += taxp->a_size;
801 else /*For concatenated BIT, CODE, and XRAM areax's*/
804 addr += taxp->a_size;
805 size += taxp->a_size;
812 if ((tap->a_flag&A_PAG) && (size > 256))
815 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);