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