* as/link/aslink.h,
[fw/sdcc] / as / link / z80 / 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
12 #include <stdio.h>
13 #include <string.h>
14 #include "aslink.h"
15
16 /*)Module       lkarea.c
17  *
18  *      The module lkarea.c contains the functions which
19  *      create and link together all area definitions read
20  *      from the .rel file(s).
21  *
22  *      lkarea.c contains the following functions:
23  *              VOID    lnkarea()
24  *              VOID    lnksect()
25  *              VOID    lkparea()
26  *              VOID    newarea()
27  *
28  *      lkarea.c contains no global variables.
29  */
30
31 /*)Function     VOID    newarea()
32  * 
33  *      The function newarea() creates and/or modifies area
34  *      and areax structures for each A directive read from
35  *      the .rel file(s).  The function lkparea() is called
36  *      to find the area structure associated with this name.
37  *      If the area does not yet exist then a new area
38  *      structure is created and linked to any existing
39  *      linked area structures. The area flags are copied
40  *      into the area flag variable.  For each occurence of
41  *      an A directive an areax structure is created and
42  *      linked to the areax structures associated with this
43  *      area.  The size of this area section is placed into
44  *      the areax structure.  The flag value for all subsequent
45  *      area definitions for the same area are compared and
46  *      flagged as an error if they are not identical.
47  *      The areax structure created for every occurence of
48  *      an A directive is loaded with a pointer to the base
49  *      area structure and a pointer to the associated
50  *      head structure.  And finally, a pointer to this
51  *      areax structure is loaded into the list of areax
52  *      structures in the head structure.  Refer to lkdata.c
53  *      for details of the structures and their linkage.
54  *
55  *      local variables:
56  *              areax **halp            pointer to an array of pointers
57  *              int     i               counter, loop variable, value
58  *              char    id[]            id string
59  *              int     narea           number of areas in this head structure
60  *              areax * taxp            pointer to an areax structure
61  *                                      to areax structures
62  *
63  *      global variables:
64  *              area    *ap             Pointer to the current
65  *                                      area structure
66  *              areax   *axp            Pointer to the current
67  *                                      areax structure
68  *              head    *hp             Pointer to the current
69  *                                      head structure
70  *              int     lkerr           error flag
71  *
72  *      functions called:
73  *              Addr_T  eval()          lkeval.c
74  *              VOID    exit()          c_library
75  *              int     fprintf()       c_library
76  *              VOID    getid()         lklex.c
77  *              VOID    lkparea()       lkarea.c
78  *              VOID    skip()          lklex.c
79  *
80  *      side effects:
81  *              The area and areax structures are created and
82  *              linked with the appropriate head structures.
83  *              Failure to allocate area or areax structure
84  *              space will terminate the linker.  Other internal
85  *              errors most likely caused by corrupted .rel
86  *              files will also terminate the linker.
87  */
88
89 /*
90  * Create an area entry.
91  *
92  * A xxxxxx size nnnn flags mm
93  *   |           |          |
94  *   |           |          `--  ap->a_flag
95  *   |           `------------- axp->a_size
96  *   `-------------------------  ap->a_id
97  *
98  */
99 VOID
100 newarea()
101 {
102         register int i, narea;
103         struct areax *taxp;
104         struct areax **halp;
105         char id[NCPS];
106
107         /*
108          * Create Area entry
109          */
110         getid(id, -1);
111         lkparea(id);
112         /*
113          * Evaluate area size
114          */
115         skip(-1);
116         axp->a_size = eval();
117         /*
118          * Evaluate flags
119          */
120         skip(-1);
121         i = 0;
122         taxp = ap->a_axp;
123         while (taxp->a_axp) {
124                 ++i;
125                 taxp = taxp->a_axp;
126         }
127         if (i == 0) {
128                 ap->a_flag = eval();
129         } else {
130                 i = eval();
131                 if (i && (ap->a_flag != i)) {
132                     fprintf(stderr, "Conflicting flags in area %.8s\n", id);
133                     lkerr++;
134                 }
135         }
136         /*
137          * Place pointer in header area list
138          */
139         if (headp == NULL) {
140                 fprintf(stderr, "No header defined\n");
141                 lkexit(1);
142         }
143         narea = hp->h_narea;
144         halp = hp->a_list;
145         for (i=0; i < narea ;++i) {
146                 if (halp[i] == NULL) {
147                         halp[i] = taxp;
148                         return;
149                 }
150         }
151         fprintf(stderr, "Header area list overflow\n");
152         lkexit(1);
153 }
154
155 /*)Function     VOID    lkparea(id)
156  *
157  *              char *  id              pointer to the area name string
158  *
159  *      The function lkparea() searches the linked area structures
160  *      for a name match.  If the name is not found then an area
161  *      structure is created.  An areax structure is created and
162  *      appended to the areax structures linked to the area structure.
163  *      The associated base area and head structure pointers are
164  *      loaded into the areax structure.
165  *
166  *      local variables:
167  *              area *  tap             pointer to an area structure
168  *              areax * taxp            pointer to an areax structure
169  *
170  *      global variables:
171  *              area    *ap             Pointer to the current
172  *                                      area structure
173  *              area    *areap          The pointer to the first
174  *                                      area structure of a linked list
175  *              areax   *axp            Pointer to the current
176  *                                      areax structure
177  *
178  *      functions called:
179  *              VOID *  new()           lksym()
180  *              char *  strcpy()        c_library
181  *              int     symeq()         lksym.c
182  *
183  *      side effects:
184  *              Area and/or areax structures are created.
185  *              Failure to allocate space for created structures
186  *              will terminate the linker.
187  */
188
189 VOID
190 lkparea(char *id)
191 {
192         register struct area *tap;
193         register struct areax *taxp;
194
195         ap = areap;
196         axp = (struct areax *) new (sizeof(struct areax));
197         while (ap) {
198                 if (symeq(id, ap->a_id)) {
199                         taxp = ap->a_axp;
200                         while (taxp->a_axp)
201                                 taxp = taxp->a_axp;
202                         taxp->a_axp = axp;
203                         axp->a_bap = ap;
204                         axp->a_bhp = hp;
205                         return;
206                 }
207                 ap = ap->a_ap;
208         }
209         ap = (struct area *) new (sizeof(struct area));
210         if (areap == NULL) {
211                 areap = ap;
212         } else {
213                 tap = areap;
214                 while (tap->a_ap)
215                         tap = tap->a_ap;
216                 tap->a_ap = ap;
217         }
218         ap->a_axp = axp;
219         axp->a_bap = ap;
220         axp->a_bhp = hp;
221         strncpy(ap->a_id, id, NCPS);
222         ap->a_addr = 0;
223 }
224
225 /*)Function     VOID    lnkarea()
226  *
227  *      The function lnkarea() resolves all area addresses.
228  *      The function evaluates each area structure (and all
229  *      the associated areax structures) in sequence.  The
230  *      linking process supports four (4) possible area types:
231  *
232  *      ABS/OVR -       All sections (each individual areax
233  *                      section) starts at the identical base
234  *                      area address overlaying all other
235  *                      areax sections for this area.  The
236  *                      size of the area is largest of the area
237  *                      sections.
238  *
239  *      ABS/CON -       All sections (each individual areax
240  *                      section) are concatenated with the
241  *                      first section starting at the base
242  *                      area address.  The size of the area
243  *                      is the sum of the section sizes.
244  *
245  *              NOTE:   Multiple absolute (ABS) areas are
246  *                      never concatenated with each other,
247  *                      thus absolute area A and absolute area
248  *                      B will overlay each other if they begin
249  *                      at the same location (the default is
250  *                      always address 0 for absolute areas).
251  *
252  *      REL/OVR -       All sections (each individual areax
253  *                      section) starts at the identical base
254  *                      area address overlaying all other
255  *                      areax sections for this area.  The
256  *                      size of the area is largest of the area
257  *                      sections.
258  *
259  *      REL/CON -       All sections (each individual areax
260  *                      section) are concatenated with the
261  *                      first section starting at the base
262  *                      area address.  The size of the area
263  *                      is the sum of the section sizes.
264  *
265  *              NOTE:   Relocatable (REL) areas are always concatenated
266  *                      with each other, thus relocatable area B
267  *                      (defined after area A) will follow
268  *                      relocatable area A independent of the
269  *                      starting address of area A.  Within a
270  *                      specific area each areax section may be
271  *                      overlayed or concatenated with other
272  *                      areax sections.
273  *
274  *
275  *      If a base address for an area is specified then the
276  *      area will start at that address.  Any relocatable
277  *      areas defined subsequently will be concatenated to the
278  *      previous relocatable area if it does not have a base
279  *      address specified.
280  *
281  *      The names s_<areaname> and l_<areaname> are created to
282  *      define the starting address and length of each area.
283  *
284  *      local variables:
285  *              Addr_T  rloc            ;current relocation address
286  *              char    temp[]          ;temporary string
287  *              struct symbol   *sp     ;symbol structure
288  *
289  *      global variables:
290  *              area    *ap             Pointer to the current
291  *                                      area structure
292  *              area    *areap          The pointer to the first
293  *                                      area structure of a linked list
294  *
295  *      functions called:
296  *              int     fprintf()       c_library
297  *              VOID    lnksect()       lkarea.c
298  *              symbol *lkpsym()        lksym.c
299  *              char *  strncpy()       c_library
300  *              int     symeq()         lksym.c
301  *
302  *      side effects:
303  *              All area and areax addresses and sizes are
304  *              determined and saved in their respective
305  *              structures.
306  */
307
308 unsigned long codemap[2048];
309 Addr_T lnksect(register struct area *tap);
310 /*
311  * Resolve all area addresses.
312  */
313 VOID
314 lnkarea()
315 {
316         register Addr_T rloc = 0;
317         Addr_T gs_size = 0;
318         char temp[NCPS];
319         struct sym *sp;
320         struct area *abs_ap = NULL;
321         struct area *gs0_ap = NULL;
322
323         memset(codemap, 0, sizeof(codemap));
324
325         /* first sort all absolute areas to the front */
326         ap = areap;
327         /* no need to check first area, it's in front anyway */
328         while (ap && ap->a_ap)
329         {
330                 if (ap->a_ap->a_flag & A_ABS)
331                 {/* next area is absolute, move it to front,
332                     reversed sequence is no problem for absolutes */
333                         abs_ap = ap->a_ap;
334                         ap->a_ap = abs_ap->a_ap;
335                         abs_ap->a_ap = areap;
336                         areap = abs_ap;
337                 }
338                 else
339                 {
340                         ap = ap->a_ap;
341                 }
342         }
343
344         /* next accumulate all GSINITx/GSFINAL area sizes
345            into GSINIT so they stay together */
346         ap = areap;
347         while (ap)
348         {
349                 if (!strncmp(ap->a_id, "GS", 2))
350                 {/* GSxxxxx area */
351                         if (ap->a_size == 0)
352                         {
353                                 axp = ap->a_axp;
354                                 while (axp)
355                                 {
356                                         ap->a_size += axp->a_size;
357                                         axp = axp->a_axp;
358                                 }
359                         }
360                         gs_size += ap->a_size;
361                         if (!strcmp(ap->a_id, "GSINIT0"))
362                         {/* GSINIT0 area */
363                                 gs0_ap = ap;
364                         }
365                 }
366                 ap = ap->a_ap;
367         }
368         if (gs0_ap)
369                 gs0_ap->a_size = gs_size;
370
371         ap = areap;
372         while (ap)
373         {
374                 if (ap->a_flag & A_ABS) {
375                         /*
376                          * Absolute sections
377                          */
378                         lnksect(ap);
379                 } else {
380                         /*
381                          * Relocatable sections
382                          */
383                         if (ap->a_addr == 0)
384                                 ap->a_addr = rloc;
385                         rloc = lnksect(ap);
386                 }
387
388                 /*
389                  * Create symbols called:
390                  *      s_<areaname>    the start address of the area
391                  *      l_<areaname>    the length of the area
392                  */
393
394                 if (! symeq(ap->a_id, _abs_))
395                 {
396                         strncpy(temp+2,ap->a_id,NCPS-2);
397                         *(temp+1) = '_';
398
399                         *temp = 's';
400                         sp = lkpsym(temp, 1);
401                         sp->s_addr = ap->a_addr;
402                         sp->s_axp = NULL;
403                         sp->s_type |= S_DEF;
404
405                         *temp = 'l';
406                         sp = lkpsym(temp, 1);
407                         sp->s_addr = ap->a_size;
408                         sp->s_axp = NULL;
409                         sp->s_type |= S_DEF;
410                 }
411                 ap = ap->a_ap;
412         }
413 }
414
415 static
416 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
417 {
418     int i, j, k;
419     unsigned long mask, b;
420
421     while (1)
422     {
423         Addr_T a = start;
424         i = start >> 5;
425         j = (start + size) >> 5;
426         mask = -(1 << (start & 0x1F));
427
428         while (i < j)
429         {
430             if (map[i] & mask)
431             {
432                 k = 32;
433                 for (b=0x80000000; b!=0; b>>=1, k--)
434                 {
435                     if (map[i] & b)
436                       break;
437                 }
438                 start = a + k;
439                 break;
440             }
441             i++;
442             mask = 0xFFFFFFFF;
443             a += 32;
444         }
445         if (start > a)
446           continue;
447
448         mask &= (1 << ((start + size) & 0x1F)) - 1;
449         if (map[i] & mask)
450         {
451             k = 32;
452             for (b=0x80000000; b!=0; b>>=1, k--)
453             {
454                 if (map[i] & b)
455                   break;
456             }
457             start = (a & ~0x1F) + k;
458         }
459         if (start <= a)
460           break;
461     }
462     return start;
463 }
464
465 static
466 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
467 {
468     int i, j;
469     unsigned long mask;
470     Addr_T a = start;
471     i = start >> 5;
472     j = (start + size) >> 5;
473     mask = -(1 << (start & 0x1F));
474
475     while (i < j)
476     {
477         if (map[i] & mask)
478         {
479             fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
480         }
481         map[i++] |= mask;
482         mask = 0xFFFFFFFF;
483         a += 32;
484     }
485     mask &= (1 << ((start + size) & 0x1F)) - 1;
486     if (map[i] & mask)
487     {
488         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
489     }
490     map[i] |= mask;
491     return start;
492 }
493
494 /*)Function     VOID    lnksect()
495  *
496  *              area *  tap             pointer to an area structure
497  *
498  *      The function lnksect() is the function called by
499  *      lnkarea() to resolve the areax addresses.  Refer
500  *      to the function lnkarea() for more detail. Pageing
501  *      boundary and length errors will be reported by this
502  *      function.
503  *
504  *      local variables:
505  *              Addr_T  size            size of area
506  *              Addr_T  addr            address of area
507  *              areax * taxp            pointer to an areax structure
508  *
509  *      global variables:
510  *              int     lkerr           error flag
511  *
512  *      functions called:
513  *              none
514  *
515  *      side effects:
516  *              All area and areax addresses and sizes area determined
517  *              and linked into the structures.
518  */
519
520 Addr_T lnksect(register struct area *tap)
521 {
522         register Addr_T size, addr;
523         register struct areax *taxp;
524
525         size = 0;
526         addr = tap->a_addr;
527         if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
528             fprintf(stderr,
529             "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
530             lkerr++;
531         }
532
533         taxp = tap->a_axp;
534         if (tap->a_flag & A_OVR) {
535                 /*
536                  * Overlayed sections
537                  */
538                 while (taxp) {
539                         taxp->a_addr = addr;
540                         if (taxp->a_size > size)
541                                 size = taxp->a_size;
542                         taxp = taxp->a_axp;
543                 }
544         }
545         else if (tap->a_flag & A_ABS)
546         {
547                 /*
548                  * Absolute sections
549                  */
550                 while (taxp)
551                 {
552                         allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
553                         taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
554                         size += taxp->a_size;
555                         taxp = taxp->a_axp;
556                 }
557         }
558         else
559         {
560                 /*
561                  * Concatenated sections
562                  */
563                 if (tap->a_size) {
564                         addr = find_empty_space(addr, tap->a_size, codemap);
565                 }
566                 while (taxp) {
567                         //find next unused address now
568                         if (taxp->a_size)
569                         {
570                                 addr = find_empty_space(addr, taxp->a_size, codemap);
571                                 allocate_space(addr, taxp->a_size, tap->a_id, codemap);
572                         }
573                         taxp->a_addr = addr;
574                         addr += taxp->a_size;
575                         size += taxp->a_size;
576                         taxp = taxp->a_axp;
577                 }
578         }
579         tap->a_size = size;
580
581         if ((tap->a_flag & A_PAG) && (size > 256))
582         {
583             fprintf(stderr,
584             "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
585             lkerr++;
586         }
587         return addr;
588 }