1 /*-------------------------------------------------------------------------
2 lkmem.c - Create a memory summary file with extension .mem
4 Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
26 int summary(struct area * areap)
28 #define EQ(A,B) !strcmpi((A),(B))
30 #define REPORT_ERROR(A, H) \
32 fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
33 fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
37 #define REPORT_WARNING(A, H) \
39 fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
40 fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
45 unsigned int Total_Last=0, k;
50 /*Artifacts used for printing*/
51 char start[8], end[8], size[8], max[8];
52 char format[]=" %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
53 char line[]="---------------------";
64 unsigned int dram[0x100];
66 {0, 8, 8, "REG_BANK_0", 0x0001},
67 {0x8, 8, 8, "REG_BANK_1", 0x0002},
68 {0x10, 8, 8, "REG_BANK_2", 0x0004},
69 {0x18, 8, 8, "REG_BANK_3", 0x0008},
70 {0x20, 0, 16, "BSEG_BYTES", 0x0010},
71 {0, 0, 128, "UNUSED", 0x0000},
72 {0x7f, 0, 128, "DATA", 0x0020},
73 {0, 0, 128, "TOTAL:", 0x0000}
76 _Mem IRam= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
77 _Mem Stack={0xff, 0, 1, "STACK", 0x0000};
78 _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
79 _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
81 if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
89 else if(iram_size<0x80)
101 IRam.Max=iram_size-0x80;
104 for(j=0; j<(int)iram_size; j++) dram[j]=0;
105 for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
107 /* Open Memory Summary File*/
108 of = afile(linkp->f_idp, "mem", 1);
117 /**/ if (EQ(xp->a_id, "REG_BANK_0"))
119 Ram[0].Size=xp->a_size;
121 else if (EQ(xp->a_id, "REG_BANK_1"))
123 Ram[1].Size=xp->a_size;
125 else if (EQ(xp->a_id, "REG_BANK_2"))
127 Ram[2].Size=xp->a_size;
129 else if (EQ(xp->a_id, "REG_BANK_3"))
131 Ram[3].Size=xp->a_size;
133 else if (EQ(xp->a_id, "BSEG_BYTES"))
135 Ram[4].Size=xp->a_size;
137 else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
139 Ram[6].Size+=xp->a_size;
140 if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
143 else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
144 EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
146 Rom.Size+=xp->a_size;
147 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
150 else if (EQ(xp->a_id, "SSEG"))
152 Stack.Size+=xp->a_size;
153 if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
156 else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG"))
158 XRam.Size+=xp->a_size;
159 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
162 else if (EQ(xp->a_id, "ISEG"))
164 IRam.Size+=xp->a_size;
165 if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
171 for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
172 dram[k]|=Ram[j].flag; /*Mark as used*/
174 for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
175 dram[k]|=IRam.flag; /*Mark as used*/
177 /*Compute the amount of unused memory in direct data Ram. This is the
178 gap between the last register bank or bit segment and the data segment.*/
179 for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
181 Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
183 /*Compute the data Ram totals*/
186 if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
187 Ram[7].Size+=Ram[j].Size;
189 Total_Last=Ram[6].Size+Ram[6].Start-1;
191 /*Report the Ram totals*/
192 fprintf(of, "Direct Internal RAM:\n");
193 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
197 if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
198 if((j!=5) || (Ram[j].Size>0))
200 sprintf(start, "0x%02x", Ram[j].Start);
202 end[0]=0;/*Empty string*/
204 sprintf(end, "0x%02x", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
205 sprintf(size, "%5u", Ram[j].Size);
206 sprintf(max, "%5u", Ram[j].Max);
207 fprintf(of, format, Ram[j].Name, start, end, size, max);
211 for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
213 if(dram[k]!=Ram[6].flag)
215 sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
216 REPORT_ERROR(buff, 1);
221 if(Ram[4].Size>Ram[4].Max)
223 k=Ram[4].Size-Ram[4].Max;
224 sprintf(buff, "Insufficient bit addressable memory. "
225 "%d byte%s short.\n", k, (k==1)?"":"s");
226 REPORT_ERROR(buff, 1);
231 sprintf(buff, "%d bytes in DRAM wasted. "
232 "SDCC link could use: --data-loc 0x%02x\n",
233 Ram[5].Size, Ram[6].Start-Ram[5].Size);
234 REPORT_WARNING(buff, 1);
237 if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
239 k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
240 sprintf(buff, "Insufficient DRAM memory. "
241 "%d byte%s short.\n", k, (k==1)?"":"s");
242 REPORT_ERROR(buff, 1);
245 /*Report the position of the begining of the stack*/
246 fprintf(of, "\nStack starts at: 0x%02x", Stack.Start);
248 /*Check that the stack pointer is landing in a safe place:*/
249 if( (dram[Stack.Start] & 0x8000) == 0x8000 )
252 sprintf(buff, "Stack set to unavailable memory.\n");
253 REPORT_ERROR(buff, 1);
255 else if(dram[Stack.Start])
258 sprintf(buff, "Stack overlaps area ");
259 REPORT_ERROR(buff, 1);
262 if(dram[Stack.Start]&Ram[j].flag)
264 sprintf(buff, "'%s'\n", Ram[j].Name);
268 if(dram[Stack.Start]&IRam.flag)
270 sprintf(buff, "'%s'\n", IRam.Name);
272 REPORT_ERROR(buff, 0);
276 for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
277 fprintf(of, " with %d bytes available\n", k);
280 sprintf(buff, "Only %d byte%s available for stack.\n",
282 REPORT_WARNING(buff, 1);
286 fprintf(of, "\nOther memory:\n");
287 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
288 fprintf(of, format, line, line, line, line, line);
290 /*Report IRam totals:*/
291 sprintf(start, "0x%02x", IRam.Start);
293 end[0]=0;/*Empty string*/
295 sprintf(end, "0x%02x", IRam.Size+IRam.Start-1);
296 sprintf(size, "%5u", IRam.Size);
297 sprintf(max, "%5u", IRam.Max);
298 fprintf(of, format, IRam.Name, start, end, size, max);
300 /*Report XRam totals:*/
301 sprintf(start, "0x%04x", XRam.Start);
303 end[0]=0;/*Empty string*/
305 sprintf(end, "0x%04x", XRam.Size+XRam.Start-1);
306 sprintf(size, "%5u", XRam.Size);
307 sprintf(max, "%5u", XRam.Max);
308 fprintf(of, format, XRam.Name, start, end, size, max);
310 /*Report Rom/Flash totals:*/
311 sprintf(start, "0x%04x", Rom.Start);
313 end[0]=0;/*Empty string*/
315 sprintf(end, "0x%04x", Rom.Size+Rom.Start-1);
316 sprintf(size, "%5u", Rom.Size);
317 sprintf(max, "%5u", Rom.Max);
318 fprintf(of, format, Rom.Name, start, end, size, max);
320 /*Report any excess:*/
321 if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
323 sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
324 REPORT_ERROR(buff, 1);
326 if((XRam.Start+XRam.Size)>XRam.Max)
328 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
329 REPORT_ERROR(buff, 1);
331 if((Rom.Start+Rom.Size)>Rom.Max)
333 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
334 REPORT_ERROR(buff, 1);