608e3e151a7d079b7512f2ea34e9c117501437a7
[fw/sdcc] / as / 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 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.
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      * Place pointer in header area list
142      */
143     if (headp == NULL) {
144         fprintf(stderr, "No header defined\n");
145         lkexit(1);
146     }
147     narea = hp->h_narea;
148     halp = hp->a_list;
149     for (i=0; i < narea ;++i) {
150         if (halp[i] == NULL) {
151             halp[i] = taxp;
152             return;
153         }
154     }
155     fprintf(stderr, "Header area list overflow\n");
156     lkexit(1);
157 }
158
159 /*)Function VOID    lkparea(id)
160  *
161  *      char *  id      pointer to the area name string
162  *
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.
169  *
170  *  local variables:
171  *      area *  tap         pointer to an area structure
172  *      areax * taxp        pointer to an areax structure
173  *
174  *  global variables:
175  *      area    *ap         Pointer to the current
176  *                          area structure
177  *      area    *areap      The pointer to the first
178  *                          area structure of a linked list
179  *      areax   *axp        Pointer to the current
180  *                          areax structure
181  *
182  *  functions called:
183  *      VOID *  new()       lksym()
184  *      char *  strcpy()    c_library
185  *      int     symeq()     lksym.c
186  *
187  *  side effects:
188  *      Area and/or areax structures are created.
189  *      Failure to allocate space for created structures
190  *      will terminate the linker.
191  */
192
193 VOID
194 lkparea(char *id)
195 {
196     register struct area *tap;
197     register struct areax *taxp;
198
199     ap = areap;
200     axp = (struct areax *) new (sizeof(struct areax));
201     axp->a_addr = -1; /* default: no address yet */
202     while (ap) {
203         if (symeq(id, ap->a_id)) {
204             taxp = ap->a_axp;
205             while (taxp->a_axp)
206                 taxp = taxp->a_axp;
207             taxp->a_axp = axp;
208             axp->a_bap = ap;
209             axp->a_bhp = hp;
210             return;
211         }
212         ap = ap->a_ap;
213     }
214     ap = (struct area *) new (sizeof(struct area));
215     if (areap == NULL) {
216         areap = ap;
217     } else {
218         tap = areap;
219         while (tap->a_ap)
220             tap = tap->a_ap;
221         tap->a_ap = ap;
222     }
223     ap->a_axp = axp;
224     axp->a_bap = ap;
225     axp->a_bhp = hp;
226     strncpy(ap->a_id, id, NCPS);
227     ap->a_addr = 0;
228 }
229
230 /*)Function VOID    lnkarea()
231  *
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:
236  *
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
242  *          sections.
243  *
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.
249  *
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).
256  *
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
262  *          sections.
263  *
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.
269  *
270  *  NOTE:   Relocatable (REL) areas are 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
277  *          areax sections.
278  *
279  *
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
284  *  address specified.
285  *
286  *  The names s_<areaname> and l_<areaname> are created to
287  *  define the starting address and length of each area.
288  *
289  *  local variables:
290  *      Addr_T  rloc        ;current relocation address
291  *      char    temp[]      ;temporary string
292  *      struct symbol   *sp ;symbol structure
293  *
294  *  global variables:
295  *      area    *ap         Pointer to the current
296  *                          area structure
297  *      area    *areap      The pointer to the first
298  *                          area structure of a linked list
299  *
300  *  functions called:
301  *      int     fprintf()   c_library
302  *      VOID    lnksect()   lkarea.c
303  *      symbol *lkpsym()    lksym.c
304  *      char *  strncpy()   c_library
305  *      int     symeq()     lksym.c
306  *
307  *  side effects:
308  *      All area and areax addresses and sizes are
309  *      determined and saved in their respective
310  *      structures.
311  */
312
313 /*
314  * Resolve all area addresses.
315  */
316 VOID
317 lnkarea()
318 {
319     Addr_T rloc[4];
320     int  locIndex;
321     char temp[NCPS];
322     struct sym *sp;
323     /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
324     struct area *ta[5];
325     int j;
326
327     rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
328     ap = areap;
329     while (ap) {
330         if (ap->a_flag&A_ABS) {
331             /*
332              * Absolute sections
333              */
334             lnksect(ap);
335         } else {
336             /* Determine memory space */
337             locIndex = 0;
338             if (ap->a_flag & A_CODE) {
339                 locIndex = 1;
340             }
341             if (ap->a_flag & A_XDATA) {
342                 locIndex = 2;
343             }
344             if (ap->a_flag & A_BIT) {
345                 locIndex = 3;
346             }
347             /*
348              * Relocatable sections
349              */
350             if (ap->a_type == 0) {  /* JLH */
351                 ap->a_addr = rloc[ locIndex ];
352                 ap->a_type = 1;
353             }
354             lnksect(ap);
355             rloc[ locIndex ] = ap->a_addr + ap->a_size;
356         }
357
358         /*
359          * Create symbols called:
360          *  s_<areaname>    the start address of the area
361          *  l_<areaname>    the length of the area
362          */
363
364         if (! symeq(ap->a_id, _abs_)) {
365             strncpy(temp+2,ap->a_id,NCPS-2);
366             *(temp+1) = '_';
367
368             *temp = 's';
369             sp = lkpsym(temp, 1);
370             sp->s_addr = ap->a_addr ;
371             /* sp->s_axp = ap->a_axp;  JLH: was NULL; */
372             sp->s_type |= S_DEF;
373
374             *temp = 'l';
375             sp = lkpsym(temp, 1);
376             sp->s_addr = ap->a_size;
377             sp->s_axp = NULL;
378             sp->s_type |= S_DEF;
379
380         }
381
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 + ap->a_size + 7)/8); /*Bits to bytes*/
386         }
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"))
392         {
393             ta[4]=ap;
394             for(j=4; j>1; j--)
395             {
396                 /*If upper register banks are not used roll back the relocation counter*/
397                 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
398                 {
399                     rloc[0]-=8;
400                 }
401                 else break;
402             }
403         }
404         ap = ap->a_ap;
405     }
406 }
407
408 /*)Function VOID    lnksect()
409  *
410  *      area *  tap         pointer to an area structure
411  *
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
416  *  function.
417  *
418  *  local variables:
419  *      Addr_T  size        size of area
420  *      Addr_T  addr        address of area
421  *      areax * taxp        pointer to an areax structure
422  *
423  *  global variables:
424  *      int     lkerr       error flag
425  *
426  *  functions called:
427  *      none
428  *
429  *  side effects:
430  *      All area and areax addresses and sizes area determined
431  *      and linked into the structures.
432  */
433
434 VOID
435 lnksect(register struct area *tap)
436 {
437     register Addr_T size, addr;
438     register struct areax *taxp;
439
440     size = 0;
441     addr = tap->a_addr;
442 #if 0
443     if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
444         fprintf(stderr,
445         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
446         lkerr++;
447     }
448 #endif
449     taxp = tap->a_axp;
450     if (tap->a_flag&A_OVR) {
451         /*
452          * Overlayed sections
453          */
454         while (taxp) {
455             taxp->a_addr = addr;
456             if (taxp->a_size > size)
457                 size = taxp->a_size;
458             taxp = taxp->a_axp;
459         }
460     } else {
461         /*
462          * Concatenated sections
463          */
464         while (taxp) {
465             taxp->a_addr = addr;
466             addr += taxp->a_size;
467             size += taxp->a_size;
468             taxp = taxp->a_axp;
469         }
470     }
471     tap->a_size = size;
472     if ((tap->a_flag&A_PAG) && (size > 256)) {
473         fprintf(stderr,
474         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
475         lkerr++;
476     }
477     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
478         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
479     {
480         fprintf(stderr,
481         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
482         lkerr++;
483     }
484 }
485
486 void lnksect2 (struct area *tap, int rloc);
487 char idatamap[256];
488 long codemap[524288];
489
490 /*Modified version of the functions for packing variables in internal data memory*/
491 VOID lnkarea2 (void)
492 {
493     Addr_T rloc[4]={0, 0, 0, 0};
494     int  locIndex;
495     char temp[NCPS];
496     struct sym *sp;
497     int j;
498     struct area *dseg_ap=NULL;
499     struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
500
501     for(j=0; j<256; j++) idatamap[j]=' ';
502     memset(codemap, 0, sizeof(codemap));
503
504     ap = areap;
505     while (ap)
506     {
507         /* Determine memory space */
508              if (ap->a_flag & A_CODE)  locIndex = 1;
509         else if (ap->a_flag & A_XDATA) locIndex = 2;
510         else if (ap->a_flag & A_BIT)   locIndex = 3;
511         else locIndex = 0;
512
513         if (ap->a_flag&A_ABS) /* Absolute sections */
514         {
515             lnksect2(ap, locIndex);
516         }
517         else /* Relocatable sections */
518         {
519             if (ap->a_type == 0)
520             {
521                 ap->a_addr=rloc[locIndex];
522                 ap->a_type=1;
523             }
524
525             lnksect2(ap, locIndex);
526             rloc[locIndex] = ap->a_addr + ap->a_size;
527         }
528
529         /*
530          * Create symbols called:
531          *  s_<areaname>    the start address of the area
532          *  l_<areaname>    the length of the area
533          */
534
535         if (! symeq(ap->a_id, _abs_))
536         {
537             strncpy(temp+2,ap->a_id,NCPS-2);
538             *(temp+1) = '_';
539
540             *temp = 's';
541             sp = lkpsym(temp, 1);
542             sp->s_addr = ap->a_addr ;
543             sp->s_type |= S_DEF;
544             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
545
546             *temp = 'l';
547             sp = lkpsym(temp, 1);
548             sp->s_addr = ap->a_size;
549             sp->s_axp = NULL;
550             sp->s_type |= S_DEF;
551             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
552         }
553
554         /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
555         to compute the byte size of BSEG_BYTES: */
556         if (!strcmp(ap->a_id, "BSEG"))
557         {
558                 ap->a_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
559         }
560         else if (!strcmp(ap->a_id, "DSEG"))
561         {
562             dseg_ap=ap; /*Need it later to set its correct size*/
563         }
564         ap = ap->a_ap;
565     }
566
567     /*Compute the size of DSEG*/
568     if(dseg_ap!=NULL)
569     {
570         dseg_ap->a_addr=0;
571         dseg_ap->a_size=0;
572         for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
573     }
574     if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
575     if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
576
577 #if 0
578     /*Print the memory map*/
579     fprintf(stderr, "Internal RAM layout:\n"
580            "      0 1 2 3 4 5 6 7 8 9 A B C D E F");
581     for(j=0; j<256; j++)
582     {
583         if(j%16==0) fprintf(stderr, "\n0x%02x:|", j);
584         fprintf(stderr, "%c|", idatamap[j]);
585     }
586     fprintf(stderr, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
587 #endif
588 }
589
590 void lnksect2 (struct area *tap, int rloc)
591 {
592     register Addr_T size, addr;
593     register struct areax *taxp;
594     int j, k, ramlimit;
595     char fchar, dchar='a';
596     char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
597                   " in internal RAM for area %s.\n";
598
599     tap->a_unaloc=0;
600
601     /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
602     if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
603     {
604         if((iram_size<=0)||(iram_size>0x100))
605             ramlimit=0x100;
606         else
607             ramlimit=iram_size;
608     }
609     else
610     {
611         if((iram_size<=0)||(iram_size>0x80))
612             ramlimit=0x80;
613         else
614             ramlimit=iram_size;
615     }
616
617     size = 0;
618     addr = tap->a_addr;
619 #if 0
620     if ((tap->a_flag&A_PAG) && (addr & 0xFF))
621     {
622         fprintf(stderr,
623           "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
624         lkerr++;
625     }
626 #endif
627     taxp = tap->a_axp;
628
629     /*Use a letter to identify each area in the internal RAM layout map*/
630     if(rloc==0)
631     {
632         /**/ if(!strcmp(tap->a_id, "DSEG"))
633             fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
634         else if(!strcmp(tap->a_id, "ISEG"))
635             fchar='I';
636         else if(!strcmp(tap->a_id, "SSEG"))
637             fchar='S';
638         else if(!strcmp(tap->a_id, "OSEG"))
639             fchar='Q';
640         else if(!strcmp(tap->a_id, "REG_BANK_0"))
641             fchar='0';
642         else if(!strcmp(tap->a_id, "REG_BANK_1"))
643             fchar='1';
644         else if(!strcmp(tap->a_id, "REG_BANK_2"))
645             fchar='2';
646         else if(!strcmp(tap->a_id, "REG_BANK_3"))
647             fchar='3';
648         else if(!strcmp(tap->a_id, "BSEG_BYTES"))
649             fchar='B';
650         else if(!strcmp(tap->a_id, "BIT_BANK"))
651             fchar='T';
652         else
653             fchar=' ';/*???*/
654     }
655     else
656     {
657         fchar=' ';
658     }
659
660     if (tap->a_flag&A_OVR) /* Overlayed sections */
661     {
662         while (taxp)
663         {
664             if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
665             {
666                 addr=(fchar-'0')*8;
667                 taxp->a_addr=addr;
668                 size=taxp->a_size;
669                 for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
670                     idatamap[j]=fchar;
671             }
672             else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
673             {
674                 /*Find the size of the space currently used for this areax overlay*/
675                 for(j=0, size=0; j<ramlimit; j++)
676                     if(idatamap[j]==fchar) size++;
677
678                 if( (fchar=='S') && (stacksize==0) )
679                 {
680                    /*Search for the largest space available and use it for stack*/
681                     for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
682                     {
683                         if(idatamap[j]==' ')
684                         {
685                             if((++k)>(int)taxp->a_size) taxp->a_size=k;
686                         }
687                         else
688                         {
689                             k=0;
690                         }
691                     }
692                     stacksize=taxp->a_size;
693                 }
694
695                 /*If more space required, release the previously allocated areax in
696                 internal RAM and search for a bigger one*/
697                 if((int)taxp->a_size>size)
698                 {
699                     size=(int)taxp->a_size;
700
701                     for(j=0; j<ramlimit; j++)
702                         if(idatamap[j]==fchar) idatamap[j]=' ';
703
704                     /*Search for a space large enough in data memory for this overlay areax*/
705                     for(j=0, k=0; j<ramlimit; j++)
706                     {
707                         if(idatamap[j]==' ')
708                             k++;
709                         else
710                             k=0;
711                         if(k==(int)taxp->a_size) break;
712                     }
713
714                     if(k==(int)taxp->a_size)
715                     {
716                         taxp->a_addr = j-k+1;
717                         if(addr<(unsigned int)ramlimit)
718                         {
719                             for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
720                             if(j>=0) addr=j+1;
721                         }
722                     }
723
724                     /*Mark the memory used for overlay*/
725                     if(k==(int)taxp->a_size)
726                     {
727                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
728                             idatamap[j]=fchar;
729
730                         /*Set the new size of the data memory area*/
731                         size=ramlimit-addr;
732                     }
733                     else /*Couldn't find a chunk big enough: report the problem.*/
734                     {
735                         tap->a_unaloc=taxp->a_size;
736                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
737                         lkerr++;
738                     }
739                }
740
741                 for(j=0; j<ramlimit; j++)
742                 {
743                     if (idatamap[j]==fchar)
744                     {
745                         addr=j;
746                         tap->a_addr=addr;
747                         taxp->a_addr=addr;
748                         break;
749                     }
750                 }
751             }
752             else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
753             {
754                 /*Find the size of the space currently used for this areax overlay*/
755                 for(j=0x20, size=0; j<0x30; j++)
756                     if(idatamap[j]==fchar) size++;
757
758                 /*If more space required, release the previously allocated areax in
759                 internal RAM and search for a bigger one*/
760                 if((int)taxp->a_size>size)
761                 {
762                     size=(int)taxp->a_size;
763
764                     for(j=0x20; j<0x30; j++)
765                         if(idatamap[j]==fchar) idatamap[j]=' ';
766
767                     /*Search for a space large enough in data memory for this overlay areax*/
768                     for(j=0x20, k=0; j<0x30; j++)
769                     {
770                         if(idatamap[j]==' ')
771                             k++;
772                         else
773                             k=0;
774                         if(k==(int)taxp->a_size) break;
775                     }
776
777                     if(k==(int)taxp->a_size)
778                     {
779                         taxp->a_addr = j-k+1;
780                         if(addr<(unsigned int)0x30)
781                         {
782                             for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--);
783                             if(j>=0x20) addr=j+1;
784                         }
785                     }
786
787                     /*Mark the memory used for overlay*/
788                     if(k==(int)taxp->a_size)
789                     {
790                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
791                             idatamap[j]=fchar;
792
793                         /*Set the new size of the data memory area*/
794                         size=ramlimit-addr;
795                     }
796                     else /*Couldn't find a chunk big enough: report the problem.*/
797                     {
798                         tap->a_unaloc=taxp->a_size;
799                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
800                         lkerr++;
801                     }
802                 }
803
804                 for(j=0x20; j<0x30; j++)
805                 {
806                     if (idatamap[j]==fchar)
807                     {
808                         addr=j;
809                         tap->a_addr=addr;
810                         taxp->a_addr=addr;
811                         break;
812                     }
813                 }
814             }
815             else /*Overlay areas not in internal ram*/
816             {
817                 taxp->a_addr = addr;
818                 if (taxp->a_size > size) size = taxp->a_size;
819             }
820             taxp = taxp->a_axp;
821         }
822     }
823     else /* Concatenated sections */
824     {
825         while (taxp)
826         {
827             if( (fchar=='D') || (fchar=='I') )
828             {
829                 if(taxp->a_size)
830                 {
831                     /*Search for a space large enough in internal RAM for this areax*/
832                     for(j=0, k=0; j<ramlimit; j++)
833                     {
834                         if(idatamap[j]==' ')
835                             k++;
836                         else
837                             k=0;
838                         if(k==(int)taxp->a_size) break;
839                     }
840
841                     if(k==(int)taxp->a_size)
842                     {
843                         taxp->a_addr = j-k+1;
844                         if(addr<(unsigned int)ramlimit)
845                         {
846                             for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
847                             if(j>=0) addr=j+1;
848                             size=ramlimit-addr;
849                         }
850
851                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
852                             idatamap[j]=(fchar=='D')?dchar:fchar;
853                         if((taxp->a_size>0)&&(fchar=='D'))dchar++;
854                         if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
855                     }
856                     else /*We are in trouble, there is not enough memory for an areax chunk*/
857                     {
858                         taxp->a_addr = addr;
859                         addr += taxp->a_size;
860                         size += taxp->a_size;
861                         tap->a_unaloc+=taxp->a_size;
862                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
863                         lkerr++;
864                     }
865                }
866                taxp = taxp->a_axp;
867             }
868             else if(fchar=='B')
869             {
870                 if(taxp->a_size!=0)
871                 {
872                     for(j=addr; j<((int)(addr+taxp->a_size)); j++)
873                         idatamap[j]=fchar;
874                 }
875
876                 taxp->a_addr = addr;
877                 addr += taxp->a_size;
878                 size += taxp->a_size;
879                 taxp = taxp->a_axp;
880             }
881             else /*For concatenated BIT, CODE, and XRAM areax's*/
882             {
883                 if(!strcmp(tap->a_id, "XSTK") && (taxp->a_size == 1))
884                 {
885                     taxp->a_size = 256-(addr & 0xFF);
886                 }
887                 //should find next unused address now!!!
888                 //but let's first just warn for overlaps
889                 if (rloc == 1)
890                 {
891                     int a = addr;
892                     int i = addr >> 5;
893                     int j = (addr + taxp->a_size) >> 5;
894                     long mask = -(1 << (addr & 0x1F));
895
896                     while (i < j)
897                     {
898                         if (codemap[i] & mask)
899                         {
900                             fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id);
901                         }
902                         codemap[i++] |= mask;
903                         mask = 0xFFFFFFFF;
904                         a += 32;
905                     }
906                     mask &= (1 << ((addr + taxp->a_size) & 0x1F)) - 1;
907                     if (codemap[i] & mask)
908                     {
909                         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id);
910                     }
911                     codemap[i] |= mask;
912                 }
913                 taxp->a_addr = addr;
914                 addr += taxp->a_size;
915                 size += taxp->a_size;
916                 taxp = taxp->a_axp;
917             }
918         }
919     }
920     tap->a_size = size;
921
922     if ((tap->a_flag&A_PAG) && (size > 256))
923     {
924         fprintf(stderr,
925         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
926         lkerr++;
927     }
928     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
929         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
930     {
931         fprintf(stderr,
932         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
933         lkerr++;
934     }
935 }