Now reports memory usage using the value from option --iram-size.
[fw/sdcc] / as / mcs51 / lklist.c
index 5ac3f07b6a70d85f8c078af62989593878f186b2..688134a027b4cd3a54a595b2886cd2e8355b0c3e 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <alloc.h>
+#include <stdlib.h>
 #include "aslink.h"
 
 /*)Module      lklist.c
@@ -116,6 +116,23 @@ FILE *fp;
        lop = 1;
 }
 
+/* Used for qsort call in lstsym */
+static int _cmpSymByAddr(const void *p1, const void *p2)
+{
+    struct sym **s1 = (struct sym **)(p1);
+    struct sym **s2 = (struct sym **)(p2);
+    int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
+               ((*s2)->s_addr + (*s2)->s_axp->a_addr);
+
+    /* Sort first by address, then by name. */
+    if (delta)
+    {
+       return delta;
+    }
+    return strcmp((*s1)->s_id,(*s2)->s_id);    
+}
+
+
 #if    NCPS-8
 
 /* NCPS != 8 */
@@ -138,9 +155,9 @@ FILE *fp;
  *             int     j               bubble sort update status
  *             char *  ptr             pointer to an id string
  *             int     nmsym           number of symbols in area
- *             addr_t  a0              temporary
- *             addr_t  ai              temporary
- *             addr_t  aj              temporary
+ *             Addr_T  a0              temporary
+ *             Addr_T  ai              temporary
+ *             Addr_T  aj              temporary
  *             sym *   sp              pointer to a symbol structure
  *             sym **  p               pointer to an array of
  *                                     pointers to symbol structures
@@ -167,10 +184,12 @@ lstarea(xp)
 struct area *xp;
 {
        register struct areax *oxp;
-       register int i, j;
+       register int i;
+       /* int j; */
        register char *ptr;
        int nmsym;
-       addr_t a0, ai, aj;
+       /* Addr_T a0; */
+       Addr_T     ai, aj;
        struct sym *sp;
        struct sym **p;
        int memPage;
@@ -186,7 +205,8 @@ struct area *xp;
                fprintf(mfp, "Decimal\n\n");
        }
        fprintf(mfp, "Area                               ");
-       fprintf(mfp, "Addr   Size   Decimal Bytes (Attributes)\n");
+       fprintf(mfp, "Addr   Size   Decimal %s (Attributes)\n",
+               (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/
        fprintf(mfp, "--------------------------------   ");
        fprintf(mfp, "----   ----   ------- ----- ------------\n");
        /*
@@ -205,7 +225,8 @@ struct area *xp;
        if (xflag == 2) {
                fprintf(mfp, "  %05u  %05u", ai, aj);
        }
-       fprintf(mfp, " = %6u. bytes ", aj);
+       fprintf(mfp, " = %6u. %s ", aj,
+               (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/
        if (xp->a_flag & A_ABS) {
                fprintf(mfp, "(ABS");
        } else {
@@ -289,6 +310,7 @@ struct area *xp;
                oxp = oxp->a_axp;
        }
 
+#if 0
        /*
         * Bubble Sort of Addresses in Symbol Table Array
         */
@@ -308,6 +330,9 @@ struct area *xp;
                        a0 = ai;
                }
        }
+#else
+       qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif 
 
        /*
         * Symbol Table Output
@@ -374,9 +399,9 @@ struct area *xp;
  *             int     j               bubble sort update status
  *             char *  ptr             pointer to an id string
  *             int     nmsym           number of symbols in area
- *             addr_t  a0              temporary
- *             addr_t  ai              temporary
- *             addr_t  aj              temporary
+ *             Addr_T  a0              temporary
+ *             Addr_T  ai              temporary
+ *             Addr_T  aj              temporary
  *             sym *   sp              pointer to a symbol structure
  *             sym **  p               pointer to an array of
  *                                     pointers to symbol structures
@@ -406,7 +431,7 @@ struct area *xp;
        register c, i, j;
        register char *ptr;
        int nmsym;
-       addr_t a0, ai, aj;
+       Addr_T a0, ai, aj;
        struct sym *sp;
        struct sym **p;
         int page;
@@ -521,6 +546,7 @@ struct area *xp;
                oxp = oxp->a_axp;
        }
 
+#if 0
        /*
         * Bubble Sort of Addresses in Symbol Table Array
         */
@@ -540,6 +566,9 @@ struct area *xp;
                        a0 = ai;
                }
        }
