From: jesusc Date: Sun, 4 Jan 2004 14:18:23 +0000 (+0000) Subject: Linker places variables in unused register banks. Call using -Wl-Y[stack_size] X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=af3b901c1ec2278914fe7415b539927f2764633a;p=fw%2Fsdcc Linker places variables in unused register banks. Call using -Wl-Y[stack_size] git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3077 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index 3b094f62..0ad48633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2004-01-04 Jesus Calvino-Fraga + + * as/mcs51/aslink.h, as/mcs51/lkarea.c, as/mcs51/lkdata.c, + as/mcs51/lkmain.c, as/mcs51/lkmem.c: 8051 linker can now pack + variables in unused register banks. Also the SSEG is placed + wherever there is enough space for it, and IDATA can be anywhere + in internal RAM. For now compile using -Wl-Y[stack_size]. + The mem file is different for this option as well, since it + makes no sense of talking about DSEG lenght. + 2004-01-02 Vangelis Rokas * src/SDCClrange.c: fixed bug 869095 that caused segfault diff --git a/as/mcs51/aslink.h b/as/mcs51/aslink.h index 263467a0..ff4cb8da 100644 --- a/as/mcs51/aslink.h +++ b/as/mcs51/aslink.h @@ -244,6 +244,7 @@ struct area struct areax *a_axp; /* Area extension link */ Addr_T a_addr; /* Beginning address of area */ Addr_T a_size; /* Total size of the area */ + Addr_T a_unaloc; /* Total number of unalocated bytes, for error reporting */ char a_type; /* Area subtype */ char a_flag; /* Flag byte */ char a_id[NCPS]; /* Name */ @@ -577,6 +578,8 @@ extern int mflag; /* Map output flag */ extern int sflag; /* JCF: Memory usage output flag */ +extern int packflag_and_stacksize; /* Pack data memory flag + */ extern int jflag; /* NoICE output flag */ extern int xflag; /* Map file radix type flag @@ -685,6 +688,7 @@ extern VOID chop_crlf(); /* lkarea.c */ extern VOID lkparea(); extern VOID lnkarea(); +extern VOID lnkarea2(); extern VOID lnksect(); extern VOID newarea(); @@ -769,6 +773,7 @@ extern void DefineNoICE( char *name, Addr_T value, int page ); /* JCF: lkmem.c */ extern int summary(struct area * xp); +extern int summary2(struct area * xp); /* JCF: lkaomf51.c */ extern void SaveLinkedFilePath(char * filepath); diff --git a/as/mcs51/lkarea.c b/as/mcs51/lkarea.c index d13f104e..44318682 100644 --- a/as/mcs51/lkarea.c +++ b/as/mcs51/lkarea.c @@ -474,3 +474,325 @@ register struct area *tap; lkerr++; } } + +void lnksect2 (struct area *tap, int rloc); +char idatamap[256]; + +/*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 sym *sp_dseg_s, *sp_dseg_l; + + for(j=0; j<256; j++) idatamap[j]=' '; + + 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/8)+((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*/ + dseg_ap->a_addr=0; + dseg_ap->a_size=0; + for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++; + sp_dseg_s->s_addr=0; + 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; + 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 + { + ramlimit=0x80; + } + + 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; + + /*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' latter 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 + 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>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 /*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=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_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*/ + { + 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++; + } +} diff --git a/as/mcs51/lkdata.c b/as/mcs51/lkdata.c index d6a35175..1840ee79 100644 --- a/as/mcs51/lkdata.c +++ b/as/mcs51/lkdata.c @@ -55,6 +55,8 @@ int mflag; /* Map output flag */ int sflag; /* JCF: Memory usage output flag */ +int packflag_and_stacksize=0; /* JCF: Pack internal memory flag + */ int aflag; /* Overlapping area warning flag */ int jflag; /* NoICE output flag diff --git a/as/mcs51/lkmain.c b/as/mcs51/lkmain.c index 548a44fd..fd9e4d07 100644 --- a/as/mcs51/lkmain.c +++ b/as/mcs51/lkmain.c @@ -79,7 +79,7 @@ void Areas51 (void) { char * rel[]={ "XH", - "H 7 areas 0 global symbols", + "H B areas 0 global symbols", "A _CODE size 0 flags 0", /*Each .rel has one, so...*/ "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/ "A REG_BANK_1 size 0 flags 4", @@ -87,6 +87,10 @@ void Areas51 (void) "A REG_BANK_3 size 0 flags 4", "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/ "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/ + "A DSEG size 0 flags 0", + "A OSEG size 0 flags 4", + "A ISEG size 0 flags 0", + "A SSEG size 0 flags 4", "" }; int j; @@ -105,6 +109,10 @@ void Areas51 (void) else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; } else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; } else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; } + else if (!strcmp(ap->a_id, "SSEG")) + { + if(packflag_and_stacksize>1) ap->a_axp->a_size=packflag_and_stacksize; + } } } @@ -308,7 +316,10 @@ char *argv[]; /* * Link all area addresses. */ - lnkarea(); + if(!packflag_and_stacksize) + lnkarea(); + else + lnkarea2(); /* * Process global definitions. */ @@ -335,9 +346,18 @@ char *argv[]; map(); if (sflag) /*JCF: memory usage summary output*/ - if(summary(areap))lkexit(1); + { + if(!packflag_and_stacksize) + { + if(summary(areap)) lkexit(1); + } + else + { + if(summary2(areap)) lkexit(1); + } + } - if (iram_size) + if ((iram_size) && (!packflag_and_stacksize)) iramcheck(); /* @@ -776,10 +796,15 @@ parse() break; case 'y': /*JCF: memory usage summary output*/ - case 'Y': ++sflag; break; + case 'Y': + unget(getnb()); + /*The stack segment default size is 16 bytes. Use -Yxx for xx bytes*/ + packflag_and_stacksize=(ip && *ip)?expr(0):16; + break; + case 'j': case 'J': jflag = 1; @@ -858,7 +883,7 @@ parse() return(0); case 'z': - case 'Z': + case 'Z': dflag = 1; return(0); default: diff --git a/as/mcs51/lkmem.c b/as/mcs51/lkmem.c index 54fb0628..0184e396 100644 --- a/as/mcs51/lkmem.c +++ b/as/mcs51/lkmem.c @@ -349,3 +349,157 @@ int summary(struct area * areap) fclose(of); return toreturn; } + +extern char idatamap[]; //0:not used, 1:used + + +int summary2(struct area * areap) +{ + #define EQ(A,B) !as_strcmpi((A),(B)) + #define MIN_STACK 16 + + char buff[128]; + int j, toreturn=0; + long int Stack_Start=0; + + struct area * xp; + FILE * of; + + /*Artifacts used for printing*/ + char start[15], end[15], size[15], max[15]; + char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n"; + char line[]="---------------------"; + + typedef struct + { + unsigned long Start; + unsigned long Size; + unsigned long Max; + char Name[NCPS]; + unsigned long flag; + } _Mem; + + _Mem Stack={0xff, 0, 1, "STACK", 0x0000}; + _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100}; + _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200}; + + if(rflag) /*For the DS390*/ + { + XRam.Max=0x1000000; /*24 bits*/ + XRam.Start=0xffffff; + Rom.Max=0x1000000; + Rom.Start=0xffffff; + } + + /* Open Memory Summary File*/ + of = afile(linkp->f_idp, "mem", 1); + if (of == NULL) + { + lkexit(1); + } + + xp=areap; + while (xp) + { + if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") || + EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") ) + { + Rom.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if (EQ(xp->a_id, "SSEG")) + { + Stack.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) + { + XRam.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + xp=xp->a_ap; + } + + /*Report the Ram totals*/ + fprintf(of, "Internal RAM layout:\n"); + fprintf(of, " 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(of, "\n0x%02x:|", j); + fprintf(of, "%c|", idatamap[j]); + } + fprintf(of, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n"); + + for(j=0; j<256; j++) + { + if(idatamap[j]=='S') + { + Stack_Start=j; + break; + } + } + + xp=areap; + while (xp) + { + if(xp->a_unaloc>0) + { + fprintf(of, "\nERROR: Couldn't get %d byte%s allocated" + " in internal RAM for area %s.", + xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id); + toreturn=1; + } + xp=xp->a_ap; + } + + /*Report the position of the begining of the stack*/ + if(Stack_Start!=256) + fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)", + rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1); + else + fprintf(of, "\nI don't have a clue where the stack ended up! Sorry..."); + + fprintf(of, "\n\nOther memory:\n"); + fprintf(of, format, "Name", "Start", "End", "Size", "Max"); + fprintf(of, format, line, line, line, line, line); + + /*Report XRam totals:*/ + sprintf(start, "0x%04lx", XRam.Start); + if(XRam.Size==0) + end[0]=0;/*Empty string*/ + else + sprintf(end, "0x%04lx", XRam.Size+XRam.Start-1); + sprintf(size, "%5lu", XRam.Size); + sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size); + fprintf(of, format, XRam.Name, start, end, size, max); + + /*Report Rom/Flash totals:*/ + sprintf(start, "0x%04lx", Rom.Start); + if(Rom.Size==0) + end[0]=0;/*Empty string*/ + else + sprintf(end, "0x%04lx", Rom.Size+Rom.Start-1); + sprintf(size, "%5lu", Rom.Size); + sprintf(max, "%5lu", code_size<0?Rom.Max:code_size); + fprintf(of, format, Rom.Name, start, end, size, max); + + /*Report any excess:*/ + if( ((XRam.Start+XRam.Size)>XRam.Max) || + (((int)XRam.Size>xram_size)&&(xram_size>=0)) ) + { + sprintf(buff, "Insufficient EXTERNAL RAM memory.\n"); + REPORT_ERROR(buff, 1); + } + if( ((Rom.Start+Rom.Size)>Rom.Max) || + (((int)Rom.Size>code_size)&&(code_size>=0)) ) + { + sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n"); + REPORT_ERROR(buff, 1); + } + + fclose(of); + return toreturn; +}