From 0cc37f82bd9e8cbb775898f682d601f4e55198de Mon Sep 17 00:00:00 2001 From: jesusc Date: Wed, 4 Sep 2002 09:44:53 +0000 Subject: [PATCH] Creation of default areas. Improved memory usage. Stack diagnostics. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2094 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- as/mcs51/aslink.h | 5 + as/mcs51/lkarea.c | 26 +++++ as/mcs51/lkdata.c | 2 + as/mcs51/lklist.c | 272 +++++++++++++++++++++++++++++++++++++++++++++- as/mcs51/lkmain.c | 44 ++++++++ 5 files changed, 347 insertions(+), 2 deletions(-) diff --git a/as/mcs51/aslink.h b/as/mcs51/aslink.h index 0c746ca7..9ce5dc4c 100644 --- a/as/mcs51/aslink.h +++ b/as/mcs51/aslink.h @@ -565,6 +565,8 @@ extern int oflag; /* Output file type flag */ extern int mflag; /* Map output flag */ +extern int sflag; /* JCF: Memory usage output flag + */ extern int jflag; /* NoICE output flag */ extern int xflag; /* Map file radix type flag @@ -747,6 +749,9 @@ extern char *StoreString( char *str ); /* lknoice.c */ extern void DefineNoICE( char *name, Addr_T value, int page ); +/* JCF: lksmry.c */ +extern int summary(struct area * xp); + /* SD added this to change strcmpi --> strcmp (strcmpi NOT ANSI) */ #define strcmpi strcmp diff --git a/as/mcs51/lkarea.c b/as/mcs51/lkarea.c index cdc3c071..1d979b4f 100644 --- a/as/mcs51/lkarea.c +++ b/as/mcs51/lkarea.c @@ -320,6 +320,9 @@ lnkarea() 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; @@ -375,6 +378,29 @@ lnkarea() 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_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 rellocation counter*/ + if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) ) + { + rloc[0]-=8; + } + else break; + } + } ap = ap->a_ap; } } diff --git a/as/mcs51/lkdata.c b/as/mcs51/lkdata.c index dae15e71..cab80ee4 100644 --- a/as/mcs51/lkdata.c +++ b/as/mcs51/lkdata.c @@ -48,6 +48,8 @@ int oflag; /* Output file type flag */ int mflag; /* Map output flag */ +int sflag; /* JCF: Memory usage output flag + */ int aflag; /* Overlapping area warning flag */ int jflag; /* NoICE output flag diff --git a/as/mcs51/lklist.c b/as/mcs51/lklist.c index 3743240d..cdf4fe25 100644 --- a/as/mcs51/lklist.c +++ b/as/mcs51/lklist.c @@ -205,7 +205,8 @@ struct area *xp; fprintf(mfp, "Decimal\n\n"); } fprintf(mfp, "Area "); - fprintf(mfp, "Addr Size Decimal Bytes (Attributes)\n"); + fprintf(mfp, "Addr Size Decimal %s (Attributes)\n", + (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/ fprintf(mfp, "-------------------------------- "); fprintf(mfp, "---- ---- ------- ----- ------------\n"); /* @@ -224,7 +225,8 @@ struct area *xp; if (xflag == 2) { fprintf(mfp, " %05u %05u", ai, aj); } - fprintf(mfp, " = %6u. bytes ", aj); + fprintf(mfp, " = %6u. %s ", aj, + (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/ if (xp->a_flag & A_ABS) { fprintf(mfp, "(ABS"); } else { @@ -1094,3 +1096,269 @@ char *str; } return(1); } + +/*JCF: Create a memory summary file with extension .mem*/ +int summary(struct area * areap) +{ + #define EQ(A,B) !strcmpi((A),(B)) + #define MIN_STACK 16 + #define REPORT_ERROR(A) { fprintf(of, "%s", (A)); \ + printf("%s", (A)); \ + toreturn=1; } + + #define REPORT_WARNING(A) { fprintf(of, "%s", (A)); \ + printf("%s", (A));} + + char buff[128]; + int j, toreturn=0; + unsigned int Total_Last=0, k; + + struct area * xp; + FILE * of; + + /*Artifacts used for printing*/ + char start[8], end[8], size[8]; + char format[]=" %-20.20s %-7.7s %-7.7s %-7.7s\n"; + char line[]="---------------------"; + + typedef struct + { + unsigned int Start; + unsigned int Size; + char Name[NCPS]; + unsigned int flag; + } _Mem; + + unsigned int dram[0x100]; + _Mem Ram[]={ + {0, 8, "REG_BANK_0", 0x0001}, + {0x8, 8, "REG_BANK_1", 0x0002}, + {0x10, 8, "REG_BANK_2", 0x0004}, + {0x18, 8, "REG_BANK_3", 0x0008}, + {0x20, 0, "BSEG_BYTES", 0x0010}, + {0, 0, "UNUSED", 0x0000}, + {0x7f, 0, "DATA", 0x0020}, + {0, 0, "TOTAL:", 0x0000} + }; + + _Mem IRam= {0xff, 0, "INDIRECT RAM", 0x0080}; + _Mem Stack={0xff, 0, "STACK", 0x0000}; + _Mem XRam= {0xffff, 0, "EXTERNAL RAM", 0x0100}; + _Mem Rom= {0xffff, 0, "ROM/EPROM/FLASH", 0x0200}; + + for(j=0; j<0x100; j++) dram[j]=0; + + /* 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, "REG_BANK_0")) + { + Ram[0].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_1")) + { + Ram[1].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_2")) + { + Ram[2].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_3")) + { + Ram[3].Size=xp->a_size; + } + else if (EQ(xp->a_id, "BSEG_BYTES")) + { + Ram[4].Size=xp->a_size; + } + else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") ) + { + Ram[6].Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else 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; + } + + else if (EQ(xp->a_id, "ISEG")) + { + IRam.Size+=xp->a_size; + if(xp->a_addra_addr; + } + xp=xp->a_ap; + } + + for(j=0; j<7; j++) + for(k=Ram[j].Start; k<(Ram[j].Start+Ram[j].Size); k++) + dram[k]|=Ram[j].flag; /*Mark as used*/ + + for(k=IRam.Start; k<(IRam.Start+IRam.Size); k++) + dram[k]|=IRam.flag; /*Mark as used*/ + + /*Compute the amount of unused memory in direct data Ram. This is the + gap between the last register bank or bit segment and the data segment.*/ + for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--); + Ram[5].Start=k+1; + Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/ + + /*Compute the data Ram totals*/ + for(j=0; j<7; j++) + { + if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start; + Ram[7].Size+=Ram[j].Size; + } + Total_Last=Ram[6].Size+Ram[6].Start-1; + + /*Report the Ram totals*/ + fprintf(of, "Direct Internal RAM:\n"); + fprintf(of, format, "Name", "Start", "End", "Size"); + + for(j=0; j<8; j++) + { + if((j==0) || (j==7)) fprintf(of, format, line, line, line, line); + if((j!=5) || (Ram[j].Size>0)) + { + sprintf(start, "0x%02x", Ram[j].Start); + if(Ram[j].Size==0) + end[0]=0;/*Empty string*/ + else + sprintf(end, "0x%02x", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1); + sprintf(size, "%5u", Ram[j].Size); + fprintf(of, format, Ram[j].Name, start, end, size); + } + } + + for(k=Ram[6].Start; k<(Ram[6].Start+Ram[6].Size); k++) + { + if(dram[k]!=Ram[6].flag) + { + sprintf(buff, "*** ERROR: There is a memory overlap starting at 0x%02x.\n", k); + REPORT_ERROR(buff); + break; + } + } + + if(Ram[7].Size>0x80) + { + sprintf(buff, "*** ERROR: Insuficient DRAM memory. " + "%d byte%s short.", Ram[7].Size-0x80); + REPORT_ERROR(buff); + } + + if(Ram[5].Size!=0) + { + sprintf(buff, "*** WARNING: %d bytes in DRAM wasted. " + "Link could use: --data-loc 0x%02x\n", + Ram[5].Size, Ram[6].Start-Ram[5].Size); + REPORT_WARNING(buff); + } + + /*Report the position of the begining of the stack*/ + fprintf(of, "\nStack starts at: 0x%02x", Stack.Start); + + /*Check that the stack pointer is landing in a safe place:*/ + if(dram[Stack.Start]) + { + fprintf(of, ".\n"); + sprintf(buff, "*** ERROR: Stack overlaps area "); + REPORT_ERROR(buff); + for(j=0; j<7; j++) + { + if(dram[Stack.Start]&Ram[j].flag) + { + sprintf(buff, "'%s'\n", Ram[j].Name); + break; + } + } + if(dram[Stack.Start]&IRam.flag) + { + sprintf(buff, "'%s'\n", IRam.Name); + } + REPORT_ERROR(buff); + } + else + { + for(j=Stack.Start, k=0; (j<0x100)&&(dram[j]==0); j++, k++); + fprintf(of, " with %d bytes available\n", k); + if (k0x80) + { + sprintf(buff, "*** ERROR: Insuficient INDIRECT RAM memory.\n"); + REPORT_ERROR(buff); + } + if(XRam.Size>0x10000) + { + sprintf(buff, "*** ERROR: Insuficient EXTERNAL RAM memory.\n"); + REPORT_ERROR(buff); + } + if(Rom.Size>0x10000) + { + sprintf(buff, "*** ERROR: Insuficient ROM/EPROM/FLASH memory.\n"); + REPORT_ERROR(buff); + } + + fclose(of); + return toreturn; +} diff --git a/as/mcs51/lkmain.c b/as/mcs51/lkmain.c index 3b0dbfe9..899e70e1 100644 --- a/as/mcs51/lkmain.c +++ b/as/mcs51/lkmain.c @@ -51,6 +51,40 @@ extern int unlink(const char *); * */ +/*JCF: Creates some of the default areas so they are allocated in the right order.*/ +void Areas51 (void) +{ + char * rel[]={ + "XH", + "H 7 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", + "A REG_BANK_2 size 0 flags 4", + "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()*/ + "" + }; + int j; + + for (j=0; rel[j][0]!=0; j++) + { + ip=rel[j]; + link_main(); + } + + /*Set the start address of the default areas:*/ + for(ap=areap; ap; ap=ap->a_ap) + { + /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; } + else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; } + 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; } + } +} + /*)Function VOID main(argc,argv) * * int argc number of command line arguments + 1 @@ -221,6 +255,8 @@ char *argv[]; filep = linkp; hp = NULL; radix = 10; + + Areas51(); /*JCF: Create the default 8051 areas in the right order*/ while (getline()) { ip = ib; @@ -269,6 +305,9 @@ char *argv[]; if (mflag || jflag) map(); + if (sflag) /*JCF: memory usage summary output*/ + if(summary(areap))lkexit(1); + if (iram_size) iramcheck(); @@ -674,6 +713,11 @@ parse() ++mflag; break; + case 'y': /*JCF: memory usage summary output*/ + case 'Y': + ++sflag; + break; + case 'j': case 'J': jflag = 1; -- 2.30.2