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