+#else
+       qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif 
 
        /*
         * Symbol Table Output
@@ -586,7 +615,7 @@ struct area *xp;
  *     output file.
  *
  *     local variables:
- *             addr_t  pc              current program counter address
+ *             Addr_T  pc              current program counter address
  *
  *     global variables:
  *             int     hilo            byte order
@@ -597,7 +626,7 @@ struct area *xp;
  *                                     output RST file
  *             int     rtcnt           count of data words
  *             int     rtflg[]         output the data flag
- *             addr_t  rtval[]         relocated data
+ *             Addr_T  rtval[]         relocated data
  *             FILE    *tfp            The file handle to the current
  *                                     LST file being scanned
  *
@@ -617,7 +646,7 @@ VOID
 lkulist(i)
 int i;
 {
-       addr_t pc;
+       Addr_T pc;
 
        /*
         * Exit if listing file is not open
@@ -718,7 +747,7 @@ int i;
 
 VOID
 lkalist(pc)
-addr_t pc;
+Addr_T pc;
 {
        char str[8];
        int i;
@@ -845,7 +874,7 @@ loop:       if (tfp == NULL)
 
 VOID
 lkglist(pc,v)
-addr_t pc;
+Addr_T pc;
 int v;
 {
        char str[8];
@@ -1067,3 +1096,319 @@ char *str;
        }
        return(1);
 }
+
+/*JCF: Create a memory summary file with extension .mem*/
+int summary(struct area * areap) 
+{
+       #define EQ(A,B) !strcmpi((A),(B))
+       #define MIN_STACK 16
+       #define REPORT_ERROR(A, H) \
+       {\
+               fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
+               fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
+               toreturn=1; \
+       }
+
+       #define REPORT_WARNING(A, H) \
+       { \
+               fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
+               fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
+       }
+
+       char buff[128];
+       int j, toreturn=0;
+       unsigned int Total_Last=0, k; 
+
+       struct area * xp;
+       FILE * of;
+       
+       /*Artifacts used for printing*/
+       char start[8], end[8], size[8], max[8];
+       char format[]="   %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
+       char line[]="---------------------";
+
+       typedef struct
+       {
+               unsigned int Start;
+               unsigned int Size;
+               unsigned int Max;
+               char Name[NCPS];
+               unsigned int flag;
+       } _Mem;
+
+       unsigned int dram[0x100];
+       _Mem Ram[]={
+               {0,             8,      8,       "REG_BANK_0", 0x0001},
+               {0x8,   8,      8,       "REG_BANK_1", 0x0002},
+               {0x10,  8,      8,       "REG_BANK_2", 0x0004},
+               {0x18,  8,      8,       "REG_BANK_3", 0x0008},
+               {0x20,  0,      16,      "BSEG_BYTES", 0x0010},
+               {0,             0,      128, "UNUSED",     0x0000},
+               {0x7f,  0,      128, "DATA",       0x0020},
+               {0,             0,      128, "TOTAL:",     0x0000}
+       };
+       
+       _Mem IRam= {0xff,   0,   128, "INDIRECT RAM",           0x0080};
+       _Mem Stack={0xff,   0,     1, "STACK",                          0x0000};
+       _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM",           0x0100};
+       _Mem Rom=  {0xffff, 0, 65536, "ROM/EPROM/FLASH",        0x0200};
+
+       if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
+       {
+               Ram[5].Max=0x80;
+               Ram[6].Max=0x80;
+               Ram[7].Max=0x80;
+               IRam.Max=0x80;
+               iram_size=0x100;
+       }
+       else if(iram_size<0x80)
+       {
+               Ram[5].Max=iram_size;
+               Ram[6].Max=iram_size;
+               Ram[7].Max=iram_size;
+               IRam.Max=0;
+       }
+       else
+       {
+               Ram[5].Max=0x80;
+               Ram[6].Max=0x80;
+               Ram[7].Max=0x80;
+               IRam.Max=iram_size-0x80;
+       }
+
+       for(j=0; j<(int)iram_size; j++) dram[j]=0;
+       for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
+
+       /* Open Memory Summary File*/
+       of = afile(linkp->f_idp, "mem", 1);
+       if (of == NULL)
+       {
+               lkexit(1);
+       }
+
+       xp=areap;
+       while (xp)
+       {
+               /**/ if (EQ(xp->a_id, "REG_BANK_0"))
+               {
+                       Ram[0].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_1"))
+               {
+                       Ram[1].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_2"))
+               {
+                       Ram[2].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_3"))
+               {
+                       Ram[3].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "BSEG_BYTES"))
+               {
+                       Ram[4].Size=xp->a_size;
+               }
+               else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
+               {
+                       Ram[6].Size+=xp->a_size;
+                       if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
+               }
+
+               else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
+                                EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
+               {
+                       Rom.Size+=xp->a_size;
+                       if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
+               }
+               
+               else if (EQ(xp->a_id, "SSEG"))
+               {
+                       Stack.Size+=xp->a_size;
+                       if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
+               }
+
+               else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) 
+               {
+                       XRam.Size+=xp->a_size;
+                       if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
+               }
+
+               else if (EQ(xp->a_id, "ISEG"))
+               {
+                       IRam.Size+=xp->a_size;
+                       if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
+               }
+               xp=xp->a_ap;
+       }
+
+       for(j=0; j<7; j++)
+               for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
+                       dram[k]|=Ram[j].flag; /*Mark as used*/
+       
+       for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
+               dram[k]|=IRam.flag; /*Mark as used*/
+
+       /*Compute the amount of unused memory in direct data Ram.  This is the
+       gap between the last register bank or bit segment and the data segment.*/
+       for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
+       Ram[5].Start=k+1;
+       Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
+
+       /*Compute the data Ram totals*/
+       for(j=0; j<7; j++)
+       {
+               if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
+               Ram[7].Size+=Ram[j].Size;
+       }
+       Total_Last=Ram[6].Size+Ram[6].Start-1;
+
+       /*Report the Ram totals*/
+       fprintf(of, "Direct Internal RAM:\n");
+       fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+
+       for(j=0; j<8; j++)
+       {
+               if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
+               if((j!=5) || (Ram[j].Size>0))
+               {
+                       sprintf(start, "0x%02x", Ram[j].Start);
+                       if(Ram[j].Size==0)
+                               end[0]=0;/*Empty string*/
+                       else
+                               sprintf(end,  "0x%02x", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
+                       sprintf(size, "%5u", Ram[j].Size);
+                       sprintf(max, "%5u", Ram[j].Max);
+                       fprintf(of, format, Ram[j].Name, start, end, size, max);
+               }
+       }
+
+       for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
+       {
+               if(dram[k]!=Ram[6].flag)
+               {
+                       sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
+                       REPORT_ERROR(buff, 1);
+                       break;
+               }
+       }
+
+       if(Ram[4].Size>Ram[4].Max)
+       {
+               k=Ram[4].Size-Ram[4].Max;
+               sprintf(buff, "Insufficient bit addressable memory.  "
+                                       "%d byte%s short.\n", k, (k==1)?"":"s");
+               REPORT_ERROR(buff, 1);
+       }
+
+       if(Ram[5].Size!=0)
+       {
+               sprintf(buff, "%d bytes in DRAM wasted.  "
+                           "SDCC link could use: --data-loc 0x%02x\n",
+                                       Ram[5].Size, Ram[6].Start-Ram[5].Size);
+               REPORT_WARNING(buff, 1);
+       }
+
+       if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
+       {
+               k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
+               sprintf(buff, "Insufficient DRAM memory.  "
+                                       "%d byte%s short.\n", k, (k==1)?"":"s");
+               REPORT_ERROR(buff, 1);
+       }
+
+       /*Report the position of the begining of the stack*/
+       fprintf(of, "\nStack starts at: 0x%02x", Stack.Start);
+
+       /*Check that the stack pointer is landing in a safe place:*/
+       if( (dram[Stack.Start] & 0x8000) == 0x8000 )
+       {
+               fprintf(of, ".\n");
+               sprintf(buff, "Stack set to unavailable memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+       else if(dram[Stack.Start])
+       {
+               fprintf(of, ".\n");
+               sprintf(buff, "Stack overlaps area ");
+               REPORT_ERROR(buff, 1);
+               for(j=0; j<7; j++)
+               {
+                       if(dram[Stack.Start]&Ram[j].flag)
+                       {
+                               sprintf(buff, "'%s'\n", Ram[j].Name);
+                               break;
+                       }
+               }
+               if(dram[Stack.Start]&IRam.flag)
+               {
+                       sprintf(buff, "'%s'\n", IRam.Name);
+               }
+               REPORT_ERROR(buff, 0);
+       }
+       else    
+       {
+               for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
+               fprintf(of, " with %d bytes available\n", k);
+               if (k<MIN_STACK)
+               {
+                       sprintf(buff, "Only %d byte%s available for stack.\n",
+                                       k, (k==1)?"":"s");
+                       REPORT_WARNING(buff, 1);
+               }
+       }
+
+       fprintf(of, "\nOther memory:\n");
+       fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+       fprintf(of, format, line, line, line, line, line);
+
+       /*Report IRam totals:*/
+       sprintf(start, "0x%02x", IRam.Start);
+       if(IRam.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%02x", IRam.Size+IRam.Start-1);
+       sprintf(size, "%5u", IRam.Size);
+       sprintf(max, "%5u", IRam.Max);
+       fprintf(of, format, IRam.Name, start, end, size, max);
+
+       /*Report XRam totals:*/
+       sprintf(start, "0x%04x", XRam.Start);
+       if(XRam.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%04x", XRam.Size+XRam.Start-1);
+       sprintf(size, "%5u", XRam.Size);
+       sprintf(max, "%5u", XRam.Max);
+       fprintf(of, format, XRam.Name, start, end, size, max);
+
+       /*Report Rom/Flash totals:*/
+       sprintf(start, "0x%04x", Rom.Start);
+       if(Rom.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%04x", Rom.Size+Rom.Start-1);
+       sprintf(size, "%5u", Rom.Size);
+       sprintf(max, "%5u", Rom.Max);
+       fprintf(of, format, Rom.Name, start, end, size, max);
+
+       /*Report any excess:*/
+       if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
+       {
+               sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+       if((XRam.Start+XRam.Size)>XRam.Max)
+       {
+               sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+       if((Rom.Start+Rom.Size)>Rom.Max)
+       {
+               sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+
+       fclose(of);
+       return toreturn;                
+}