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