1 /* lkmem.c - Create a memory summary file with extension .mem
3 Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 int summary(struct area * areap)
25 #define EQ(A,B) !as_strcmpi((A),(B))
27 #define REPORT_ERROR(A, H) \
29 fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
30 fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
34 #define REPORT_WARNING(A, H) \
36 fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
37 fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
42 unsigned int Total_Last=0, k;
47 /*Artifacts used for printing*/
48 char start[15], end[15], size[15], max[15];
49 char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
50 char line[]="---------------------";
61 unsigned int dram[0x100];
63 {0, 8, 8, "REG_BANK_0", 0x0001},
64 {0x8, 8, 8, "REG_BANK_1", 0x0002},
65 {0x10, 8, 8, "REG_BANK_2", 0x0004},
66 {0x18, 8, 8, "REG_BANK_3", 0x0008},
67 {0x20, 0, 16, "BSEG_BYTES", 0x0010},
68 {0, 0, 128, "UNUSED", 0x0000},
69 {0x7f, 0, 128, "DATA", 0x0020},
70 {0, 0, 128, "TOTAL:", 0x0000}
73 _Mem IRam= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
74 _Mem Stack={0xff, 0, 1, "STACK", 0x0000};
75 _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
76 _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
78 if(stacksize==0) stacksize=MIN_STACK;
80 if(rflag) /*For the DS390*/
82 XRam.Max=0x1000000; /*24 bits*/
88 if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
96 else if(iram_size<0x80)
100 Ram[7].Max=iram_size;
108 IRam.Max=iram_size-0x80;
111 for(j=0; j<(int)iram_size; j++) dram[j]=0;
112 for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
114 /* Open Memory Summary File*/
115 of = afile(linkp->f_idp, "mem", 1);
124 /**/ if (EQ(xp->a_id, "REG_BANK_0"))
126 Ram[0].Size=xp->a_size;
128 else if (EQ(xp->a_id, "REG_BANK_1"))
130 Ram[1].Size=xp->a_size;
132 else if (EQ(xp->a_id, "REG_BANK_2"))
134 Ram[2].Size=xp->a_size;
136 else if (EQ(xp->a_id, "REG_BANK_3"))
138 Ram[3].Size=xp->a_size;
140 else if (EQ(xp->a_id, "BSEG_BYTES"))
142 Ram[4].Size+=xp->a_size;
144 else if (EQ(xp->a_id, "BIT_BANK"))
146 Ram[4].Size+=xp->a_size;
149 else if(xp->a_flag & A_CODE)
153 Rom.Size+=xp->a_size;
154 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
158 else if (EQ(xp->a_id, "SSEG"))
160 Stack.Size+=xp->a_size;
161 if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
164 else if(xp->a_flag & A_XDATA)
168 XRam.Size+=xp->a_size;
169 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
173 else if (EQ(xp->a_id, "ISEG"))
175 IRam.Size+=xp->a_size;
176 if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
179 /*If is not a register bank, bit, stack, or idata, then it should be data*/
180 else if((xp->a_flag & (A_CODE|A_BIT|A_XDATA))==0)
184 Ram[6].Size+=xp->a_size;
185 if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
193 for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
194 dram[k]|=Ram[j].flag; /*Mark as used*/
196 for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
197 dram[k]|=IRam.flag; /*Mark as used*/
199 /*Compute the amount of unused memory in direct data Ram. This is the
200 gap between the last register bank or bit segment and the data segment.*/
201 for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
203 Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
205 /*Compute the data Ram totals*/
208 if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
209 Ram[7].Size+=Ram[j].Size;
211 Total_Last=Ram[6].Size+Ram[6].Start-1;
213 /*Report the Ram totals*/
214 fprintf(of, "Direct Internal RAM:\n");
215 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
219 if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
220 if((j!=5) || (Ram[j].Size>0))
222 sprintf(start, "0x%02lx", Ram[j].Start);
224 end[0]=0;/*Empty string*/
226 sprintf(end, "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
227 sprintf(size, "%5lu", Ram[j].Size);
228 sprintf(max, "%5lu", Ram[j].Max);
229 fprintf(of, format, Ram[j].Name, start, end, size, max);
233 for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
235 if(dram[k]!=Ram[6].flag)
237 sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
238 REPORT_ERROR(buff, 1);
243 if(Ram[4].Size>Ram[4].Max)
245 k=Ram[4].Size-Ram[4].Max;
246 sprintf(buff, "Insufficient bit addressable memory. "
247 "%d byte%s short.\n", k, (k==1)?"":"s");
248 REPORT_ERROR(buff, 1);
253 sprintf(buff, "%ld bytes in data memory wasted. "
254 "SDCC link could use: --data-loc 0x%02lx\n",
255 Ram[5].Size, Ram[6].Start-Ram[5].Size);
256 REPORT_WARNING(buff, 1);
259 if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
261 k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
262 sprintf(buff, "Insufficient space in data memory. "
263 "%d byte%s short.\n", k, (k==1)?"":"s");
264 REPORT_ERROR(buff, 1);
267 /*Report the position of the beginning of the stack*/
268 fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
269 rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1);
271 /*Check that the stack pointer is landing in a safe place:*/
272 if( (dram[Stack.Start] & 0x8000) == 0x8000 )
275 sprintf(buff, "Stack set to unavailable memory.\n");
276 REPORT_ERROR(buff, 1);
278 else if(dram[Stack.Start])
281 sprintf(buff, "Stack overlaps area ");
282 REPORT_ERROR(buff, 1);
285 if(dram[Stack.Start]&Ram[j].flag)
287 sprintf(buff, "'%s'\n", Ram[j].Name);
291 if(dram[Stack.Start]&IRam.flag)
293 sprintf(buff, "'%s'\n", IRam.Name);
295 REPORT_ERROR(buff, 0);
299 for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
300 fprintf(of, " with %d bytes available\n", k);
301 if ((int)k<stacksize)
303 sprintf(buff, "Only %d byte%s available for stack.\n",
305 REPORT_WARNING(buff, 1);
309 fprintf(of, "\nOther memory:\n");
310 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
311 fprintf(of, format, line, line, line, line, line);
313 /*Report IRam totals:*/
316 start[0]=0;/*Empty string*/
317 end[0]=0;/*Empty string*/
321 sprintf(start, "0x%02lx", IRam.Start);
322 sprintf(end, "0x%02lx", IRam.Size+IRam.Start-1);
324 sprintf(size, "%5lu", IRam.Size);
325 sprintf(max, "%5lu", IRam.Max);
326 fprintf(of, format, IRam.Name, start, end, size, max);
328 /*Report XRam totals:*/
331 start[0]=0;/*Empty string*/
332 end[0]=0;/*Empty string*/
336 sprintf(start, "0x%04lx", XRam.Start);
337 sprintf(end, "0x%04lx", XRam.Size+XRam.Start-1);
339 sprintf(size, "%5lu", XRam.Size);
340 sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
341 fprintf(of, format, XRam.Name, start, end, size, max);
343 /*Report Rom/Flash totals:*/
346 start[0]=0;/*Empty string*/
347 end[0]=0;/*Empty string*/
351 sprintf(start, "0x%04lx", Rom.Start);
352 sprintf(end, "0x%04lx", Rom.Size+Rom.Start-1);
354 sprintf(size, "%5lu", Rom.Size);
355 sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
356 fprintf(of, format, Rom.Name, start, end, size, max);
358 /*Report any excess:*/
359 if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
361 sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
362 REPORT_ERROR(buff, 1);
364 if( ((XRam.Start+XRam.Size)>XRam.Max) ||
365 (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
367 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
368 REPORT_ERROR(buff, 1);
370 if( ((Rom.Start+Rom.Size)>Rom.Max) ||
371 (((int)Rom.Size>code_size)&&(code_size>=0)) )
373 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
374 REPORT_ERROR(buff, 1);
381 extern char idatamap[]; //0:not used, 1:used
384 int summary2(struct area * areap)
386 #define EQ(A,B) !as_strcmpi((A),(B))
391 unsigned long int Stack_Start=0, Stack_Size;
394 struct area * xstack_xp = NULL;
397 /*Artifacts used for printing*/
398 char start[15], end[15], size[15], max[15];
399 char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
400 char line[]="---------------------";
412 _Mem Stack={0xff, 0, 0, 1, "STACK", 0x0000};
413 _Mem Paged={0xffff, 0, 0, 256, "PAGED EXT. RAM", A_PAG};
414 _Mem XRam= {0xffff, 0, 0, 65536, "EXTERNAL RAM", 0x0100};
415 _Mem Rom= {0xffff, 0, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
417 if(rflag) /*For the DS390*/
419 XRam.Max=0x1000000; /*24 bits*/
425 /* Open Memory Summary File*/
426 of = afile(linkp->f_idp, "mem", 1);
435 if (xp->a_flag & A_CODE)
439 Rom.Size += xp->a_size;
440 if(xp->a_addr < Rom.Start)
441 Rom.Start = xp->a_addr;
442 if(xp->a_addr + xp->a_size > Rom.End)
443 Rom.End = xp->a_addr + xp->a_size;
447 else if (EQ(xp->a_id, "SSEG"))
449 Stack.Size += xp->a_size;
450 if(xp->a_addr < Stack.Start)
451 Stack.Start = xp->a_addr;
452 if(xp->a_addr + xp->a_size > Stack.End)
453 Stack.End = xp->a_addr + xp->a_size;
456 else if (EQ(xp->a_id, "PSEG"))
458 Paged.Size += xp->a_size;
459 if(xp->a_addr < Paged.Start)
460 Paged.Start = xp->a_addr;
461 if(xp->a_addr + xp->a_size > Paged.End)
462 Paged.End = xp->a_addr + xp->a_size;
465 else if (EQ(xp->a_id, "XSTK"))
468 Paged.Size += xp->a_size;
469 if(xp->a_addr < Paged.Start)
470 Paged.Start = xp->a_addr;
471 if(xp->a_addr + xp->a_size > Paged.End)
472 Paged.End = xp->a_addr + xp->a_size;
475 else if (xp->a_flag & A_XDATA)
479 XRam.Size += xp->a_size;
480 if(xp->a_addr < XRam.Start)
481 XRam.Start = xp->a_addr;
482 if(xp->a_addr + xp->a_size > XRam.End)
483 XRam.End = xp->a_addr + xp->a_size;
490 /*Report the Ram totals*/
491 fprintf(of, "Internal RAM layout:\n");
492 fprintf(of, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
495 if(j%16==0) fprintf(of, "\n0x%02x:|", j);
496 fprintf(of, "%c|", idatamap[j]);
498 fprintf(of, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
509 for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
511 if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
520 fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
521 " in internal RAM for area %s.",
522 xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
528 /*Report the position of the begining of the stack*/
530 fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
531 rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1, Stack_Size);
533 fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
535 /*Report about xstack*/
538 Stack_Start = xstack_xp->a_addr;
539 Stack_Size = xstack_xp->a_size;
540 fprintf(of, "\nXstack starts at: 0x%04lx with %ld bytes available.",
541 Stack_Start, Stack_Size);
544 fprintf(of, "\n\nOther memory:\n");
545 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
546 fprintf(of, format, line, line, line, line, line);
548 /*Report Paged XRam totals:*/
551 start[0]=0;/*Empty string*/
552 end[0]=0;/*Empty string*/
556 sprintf(start, "0x%04lx", Paged.Start);
557 sprintf(end, "0x%04lx", Paged.End-1);
559 sprintf(size, "%5lu", Paged.Size);
560 sprintf(max, "%5lu", xram_size<0 ? Paged.Max : xram_size<256 ? xram_size : 256);
561 fprintf(of, format, Paged.Name, start, end, size, max);
563 /*Report XRam totals:*/
566 start[0]=0;/*Empty string*/
567 end[0]=0;/*Empty string*/
571 sprintf(start, "0x%04lx", XRam.Start);
572 sprintf(end, "0x%04lx", XRam.End-1);
574 sprintf(size, "%5lu", XRam.Size);
575 sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
576 fprintf(of, format, XRam.Name, start, end, size, max);
578 /*Report Rom/Flash totals:*/
581 start[0]=0;/*Empty string*/
582 end[0]=0;/*Empty string*/
586 sprintf(start, "0x%04lx", Rom.Start);
587 sprintf(end, "0x%04lx", Rom.End-1);
589 sprintf(size, "%5lu", Rom.Size);
590 sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
591 fprintf(of, format, Rom.Name, start, end, size, max);
593 /*Report any excess:*/
594 if( ((XRam.End) > XRam.Max) ||
595 (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
597 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
598 REPORT_ERROR(buff, 1);
600 if( ((Rom.End) > Rom.Max) ||
601 (((int)Rom.Size>code_size)&&(code_size>=0)) )
603 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
604 REPORT_ERROR(buff, 1);