Linker places variables in unused register banks. Call using -Wl-Y[stack_size]
[fw/sdcc] / as / mcs51 / lkmain.c
index 899e70e1dab5e84dfcd4c74483f2e22052ab5886..fd9e4d070788f16b28036905f9fe5fd0c4f95532 100644 (file)
 #include <string.h>
 #include "aslink.h"
 
+#ifdef WIN32T
+#include <time.h>
+
+void Timer(int action, char * message)
+{
+       static double start, end, total=0.0;
+    static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+
+    if(action==0) start=clock()*secs_per_tick;
+    else if(action==1)
+    {
+       end=clock() * secs_per_tick;
+               printf("%s \t%f seconds.\n", message, (end-start));
+               total+=end-start;
+    }
+    else
+    {
+               printf("Total time: \t%f seconds.\n", total);
+               total=0.0;
+    }
+}
+#endif
+
 /* yuck - but including unistd.h causes problems on Cygwin by redefining
  * Addr_T.
  */
@@ -56,7 +79,7 @@ void Areas51 (void)
 {
        char * rel[]={
                "XH",
-               "H 7 areas 0 global symbols",
+               "H B areas 0 global symbols",
                "A _CODE size 0 flags 0",               /*Each .rel has one, so...*/
                "A REG_BANK_0 size 0 flags 4",  /*Register banks are overlayable*/
                "A REG_BANK_1 size 0 flags 4",
@@ -64,6 +87,10 @@ void Areas51 (void)
                "A REG_BANK_3 size 0 flags 4",
                "A BSEG size 0 flags 80",               /*BSEG must be just before BITS*/
                "A BSEG_BYTES size 0 flags 0",  /*Size will be obtained from BSEG in lnkarea()*/
+               "A DSEG size 0 flags 0",
+               "A OSEG size 0 flags 4",
+               "A ISEG size 0 flags 0",
+               "A SSEG size 0 flags 4",
                ""
        };
        int j;
@@ -82,6 +109,10 @@ void Areas51 (void)
                else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; }
                else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; }
                else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; }
+               else if (!strcmp(ap->a_id, "SSEG"))
+        {
+            if(packflag_and_stacksize>1) ap->a_axp->a_size=packflag_and_stacksize;
+        }
        }
 }
 
@@ -176,6 +207,10 @@ char *argv[];
        register char *p;
        register int c, i;
 
+#ifdef WIN32T
+    Timer(0, "");
+#endif
+
        startp = (struct lfile *) new (sizeof (struct lfile));
 
        pflag = 1;
@@ -244,7 +279,9 @@ char *argv[];
        syminit();
        
        if (dflag){
-           dfp = afile("temp", "cdb", 1);
+           //dfp = afile("temp", "cdb", 1);
+               SaveLinkedFilePath(linkp->f_idp); //Must be the first one... 
+               dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002
            if (dfp == NULL) 
                lkexit(1);
        }
@@ -279,7 +316,10 @@ char *argv[];
                        /*
                         * Link all area addresses.
                         */
-                       lnkarea();
+                       if(!packflag_and_stacksize)
+                lnkarea();
+            else
+                lnkarea2();
                        /*
                         * Process global definitions.
                         */
@@ -306,9 +346,18 @@ char *argv[];
                                map();
 
                        if (sflag) /*JCF: memory usage summary output*/
-                               if(summary(areap))lkexit(1);
-
-                       if (iram_size)
+            {
+                if(!packflag_and_stacksize)
+                {
+                                   if(summary(areap)) lkexit(1);
+                }
+                else
+                {
+                                   if(summary2(areap)) lkexit(1);
+                }
+            }
+
+                       if ((iram_size) && (!packflag_and_stacksize))
                                iramcheck();
 
                        /*
@@ -339,6 +388,13 @@ char *argv[];
                        reloc('E');
                }
        }
+       //JCF:
+       CreateAOMF51();
+
+#ifdef WIN32T
+    Timer(1, "Linker execution time");
+#endif
+
        lkexit(lkerr);
        return 0;
 }
@@ -378,14 +434,15 @@ int i;
        if (rfp != NULL) fclose(rfp);
        if (sfp != NULL) fclose(sfp);
        if (tfp != NULL) fclose(tfp);
-       if (dfp != NULL) {
+       if (dfp != NULL) fclose(dfp);
+       /*if (dfp != NULL)
            FILE *xfp = afile(linkp->f_idp,"cdb",1);
            dfp = freopen("temp.cdb","r",dfp);
            copyfile(xfp,dfp);
            fclose(xfp);
            fclose(dfp);
            unlink("temp.cdb");
-       }
+       }*/
        exit(i);
 }
 
