Pre 2.95-2
[fw/sdcc] / 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 <alloc.h>
15 #include "aslink.h"
16
17 /*)Module       lkarea.c
18  *
19  *      The module lkarea.c contains the functions which
20  *      create and link together all area definitions read
21  *      from the .rel file(s).
22  *
23  *      lkarea.c contains the following functions:
24  *              VOID    lnkarea()
25  *              VOID    lnksect()
26  *              VOID    lkparea()
27  *              VOID    newarea()
28  *
29  *      lkarea.c contains no global variables.
30  */
31
32 /*)Function     VOID    newarea()
33  * 
34  *      The function newarea() creates and/or modifies area
35  *      and areax structures for each A directive read from
36  *      the .rel file(s).  The function lkparea() is called
37  *      to find tha area structure associated with this name.
38  *      If the area does not yet exist then a new area
39  *      structure is created and linked to any existing
40  *      linked area structures. The area flags are copied
41  *      into the area flag variable.  For each occurence of
42  *      an A directive an areax structure is created and
43  *      linked to the areax structures associated with this
44  *      area.  The size of this area section is placed into
45  *      the areax structure.  The flag value for all subsequent
46  *      area definitions for the same area are compared and
47  *      flagged as an error if they are not identical.
48  *      The areax structure created for every occurence of
49  *      an A directive is loaded with a pointer to the base
50  *      area structure and a pointer to the associated
51  *      head structure.  And finally, a pointer to this
52  *      areax structure is loaded into the list of areax
53  *      structures in the head structure.  Refer to lkdata.c
54  *      for details of the structures and their linkage.
55  *
56  *      local variables:
57  *              areax **halp            pointer to an array of pointers
58  *              int     i               counter, loop variable, value
59  *              char    id[]            id string
60  *              int     narea           number of areas in this head structure
61  *              areax * taxp            pointer to an areax structure
62  *                                      to areax structures
63  *
64  *      global variables:
65  *              area    *ap             Pointer to the current
66  *                                      area structure
67  *              areax   *axp            Pointer to the current
68  *                                      areax structure
69  *              head    *hp             Pointer to the current
70  *                                      head structure
71  *              int     lkerr           error flag
72  *
73  *      functions called:
74  *              addr_t  eval()          lkeval.c
75  *              VOID    exit()          c_library
76  *              int     fprintf()       c_library
77  *              VOID    getid()         lklex.c
78  *              VOID    lkparea()       lkarea.c
79  *              VOID    skip()          lklex.c
80  *
81  *      side effects:
82  *              The area and areax structures are created and
83  *              linked with the appropriate head structures.
84  *              Failure to allocate area or areax structure
85  *              space will terminate the linker.  Other internal
86  *              errors most likely caused by corrupted .rel
87  *              files will also terminate the linker.
88  */
89
90 /*
91  * Create an area entry.
92  *
93  * A xxxxxx size nnnn flags mm
94  *   |           |          |
95  *   |           |          `--  ap->a_flag
96  *   |           `------------- axp->a_size
97  *   `-------------------------  ap->a_id
98  *
99  */
100 VOID
101 newarea()
102 {
103         register int i, narea;
104         struct areax *taxp;
105         struct areax **halp;
106         char id[NCPS];
107
108         /*
109          * Create Area entry
110          */
111         getid(id, -1);
112         lkparea(id);
113         /*
114          * Evaluate area size
115          */
116         skip(-1);
117         axp->a_size = eval();
118         /*
119          * Evaluate flags
120          */
121         skip(-1);
122         i = 0;
123         taxp = ap->a_axp;
124         while (taxp->a_axp) {
125                 ++i;
126                 taxp = taxp->a_axp;
127         }
128         if (i == 0) {
129                 ap->a_flag = eval();
130         } else {
131                 i = eval();
132                 if (i && (ap->a_flag != i)) {
133                     fprintf(stderr, "Conflicting flags in area %.8s\n", id);
134                     lkerr++;
135                 }
136         }
137         /*
138          * Place pointer in header area list
139          */
140         if (headp == NULL) {
141                 fprintf(stderr, "No header defined\n");
142                 lkexit(1);
143         }
144         narea = hp->h_narea;
145         halp = hp->a_list;
146         for (i=0; i < narea ;++i) {
147                 if (halp[i] == NULL) {
148                         halp[i] = taxp;
149                         return;
150                 }
151         }
152         fprintf(stderr, "Header area list overflow\n");
153         lkexit(1);
154 }
155
156 /*)Function     VOID    lkparea(id)
157  *
158  *              char *  id              pointer to the area name string
159  *
160  *      The function lkparea() searches the linked area structures
161  *      for a name match.  If the name is not found then an area
162  *      structure is created.  An areax structure is created and
163  *      appended to the areax structures linked to the area structure.
164  *      The associated base area and head structure pointers are
165  *      loaded into the areax structure.
166  *
167  *      local variables:
168  *              area *  tap             pointer to an area structure
169  *              areax * taxp            pointer to an areax structure
170  *
171  *      global variables:
172  *              area    *ap             Pointer to the current
173  *                                      area structure
174  *              area    *areap          The pointer to the first
175  *                                      area structure of a linked list
176  *              areax   *axp            Pointer to the current
177  *                                      areax structure
178  *
179  *      functions called:
180  *              VOID *  new()           lksym()
181  *              char *  strcpy()        c_library
182  *              int     symeq()         lksym.c
183  *
184  *      side effects:
185  *              Area and/or areax structures are created.
186  *              Failure to allocate space for created structures
187  *              will terminate the linker.
188  */
189
190 VOID
191 lkparea(id)
192 char *id;
193 {
194         register struct area *tap;
195         register struct areax *taxp;
196
197         ap = areap;
198         axp = (struct areax *) new (sizeof(struct areax));
199         while (ap) {
200                 if (symeq(id, ap->a_id)) {
201                         taxp = ap->a_axp;
202                         while (taxp->a_axp)
203                                 taxp = taxp->a_axp;
204                         taxp->a_axp = axp;
205                         axp->a_bap = ap;
206                         axp->a_bhp = hp;
207                         return;
208                 }
209                 ap = ap->a_ap;
210         }
211         ap = (struct area *) new (sizeof(struct area));
212         if (areap == NULL) {
213                 areap = ap;
214         } else {
215                 tap = areap;
216                 while (tap->a_ap)
217                         tap = tap->a_ap;
218                 tap->a_ap = ap;
219         }
220         ap->a_axp = axp;
221         axp->a_bap = ap;
222         axp->a_bhp = hp;
223         strncpy(ap->a_id, id, NCPS);
224 }
225
226 /*)Function     VOID    lnkarea()
227  *
228  *      The function lnkarea() resolves all area addresses.
229  *      The function evaluates each area structure (and all
230  *      the associated areax structures) in sequence.  The
231  *      linking process supports four (4) possible area types:
232  *
233  *      ABS/OVR -       All sections (each individual areax
234  *                      section) starts at the identical base
235  *                      area address overlaying all other
236  *                      areax sections for this area.  The
237  *                      size of the area is largest of the area
238  *                      sections.
239  *
240  *      ABS/CON -       All sections (each individual areax
241  *                      section) are concatenated with the
242  *                      first section starting at the base
243  *                      area address.  The size of the area
244  *                      is the sum of the section sizes.
245  *
246  *              NOTE:   Multiple absolute (ABS) areas are
247  *                      never concatenated with each other,
248  *                      thus absolute area A and absolute area
249  *                      B will overlay each other if they begin
250  *                      at the same location (the default is
251  *                      always address 0 for absolute areas).
252  *
253  *      REL/OVR -       All sections (each individual areax
254  *                      section) starts at the identical base
255  *                      area address overlaying all other
256  *                      areax sections for this area.  The
257  *                      size of the area is largest of the area
258  *                      sections.
259  *
260  *      REL/CON -       All sections (each individual areax
261  *                      section) are concatenated with the
262  *                      first section starting at the base
263  *                      area address.  The size of the area
264  *                      is the sum of the section sizes.
265  *
266  *              NOTE:   Relocatable (REL) areas ae always concatenated
267  *                      with each other, thus relocatable area B
268  *                      (defined after area A) will follow
269  *                      relocatable area A independent of the
270  *                      starting address of area A.  Within a
271  *                      specific area each areax section may be
272  *                      overlayed or concatenated with other
273  *                      areax sections.
274  *
275  *
276  *      If a base address for an area is specified then the
277  *      area will start at that address.  Any relocatable
278  *      areas defined subsequently will be concatenated to the
279  *      previous relocatable area if it does not have a base
280  *      address specified.
281  *
282  *      The names s_<areaname> and l_<areaname> are created to
283  *      define the starting address and length of each area.
284  *
285  *      local variables:
286  *              addr_t  rloc            ;current relocation address
287  *              char    temp[]          ;temporary string
288  *              struct symbol   *sp     ;symbol structure
289  *
290  *      global variables:
291  *              area    *ap             Pointer to the current
292  *                                      area structure
293  *              area    *areap          The pointer to the first
294  *                                      area structure of a linked list
295  *
296  *      functions called:
297  *              int     fprintf()       c_library
298  *              VOID    lnksect()       lkarea.c
299  *              symbol *lkpsym()        lksysm.c
300  *              char *  strncpy()       c_library
301  *              int     symeq()         lksysm.c
302  *
303  *      side effects:
304  *              All area and areax addresses and sizes are
305  *              determined and saved in their respective
306  *              structures.
307  */
308
309 /*
310  * Resolve all area addresses.
311  */
312 VOID
313 lnkarea()
314 {
315         register int rloc;
316         char temp[NCPS];
317         struct sym *sp;
318
319         rloc = 0;
320         ap = areap;
321         while (ap) {
322                 if (ap->a_flag&A_ABS) {
323                         /*
324                          * Absolute sections
325                          */
326                         lnksect(ap);
327                 } else {
328                         /*
329                          * Relocatable sections
330                          */
331                         if (ap->a_addr == 0)
332                                 ap->a_addr = rloc;
333                         lnksect(ap);
334                         rloc = ap->a_addr + ap->a_size;
335                 }
336
337                 /*
338                  * Create symbols called:
339                  *      s_<areaname>    the start address of the area
340                  *      l_<areaname>    the length of the area
341                  */
342
343                 if (! symeq(ap->a_id, _abs_)) {
344                         strncpy(temp+2,ap->a_id,NCPS-2);
345                         *(temp+1) = '_';
346
347                         *temp = 's';
348                         sp = lkpsym(temp, 1);
349                         sp->s_addr = ap->a_addr;
350                         sp->s_axp = NULL;
351                         sp->s_type |= S_DEF;
352
353                         *temp = 'l';
354                         sp = lkpsym(temp, 1);
355                         sp->s_addr = ap->a_size;
356                         sp->s_axp = NULL;
357                         sp->s_type |= S_DEF;
358                 }
359                 ap = ap->a_ap;
360         }
361 }
362
363 /*)Function     VOID    lnksect()
364  *
365  *              area *  tap             pointer to an area structure
366  *
367  *      The function lnksect() is the function called by
368  *      lnkarea() to resolve the areax addresses.  Refer
369  *      to the function lnkarea() for more detail. Pageing
370  *      boundary and length errors will be reported by this
371  *      function.
372  *
373  *      local variables:
374  *              addr_t  size            size of area
375  *              addr_t  addr            address of area
376  *              areax * taxp            pointer to an areax structure
377  *
378  *      global variables:
379  *              int     lkerr           error flag
380  *
381  *      functions called:
382  *              none
383  *
384  *      side effects:
385  *              All area and areax addresses and sizes area determined
386  *              and linked into the structures.
387  */
388
389 VOID
390 lnksect(tap)
391 register struct area *tap;
392 {
393         register addr_t size, addr;
394         register struct areax *taxp;
395
396         size = 0;
397         addr = tap->a_addr;
398         if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
399             fprintf(stderr,
400             "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
401             lkerr++;
402         }
403         taxp = tap->a_axp;
404         if (tap->a_flag&A_OVR) {
405                 /*
406                  * Overlayed sections
407                  */
408                 while (taxp) {
409                         taxp->a_addr = addr;
410                         if (taxp->a_size > size)
411                                 size = taxp->a_size;
412                         taxp = taxp->a_axp;
413                 }
414         } else {
415                 /*
416                  * Concatenated sections
417                  */
418                 while (taxp) {
419                         taxp->a_addr = addr;
420                         addr += taxp->a_size;
421                         size += taxp->a_size;
422                         taxp = taxp->a_axp;
423                 }
424         }
425         tap->a_size = size;
426         if ((tap->a_flag&A_PAG) && (size > 256)) {
427             fprintf(stderr,
428             "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
429             lkerr++;
430         }
431 }