deb61c99c89cf6572df42e1a02d2517259c71284
[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 tha 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(id)
191 char *id;
192 {
193         register struct area *tap;
194         register struct areax *taxp;
195
196         ap = areap;
197         axp = (struct areax *) new (sizeof(struct areax));
198         while (ap) {
199                 if (symeq(id, ap->a_id)) {
200                         taxp = ap->a_axp;
201                         while (taxp->a_axp)
202                                 taxp = taxp->a_axp;
203                         taxp->a_axp = axp;
204                         axp->a_bap = ap;
205                         axp->a_bhp = hp;
206                         return;
207                 }
208                 ap = ap->a_ap;
209         }
210         ap = (struct area *) new (sizeof(struct area));
211         if (areap == NULL) {
212                 areap = ap;
213         } else {
214                 tap = areap;
215                 while (tap->a_ap)
216                         tap = tap->a_ap;
217                 tap->a_ap = ap;
218         }
219         ap->a_axp = axp;
220         axp->a_bap = ap;
221         axp->a_bhp = hp;
222         strncpy(ap->a_id, id, NCPS);
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 ae 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()        lksysm.c
299  *              char *  strncpy()       c_library
300  *              int     symeq()         lksysm.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 /*
309  * Resolve all area addresses.
310  */
311 VOID
312 lnkarea()
313 {
314         register int rloc;
315         char temp[NCPS];
316         struct sym *sp;
317
318         rloc = 0;
319         ap = areap;
320         while (ap) {
321                 if (ap->a_flag&A_ABS) {
322                         /*
323                          * Absolute sections
324                          */
325                         lnksect(ap);
326                 } else {
327                         /*
328                          * Relocatable sections
329                          */
330                         if (ap->a_addr == 0)
331                                 ap->a_addr = rloc;
332                         lnksect(ap);
333                         rloc = ap->a_addr + ap->a_size;
334                 }
335
336                 /*
337                  * Create symbols called:
338                  *      s_<areaname>    the start address of the area
339                  *      l_<areaname>    the length of the area
340                  */
341
342                 if (! symeq(ap->a_id, _abs_)) {
343                         strncpy(temp+2,ap->a_id,NCPS-2);
344                         *(temp+1) = '_';
345
346                         *temp = 's';
347                         sp = lkpsym(temp, 1);
348                         sp->s_addr = ap->a_addr;
349                         sp->s_axp = NULL;
350                         sp->s_type |= S_DEF;
351
352                         *temp = 'l';
353                         sp = lkpsym(temp, 1);
354                         sp->s_addr = ap->a_size;
355                         sp->s_axp = NULL;
356                         sp->s_type |= S_DEF;
357                 }
358                 ap = ap->a_ap;
359         }
360 }
361
362 /*)Function     VOID    lnksect()
363  *
364  *              area *  tap             pointer to an area structure
365  *
366  *      The function lnksect() is the function called by
367  *      lnkarea() to resolve the areax addresses.  Refer
368  *      to the function lnkarea() for more detail. Pageing
369  *      boundary and length errors will be reported by this
370  *      function.
371  *
372  *      local variables:
373  *              Addr_T  size            size of area
374  *              Addr_T  addr            address of area
375  *              areax * taxp            pointer to an areax structure
376  *
377  *      global variables:
378  *              int     lkerr           error flag
379  *
380  *      functions called:
381  *              none
382  *
383  *      side effects:
384  *              All area and areax addresses and sizes area determined
385  *              and linked into the structures.
386  */
387
388 VOID
389 lnksect(tap)
390 register struct area *tap;
391 {
392         register Addr_T size, addr;
393         register struct areax *taxp;
394
395         size = 0;
396         addr = tap->a_addr;
397         if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
398             fprintf(stderr,
399             "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
400             lkerr++;
401         }
402         taxp = tap->a_axp;
403         if (tap->a_flag&A_OVR) {
404                 /*
405                  * Overlayed sections
406                  */
407                 while (taxp) {
408                         taxp->a_addr = addr;
409                         if (taxp->a_size > size)
410                                 size = taxp->a_size;
411                         taxp = taxp->a_axp;
412                 }
413         } else {
414                 /*
415                  * Concatenated sections
416                  */
417                 while (taxp) {
418                         taxp->a_addr = addr;
419                         addr += taxp->a_size;
420                         size += taxp->a_size;
421                         taxp = taxp->a_axp;
422                 }
423         }
424         tap->a_size = size;
425         if ((tap->a_flag&A_PAG) && (size > 256)) {
426             fprintf(stderr,
427             "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
428             lkerr++;
429         }
430 }