Added support to generate aomf51 file. (Basic Intel support, no Keil
[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
26 int summary(struct area * areap) 
27 {
28         #define EQ(A,B) !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[8], end[8], size[8], max[8];
52         char format[]="   %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
53         char line[]="---------------------";
54
55         typedef struct
56         {
57                 unsigned int Start;
58                 unsigned int Size;
59                 unsigned int Max;
60                 char Name[NCPS];
61                 unsigned int 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((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
82         {
83                 Ram[5].Max=0x80;
84                 Ram[6].Max=0x80;
85                 Ram[7].Max=0x80;
86                 IRam.Max=0x80;
87                 iram_size=0x100;
88         }
89         else if(iram_size<0x80)
90         {
91                 Ram[5].Max=iram_size;
92                 Ram[6].Max=iram_size;
93                 Ram[7].Max=iram_size;
94                 IRam.Max=0;
95         }
96         else
97         {
98                 Ram[5].Max=0x80;
99                 Ram[6].Max=0x80;
100                 Ram[7].Max=0x80;
101                 IRam.Max=iram_size-0x80;
102         }
103
104         for(j=0; j<(int)iram_size; j++) dram[j]=0;
105         for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
106
107         /* Open Memory Summary File*/
108         of = afile(linkp->f_idp, "mem", 1);
109         if (of == NULL)
110         {
111                 lkexit(1);
112         }
113
114         xp=areap;
115         while (xp)
116         {
117                 /**/ if (EQ(xp->a_id, "REG_BANK_0"))
118                 {
119                         Ram[0].Size=xp->a_size;
120                 }
121                 else if (EQ(xp->a_id, "REG_BANK_1"))
122                 {
123                         Ram[1].Size=xp->a_size;
124                 }
125                 else if (EQ(xp->a_id, "REG_BANK_2"))
126                 {
127                         Ram[2].Size=xp->a_size;
128                 }
129                 else if (EQ(xp->a_id, "REG_BANK_3"))
130                 {
131                         Ram[3].Size=xp->a_size;
132                 }
133                 else if (EQ(xp->a_id, "BSEG_BYTES"))
134                 {
135                         Ram[4].Size=xp->a_size;
136                 }
137                 else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
138                 {
139                         Ram[6].Size+=xp->a_size;
140                         if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
141                 }
142
143                 else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
144                                  EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
145                 {
146                         Rom.Size+=xp->a_size;
147                         if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
148                 }
149                 
150                 else if (EQ(xp->a_id, "SSEG"))
151                 {
152                         Stack.Size+=xp->a_size;
153                         if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
154                 }
155
156                 else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) 
157                 {
158                         XRam.Size+=xp->a_size;
159                         if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
160                 }
161
162                 else if (EQ(xp->a_id, "ISEG"))
163                 {
164                         IRam.Size+=xp->a_size;
165                         if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
166                 }
167                 xp=xp->a_ap;
168         }
169
170         for(j=0; j<7; j++)
171                 for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
172                         dram[k]|=Ram[j].flag; /*Mark as used*/
173         
174         for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
175                 dram[k]|=IRam.flag; /*Mark as used*/
176
177         /*Compute the amount of unused memory in direct data Ram.  This is the
178         gap between the last register bank or bit segment and the data segment.*/
179         for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
180         Ram[5].Start=k+1;
181         Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
182
183         /*Compute the data Ram totals*/
184         for(j=0; j<7; j++)
185         {
186                 if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
187                 Ram[7].Size+=Ram[j].Size;
188         }
189         Total_Last=Ram[6].Size+Ram[6].Start-1;
190
191         /*Report the Ram totals*/
192         fprintf(of, "Direct Internal RAM:\n");
193         fprintf(of, format, "Name", "Start", "End", "Size", "Max");
194
195         for(j=0; j<8; j++)
196         {
197                 if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
198                 if((j!=5) || (Ram[j].Size>0))
199                 {
200                         sprintf(start, "0x%02x", Ram[j].Start);
201                         if(Ram[j].Size==0)
202                                 end[0]=0;/*Empty string*/
203                         else
204                                 sprintf(end,  "0x%02x", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
205                         sprintf(size, "%5u", Ram[j].Size);
206                         sprintf(max, "%5u", Ram[j].Max);
207                         fprintf(of, format, Ram[j].Name, start, end, size, max);
208                 }
209         }
210
211         for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
212         {
213                 if(dram[k]!=Ram[6].flag)
214                 {
215                         sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
216                         REPORT_ERROR(buff, 1);
217                         break;
218                 }
219         }
220
221         if(Ram[4].Size>Ram[4].Max)
222         {
223                 k=Ram[4].Size-Ram[4].Max;
224                 sprintf(buff, "Insufficient bit addressable memory.  "
225                                         "%d byte%s short.\n", k, (k==1)?"":"s");
226                 REPORT_ERROR(buff, 1);
227         }
228
229         if(Ram[5].Size!=0)
230         {
231                 sprintf(buff, "%d bytes in DRAM wasted.  "
232                             "SDCC link could use: --data-loc 0x%02x\n",
233                                         Ram[5].Size, Ram[6].Start-Ram[5].Size);
234                 REPORT_WARNING(buff, 1);
235         }
236
237         if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
238         {
239                 k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
240                 sprintf(buff, "Insufficient DRAM memory.  "
241                                         "%d byte%s short.\n", k, (k==1)?"":"s");
242                 REPORT_ERROR(buff, 1);
243         }
244
245         /*Report the position of the begining of the stack*/
246         fprintf(of, "\nStack starts at: 0x%02x", Stack.Start);
247
248         /*Check that the stack pointer is landing in a safe place:*/
249         if( (dram[Stack.Start] & 0x8000) == 0x8000 )
250         {
251                 fprintf(of, ".\n");
252                 sprintf(buff, "Stack set to unavailable memory.\n");
253                 REPORT_ERROR(buff, 1);
254         }
255         else if(dram[Stack.Start])
256         {
257                 fprintf(of, ".\n");
258                 sprintf(buff, "Stack overlaps area ");
259                 REPORT_ERROR(buff, 1);
260                 for(j=0; j<7; j++)
261                 {
262                         if(dram[Stack.Start]&Ram[j].flag)
263                         {
264                                 sprintf(buff, "'%s'\n", Ram[j].Name);
265                                 break;
266                         }
267                 }
268                 if(dram[Stack.Start]&IRam.flag)
269                 {
270                         sprintf(buff, "'%s'\n", IRam.Name);
271                 }
272                 REPORT_ERROR(buff, 0);
273         }
274         else    
275         {
276                 for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
277                 fprintf(of, " with %d bytes available\n", k);
278                 if (k<MIN_STACK)
279                 {
280                         sprintf(buff, "Only %d byte%s available for stack.\n",
281                                         k, (k==1)?"":"s");
282                         REPORT_WARNING(buff, 1);
283                 }
284         }
285
286         fprintf(of, "\nOther memory:\n");
287         fprintf(of, format, "Name", "Start", "End", "Size", "Max");
288         fprintf(of, format, line, line, line, line, line);
289
290         /*Report IRam totals:*/
291         sprintf(start, "0x%02x", IRam.Start);
292         if(IRam.Size==0)
293                 end[0]=0;/*Empty string*/
294         else
295                 sprintf(end,  "0x%02x", IRam.Size+IRam.Start-1);
296         sprintf(size, "%5u", IRam.Size);
297         sprintf(max, "%5u", IRam.Max);
298         fprintf(of, format, IRam.Name, start, end, size, max);
299
300         /*Report XRam totals:*/
301         sprintf(start, "0x%04x", XRam.Start);
302         if(XRam.Size==0)
303                 end[0]=0;/*Empty string*/
304         else
305                 sprintf(end,  "0x%04x", XRam.Size+XRam.Start-1);
306         sprintf(size, "%5u", XRam.Size);
307         sprintf(max, "%5u", XRam.Max);
308         fprintf(of, format, XRam.Name, start, end, size, max);
309
310         /*Report Rom/Flash totals:*/
311         sprintf(start, "0x%04x", Rom.Start);
312         if(Rom.Size==0)
313                 end[0]=0;/*Empty string*/
314         else
315                 sprintf(end,  "0x%04x", Rom.Size+Rom.Start-1);
316         sprintf(size, "%5u", Rom.Size);
317         sprintf(max, "%5u", Rom.Max);
318         fprintf(of, format, Rom.Name, start, end, size, max);
319
320         /*Report any excess:*/
321         if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
322         {
323                 sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
324                 REPORT_ERROR(buff, 1);
325         }
326         if((XRam.Start+XRam.Size)>XRam.Max)
327         {
328                 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
329                 REPORT_ERROR(buff, 1);
330         }
331         if((Rom.Start+Rom.Size)>Rom.Max)
332         {
333                 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
334                 REPORT_ERROR(buff, 1);
335         }
336
337         fclose(of);
338         return toreturn;                
339 }