e250f95d62c778664e2ae32d6436839427e81db7
[fw/sdcc] / as / link / hc08 / 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,     0,      0,       "REG_BANK_0", 0x0001},
67                 {0x0,   0,      0,       "REG_BANK_1", 0x0002},
68                 {0x0,   0,      0,       "REG_BANK_2", 0x0004},
69                 {0x0,   0,      0,       "REG_BANK_3", 0x0008},
70                 {0x0,   0,      0,       "BSEG_BYTES", 0x0010},
71                 {0,     0,      256,    "UNUSED",     0x0000},
72                 {0xff,  0,      256,    "DATA",       0x0020},
73                 {0,             0,      256, "TOTAL:",     0x0000}
74         };
75         
76         _Mem IRam= {0xff,   0,     0, "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 0
82         if(rflag) /*For the DS390*/
83         {
84                 XRam.Max=0x1000000; /*24 bits*/
85                 XRam.Start=0xffffff;
86                 Rom.Max=0x1000000;
87                 Rom.Start=0xffffff;
88         }
89
90         if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
91         {
92                 Ram[5].Max=0x80;
93                 Ram[6].Max=0x80;
94                 Ram[7].Max=0x80;
95                 IRam.Max=0x80;
96                 iram_size=0x100;
97         }
98         else if(iram_size<0x80)
99         {
100                 Ram[5].Max=iram_size;
101                 Ram[6].Max=iram_size;
102                 Ram[7].Max=iram_size;
103                 IRam.Max=0;
104         }
105         else
106         {
107                 Ram[5].Max=0x80;
108                 Ram[6].Max=0x80;
109                 Ram[7].Max=0x80;
110                 IRam.Max=iram_size-0x80;
111         }
112 #endif
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, "DSEG") || EQ(xp->a_id, "OSEG") )
148                 {
149                         Ram[6].Size+=xp->a_size;
150                         if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
151                 }
152
153                 else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
154                                  EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
155                 {
156                         Rom.Size+=xp->a_size;
157                         if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
158                 }
159                 
160                 else if (EQ(xp->a_id, "SSEG"))
161                 {
162                         Stack.Size+=xp->a_size;
163                         if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
164                 }
165
166                 else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) 
167                 {
168                         XRam.Size+=xp->a_size;
169                         if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
170                 }
171
172                 else if (EQ(xp->a_id, "ISEG"))
173                 {
174                         IRam.Size+=xp->a_size;
175                         if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
176                 }
177                 xp=xp->a_ap;
178         }
179
180         for(j=0; j<7; j++)
181                 for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
182                         dram[k]|=Ram[j].flag; /*Mark as used*/
183         
184 #if 0
185         for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
186                 dram[k]|=IRam.flag; /*Mark as used*/
187 #endif
188
189         /*Compute the amount of unused memory in direct data Ram.  This is the
190         gap between the last register bank or bit segment and the data segment.*/
191         for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
192         Ram[5].Start=k+1;
193         Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
194
195         /*Compute the data Ram totals*/
196         for(j=0; j<7; j++)
197         {
198                 if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
199                 Ram[7].Size+=Ram[j].Size;
200         }
201         Total_Last=Ram[6].Size+Ram[6].Start-1;
202
203         /*Report the Ram totals*/
204         fprintf(of, "Direct Internal RAM:\n");
205         fprintf(of, format, "Name", "Start", "End", "Size", "Max");
206
207         for(j=0; j<8; j++)
208         {
209                 if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
210                 if((j!=5) || (Ram[j].Size>0))
211                 {
212                         sprintf(start, "0x%02lx", Ram[j].Start);
213                         if(Ram[j].Size==0)
214                                 end[0]=0;/*Empty string*/
215                         else
216                                 sprintf(end,  "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
217                         sprintf(size, "%5lu", Ram[j].Size);
218                         sprintf(max, "%5lu", Ram[j].Max);
219                         fprintf(of, format, Ram[j].Name, start, end, size, max);
220                 }
221         }
222
223 #if 0
224         for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
225         {
226                 if(dram[k]!=Ram[6].flag)
227                 {
228                         sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
229                         REPORT_ERROR(buff, 1);
230                         break;
231                 }
232         }
233
234  
235         if(Ram[4].Size>Ram[4].Max)
236         {
237                 k=Ram[4].Size-Ram[4].Max;
238                 sprintf(buff, "Insufficient bit addressable memory.  "
239                                         "%d byte%s short.\n", k, (k==1)?"":"s");
240                 REPORT_ERROR(buff, 1);
241         }
242
243         if(Ram[5].Size!=0)
244         {
245                 sprintf(buff, "%ld bytes in data memory wasted.  "
246                             "SDCC link could use: --data-loc 0x%02lx\n",
247                                         Ram[5].Size, Ram[6].Start-Ram[5].Size);
248                 REPORT_WARNING(buff, 1);
249         }
250
251         if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
252         {
253                 k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
254                 sprintf(buff, "Insufficient space in data memory.   "
255                                         "%d byte%s short.\n", k, (k==1)?"":"s");
256                 REPORT_ERROR(buff, 1);
257         }
258 #endif
259         /*Report the position of the beginning of the stack*/
260         fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
261                 rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1);
262
263 #if 0
264         /*Check that the stack pointer is landing in a safe place:*/
265         if( (dram[Stack.Start] & 0x8000) == 0x8000 )
266         {
267                 fprintf(of, ".\n");
268                 sprintf(buff, "Stack set to unavailable memory.\n");
269                 REPORT_ERROR(buff, 1);
270         }
271         else if(dram[Stack.Start])
272         {
273                 fprintf(of, ".\n");
274                 sprintf(buff, "Stack overlaps area ");
275                 REPORT_ERROR(buff, 1);
276                 for(j=0; j<7; j++)
277                 {
278                         if(dram[Stack.Start]&Ram[j].flag)
279                         {
280                                 sprintf(buff, "'%s'\n", Ram[j].Name);
281                                 break;
282                         }
283                 }
284                 if(dram[Stack.Start]&IRam.flag)
285                 {
286                         sprintf(buff, "'%s'\n", IRam.Name);
287                 }
288                 REPORT_ERROR(buff, 0);
289         }
290         else
291         {
292                 for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
293                 fprintf(of, " with %d bytes available\n", k);
294                 if (k<MIN_STACK)
295                 {
296                         sprintf(buff, "Only %d byte%s available for stack.\n",
297                                 k, (k==1)?"":"s");
298                         REPORT_WARNING(buff, 1);
299                 }
300         }
301 #endif
302
303         fprintf(of, "\nOther memory:\n");
304         fprintf(of, format, "Name", "Start", "End", "Size", "Max");
305         fprintf(of, format, line, line, line, line, line);
306
307         /*Report IRam totals:*/
308         sprintf(start, "0x%02lx", IRam.Start);
309         if(IRam.Size==0)
310                 end[0]=0;/*Empty string*/
311         else
312                 sprintf(end,  "0x%02lx", IRam.Size+IRam.Start-1);
313         sprintf(size, "%5lu", IRam.Size);
314         sprintf(max, "%5lu", IRam.Max);
315         fprintf(of, format, IRam.Name, start, end, size, max);
316
317         /*Report XRam totals:*/
318         sprintf(start, "0x%04lx", XRam.Start);
319         if(XRam.Size==0)
320                 end[0]=0;/*Empty string*/
321         else
322                 sprintf(end,  "0x%04lx", XRam.Size+XRam.Start-1);
323         sprintf(size, "%5lu", XRam.Size);
324         sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
325         fprintf(of, format, XRam.Name, start, end, size, max);
326
327         /*Report Rom/Flash totals:*/
328         sprintf(start, "0x%04lx", Rom.Start);
329         if(Rom.Size==0)
330                 end[0]=0;/*Empty string*/
331         else
332                 sprintf(end,  "0x%04lx", Rom.Size+Rom.Start-1);
333         sprintf(size, "%5lu", Rom.Size);
334         sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
335         fprintf(of, format, Rom.Name, start, end, size, max);
336
337         /*Report any excess:*/
338 #if 0
339         if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
340         {
341                 sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
342                 REPORT_ERROR(buff, 1);
343         }
344 #endif
345         if( ((XRam.Start+XRam.Size)>XRam.Max) ||
346                 (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
347         {
348                 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
349                 REPORT_ERROR(buff, 1);
350         }
351         if( ((Rom.Start+Rom.Size)>Rom.Max) ||
352                 (((int)Rom.Size>code_size)&&(code_size>=0)) )
353         {
354                 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
355                 REPORT_ERROR(buff, 1);
356         }
357
358         fclose(of);
359         return toreturn;                
360 }