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