95e5a8aca30342737811bd3a0a0e60a261837160
[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 VOID lnksect(register struct area *tap);
311 /*
312  * Resolve all area addresses.
313  */
314 VOID
315 lnkarea()
316 {
317         register Addr_T rloc = 0;
318 //        Addr_T gs_size = 0;
319         char temp[NCPS];
320         struct sym *sp;
321 #if 0
322         struct area *abs_ap = NULL;
323         struct area *gs0_ap = NULL;
324
325         memset(codemap, 0, sizeof(codemap));
326
327         /* first sort all absolute areas to the front */
328         ap = areap;
329         /* no need to check first area, it's in front anyway */
330         while (ap && ap->a_ap)
331         {
332                 if (ap->a_ap->a_flag & A_ABS)
333                 {/* next area is absolute, move it to front,
334                     reversed sequence is no problem for absolutes */
335                         abs_ap = ap->a_ap;
336                         ap->a_ap = abs_ap->a_ap;
337                         abs_ap->a_ap = areap;
338                         areap = abs_ap;
339                 }
340                 else
341                 {
342                         ap = ap->a_ap;
343                 }
344         }
345
346         /* next accumulate all GSINITx/GSFINAL area sizes
347            into GSINIT so they stay together */
348         ap = areap;
349         while (ap)
350         {
351                 if (!strncmp(ap->a_id, "GS", 2))
352                 {/* GSxxxxx area */
353                         if (ap->a_size == 0)
354                         {
355                                 axp = ap->a_axp;
356                                 while (axp)
357                                 {
358                                         ap->a_size += axp->a_size;
359                                         axp = axp->a_axp;
360                                 }
361                         }
362                         gs_size += ap->a_size;
363                         if (!strcmp(ap->a_id, "GSINIT0"))
364                         {/* GSINIT0 area */
365                                 gs0_ap = ap;
366                         }
367                 }
368                 ap = ap->a_ap;
369         }
370         if (gs0_ap)
371                 gs0_ap->a_size = gs_size;
372 #endif
373         ap = areap;
374         while (ap)
375         {
376                 if (ap->a_flag & A_ABS) {
377                         /*
378                          * Absolute sections
379                          */
380                         lnksect(ap);
381                 } else {
382                         /*
383                          * Relocatable sections
384                          */
385                         if (ap->a_addr == 0)
386                                 ap->a_addr = rloc;
387 //                        rloc = lnksect(ap);
388                         lnksect(ap);
389                         rloc = ap->a_addr + ap->a_size;
390                 }
391
392                 /*
393                  * Create symbols called:
394                  *      s_<areaname>    the start address of the area
395                  *      l_<areaname>    the length of the area
396                  */
397
398                 if (! symeq(ap->a_id, _abs_))
399                 {
400                         strncpy(temp+2,ap->a_id,NCPS-2);
401                         *(temp+1) = '_';
402
403                         *temp = 's';
404                         sp = lkpsym(temp, 1);
405                         sp->s_addr = ap->a_addr;
406                         sp->s_axp = NULL;
407                         sp->s_type |= S_DEF;
408
409                         *temp = 'l';
410                         sp = lkpsym(temp, 1);
411                         sp->s_addr = ap->a_size;
412                         sp->s_axp = NULL;
413                         sp->s_type |= S_DEF;
414                 }
415                 ap = ap->a_ap;
416         }
417 }
418 #if 0
419 static
420 Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
421 {
422     int i, j, k;
423     unsigned long mask, b;
424
425     while (1)
426     {
427         Addr_T a = start;
428         i = start >> 5;
429         j = (start + size) >> 5;
430         mask = -(1 << (start & 0x1F));
431
432         while (i < j)
433         {
434             if (map[i] & mask)
435             {
436                 k = 32;
437                 for (b=0x80000000; b!=0; b>>=1, k--)
438                 {
439                     if (map[i] & b)
440                       break;
441                 }
442                 start = a + k;
443                 break;
444             }
445             i++;
446             mask = 0xFFFFFFFF;
447             a += 32;
448         }
449         if (start > a)
450           continue;
451
452         mask &= (1 << ((start + size) & 0x1F)) - 1;
453         if (map[i] & mask)
454         {
455             k = 32;
456             for (b=0x80000000; b!=0; b>>=1, k--)
457             {
458                 if (map[i] & b)
459                   break;
460             }
461             start = (a & ~0x1F) + k;
462         }
463         if (start <= a)
464           break;
465     }
466     return start;
467 }
468
469 static
470 Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
471 {
472     int i, j;
473     unsigned long mask;
474     Addr_T a = start;
475     i = start >> 5;
476     j = (start + size) >> 5;
477     mask = -(1 << (start & 0x1F));
478
479     while (i < j)
480     {
481         if (map[i] & mask)
482         {
483             fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
484         }
485         map[i++] |= mask;
486         mask = 0xFFFFFFFF;
487         a += 32;
488     }
489     mask &= (1 << ((start + size) & 0x1F)) - 1;
490     if (map[i] & mask)
491     {
492         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
493     }
494     map[i] |= mask;
495     return start;
496 }
497 #endif
498 /*)Function     VOID    lnksect()
499  *
500  *              area *  tap             pointer to an area structure
501  *
502  *      The function lnksect() is the function called by
503  *      lnkarea() to resolve the areax addresses.  Refer
504  *      to the function lnkarea() for more detail. Pageing
505  *      boundary and length errors will be reported by this
506  *      function.
507  *
508  *      local variables:
509  *              Addr_T  size            size of area
510  *              Addr_T  addr            address of area
511  *              areax * taxp            pointer to an areax structure
512  *
513  *      global variables:
514  *              int     lkerr           error flag
515  *
516  *      functions called:
517  *              none
518  *
519  *      side effects:
520  *              All area and areax addresses and sizes area determined
521  *              and linked into the structures.
522  */
523
524 VOID lnksect(register struct area *tap)
525 //Addr_T lnksect(register struct area *tap)
526 {
527         register Addr_T size, addr;
528         register struct areax *taxp;
529
530         size = 0;
531         addr = tap->a_addr;
532         if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
533             fprintf(stderr,
534             "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
535             lkerr++;
536         }
537
538         taxp = tap->a_axp;
539         if (tap->a_flag & A_OVR) {
540                 /*
541                  * Overlayed sections
542                  */
543                 while (taxp) {
544                         taxp->a_addr = addr;
545                         if (taxp->a_size > size)
546                                 size = taxp->a_size;
547                         taxp = taxp->a_axp;
548                 }
549         }
550 #if 0
551         else if (tap->a_flag & A_ABS)
552         {
553                 /*
554                  * Absolute sections
555                  */
556                 while (taxp)
557                 {
558                         allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
559                         taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
560                         size += taxp->a_size;
561                         taxp = taxp->a_axp;
562                 }
563         }
564 #endif
565         else
566         {
567                 /*
568                  * Concatenated sections
569                  */
570 /*
571                 if (tap->a_size) {
572                         addr = find_empty_space(addr, tap->a_size, codemap);
573                 }
574 */
575                 while (taxp) {
576 /*
577                         //find next unused address now
578                         if (taxp->a_size)
579                         {
580                                 addr = find_empty_space(addr, taxp->a_size, codemap);
581                                 allocate_space(addr, taxp->a_size, tap->a_id, codemap);
582                         }
583 */
584                         taxp->a_addr = addr;
585                         addr += taxp->a_size;
586                         size += taxp->a_size;
587                         taxp = taxp->a_axp;
588                 }
589         }
590         tap->a_size = size;
591
592         if ((tap->a_flag & A_PAG) && (size > 256))
593         {
594             fprintf(stderr,
595             "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
596             lkerr++;
597         }
598 //        return addr;
599 }