47fc14d43d470ef7020f33287abbb752887d5a60
[fw/sdcc] / as / mcs51 / lkmem.c
1 /*-------------------------------------------------------------------------
2   lkmem.c - Create a memory summary file with extension .mem
3
4    Written By -  Jesus Calvino-Fraga, jesusc@ieee.org (2002)
5
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
9    later version.
10
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.
15
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 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include "aslink.h"
25 #include "strcmpi.h"
26
27 int summary(struct area * areap)
28 {
29     #define EQ(A,B) !as_strcmpi((A),(B))
30     #define MIN_STACK 16
31     #define REPORT_ERROR(A, H) \
32     {\
33         fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
34         fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
35         toreturn=1; \
36     }
37
38     #define REPORT_WARNING(A, H) \
39     { \
40         fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
41         fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
42     }
43
44     char buff[128];
45     int j, toreturn=0;
46     unsigned int Total_Last=0, k;
47
48     struct area * xp;
49     FILE * of;
50
51     /*Artifacts used for printing*/
52     char start[15], end[15], size[15], max[15];
53     char format[]="   %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
54     char line[]="---------------------";
55
56     typedef struct
57     {
58         unsigned long Start;
59         unsigned long Size;
60         unsigned long Max;
61         char Name[NCPS];
62         unsigned long flag;
63     } _Mem;
64
65     unsigned int dram[0x100];
66     _Mem Ram[]={
67         {0,     8,  8,   "REG_BANK_0", 0x0001},
68         {0x8,   8,  8,   "REG_BANK_1", 0x0002},
69         {0x10,  8,  8,   "REG_BANK_2", 0x0004},
70         {0x18,  8,  8,   "REG_BANK_3", 0x0008},
71         {0x20,  0,  16,  "BSEG_BYTES", 0x0010},
72         {0,     0,  128, "UNUSED",     0x0000},
73         {0x7f,  0,  128, "DATA",       0x0020},
74         {0,     0,  128, "TOTAL:",     0x0000}
75     };
76
77     _Mem IRam= {0xff,   0,   128, "INDIRECT RAM",       0x0080};
78     _Mem Stack={0xff,   0,     1, "STACK",              0x0000};
79     _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM",       0x0100};
80     _Mem Rom=  {0xffff, 0, 65536, "ROM/EPROM/FLASH",    0x0200};
81
82     if(stacksize==0) stacksize=MIN_STACK;
83
84     if(rflag) /*For the DS390*/
85     {
86         XRam.Max=0x1000000; /*24 bits*/
87         XRam.Start=0xffffff;
88         Rom.Max=0x1000000;
89         Rom.Start=0xffffff;
90     }
91
92     if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
93     {
94         Ram[5].Max=0x80;
95         Ram[6].Max=0x80;
96         Ram[7].Max=0x80;
97         IRam.Max=0x80;
98         iram_size=0x100;
99     }
100     else if(iram_size<0x80)
101     {
102         Ram[5].Max=iram_size;
103         Ram[6].Max=iram_size;
104         Ram[7].Max=iram_size;
105         IRam.Max=0;
106     }
107     else
108     {
109         Ram[5].Max=0x80;
110         Ram[6].Max=0x80;
111         Ram[7].Max=0x80;
112         IRam.Max=iram_size-0x80;
113     }
114
115     for(j=0; j<(int)iram_size; j++) dram[j]=0;
116     for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
117
118     /* Open Memory Summary File*/
119     of = afile(linkp->f_idp, "mem", 1);
120     if (of == NULL)
121     {
122         lkexit(1);
123     }
124
125     xp=areap;
126     while (xp)
127     {
128         /**/ if (EQ(xp->a_id, "REG_BANK_0"))
129         {
130             Ram[0].Size=xp->a_size;
131         }
132         else if (EQ(xp->a_id, "REG_BANK_1"))
133         {
134             Ram[1].Size=xp->a_size;
135         }
136         else if (EQ(xp->a_id, "REG_BANK_2"))
137         {
138             Ram[2].Size=xp->a_size;
139         }
140         else if (EQ(xp->a_id, "REG_BANK_3"))
141         {
142             Ram[3].Size=xp->a_size;
143         }
144         else if (EQ(xp->a_id, "BSEG_BYTES"))
145         {
146             Ram[4].Size+=xp->a_size;
147         }
148         else if (EQ(xp->a_id, "BIT_BANK"))
149         {
150             Ram[4].Size+=xp->a_size;
151         }
152
153         else if(xp->a_flag & A_CODE)
154         {
155             if(xp->a_size>0)
156             {
157                 Rom.Size+=xp->a_size;
158                 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
159             }
160         }
161
162         else if (EQ(xp->a_id, "SSEG"))
163         {
164             Stack.Size+=xp->a_size;
165             if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
166         }
167
168         else if(xp->a_flag & A_XDATA)
169         {
170             if(xp->a_size>0)
171             {
172                 XRam.Size+=xp->a_size;
173                 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
174             }
175         }
176
177         else if (EQ(xp->a_id, "ISEG"))
178         {
179             IRam.Size+=xp->a_size;
180             if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
181         }
182
183         /*If is not a register bank, bit, stack, or idata, then it should be data*/
184         else if((xp->a_flag & (A_CODE|A_BIT|A_XDATA))==0)
185         {
186             if(xp->a_size)
187             {
188                 Ram[6].Size+=xp->a_size;
189                 if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
190             }
191         }
192
193         xp=xp->a_ap;
194     }
195
196     for(j=0; j<7; j++)
197         for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
198             dram[k]|=Ram[j].flag; /*Mark as used*/
199
200     for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
201         dram[k]|=IRam.flag; /*Mark as used*/
202
203     /*Compute the amount of unused memory in direct data Ram.  This is the
204     gap between the last register bank or bit segment and the data segment.*/
205     for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
206     Ram[5].Start=k+1;
207     Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
208
209     /*Compute the data Ram totals*/
210     for(j=0; j<7; j++)
211     {
212         if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
213         Ram[7].Size+=Ram[j].Size;
214     }
215     Total_Last=Ram[6].Size+Ram[6].Start-1;
216
217     /*Report the Ram totals*/
218     fprintf(of, "Direct Internal RAM:\n");
219     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
220
221     for(j=0; j<8; j++)
222     {
223         if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
224         if((j!=5) || (Ram[j].Size>0))
225         {
226             sprintf(start, "0x%02lx", Ram[j].Start);
227             if(Ram[j].Size==0)
228                 end[0]=0;/*Empty string*/
229             else
230                 sprintf(end,  "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
231             sprintf(size, "%5lu", Ram[j].Size);
232             sprintf(max, "%5lu", Ram[j].Max);
233             fprintf(of, format, Ram[j].Name, start, end, size, max);
234         }
235     }
236
237     for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
238     {
239         if(dram[k]!=Ram[6].flag)
240         {
241             sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
242             REPORT_ERROR(buff, 1);
243             break;
244         }
245     }
246
247     if(Ram[4].Size>Ram[4].Max)
248     {
249         k=Ram[4].Size-Ram[4].Max;
250         sprintf(buff, "Insufficient bit addressable memory.  "
251                     "%d byte%s short.\n", k, (k==1)?"":"s");
252         REPORT_ERROR(buff, 1);
253     }
254
255     if(Ram[5].Size!=0)
256     {
257         sprintf(buff, "%ld bytes in data memory wasted.  "
258                     "SDCC link could use: --data-loc 0x%02lx\n",
259                     Ram[5].Size, Ram[6].Start-Ram[5].Size);
260         REPORT_WARNING(buff, 1);
261     }
262
263     if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
264     {
265         k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
266         sprintf(buff, "Insufficient space in data memory.   "
267                     "%d byte%s short.\n", k, (k==1)?"":"s");
268         REPORT_ERROR(buff, 1);
269     }
270
271     /*Report the position of the beginning of the stack*/
272     fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
273         rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1);
274
275     /*Check that the stack pointer is landing in a safe place:*/
276     if( (dram[Stack.Start] & 0x8000) == 0x8000 )
277     {
278         fprintf(of, ".\n");
279         sprintf(buff, "Stack set to unavailable memory.\n");
280         REPORT_ERROR(buff, 1);
281     }
282     else if(dram[Stack.Start])
283     {
284         fprintf(of, ".\n");
285         sprintf(buff, "Stack overlaps area ");
286         REPORT_ERROR(buff, 1);
287         for(j=0; j<7; j++)
288         {
289                         if(dram[Stack.Start]&Ram[j].flag)
290             {
291                 sprintf(buff, "'%s'\n", Ram[j].Name);
292                 break;
293             }
294         }
295         if(dram[Stack.Start]&IRam.flag)
296         {
297             sprintf(buff, "'%s'\n", IRam.Name);
298         }
299         REPORT_ERROR(buff, 0);
300     }
301     else
302     {
303         for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
304         fprintf(of, " with %d bytes available\n", k);
305         if ((int)k<stacksize)
306         {
307             sprintf(buff, "Only %d byte%s available for stack.\n",
308                 k, (k==1)?"":"s");
309             REPORT_WARNING(buff, 1);
310         }
311     }
312
313     fprintf(of, "\nOther memory:\n");
314     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
315     fprintf(of, format, line, line, line, line, line);
316
317     /*Report IRam totals:*/
318     if(IRam.Size==0)
319     {
320         start[0]=0;/*Empty string*/
321         end[0]=0;/*Empty string*/
322     }
323     else
324     {
325         sprintf(start, "0x%02lx", IRam.Start);
326         sprintf(end,  "0x%02lx", IRam.Size+IRam.Start-1);
327     }
328     sprintf(size, "%5lu", IRam.Size);
329     sprintf(max, "%5lu", IRam.Max);
330     fprintf(of, format, IRam.Name, start, end, size, max);
331
332     /*Report XRam totals:*/
333     if(XRam.Size==0)
334     {
335         start[0]=0;/*Empty string*/
336         end[0]=0;/*Empty string*/
337     }
338     else
339     {
340         sprintf(start, "0x%04lx", XRam.Start);
341         sprintf(end,  "0x%04lx", XRam.Size+XRam.Start-1);
342     }
343     sprintf(size, "%5lu", XRam.Size);
344     sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
345     fprintf(of, format, XRam.Name, start, end, size, max);
346
347     /*Report Rom/Flash totals:*/
348     if(Rom.Size==0)
349     {
350         start[0]=0;/*Empty string*/
351         end[0]=0;/*Empty string*/
352     }
353     else
354     {
355         sprintf(start, "0x%04lx", Rom.Start);
356         sprintf(end,  "0x%04lx", Rom.Size+Rom.Start-1);
357     }
358     sprintf(size, "%5lu", Rom.Size);
359     sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
360     fprintf(of, format, Rom.Name, start, end, size, max);
361
362     /*Report any excess:*/
363     if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
364     {
365         sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
366         REPORT_ERROR(buff, 1);
367     }
368     if( ((XRam.Start+XRam.Size)>XRam.Max) ||
369         (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
370     {
371         sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
372         REPORT_ERROR(buff, 1);
373     }
374     if( ((Rom.Start+Rom.Size)>Rom.Max) ||
375         (((int)Rom.Size>code_size)&&(code_size>=0)) )
376     {
377         sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
378         REPORT_ERROR(buff, 1);
379     }
380
381     fclose(of);
382     return toreturn;
383 }
384
385 extern char idatamap[]; //0:not used, 1:used
386
387
388 int summary2(struct area * areap)
389 {
390     #define EQ(A,B) !as_strcmpi((A),(B))
391
392     char buff[128];
393     int toreturn = 0;
394     unsigned int j;
395     unsigned long int Stack_Start=0, Stack_Size;
396
397     struct area * xp;
398     struct area * xstack_xp = NULL;
399     FILE * of;
400
401     /*Artifacts used for printing*/
402     char start[15], end[15], size[15], max[15];
403     char format[]="   %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
404     char line[]="---------------------";
405
406     typedef struct
407     {
408         unsigned long Start;
409         unsigned long End;
410         unsigned long Size;
411         unsigned long Max;
412         char Name[NCPS];
413         unsigned long flag;
414     } _Mem;
415
416     _Mem Stack={0xff,   0, 0,     1, "STACK",           0x0000};
417     _Mem Paged={0xff,   0, 0,   256, "PAGED EXT. RAM",  A_PAG};
418     _Mem XRam= {0xffff, 0, 0, 65536, "EXTERNAL RAM",    0x0100};
419     _Mem Rom=  {0xffff, 0, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
420
421     if(rflag) /*For the DS390*/
422     {
423         XRam.Max=0x1000000; /*24 bits*/
424         XRam.Start=0xffffff;
425         Rom.Max=0x1000000;
426         Rom.Start=0xffffff;
427     }
428
429     /* Open Memory Summary File*/
430     of = afile(linkp->f_idp, "mem", 1);
431     if (of == NULL)
432     {
433         lkexit(1);
434     }
435
436     xp=areap;
437     while (xp)
438     {
439         if(xp->a_flag & A_CODE)
440         {
441             if(xp->a_size)
442             {
443                 Rom.Size += xp->a_size;
444                 if(xp->a_addr < Rom.Start)
445                     Rom.Start = xp->a_addr;
446                 if(xp->a_addr + xp->a_size > Rom.End)
447                     Rom.End = xp->a_addr + xp->a_size;
448             }
449         }
450
451         else if (EQ(xp->a_id, "SSEG"))
452         {
453             Stack.Size += xp->a_size;
454             if(xp->a_addr < Stack.Start)
455                 Stack.Start = xp->a_addr;
456             if(xp->a_addr + xp->a_size > Stack.End)
457                 Stack.End = xp->a_addr + xp->a_size;
458         }
459
460         else if (EQ(xp->a_id, "PSEG"))
461         {
462             Paged.Size += xp->a_size;
463             if(xp->a_addr < Paged.Start)
464                 Paged.Start = xp->a_addr;
465             if(xp->a_addr + xp->a_size > Paged.End)
466                 Paged.End = xp->a_addr + xp->a_size;
467         }
468
469         else if (EQ(xp->a_id, "XSTK"))
470         {
471             xstack_xp = xp;
472             Paged.Size += xp->a_size;
473             if(xp->a_addr < Paged.Start)
474                 Paged.Start = xp->a_addr;
475             if(xp->a_addr + xp->a_size > Paged.End)
476                 Paged.End = xp->a_addr + xp->a_size;
477         }
478
479         else if(xp->a_flag & A_XDATA)
480         {
481             if(xp->a_size)
482             {
483                 XRam.Size += xp->a_size;
484                 if(xp->a_addr < XRam.Start)
485                     XRam.Start = xp->a_addr;
486                 if(xp->a_addr + xp->a_size > XRam.End)
487                     XRam.End = xp->a_addr + xp->a_size;
488             }
489         }
490
491         xp = xp->a_ap;
492     }
493
494     /*Report the Ram totals*/
495     fprintf(of, "Internal RAM layout:\n");
496     fprintf(of, "      0 1 2 3 4 5 6 7 8 9 A B C D E F");
497     for(j=0; j<256; j++)
498     {
499         if(j%16==0) fprintf(of, "\n0x%02x:|", j);
500         fprintf(of, "%c|", idatamap[j]);
501     }
502         fprintf(of, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
503
504     for(j=0; j<256; j++)
505     {
506         if(idatamap[j]=='S')
507         {
508             Stack_Start=j;
509             break;
510         }
511     }
512
513     for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
514     {
515         if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
516         else break;
517     }
518
519     xp=areap;
520     while (xp)
521     {
522         if(xp->a_unaloc>0)
523         {
524             fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
525                         " in internal RAM for area %s.",
526                         xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
527             toreturn=1;
528         }
529         xp=xp->a_ap;
530     }
531
532     /*Report the position of the begining of the stack*/
533     if(Stack_Start!=256)
534         fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
535             rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1, Stack_Size);
536     else
537         fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
538
539     /*Report about xstack*/
540     if (xstack_xp)
541     {
542         Stack_Start = xstack_xp->a_addr;
543         Stack_Size = xstack_xp->a_size;
544         fprintf(of, "\nXstack starts at: 0x%04lx with %ld bytes available.",
545             Stack_Start, Stack_Size);
546     }
547
548     fprintf(of, "\n\nOther memory:\n");
549     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
550     fprintf(of, format, line, line, line, line, line);
551
552     /*Report Paged XRam totals:*/
553     if(Paged.Size==0)
554     {
555         start[0]=0;/*Empty string*/
556         end[0]=0;/*Empty string*/
557     }
558     else
559     {
560         sprintf(start, "0x%04lx", Paged.Start);
561         sprintf(end,  "0x%04lx", Paged.End-1);
562     }
563     sprintf(size, "%5lu", Paged.Size);
564     sprintf(max, "%5lu", xram_size<0 ? Paged.Max : xram_size<256 ? xram_size : 256);
565     fprintf(of, format, Paged.Name, start, end, size, max);
566
567     /*Report XRam totals:*/
568     if(XRam.Size==0)
569     {
570         start[0]=0;/*Empty string*/
571         end[0]=0;/*Empty string*/
572     }
573     else
574     {
575         sprintf(start, "0x%04lx", XRam.Start);
576         sprintf(end,  "0x%04lx", XRam.End-1);
577     }
578     sprintf(size, "%5lu", XRam.Size);
579     sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
580     fprintf(of, format, XRam.Name, start, end, size, max);
581
582     /*Report Rom/Flash totals:*/
583     if(Rom.Size==0)
584     {
585         start[0]=0;/*Empty string*/
586         end[0]=0;/*Empty string*/
587     }
588     else
589     {
590         sprintf(start, "0x%04lx", Rom.Start);
591         sprintf(end,  "0x%04lx", Rom.End-1);
592     }
593     sprintf(size, "%5lu", Rom.Size);
594     sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
595     fprintf(of, format, Rom.Name, start, end, size, max);
596
597     /*Report any excess:*/
598     if( ((XRam.End) > XRam.Max) ||
599         (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
600     {
601         sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
602         REPORT_ERROR(buff, 1);
603     }
604     if( ((Rom.End) > Rom.Max) ||
605         (((int)Rom.Size>code_size)&&(code_size>=0)) )
606     {
607         sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
608         REPORT_ERROR(buff, 1);
609     }
610
611     fclose(of);
612     return toreturn;
613 }