* as/mcs51/lkarea.c: removed old K&R style,
[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
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 Size;
406         unsigned long Max;
407         char Name[NCPS];
408         unsigned long flag;
409     } _Mem;
410
411     _Mem Stack={0xff,   0,     1, "STACK",           0x0000};
412     _Mem Paged={0xff,   0,   256, "PAGED EXT. RAM",  A_PAG};
413     _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM",    0x0100};
414     _Mem Rom=  {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
415
416     if(rflag) /*For the DS390*/
417     {
418         XRam.Max=0x1000000; /*24 bits*/
419         XRam.Start=0xffffff;
420         Rom.Max=0x1000000;
421         Rom.Start=0xffffff;
422     }
423
424     /* Open Memory Summary File*/
425     of = afile(linkp->f_idp, "mem", 1);
426     if (of == NULL)
427     {
428         lkexit(1);
429     }
430
431     xp=areap;
432     while (xp)
433     {
434         if(xp->a_flag & A_CODE)
435         {
436             if(xp->a_size)
437             {
438                 Rom.Size+=xp->a_size;
439                 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
440             }
441         }
442
443         else if (EQ(xp->a_id, "SSEG"))
444         {
445             Stack.Size+=xp->a_size;
446             if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
447         }
448
449         else if (EQ(xp->a_id, "PSEG"))
450         {
451             Paged.Size+=xp->a_size;
452             if(xp->a_addr<Paged.Start) Paged.Start=xp->a_addr;
453         }
454
455         else if (EQ(xp->a_id, "XSTK"))
456         {
457             xstack_xp = xp;
458             Paged.Size+=xp->a_size;
459             if(xp->a_addr<Paged.Start) Paged.Start=xp->a_addr;
460         }
461
462         else if(xp->a_flag & A_XDATA)
463         {
464             if(xp->a_size)
465             {
466                 XRam.Size+=xp->a_size;
467                 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
468             }
469         }
470
471         xp=xp->a_ap;
472     }
473
474     /*Report the Ram totals*/
475     fprintf(of, "Internal RAM layout:\n");
476     fprintf(of, "      0 1 2 3 4 5 6 7 8 9 A B C D E F");
477     for(j=0; j<256; j++)
478     {
479         if(j%16==0) fprintf(of, "\n0x%02x:|", j);
480         fprintf(of, "%c|", idatamap[j]);
481     }
482     fprintf(of, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
483
484     for(j=0; j<256; j++)
485     {
486         if(idatamap[j]=='S')
487         {
488             Stack_Start=j;
489             break;
490         }
491     }
492
493     for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
494     {
495         if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
496         else break;
497     }
498
499     xp=areap;
500     while (xp)
501     {
502         if(xp->a_unaloc>0)
503         {
504             fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
505                         " in internal RAM for area %s.",
506                         xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
507             toreturn=1;
508         }
509         xp=xp->a_ap;
510     }
511
512     /*Report the position of the begining of the stack*/
513     if(Stack_Start!=256)
514         fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
515             rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1, Stack_Size);
516     else
517         fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
518
519     /*Report about xstack*/
520     if (xstack_xp)
521     {
522         Stack_Start = xstack_xp->a_addr;
523         Stack_Size = xstack_xp->a_size;
524         fprintf(of, "\nXstack starts at: 0x%04lx with %ld bytes available.",
525             Stack_Start, Stack_Size);
526     }
527
528     fprintf(of, "\n\nOther memory:\n");
529     fprintf(of, format, "Name", "Start", "End", "Size", "Max");
530     fprintf(of, format, line, line, line, line, line);
531
532     /*Report Paged XRam totals:*/
533     if(Paged.Size==0)
534     {
535         start[0]=0;/*Empty string*/
536         end[0]=0;/*Empty string*/
537     }
538     else
539     {
540         sprintf(start, "0x%04lx", Paged.Start);
541         sprintf(end,  "0x%04lx", Paged.Size+Paged.Start-1);
542     }
543     sprintf(size, "%5lu", Paged.Size);
544     sprintf(max, "%5lu", xram_size<0 ? Paged.Max : xram_size<256 ? xram_size : 256);
545     fprintf(of, format, Paged.Name, start, end, size, max);
546
547     /*Report XRam totals:*/
548     if(XRam.Size==0)
549     {
550         start[0]=0;/*Empty string*/
551         end[0]=0;/*Empty string*/
552     }
553     else
554     {
555         sprintf(start, "0x%04lx", XRam.Start);
556         sprintf(end,  "0x%04lx", XRam.Size+XRam.Start-1);
557     }
558     sprintf(size, "%5lu", XRam.Size);
559     sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
560     fprintf(of, format, XRam.Name, start, end, size, max);
561
562     /*Report Rom/Flash totals:*/
563     if(Rom.Size==0)
564     {
565         start[0]=0;/*Empty string*/
566         end[0]=0;/*Empty string*/
567     }
568     else
569     {
570         sprintf(start, "0x%04lx", Rom.Start);
571         sprintf(end,  "0x%04lx", Rom.Size+Rom.Start-1);
572     }
573     sprintf(size, "%5lu", Rom.Size);
574     sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
575     fprintf(of, format, Rom.Name, start, end, size, max);
576
577     /*Report any excess:*/
578     if( ((XRam.Start+XRam.Size)>XRam.Max) ||
579         (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
580     {
581         sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
582         REPORT_ERROR(buff, 1);
583     }
584     if( ((Rom.Start+Rom.Size)>Rom.Max) ||
585         (((int)Rom.Size>code_size)&&(code_size>=0)) )
586     {
587         sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
588         REPORT_ERROR(buff, 1);
589     }
590
591     fclose(of);
592     return toreturn;
593 }