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