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