1 /* lkmem.c - Create a memory summary file with extension .mem
3 Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
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
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.
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/>. */
25 int summary(struct area
* areap
)
27 if (TARGET_IS_8051
|| TARGET_IS_6808
) {
28 /* only for 8051 and 6808 targets */
30 #define EQ(A,B) !as_strcmpi((A),(B))
32 #define REPORT_ERROR(A, H) \
34 fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
35 fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
39 #define REPORT_WARNING(A, H) \
41 fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
42 fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
47 unsigned int Total_Last
=0, k
;
52 /*Artifacts used for printing*/
53 char start
[15], end
[15], size
[15], max
[15];
54 char format
[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
55 char line
[]="---------------------";
66 unsigned int dram
[0x100];
68 {0, 8, 8, "REG_BANK_0", 0x0001},
69 {0x8, 8, 8, "REG_BANK_1", 0x0002},
70 {0x10, 8, 8, "REG_BANK_2", 0x0004},
71 {0x18, 8, 8, "REG_BANK_3", 0x0008},
72 {0x20, 0, 16, "BSEG_BYTES", 0x0010},
73 {0, 0, 128, "UNUSED", 0x0000},
74 {0x7f, 0, 128, "DATA", 0x0020},
75 {0, 0, 128, "TOTAL:", 0x0000}
78 _Mem IRam8051
= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
79 _Mem Stack8051
= {0xff, 0, 1, "STACK", 0x0000};
80 _Mem XRam8051
= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
81 _Mem Rom8051
= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
84 {0, 0, 0, "REG_BANK_0", 0x0001},
85 {0x0, 0, 0, "REG_BANK_1", 0x0002},
86 {0x0, 0, 0, "REG_BANK_2", 0x0004},
87 {0x0, 0, 0, "REG_BANK_3", 0x0008},
88 {0x0, 0, 0, "BSEG_BYTES", 0x0010},
89 {0, 0, 256, "UNUSED", 0x0000},
90 {0xff, 0, 256, "DATA", 0x0020},
91 {0, 0, 256, "TOTAL:", 0x0000}
94 _Mem IRam6808
= {0xff, 0, 0, "INDIRECT RAM", 0x0080};
95 _Mem Stack6808
= {0xff, 0, 1, "STACK", 0x0000};
96 _Mem XRam6808
= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
97 _Mem Rom6808
= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
101 _Mem IRam
= {0, 0, 0, "", 0};
102 _Mem Stack
= {0, 0, 0, "", 0};
103 _Mem XRam
= {0, 0, 0, "", 0};
104 _Mem Rom
= {0, 0, 0, "", 0};
106 if (TARGET_IS_8051
) {
108 memcpy(&IRam
, &IRam8051
, sizeof (_Mem
));
109 memcpy(&Stack
, &Stack8051
, sizeof (_Mem
));
110 memcpy(&XRam
, &XRam8051
, sizeof (_Mem
));
111 memcpy(&Rom
, &Rom8051
, sizeof (_Mem
));
115 memcpy(&IRam
, &IRam6808
, sizeof (_Mem
));
116 memcpy(&Stack
, &Stack6808
, sizeof (_Mem
));
117 memcpy(&XRam
, &XRam6808
, sizeof (_Mem
));
118 memcpy(&Rom
, &Rom6808
, sizeof (_Mem
));
121 if (stacksize
== 0) stacksize
= MIN_STACK
;
123 if (TARGET_IS_8051
) {
124 if(rflag
) /*For the DS390*/
126 XRam
.Max
=0x1000000; /*24 bits*/
132 if((iram_size
<=0)||(iram_size
>0x100)) /*Default: 8052 like memory*/
140 else if(iram_size
<0x80)
142 Ram
[5].Max
=iram_size
;
143 Ram
[6].Max
=iram_size
;
144 Ram
[7].Max
=iram_size
;
152 IRam
.Max
=iram_size
-0x80;
156 for(j
=0; j
<(int)iram_size
; j
++) dram
[j
]=0;
157 for(; j
<0x100; j
++) dram
[j
]=0x8000; /*Memory not available*/
159 /* Open Memory Summary File*/
160 of
= afile(linkp
->f_idp
, "mem", 1);
169 /**/ if (EQ(xp
->a_id
, "REG_BANK_0"))
171 Ram
[0].Size
=xp
->a_size
;
173 else if (EQ(xp
->a_id
, "REG_BANK_1"))
175 Ram
[1].Size
=xp
->a_size
;
177 else if (EQ(xp
->a_id
, "REG_BANK_2"))
179 Ram
[2].Size
=xp
->a_size
;
181 else if (EQ(xp
->a_id
, "REG_BANK_3"))
183 Ram
[3].Size
=xp
->a_size
;
185 else if (EQ(xp
->a_id
, "BSEG_BYTES"))
188 Ram
[4].Size
+=xp
->a_size
;
190 Ram
[4].Size
=xp
->a_size
;
193 else if (EQ(xp
->a_id
, "SSEG"))
195 Stack
.Size
+=xp
->a_size
;
196 if(xp
->a_addr
<Stack
.Start
) Stack
.Start
=xp
->a_addr
;
199 else if (EQ(xp
->a_id
, "ISEG"))
201 IRam
.Size
+=xp
->a_size
;
202 if(xp
->a_addr
<IRam
.Start
) IRam
.Start
=xp
->a_addr
;
205 else if (TARGET_IS_8051
)
207 if(xp
->a_flag
& A_XDATA
)
211 XRam
.Size
+=xp
->a_size
;
212 if(xp
->a_addr
<XRam
.Start
) XRam
.Start
=xp
->a_addr
;
216 else if (EQ(xp
->a_id
, "BIT_BANK"))
218 Ram
[4].Size
+=xp
->a_size
;
221 else if(xp
->a_flag
& A_CODE
)
225 Rom
.Size
+=xp
->a_size
;
226 if(xp
->a_addr
<Rom
.Start
) Rom
.Start
=xp
->a_addr
;
231 else if(TARGET_IS_6808
)
233 if ( EQ(xp
->a_id
, "DSEG") || EQ(xp
->a_id
, "OSEG") )
235 Ram
[6].Size
+=xp
->a_size
;
236 if(xp
->a_addr
<Ram
[6].Start
) Ram
[6].Start
=xp
->a_addr
;
239 else if( EQ(xp
->a_id
, "CSEG") || EQ(xp
->a_id
, "GSINIT") ||
240 EQ(xp
->a_id
, "GSFINAL") || EQ(xp
->a_id
, "HOME") )
242 Rom
.Size
+=xp
->a_size
;
243 if(xp
->a_addr
<Rom
.Start
) Rom
.Start
=xp
->a_addr
;
246 else if (EQ(xp
->a_id
, "XSEG") || EQ(xp
->a_id
, "XISEG"))
248 XRam
.Size
+=xp
->a_size
;
249 if(xp
->a_addr
<XRam
.Start
) XRam
.Start
=xp
->a_addr
;
253 /*If is not a register bank, bit, stack, or idata, then it should be data*/
254 else if((TARGET_IS_8051
&& xp
->a_flag
& (A_CODE
|A_BIT
|A_XDATA
))==0)
258 Ram
[6].Size
+=xp
->a_size
;
259 if(xp
->a_addr
<Ram
[6].Start
) Ram
[6].Start
=xp
->a_addr
;
267 for(k
=Ram
[j
].Start
; (k
<(Ram
[j
].Start
+Ram
[j
].Size
))&&(k
<0x100); k
++)
268 dram
[k
]|=Ram
[j
].flag
; /*Mark as used*/
270 if (TARGET_IS_8051
) {
271 for(k
=IRam
.Start
; (k
<(IRam
.Start
+IRam
.Size
))&&(k
<0x100); k
++)
272 dram
[k
]|=IRam
.flag
; /*Mark as used*/
275 /*Compute the amount of unused memory in direct data Ram. This is the
276 gap between the last register bank or bit segment and the data segment.*/
277 for(k
=Ram
[6].Start
-1; (dram
[k
]==0) && (k
>0); k
--);
279 Ram
[5].Size
=Ram
[6].Start
-Ram
[5].Start
; /*It may be zero (which is good!)*/
281 /*Compute the data Ram totals*/
284 if(Ram
[7].Start
>Ram
[j
].Start
) Ram
[7].Start
=Ram
[j
].Start
;
285 Ram
[7].Size
+=Ram
[j
].Size
;
287 Total_Last
=Ram
[6].Size
+Ram
[6].Start
-1;
289 /*Report the Ram totals*/
290 fprintf(of
, "Direct Internal RAM:\n");
291 fprintf(of
, format
, "Name", "Start", "End", "Size", "Max");
295 if((j
==0) || (j
==7)) fprintf(of
, format
, line
, line
, line
, line
, line
);
296 if((j
!=5) || (Ram
[j
].Size
>0))
298 sprintf(start
, "0x%02lx", Ram
[j
].Start
);
300 end
[0]=0;/*Empty string*/
302 sprintf(end
, "0x%02lx", j
==7?Total_Last
:Ram
[j
].Size
+Ram
[j
].Start
-1);
303 sprintf(size
, "%5lu", Ram
[j
].Size
);
304 sprintf(max
, "%5lu", Ram
[j
].Max
);
305 fprintf(of
, format
, Ram
[j
].Name
, start
, end
, size
, max
);
309 if (TARGET_IS_8051
) {
310 for(k
=Ram
[6].Start
; (k
<(Ram
[6].Start
+Ram
[6].Size
))&&(k
<0x100); k
++)
312 if(dram
[k
]!=Ram
[6].flag
)
314 sprintf(buff
, "Internal memory overlap starting at 0x%02x.\n", k
);
315 REPORT_ERROR(buff
, 1);
320 if(Ram
[4].Size
>Ram
[4].Max
)
322 k
=Ram
[4].Size
-Ram
[4].Max
;
323 sprintf(buff
, "Insufficient bit addressable memory. "
324 "%d byte%s short.\n", k
, (k
==1)?"":"s");
325 REPORT_ERROR(buff
, 1);
330 sprintf(buff
, "%ld bytes in data memory wasted. "
331 "SDCC link could use: --data-loc 0x%02lx\n",
332 Ram
[5].Size
, Ram
[6].Start
-Ram
[5].Size
);
333 REPORT_WARNING(buff
, 1);
336 if((Ram
[6].Start
+Ram
[6].Size
)>Ram
[6].Max
)
338 k
=(Ram
[6].Start
+Ram
[6].Size
)-Ram
[6].Max
;
339 sprintf(buff
, "Insufficient space in data memory. "
340 "%d byte%s short.\n", k
, (k
==1)?"":"s");
341 REPORT_ERROR(buff
, 1);
345 /*Report the position of the beginning of the stack*/
346 fprintf(of
, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
347 rflag
? "16 bit mode initial s" : "S", Stack
.Start
, Stack
.Start
-1);
349 if (TARGET_IS_8051
) {
350 /*Check that the stack pointer is landing in a safe place:*/
351 if( (dram
[Stack
.Start
] & 0x8000) == 0x8000 )
354 sprintf(buff
, "Stack set to unavailable memory.\n");
355 REPORT_ERROR(buff
, 1);
357 else if(dram
[Stack
.Start
])
360 sprintf(buff
, "Stack overlaps area ");
361 REPORT_ERROR(buff
, 1);
364 if(dram
[Stack
.Start
]&Ram
[j
].flag
)
366 sprintf(buff
, "'%s'\n", Ram
[j
].Name
);
370 if(dram
[Stack
.Start
]&IRam
.flag
)
372 sprintf(buff
, "'%s'\n", IRam
.Name
);
374 REPORT_ERROR(buff
, 0);
378 for(j
=Stack
.Start
, k
=0; (j
<(int)iram_size
)&&(dram
[j
]==0); j
++, k
++);
379 fprintf(of
, " with %d bytes available\n", k
);
380 if ((int)k
<stacksize
)
382 sprintf(buff
, "Only %d byte%s available for stack.\n",
384 REPORT_WARNING(buff
, 1);
389 fprintf(of
, "\nOther memory:\n");
390 fprintf(of
, format
, "Name", "Start", "End", "Size", "Max");
391 fprintf(of
, format
, line
, line
, line
, line
, line
);
393 /*Report IRam totals:*/
396 start
[0]=0;/*Empty string*/
397 end
[0]=0;/*Empty string*/
401 sprintf(start
, "0x%02lx", IRam
.Start
);
402 sprintf(end
, "0x%02lx", IRam
.Size
+IRam
.Start
-1);
404 sprintf(size
, "%5lu", IRam
.Size
);
405 sprintf(max
, "%5lu", IRam
.Max
);
406 fprintf(of
, format
, IRam
.Name
, start
, end
, size
, max
);
408 /*Report XRam totals:*/
411 start
[0]=0;/*Empty string*/
412 end
[0]=0;/*Empty string*/
416 sprintf(start
, "0x%04lx", XRam
.Start
);
417 sprintf(end
, "0x%04lx", XRam
.Size
+XRam
.Start
-1);
419 sprintf(size
, "%5lu", XRam
.Size
);
420 sprintf(max
, "%5lu", xram_size
<0?XRam
.Max
:xram_size
);
421 fprintf(of
, format
, XRam
.Name
, start
, end
, size
, max
);
423 /*Report Rom/Flash totals:*/
426 start
[0]=0;/*Empty string*/
427 end
[0]=0;/*Empty string*/
431 sprintf(start
, "0x%04lx", Rom
.Start
);
432 sprintf(end
, "0x%04lx", Rom
.Size
+Rom
.Start
-1);
434 sprintf(size
, "%5lu", Rom
.Size
);
435 sprintf(max
, "%5lu", code_size
<0?Rom
.Max
:code_size
);
436 fprintf(of
, format
, Rom
.Name
, start
, end
, size
, max
);
438 /*Report any excess:*/
439 if (TARGET_IS_8051
) {
440 if((IRam
.Start
+IRam
.Size
)>(IRam
.Max
+0x80))
442 sprintf(buff
, "Insufficient INDIRECT RAM memory.\n");
443 REPORT_ERROR(buff
, 1);
446 if( ((XRam
.Start
+XRam
.Size
)>XRam
.Max
) ||
447 (((int)XRam
.Size
>xram_size
)&&(xram_size
>=0)) )
449 sprintf(buff
, "Insufficient EXTERNAL RAM memory.\n");
450 REPORT_ERROR(buff
, 1);
452 if( ((Rom
.Start
+Rom
.Size
)>Rom
.Max
) ||
453 (((int)Rom
.Size
>code_size
)&&(code_size
>=0)) )
455 sprintf(buff
, "Insufficient ROM/EPROM/FLASH memory.\n");
456 REPORT_ERROR(buff
, 1);
468 int summary2(struct area
* areap
)
470 if (TARGET_IS_8051
) {
471 /* only for 8051 target */
473 #define EQ(A,B) !as_strcmpi((A),(B))
478 unsigned long int Stack_Start
=0, Stack_Size
;
479 unsigned int spare_begin
= 0, spare_size
= 0;
482 struct area
* xstack_xp
= NULL
;
485 /*Artifacts used for printing*/
486 char start
[15], end
[15], size
[15], max
[15];
487 char format
[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
488 char line
[]="---------------------";
500 _Mem Stack
={0xff, 0, 0, 1, "STACK", 0x0000};
501 _Mem Paged
={0xffff, 0, 0, 256, "PAGED EXT. RAM", A3_PAG
};
502 _Mem XRam
= {0xffff, 0, 0, 65536, "EXTERNAL RAM", 0x0100};
503 _Mem Rom
= {0xffff, 0, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
505 if(rflag
) /*For the DS390*/
507 XRam
.Max
=0x1000000; /*24 bits*/
513 /* Open Memory Summary File*/
514 of
= afile(linkp
->f_idp
, "mem", 1);
523 if (xp
->a_flag
& A_CODE
)
527 Rom
.Size
+= xp
->a_size
;
528 if(xp
->a_addr
< Rom
.Start
)
529 Rom
.Start
= xp
->a_addr
;
530 if(xp
->a_addr
+ xp
->a_size
> Rom
.End
)
531 Rom
.End
= xp
->a_addr
+ xp
->a_size
;
535 else if (EQ(xp
->a_id
, "SSEG"))
537 Stack
.Size
+= xp
->a_size
;
538 if(xp
->a_addr
< Stack
.Start
)
539 Stack
.Start
= xp
->a_addr
;
540 if(xp
->a_addr
+ xp
->a_size
> Stack
.End
)
541 Stack
.End
= xp
->a_addr
+ xp
->a_size
;
544 else if (EQ(xp
->a_id
, "PSEG"))
546 Paged
.Size
+= xp
->a_size
;
547 if(xp
->a_addr
< Paged
.Start
)
548 Paged
.Start
= xp
->a_addr
;
549 if(xp
->a_addr
+ xp
->a_size
> Paged
.End
)
550 Paged
.End
= xp
->a_addr
+ xp
->a_size
;
553 else if (EQ(xp
->a_id
, "XSTK"))
556 Paged
.Size
+= xp
->a_size
;
557 if(xp
->a_addr
< Paged
.Start
)
558 Paged
.Start
= xp
->a_addr
;
559 if(xp
->a_addr
+ xp
->a_size
> Paged
.End
)
560 Paged
.End
= xp
->a_addr
+ xp
->a_size
;
563 else if (xp
->a_flag
& A_XDATA
)
567 XRam
.Size
+= xp
->a_size
;
568 if(xp
->a_addr
< XRam
.Start
)
569 XRam
.Start
= xp
->a_addr
;
570 if(xp
->a_addr
+ xp
->a_size
> XRam
.End
)
571 XRam
.End
= xp
->a_addr
+ xp
->a_size
;
578 /*Report the Ram totals*/
579 fprintf(of
, "Internal RAM layout:\n");
580 fprintf(of
, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
583 if(j
%16==0) fprintf(of
, "\n0x%02x:|", j
);
584 fprintf(of
, "%c|", idatamap
[j
]);
586 fprintf(of
, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
597 for(j
=Stack_Start
, Stack_Size
=0; j
<((iram_size
)?iram_size
:256); j
++)
599 if(idatamap
[j
]=='S') Stack_Size
++;
608 fprintf(of
, "\nERROR: Couldn't get %d byte%s allocated"
609 " in internal RAM for area %s.",
610 xp
->a_unaloc
, xp
->a_unaloc
>1?"s":"", xp
->a_id
);
616 /*Report the position of the begining of the stack*/
617 if(Stack_Start
!=256 && Stack_Size
> 0)
618 fprintf(of
, "\n%s starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
619 rflag
? "16 bit mode initial stack" : "Stack", Stack_Start
, Stack_Start
-1, Stack_Size
);
621 fprintf(of
, "\nNo clue at where the stack begins and ends!");
623 /* Report the spare space left in the IRAM */
624 for (j
= 0; j
< (iram_size
? iram_size
: 256); )
626 for (i
= j
; i
< (iram_size
? iram_size
: 256) && idatamap
[i
] == ' '; i
++);
627 if (i
- j
> spare_size
)
635 fprintf(of
, "\nThe largest spare internal RAM space starts at 0x%x with %d byte%s available.", spare_begin
, spare_size
, spare_size
> 1 ? "s" : "");
637 fprintf(of
, "\nNo spare internal RAM space left.");
639 /*Report about xstack*/
642 Stack_Start
= xstack_xp
->a_addr
;
643 Stack_Size
= xstack_xp
->a_size
;
644 fprintf(of
, "\nXstack starts at: 0x%04lx with %ld bytes available.",
645 Stack_Start
, Stack_Size
);
648 fprintf(of
, "\n\nOther memory:\n");
649 fprintf(of
, format
, "Name", "Start", "End", "Size", "Max");
650 fprintf(of
, format
, line
, line
, line
, line
, line
);
652 /*Report Paged XRam totals:*/
655 start
[0]=0;/*Empty string*/
656 end
[0]=0;/*Empty string*/
660 sprintf(start
, "0x%04lx", Paged
.Start
);
661 sprintf(end
, "0x%04lx", Paged
.End
-1);
663 sprintf(size
, "%5lu", Paged
.Size
);
664 sprintf(max
, "%5lu", xram_size
<0 ? Paged
.Max
: xram_size
<256 ? xram_size
: 256);
665 fprintf(of
, format
, Paged
.Name
, start
, end
, size
, max
);
667 /*Report XRam totals:*/
670 start
[0]=0;/*Empty string*/
671 end
[0]=0;/*Empty string*/
675 sprintf(start
, "0x%04lx", XRam
.Start
);
676 sprintf(end
, "0x%04lx", XRam
.End
-1);
678 sprintf(size
, "%5lu", XRam
.Size
);
679 sprintf(max
, "%5lu", xram_size
<0?XRam
.Max
:xram_size
);
680 fprintf(of
, format
, XRam
.Name
, start
, end
, size
, max
);
682 /*Report Rom/Flash totals:*/
685 start
[0]=0;/*Empty string*/
686 end
[0]=0;/*Empty string*/
690 sprintf(start
, "0x%04lx", Rom
.Start
);
691 sprintf(end
, "0x%04lx", Rom
.End
-1);
693 sprintf(size
, "%5lu", Rom
.Size
);
694 sprintf(max
, "%5lu", code_size
<0?Rom
.Max
:code_size
);
695 fprintf(of
, format
, Rom
.Name
, start
, end
, size
, max
);
697 /*Report any excess:*/
698 if( ((XRam
.End
) > XRam
.Max
) ||
699 ((((int)XRam
.Size
+(int)Paged
.Size
)>xram_size
)&&(xram_size
>=0)) )
701 sprintf(buff
, "Insufficient EXTERNAL RAM memory.\n");
702 REPORT_ERROR(buff
, 1);
704 if( ((Rom
.End
) > Rom
.Max
) ||
705 (((int)Rom
.Size
>code_size
)&&(code_size
>=0)) )
707 sprintf(buff
, "Insufficient ROM/EPROM/FLASH memory.\n");
708 REPORT_ERROR(buff
, 1);