* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / mcs51 / lkmem.c
1 /* lkmem.c - Create a memory summary file with extension .mem
2
3    Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
4
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
8 later version.
9
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.
14
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/>. */
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include "aslink.h"
22
23 int summary(struct area * areap)
24 {
25     #define EQ(A,B) !as_strcmpi((A),(B))
26     #define MIN_STACK 16
27     #define REPORT_ERROR(A, H) \
28     {\
29         fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
30         fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
31         toreturn=1; \
32     }
33
34     #define REPORT_WARNING(A, H) \
35     { \
36         fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
37         fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
38     }
39
40     char buff[128];
41     int j, toreturn=0;
42     unsigned int Total_Last=0, k;
43
44     struct area * xp;
45     FILE * of;
46
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[]="---------------------";
51
52     typedef struct
53     {
54         unsigned long Start;
55         unsigned long Size;
56         unsigned long Max;
57         char Name[NCPS];
58         unsigned long flag;
59     } _Mem;
60
61     unsigned int dram[0x100];
62     _Mem Ram[]={
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}
71     };
72
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};
77
78     if(stacksize==0) stacksize=MIN_STACK;
79
80     if(rflag) /*For the DS390*/
81     {
82         XRam.Max=0x1000000; /*24 bits*/
83         XRam.Start=0xffffff;
84         Rom.Max=0x1000000;
85         Rom.Start=0xffffff;
86     }
87
88     if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
89     {
90         Ram[5].Max=0x80;
91         Ram[6].Max=0x80;
92         Ram[7].Max=0x80;
93         IRam.Max=0x80;
94         iram_size=0x100;
95     }
96     else if(iram_size<0x80)
97     {
98         Ram[5].Max=iram_size;
99         Ram[6].Max=iram_size;
100         Ram[7].Max=iram_size;
101         IRam.Max=0;
102     }
103     else
104     {
105         Ram[5].Max=0x80;
106         Ram[6].Max=0x80;
107         Ram[7].Max=0x80;
108         IRam.Max=iram_size-0x80;
109     }
110
111     for(j=0; j<(int)iram_size; j++) dram[j]=0;
112     for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
113
114     /* Open Memory Summary File*/
115     of = afile(linkp->f_idp, "mem", 1);
116     if (of == NULL)
117     {
118         lkexit(1);
119     }
120
121     xp=areap;
122     while (xp)
123     {
124         /**/ if (EQ(xp->a_id, "REG_BANK_0"))
125         {
126             Ram[0].Size=xp->a_size;
127         }
128         else if (EQ(xp->a_id, "REG_BANK_1"))
129         {
130             Ram[1].Size=xp->a_size;
131         }
132         else if (EQ(xp->a_id, "REG_BANK_2"))
133         {
134             Ram[2].Size=xp->a_size;
135         }
136         else if (EQ(xp->a_id, "REG_BANK_3"))
137         {
138             Ram[3].Size=xp->a_size;
139         }
140         else if (EQ(xp->a_id, "BSEG_BYTES"))
141         {
142             Ram[4].Size+=xp->a_size;
143         }
144         else if (EQ(xp->a_id, "BIT_BANK"))
145         {
146             Ram[4].Size+=xp->a_size;
147         }
148
149         else if(xp->a_flag & A_CODE)
150         {
151             if(xp->a_size>0)
152             {
153                 Rom.Size+=xp->a_size;
154                 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
155             }
156         }
157
158         else if (EQ(xp->a_id, "SSEG"))
159         {
160             Stack.Size+=xp->a_size;
161             if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
162         }
163
164         else if(xp->a_flag & A_XDATA)
165         {
166             if(xp->a_size>0)
167             {
168                 XRam.Size+=xp->a_size;
169                 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
170             }
171         }
172
173         else if (EQ(xp->a_id, "ISEG"))
174         {
175             IRam.Size+=xp->a_size;
176             if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
177         }
178
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)
181         {
182             if(xp->a_size)
183             {
184                 Ram[6].Size+=xp->a_size;
185                 if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
186             }
187         }
188
189         xp=xp->a_ap;
190     }
191
192     for(j=0; j<7; j++)
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*/
195
196     for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
197         dram[k]|=IRam.flag; /*Mark as used*/
198
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--);
202     Ram[5].Start=k+1;
203     Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
204
205     /*Compute the data Ram totals*/
206     for(j=0; j<7; j++)
207     {
208         if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
209         Ram[7].Size+=Ram[j].Size;
210     }
211     Total_Last=Ram[6].Size+Ram[6].Start-1;
212
213     /*Report the Ram totals*/
214     fprintf(of, "Direct Internal RAM:\n");
215     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
216
217     for(j=0; j<8; j++)
218     {
219         if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
220         if((j!=5) || (Ram[j].Size>0))
221         {
222             sprintf(start, "0x%02lx", Ram[j].Start);
223             if(Ram[j].Size==0)
224                 end[0]=0;/*Empty string*/
225             else
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);
230         }
231     }
232
233     for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
234     {
235         if(dram[k]!=Ram[6].flag)
236         {
237             sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
238             REPORT_ERROR(buff, 1);
239             break;
240         }
241     }
242
243     if(Ram[4].Size>Ram[4].Max)
244     {
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);
249     }
250
251     if(Ram[5].Size!=0)
252     {
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);
257     }
258
259     if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
260     {
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);
265     }
266
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);
270
271     /*Check that the stack pointer is landing in a safe place:*/
272     if( (dram[Stack.Start] & 0x8000) == 0x8000 )
273     {
274         fprintf(of, ".\n");
275         sprintf(buff, "Stack set to unavailable memory.\n");
276         REPORT_ERROR(buff, 1);
277     }
278     else if(dram[Stack.Start])
279     {
280         fprintf(of, ".\n");
281         sprintf(buff, "Stack overlaps area ");
282         REPORT_ERROR(buff, 1);
283         for(j=0; j<7; j++)
284         {
285                         if(dram[Stack.Start]&Ram[j].flag)
286             {
287                 sprintf(buff, "'%s'\n", Ram[j].Name);
288                 break;
289             }
290         }
291         if(dram[Stack.Start]&IRam.flag)
292         {
293             sprintf(buff, "'%s'\n", IRam.Name);
294         }
295         REPORT_ERROR(buff, 0);
296     }
297     else
298     {
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)
302         {
303             sprintf(buff, "Only %d byte%s available for stack.\n",
304                 k, (k==1)?"":"s");
305             REPORT_WARNING(buff, 1);
306         }
307     }
308
309     fprintf(of, "\nOther memory:\n");
310     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
311     fprintf(of, format, line, line, line, line, line);
312
313     /*Report IRam totals:*/
314     if(IRam.Size==0)
315     {
316         start[0]=0;/*Empty string*/
317         end[0]=0;/*Empty string*/
318     }
319     else
320     {
321         sprintf(start, "0x%02lx", IRam.Start);
322         sprintf(end,  "0x%02lx", IRam.Size+IRam.Start-1);
323     }
324     sprintf(size, "%5lu", IRam.Size);
325     sprintf(max, "%5lu", IRam.Max);
326     fprintf(of, format, IRam.Name, start, end, size, max);
327
328     /*Report XRam totals:*/
329     if(XRam.Size==0)
330     {
331         start[0]=0;/*Empty string*/
332         end[0]=0;/*Empty string*/
333     }
334     else
335     {
336         sprintf(start, "0x%04lx", XRam.Start);
337         sprintf(end,  "0x%04lx", XRam.Size+XRam.Start-1);
338     }
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);
342
343     /*Report Rom/Flash totals:*/
344     if(Rom.Size==0)
345     {
346         start[0]=0;/*Empty string*/
347         end[0]=0;/*Empty string*/
348     }
349     else
350     {
351         sprintf(start, "0x%04lx", Rom.Start);
352         sprintf(end,  "0x%04lx", Rom.Size+Rom.Start-1);
353     }
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);
357
358     /*Report any excess:*/
359     if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
360     {
361         sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
362         REPORT_ERROR(buff, 1);
363     }
364     if( ((XRam.Start+XRam.Size)>XRam.Max) ||
365         (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
366     {
367         sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
368         REPORT_ERROR(buff, 1);
369     }
370     if( ((Rom.Start+Rom.Size)>Rom.Max) ||
371         (((int)Rom.Size>code_size)&&(code_size>=0)) )
372     {
373         sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
374         REPORT_ERROR(buff, 1);
375     }
376
377     fclose(of);
378     return toreturn;
379 }
380
381 extern char idatamap[]; //0:not used, 1:used
382
383
384 int summary2(struct area * areap)
385 {
386     #define EQ(A,B) !as_strcmpi((A),(B))
387
388     char buff[128];
389     int toreturn = 0;
390     unsigned int j;
391     unsigned long int Stack_Start=0, Stack_Size;
392
393     struct area * xp;
394     struct area * xstack_xp = NULL;
395     FILE * of;
396
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[]="---------------------";
401
402     typedef struct
403     {
404         unsigned long Start;
405         unsigned long End;
406         unsigned long Size;
407         unsigned long Max;
408         char Name[NCPS];
409         unsigned long flag;
410     } _Mem;
411
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};
416
417     if(rflag) /*For the DS390*/
418     {
419         XRam.Max=0x1000000; /*24 bits*/
420         XRam.Start=0xffffff;
421         Rom.Max=0x1000000;
422         Rom.Start=0xffffff;
423     }
424
425     /* Open Memory Summary File*/
426     of = afile(linkp->f_idp, "mem", 1);
427     if (of == NULL)
428     {
429         lkexit(1);
430     }
431
432     xp=areap;
433     while (xp)
434     {
435         if (xp->a_flag & A_CODE)
436         {
437             if(xp->a_size)
438             {
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;
444             }
445         }
446
447         else if (EQ(xp->a_id, "SSEG"))
448         {
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;
454         }
455
456         else if (EQ(xp->a_id, "PSEG"))
457         {
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;
463         }
464
465         else if (EQ(xp->a_id, "XSTK"))
466         {
467             xstack_xp = xp;
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;
473         }
474
475         else if (xp->a_flag & A_XDATA)
476         {
477             if(xp->a_size)
478             {
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;
484             }
485         }
486
487         xp = xp->a_ap;
488     }
489
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");
493     for(j=0; j<256; j++)
494     {
495         if(j%16==0) fprintf(of, "\n0x%02x:|", j);
496         fprintf(of, "%c|", idatamap[j]);
497     }
498         fprintf(of, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
499
500     for(j=0; j<256; j++)
501     {
502         if(idatamap[j]=='S')
503         {
504             Stack_Start=j;
505             break;
506         }
507     }
508
509     for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
510     {
511         if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
512         else break;
513     }
514
515     xp=areap;
516     while (xp)
517     {
518         if(xp->a_unaloc>0)
519         {
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);
523             toreturn=1;
524         }
525         xp=xp->a_ap;
526     }
527
528     /*Report the position of the begining of the stack*/
529     if(Stack_Start!=256)
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);
532     else
533         fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
534
535     /*Report about xstack*/
536     if (xstack_xp)
537     {
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);
542     }
543
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);
547
548     /*Report Paged XRam totals:*/
549     if(Paged.Size==0)
550     {
551         start[0]=0;/*Empty string*/
552         end[0]=0;/*Empty string*/
553     }
554     else
555     {
556         sprintf(start, "0x%04lx", Paged.Start);
557         sprintf(end,  "0x%04lx", Paged.End-1);
558     }
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);
562
563     /*Report XRam totals:*/
564     if(XRam.Size==0)
565     {
566         start[0]=0;/*Empty string*/
567         end[0]=0;/*Empty string*/
568     }
569     else
570     {
571         sprintf(start, "0x%04lx", XRam.Start);
572         sprintf(end,  "0x%04lx", XRam.End-1);
573     }
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);
577
578     /*Report Rom/Flash totals:*/
579     if(Rom.Size==0)
580     {
581         start[0]=0;/*Empty string*/
582         end[0]=0;/*Empty string*/
583     }
584     else
585     {
586         sprintf(start, "0x%04lx", Rom.Start);
587         sprintf(end,  "0x%04lx", Rom.End-1);
588     }
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);
592
593     /*Report any excess:*/
594     if( ((XRam.End) > XRam.Max) ||
595         (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
596     {
597         sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
598         REPORT_ERROR(buff, 1);
599     }
600     if( ((Rom.End) > Rom.Max) ||
601         (((int)Rom.Size>code_size)&&(code_size>=0)) )
602     {
603         sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
604         REPORT_ERROR(buff, 1);
605     }
606
607     fclose(of);
608     return toreturn;
609 }