X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fmcs51%2Flkarea.c;h=3913ae83af8e168f7a0bb542a27d2080cf34e5d8;hb=5e7a815ef82dacf659fdad6451a982842eb255a2;hp=b535f2599b7f7c38f2c9c01881fadf80ed866144;hpb=b09af35f2f1cde7649d3ac4a6f5d2af6d97895a0;p=fw%2Fsdcc diff --git a/as/mcs51/lkarea.c b/as/mcs51/lkarea.c index b535f259..3913ae83 100644 --- a/as/mcs51/lkarea.c +++ b/as/mcs51/lkarea.c @@ -8,87 +8,86 @@ * 721 Berkeley St. * Kent, Ohio 44240 * - * 3-Nov-97 JLH: + * 3-Nov-97 JLH: * - change lkparea to use a_type == 0 as "virgin area" flag * 02-Apr-98 JLH: add code to link 8051 data spaces */ #include #include -#include #include "aslink.h" -/*)Module lkarea.c +/*)Module lkarea.c * - * The module lkarea.c contains the functions which - * create and link together all area definitions read - * from the .rel file(s). + * The module lkarea.c contains the functions which + * create and link together all area definitions read + * from the .rel file(s). * - * lkarea.c contains the following functions: - * VOID lnkarea() - * VOID lnksect() - * VOID lkparea() - * VOID newarea() + * lkarea.c contains the following functions: + * VOID lnkarea() + * VOID lnksect() + * VOID lkparea() + * VOID newarea() * - * lkarea.c contains no global variables. + * lkarea.c contains no global variables. */ -/*)Function VOID newarea() - * - * The function newarea() creates and/or modifies area - * and areax structures for each A directive read from - * the .rel file(s). The function lkparea() is called - * to find tha area structure associated with this name. - * If the area does not yet exist then a new area - * structure is created and linked to any existing - * linked area structures. The area flags are copied - * into the area flag variable. For each occurence of - * an A directive an areax structure is created and - * linked to the areax structures associated with this - * area. The size of this area section is placed into - * the areax structure. The flag value for all subsequent - * area definitions for the same area are compared and - * flagged as an error if they are not identical. - * The areax structure created for every occurence of - * an A directive is loaded with a pointer to the base - * area structure and a pointer to the associated - * head structure. And finally, a pointer to this - * areax structure is loaded into the list of areax - * structures in the head structure. Refer to lkdata.c - * for details of the structures and their linkage. - * - * local variables: - * areax **halp pointer to an array of pointers - * int i counter, loop variable, value - * char id[] id string - * int narea number of areas in this head structure - * areax * taxp pointer to an areax structure - * to areax structures - * - * global variables: - * area *ap Pointer to the current - * area structure - * areax *axp Pointer to the current - * areax structure - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * - * functions called: - * addr_t eval() lkeval.c - * VOID exit() c_library - * int fprintf() c_library - * VOID getid() lklex.c - * VOID lkparea() lkarea.c - * VOID skip() lklex.c - * - * side effects: - * The area and areax structures are created and - * linked with the appropriate head structures. - * Failure to allocate area or areax structure - * space will terminate the linker. Other internal - * errors most likely caused by corrupted .rel - * files will also terminate the linker. +/*)Function VOID newarea() + * + * The function newarea() creates and/or modifies area + * and areax structures for each A directive read from + * the .rel file(s). The function lkparea() is called + * to find tha area structure associated with this name. + * If the area does not yet exist then a new area + * structure is created and linked to any existing + * linked area structures. The area flags are copied + * into the area flag variable. For each occurence of + * an A directive an areax structure is created and + * linked to the areax structures associated with this + * area. The size of this area section is placed into + * the areax structure. The flag value for all subsequent + * area definitions for the same area are compared and + * flagged as an error if they are not identical. + * The areax structure created for every occurence of + * an A directive is loaded with a pointer to the base + * area structure and a pointer to the associated + * head structure. And finally, a pointer to this + * areax structure is loaded into the list of areax + * structures in the head structure. Refer to lkdata.c + * for details of the structures and their linkage. + * + * local variables: + * areax **halp pointer to an array of pointers + * int i counter, loop variable, value + * char id[] id string + * int narea number of areas in this head structure + * areax * taxp pointer to an areax structure + * to areax structures + * + * global variables: + * area *ap Pointer to the current + * area structure + * areax *axp Pointer to the current + * areax structure + * head *hp Pointer to the current + * head structure + * int lkerr error flag + * + * functions called: + * Addr_T eval() lkeval.c + * VOID exit() c_library + * int fprintf() c_library + * VOID getid() lklex.c + * VOID lkparea() lkarea.c + * VOID skip() lklex.c + * + * side effects: + * The area and areax structures are created and + * linked with the appropriate head structures. + * Failure to allocate area or areax structure + * space will terminate the linker. Other internal + * errors most likely caused by corrupted .rel + * files will also terminate the linker. */ /* @@ -104,211 +103,211 @@ VOID newarea() { - register int i, narea; - struct areax *taxp; - struct areax **halp; - char id[NCPS]; - - /* - * Create Area entry - */ - getid(id, -1); - lkparea(id); - /* - * Evaluate area size - */ - skip(-1); - axp->a_size = eval(); - /* - * Evaluate flags - */ - skip(-1); - i = 0; - taxp = ap->a_axp; - while (taxp->a_axp) { - ++i; - taxp = taxp->a_axp; - } - if (i == 0) { - ap->a_flag = eval(); - } else { - i = eval(); -/* if (i && (ap->a_flag != i)) { */ -/* fprintf(stderr, "Conflicting flags in area %8s\n", id); */ -/* lkerr++; */ -/* } */ - } - /* - * Place pointer in header area list - */ - if (headp == NULL) { - fprintf(stderr, "No header defined\n"); - lkexit(1); - } - narea = hp->h_narea; - halp = hp->a_list; - for (i=0; i < narea ;++i) { - if (halp[i] == NULL) { - halp[i] = taxp; - return; - } - } - fprintf(stderr, "Header area list overflow\n"); - lkexit(1); + register int i, narea; + struct areax *taxp; + struct areax **halp; + char id[NCPS]; + + /* + * Create Area entry + */ + getid(id, -1); + lkparea(id); + /* + * Evaluate area size + */ + skip(-1); + axp->a_size = eval(); + /* + * Evaluate flags + */ + skip(-1); + i = 0; + taxp = ap->a_axp; + while (taxp->a_axp) { + ++i; + taxp = taxp->a_axp; + } + if (i == 0) { + ap->a_flag = eval(); + } else { + i = eval(); +/* if (i && (ap->a_flag != i)) { */ +/* fprintf(stderr, "Conflicting flags in area %8s\n", id); */ +/* lkerr++; */ +/* } */ + } + /* + * Place pointer in header area list + */ + if (headp == NULL) { + fprintf(stderr, "No header defined\n"); + lkexit(1); + } + narea = hp->h_narea; + halp = hp->a_list; + for (i=0; i < narea ;++i) { + if (halp[i] == NULL) { + halp[i] = taxp; + return; + } + } + fprintf(stderr, "Header area list overflow\n"); + lkexit(1); } -/*)Function VOID lkparea(id) - * - * char * id pointer to the area name string - * - * The function lkparea() searches the linked area structures - * for a name match. If the name is not found then an area - * structure is created. An areax structure is created and - * appended to the areax structures linked to the area structure. - * The associated base area and head structure pointers are - * loaded into the areax structure. - * - * local variables: - * area * tap pointer to an area structure - * areax * taxp pointer to an areax structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * areax *axp Pointer to the current - * areax structure - * - * functions called: - * VOID * new() lksym() - * char * strcpy() c_library - * int symeq() lksym.c - * - * side effects: - * Area and/or areax structures are created. - * Failure to allocate space for created structures - * will terminate the linker. +/*)Function VOID lkparea(id) + * + * char * id pointer to the area name string + * + * The function lkparea() searches the linked area structures + * for a name match. If the name is not found then an area + * structure is created. An areax structure is created and + * appended to the areax structures linked to the area structure. + * The associated base area and head structure pointers are + * loaded into the areax structure. + * + * local variables: + * area * tap pointer to an area structure + * areax * taxp pointer to an areax structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * areax *axp Pointer to the current + * areax structure + * + * functions called: + * VOID * new() lksym() + * char * strcpy() c_library + * int symeq() lksym.c + * + * side effects: + * Area and/or areax structures are created. + * Failure to allocate space for created structures + * will terminate the linker. */ VOID -lkparea(id) -char *id; +lkparea(char *id) { - register struct area *tap; - register struct areax *taxp; - - ap = areap; - axp = (struct areax *) new (sizeof(struct areax)); - while (ap) { - if (symeq(id, ap->a_id)) { - taxp = ap->a_axp; - while (taxp->a_axp) - taxp = taxp->a_axp; - taxp->a_axp = axp; - axp->a_bap = ap; - axp->a_bhp = hp; - return; - } - ap = ap->a_ap; - } - ap = (struct area *) new (sizeof(struct area)); - if (areap == NULL) { - areap = ap; - } else { - tap = areap; - while (tap->a_ap) - tap = tap->a_ap; - tap->a_ap = ap; - } - ap->a_axp = axp; - axp->a_bap = ap; - axp->a_bhp = hp; - strncpy(ap->a_id, id, NCPS); - ap->a_addr = 0; + register struct area *tap; + register struct areax *taxp; + + ap = areap; + axp = (struct areax *) new (sizeof(struct areax)); + axp->a_addr = -1; /* default: no address yet */ + while (ap) { + if (symeq(id, ap->a_id)) { + taxp = ap->a_axp; + while (taxp->a_axp) + taxp = taxp->a_axp; + taxp->a_axp = axp; + axp->a_bap = ap; + axp->a_bhp = hp; + return; + } + ap = ap->a_ap; + } + ap = (struct area *) new (sizeof(struct area)); + if (areap == NULL) { + areap = ap; + } else { + tap = areap; + while (tap->a_ap) + tap = tap->a_ap; + tap->a_ap = ap; + } + ap->a_axp = axp; + axp->a_bap = ap; + axp->a_bhp = hp; + strncpy(ap->a_id, id, NCPS); + ap->a_addr = 0; } -/*)Function VOID lnkarea() - * - * The function lnkarea() resolves all area addresses. - * The function evaluates each area structure (and all - * the associated areax structures) in sequence. The - * linking process supports four (4) possible area types: - * - * ABS/OVR - All sections (each individual areax - * section) starts at the identical base - * area address overlaying all other - * areax sections for this area. The - * size of the area is largest of the area - * sections. - * - * ABS/CON - All sections (each individual areax - * section) are concatenated with the - * first section starting at the base - * area address. The size of the area - * is the sum of the section sizes. - * - * NOTE: Multiple absolute (ABS) areas are - * never concatenated with each other, - * thus absolute area A and absolute area - * B will overlay each other if they begin - * at the same location (the default is - * always address 0 for absolute areas). - * - * REL/OVR - All sections (each individual areax - * section) starts at the identical base - * area address overlaying all other - * areax sections for this area. The - * size of the area is largest of the area - * sections. - * - * REL/CON - All sections (each individual areax - * section) are concatenated with the - * first section starting at the base - * area address. The size of the area - * is the sum of the section sizes. - * - * NOTE: Relocatable (REL) areas ae always concatenated - * with each other, thus relocatable area B - * (defined after area A) will follow - * relocatable area A independent of the - * starting address of area A. Within a - * specific area each areax section may be - * overlayed or concatenated with other - * areax sections. - * - * - * If a base address for an area is specified then the - * area will start at that address. Any relocatable - * areas defined subsequently will be concatenated to the - * previous relocatable area if it does not have a base - * address specified. - * - * The names s_ and l_ are created to - * define the starting address and length of each area. - * - * local variables: - * addr_t rloc ;current relocation address - * char temp[] ;temporary string - * struct symbol *sp ;symbol structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * - * functions called: - * int fprintf() c_library - * VOID lnksect() lkarea.c - * symbol *lkpsym() lksysm.c - * char * strncpy() c_library - * int symeq() lksysm.c - * - * side effects: - * All area and areax addresses and sizes are - * determined and saved in their respective - * structures. +/*)Function VOID lnkarea() + * + * The function lnkarea() resolves all area addresses. + * The function evaluates each area structure (and all + * the associated areax structures) in sequence. The + * linking process supports four (4) possible area types: + * + * ABS/OVR - All sections (each individual areax + * section) starts at the identical base + * area address overlaying all other + * areax sections for this area. The + * size of the area is largest of the area + * sections. + * + * ABS/CON - All sections (each individual areax + * section) are concatenated with the + * first section starting at the base + * area address. The size of the area + * is the sum of the section sizes. + * + * NOTE: Multiple absolute (ABS) areas are + * never concatenated with each other, + * thus absolute area A and absolute area + * B will overlay each other if they begin + * at the same location (the default is + * always address 0 for absolute areas). + * + * REL/OVR - All sections (each individual areax + * section) starts at the identical base + * area address overlaying all other + * areax sections for this area. The + * size of the area is largest of the area + * sections. + * + * REL/CON - All sections (each individual areax + * section) are concatenated with the + * first section starting at the base + * area address. The size of the area + * is the sum of the section sizes. + * + * NOTE: Relocatable (REL) areas are always concatenated + * with each other, thus relocatable area B + * (defined after area A) will follow + * relocatable area A independent of the + * starting address of area A. Within a + * specific area each areax section may be + * overlayed or concatenated with other + * areax sections. + * + * + * If a base address for an area is specified then the + * area will start at that address. Any relocatable + * areas defined subsequently will be concatenated to the + * previous relocatable area if it does not have a base + * address specified. + * + * The names s_ and l_ are created to + * define the starting address and length of each area. + * + * local variables: + * Addr_T rloc ;current relocation address + * char temp[] ;temporary string + * struct symbol *sp ;symbol structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * + * functions called: + * int fprintf() c_library + * VOID lnksect() lkarea.c + * symbol *lkpsym() lksym.c + * char * strncpy() c_library + * int symeq() lksym.c + * + * side effects: + * All area and areax addresses and sizes are + * determined and saved in their respective + * structures. */ /* @@ -317,21 +316,24 @@ char *id; VOID lnkarea() { - addr_t rloc[4]; - int locIndex; - char temp[NCPS]; - struct sym *sp; - - rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0; - ap = areap; - while (ap) { - if (ap->a_flag&A_ABS) { - /* - * Absolute sections - */ - lnksect(ap); - } else { - /* Determine memory space */ + Addr_T rloc[4]; + int locIndex; + char temp[NCPS]; + struct sym *sp; + /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/ + struct area *ta[5]; + int j; + + rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0; + ap = areap; + while (ap) { + if (ap->a_flag&A_ABS) { + /* + * Absolute sections + */ + lnksect(ap); + } else { + /* Determine memory space */ locIndex = 0; if (ap->a_flag & A_CODE) { locIndex = 1; @@ -342,110 +344,609 @@ lnkarea() if (ap->a_flag & A_BIT) { locIndex = 3; } - /* - * Relocatable sections - */ - if (ap->a_type == 0) { /* JLH */ - ap->a_addr = rloc[ locIndex ]; - ap->a_type = 1; - } - lnksect(ap); - rloc[ locIndex ] = ap->a_addr + ap->a_size; - } - - /* - * Create symbols called: - * s_ the start address of the area - * l_ the length of the area - */ - - if (! symeq(ap->a_id, _abs_)) { - strncpy(temp+2,ap->a_id,NCPS-2); - *(temp+1) = '_'; - - *temp = 's'; - sp = lkpsym(temp, 1); - sp->s_addr = ap->a_addr ; - /* sp->s_axp = ap->a_axp; JLH: was NULL; */ - sp->s_type |= S_DEF; - - *temp = 'l'; - sp = lkpsym(temp, 1); - sp->s_addr = ap->a_size; - sp->s_axp = NULL; - sp->s_type |= S_DEF; - - } - ap = ap->a_ap; - } + /* + * Relocatable sections + */ + if (ap->a_type == 0) { /* JLH */ + ap->a_addr = rloc[ locIndex ]; + ap->a_type = 1; + } + lnksect(ap); + rloc[ locIndex ] = ap->a_addr + ap->a_size; + } + + /* + * Create symbols called: + * s_ the start address of the area + * l_ the length of the area + */ + + if (! symeq(ap->a_id, _abs_)) { + strncpy(temp+2,ap->a_id,NCPS-2); + *(temp+1) = '_'; + + *temp = 's'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_addr ; + /* sp->s_axp = ap->a_axp; JLH: was NULL; */ + sp->s_type |= S_DEF; + + *temp = 'l'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_size; + sp->s_axp = NULL; + sp->s_type |= S_DEF; + + } + + /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG + to compute the byte size of BSEG_BYTES: */ + if (!strcmp(ap->a_id, "BSEG")) { + ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/ + } + else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap; + else if (!strcmp(ap->a_id, "BSEG_BYTES")) + { + ta[4]=ap; + for(j=4; j>1; j--) + { + /*If upper register banks are not used roll back the relocation counter*/ + if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) ) + { + rloc[0]-=8; + } + else break; + } + } + ap = ap->a_ap; + } } -/*)Function VOID lnksect() +/*)Function VOID lnksect() * - * area * tap pointer to an area structure + * area * tap pointer to an area structure * - * The function lnksect() is the function called by - * lnkarea() to resolve the areax addresses. Refer - * to the function lnkarea() for more detail. Pageing - * boundary and length errors will be reported by this - * function. + * The function lnksect() is the function called by + * lnkarea() to resolve the areax addresses. Refer + * to the function lnkarea() for more detail. Pageing + * boundary and length errors will be reported by this + * function. * - * local variables: - * addr_t size size of area - * addr_t addr address of area - * areax * taxp pointer to an areax structure + * local variables: + * Addr_T size size of area + * Addr_T addr address of area + * areax * taxp pointer to an areax structure * - * global variables: - * int lkerr error flag + * global variables: + * int lkerr error flag * - * functions called: - * none + * functions called: + * none * - * side effects: - * All area and areax addresses and sizes area determined - * and linked into the structures. + * side effects: + * All area and areax addresses and sizes area determined + * and linked into the structures. */ VOID -lnksect(tap) -register struct area *tap; +lnksect(register struct area *tap) +{ + register Addr_T size, addr; + register struct areax *taxp; + + size = 0; + addr = tap->a_addr; +#if 0 + if ((tap->a_flag&A_PAG) && (addr & 0xFF)) { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); + lkerr++; + } +#endif + taxp = tap->a_axp; + if (tap->a_flag&A_OVR) { + /* + * Overlayed sections + */ + while (taxp) { + taxp->a_addr = addr; + if (taxp->a_size > size) + size = taxp->a_size; + taxp = taxp->a_axp; + } + } else { + /* + * Concatenated sections + */ + while (taxp) { + taxp->a_addr = addr; + addr += taxp->a_size; + size += taxp->a_size; + taxp = taxp->a_axp; + } + } + tap->a_size = size; + if ((tap->a_flag&A_PAG) && (size > 256)) { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id); + lkerr++; + } + if ((tap->a_flag&A_PAG) && (tap->a_size) && + ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00))) + { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); + lkerr++; + } +} + +void lnksect2 (struct area *tap, int rloc); +char idatamap[256]; +long codemap[524288]; + +/*Modified version of the functions for packing variables in internal data memory*/ +VOID lnkarea2 (void) +{ + Addr_T rloc[4]={0, 0, 0, 0}; + int locIndex; + char temp[NCPS]; + struct sym *sp; + int j; + struct area *dseg_ap = NULL; + struct area *abs_ap = NULL; + struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL; + + for(j=0; j<256; j++) idatamap[j]=' '; + memset(codemap, 0, sizeof(codemap)); + + /* first sort all absolute areas to the front */ + ap = areap; + /* no need to check first area, it's in front anyway */ + while (ap && ap->a_ap) + { + if (ap->a_ap->a_flag & A_ABS) + {/* next area is absolute, move it to front, + reversed sequence is no problem for absolutes */ + abs_ap = ap->a_ap; + ap->a_ap = abs_ap->a_ap; + abs_ap->a_ap = areap; + areap = abs_ap; + } + ap = ap->a_ap; + } + + ap = areap; + while (ap) + { + /* Determine memory space */ + if (ap->a_flag & A_CODE) locIndex = 1; + else if (ap->a_flag & A_XDATA) locIndex = 2; + else if (ap->a_flag & A_BIT) locIndex = 3; + else locIndex = 0; + + if (ap->a_flag&A_ABS) /* Absolute sections */ + { + lnksect2(ap, locIndex); + } + else /* Relocatable sections */ + { + if (ap->a_type == 0) + { + ap->a_addr=rloc[locIndex]; + ap->a_type=1; + } + + lnksect2(ap, locIndex); + rloc[locIndex] = ap->a_addr + ap->a_size; + } + + /* + * Create symbols called: + * s_ the start address of the area + * l_ the length of the area + */ + + if (! symeq(ap->a_id, _abs_)) + { + strncpy(temp+2,ap->a_id,NCPS-2); + *(temp+1) = '_'; + + *temp = 's'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_addr ; + sp->s_type |= S_DEF; + if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp; + + *temp = 'l'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_size; + sp->s_axp = NULL; + sp->s_type |= S_DEF; + if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp; + } + + /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG + to compute the byte size of BSEG_BYTES: */ + if (!strcmp(ap->a_id, "BSEG")) + { + ap->a_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/ + } + else if (!strcmp(ap->a_id, "DSEG")) + { + dseg_ap=ap; /*Need it later to set its correct size*/ + } + ap = ap->a_ap; + } + + /*Compute the size of DSEG*/ + if(dseg_ap!=NULL) + { + dseg_ap->a_addr=0; + dseg_ap->a_size=0; + for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++; + } + if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0; + if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size; + +#if 0 + /*Print the memory map*/ + fprintf(stderr, "Internal RAM layout:\n" + " 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for(j=0; j<256; j++) + { + if(j%16==0) fprintf(stderr, "\n0x%02x:|", j); + fprintf(stderr, "%c|", idatamap[j]); + } + fprintf(stderr, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n"); +#endif +} + +void lnksect2 (struct area *tap, int rloc) { - register addr_t size, addr; - register struct areax *taxp; - - size = 0; - addr = tap->a_addr; - if ((tap->a_flag&A_PAG) && (addr & 0xFF)) { - fprintf(stderr, - "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); - lkerr++; - } - taxp = tap->a_axp; - if (tap->a_flag&A_OVR) { - /* - * Overlayed sections - */ - while (taxp) { - taxp->a_addr = addr; - if (taxp->a_size > size) - size = taxp->a_size; - taxp = taxp->a_axp; - } - } else { - /* - * Concatenated sections - */ - while (taxp) { - taxp->a_addr = addr; - addr += taxp->a_size; - size += taxp->a_size; - taxp = taxp->a_axp; - } - } - tap->a_size = size; - if ((tap->a_flag&A_PAG) && (size > 256)) { - fprintf(stderr, - "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id); - lkerr++; - } + register Addr_T size, addr; + register struct areax *taxp; + int j, k, ramlimit; + char fchar, dchar='a'; + char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s" + " in internal RAM for area %s.\n"; + + tap->a_unaloc=0; + + /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/ + if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) ) + { + if((iram_size<=0)||(iram_size>0x100)) + ramlimit=0x100; + else + ramlimit=iram_size; + } + else + { + if((iram_size<=0)||(iram_size>0x80)) + ramlimit=0x80; + else + ramlimit=iram_size; + } + + size = 0; + addr = tap->a_addr; +#if 0 + if ((tap->a_flag&A_PAG) && (addr & 0xFF)) + { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); + lkerr++; + } +#endif + taxp = tap->a_axp; + + /*Use a letter to identify each area in the internal RAM layout map*/ + if(rloc==0) + { + /**/ if(!strcmp(tap->a_id, "DSEG")) + fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/ + else if(!strcmp(tap->a_id, "ISEG")) + fchar='I'; + else if(!strcmp(tap->a_id, "SSEG")) + fchar='S'; + else if(!strcmp(tap->a_id, "OSEG")) + fchar='Q'; + else if(!strcmp(tap->a_id, "REG_BANK_0")) + fchar='0'; + else if(!strcmp(tap->a_id, "REG_BANK_1")) + fchar='1'; + else if(!strcmp(tap->a_id, "REG_BANK_2")) + fchar='2'; + else if(!strcmp(tap->a_id, "REG_BANK_3")) + fchar='3'; + else if(!strcmp(tap->a_id, "BSEG_BYTES")) + fchar='B'; + else if(!strcmp(tap->a_id, "BIT_BANK")) + fchar='T'; + else + fchar=' ';/*???*/ + } + else + { + fchar=' '; + } + + if (tap->a_flag&A_OVR) /* Overlayed sections */ + { + while (taxp) + { + if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/ + { + addr=(fchar-'0')*8; + taxp->a_addr=addr; + size=taxp->a_size; + for(j=addr; (j<(int)(addr+taxp->a_size)) && (ja_size=0; j(int)taxp->a_size) taxp->a_size=k; + } + else + { + k=0; + } + } + stacksize=taxp->a_size; + } + + /*If more space required, release the previously allocated areax in + internal RAM and search for a bigger one*/ + if((int)taxp->a_size>size) + { + size=(int)taxp->a_size; + + for(j=0; ja_size) break; + } + + if(k==(int)taxp->a_size) + { + taxp->a_addr = j-k+1; + if(addr<(unsigned int)ramlimit) + { + for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--); + if(j>=0) addr=j+1; + } + } + + /*Mark the memory used for overlay*/ + if(k==(int)taxp->a_size) + { + for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (ja_unaloc=taxp->a_size; + fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id); + lkerr++; + } + } + + for(j=0; ja_addr=addr; + taxp->a_addr=addr; + break; + } + } + } + else if (fchar=='T') /*Bit addressable bytes in internal RAM*/ + { + /*Find the size of the space currently used for this areax overlay*/ + for(j=0x20, size=0; j<0x30; j++) + if(idatamap[j]==fchar) size++; + + /*If more space required, release the previously allocated areax in + internal RAM and search for a bigger one*/ + if((int)taxp->a_size>size) + { + size=(int)taxp->a_size; + + for(j=0x20; j<0x30; j++) + if(idatamap[j]==fchar) idatamap[j]=' '; + + /*Search for a space large enough in data memory for this overlay areax*/ + for(j=0x20, k=0; j<0x30; j++) + { + if(idatamap[j]==' ') + k++; + else + k=0; + if(k==(int)taxp->a_size) break; + } + + if(k==(int)taxp->a_size) + { + taxp->a_addr = j-k+1; + if(addr<(unsigned int)0x30) + { + for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--); + if(j>=0x20) addr=j+1; + } + } + + /*Mark the memory used for overlay*/ + if(k==(int)taxp->a_size) + { + for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++) + idatamap[j]=fchar; + + /*Set the new size of the data memory area*/ + size=ramlimit-addr; + } + else /*Couldn't find a chunk big enough: report the problem.*/ + { + tap->a_unaloc=taxp->a_size; + fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id); + lkerr++; + } + } + + for(j=0x20; j<0x30; j++) + { + if (idatamap[j]==fchar) + { + addr=j; + tap->a_addr=addr; + taxp->a_addr=addr; + break; + } + } + } + else /*Overlay areas not in internal ram*/ + { + taxp->a_addr = addr; + if (taxp->a_size > size) size = taxp->a_size; + } + taxp = taxp->a_axp; + } + } + else /* Concatenated sections */ + { + while (taxp) + { + if( (fchar=='D') || (fchar=='I') ) + { + if(taxp->a_size) + { + /*Search for a space large enough in internal RAM for this areax*/ + for(j=0, k=0; ja_size) break; + } + + if(k==(int)taxp->a_size) + { + taxp->a_addr = j-k+1; + if(addr<(unsigned int)ramlimit) + { + for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--); + if(j>=0) addr=j+1; + size=ramlimit-addr; + } + + for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (ja_size>0)&&(fchar=='D'))dchar++; + if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/ + } + else /*We are in trouble, there is not enough memory for an areax chunk*/ + { + taxp->a_addr = addr; + addr += taxp->a_size; + size += taxp->a_size; + tap->a_unaloc+=taxp->a_size; + fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id); + lkerr++; + } + } + taxp = taxp->a_axp; + } + else if(fchar=='B') + { + if(taxp->a_size!=0) + { + for(j=addr; j<((int)(addr+taxp->a_size)); j++) + idatamap[j]=fchar; + } + + taxp->a_addr = addr; + addr += taxp->a_size; + size += taxp->a_size; + taxp = taxp->a_axp; + } + else /*For concatenated BIT, CODE, and XRAM areax's*/ + { + if(!strcmp(tap->a_id, "XSTK") && (taxp->a_size == 1)) + { + taxp->a_size = 256-(addr & 0xFF); + } + //should find next unused address now!!! + //but let's first just warn for overlaps + if (rloc == 1) + { + int a = addr; + int i = addr >> 5; + int j = (addr + taxp->a_size) >> 5; + long mask = -(1 << (addr & 0x1F)); + + while (i < j) + { + if (codemap[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id); + } + codemap[i++] |= mask; + mask = 0xFFFFFFFF; + a += 32; + } + mask &= (1 << ((addr + taxp->a_size) & 0x1F)) - 1; + if (codemap[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id); + } + codemap[i] |= mask; + } + taxp->a_addr = addr; + addr += taxp->a_size; + size += taxp->a_size; + taxp = taxp->a_axp; + } + } + } + tap->a_size = size; + + if ((tap->a_flag&A_PAG) && (size > 256)) + { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id); + lkerr++; + } + if ((tap->a_flag&A_PAG) && (tap->a_size) && + ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00))) + { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); + lkerr++; + } }