+2002-12-10 Jesus Calvino-Fraga <jesusc@ece.ubc.ca>
+
+ * in \sdcc\as\mcs51\ changed these files in order to create an
+ aomf51 file: aslink.h, lkdta.c, lklex.c, lklibr.c, lklist.c,
+ lkmain.c. Also added: lkmem.c and lkaomf51.c. Changed the
+ following files to include the previous two files: aslink.dsp,
+ Makefile.aslink, Makefile.bcc, and Makefile.in.
+
+ * Changed \sdcc\src\SDCCmain.c so it creates files with extension
+ .adb instead of .cdb
+
2002-11-09 Jesus Calvino-Fraga <jesusc@ece.ubc.ca>
* \sdcc\as\mcs51\lklist.c: Now reports memory usage using the
#endif
/*
- * PATH_AMX
+ * PATH_MAX
*/
#include <limits.h>
#ifndef PATH_MAX /* POSIX, but not required */
-#define PATH_MAX 255 /* define a reasonable value */
+ #if defined(__BORLANDC__) || defined(_MSC_VER)
+ #include <stdlib.h>
+ #define PATH_MAX _MAX_PATH
+ #else
+ #define PATH_MAX 255 /* define a reasonable value */
+ #endif
#endif
/*
extern char rb[NINPUT]; /* LST file text line being
* address relocated
*/
-extern char ctype[]; /* array of character types, one per
+extern unsigned char ctype[]; /* array of character types, one per
* ASCII character
*/
/* lknoice.c */
extern void DefineNoICE( char *name, Addr_T value, int page );
-/* JCF: lksmry.c */
+/* JCF: lkmem.c */
extern int summary(struct area * xp);
+/* JCF: lkaomf51.c */
+extern void SaveLinkedFilePath(char * filepath);
+extern void CreateAOMF51(void);
+
/* SD added this to change
strcmpi --> strcmp (strcmpi NOT ANSI) */
#define strcmpi strcmp
--- /dev/null
+/*-------------------------------------------------------------------------
+ lkaomf51.c - Create an absolute object memory format 51 file
+
+ Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MEMSIZE 0x10000
+
+typedef struct
+{
+ char PathName[PATH_MAX];
+ char ModuleName[PATH_MAX];
+} _infn;
+
+int numin=0;
+_infn * infn=NULL;
+
+char ihxFileName[PATH_MAX];
+char aomf51FileName[PATH_MAX];
+
+typedef struct
+{
+ char name[0x100];
+ int FileNameNumber;
+ int Procedure;//If the symbol belongs to a function
+ int Static; //If the symbol is only public on its file
+ int Address;
+ int UsageType;
+} _symbol;
+
+int numsym=0;
+_symbol * symbol=NULL;
+
+typedef struct
+{
+ char name[0x100];
+ int FileNameNumber;
+ int BeginAdd;
+ int EndAdd;
+} _procedure;
+
+int numproc=0;
+_procedure * procedure=NULL;
+
+typedef struct
+{
+ int Number;
+ int Address;
+ int Procedure;
+ int FileNameNumber;
+} _linenum;
+
+int numlinenum=0;
+_linenum * linenum=NULL;
+
+typedef struct
+{
+ char * name;
+ int usage;
+}
+_UsageType;
+
+_UsageType UsageType[]=
+{
+ {"CSEG", 0},
+ {"GSINIT", 0},
+ {"GSFINAL", 0},
+ {"HOME", 0},
+ {"XINIT", 0},
+ {"XSEG", 1},
+ {"XISEG", 1},
+ {"REG_BANK_0", 2},
+ {"REG_BANK_1", 2},
+ {"REG_BANK_2", 2},
+ {"REG_BANK_3", 2},
+ {"DSEG", 2},
+ {"OSEG", 2},
+ {"SSEG", 2},
+ {"ISEG", 3},
+ {"BSEG", 4},
+ {"", 5} /*A typeless number?*/
+};
+
+char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"};
+int AddNumber;
+unsigned char * ihxBuff=NULL;
+FILE * aomf51out;
+int GlobalChkSum=0;
+int HexSize, HexBegin=0x10000;
+
+
+void GetName(char * filepath, char * name)
+{
+ int j, k;
+ for(j=strlen(filepath); j>0; j--)
+ if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break;
+ for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++)
+ name[k]=filepath[j];
+ name[k]=0;
+}
+
+void SaveLinkedFilePath(char * filepath)
+{
+ int j;
+
+ if(dflag)
+ {
+ infn=realloc(infn, sizeof(_infn)*(numin+1));
+
+ strcpy(infn[numin].PathName, filepath);
+ j=strlen(infn[numin].PathName);
+
+ /*If there is an extension remove it*/
+ if(j>=4)
+ {
+ if(EQ(&infn[numin].PathName[j-4], ".rel"))
+ {
+ infn[numin].PathName[j-4]=0;
+ }
+ }
+
+ /*Get the module name=filename, no drive, no dir, no ext*/
+ GetName(infn[numin].PathName, infn[numin].ModuleName);
+ //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName);
+
+ numin++;
+ }
+}
+
+void FreeAll(void)
+{
+ if(infn!=NULL)
+ {
+ free(infn);
+ numin=0;
+ infn=NULL;
+ }
+
+ if(symbol!=NULL)
+ {
+ free(symbol);
+ numsym=0;
+ symbol=NULL;
+ }
+
+ if(procedure!=NULL)
+ {
+ free(procedure);
+ numproc=0;
+ procedure=NULL;
+
+ }
+ if(linenum!=NULL)
+ {
+ free(linenum);
+ numlinenum=0;
+ linenum=NULL;
+ }
+
+ if(ihxBuff!=NULL)
+ {
+ free(ihxBuff);
+ ihxBuff=NULL;
+ }
+}
+
+void OutputByte(unsigned char value)
+{
+ GlobalChkSum+=value;
+ fwrite( &value, 1, 1, aomf51out );
+}
+
+void OutputWord(int value)
+{
+ OutputByte((unsigned char)(value%0x100));
+ OutputByte((unsigned char)(value/0x100));
+}
+
+void OutputName(char * name)
+{
+ int k;
+ OutputByte((unsigned char)strlen(name));
+ for(k=0; name[k]!=0; k++)
+ OutputByte((unsigned char)toupper(name[k]));
+}
+
+void OutputChkSum(void)
+{
+ OutputByte((unsigned char)(0x100-(GlobalChkSum%0x100)));
+ GlobalChkSum=0;
+}
+
+void DumpForDebug (void)
+{
+ char DumpFileName[PATH_MAX];
+ FILE * DumpFile;
+ int j;
+
+ strcpy(DumpFileName, infn[0].PathName);
+ strcat(DumpFileName, ".d51");
+
+ DumpFile=fopen(DumpFileName, "wb");
+ if(DumpFile==NULL)
+ {
+ printf("Couldn't create file %s\n", DumpFileName);
+ return;
+ }
+
+ fprintf(DumpFile,"SYMBOLS:\n");
+
+ for(j=0; j<numsym; j++)
+ {
+ fprintf(DumpFile, "%s, %s, %s, 0x%04x, %s\n",
+ symbol[j].name,
+ infn[symbol[j].FileNameNumber].PathName,
+ (symbol[j].Procedure>=0)?procedure[symbol[j].Procedure].name:"GLOBAL",
+ symbol[j].Address,
+ UsageTypeName[symbol[j].UsageType&0xf]);
+ }
+
+ fprintf(DumpFile,"\nPROCEDURES:\n");
+ for(j=0; j<numproc; j++)
+ {
+ fprintf(DumpFile, "%s, %s, 0x%04x-0x%04x\n",
+ procedure[j].name,
+ infn[procedure[j].FileNameNumber].PathName,
+ procedure[j].BeginAdd,
+ procedure[j].EndAdd);
+ }
+
+ fprintf(DumpFile,"\nLINE NUMBERS:\n");
+ for(j=0; j<numlinenum; j++)
+ {
+ fprintf(DumpFile, "%d:0x%04x, %s -> %s\n",
+ linenum[j].Number,
+ linenum[j].Address,
+ infn[linenum[j].FileNameNumber].PathName,
+ (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know");
+ }
+
+ fclose(DumpFile);
+}
+
+void OutputAOEMF51(void)
+{
+ int i, j, k, recsize;
+ char MHRname[0x100], Mname[0x100];
+
+ strcpy(aomf51FileName, infn[0].PathName);
+
+ aomf51out=fopen(aomf51FileName, "wb");
+ if(aomf51out==NULL)
+ {
+ printf("Couldn't create file %s\n", aomf51FileName);
+ return;
+ }
+
+ GetName(infn[0].PathName, MHRname);
+ GlobalChkSum=0;
+
+ /*Module header record*/
+ OutputByte(0x02);/*REC TYPE*/
+ OutputWord((strlen(MHRname)+1)+3);/*Record Length*/
+ OutputName(MHRname);/*Module Name*/
+ OutputByte(0xff);/*TRN ID: RL51?*/
+ OutputByte(0x00);
+ OutputChkSum();
+
+ for(j=0; j<numin; j++)
+ {
+ GetName(infn[j].PathName, Mname);
+
+ /*Scope Definition record: begin module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x00);/*BLK TYP: module block*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ /*Public symbols defined in this module*/
+ recsize=2;
+ for(k=0; k<numsym; k++)/*Compute the record length*/
+ if ( (symbol[k].FileNameNumber==j) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==-1) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x01); /*DEF TYPE: Public symbols*/
+ for(k=0; k<numsym; k++)
+ {
+ if ( (symbol[k].FileNameNumber==j) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==-1) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+ OutputWord(symbol[k].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[k].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Local symbols defined in this module*/
+ recsize=2;
+ for(k=0; k<numsym; k++)/*Compute the record length*/
+ if ( (symbol[k].FileNameNumber==j) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==j) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00); /*DEF TYPE: Local symbols*/
+ for(k=0; k<numsym; k++)
+ {
+ if ( (symbol[k].FileNameNumber==j) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==j) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+ OutputWord(symbol[k].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[k].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Output the procedures of this module*/
+
+ for(k=0; k<numproc; k++)
+ {
+ if(procedure[k].FileNameNumber==j)
+ {
+ /*Scope Definition record: begin PROCEDURE block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+ OutputByte(0x02);/*BLK TYP: PROCEDURE block*/
+ OutputName(procedure[k].name);/*Module Name*/
+ OutputChkSum();
+
+ /*Content Record*/
+ OutputByte(0x06);/*REC TYPE*/
+ recsize=procedure[k].EndAdd-procedure[k].BeginAdd+1+4;
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(procedure[k].BeginAdd); /*Offset*/
+ for(i=procedure[k].BeginAdd; i<=procedure[k].EndAdd; i++)
+ OutputByte(ihxBuff[i]);
+ OutputChkSum();
+
+ /*Local Symbols*/
+
+ recsize=2;
+ for(i=0; i<numsym; i++)/*Get the record length*/
+ if(symbol[i].Procedure==k)
+ recsize+=((strlen(symbol[i].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00); /*DEF TYPE: Local symbols*/
+ for(i=0; i<numsym; i++)
+ {
+ if ( (symbol[i].Procedure==k) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[i].UsageType);/*SYM INFO*/
+ OutputWord(symbol[i].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[i].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Line Numbers*/
+ recsize=2;
+ for(i=0; i<numlinenum; i++)/*Get the record length*/
+ if(linenum[i].Procedure==k) recsize+=5;
+
+ if(recsize>2) /*If there are any line numbers*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x03); /*DEF TYPE: Line numbers*/
+ for(i=0; i<numlinenum; i++)
+ {
+ if ( (linenum[i].Procedure==k) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(linenum[i].Address);/*Offset*/
+ OutputWord(linenum[i].Number);/*Line Number*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Scope Definition record: end PROCEDURE block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+ OutputByte(0x05);/*BLK TYP: PROCEDURE end block*/
+ OutputName(procedure[k].name);/*Module Name*/
+ OutputChkSum();
+ }
+ }
+
+ /*Scope Definition record: end module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x03);/*BLK TYP: module end*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+ }
+
+ /*Content records for everything that is not in the above procedures*/
+ strcpy(Mname, "OTHER_SDCC_STUF");
+
+ /*Scope Definition record: begin module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x00);/*BLK TYP: module block*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ for(j=-1; j<numproc; j++)
+ {
+ if(j==-1)
+ {
+ i=HexBegin;
+ k=procedure[0].BeginAdd;
+ }
+ else if(j==(numproc-1))
+ {
+ i=procedure[j].EndAdd+1;
+ k=HexSize;
+ }
+ else
+ {
+ i=procedure[j].EndAdd+1;
+ k=procedure[j+1].BeginAdd;
+ }
+
+ if(i<k)
+ {
+ /*Content Record*/
+ OutputByte(0x06);/*REC TYPE*/
+ OutputWord(k-i+4);/*Record Length*/
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(i); /*Offset*/
+ for(; i<k; i++) OutputByte(ihxBuff[i]);
+ OutputChkSum();
+ }
+ }
+
+ /*Scope Definition record: end module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x03);/*BLK TYP: module end*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ /*Module end record*/
+ OutputByte(0x04);/*REC TYPE*/
+ OutputWord((strlen(MHRname)+1)+5);/*Record Length*/
+ OutputName(MHRname);/*Module Name*/
+ OutputWord(0x00);
+ OutputByte(0x0f);/*REG MSK: All the register banks?*/
+ OutputByte(0x00);
+ OutputChkSum();
+
+ fclose(aomf51out);
+}
+
+void CollectInfoFromCDB(void)
+{
+ int i, j, k, CurrentModule;
+ FILE * CDBin;
+ char buff[0x1000];
+ char SourceName[PATH_MAX];
+
+ //"S:{G|F<filename>|L<functionName>}$<name>$<level>$<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>"
+ char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s";
+ char c;
+ char scope[0x100];
+ char name[0x100];
+ char level[0x100];
+ char block[0x100];
+ char Bfmt[]="%[^)] %c %c %c %c %d %c %d";
+ char TypeInfo[0x100];
+ char AddressSpace;
+ int OnStack;
+ int StackOffset;
+ int Address, CLine;
+
+ if(numin==0) return;
+
+ if (dfp != NULL)
+ {
+ fclose(dfp);
+ dfp=NULL;
+ }
+
+ /*Build the source filename*/
+ strcpy(SourceName, infn[0].PathName);
+ strcat(SourceName, ".cdb");
+ CDBin=fopen(SourceName, "r");
+ if(CDBin==NULL)
+ {
+ printf("Couldn't open file '%s'\n", SourceName);
+ }
+
+ CurrentModule=0; /*Set the active module as the first one*/
+ while(!feof(CDBin))
+ {
+ fgets(buff, sizeof(buff)-1, CDBin);
+
+ if(!feof(CDBin)) switch(buff[0])
+ {
+ /*Example: "M:adq"*/
+ case 'M':
+ sscanf(&buff[2], "%s", name);
+ for(j=0; j<numin; j++)
+ if(EQ(infn[j].ModuleName, name)) break;
+ if(j<numin) CurrentModule=j;
+ break;
+
+ /* Example:
+ "S:G$actual$0$0({7}ST__00010000:S),E,0,0"
+ "S:Lmain$j$1$1({2}SI:S),E,0,0"
+ */
+
+ case 'S':
+ sscanf(buff, Sfmt,
+ scope, &c,
+ name, &c,
+ level, &c,
+ block);
+
+ /*<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>*/
+ sscanf(block, Bfmt,
+ TypeInfo, &c, &c,
+ &AddressSpace, &c,
+ &OnStack, &c,
+ &StackOffset);
+
+ i=-1; k=-1;
+ switch(scope[2])
+ {
+ case 'G': /*Global symbol*/
+ break;
+ case 'L': /*Local symbol of a procedure*/
+ for(j=0; j<numproc; j++)
+ {
+ if(EQ(&scope[3], procedure[j].name)) break;
+ }
+ if(j<numproc) k=j; /*Local symbol*/
+ break;
+ case 'F': /*Local symbol to a module*/
+ for(j=0; j<numin; j++)
+ {
+ if(EQ(&scope[3], infn[j].ModuleName)) break;
+ }
+ if(j<numin) i=j;
+ break;
+ }
+
+ /*This symbol may have been already defined*/
+ for(j=0; j<numsym; j++)
+ {
+ if( EQ(name, symbol[j].name) &&
+ (symbol[j].Procedure==k) &&
+ (symbol[j].Static==i) ) break;
+ }
+ if(j==numsym) /*New symbol*/
+ {
+ symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+ symbol[numsym].FileNameNumber=CurrentModule;
+ strcpy(symbol[numsym].name, name);
+ symbol[numsym].Procedure=k;
+ symbol[numsym].Static=i;
+ symbol[numsym].Address=-1;/*Collected later*/
+
+ switch(AddressSpace)
+ {
+ case 'C': /*Code*/
+ case 'D': /*Code/static segment*/
+ symbol[numsym].UsageType=0x40;
+ break;
+
+ case 'F': /*External ram*/
+ case 'A': /*External stack*/
+ symbol[numsym].UsageType=0x41;
+ break;
+
+ case 'E': /*Internal ram (lower 128) bytes*/
+ case 'I': /*SFR space*/
+ symbol[numsym].UsageType=0x42;
+ break;
+
+ case 'B': /*Internal stack*/
+ case 'G': /*Internal ram*/
+ symbol[numsym].UsageType=0x43;
+ break;
+
+ case 'H': /*Bit addressable*/
+ case 'J': /*SBIT space*/
+ symbol[numsym].UsageType=0x44;
+ break;
+ }
+ numsym++;
+ }
+ break;
+
+ /*Examples:
+ F:G$AsciiToHex$0$0({2}DF,SC:U),C,0,0,0,0,0
+ F:G$main$0$0({2}DF,SV:S),C,0,0,0,0,0 */
+
+ case 'F':
+ sscanf(buff, "%[^$] %c %[^$]", scope, &c, name);
+ /*The same may have been already defined */
+ for(j=0; j<numproc; j++)
+ {
+ if(EQ(name, procedure[j].name)) break;
+ }
+ if(j==numproc)
+ {
+ procedure=realloc(procedure, sizeof(_procedure)*(numproc+1));
+ strcpy(procedure[numproc].name, name);
+ procedure[numproc].FileNameNumber=CurrentModule;
+ procedure[numproc].BeginAdd=-1;/*To be collected latter*/
+ procedure[numproc].EndAdd=-1;/*To be collected latter*/
+ numproc++;
+ }
+
+ /*This function name is also a global symbol*/
+ for(j=0; j<numsym; j++)/*A global symbol may have been already defined*/
+ {
+ if( EQ(name, symbol[j].name) && (symbol[j].Procedure==-1) ) break;
+ }
+ if(j==numsym)
+ {
+ symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+ symbol[numsym].FileNameNumber=CurrentModule;
+ strcpy(symbol[numsym].name, name);
+ symbol[numsym].UsageType=0x00;/*A procedure name symbol*/
+ symbol[numsym].Procedure=-1; /*Global symbol*/
+ symbol[numsym].Address=-1;/*Collected later*/
+ numsym++;
+ }
+
+ break;
+
+ case 'L':
+ switch(buff[2])
+ {
+ case 'G': /*Example L:G$P0$0$0:80*/
+ sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(j=0; j<numsym; j++)
+ {
+ if(EQ(symbol[j].name, name))
+ {
+ if( (symbol[j].Address==-1) && (symbol[j].Procedure==-1) )
+ {
+ symbol[j].Address=Address;
+ /*If the symbol is the name of a procedure, the address is also
+ the begining of such procedure*/
+ if(symbol[j].UsageType==0x00)
+ {
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(symbol[j].name, procedure[k].name))
+ {
+ if(procedure[k].BeginAdd==-1)
+ procedure[k].BeginAdd=Address;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case 'F': /*Example L:Fadq$_str_2$0$0:57A*/
+ sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(j=0; j<numsym; j++)
+ {
+ if(EQ(symbol[j].name, name))
+ {
+ if( (symbol[j].Address==-1) ) symbol[j].Address=Address;
+ break;
+ }
+ }
+ break;
+
+ case 'L': /*Example L:Lmain$j$1$1:29*/
+
+ /*
+ L:LDS1306_Write$Value$1$1:34
+ L:LDS1306_Burst_Read$count$1$1:35
+ L:LDS1306_Burst_Read$address$1$1:36
+ L:LDS1306_Burst_Write$count$1$1:37
+ L:LDS1306_Burst_Write$address$1$1:38
+ */
+ sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(procedure[k].name, scope)) break;
+ }
+
+ if(k<numproc) for(j=0; j<numsym; j++)
+ {
+ if( EQ(symbol[j].name, name) && (symbol[j].Procedure==k) )
+ {
+ if(symbol[j].Address==-1) symbol[j].Address=Address;
+ break;
+ }
+ }
+ break;
+
+ /*Line Numbers*/
+ case 'C': /*Example L:C$adq.c$38$1$1:3E*/ /*L:C$hwinit.c$29$1$1:7AD*/
+ sscanf(&buff[4], "%[^.] %[^$] %c %d %[^:] %c %x",
+ name, level, &c, &CLine, level, &c, &Address);
+
+ for(j=0; j<numin; j++)
+ if(EQ(infn[j].ModuleName, name)) break;
+ if(j<numin)
+ {
+ /*Check if this line is already defined*/
+ for(k=0; k<numlinenum; k++)
+ {
+ if( (linenum[k].Number==CLine) &&
+ (linenum[k].FileNameNumber==j) )break;
+ }
+ if(k==numlinenum) /*New line number*/
+ {
+ linenum=realloc(linenum, sizeof(_linenum)*(numlinenum+1));
+ linenum[numlinenum].Number=CLine;
+ linenum[numlinenum].FileNameNumber=j;
+ linenum[numlinenum].Procedure=-1;/*To be asigned later*/
+ linenum[numlinenum].Address=Address;
+ numlinenum++;
+ }
+ }
+ break;
+
+ case 'A': /*Example L:A$adq$424:40*/
+ /*No use for this one*/
+ break;
+
+ /*The end of a procedure*/
+ case 'X': /*Example L:XG$AsciiToHex$0$0:88*/
+ sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(procedure[k].name, name))
+ {
+ if(procedure[k].EndAdd==-1) procedure[k].EndAdd=Address;
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*Asign each line number to a procedure*/
+ for(j=0; j<numlinenum; j++)
+ {
+ for(k=0; k<numproc; k++)
+ {
+ if ( (linenum[j].Address>=procedure[k].BeginAdd) &&
+ (linenum[j].Address<=procedure[k].EndAdd) &&
+ (linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
+ {
+ linenum[j].Procedure=k;
+ }
+ }
+ }
+
+ fclose(CDBin);
+}
+
+int hex2dec (char hex_digit)
+{
+ int j;
+ j=toupper(hex_digit)-'0';
+ if (j>9) j -= 7;
+ return j;
+}
+
+unsigned char GetByte(char * buffer)
+{
+ return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
+}
+
+unsigned short GetWord(char * buffer)
+{
+ return hex2dec(buffer[0])*0x1000+
+ hex2dec(buffer[1])*0x100+
+ hex2dec(buffer[2])*0x10+
+ hex2dec(buffer[3]);
+}
+
+int ReadHexFile(int * Begin)
+{
+ char buffer[1024];
+ FILE * filein;
+ int j;
+ unsigned char linesize, recordtype, rchksum, value;
+ unsigned short address;
+ int MaxAddress=0;
+ int chksum;
+
+ /*If the hexfile is already open, close it*/
+ if(ofp!=NULL)
+ {
+ fclose(ofp);
+ ofp=NULL;
+ }
+
+ strcpy(ihxFileName, infn[0].PathName);
+ strcat(ihxFileName, ".ihx");
+
+ if ( (filein=fopen(ihxFileName, "r")) == NULL )
+ {
+ printf("Error: Can't open file `%s`.\r\n", ihxFileName);
+ return 0;
+ }
+
+ ihxBuff=calloc(MEMSIZE, sizeof(unsigned char));
+ if(ihxBuff==NULL)
+ {
+ printf("Insufficient memory\n");
+ fclose(filein);
+ return -1;
+ }
+
+ for(j=0; j<MEMSIZE; j++) ihxBuff[j]=0xff;
+
+ while(1)
+ {
+ if(fgets(buffer, sizeof(buffer), filein)==NULL)
+ {
+ printf("Error reading file '%s'\n", ihxFileName);
+ break;
+ }
+ if(buffer[0]==':')
+ {
+ linesize = GetByte(&buffer[1]);
+ address = GetWord(&buffer[3]);
+ recordtype = GetByte(&buffer[7]);
+ rchksum = GetByte(&buffer[9]+(linesize*2));
+ chksum=linesize+(address/0x100)+(address%0x100)+recordtype+rchksum;
+
+ if (recordtype==1) break; /*End of record*/
+
+ for(j=0; j<linesize; j++)
+ {
+ value=GetByte(&buffer[9]+(j*2));
+ chksum+=value;
+ ihxBuff[address+j]=value;
+ }
+ if(MaxAddress<(address+linesize-1)) MaxAddress=(address+linesize-1);
+ if(address<*Begin) *Begin=address;
+
+ if((chksum%0x100)!=0)
+ {
+ printf("ERROR: Bad checksum in file %s\n", ihxFileName);
+ fclose(filein);
+ return -1;
+ }
+ }
+ }
+ fclose(filein);
+
+ return MaxAddress;
+}
+
+void CreateAOMF51(void)
+{
+ if(dflag)
+ {
+ CollectInfoFromCDB();
+ //DumpForDebug();
+ HexSize=ReadHexFile(&HexBegin)+1;
+ OutputAOEMF51();
+ FreeAll();
+ }
+}
* array of character types, one per
* ASCII character
*/
-char ctype[128] = {
+unsigned char ctype[128] = {
/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL,
/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
sfp = afile(fid, "rel", 0);
/* if a .cdb file exists then copy it over */
if (dflag && sfp && dfp && pass == 0) {
- FILE *xfp = afile(fid,"cdb",0);
+ FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002
if (xfp) {
copyfile(dfp,xfp);
fclose(xfp);
}
}
if (uflag && pass != 0) {
+ SaveLinkedFilePath(fid); //Save the linked path for aomf51
if ((tfp = afile(fid, "lst", 0)) != NULL) {
if ((rfp = afile(fid, "rst", 1)) == NULL) {
fclose(tfp);
fclose(libfp);
/* if cdb information required & cdb file present */
if (dflag && dfp) {
- FILE *xfp = afile(str,"cdb",0);
+ FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
if (xfp) {
copyfile(dfp,xfp);
fclose(xfp);
if (dflag &&
strchr(ptr,'$'))
fprintf(dfp,"L:%s:%X\n",ptr,aj);
+
/* NoICE output of symbol */
if (jflag) DefineNoICE( ptr, aj, memPage );
}
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, H) \
- {\
- fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
- fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
- toreturn=1; \
- }
-
- #define REPORT_WARNING(A, H) \
- { \
- fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
- fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (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], max[8];
- char format[]=" %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
- char line[]="---------------------";
-
- typedef struct
- {
- unsigned int Start;
- unsigned int Size;
- unsigned int Max;
- char Name[NCPS];
- unsigned int flag;
- } _Mem;
-
- unsigned int dram[0x100];
- _Mem Ram[]={
- {0, 8, 8, "REG_BANK_0", 0x0001},
- {0x8, 8, 8, "REG_BANK_1", 0x0002},
- {0x10, 8, 8, "REG_BANK_2", 0x0004},
- {0x18, 8, 8, "REG_BANK_3", 0x0008},
- {0x20, 0, 16, "BSEG_BYTES", 0x0010},
- {0, 0, 128, "UNUSED", 0x0000},
- {0x7f, 0, 128, "DATA", 0x0020},
- {0, 0, 128, "TOTAL:", 0x0000}
- };
-
- _Mem IRam= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
- _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((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
- {
- Ram[5].Max=0x80;
- Ram[6].Max=0x80;
- Ram[7].Max=0x80;
- IRam.Max=0x80;
- iram_size=0x100;
- }
- else if(iram_size<0x80)
- {
- Ram[5].Max=iram_size;
- Ram[6].Max=iram_size;
- Ram[7].Max=iram_size;
- IRam.Max=0;
- }
- else
- {
- Ram[5].Max=0x80;
- Ram[6].Max=0x80;
- Ram[7].Max=0x80;
- IRam.Max=iram_size-0x80;
- }
-
- for(j=0; j<(int)iram_size; j++) dram[j]=0;
- for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
-
- /* 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_addr<Ram[6].Start) Ram[6].Start=xp->a_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_addr<Rom.Start) Rom.Start=xp->a_addr;
- }
-
- else if (EQ(xp->a_id, "SSEG"))
- {
- Stack.Size+=xp->a_size;
- if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
- }
-
- else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG"))
- {
- XRam.Size+=xp->a_size;
- if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
- }
-
- else if (EQ(xp->a_id, "ISEG"))
- {
- IRam.Size+=xp->a_size;
- if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
- }
- xp=xp->a_ap;
- }
-
- for(j=0; j<7; j++)
- for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
- dram[k]|=Ram[j].flag; /*Mark as used*/
-
- for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); 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", "Max");
-
- for(j=0; j<8; j++)
- {
- if((j==0) || (j==7)) fprintf(of, format, line, 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);
- sprintf(max, "%5u", Ram[j].Max);
- fprintf(of, format, Ram[j].Name, start, end, size, max);
- }
- }
-
- for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
- {
- if(dram[k]!=Ram[6].flag)
- {
- sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
- REPORT_ERROR(buff, 1);
- break;
- }
- }
-
- if(Ram[4].Size>Ram[4].Max)
- {
- k=Ram[4].Size-Ram[4].Max;
- sprintf(buff, "Insufficient bit addressable memory. "
- "%d byte%s short.\n", k, (k==1)?"":"s");
- REPORT_ERROR(buff, 1);
- }
-
- if(Ram[5].Size!=0)
- {
- sprintf(buff, "%d bytes in DRAM wasted. "
- "SDCC link could use: --data-loc 0x%02x\n",
- Ram[5].Size, Ram[6].Start-Ram[5].Size);
- REPORT_WARNING(buff, 1);
- }
-
- if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
- {
- k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
- sprintf(buff, "Insufficient DRAM memory. "
- "%d byte%s short.\n", k, (k==1)?"":"s");
- REPORT_ERROR(buff, 1);
- }
-
- /*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] & 0x8000) == 0x8000 )
- {
- fprintf(of, ".\n");
- sprintf(buff, "Stack set to unavailable memory.\n");
- REPORT_ERROR(buff, 1);
- }
- else if(dram[Stack.Start])
- {
- fprintf(of, ".\n");
- sprintf(buff, "Stack overlaps area ");
- REPORT_ERROR(buff, 1);
- 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, 0);
- }
- else
- {
- for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
- fprintf(of, " with %d bytes available\n", k);
- if (k<MIN_STACK)
- {
- sprintf(buff, "Only %d byte%s available for stack.\n",
- k, (k==1)?"":"s");
- REPORT_WARNING(buff, 1);
- }
- }
-
- fprintf(of, "\nOther memory:\n");
- fprintf(of, format, "Name", "Start", "End", "Size", "Max");
- fprintf(of, format, line, line, line, line, line);
-
- /*Report IRam totals:*/
- sprintf(start, "0x%02x", IRam.Start);
- if(IRam.Size==0)
- end[0]=0;/*Empty string*/
- else
- sprintf(end, "0x%02x", IRam.Size+IRam.Start-1);
- sprintf(size, "%5u", IRam.Size);
- sprintf(max, "%5u", IRam.Max);
- fprintf(of, format, IRam.Name, start, end, size, max);
-
- /*Report XRam totals:*/
- sprintf(start, "0x%04x", XRam.Start);
- if(XRam.Size==0)
- end[0]=0;/*Empty string*/
- else
- sprintf(end, "0x%04x", XRam.Size+XRam.Start-1);
- sprintf(size, "%5u", XRam.Size);
- sprintf(max, "%5u", XRam.Max);
- fprintf(of, format, XRam.Name, start, end, size, max);
-
- /*Report Rom/Flash totals:*/
- sprintf(start, "0x%04x", Rom.Start);
- if(Rom.Size==0)
- end[0]=0;/*Empty string*/
- else
- sprintf(end, "0x%04x", Rom.Size+Rom.Start-1);
- sprintf(size, "%5u", Rom.Size);
- sprintf(max, "%5u", Rom.Max);
- fprintf(of, format, Rom.Name, start, end, size, max);
-
- /*Report any excess:*/
- if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
- {
- sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
- REPORT_ERROR(buff, 1);
- }
- if((XRam.Start+XRam.Size)>XRam.Max)
- {
- sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
- REPORT_ERROR(buff, 1);
- }
- if((Rom.Start+Rom.Size)>Rom.Max)
- {
- sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
- REPORT_ERROR(buff, 1);
- }
-
- fclose(of);
- return toreturn;
-}
syminit();
if (dflag){
- dfp = afile("temp", "cdb", 1);
+ //dfp = afile("temp", "cdb", 1);
+ dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002
if (dfp == NULL)
lkexit(1);
}
reloc('E');
}
}
+ //JCF:
+ CreateAOMF51();
+
lkexit(lkerr);
return 0;
}
if (rfp != NULL) fclose(rfp);
if (sfp != NULL) fclose(sfp);
if (tfp != NULL) fclose(tfp);
- if (dfp != NULL) {
+ if (dfp != NULL) fclose(dfp);
+ /*if (dfp != NULL)
FILE *xfp = afile(linkp->f_idp,"cdb",1);
dfp = freopen("temp.cdb","r",dfp);
copyfile(xfp,dfp);
fclose(xfp);
fclose(dfp);
unlink("temp.cdb");
- }
+ }*/
exit(i);
}
}
*p2++ = 0;
if ((fp = fopen(fb, omode)) == NULL) {
- if (strcmp(ft,"cdb")) {
+ if (strcmp(ft,"adb")) {
fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
lkerr++;
}
--- /dev/null
+/*-------------------------------------------------------------------------
+ lkmem.c - Create a memory summary file with extension .mem
+
+ Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+int summary(struct area * areap)
+{
+ #define EQ(A,B) !strcmpi((A),(B))
+ #define MIN_STACK 16
+ #define REPORT_ERROR(A, H) \
+ {\
+ fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
+ fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
+ toreturn=1; \
+ }
+
+ #define REPORT_WARNING(A, H) \
+ { \
+ fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
+ fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (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], max[8];
+ char format[]=" %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
+ char line[]="---------------------";
+
+ typedef struct
+ {
+ unsigned int Start;
+ unsigned int Size;
+ unsigned int Max;
+ char Name[NCPS];
+ unsigned int flag;
+ } _Mem;
+
+ unsigned int dram[0x100];
+ _Mem Ram[]={
+ {0, 8, 8, "REG_BANK_0", 0x0001},
+ {0x8, 8, 8, "REG_BANK_1", 0x0002},
+ {0x10, 8, 8, "REG_BANK_2", 0x0004},
+ {0x18, 8, 8, "REG_BANK_3", 0x0008},
+ {0x20, 0, 16, "BSEG_BYTES", 0x0010},
+ {0, 0, 128, "UNUSED", 0x0000},
+ {0x7f, 0, 128, "DATA", 0x0020},
+ {0, 0, 128, "TOTAL:", 0x0000}
+ };
+
+ _Mem IRam= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
+ _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((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
+ {
+ Ram[5].Max=0x80;
+ Ram[6].Max=0x80;
+ Ram[7].Max=0x80;
+ IRam.Max=0x80;
+ iram_size=0x100;
+ }
+ else if(iram_size<0x80)
+ {
+ Ram[5].Max=iram_size;
+ Ram[6].Max=iram_size;
+ Ram[7].Max=iram_size;
+ IRam.Max=0;
+ }
+ else
+ {
+ Ram[5].Max=0x80;
+ Ram[6].Max=0x80;
+ Ram[7].Max=0x80;
+ IRam.Max=iram_size-0x80;
+ }
+
+ for(j=0; j<(int)iram_size; j++) dram[j]=0;
+ for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
+
+ /* 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_addr<Ram[6].Start) Ram[6].Start=xp->a_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_addr<Rom.Start) Rom.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "SSEG"))
+ {
+ Stack.Size+=xp->a_size;
+ if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG"))
+ {
+ XRam.Size+=xp->a_size;
+ if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "ISEG"))
+ {
+ IRam.Size+=xp->a_size;
+ if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
+ }
+ xp=xp->a_ap;
+ }
+
+ for(j=0; j<7; j++)
+ for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
+ dram[k]|=Ram[j].flag; /*Mark as used*/
+
+ for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); 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", "Max");
+
+ for(j=0; j<8; j++)
+ {
+ if((j==0) || (j==7)) fprintf(of, format, line, 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);
+ sprintf(max, "%5u", Ram[j].Max);
+ fprintf(of, format, Ram[j].Name, start, end, size, max);
+ }
+ }
+
+ for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
+ {
+ if(dram[k]!=Ram[6].flag)
+ {
+ sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
+ REPORT_ERROR(buff, 1);
+ break;
+ }
+ }
+
+ if(Ram[4].Size>Ram[4].Max)
+ {
+ k=Ram[4].Size-Ram[4].Max;
+ sprintf(buff, "Insufficient bit addressable memory. "
+ "%d byte%s short.\n", k, (k==1)?"":"s");
+ REPORT_ERROR(buff, 1);
+ }
+
+ if(Ram[5].Size!=0)
+ {
+ sprintf(buff, "%d bytes in DRAM wasted. "
+ "SDCC link could use: --data-loc 0x%02x\n",
+ Ram[5].Size, Ram[6].Start-Ram[5].Size);
+ REPORT_WARNING(buff, 1);
+ }
+
+ if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
+ {
+ k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
+ sprintf(buff, "Insufficient DRAM memory. "
+ "%d byte%s short.\n", k, (k==1)?"":"s");
+ REPORT_ERROR(buff, 1);
+ }
+
+ /*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] & 0x8000) == 0x8000 )
+ {
+ fprintf(of, ".\n");
+ sprintf(buff, "Stack set to unavailable memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ else if(dram[Stack.Start])
+ {
+ fprintf(of, ".\n");
+ sprintf(buff, "Stack overlaps area ");
+ REPORT_ERROR(buff, 1);
+ 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, 0);
+ }
+ else
+ {
+ for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
+ fprintf(of, " with %d bytes available\n", k);
+ if (k<MIN_STACK)
+ {
+ sprintf(buff, "Only %d byte%s available for stack.\n",
+ k, (k==1)?"":"s");
+ REPORT_WARNING(buff, 1);
+ }
+ }
+
+ fprintf(of, "\nOther memory:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+ fprintf(of, format, line, line, line, line, line);
+
+ /*Report IRam totals:*/
+ sprintf(start, "0x%02x", IRam.Start);
+ if(IRam.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%02x", IRam.Size+IRam.Start-1);
+ sprintf(size, "%5u", IRam.Size);
+ sprintf(max, "%5u", IRam.Max);
+ fprintf(of, format, IRam.Name, start, end, size, max);
+
+ /*Report XRam totals:*/
+ sprintf(start, "0x%04x", XRam.Start);
+ if(XRam.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04x", XRam.Size+XRam.Start-1);
+ sprintf(size, "%5u", XRam.Size);
+ sprintf(max, "%5u", XRam.Max);
+ fprintf(of, format, XRam.Name, start, end, size, max);
+
+ /*Report Rom/Flash totals:*/
+ sprintf(start, "0x%04x", Rom.Start);
+ if(Rom.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04x", Rom.Size+Rom.Start-1);
+ sprintf(size, "%5u", Rom.Size);
+ sprintf(max, "%5u", Rom.Max);
+ fprintf(of, format, Rom.Name, start, end, size, max);
+
+ /*Report any excess:*/
+ if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
+ {
+ sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ if((XRam.Start+XRam.Size)>XRam.Max)
+ {
+ sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ if((Rom.Start+Rom.Size)>Rom.Max)
+ {
+ sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+
+ fclose(of);
+ return toreturn;
+}