3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 * - change lkparea to use a_type == 0 as "virgin area" flag
22 * 02-Apr-98 JLH: add code to link 8051 data spaces
31 * The module lkarea.c contains the functions which
32 * create and link together all area definitions read
33 * from the .rel file(s).
35 * lkarea.c contains the following functions:
41 * lkarea.c contains no global variables.
44 /*)Function VOID newarea()
46 * The function newarea() creates and/or modifies area
47 * and areax structures for each A directive read from
48 * the .rel file(s). The function lkparea() is called
49 * to find the area structure associated with this name.
50 * If the area does not yet exist then a new area
51 * structure is created and linked to any existing
52 * linked area structures. The area flags are copied
53 * into the area flag variable. For each occurence of
54 * an A directive an areax structure is created and
55 * linked to the areax structures associated with this
56 * area. The size of this area section is placed into
57 * the areax structure. The flag value for all subsequent
58 * area definitions for the same area are compared and
59 * flagged as an error if they are not identical.
60 * The areax structure created for every occurence of
61 * an A directive is loaded with a pointer to the base
62 * area structure and a pointer to the associated
63 * head structure. And finally, a pointer to this
64 * areax structure is loaded into the list of areax
65 * structures in the head structure. Refer to lkdata.c
66 * for details of the structures and their linkage.
69 * areax **halp pointer to an array of pointers
70 * int i counter, loop variable, value
72 * int narea number of areas in this head structure
73 * areax * taxp pointer to an areax structure
77 * area *ap Pointer to the current
79 * areax *axp Pointer to the current
81 * head *hp Pointer to the current
83 * int lkerr error flag
86 * Addr_T eval() lkeval.c
87 * VOID exit() c_library
88 * int fprintf() c_library
89 * VOID getid() lklex.c
90 * VOID lkparea() lkarea.c
94 * The area and areax structures are created and
95 * linked with the appropriate head structures.
96 * Failure to allocate area or areax structure
97 * space will terminate the linker. Other internal
98 * errors most likely caused by corrupted .rel
99 * files will also terminate the linker.
103 * Create an area entry.
105 * A xxxxxx size nnnn flags mm
108 * | `------------- axp->a_size
109 * `------------------------- ap->a_id
115 register int i, narea;
129 axp->a_size = eval();
136 while (taxp->a_axp) {
144 /* if (i && (ap->a_flag != i)) { */
145 /* fprintf(stderr, "Conflicting flags in area %8s\n", id); */
150 * Evaluate area address
153 axp->a_addr = eval();
155 * Place pointer in header area list
158 fprintf(stderr, "No header defined\n");
163 for (i=0; i < narea ;++i) {
164 if (halp[i] == NULL) {
169 fprintf(stderr, "Header area list overflow\n");
173 /*)Function VOID lkparea(id)
175 * char * id pointer to the area name string
177 * The function lkparea() searches the linked area structures
178 * for a name match. If the name is not found then an area
179 * structure is created. An areax structure is created and
180 * appended to the areax structures linked to the area structure.
181 * The associated base area and head structure pointers are
182 * loaded into the areax structure.
185 * area * tap pointer to an area structure
186 * areax * taxp pointer to an areax structure
189 * area *ap Pointer to the current
191 * area *areap The pointer to the first
192 * area structure of a linked list
193 * areax *axp Pointer to the current
197 * VOID * new() lksym()
198 * char * strcpy() c_library
199 * int symeq() lksym.c
202 * Area and/or areax structures are created.
203 * Failure to allocate space for created structures
204 * will terminate the linker.
210 register struct area *tap;
211 register struct areax *taxp;
214 axp = (struct areax *) new (sizeof(struct areax));
215 axp->a_addr = -1; /* default: no address yet */
217 if (symeq(id, ap->a_id)) {
228 ap = (struct area *) new (sizeof(struct area));
240 strncpy(ap->a_id, id, NCPS);
244 /*)Function VOID lnkarea()
246 * The function lnkarea() resolves all area addresses.
247 * The function evaluates each area structure (and all
248 * the associated areax structures) in sequence. The
249 * linking process supports four (4) possible area types:
251 * ABS/OVR - All sections (each individual areax
252 * section) starts at the identical base
253 * area address overlaying all other
254 * areax sections for this area. The
255 * size of the area is largest of the area
258 * ABS/CON - All sections (each individual areax
259 * section) are concatenated with the
260 * first section starting at the base
261 * area address. The size of the area
262 * is the sum of the section sizes.
264 * NOTE: Multiple absolute (ABS) areas are
265 * never concatenated with each other,
266 * thus absolute area A and absolute area
267 * B will overlay each other if they begin
268 * at the same location (the default is
269 * always address 0 for absolute areas).
271 * REL/OVR - All sections (each individual areax
272 * section) starts at the identical base
273 * area address overlaying all other
274 * areax sections for this area. The
275 * size of the area is largest of the area
278 * REL/CON - All sections (each individual areax
279 * section) are concatenated with the
280 * first section starting at the base
281 * area address. The size of the area
282 * is the sum of the section sizes.
284 * NOTE: Relocatable (REL) areas are always concatenated
285 * with each other, thus relocatable area B
286 * (defined after area A) will follow
287 * relocatable area A independent of the
288 * starting address of area A. Within a
289 * specific area each areax section may be
290 * overlayed or concatenated with other
294 * If a base address for an area is specified then the
295 * area will start at that address. Any relocatable
296 * areas defined subsequently will be concatenated to the
297 * previous relocatable area if it does not have a base
300 * The names s_<areaname> and l_<areaname> are created to
301 * define the starting address and length of each area.
304 * Addr_T rloc ;current relocation address
305 * char temp[] ;temporary string
306 * struct symbol *sp ;symbol structure
309 * area *ap Pointer to the current
311 * area *areap The pointer to the first
312 * area structure of a linked list
315 * int fprintf() c_library
316 * VOID lnksect() lkarea.c
317 * symbol *lkpsym() lksym.c
318 * char * strncpy() c_library
319 * int symeq() lksym.c
322 * All area and areax addresses and sizes are
323 * determined and saved in their respective
327 VOID lnksect(register struct area *tap);
329 * Resolve all area addresses.
338 /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
342 rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
345 if (ap->a_flag&A_ABS) {
351 /* Determine memory space */
353 if (ap->a_flag & A_CODE) {
356 if (ap->a_flag & A_XDATA) {
359 if (ap->a_flag & A_BIT) {
363 * Relocatable sections
365 if (ap->a_type == 0) { /* JLH */
366 ap->a_addr = rloc[ locIndex ];
370 rloc[ locIndex ] = ap->a_addr + ap->a_size;
374 * Create symbols called:
375 * s_<areaname> the start address of the area
376 * l_<areaname> the length of the area
379 if (! symeq(ap->a_id, _abs_)) {
380 strncpy(temp+2,ap->a_id,NCPS-2);
384 sp = lkpsym(temp, 1);
385 sp->s_addr = ap->a_addr ;
386 /* sp->s_axp = ap->a_axp; JLH: was NULL; */
390 sp = lkpsym(temp, 1);
391 sp->s_addr = ap->a_size;
397 /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
398 to compute the byte size of BSEG_BYTES: */
399 if (!strcmp(ap->a_id, "BSEG")) {
400 ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
402 else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
403 else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
404 else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
405 else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
406 else if (!strcmp(ap->a_id, "BSEG_BYTES"))
411 /*If upper register banks are not used roll back the relocation counter*/
412 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
423 /*)Function VOID lnksect()
425 * area * tap pointer to an area structure
427 * The function lnksect() is the function called by
428 * lnkarea() to resolve the areax addresses. Refer
429 * to the function lnkarea() for more detail. Pageing
430 * boundary and length errors will be reported by this
434 * Addr_T size size of area
435 * Addr_T addr address of area
436 * areax * taxp pointer to an areax structure
439 * int lkerr error flag
445 * All area and areax addresses and sizes area determined
446 * and linked into the structures.
450 lnksect(register struct area *tap)
452 register Addr_T size, addr;
453 register struct areax *taxp;
458 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
460 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
465 if (tap->a_flag&A_OVR) {
471 if (taxp->a_size > size)
477 * Concatenated sections
481 addr += taxp->a_size;
482 size += taxp->a_size;
487 if ((tap->a_flag&A_PAG) && (size > 256)) {
489 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
492 if ((tap->a_flag&A_PAG) && (tap->a_size) &&
493 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
496 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
501 Addr_T lnksect2 (struct area *tap, int locIndex);
503 unsigned long codemap[524288];
504 unsigned long xdatamap[131072];
505 struct area *dseg_ap = NULL;
506 Addr_T dram_start = 0;
507 Addr_T iram_start = 0;
509 /*Modified version of the functions for packing variables in internal data memory*/
512 Addr_T rloc[4]={0, 0, 0, 0};
518 struct area *bseg_ap = NULL;
519 struct area *abs_ap = NULL;
520 struct area *gs0_ap = NULL;
521 struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
523 for(j=0; j<256; j++) idatamap[j]=' ';
524 memset(codemap, 0, sizeof(codemap));
525 memset(xdatamap, 0, sizeof(xdatamap));
527 /* first sort all absolute areas to the front */
529 /* no need to check first area, it's in front anyway */
530 while (ap && ap->a_ap)
532 if (ap->a_ap->a_flag & A_ABS)
533 {/* next area is absolute, move it to front,
534 reversed sequence is no problem for absolutes */
536 ap->a_ap = abs_ap->a_ap;
537 abs_ap->a_ap = areap;
546 /* next accumulate all GSINITx/GSFINAL area sizes
547 into GSINIT so they stay together */
552 if (ap->a_flag & A_ABS)
554 abs_ap = ap; /* Remember the last abs area */
556 if (!strncmp(ap->a_id, "GS", 2))
563 ap->a_size += axp->a_size;
567 gs_size += ap->a_size;
568 if (!strcmp(ap->a_id, "GSINIT0"))
573 /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
574 to compute the byte size of BSEG_BYTES: */
575 else if (!strcmp(ap->a_id, "BSEG"))
577 bseg_ap = ap->a_ap; //BSEG_BYTES
578 for (axp=ap->a_axp; axp; axp=axp->a_axp)
579 ap->a_size += axp->a_size;
580 bseg_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
581 ap->a_ap = bseg_ap->a_ap; //removed BSEG_BYTES from list
582 bseg_ap->a_ap = abs_ap->a_ap;
583 abs_ap->a_ap = bseg_ap; //inserted BSEG_BYTES after abs
586 else if (!strcmp(ap->a_id, "DSEG"))
588 dseg_ap = ap; /*Need it later*/
589 dram_start = ap->a_addr;
591 else if (!strcmp(ap->a_id, "ISEG"))
593 iram_start = ap->a_addr;
598 gs0_ap->a_size = gs_size;
603 /* Determine memory space */
604 if (ap->a_flag & A_CODE) locIndex = 1;
605 else if (ap->a_flag & A_XDATA) locIndex = 2;
606 else if (ap->a_flag & A_BIT) locIndex = 3;
609 if (ap->a_flag & A_ABS) /* Absolute sections */
611 lnksect2(ap, locIndex);
613 else /* Relocatable sections */
617 ap->a_addr = rloc[locIndex];
621 rloc[locIndex] = lnksect2(ap, locIndex);
624 if (!strcmp(ap->a_id, "BSEG_BYTES"))
626 bseg_ap->a_addr = (ap->a_axp->a_addr - 0x20) * 8; /*Bytes to bits*/
629 * Create symbols called:
630 * s_<areaname> the start address of the area
631 * l_<areaname> the length of the area
634 if (! symeq(ap->a_id, _abs_))
636 strncpy(temp+2,ap->a_id,NCPS-2);
640 sp = lkpsym(temp, 1);
641 sp->s_addr = ap->a_addr;
643 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
646 sp = lkpsym(temp, 1);
647 sp->s_addr = ap->a_size;
650 if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
656 /*Compute the size of DSEG*/
661 for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
663 if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
664 if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
668 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
671 unsigned long mask, b;
677 j = (start + size) >> 5;
678 mask = -(1 << (start & 0x1F));
685 for (b=0x80000000; b!=0; b>>=1, k--)
700 mask &= (1 << ((start + size) & 0x1F)) - 1;
704 for (b=0x80000000; b!=0; b>>=1, k--)
709 start = (a & ~0x1F) + k;
718 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
724 j = (start + size) >> 5;
725 mask = -(1 << (start & 0x1F));
731 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
737 mask &= (1 << ((start + size) & 0x1F)) - 1;
740 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
746 Addr_T lnksect2 (struct area *tap, int locIndex)
748 register Addr_T size, addr;
749 register struct areax *taxp;
750 int j, k, ramlimit, ramstart;
751 char fchar=' ', dchar='a';
752 char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
753 " in internal RAM for area %s.\n";
757 /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
758 if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
760 ramstart = iram_start;
762 if ((iram_size <= 0) || (ramstart + iram_size > 0x100))
765 ramlimit = ramstart + iram_size;
769 ramstart = dram_start;
771 if ((iram_size <= 0) || (ramstart + iram_size > 0x80))
774 ramlimit = ramstart + iram_size;
780 if ((tap->a_flag&A_PAG) && (addr & 0xFF))
783 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
789 /*Use a letter to identify each area in the internal RAM layout map*/
792 /**/ if(!strcmp(tap->a_id, "DSEG"))
793 fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
794 else if(!strcmp(tap->a_id, "ISEG"))
796 else if(!strcmp(tap->a_id, "SSEG"))
798 else if(!strcmp(tap->a_id, "OSEG"))
800 else if(!strcmp(tap->a_id, "REG_BANK_0"))
802 else if(!strcmp(tap->a_id, "REG_BANK_1"))
804 else if(!strcmp(tap->a_id, "REG_BANK_2"))
806 else if(!strcmp(tap->a_id, "REG_BANK_3"))
808 else if(!strcmp(tap->a_id, "BSEG_BYTES"))
810 else if(!strcmp(tap->a_id, "BIT_BANK"))
815 else if (locIndex == 1)
817 /**/ if(!strcmp(tap->a_id, "GSINIT"))
820 else if (locIndex == 2)
822 /**/ if(!strcmp(tap->a_id, "XSTK"))
826 if (tap->a_flag&A_OVR) /* Overlayed sections */
830 if(taxp->a_size == 0)
836 if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
841 for(j=addr; (j<(int)(addr+size)) && (j<ramlimit); j++)
844 else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
846 /*Find the size of the space currently used for this areax overlay*/
847 for(j=ramstart, size=0; j<ramlimit; j++)
848 if(idatamap[j]==fchar) size++;
850 if( (fchar=='S') && (stacksize==0) )
852 /*Search for the largest space available and use it for stack*/
853 for(j=ramstart, k=0, taxp->a_size=0; j<ramlimit; j++)
857 if((++k)>(int)taxp->a_size)
865 stacksize=taxp->a_size;
868 /*If more space required, release the previously allocated areax in
869 internal RAM and search for a bigger one*/
870 if((int)taxp->a_size>size)
872 size=(int)taxp->a_size;
874 for(j=ramstart; j<ramlimit; j++)
875 if(idatamap[j]==fchar) idatamap[j]=' ';
877 /*Search for a space large enough in data memory for this overlay areax*/
878 for(j=ramstart, k=0; j<ramlimit; j++)
884 if(k==(int)taxp->a_size)
888 /*Mark the memory used for overlay*/
889 if(k==(int)taxp->a_size)
892 for(j=addr; (j<(int)(addr+size)); j++)
895 else /*Couldn't find a chunk big enough: report the problem.*/
897 tap->a_unaloc=taxp->a_size;
898 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
903 else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
905 /*Find the size of the space currently used for this areax overlay*/
906 // for(j=0x20, size=0; j<0x30; j++)
907 // if(idatamap[j]==fchar) size++;
909 /*If more space required, release the previously allocated areax in
910 internal RAM and search for a bigger one*/
911 if((int)taxp->a_size>size)
913 size=(int)taxp->a_size;
915 for(j=0x20; j<0x30; j++)
916 if(idatamap[j]==fchar) idatamap[j]=' ';
918 /*Search for a space large enough in data memory for this overlay areax*/
919 for(j=0x20, k=0; j<0x30; j++)
925 if(k==(int)taxp->a_size)
929 /*Mark the memory used for overlay*/
933 for(j=addr; (j<(int)(addr+size)); j++)
936 else /*Couldn't find a chunk big enough: report the problem.*/
938 tap->a_unaloc=taxp->a_size;
939 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
944 else /*Overlay areas not in internal ram*/
947 if (taxp->a_size > size) size = taxp->a_size;
951 /*Now set all overlayed areax to the same start address*/
959 else if (tap->a_flag & A_ABS) /* Absolute sections */
965 for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<256); j++)
967 if (idatamap[j] == ' ')
970 fprintf(stderr, "memory overlap at 0x%X for %s\n", j, tap->a_id);
973 else if (locIndex == 1)
975 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
977 else if (locIndex == 2)
979 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
981 taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
982 size += taxp->a_size;
986 else /* Concatenated sections */
988 if ((locIndex == 1) && tap->a_size)
990 addr = find_empty_space(addr, tap->a_size, codemap);
992 if ((locIndex == 2) && tap->a_size)
994 addr = find_empty_space(addr, tap->a_size, xdatamap);
998 if( (fchar=='D') || (fchar=='I') )
1002 /*Search for a space large enough in internal RAM for this areax*/
1003 for(j=ramstart, k=0; j<ramlimit; j++)
1005 if(idatamap[j]==' ')
1009 if(k==(int)taxp->a_size)
1013 if(k==(int)taxp->a_size)
1015 taxp->a_addr = j-k+1;
1017 size += taxp->a_size;
1019 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
1020 idatamap[j]=(fchar=='D')?dchar:fchar;
1021 if((taxp->a_size>0)&&(fchar=='D'))dchar++;
1022 if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
1024 else /*We are in trouble, there is not enough memory for an areax chunk*/
1026 taxp->a_addr = addr;
1027 addr += taxp->a_size;
1028 size += taxp->a_size;
1029 tap->a_unaloc+=taxp->a_size;
1030 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1040 /*Search for a space large enough in data memory for this areax*/
1041 for(j=0x20, k=0; j<0x30; j++)
1043 if(idatamap[j]==' ')
1047 if(k==(int)taxp->a_size) break;
1050 /*Mark the memory used*/
1051 if(k==(int)taxp->a_size)
1053 taxp->a_addr = j-k+1;
1054 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
1057 else /*Couldn't find a chunk big enough: report the problem.*/
1059 tap->a_unaloc=taxp->a_size;
1060 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1064 size += taxp->a_size;
1067 else /*For concatenated BIT, CODE, and XRAM areax's*/
1069 if((fchar=='K') && (taxp->a_size == 1))
1071 taxp->a_size = 256-(addr & 0xFF);
1073 //find next unused address now
1074 if ((locIndex == 1) && taxp->a_size)
1076 addr = find_empty_space(addr, taxp->a_size, codemap);
1077 allocate_space(addr, taxp->a_size, tap->a_id, codemap);
1079 if ((locIndex == 2) && taxp->a_size)
1081 addr = find_empty_space(addr, taxp->a_size, xdatamap);
1082 allocate_space(addr, taxp->a_size, tap->a_id, xdatamap);
1084 taxp->a_addr = addr;
1085 addr += taxp->a_size;
1086 size += taxp->a_size;
1092 tap->a_addr = tap->a_axp->a_addr;
1094 if ((tap->a_flag&A_PAG) && (size > 256))
1097 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
1100 if ((tap->a_flag&A_PAG) && (tap->a_size) &&
1101 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
1104 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);