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 the 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));
206 axp->a_addr = -1; /* default: no address yet */
208 if (symeq(id, ap->a_id)) {
219 ap = (struct area *) new (sizeof(struct area));
231 strncpy(ap->a_id, id, NCPS);
235 /*)Function VOID lnkarea()
237 * The function lnkarea() resolves all area addresses.
238 * The function evaluates each area structure (and all
239 * the associated areax structures) in sequence. The
240 * linking process supports four (4) possible area types:
242 * ABS/OVR - All sections (each individual areax
243 * section) starts at the identical base
244 * area address overlaying all other
245 * areax sections for this area. The
246 * size of the area is largest of the area
249 * ABS/CON - All sections (each individual areax
250 * section) are concatenated with the
251 * first section starting at the base
252 * area address. The size of the area
253 * is the sum of the section sizes.
255 * NOTE: Multiple absolute (ABS) areas are
256 * never concatenated with each other,
257 * thus absolute area A and absolute area
258 * B will overlay each other if they begin
259 * at the same location (the default is
260 * always address 0 for absolute areas).
262 * REL/OVR - All sections (each individual areax
263 * section) starts at the identical base
264 * area address overlaying all other
265 * areax sections for this area. The
266 * size of the area is largest of the area
269 * REL/CON - All sections (each individual areax
270 * section) are concatenated with the
271 * first section starting at the base
272 * area address. The size of the area
273 * is the sum of the section sizes.
275 * NOTE: Relocatable (REL) areas are always concatenated
276 * with each other, thus relocatable area B
277 * (defined after area A) will follow
278 * relocatable area A independent of the
279 * starting address of area A. Within a
280 * specific area each areax section may be
281 * overlayed or concatenated with other
285 * If a base address for an area is specified then the
286 * area will start at that address. Any relocatable
287 * areas defined subsequently will be concatenated to the
288 * previous relocatable area if it does not have a base
291 * The names s_<areaname> and l_<areaname> are created to
292 * define the starting address and length of each area.
295 * Addr_T rloc ;current relocation address
296 * char temp[] ;temporary string
297 * struct symbol *sp ;symbol structure
300 * area *ap Pointer to the current
302 * area *areap The pointer to the first
303 * area structure of a linked list
306 * int fprintf() c_library
307 * VOID lnksect() lkarea.c
308 * symbol *lkpsym() lksym.c
309 * char * strncpy() c_library
310 * int symeq() lksym.c
313 * All area and areax addresses and sizes are
314 * determined and saved in their respective
318 VOID lnksect(register struct area *tap);
320 * Resolve all area addresses.
329 /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
333 rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
336 if (ap->a_flag&A_ABS) {
342 /* Determine memory space */
344 if (ap->a_flag & A_CODE) {
347 if (ap->a_flag & A_XDATA) {
350 if (ap->a_flag & A_BIT) {
354 * Relocatable sections
356 if (ap->a_type == 0) { /* JLH */
357 ap->a_addr = rloc[ locIndex ];
361 rloc[ locIndex ] = ap->a_addr + ap->a_size;
365 * Create symbols called:
366 * s_<areaname> the start address of the area
367 * l_<areaname> the length of the area
370 if (! symeq(ap->a_id, _abs_)) {
371 strncpy(temp+2,ap->a_id,NCPS-2);
375 sp = lkpsym(temp, 1);
376 sp->s_addr = ap->a_addr ;
377 /* sp->s_axp = ap->a_axp; JLH: was NULL; */
381 sp = lkpsym(temp, 1);
382 sp->s_addr = ap->a_size;
388 /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
389 to compute the byte size of BSEG_BYTES: */
390 if (!strcmp(ap->a_id, "BSEG")) {
391 ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
393 else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
394 else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
395 else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
396 else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
397 else if (!strcmp(ap->a_id, "BSEG_BYTES"))
402 /*If upper register banks are not used roll back the relocation counter*/
403 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
414 /*)Function VOID lnksect()
416 * area * tap pointer to an area structure
418 * The function lnksect() is the function called by
419 * lnkarea() to resolve the areax addresses. Refer
420 * to the function lnkarea() for more detail. Pageing
421 * boundary and length errors will be reported by this
425 * Addr_T size size of area
426 * Addr_T addr address of area
427 * areax * taxp pointer to an areax structure
430 * int lkerr error flag
436 * All area and areax addresses and sizes area determined
437 * and linked into the structures.
441 lnksect(register struct area *tap)
443 register Addr_T size, addr;
444 register struct areax *taxp;
449 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
451 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
456 if (tap->a_flag&A_OVR) {
462 if (taxp->a_size > size)
468 * Concatenated sections
472 addr += taxp->a_size;
473 size += taxp->a_size;
478 if ((tap->a_flag&A_PAG) && (size > 256)) {
480 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
483 if ((tap->a_flag&A_PAG) && (tap->a_size) &&
484 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
487 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
492 Addr_T lnksect2 (struct area *tap, int locIndex);
494 unsigned long codemap[524288];
495 unsigned long xdatamap[131072];
496 struct area *dseg_ap = NULL;
497 Addr_T dram_start = 0;
498 Addr_T iram_start = 0;
500 /*Modified version of the functions for packing variables in internal data memory*/
503 Addr_T rloc[4]={0, 0, 0, 0};
509 struct area *bseg_ap = NULL;
510 struct area *abs_ap = NULL;
511 struct area *gs0_ap = NULL;
512 struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
514 for(j=0; j<256; j++) idatamap[j]=' ';
515 memset(codemap, 0, sizeof(codemap));
516 memset(xdatamap, 0, sizeof(xdatamap));
518 /* first sort all absolute areas to the front */
520 /* no need to check first area, it's in front anyway */
521 while (ap && ap->a_ap)
523 if (ap->a_ap->a_flag & A_ABS)
524 {/* next area is absolute, move it to front,
525 reversed sequence is no problem for absolutes */
527 ap->a_ap = abs_ap->a_ap;
528 abs_ap->a_ap = areap;
537 /* next accumulate all GSINITx/GSFINAL area sizes
538 into GSINIT so they stay together */
543 if (ap->a_flag & A_ABS)
545 abs_ap = ap; /* Remember the last abs area */
547 if (!strncmp(ap->a_id, "GS", 2))
554 ap->a_size += axp->a_size;
558 gs_size += ap->a_size;
559 if (!strcmp(ap->a_id, "GSINIT0"))
564 /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
565 to compute the byte size of BSEG_BYTES: */
566 else if (!strcmp(ap->a_id, "BSEG"))
568 bseg_ap = ap->a_ap; //BSEG_BYTES
569 for (axp=ap->a_axp; axp; axp=axp->a_axp)
570 ap->a_size += axp->a_size;
571 bseg_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
572 ap->a_ap = bseg_ap->a_ap; //removed BSEG_BYTES from list
573 bseg_ap->a_ap = abs_ap->a_ap;
574 abs_ap->a_ap = bseg_ap; //inserted BSEG_BYTES after abs
577 else if (!strcmp(ap->a_id, "DSEG"))
579 dseg_ap = ap; /*Need it later*/
580 dram_start = ap->a_addr;
582 else if (!strcmp(ap->a_id, "ISEG"))
584 iram_start = ap->a_addr;
589 gs0_ap->a_size = gs_size;
594 /* Determine memory space */
595 if (ap->a_flag & A_CODE) locIndex = 1;
596 else if (ap->a_flag & A_XDATA) locIndex = 2;
597 else if (ap->a_flag & A_BIT) locIndex = 3;
600 if (ap->a_flag & A_ABS) /* Absolute sections */
602 lnksect2(ap, locIndex);
604 else /* Relocatable sections */
608 ap->a_addr = rloc[locIndex];
612 rloc[locIndex] = lnksect2(ap, locIndex);
615 if (!strcmp(ap->a_id, "BSEG_BYTES"))
617 bseg_ap->a_addr = (ap->a_axp->a_addr - 0x20) * 8; /*Bytes to bits*/
620 * Create symbols called:
621 * s_<areaname> the start address of the area
622 * l_<areaname> the length of the area
625 if (! symeq(ap->a_id, _abs_))
627 strncpy(temp+2,ap->a_id,NCPS-2);
631 sp = lkpsym(temp, 1);
632 sp->s_addr = ap->a_addr;
634 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
637 sp = lkpsym(temp, 1);
638 sp->s_addr = ap->a_size;
641 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
647 /*Compute the size of DSEG*/
652 for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
654 if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
655 if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
659 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
662 unsigned long mask, b;
668 j = (start + size) >> 5;
669 mask = -(1 << (start & 0x1F));
676 for (b=0x80000000; b!=0; b>>=1, k--)
691 mask &= (1 << ((start + size) & 0x1F)) - 1;
695 for (b=0x80000000; b!=0; b>>=1, k--)
700 start = (a & ~0x1F) + k;
709 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
715 j = (start + size) >> 5;
716 mask = -(1 << (start & 0x1F));
722 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
728 mask &= (1 << ((start + size) & 0x1F)) - 1;
731 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
737 Addr_T lnksect2 (struct area *tap, int locIndex)
739 register Addr_T size, addr;
740 register struct areax *taxp;
741 int j, k, ramlimit, ramstart;
742 char fchar=' ', dchar='a';
743 char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
744 " in internal RAM for area %s.\n";
748 /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
749 if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
751 ramstart = iram_start;
753 if ((iram_size <= 0) || (ramstart + iram_size > 0x100))
756 ramlimit = ramstart + iram_size;
760 ramstart = dram_start;
762 if ((iram_size <= 0) || (ramstart + iram_size > 0x80))
765 ramlimit = ramstart + iram_size;
771 if ((tap->a_flag&A_PAG) && (addr & 0xFF))
774 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
780 /*Use a letter to identify each area in the internal RAM layout map*/
783 /**/ if(!strcmp(tap->a_id, "DSEG"))
784 fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
785 else if(!strcmp(tap->a_id, "ISEG"))
787 else if(!strcmp(tap->a_id, "SSEG"))
789 else if(!strcmp(tap->a_id, "OSEG"))
791 else if(!strcmp(tap->a_id, "REG_BANK_0"))
793 else if(!strcmp(tap->a_id, "REG_BANK_1"))
795 else if(!strcmp(tap->a_id, "REG_BANK_2"))
797 else if(!strcmp(tap->a_id, "REG_BANK_3"))
799 else if(!strcmp(tap->a_id, "BSEG_BYTES"))
801 else if(!strcmp(tap->a_id, "BIT_BANK"))
806 else if (locIndex == 1)
808 /**/ if(!strcmp(tap->a_id, "GSINIT"))
811 else if (locIndex == 2)
813 /**/ if(!strcmp(tap->a_id, "XSTK"))
817 if (tap->a_flag&A_OVR) /* Overlayed sections */
821 if(taxp->a_size == 0)
827 if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
832 for(j=addr; (j<(int)(addr+size)) && (j<ramlimit); j++)
835 else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
837 /*Find the size of the space currently used for this areax overlay*/
838 for(j=ramstart, size=0; j<ramlimit; j++)
839 if(idatamap[j]==fchar) size++;
841 if( (fchar=='S') && (stacksize==0) )
843 /*Search for the largest space available and use it for stack*/
844 for(j=ramstart, k=0, taxp->a_size=0; j<ramlimit; j++)
848 if((++k)>(int)taxp->a_size)
856 stacksize=taxp->a_size;
859 /*If more space required, release the previously allocated areax in
860 internal RAM and search for a bigger one*/
861 if((int)taxp->a_size>size)
863 size=(int)taxp->a_size;
865 for(j=ramstart; j<ramlimit; j++)
866 if(idatamap[j]==fchar) idatamap[j]=' ';
868 /*Search for a space large enough in data memory for this overlay areax*/
869 for(j=ramstart, k=0; j<ramlimit; j++)
875 if(k==(int)taxp->a_size)
879 /*Mark the memory used for overlay*/
880 if(k==(int)taxp->a_size)
883 for(j=addr; (j<(int)(addr+size)); j++)
886 else /*Couldn't find a chunk big enough: report the problem.*/
888 tap->a_unaloc=taxp->a_size;
889 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
894 else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
896 /*Find the size of the space currently used for this areax overlay*/
897 // for(j=0x20, size=0; j<0x30; j++)
898 // if(idatamap[j]==fchar) size++;
900 /*If more space required, release the previously allocated areax in
901 internal RAM and search for a bigger one*/
902 if((int)taxp->a_size>size)
904 size=(int)taxp->a_size;
906 for(j=0x20; j<0x30; j++)
907 if(idatamap[j]==fchar) idatamap[j]=' ';
909 /*Search for a space large enough in data memory for this overlay areax*/
910 for(j=0x20, k=0; j<0x30; j++)
916 if(k==(int)taxp->a_size)
920 /*Mark the memory used for overlay*/
924 for(j=addr; (j<(int)(addr+size)); j++)
927 else /*Couldn't find a chunk big enough: report the problem.*/
929 tap->a_unaloc=taxp->a_size;
930 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
935 else /*Overlay areas not in internal ram*/
938 if (taxp->a_size > size) size = taxp->a_size;
942 /*Now set all overlayed areax to the same start address*/
950 else if (tap->a_flag & A_ABS) /* Absolute sections */
956 for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<256); j++)
958 if (idatamap[j] == ' ')
961 fprintf(stderr, "memory overlap at 0x%X for %s\n", j, tap->a_id);
964 else if (locIndex == 1)
966 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
968 else if (locIndex == 2)
970 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
972 taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
973 size += taxp->a_size;
977 else /* Concatenated sections */
979 if ((locIndex == 1) && tap->a_size)
981 addr = find_empty_space(addr, tap->a_size, codemap);
983 if ((locIndex == 2) && tap->a_size)
985 addr = find_empty_space(addr, tap->a_size, xdatamap);
989 if( (fchar=='D') || (fchar=='I') )
993 /*Search for a space large enough in internal RAM for this areax*/
994 for(j=ramstart, k=0; j<ramlimit; j++)
1000 if(k==(int)taxp->a_size)
1004 if(k==(int)taxp->a_size)
1006 taxp->a_addr = j-k+1;
1008 size += taxp->a_size;
1010 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
1011 idatamap[j]=(fchar=='D')?dchar:fchar;
1012 if((taxp->a_size>0)&&(fchar=='D'))dchar++;
1013 if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
1015 else /*We are in trouble, there is not enough memory for an areax chunk*/
1017 taxp->a_addr = addr;
1018 addr += taxp->a_size;
1019 size += taxp->a_size;
1020 tap->a_unaloc+=taxp->a_size;
1021 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1031 /*Search for a space large enough in data memory for this areax*/
1032 for(j=0x20, k=0; j<0x30; j++)
1034 if(idatamap[j]==' ')
1038 if(k==(int)taxp->a_size) break;
1041 /*Mark the memory used*/
1042 if(k==(int)taxp->a_size)
1044 taxp->a_addr = j-k+1;
1045 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
1048 else /*Couldn't find a chunk big enough: report the problem.*/
1050 tap->a_unaloc=taxp->a_size;
1051 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1055 size += taxp->a_size;
1058 else /*For concatenated BIT, CODE, and XRAM areax's*/
1060 if((fchar=='K') && (taxp->a_size == 1))
1062 taxp->a_size = 256-(addr & 0xFF);
1064 //find next unused address now
1065 if ((locIndex == 1) && taxp->a_size)
1067 addr = find_empty_space(addr, taxp->a_size, codemap);
1068 allocate_space(addr, taxp->a_size, tap->a_id, codemap);
1070 if ((locIndex == 2) && taxp->a_size)
1072 addr = find_empty_space(addr, taxp->a_size, xdatamap);
1073 allocate_space(addr, taxp->a_size, tap->a_id, xdatamap);
1075 taxp->a_addr = addr;
1076 addr += taxp->a_size;
1077 size += taxp->a_size;
1083 tap->a_addr = tap->a_axp->a_addr;
1085 if ((tap->a_flag&A_PAG) && (size > 256))
1088 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
1091 if ((tap->a_flag&A_PAG) && (tap->a_size) &&
1092 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
1095 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);