* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / hc08 / 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 unsigned long codemap[2048];
328 Addr_T lnksect(struct area *tap);
329 /*
330  * Resolve all area addresses.
331  */
332 VOID
333 lnkarea()
334 {
335     Addr_T rloc[4] = {0, 0, 0, 0};
336     Addr_T gs_size = 0;
337     int  locIndex;
338     char temp[NCPS];
339     struct sym *sp;
340     /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
341     struct area *ta[5];
342     int j;
343     struct area *abs_ap = NULL;
344     struct area *gs0_ap = NULL;
345
346     memset(codemap, 0, sizeof(codemap));
347
348     /* first sort all absolute areas to the front */
349     ap = areap;
350     /* no need to check first area, it's in front anyway */
351     while (ap && ap->a_ap)
352     {
353         if (ap->a_ap->a_flag & A_ABS)
354         {/* next area is absolute, move it to front,
355             reversed sequence is no problem for absolutes */
356             abs_ap = ap->a_ap;
357             ap->a_ap = abs_ap->a_ap;
358             abs_ap->a_ap = areap;
359             areap = abs_ap;
360         }
361         else
362         {
363             ap = ap->a_ap;
364         }
365     }
366
367     /* next accumulate all GSINITx/GSFINAL area sizes
368        into GSINIT so they stay together */
369     ap = areap;
370     while (ap)
371     {
372         if (!strncmp(ap->a_id, "GS", 2))
373         {/* GSxxxxx area */
374             if (ap->a_size == 0)
375             {
376                 axp = ap->a_axp;
377                 while (axp)
378                 {
379                     ap->a_size += axp->a_size;
380                     axp = axp->a_axp;
381                 }
382             }
383             gs_size += ap->a_size;
384             if (!strcmp(ap->a_id, "GSINIT0"))
385             {/* GSINIT0 area */
386                 gs0_ap = ap;
387             }
388         }
389         ap = ap->a_ap;
390     }
391     if (gs0_ap)
392         gs0_ap->a_size = gs_size;
393
394     ap = areap;
395     while (ap) {
396         if (ap->a_flag & A_ABS) {
397             /*
398              * Absolute sections
399              */
400             lnksect(ap);
401         } else {
402             /* Determine memory space */
403             locIndex = 0;
404             #if 0
405             if (ap->a_flag & A_CODE) {
406                 locIndex = 1;
407             }
408             if (ap->a_flag & A_XDATA) {
409                 locIndex = 2;
410             }
411             if (ap->a_flag & A_BIT) {
412                 locIndex = 3;
413             }
414             #endif
415             /*
416              * Relocatable sections
417              */
418             if (ap->a_type == 0) {  /* JLH */
419                 if (ap->a_flag & A_NOLOAD) {
420                     locIndex = 2;
421                     ap->a_addr = 0;
422                 } else {
423                     ap->a_addr = rloc[ locIndex ];
424                 }
425                 ap->a_type = 1;
426             }
427
428             rloc[ locIndex ] = lnksect(ap);
429         }
430
431         /*
432          * Create symbols called:
433          *      s_<areaname>    the start address of the area
434          *      l_<areaname>    the length of the area
435          */
436
437         if (! symeq(ap->a_id, _abs_))
438         {
439             strncpy(temp+2,ap->a_id,NCPS-2);
440             *(temp+1) = '_';
441
442             *temp = 's';
443             sp = lkpsym(temp, 1);
444             sp->s_addr = ap->a_addr ;
445             /* sp->s_axp = ap->a_axp;  JLH: was NULL; */
446             sp->s_type |= S_DEF;
447
448             *temp = 'l';
449             sp = lkpsym(temp, 1);
450             sp->s_addr = ap->a_size;
451             sp->s_axp = NULL;
452             sp->s_type |= S_DEF;
453
454         }
455
456         /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
457         to compute the byte size of BSEG_BYTES: */
458         if (!strcmp(ap->a_id, "BSEG")) {
459             ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
460         }
461         else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
462         else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
463         else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
464         else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
465         else if (!strcmp(ap->a_id, "BSEG_BYTES"))
466         {
467             ta[4]=ap;
468             for(j=4; j>1; j--)
469             {
470                 /*If upper register banks are not used roll back the relocation counter*/
471                 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
472                 {
473                     rloc[0]-=8;
474                 }
475                 else break;
476             }
477         }
478         ap = ap->a_ap;
479     }
480 }
481
482 static
483 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
484 {
485     int i, j, k;
486     unsigned long mask, b;
487
488     while (1)
489     {
490         Addr_T a = start;
491         i = start >> 5;
492         j = (start + size) >> 5;
493         mask = -(1 << (start & 0x1F));
494
495         while (i < j)
496         {
497             if (map[i] & mask)
498             {
499                 k = 32;
500                 for (b=0x80000000; b!=0; b>>=1, k--)
501                 {
502                     if (map[i] & b)
503                       break;
504                 }
505                 start = a + k;
506                 break;
507             }
508             i++;
509             mask = 0xFFFFFFFF;
510             a += 32;
511         }
512         if (start > a)
513           continue;
514
515         mask &= (1 << ((start + size) & 0x1F)) - 1;
516         if (map[i] & mask)
517         {
518             k = 32;
519             for (b=0x80000000; b!=0; b>>=1, k--)
520             {
521                 if (map[i] & b)
522                   break;
523             }
524             start = (a & ~0x1F) + k;
525         }
526         if (start <= a)
527           break;
528     }
529     return start;
530 }
531
532 static
533 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
534 {
535     int i, j;
536     unsigned long mask;
537     Addr_T a = start;
538     i = start >> 5;
539     j = (start + size) >> 5;
540     mask = -(1 << (start & 0x1F));
541
542     while (i < j)
543     {
544         if (map[i] & mask)
545         {
546             fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
547         }
548         map[i++] |= mask;
549         mask = 0xFFFFFFFF;
550         a += 32;
551     }
552     mask &= (1 << ((start + size) & 0x1F)) - 1;
553     if (map[i] & mask)
554     {
555         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
556     }
557     map[i] |= mask;
558     return start;
559 }
560
561 /*)Function     VOID    lnksect()
562  *
563  *              area *  tap             pointer to an area structure
564  *
565  *      The function lnksect() is the function called by
566  *      lnkarea() to resolve the areax addresses.  Refer
567  *      to the function lnkarea() for more detail. Pageing
568  *      boundary and length errors will be reported by this
569  *      function.
570  *
571  *      local variables:
572  *              Addr_T  size            size of area
573  *              Addr_T  addr            address of area
574  *              areax * taxp            pointer to an areax structure
575  *
576  *      global variables:
577  *              int     lkerr           error flag
578  *
579  *      functions called:
580  *              none
581  *
582  *      side effects:
583  *              All area and areax addresses and sizes area determined
584  *              and linked into the structures.
585  */
586
587 Addr_T lnksect(struct area *tap)
588 {
589     register Addr_T size, addr;
590     register struct areax *taxp;
591
592     size = 0;
593     addr = tap->a_addr;
594
595     if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
596         fprintf(stderr,
597         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
598         lkerr++;
599     }
600
601     taxp = tap->a_axp;
602     if (tap->a_flag&A_OVR) {
603         /*
604          * Overlayed sections
605          */
606         while (taxp) {
607             taxp->a_addr = addr;
608             if (taxp->a_size > size)
609                 size = taxp->a_size;
610             taxp = taxp->a_axp;
611         }
612     } else if (tap->a_flag & A_ABS) {
613         /*
614          * Absolute sections
615          */
616         while (taxp) {
617             allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
618             taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
619             size += taxp->a_size;
620             taxp = taxp->a_axp;
621         }
622     } else {
623         /*
624          * Concatenated sections
625          */
626         if (tap->a_size) {
627             addr = find_empty_space(addr, tap->a_size, codemap);
628         }
629         while (taxp) {
630             //find next unused address now
631             if (taxp->a_size)
632             {
633                 addr = find_empty_space(addr, taxp->a_size, codemap);
634                 allocate_space(addr, taxp->a_size, tap->a_id, codemap);
635             }
636             taxp->a_addr = addr;
637             addr += taxp->a_size;
638             size += taxp->a_size;
639             taxp = taxp->a_axp;
640         }
641     }
642     tap->a_size = size;
643
644     if ((tap->a_flag&A_PAG) && (size > 256)) {
645         fprintf(stderr,
646         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
647         lkerr++;
648     }
649
650     return addr;
651 }