@@ -428,6 +485,29 @@ link_main()
        if ((c=endline()) == 0) { return; }
        switch (c) {
 
+    case 'O': /*For some important sdcc options*/
+        if (pass == 0)
+        {
+            if(strlen(sdccopt)==0)
+            {
+                strcpy(sdccopt, &ip[1]);
+                strcpy(sdccopt_module, curr_module);
+            }
+            else
+            {
+                if(strcmp(sdccopt, &ip[1])!=0)
+                {
+                                   fprintf(stderr,
+                                   "?ASlink-Warning-Conflicting sdcc options:\n"
+                    "   \"%s\" in module \"%s\" and\n"
+                    "   \"%s\" in module \"%s\".\n",
+                    sdccopt, sdccopt_module, &ip[1], curr_module);
+                                   lkerr++;
+                }
+            }
+        }
+               break;
+
        case 'X':
                radix = 16;
                break;
@@ -453,12 +533,14 @@ link_main()
                sdp.s_area = NULL;
                sdp.s_areax = NULL;
                sdp.s_addr = 0;
-               // jwk lastExtendedAddress = -1;
                break;
 
        case 'M':
                if (pass == 0)
+        {
+            strcpy(curr_module, &ip[1]);
                        module();
+        }
                break;
 
        case 'A':
@@ -714,10 +796,15 @@ parse()
                                        break;
 
                                case 'y': /*JCF: memory usage summary output*/
-                               case 'Y':
                                        ++sflag;
                                        break;
 
+                case 'Y':
+                    unget(getnb());
+                    /*The stack segment default size is 16 bytes.  Use -Yxx for xx bytes*/
+                    packflag_and_stacksize=(ip && *ip)?expr(0):16;
+                    break;
+
                                case 'j':
                                case 'J':
                                        jflag = 1;
@@ -785,8 +872,18 @@ parse()
                                        iramsav();
                                        return(0);
 
+                               case 'v':
+                               case 'V':
+                                       xramsav();
+                                       return(0);
+
+                               case 'w':
+                               case 'W':
+                                       codesav();
+                                       return(0);
+
                                case 'z':
-                                case 'Z':
+                case 'Z':
                                        dflag = 1;                                      
                                        return(0);
                                default:
@@ -913,14 +1010,14 @@ setbas()
                        }
                        if (ap == NULL) {
                                fprintf(stderr,
-                               "No definition of area %s\n", id);
+                               "ASlink-Warning-No definition of area %s\n", id);
                                lkerr++;
                        } else {
                                ap->a_addr = v;
                                 ap->a_type = 1;        /* JLH: value set */
                        }
                } else {
-                       fprintf(stderr, "No '=' in base expression");
+                       fprintf(stderr, "ASlink-Warning-No '=' in base expression");
                        lkerr++;
                }
                bsp = bsp->b_base;
@@ -1061,12 +1158,8 @@ setgbl()
  *     the assembler on an open error.
  *
  *     local variables:
- *             int     c               character value
  *             char    fb[]            constructed file specification string
  *             FILE *  fp              filehandle for opened file
- *             char *  p1              pointer to filespec string fn
- *             char *  p2              pointer to filespec string fb
- *             char *  p3              pointer to filetype string ft
  *
  *     global variables:
  *             int     lkerr           error flag
@@ -1084,36 +1177,35 @@ afile(fn, ft, wf)
 char *fn;
 char *ft;
 {
-       register char *p1, *p2, *p3;
-       register int c;
        FILE *fp;
        char fb[PATH_MAX];
        char *omode = (wf ? (wf == 2 ? "a" : "w") : "r");
+       int i;
 
-       p1 = fn;
-       p2 = fb;
-       p3 = ft;
-       while ((c = *p1++) != 0 && c != FSEPX) {
-               if (p2 < &fb[PATH_MAX-4])
-                       *p2++ = c;
-       }
-       *p2++ = FSEPX;
-       if (*p3 == 0) {
-               if (c == FSEPX) {
-                       p3 = p1;
-               } else {
-                       p3 = "rel";
-               }
+       /*Look backward the name path and get rid of the extension, if any*/
+       i=strlen(fn);
+       for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>=0); i--);
+       if( (fn[i]=='.') && strcmp(ft, "lnk") )
+       {
+               strncpy(fb, fn, i);
+               fb[i]=0;
        }
-       while ((c = *p3++) != 0) {
-               if (p2 < &fb[PATH_MAX-1])
-                       *p2++ = c;
+       else
+       {
+               strcpy(fb, fn);
        }
-       *p2++ = 0;      
-       if ((fp = fopen(fb, omode)) == NULL) {
-           if (strcmp(ft,"cdb")) {
-               fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
-               lkerr++;
+
+       /*Add the extension*/
+       strcat(fb, ".");
+       strcat(fb, strlen(ft)?ft:"rel");
+       
+       fp = fopen(fb, omode);
+       if (fp==NULL)
+       {
+           if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/
+               {
+                       fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
+                       lkerr++;
            }
        }
        return (fp);
@@ -1155,6 +1247,29 @@ iramsav()
     iram_size = 128;           /* Default is 128 (0x80) bytes */
 }
 
+/*Similar to iramsav but for xram memory*/
+VOID
+xramsav()
+{
+  unget(getnb());
+  if (ip && *ip)
+    xram_size = expr(0);       /* evaluate size expression */
+  else
+       xram_size = rflag?0x1000000:0x10000;
+}
+
+/*Similar to iramsav but for code memory*/
+VOID
+codesav()
+{
+  unget(getnb());
+  if (ip && *ip)
+    code_size = expr(0);       /* evaluate size expression */
+  else
+       code_size = rflag?0x1000000:0x10000;
+}
+
+
 /*)Function    VOID    iramcheck()
  *
  *     The function iramcheck() is used at the end of linking to check that
@@ -1225,6 +1340,8 @@ char *usetxt[] = {
        "  -u   Update listing file(s) with link data as file(s)[.RST]",
        "Miscellaneous:\n"
        "  -a   [iram-size] Check for internal RAM overflow",
+       "  -v   [xram-size] Check for external RAM overflow",
+       "  -w   [code-size] Check for code overflow",
        "End:",
        "  -e   or null line terminates input",
        0