1 /* lkarea.c */
2 
3 /*
4  *  Copyright (C) 1989-2009  Alan R. Baldwin
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * Alan R. Baldwin
21  * 721 Berkeley St.
22  * Kent, Ohio  44240
23  */
24 
25 /*
26  * 02-Apr-98 JLH: add code to link 8051 data spaces
27  */
28 
29 #include "aslink.h"
30 
31 /*)Module       lkarea.c
32  *
33  *      The module lkarea.c contains the functions which
34  *      create and link together all area definitions read
35  *      from the .rel file(s).
36  *
37  *      lkarea.c contains the following functions:
38  *              VOID    lnkarea()
39  *              VOID    lnksect()
40  *              VOID    lkparea()
41  *              VOID    newarea()
42  *              VOID    setarea()
43  *
44  *      lkarea.c contains no global variables.
45  */
46 
47 /*)Function VOID        newarea()
48  *
49  *      The function newarea() creates and/or modifies area
50  *      and areax structures for each A directive read from
51  *      the .rel file(s).  The function lkparea() is called
52  *      to find the area structure associated with this name.
53  *      If the area does not yet exist then a new area
54  *      structure is created and linked to any existing
55  *      linked area structures. The area flags are copied
56  *      into the area flag variable.  For each occurence of
57  *      an A directive an areax structure is created and
58  *      linked to the areax structures associated with this
59  *      area.  The size of this area section is placed into
60  *      the areax structure.  The flag value for all subsequent
61  *      area definitions for the same area are compared and
62  *      flagged as an error if they are not identical.
63  *      The areax structure created for every occurence of
64  *      an A directive is loaded with a pointer to the base
65  *      area structure and a pointer to the associated
66  *      head structure.  And finally, a pointer to this
67  *      areax structure is loaded into the list of areax
68  *      structures in the head structure.  Refer to lkdata.c
69  *      for details of the structures and their linkage.
70  *
71  *      local variables:
72  *              areax **halp            pointer to an array of pointers
73  *              a_uint  i               value
74  *              char    id[]            id string
75  *              int     k               counter, loop variable
76  *              int     narea           number of areas in this head structure
77  *              areax * taxp            pointer to an areax structure
78  *                                      to areax structures
79  *
80  *      global variables:
81  *              area    *ap             Pointer to the current
82  *                                      area structure
83  *              areax   *axp            Pointer to the current
84  *                                      areax structure
85  *              head    *hp             Pointer to the current
86  *                                      head structure
87  *              int     lkerr           error flag
88  *
89  *      functions called:
90  *              a_uint  eval()          lkeval.c
91  *              VOID    exit()          c_library
92  *              int     fprintf()       c_library
93  *              VOID    getid()         lklex.c
94  *              VOID    lkparea()       lkarea.c
95  *              VOID    skip()          lklex.c
96  *
97  *      side effects:
98  *              The area and areax structures are created and
99  *              linked with the appropriate head structures.
100  *              Failure to allocate area or areax structure
101  *              space will terminate the linker.  Other internal
102  *              errors most likely caused by corrupted .rel
103  *              files will also terminate the linker.
104  */
105 
106 /*
107  * Create an area entry.
108  *
109  * A xxxxxx size nnnn flags mm bank n
110  *   |           |          |       |
111  *   |           |          |       `--  ap->a_bank
112  *   |           |          `----------  ap->a_flag
113  *   |           `--------------------- axp->a_size
114  *   `---------------------------------  ap->a_id
115  *
116  */
117 VOID
newarea(void)118 newarea(void)
119 {
120         a_uint i;
121         int k, narea;
122         struct areax *taxp;
123         struct areax **halp;
124         char id[NCPS];
125 
126         if (headp == NULL) {
127                 fprintf(stderr, "No header defined\n");
128                 lkexit(ER_FATAL);
129         }
130         /*
131          * Create Area entry
132          */
133         getid(id, -1);
134         lkparea(id);
135         /*
136          * Evaluate area size
137          */
138         skip(-1);
139         axp->a_size = eval();
140         /*
141          * Evaluate flags
142          */
143         skip(-1);
144         i = 0;
145         taxp = ap->a_axp;
146         while (taxp->a_axp) {
147                 ++i;
148                 taxp = taxp->a_axp;
149         }
150         if (i == 0) {
151                 ap->a_flag = eval();
152         } else {
153                 i = eval();
154                 if ((!is_sdld() || TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB) &&
155                         i && (ap->a_flag != i)) {
156                         fprintf(stderr, "Conflicting flags in area %8s\n", id);
157                         lkerr++;
158                 }
159         }
160         if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB)) {
161                 /*
162                  * Evaluate area address
163                  */
164                 skip(-1);
165                 axp->a_addr = eval();
166         }
167         /*
168          * Place pointer in header area list
169          */
170         narea = hp->h_narea;
171         halp = hp->a_list;
172         for (k=0; k < narea ;++k) {
173                 if (halp[k] == NULL) {
174                         halp[k] = taxp;
175                         return;
176                 }
177         }
178         fprintf(stderr, "Header area list overflow\n");
179         lkexit(ER_FATAL);
180 }
181 
182 /*)Function     VOID    lkparea(id)
183  *
184  *              char *  id              pointer to the area name string
185  *
186  *      The function lkparea() searches the linked area structures
187  *      for a name match.  If the name is not found then an area
188  *      structure is created.  An areax structure is created and
189  *      appended to the areax structures linked to the area structure.
190  *      The associated base area and head structure pointers are
191  *      loaded into the areax structure.
192  *
193  *      local variables:
194  *              area *  tap             pointer to an area structure
195  *              areax * taxp            pointer to an areax structure
196  *
197  *      global variables:
198  *              area    *ap             Pointer to the current
199  *                                      area structure
200  *              area    *areap          The pointer to the first
201  *                                      area structure of a linked list
202  *              areax   *axp            Pointer to the current
203  *                                      areax structure
204  *
205  *      functions called:
206  *              VOID *  new()           lksym()
207  *              char *  strsto()        lksym.c
208  *              int     symeq()         lksym.c
209  *
210  *      side effects:
211  *              Area and/or areax structures are created.
212  *              Failure to allocate space for created structures
213  *              will terminate the linker.
214  */
215 
216 VOID
lkparea(char * id)217 lkparea(char *id)
218 {
219         struct area *tap;
220         struct areax *taxp;
221 
222         ap = areap;
223         axp = (struct areax *) new (sizeof(struct areax));
224         if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB))
225                 axp->a_addr = -1; /* default: no address yet */
226         while (ap) {
227                 if (symeq(id, ap->a_id, 1)) {
228                         taxp = ap->a_axp;
229                         while (taxp->a_axp)
230                                 taxp = taxp->a_axp;
231                         taxp->a_axp = axp;
232                         axp->a_bap = ap;
233                         axp->a_bhp = hp;
234                         return;
235                 }
236                 ap = ap->a_ap;
237         }
238         ap = (struct area *) new (sizeof(struct area));
239         if (areap == NULL) {
240                 areap = ap;
241         } else {
242                 tap = areap;
243                 while (tap->a_ap)
244                         tap = tap->a_ap;
245                 tap->a_ap = ap;
246         }
247         ap->a_axp = axp;
248         axp->a_bap = ap;
249         axp->a_bhp = hp;
250         ap->a_id = strsto(id);
251         if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB))
252                 ap->a_addr = 0;
253 }
254 
255 /*)Function     VOID    lnkarea()
256  *
257  *      The function lnkarea() resolves all area addresses.
258  *      The function evaluates each area structure (and all
259  *      the associated areax structures) in sequence.  The
260  *      linking process supports four (4) possible area types:
261  *
262  *      ABS/OVR -       All sections (each individual areax
263  *                      section) starts at the identical base
264  *                      area address overlaying all other
265  *                      areax sections for this area.  The
266  *                      size of the area is largest of the area
267  *                      sections.
268  *
269  *      ABS/CON -       All sections (each individual areax
270  *                      section) are concatenated with the
271  *                      first section starting at the base
272  *                      area address.  The size of the area
273  *                      is the sum of the section sizes.
274  *
275  *      NOTE:           Multiple absolute (ABS) areas are
276  *                      never concatenated with each other,
277  *                      thus absolute area A and absolute area
278  *                      B will overlay each other if they begin
279  *                      at the same location (the default is
280  *                      always address 0 for absolute areas).
281  *
282  *      REL/OVR -       All sections (each individual areax
283  *                      section) starts at the identical base
284  *                      area address overlaying all other
285  *                      areax sections for this area.  The
286  *                      size of the area is largest of the area
287  *                      sections.
288  *
289  *      REL/CON -       All sections (each individual areax
290  *                      section) are concatenated with the
291  *                      first section starting at the base
292  *                      area address.  The size of the area
293  *                      is the sum of the section sizes.
294  *
295  *              NOTE:   Relocatable (REL) areas are always concatenated
296  *                      with each other, thus relocatable area B
297  *                      (defined after area A) will follow
298  *                      relocatable area A independent of the
299  *                      starting address of area A.  Within a
300  *                      specific area each areax section may be
301  *                      overlayed or concatenated with other
302  *                      areax sections.
303  *
304  *
305  *      If a base address for an area is specified then the
306  *      area will start at that address.  Any relocatable
307  *      areas defined subsequently will be concatenated to the
308  *      previous relocatable area if it does not have a base
309  *      address specified.
310  *
311  *      The names s_<areaname> and l_<areaname> are created to
312  *      define the starting address and length of each area.
313  *
314  *      local variables:
315  *              a_uint  rloc            ;current relocation address
316  *              char    temp[]          ;temporary string
317  *              struct symbol   *sp     ;symbol structure
318  *
319  *      global variables:
320  *              area    *ap             Pointer to the current
321  *                                      area structure
322  *              area    *areap          The pointer to the first
323  *                                      area structure of a linked list
324  *
325  *      functions called:
326  *              int     fprintf()       c_library
327  *              VOID    lnksect()       lkarea.c
328  *              symbol *lkpsym()        lksysm.c
329  *              char *  strncpy()       c_library
330  *              int     symeq()         lksysm.c
331  *
332  *      side effects:
333  *              All area and areax addresses and sizes are
334  *              determined and saved in their respective
335  *              structures.
336  */
337 
338 /* sdld6808 specific */
339 unsigned long codemap6808[2048];
340 /* end sdld6808 specific */
341 /* sdld specific */
342 VOID lnksect(struct area *tap);
343 /* end sdld specific */
344 /*
345  * Resolve all bank/area addresses.
346  */
347 VOID
lnkarea(void)348 lnkarea(void)
349 {
350         /* sdld specific */
351         a_uint rloc[4] = { 0, 0, 0, 0 };
352         int  locIndex;
353         /* end sdld specific */
354         /* sdld8051 & sdld6808 specific */
355         /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
356         struct area *ta[5];
357         int j;
358         /* end sdld8051 & sdld6808 specific */
359         /* sdld6800 specific */
360         a_uint gs_size = 0;
361         struct area *abs_ap = NULL;
362         struct area *gs0_ap = NULL;
363         /* end sdld6800 specific */
364         char temp[NCPS+2];
365         struct sym *sp;
366 
367         if (TARGET_IS_6808) {
368                 memset(codemap6808, 0, sizeof(codemap6808));
369 
370                 /* first sort all absolute areas to the front */
371                 ap = areap;
372                 /* no need to check first area, it's in front anyway */
373                 while (ap && ap->a_ap) {
374                         if (ap->a_ap->a_flag & A3_ABS)
375                         {/* next area is absolute, move it to front,
376                                 reversed sequence is no problem for absolutes */
377                                 abs_ap = ap->a_ap;
378                                 ap->a_ap = abs_ap->a_ap;
379                                 abs_ap->a_ap = areap;
380                                 areap = abs_ap;
381                         }
382                         else {
383                                 ap = ap->a_ap;
384                         }
385                 }
386 
387                 /* next accumulate all GSINITx/GSFINAL area sizes
388                    into GSINIT so they stay together */
389                 ap = areap;
390                 while (ap) {
391                         if (!strncmp(ap->a_id, "GS", 2))
392                         {/* GSxxxxx area */
393                                 if (ap->a_size == 0)
394                                 {
395                                         axp = ap->a_axp;
396                                         while (axp)
397                                         {
398                                                 ap->a_size += axp->a_size;
399                                                 axp = axp->a_axp;
400                                         }
401                                 }
402                                 gs_size += ap->a_size;
403                                 if (!strcmp(ap->a_id, "GSINIT0"))
404                                 {/* GSINIT0 area */
405                                         gs0_ap = ap;
406                                 }
407                         }
408                         ap = ap->a_ap;
409                 }
410                 if (gs0_ap)
411                         gs0_ap->a_size = gs_size;
412         }
413 
414         ap = areap;
415         while (ap) {
416                 if (ap->a_flag & A3_ABS) {
417                         /*
418                          * Absolute sections
419                          */
420                         lnksect(ap);
421                 } else {
422                         /* sdld specific */
423                         /* Determine memory space */
424                         locIndex = 0;
425                         if ((TARGET_IS_8051)) {
426                                 if (ap->a_flag & A_CODE) {
427                                         locIndex = 1;
428                                 }
429                                 if (ap->a_flag & A_XDATA) {
430                                         locIndex = 2;
431                                 }
432                                 if (ap->a_flag & A_BIT) {
433                                         locIndex = 3;
434                                 }
435                         }
436                         /*
437                          * Relocatable sections
438                          */
439                         if (!is_sdld() || TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB) {
440                                 if (ap->a_addr == 0)
441                                         ap->a_addr = rloc[locIndex];
442                         }
443                         else if (ap->a_bset == 0) {
444                                 if ((TARGET_IS_6808 || TARGET_IS_STM8) && ap->a_flag & A_NOLOAD) {
445                                         locIndex = 2;
446                                         ap->a_addr = 0;
447                                 }
448                                 else {
449                                         ap->a_addr = rloc[locIndex];
450                                 }
451                                 ap->a_bset = 1;
452                         }
453                         lnksect(ap);
454                         rloc[ locIndex ] = ap->a_addr + ap->a_size;
455                         /* end sdld specific */
456                 }
457 
458                 /*
459                  * Create symbols called:
460                  *      s_<areaname>    the start address of the area
461                  *      l_<areaname>    the length of the area
462                  */
463 
464                 if (! symeq(ap->a_id, _abs_, 1)) {
465                         strcpy(temp+2, ap->a_id);
466                         *(temp+1) = '_';
467 
468                         *temp = 's';
469                         sp = lkpsym(temp, 1);
470                         sp->s_addr = ap->a_addr;
471                         if (!is_sdld() || TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB)
472                                 sp->s_axp = NULL;
473                         sp->s_type |= S_DEF;
474 
475                         *temp = 'l';
476                         sp = lkpsym(temp, 1);
477                         sp->s_addr = ap->a_size;
478                         sp->s_axp = NULL;
479                         sp->s_type |= S_DEF;
480                 }
481 
482                 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_Z180 || TARGET_IS_GB)) {
483                         /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
484                         to compute the byte size of BSEG_BYTES: */
485                         if (!strcmp(ap->a_id, "BSEG")) {
486                                 if (TARGET_IS_8051)
487                                         ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
488                                 else
489                                         ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
490                         }
491                         else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
492                         else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
493                         else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
494                         else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
495                         else if (!strcmp(ap->a_id, "BSEG_BYTES"))
496                         {
497                                 ta[4]=ap;
498                                 for(j=4; j>1; j--)
499                                 {
500                                         /*If upper register banks are not used roll back the relocation counter*/
501                                         if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
502                                         {
503                                                 rloc[0]-=8;
504                                         }
505                                         else break;
506                                 }
507                         }
508                 }
509                 ap = ap->a_ap;
510         }
511 }
512 
513 /* sdld specific */
514 static
find_empty_space(a_uint start,a_uint size,char * id,unsigned long * map,unsigned int map_size)515 a_uint find_empty_space(a_uint start, a_uint size, char *id, unsigned long *map, unsigned int map_size)
516 {
517         a_uint i, j, k;
518         unsigned long mask, b;
519         map_size /= sizeof(*map); /* Convert from bytes to number of elements */
520 
521         while (1) {
522                 a_uint a = start;
523                 i = start >> 5;
524                 j = (start + size) >> 5;
525                 mask = -(1 << (start & 0x1F));
526 
527                 if (j > map_size) {
528                         fprintf(stderr, "internal memory limit is exceeded for %s; memory size = 0x%06X, address = 0x%06X\n", id, map_size << 5, start + size - 1);
529                         break;
530                 }
531                 else {
532                         while (i < j) {
533                                 if (map[i] & mask) {
534                                         k = 32;
535                                         for (b=0x80000000; b!=0; b>>=1, k--) {
536                                                 if (map[i] & b)
537                                                         break;
538                                         }
539                                         start = a + k;
540                                         break;
541                                 }
542                                 i++;
543                                 mask = 0xFFFFFFFF;
544                                 a += 32;
545                         }
546                         if (start > a)
547                                 continue;
548 
549                         mask &= (1 << ((start + size) & 0x1F)) - 1;
550                         if (i < map_size && map[i] & mask) {
551                                 k = 32;
552                                 for (b=0x80000000; b!=0; b>>=1, k--) {
553                                         if (map[i] & b)
554                                                 break;
555                                 }
556                                 start = (a & ~0x1F) + k;
557                         }
558                         if (start <= a)
559                                 break;
560                 }
561         }
562         return start;
563 }
564 
565 static
allocate_space(a_uint start,a_uint size,char * id,unsigned long * map,unsigned int map_size)566 a_uint allocate_space(a_uint start, a_uint size, char *id, unsigned long *map,  unsigned int map_size)
567 {
568         a_uint i, j;
569         unsigned long mask;
570         a_uint a = start;
571         i = start >> 5;
572         j = (start + size) >> 5;
573         mask = -(1 << (start & 0x1F));
574         map_size /= sizeof(*map); /* Convert from bytes to number of elements */
575 
576         if (j > map_size) {
577                 fprintf(stderr, "internal memory limit is exceeded for %s; memory size = 0x%06X, address = 0x%06X\n", id, map_size << 5, start + size - 1);
578         }
579         else {
580                 while (i < j) {
581                         if (map[i] & mask) {
582                                 fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
583                         }
584                         map[i++] |= mask;
585                         mask = 0xFFFFFFFF;
586                         a += 32;
587                 }
588                 mask &= (1 << ((start + size) & 0x1F)) - 1;
589                 if (i < map_size && map[i] & mask) {
590                         fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
591                 }
592                 map[i] |= mask;
593         }
594         return start;
595 }
596 /* end sdld specific */
597 
598 /*)Function VOID        lnksect(tap)
599  *
600  *              area *  tap                     pointer to an area structure
601  *
602  *      The function lnksect() is the function called by
603  *      lnkarea() to resolve the areax addresses.  Refer
604  *      to the function lnkarea() for more detail. Pageing
605  *      boundary and length errors will be reported by this
606  *      function.
607  *
608  *      local variables:
609  *              a_uint  size            size of area
610  *              a_uint  addr            address of area
611  *              areax * taxp            pointer to an areax structure
612  *
613  *      global variables:
614  *              int             lkerr           error flag
615  *
616  *      functions called:
617  *              none
618  *
619  *      side effects:
620  *              All area and areax addresses and sizes are determined
621  *              and linked into the structures.
622  */
623 
624 VOID
lnksect(struct area * tap)625 lnksect(struct area *tap)
626 {
627         a_uint size, addr;
628         struct areax *taxp;
629 
630         size = 0;
631         addr = tap->a_addr;
632         taxp = tap->a_axp;
633         if (tap->a_flag & A3_OVR) {
634                 /*
635                  * Overlayed sections
636                  */
637                 while (taxp) {
638                         taxp->a_addr = addr;
639                         if (taxp->a_size > size)
640                                 size = taxp->a_size;
641                         taxp = taxp->a_axp;
642                 }
643         } else if (TARGET_IS_6808 && tap->a_flag & A3_ABS) {
644                 /*
645                  * Absolute sections
646                  */
647                 while (taxp) {
648                         allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap6808, sizeof (codemap6808));
649                         taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
650                         size += taxp->a_size;
651                         taxp = taxp->a_axp;
652                 }
653         } else {
654                 /*
655                  * Concatenated sections
656                  */
657                 if (TARGET_IS_6808 && tap->a_size && !(ap->a_flag & A_NOLOAD)) {
658                         addr = find_empty_space(addr, tap->a_size, tap->a_id, codemap6808, sizeof (codemap6808));
659                 }
660                 while (taxp) {
661                         /* find next unused address now */
662                         if (TARGET_IS_6808 && taxp->a_size && !(ap->a_flag & A_NOLOAD)) {
663                                 addr = find_empty_space(addr, taxp->a_size, tap->a_id, codemap6808, sizeof (codemap6808));
664                                 allocate_space(addr, taxp->a_size, tap->a_id, codemap6808, sizeof (codemap6808));
665                         }
666                         taxp->a_addr = addr;
667                         addr += taxp->a_size;
668                         size += taxp->a_size;
669                         taxp = taxp->a_axp;
670                 }
671         }
672         tap->a_size = size;
673         tap->a_addr = tap->a_axp->a_addr;
674         for (taxp = tap->a_axp; taxp && !taxp->a_size; taxp = taxp->a_axp)
675         {
676         }
677         if (taxp)
678         {
679                 tap->a_addr = taxp->a_addr;
680         }
681 
682         if ((tap->a_flag & A3_PAG) && (size > 256)) {
683                 fprintf(stderr,
684                         "\n?ASlink-Warning-Paged Area %s Length Error\n",
685                         tap->a_id);
686                 lkerr++;
687         }
688         if (TARGET_IS_8051 &&
689                 (tap->a_flag & A3_PAG) && (tap->a_size) &&
690                 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
691         {
692                 fprintf(stderr,
693                         "\n?ASlink-Warning-Paged Area %s Boundary Error\n",
694                         tap->a_id);
695                 lkerr++;
696         }
697 }
698 
699 
700 /*)Function     VOID    setarea()
701  *
702  *      The function setarea() scans the base address lines in the
703  *      basep structure, evaluates the arguments, and sets the beginning
704  *      address of the specified areas.
705  *
706  *      local variables:
707  *              a_uint  v               expression value
708  *              char    id[]            base id string
709  *
710  *      global variables:
711  *              area    *ap             Pointer to the current
712  *                                      area structure
713  *              area    *areap          The pointer to the first
714  *                                      area structure of a linked list
715  *              base    *basep          The pointer to the first
716  *                                      base structure
717  *              base    *bsp            Pointer to the current
718  *                                      base structure
719  *              char    *ip             pointer into the REL file
720  *                                      text line in ib[]
721  *              int     lkerr           error flag
722  *
723  *       functions called:
724  *              a_uint  expr()          lkeval.c
725  *              int     fprintf()       c_library
726  *              VOID    getid()         lklex.c
727  *              int     getnb()         lklex.c
728  *              int     symeq()         lksym.c
729  *
730  *      side effects:
731  *              The base address of an area is set.
732  */
733 
734 VOID
setarea(void)735 setarea(void)
736 {
737         a_uint v;
738         char id[NCPS];
739 
740         bsp = basep;
741         while (bsp) {
742                 ip = bsp->b_strp;
743                 getid(id, -1);
744                 if (getnb() == '=') {
745                         v = expr(0);
746                         for (ap = areap; ap != NULL; ap = ap->a_ap) {
747                                 if (symeq(id, ap->a_id, 1))
748                                         break;
749                         }
750                         if (ap == NULL) {
751                                 fprintf(stderr,
752                                 "ASlink-Warning-No definition of area %s\n", id);
753                                 lkerr++;
754                         } else {
755                                 ap->a_addr = v;
756                                 ap->a_bset = 1;
757                         }
758                 } else {
759                         fprintf(stderr, "ASlink-Warning-No '=' in base expression");
760                         lkerr++;
761                 }
762                 bsp = bsp->b_base;
763         }
764 }
765 
766 
767 
768 /* sdld specific */
769 a_uint lnksect2 (struct area *tap, int locIndex);
770 unsigned long codemap8051[524288];
771 unsigned long xdatamap[131216];
772 struct area *dseg_ap = NULL;
773 a_uint dram_start = 0;
774 a_uint iram_start = 0;
775 
776 /*Modified version of the functions for packing variables in internal data memory*/
lnkarea2(void)777 VOID lnkarea2 (void)
778 {
779         a_uint rloc[4]={0, 0, 0, 0};
780         a_uint gs_size = 0;
781         int  locIndex;
782         char temp[NCPS+2];
783         struct sym *sp;
784         int j;
785         struct area *bseg_ap = NULL;
786         struct area *abs_ap = NULL;
787         struct area *gs0_ap = NULL;
788         struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
789 
790         memset(idatamap, ' ', 256);
791         memset(codemap8051, 0, sizeof(codemap8051));
792         memset(xdatamap, 0, sizeof(xdatamap));
793 
794         /* first sort all absolute areas to the front */
795         ap = areap;
796         /* no need to check first area, it's in front anyway */
797         while (ap && ap->a_ap)
798         {
799                 if (ap->a_ap->a_flag & A3_ABS)
800                 {/* next area is absolute, move it to front,
801                         reversed sequence is no problem for absolutes */
802                         abs_ap = ap->a_ap;
803                         ap->a_ap = abs_ap->a_ap;
804                         abs_ap->a_ap = areap;
805                         areap = abs_ap;
806                 }
807                 else
808                 {
809                         ap = ap->a_ap;
810                 }
811         }
812 
813         /* next accumulate all GSINITx/GSFINAL area sizes
814            into GSINIT so they stay together */
815         ap = areap;
816         abs_ap = areap;
817         while (ap)
818         {
819                 if (ap->a_flag & A3_ABS)
820                 {
821                         abs_ap = ap; /* Remember the last abs area */
822                 }
823                 if (!strncmp(ap->a_id, "GS", 2))
824                 {/* GSxxxxx area */
825                         if (ap->a_size == 0)
826                         {
827                                 axp = ap->a_axp;
828                                 while (axp)
829                                 {
830                                         ap->a_size += axp->a_size;
831                                         axp = axp->a_axp;
832                                 }
833                         }
834                         gs_size += ap->a_size;
835                         if (!strcmp(ap->a_id, "GSINIT0"))
836                         {/* GSINIT0 area */
837                                 gs0_ap = ap;
838                         }
839                 }
840                 /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
841                 to compute the byte size of BSEG_BYTES: */
842                 else if (!strcmp(ap->a_id, "BSEG"))
843                 {
844                         bseg_ap = ap->a_ap;                        //BSEG_BYTES
845                         for (axp=ap->a_axp; axp; axp=axp->a_axp)
846                                 ap->a_size += axp->a_size;
847                         bseg_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
848                         ap->a_ap = bseg_ap->a_ap;                  //removed BSEG_BYTES from list
849                         bseg_ap->a_ap = abs_ap->a_ap;
850                         abs_ap->a_ap = bseg_ap;                    //inserted BSEG_BYTES after abs
851                         bseg_ap = ap;                              //BSEG
852                 }
853                 else if (!strcmp(ap->a_id, "DSEG"))
854                 {
855                         dseg_ap = ap; /*Need it later*/
856                         dram_start = ap->a_addr;
857                 }
858                 else if (!strcmp(ap->a_id, "ISEG"))
859                 {
860                         iram_start = ap->a_addr;
861                 }
862                 ap = ap->a_ap;
863         }
864         if (gs0_ap)
865                 gs0_ap->a_size = gs_size;
866 
867         ap = areap;
868         while (ap)
869         {
870                 /* Determine memory space */
871                      if (ap->a_flag & A_CODE)  locIndex = 1;
872                 else if (ap->a_flag & A_XDATA) locIndex = 2;
873                 else if (ap->a_flag & A_BIT)   locIndex = 3;
874                 else locIndex = 0;
875 
876                 if (ap->a_flag & A3_ABS) /* Absolute sections */
877                 {
878                         lnksect2(ap, locIndex);
879                 }
880                 else /* Relocatable sections */
881                 {
882                         if (ap->a_bset == 0)
883                         {
884                                 ap->a_addr = rloc[locIndex];
885                                 ap->a_bset = 1;
886                         }
887 
888                         rloc[locIndex] = lnksect2(ap, locIndex);
889                 }
890 
891                 if (!strcmp(ap->a_id, "BSEG_BYTES") && (ap->a_axp->a_addr >= 0x20))
892                 {
893                         bseg_ap->a_addr += (ap->a_axp->a_addr - 0x20) * 8; /*Bytes to bits*/
894                 }
895                 /*
896                  * Create symbols called:
897                  *      s_<areaname>    the start address of the area
898                  *      l_<areaname>    the length of the area
899                  */
900 
901                 if (! symeq(ap->a_id, _abs_, 1))
902                 {
903                         strcpy(temp+2,ap->a_id);
904                         *(temp+1) = '_';
905 
906                         *temp = 's';
907                         sp = lkpsym(temp, 1);
908                         sp->s_addr = ap->a_addr;
909                         sp->s_type |= S_DEF;
910                         if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
911 
912                         *temp = 'l';
913                         sp = lkpsym(temp, 1);
914                         sp->s_addr = ap->a_size;
915                         sp->s_axp = NULL;
916                         sp->s_type |= S_DEF;
917                         if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
918                 }
919 
920                 ap = ap->a_ap;
921         }
922 
923         /*Compute the size of DSEG*/
924         if(dseg_ap!=NULL)
925         {
926                 dseg_ap->a_addr=0;
927                 dseg_ap->a_size=0;
928                 for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
929         }
930         if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
931         if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
932 }
933 
lnksect2(struct area * tap,int locIndex)934 a_uint lnksect2 (struct area *tap, int locIndex)
935 {
936         a_uint size, addr;
937         struct areax *taxp;
938         int j, k, ramlimit, ramstart;
939         char fchar=' ', dchar='a';
940         char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
941                                   " in internal RAM for area %s.\n";
942 
943         tap->a_unaloc=0;
944 
945         /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
946         if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
947         {
948                 ramstart = iram_start;
949 
950                 if ((iram_size <= 0) || (ramstart + iram_size > 0x100))
951                         ramlimit = 0x100;
952                 else
953                         ramlimit = ramstart + iram_size;
954         }
955         else
956         {
957                 ramstart = dram_start;
958 
959                 if ((iram_size <= 0) || (ramstart + iram_size > 0x80))
960                         ramlimit = 0x80;
961                 else
962                         ramlimit = ramstart + iram_size;
963         }
964 
965         size = 0;
966         addr = tap->a_addr;
967         taxp = tap->a_axp;
968 
969         /*Use a letter to identify each area in the internal RAM layout map*/
970         if (locIndex==0)
971         {
972                 /**/ if(!strcmp(tap->a_id, "DSEG"))
973                         fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
974                 else if(!strcmp(tap->a_id, "ISEG"))
975                         fchar='I';
976                 else if(!strcmp(tap->a_id, "SSEG"))
977                         fchar='S';
978                 else if(!strcmp(tap->a_id, "OSEG"))
979                         fchar='Q';
980                 else if(!strcmp(tap->a_id, "REG_BANK_0"))
981                         fchar='0';
982                 else if(!strcmp(tap->a_id, "REG_BANK_1"))
983                         fchar='1';
984                 else if(!strcmp(tap->a_id, "REG_BANK_2"))
985                         fchar='2';
986                 else if(!strcmp(tap->a_id, "REG_BANK_3"))
987                         fchar='3';
988                 else if(!strcmp(tap->a_id, "BSEG_BYTES"))
989                         fchar='B';
990                 else if(!strcmp(tap->a_id, "BIT_BANK"))
991                         fchar='T';
992                 else
993                         fchar=' ';/*???*/
994         }
995         else if (locIndex == 1)
996         {
997                 /**/ if(!strcmp(tap->a_id, "GSINIT"))
998                         fchar='G';
999         }
1000         else if (locIndex == 2)
1001         {
1002                 /**/ if(!strcmp(tap->a_id, "XSTK"))
1003                         fchar='K';
1004         }
1005 
1006         if (tap->a_flag & A3_OVR) /* Overlayed sections */
1007         {
1008                 while (taxp)
1009                 {
1010                         if(taxp->a_size == 0)
1011                         {
1012                                 taxp = taxp->a_axp;
1013                                 continue;
1014                         }
1015 
1016                         if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
1017                         {
1018                                 addr=(fchar-'0')*8;
1019                                 taxp->a_addr=addr;
1020                                 size=taxp->a_size;
1021                                 for(j=addr; (j<(int)(addr+size)) && (j<ramlimit); j++)
1022                                         idatamap[j]=fchar;
1023                         }
1024                         else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
1025                         {
1026                                 /*Find the size of the space currently used for this areax overlay*/
1027                                 for(j=ramstart, size=0; j<ramlimit; j++)
1028                                         if(idatamap[j]==fchar) size++;
1029 
1030                                 if( (fchar=='S') && (stacksize==0) )
1031                                 {
1032                                    /*Search for the largest space available and use it for stack*/
1033                                         for(j=ramstart, k=0, taxp->a_size=0; j<ramlimit; j++)
1034                                         {
1035                                                 if(idatamap[j]==' ')
1036                                                 {
1037                                                         if((++k)>(int)taxp->a_size)
1038                                                                 taxp->a_size=k;
1039                                                 }
1040                                                 else
1041                                                 {
1042                                                         k=0;
1043                                                 }
1044                                         }
1045                                         stacksize=taxp->a_size;
1046                                 }
1047 
1048                                 /*If more space required, release the previously allocated areax in
1049                                 internal RAM and search for a bigger one*/
1050                                 if((int)taxp->a_size>size)
1051                                 {
1052                                         size=(int)taxp->a_size;
1053 
1054                                         for(j=ramstart; j<ramlimit; j++)
1055                                                 if(idatamap[j]==fchar) idatamap[j]=' ';
1056 
1057                                         /*Search for a space large enough in data memory for this overlay areax*/
1058                                         for(j=ramstart, k=0; j<ramlimit; j++)
1059                                         {
1060                                                 if(idatamap[j]==' ')
1061                                                         k++;
1062                                                 else
1063                                                         k=0;
1064                                         if(k==(int)taxp->a_size)
1065                                                         break;
1066                                         }
1067 
1068                                         /*Mark the memory used for overlay*/
1069                                         if(k==(int)taxp->a_size)
1070                                         {
1071                                                 addr = j-k+1;
1072                                                 for(j=addr; (j<(int)(addr+size)); j++)
1073                                                         idatamap[j]=fchar;
1074                                         }
1075                                         else /*Couldn't find a chunk big enough: report the problem.*/
1076                                         {
1077                                                 tap->a_unaloc=taxp->a_size;
1078                                                 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1079                                                 lkerr++;
1080                                         }
1081 
1082                                         /* avoid redundant processing SSEG */
1083                                         if (fchar == 'S')
1084                                                 break;
1085                                 }
1086                         }
1087                         else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
1088                         {
1089                                 /*Find the size of the space currently used for this areax overlay*/
1090 //                              for(j=0x20, size=0; j<0x30; j++)
1091 //                                      if(idatamap[j]==fchar) size++;
1092 
1093                                 /*If more space required, release the previously allocated areax in
1094                                 internal RAM and search for a bigger one*/
1095                                 if((int)taxp->a_size>size)
1096                                 {
1097                                         size=(int)taxp->a_size;
1098 
1099                                         for(j=0x20; j<0x30; j++)
1100                                                 if(idatamap[j]==fchar) idatamap[j]=' ';
1101 
1102                                         /*Search for a space large enough in data memory for this overlay areax*/
1103                                         for(j=0x20, k=0; j<0x30; j++)
1104                                         {
1105                                                 if(idatamap[j]==' ')
1106                                                         k++;
1107                                                 else
1108                                                         k=0;
1109                                                 if(k==(int)taxp->a_size)
1110                                                         break;
1111                                         }
1112 
1113                                         /*Mark the memory used for overlay*/
1114                                         if(k==(int)size)
1115                                         {
1116                                                 addr = j-k+1;
1117                                                 for(j=addr; (j<(int)(addr+size)); j++)
1118                                                         idatamap[j]=fchar;
1119                                         }
1120                                         else /*Couldn't find a chunk big enough: report the problem.*/
1121                                         {
1122                                                 tap->a_unaloc=taxp->a_size;
1123                                                 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1124                                                 lkerr++;
1125                                         }
1126                                 }
1127                         }
1128                         else /*Overlay areas not in internal ram*/
1129                         {
1130                                 taxp->a_addr = addr;
1131                                 if (taxp->a_size > size) size = taxp->a_size;
1132                         }
1133                         taxp = taxp->a_axp;
1134                 }
1135                 /*Now set all overlayed areax to the same start address*/
1136                 taxp = tap->a_axp;
1137                 while (taxp)
1138                 {
1139                         taxp->a_addr = addr;
1140                         taxp = taxp->a_axp;
1141                 }
1142         }
1143         else if (tap->a_flag & A3_ABS) /* Absolute sections */
1144         {
1145                 while (taxp)
1146                 {
1147                         if (locIndex == 0)
1148                         {
1149                                 for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<256); j++)
1150                                 {
1151                                         if (idatamap[j] == ' ')
1152                                                 idatamap[j] = 'A';
1153                                         else
1154                                                 fprintf(stderr, "memory overlap at 0x%X for %s\n", j, tap->a_id);
1155                                 }
1156                         }
1157                         else if (locIndex == 1)
1158                         {
1159                                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap8051, sizeof (codemap8051));
1160                         }
1161                         else if (locIndex == 2)
1162                         {
1163                                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap, sizeof (xdatamap));
1164                         }
1165                         taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
1166                         size += taxp->a_size;
1167                         taxp = taxp->a_axp;
1168                 }
1169         }
1170         else /* Concatenated sections */
1171         {
1172                 if ((locIndex == 1) && tap->a_size)
1173                 {
1174                         addr = find_empty_space(addr, tap->a_size, tap->a_id, codemap8051, sizeof (codemap8051));
1175                 }
1176                 if ((locIndex == 2) && tap->a_size)
1177                 {
1178                         addr = find_empty_space(addr, tap->a_size, tap->a_id, xdatamap, sizeof (xdatamap));
1179                 }
1180                 while (taxp)
1181                 {
1182                         if (taxp->a_size)
1183                         {
1184                                 if( (fchar=='D') || (fchar=='I') )
1185                                 {
1186                                         /*Search for a space large enough in internal RAM for this areax*/
1187                                         for(j=ramstart, k=0; j<ramlimit; j++)
1188                                         {
1189                                                 if(idatamap[j]==' ')
1190                                                         k++;
1191                                                 else
1192                                                         k=0;
1193                                                 if(k==(int)taxp->a_size)
1194                                                         break;
1195                                         }
1196 
1197                                         if(k==(int)taxp->a_size)
1198                                         {
1199                                                 taxp->a_addr = j-k+1;
1200 
1201                                                 size += taxp->a_size;
1202 
1203                                                 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
1204                                                         idatamap[j]=(fchar=='D')?dchar:fchar;
1205                                                 if((taxp->a_size>0)&&(fchar=='D'))dchar++;
1206                                                 if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
1207                                         }
1208                                         else /*We are in trouble, there is not enough memory for an areax chunk*/
1209                                         {
1210                                                 taxp->a_addr = addr;
1211                                                 addr += taxp->a_size;
1212                                                 size += taxp->a_size;
1213                                                 tap->a_unaloc+=taxp->a_size;
1214                                                 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1215                                                 lkerr++;
1216                                         }
1217                                 }
1218                                 else if (fchar=='B')
1219                                 {
1220                                         /*Search for a space large enough in data memory for this areax*/
1221                                         for(j=0x20, k=0; j<0x30; j++)
1222                                         {
1223                                                 if(idatamap[j]==' ')
1224                                                         k++;
1225                                                 else
1226                                                         k=0;
1227                                                 if(k==(int)taxp->a_size) break;
1228                                         }
1229 
1230                                         /*Mark the memory used*/
1231                                         if(k==(int)taxp->a_size)
1232                                         {
1233                                                 taxp->a_addr = j-k+1;
1234                                                 for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
1235                                                         idatamap[j]=fchar;
1236                                         }
1237                                         else /*Couldn't find a chunk big enough: report the problem.*/
1238                                         {
1239                                                 tap->a_unaloc=taxp->a_size;
1240                                                 fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
1241                                                 lkerr++;
1242                                         }
1243                                         size += taxp->a_size;
1244                                 }
1245                                 else /*For concatenated BIT, CODE, and XRAM areax's*/
1246                                 {
1247                                         //expand external stack
1248                                         if((fchar=='K') && (taxp->a_size == 1))
1249                                         {
1250                                                 taxp->a_size = 256-(addr & 0xFF);
1251                                         }
1252                                         //find next unused address now
1253                                         if (locIndex == 1)
1254                                         {
1255                                                 addr = find_empty_space(addr, taxp->a_size, tap->a_id, codemap8051, sizeof (codemap8051));
1256                                                 allocate_space(addr, taxp->a_size, tap->a_id, codemap8051, sizeof (codemap8051));
1257                                         }
1258                                         if (locIndex == 2)
1259                                         {
1260                                                 addr = find_empty_space(addr, taxp->a_size, tap->a_id, xdatamap, sizeof (xdatamap));
1261                                                 allocate_space(addr, taxp->a_size, tap->a_id, xdatamap, sizeof (xdatamap));
1262                                         }
1263                                         taxp->a_addr = addr;
1264                                         addr += taxp->a_size;
1265                                         size += taxp->a_size;
1266                                 }
1267                         }
1268                         else
1269                         {
1270                             taxp->a_addr = addr;
1271                         }
1272                         taxp = taxp->a_axp;
1273                 }
1274         }
1275         tap->a_size = size;
1276         tap->a_addr = tap->a_axp->a_addr;
1277         for (taxp = tap->a_axp; taxp && !taxp->a_size; taxp = taxp->a_axp)
1278         {
1279         }
1280         if (taxp)
1281         {
1282                 tap->a_addr = taxp->a_addr;
1283         }
1284 
1285         if ((tap->a_flag & A3_PAG) && (size > 256))
1286         {
1287                 fprintf(stderr,
1288                         "\n?ASlink-Warning-Paged Area %s Length Error\n",
1289                         tap->a_id);
1290                 lkerr++;
1291         }
1292         if ((tap->a_flag & A3_PAG) && (tap->a_size) &&
1293                 ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
1294         {
1295                 fprintf(stderr,
1296                         "\n?ASlink-Warning-Paged Area %s Boundary Error\n",
1297                         tap->a_id);
1298                 lkerr++;
1299         }
1300         return addr;
1301 }
1302 /* end sdld specific */
1303 
1304