* as/link/mcs51/lkarea.c (lnkarea2): handle absolute areas, restructured
[fw/sdcc] / as / link / mcs51 / lkarea.c
1 /* lkarea.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  *  3-Nov-97 JLH:
12  *           - change lkparea to use a_type == 0 as "virgin area" flag
13  * 02-Apr-98 JLH: add code to link 8051 data spaces
14  */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include "aslink.h"
19
20 /*)Module   lkarea.c
21  *
22  *  The module lkarea.c contains the functions which
23  *  create and link together all area definitions read
24  *  from the .rel file(s).
25  *
26  *  lkarea.c contains the following functions:
27  *      VOID    lnkarea()
28  *      VOID    lnksect()
29  *      VOID    lkparea()
30  *      VOID    newarea()
31  *
32  *  lkarea.c contains no global variables.
33  */
34
35 /*)Function VOID    newarea()
36  *
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.
58  *
59  *  local variables:
60  *      areax **halp        pointer to an array of pointers
61  *      int     i           counter, loop variable, value
62  *      char    id[]        id string
63  *      int     narea       number of areas in this head structure
64  *      areax * taxp        pointer to an areax structure
65  *                          to areax structures
66  *
67  *  global variables:
68  *      area    *ap         Pointer to the current
69  *                          area structure
70  *      areax   *axp        Pointer to the current
71  *                          areax structure
72  *      head    *hp         Pointer to the current
73  *                          head structure
74  *      int     lkerr       error flag
75  *
76  *  functions called:
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
82  *      VOID    skip()      lklex.c
83  *
84  *  side effects:
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.
91  */
92
93 /*
94  * Create an area entry.
95  *
96  * A xxxxxx size nnnn flags mm
97  *   |           |          |
98  *   |           |          `--  ap->a_flag
99  *   |           `------------- axp->a_size
100  *   `-------------------------  ap->a_id
101  *
102  */
103 VOID
104 newarea()
105 {
106     register int i, narea;
107     struct areax *taxp;
108     struct areax **halp;
109     char id[NCPS];
110
111     /*
112      * Create Area entry
113      */
114     getid(id, -1);
115     lkparea(id);
116     /*
117      * Evaluate area size
118      */
119     skip(-1);
120     axp->a_size = eval();
121     /*
122      * Evaluate flags
123      */
124     skip(-1);
125     i = 0;
126     taxp = ap->a_axp;
127     while (taxp->a_axp) {
128         ++i;
129         taxp = taxp->a_axp;
130     }
131     if (i == 0) {
132         ap->a_flag = eval();
133     } else {
134         i = eval();
135 /*      if (i && (ap->a_flag != i)) { */
136 /*          fprintf(stderr, "Conflicting flags in area %8s\n", id); */
137 /*          lkerr++; */
138 /*      } */
139     }
140     /*
141      * Evaluate area address
142      */
143     skip(-1);
144     axp->a_addr = eval();
145     /*
146      * Place pointer in header area list
147      */
148     if (headp == NULL) {
149         fprintf(stderr, "No header defined\n");
150         lkexit(1);
151     }
152     narea = hp->h_narea;
153     halp = hp->a_list;
154     for (i=0; i < narea ;++i) {
155         if (halp[i] == NULL) {
156             halp[i] = taxp;
157             return;
158         }
159     }
160     fprintf(stderr, "Header area list overflow\n");
161     lkexit(1);
162 }
163
164 /*)Function VOID    lkparea(id)
165  *
166  *      char *  id      pointer to the area name string
167  *
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.
174  *
175  *  local variables:
176  *      area *  tap         pointer to an area structure
177  *      areax * taxp        pointer to an areax structure
178  *
179  *  global variables:
180  *      area    *ap         Pointer to the current
181  *                          area structure
182  *      area    *areap      The pointer to the first
183  *                          area structure of a linked list
184  *      areax   *axp        Pointer to the current
185  *                          areax structure
186  *
187  *  functions called:
188  *      VOID *  new()       lksym()
189  *      char *  strcpy()    c_library
190  *      int     symeq()     lksym.c
191  *
192  *  side effects:
193  *      Area and/or areax structures are created.
194  *      Failure to allocate space for created structures
195  *      will terminate the linker.
196  */
197
198 VOID
199 lkparea(char *id)
200 {
201     register struct area *tap;
202     register struct areax *taxp;
203
204     ap = areap;
205     axp = (struct areax *) new (sizeof(struct areax));
206     axp->a_addr = -1; /* default: no address yet */
207     while (ap) {
208         if (symeq(id, ap->a_id)) {
209             taxp = ap->a_axp;
210             while (taxp->a_axp)
211                 taxp = taxp->a_axp;
212             taxp->a_axp = axp;
213             axp->a_bap = ap;
214             axp->a_bhp = hp;
215             return;
216         }
217         ap = ap->a_ap;
218     }
219     ap = (struct area *) new (sizeof(struct area));
220     if (areap == NULL) {
221         areap = ap;
222     } else {
223         tap = areap;
224         while (tap->a_ap)
225             tap = tap->a_ap;
226         tap->a_ap = ap;
227     }
228     ap->a_axp = axp;
229     axp->a_bap = ap;
230     axp->a_bhp = hp;
231     strncpy(ap->a_id, id, NCPS);
232     ap->a_addr = 0;
233 }
234
235 /*)Function VOID    lnkarea()
236  *
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:
241  *
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
247  *          sections.
248  *
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.
254  *
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).
261  *
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
267  *          sections.
268  *
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.
274  *
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
282  *          areax sections.
283  *
284  *
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
289  *  address specified.
290  *
291  *  The names s_<areaname> and l_<areaname> are created to
292  *  define the starting address and length of each area.
293  *
294  *  local variables:
295  *      Addr_T  rloc        ;current relocation address
296  *      char    temp[]      ;temporary string
297  *      struct symbol   *sp ;symbol structure
298  *
299  *  global variables:
300  *      area    *ap         Pointer to the current
301  *                          area structure
302  *      area    *areap      The pointer to the first
303  *                          area structure of a linked list
304  *
305  *  functions called:
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
311  *
312  *  side effects:
313  *      All area and areax addresses and sizes are
314  *      determined and saved in their respective
315  *      structures.
316  */
317
318 VOID lnksect(register struct area *tap);
319 /*
320  * Resolve all area addresses.
321  */
322 VOID
323 lnkarea()
324 {
325     Addr_T rloc[4];
326     int  locIndex;
327     char temp[NCPS];
328     struct sym *sp;
329     /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
330     struct area *ta[5];
331     int j;
332
333     rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
334     ap = areap;
335     while (ap) {
336         if (ap->a_flag&A_ABS) {
337             /*
338              * Absolute sections
339              */
340             lnksect(ap);
341         } else {
342             /* Determine memory space */
343             locIndex = 0;
344             if (ap->a_flag & A_CODE) {
345                 locIndex = 1;
346             }
347             if (ap->a_flag & A_XDATA) {
348                 locIndex = 2;
349             }
350             if (ap->a_flag & A_BIT) {
351                 locIndex = 3;
352             }
353             /*
354              * Relocatable sections
355              */
356             if (ap->a_type == 0) {  /* JLH */
357                 ap->a_addr = rloc[ locIndex ];
358                 ap->a_type = 1;
359             }
360             lnksect(ap);
361             rloc[ locIndex ] = ap->a_addr + ap->a_size;
362         }
363
364         /*
365          * Create symbols called:
366          *  s_<areaname>    the start address of the area
367          *  l_<areaname>    the length of the area
368          */
369
370         if (! symeq(ap->a_id, _abs_)) {
371             strncpy(temp+2,ap->a_id,NCPS-2);
372             *(temp+1) = '_';
373
374             *temp = 's';
375             sp = lkpsym(temp, 1);
376             sp->s_addr = ap->a_addr ;
377             /* sp->s_axp = ap->a_axp;  JLH: was NULL; */
378             sp->s_type |= S_DEF;
379
380             *temp = 'l';
381             sp = lkpsym(temp, 1);
382             sp->s_addr = ap->a_size;
383             sp->s_axp = NULL;
384             sp->s_type |= S_DEF;
385
386         }
387
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*/
392         }
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"))
398         {
399             ta[4]=ap;
400             for(j=4; j>1; j--)
401             {
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) )
404                 {
405                     rloc[0]-=8;
406                 }
407                 else break;
408             }
409         }
410         ap = ap->a_ap;
411     }
412 }
413
414 /*)Function VOID    lnksect()
415  *
416  *      area *  tap         pointer to an area structure
417  *
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
422  *  function.
423  *
424  *  local variables:
425  *      Addr_T  size        size of area
426  *      Addr_T  addr        address of area
427  *      areax * taxp        pointer to an areax structure
428  *
429  *  global variables:
430  *      int     lkerr       error flag
431  *
432  *  functions called:
433  *      none
434  *
435  *  side effects:
436  *      All area and areax addresses and sizes area determined
437  *      and linked into the structures.
438  */
439
440 VOID
441 lnksect(register struct area *tap)
442 {
443     register Addr_T size, addr;
444     register struct areax *taxp;
445
446     size = 0;
447     addr = tap->a_addr;
448 #if 0
449     if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
450         fprintf(stderr,
451         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
452         lkerr++;
453     }
454 #endif
455     taxp = tap->a_axp;
456     if (tap->a_flag&A_OVR) {
457         /*
458          * Overlayed sections
459          */
460         while (taxp) {
461             taxp->a_addr = addr;
462             if (taxp->a_size > size)
463                 size = taxp->a_size;
464             taxp = taxp->a_axp;
465         }
466     } else {
467         /*
468          * Concatenated sections
469          */
470         while (taxp) {
471             taxp->a_addr = addr;
472             addr += taxp->a_size;
473             size += taxp->a_size;
474             taxp = taxp->a_axp;
475         }
476     }
477     tap->a_size = size;
478     if ((tap->a_flag&A_PAG) && (size > 256)) {
479         fprintf(stderr,
480         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
481         lkerr++;
482     }
483     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
484         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
485     {
486         fprintf(stderr,
487         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
488         lkerr++;
489     }
490 }
491
492 Addr_T lnksect2 (struct area *tap, int locIndex);
493 char idatamap[256];
494 unsigned long codemap[524288];
495 unsigned long xdatamap[131072];
496 struct area *dseg_ap = NULL;
497 struct area *iseg_ap = NULL;
498
499 /*Modified version of the functions for packing variables in internal data memory*/
500 VOID lnkarea2 (void)
501 {
502     Addr_T rloc[4]={0, 0, 0, 0};
503     Addr_T gs_size = 0;
504     int  locIndex;
505     char temp[NCPS];
506     struct sym *sp;
507     int j;
508     struct area *bseg_ap = NULL;
509     struct area *abs_ap = NULL;
510     struct area *gs0_ap = NULL;
511     struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
512
513     for(j=0; j<256; j++) idatamap[j]=' ';
514     memset(codemap, 0, sizeof(codemap));
515     memset(xdatamap, 0, sizeof(xdatamap));
516
517     /* first sort all absolute areas to the front */
518     ap = areap;
519     /* no need to check first area, it's in front anyway */
520     while (ap && ap->a_ap)
521     {
522         if (ap->a_ap->a_flag & A_ABS)
523         {/* next area is absolute, move it to front,
524             reversed sequence is no problem for absolutes */
525             abs_ap = ap->a_ap;
526             ap->a_ap = abs_ap->a_ap;
527             abs_ap->a_ap = areap;
528             areap = abs_ap;
529         }
530         else
531         {
532             ap = ap->a_ap;
533         }
534     }
535
536     /* next accumulate all GSINITx/GSFINAL area sizes
537        into GSINIT so they stay together */
538     ap = areap;
539     abs_ap = areap;
540     while (ap)
541     {
542         if (ap->a_flag & A_ABS)
543         {
544             abs_ap = ap; /* Remember the last abs area */
545         }
546         if (!strncmp(ap->a_id, "GS", 2))
547         {/* GSxxxxx area */
548             if (ap->a_size == 0)
549             {
550                 axp = ap->a_axp;
551                 while (axp)
552                 {
553                     ap->a_size += axp->a_size;
554                     axp = axp->a_axp;
555                 }
556             }
557             gs_size += ap->a_size;
558             if (!strcmp(ap->a_id, "GSINIT0"))
559             {/* GSINIT0 area */
560                 gs0_ap = ap;
561             }
562         }
563         /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
564         to compute the byte size of BSEG_BYTES: */
565         else if (!strcmp(ap->a_id, "BSEG"))
566         {
567             bseg_ap = ap->a_ap;            //BSEG_BYTES
568             for (axp=ap->a_axp; axp; axp=axp->a_axp)
569                 ap->a_size += axp->a_size;
570             bseg_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
571             ap->a_ap = bseg_ap->a_ap;      //removed BSEG_BYTES from list
572             bseg_ap->a_ap = abs_ap->a_ap;
573             abs_ap->a_ap = bseg_ap;        //inserted BSEG_BYTES after abs
574             bseg_ap = ap;                  //BSEG
575         }
576         else if (!strcmp(ap->a_id, "DSEG"))
577         {
578             dseg_ap = ap; /*Need it later*/
579         }
580         else if (!strcmp(ap->a_id, "ISEG"))
581         {
582             iseg_ap = ap; /*Need it later*/
583         }
584         ap = ap->a_ap;
585     }
586     if (gs0_ap)
587         gs0_ap->a_size = gs_size;
588
589     ap = areap;
590     while (ap)
591     {
592         /* Determine memory space */
593              if (ap->a_flag & A_CODE)  locIndex = 1;
594         else if (ap->a_flag & A_XDATA) locIndex = 2;
595         else if (ap->a_flag & A_BIT)   locIndex = 3;
596         else locIndex = 0;
597
598         if (ap->a_flag & A_ABS) /* Absolute sections */
599         {
600             lnksect2(ap, locIndex);
601         }
602         else /* Relocatable sections */
603         {
604             if (ap->a_type == 0)
605             {
606                 ap->a_addr = rloc[locIndex];
607                 ap->a_type = 1;
608             }
609
610             rloc[locIndex] = lnksect2(ap, locIndex);
611         }
612
613         if (!strcmp(ap->a_id, "BSEG_BYTES"))
614         {
615             bseg_ap->a_addr = (ap->a_axp->a_addr - 0x20) * 8; /*Bytes to bits*/
616         }
617         /*
618          * Create symbols called:
619          *  s_<areaname>    the start address of the area
620          *  l_<areaname>    the length of the area
621          */
622
623         if (! symeq(ap->a_id, _abs_))
624         {
625             strncpy(temp+2,ap->a_id,NCPS-2);
626             *(temp+1) = '_';
627
628             *temp = 's';
629             sp = lkpsym(temp, 1);
630             sp->s_addr = ap->a_addr;
631             sp->s_type |= S_DEF;
632             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
633
634             *temp = 'l';
635             sp = lkpsym(temp, 1);
636             sp->s_addr = ap->a_size;
637             sp->s_axp = NULL;
638             sp->s_type |= S_DEF;
639             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
640         }
641
642         ap = ap->a_ap;
643     }
644
645     /*Compute the size of DSEG*/
646     if(dseg_ap!=NULL)
647     {
648         dseg_ap->a_addr=0;
649         dseg_ap->a_size=0;
650         for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
651     }
652     if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
653     if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
654 }
655
656 static
657 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
658 {
659     int i, j, k;
660     unsigned long mask, b;
661
662     while (1)
663     {
664         Addr_T a = start;
665         i = start >> 5;
666         j = (start + size) >> 5;
667         mask = -(1 << (start & 0x1F));
668
669         while (i < j)
670         {
671             if (map[i] & mask)
672             {
673                 k = 32;
674                 for (b=0x80000000; b!=0; b>>=1, k--)
675                 {
676                     if (map[i] & b)
677                       break;
678                 }
679                 start = a + k;
680                 break;
681             }
682             i++;
683             mask = 0xFFFFFFFF;
684             a += 32;
685         }
686         if (start > a)
687           continue;
688
689         mask &= (1 << ((start + size) & 0x1F)) - 1;
690         if (map[i] & mask)
691         {
692             k = 32;
693             for (b=0x80000000; b!=0; b>>=1, k--)
694             {
695                 if (map[i] & b)
696                     break;
697             }
698             start = (a & ~0x1F) + k;
699         }
700         if (start <= a)
701           break;
702     }
703     return start;
704 }
705
706 static
707 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
708 {
709     int i, j;
710     unsigned long mask;
711     Addr_T a = start;
712     i = start >> 5;
713     j = (start + size) >> 5;
714     mask = -(1 << (start & 0x1F));
715
716     while (i < j)
717     {
718         if (map[i] & mask)
719         {
720             fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
721         }
722         map[i++] |= mask;
723         mask = 0xFFFFFFFF;
724         a += 32;
725     }
726     mask &= (1 << ((start + size) & 0x1F)) - 1;
727     if (map[i] & mask)
728     {
729         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
730     }
731     map[i] |= mask;
732     return start;
733 }
734
735 Addr_T lnksect2 (struct area *tap, int locIndex)
736 {
737     register Addr_T size, addr;
738     register struct areax *taxp;
739     int j, k, ramlimit, ramstart;
740     char fchar=' ', dchar='a';
741     char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
742                   " in internal RAM for area %s.\n";
743
744     tap->a_unaloc=0;
745
746     /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
747     if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
748     {
749         if (iseg_ap)
750             ramstart = iseg_ap->a_addr;
751         else
752             ramstart = 0;
753
754         if ((iram_size <= 0) || (ramstart + iram_size > 0x100))
755             ramlimit = 0x100;
756         else
757             ramlimit = ramstart + iram_size;
758     }
759     else
760     {
761         if (dseg_ap)
762             ramstart = dseg_ap->a_addr;
763         else
764             ramstart = 0;
765
766         if ((iram_size <= 0) || (ramstart + iram_size > 0x80))
767             ramlimit = 0x80;
768         else
769             ramlimit = ramstart + iram_size;
770     }
771
772     size = 0;
773     addr = tap->a_addr;
774 #if 0
775     if ((tap->a_flag&A_PAG) && (addr & 0xFF))
776     {
777         fprintf(stderr,
778           "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
779         lkerr++;
780     }
781 #endif
782     taxp = tap->a_axp;
783
784     /*Use a letter to identify each area in the internal RAM layout map*/
785     if (locIndex==0)
786     {
787         /**/ if(!strcmp(tap->a_id, "DSEG"))
788             fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
789         else if(!strcmp(tap->a_id, "ISEG"))
790             fchar='I';
791         else if(!strcmp(tap->a_id, "SSEG"))
792             fchar='S';
793         else if(!strcmp(tap->a_id, "OSEG"))
794             fchar='Q';
795         else if(!strcmp(tap->a_id, "REG_BANK_0"))
796             fchar='0';
797         else if(!strcmp(tap->a_id, "REG_BANK_1"))
798             fchar='1';
799         else if(!strcmp(tap->a_id, "REG_BANK_2"))
800             fchar='2';
801         else if(!strcmp(tap->a_id, "REG_BANK_3"))
802             fchar='3';
803         else if(!strcmp(tap->a_id, "BSEG_BYTES"))
804             fchar='B';
805         else if(!strcmp(tap->a_id, "BIT_BANK"))
806             fchar='T';
807         else
808             fchar=' ';/*???*/
809     }
810     else if (locIndex == 1)
811     {
812         /**/ if(!strcmp(tap->a_id, "GSINIT"))
813             fchar='G';
814     }
815     else if (locIndex == 2)
816     {
817         /**/ if(!strcmp(tap->a_id, "XSTK"))
818             fchar='K';
819     }
820
821     if (tap->a_flag&A_OVR) /* Overlayed sections */
822     {
823         while (taxp)
824         {
825             if(taxp->a_size == 0)
826             {
827                 taxp = taxp->a_axp;
828                 continue;
829             }
830
831             if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
832             {
833                 addr=(fchar-'0')*8;
834                 taxp->a_addr=addr;
835                 size=taxp->a_size;
836                 for(j=addr; (j<(int)(addr+size)) && (j<ramlimit); j++)
837                     idatamap[j]=fchar;
838             }
839             else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
840             {
841                 /*Find the size of the space currently used for this areax overlay*/
842                 for(j=ramstart, size=0; j<ramlimit; j++)
843                     if(idatamap[j]==fchar) size++;
844
845                 if( (fchar=='S') && (stacksize==0) )
846                 {
847                    /*Search for the largest space available and use it for stack*/
848                     for(j=ramstart, k=0, taxp->a_size=0; j<ramlimit; j++)
849                     {
850                         if(idatamap[j]==' ')
851                         {
852                             if((++k)>(int)taxp->a_size)
853                                 taxp->a_size=k;
854                         }
855                         else
856                         {
857                             k=0;
858                         }
859                     }
860                     stacksize=taxp->a_size;
861                 }
862
863                 /*If more space required, release the previously allocated areax in
864                 internal RAM and search for a bigger one*/
865                 if((int)taxp->a_size>size)
866                 {
867                     size=(int)taxp->a_size;
868
869                     for(j=ramstart; j<ramlimit; j++)
870                         if(idatamap[j]==fchar) idatamap[j]=' ';
871
872                     /*Search for a space large enough in data memory for this overlay areax*/
873                     for(j=ramstart, k=0; j<ramlimit; j++)
874                     {
875                         if(idatamap[j]==' ')
876                             k++;
877                         else
878                             k=0;
879                     if(k==(int)taxp->a_size)
880                             break;
881                     }
882
883                     /*Mark the memory used for overlay*/
884                     if(k==(int)taxp->a_size)
885                     {
886                         addr = j-k+1;
887                         for(j=addr; (j<(int)(addr+size)); j++)
888                             idatamap[j]=fchar;
889                     }
890                     else /*Couldn't find a chunk big enough: report the problem.*/
891                     {
892                         tap->a_unaloc=taxp->a_size;
893                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
894                         lkerr++;
895                     }
896                 }
897             }
898             else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
899             {
900                 /*Find the size of the space currently used for this areax overlay*/
901 //              for(j=0x20, size=0; j<0x30; j++)
902 //                  if(idatamap[j]==fchar) size++;
903
904                 /*If more space required, release the previously allocated areax in
905                 internal RAM and search for a bigger one*/
906                 if((int)taxp->a_size>size)
907                 {
908                     size=(int)taxp->a_size;
909
910                     for(j=0x20; j<0x30; j++)
911                         if(idatamap[j]==fchar) idatamap[j]=' ';
912
913                     /*Search for a space large enough in data memory for this overlay areax*/
914                     for(j=0x20, k=0; j<0x30; j++)
915                     {
916                         if(idatamap[j]==' ')
917                             k++;
918                         else
919                             k=0;
920                         if(k==(int)taxp->a_size)
921                             break;
922                     }
923
924                     /*Mark the memory used for overlay*/
925                     if(k==(int)size)
926                     {
927                         addr = j-k+1;
928                         for(j=addr; (j<(int)(addr+size)); j++)
929                             idatamap[j]=fchar;
930                     }
931                     else /*Couldn't find a chunk big enough: report the problem.*/
932                     {
933                         tap->a_unaloc=taxp->a_size;
934                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
935                         lkerr++;
936                     }
937                 }
938             }
939             else /*Overlay areas not in internal ram*/
940             {
941                 taxp->a_addr = addr;
942                 if (taxp->a_size > size) size = taxp->a_size;
943             }
944             taxp = taxp->a_axp;
945         }
946         /*Now set all overlayed areax to the same start address*/
947         taxp = tap->a_axp;
948         while (taxp)
949         {
950             taxp->a_addr = addr;
951             taxp = taxp->a_axp;
952         }
953     }
954     else if (tap->a_flag & A_ABS) /* Absolute sections */
955     {
956         while (taxp)
957         {
958             if (locIndex == 0)
959             {
960                 for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<256); j++)
961                 {
962                     if (idatamap[j] == ' ')
963                         idatamap[j] = 'A';
964                     else
965                         fprintf(stderr, "memory overlap at 0x%X for %s\n", j, tap->a_id);
966                 }
967             }
968             else if (locIndex == 1)
969             {
970                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
971             }
972             else if (locIndex == 2)
973             {
974                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
975             }
976             taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
977             size += taxp->a_size;
978             taxp = taxp->a_axp;
979         }
980     }
981     else /* Concatenated sections */
982     {
983         if ((locIndex == 1) && tap->a_size)
984         {
985             addr = find_empty_space(addr, tap->a_size, codemap);
986         }
987         if ((locIndex == 2) && tap->a_size)
988         {
989             addr = find_empty_space(addr, tap->a_size, xdatamap);
990         }
991         while (taxp)
992         {
993             if( (fchar=='D') || (fchar=='I') )
994             {
995                 if(taxp->a_size)
996                 {
997                     /*Search for a space large enough in internal RAM for this areax*/
998                     for(j=ramstart, k=0; j<ramlimit; j++)
999                     {
1000                         if(idatamap[j]==' ')
1001                             k++;
1002                         else
1003                             k=0;
1004                         if(k==(int)taxp->a_size)
1005                             break;
1006                     }
1007
1008                     if(k==(int)taxp->a_size)
1009                     {
1010                         taxp->a_addr = j-k+1;
1011
1012                         size += taxp->a_size;
1013
1014                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
1015                             idatamap[j]=(fchar=='D')?dchar:fchar;
1016                         if((taxp->a_size>0)&&(fchar=='D'))dchar++;
1017                         if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
1018                     }
1019                     else /*We are in trouble, there is not enough memory for an areax chunk*/
1020                     {
1021                         taxp->a_addr = addr;
1022                         addr += taxp->a_size;
1023                         size += taxp->a_size;
1024                         tap->a_unaloc+=taxp->a_size;
1025                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1026                         lkerr++;
1027                     }
1028                }
1029                taxp = taxp->a_axp;
1030             }
1031             else if(fchar=='B')
1032             {
1033                 if(taxp->a_size!=0)
1034                 {
1035                     /*Search for a space large enough in data memory for this areax*/
1036                     for(j=0x20, k=0; j<0x30; j++)
1037                     {
1038                         if(idatamap[j]==' ')
1039                             k++;
1040                         else
1041                             k=0;
1042                         if(k==(int)taxp->a_size) break;
1043                     }
1044
1045                     /*Mark the memory used*/
1046                     if(k==(int)taxp->a_size)
1047                     {
1048                         taxp->a_addr = j-k+1;
1049                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
1050                         idatamap[j]=fchar;
1051                     }
1052                     else /*Couldn't find a chunk big enough: report the problem.*/
1053                     {
1054                         tap->a_unaloc=taxp->a_size;
1055                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1056                         lkerr++;
1057                     }
1058                 }
1059                 size += taxp->a_size;
1060                 taxp = taxp->a_axp;
1061             }
1062             else /*For concatenated BIT, CODE, and XRAM areax's*/
1063             {
1064                 if((fchar=='K') && (taxp->a_size == 1))
1065                 {
1066                     taxp->a_size = 256-(addr & 0xFF);
1067                 }
1068                 //find next unused address now
1069                 if ((locIndex == 1) && taxp->a_size)
1070                 {
1071                     addr = find_empty_space(addr, taxp->a_size, codemap);
1072                     allocate_space(addr, taxp->a_size, tap->a_id, codemap);
1073                 }
1074                 if ((locIndex == 2) && taxp->a_size)
1075                 {
1076                     addr = find_empty_space(addr, taxp->a_size, xdatamap);
1077                     allocate_space(addr, taxp->a_size, tap->a_id, xdatamap);
1078                 }
1079                 taxp->a_addr = addr;
1080                 addr += taxp->a_size;
1081                 size += taxp->a_size;
1082                 taxp = taxp->a_axp;
1083             }
1084         }
1085     }
1086     tap->a_size = size;
1087
1088     if ((tap->a_flag&A_PAG) && (size > 256))
1089     {
1090         fprintf(stderr,
1091         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
1092         lkerr++;
1093     }
1094     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
1095         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
1096     {
1097         fprintf(stderr,
1098         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
1099         lkerr++;
1100     }
1101     return addr;
1102 }