* as/hc08/asmain.c,
[fw/sdcc] / as / link / mcs51 / lkarea.c
index a227b71f185f07cf5afb81e80f40b59c3966b4ca..1135e83ea30d83defdd97354717229ba3ce18e22 100644 (file)
@@ -493,6 +493,9 @@ Addr_T lnksect2 (struct area *tap, int locIndex);
 char idatamap[256];
 unsigned long codemap[524288];
 unsigned long xdatamap[131072];
+struct area *dseg_ap = NULL;
+Addr_T dram_start = 0;
+Addr_T iram_start = 0;
 
 /*Modified version of the functions for packing variables in internal data memory*/
 VOID lnkarea2 (void)
@@ -503,7 +506,7 @@ VOID lnkarea2 (void)
     char temp[NCPS];
     struct sym *sp;
     int j;
-    struct area *dseg_ap = NULL;
+    struct area *bseg_ap = NULL;
     struct area *abs_ap = NULL;
     struct area *gs0_ap = NULL;
     struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
@@ -534,8 +537,13 @@ VOID lnkarea2 (void)
     /* next accumulate all GSINITx/GSFINAL area sizes
        into GSINIT so they stay together */
     ap = areap;
+    abs_ap = areap;
     while (ap)
     {
+        if (ap->a_flag & A_ABS)
+        {
+            abs_ap = ap; /* Remember the last abs area */
+        }
         if (!strncmp(ap->a_id, "GS", 2))
         {/* GSxxxxx area */
             if (ap->a_size == 0)
@@ -553,6 +561,28 @@ VOID lnkarea2 (void)
                 gs0_ap = ap;
             }
         }
+        /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
+        to compute the byte size of BSEG_BYTES: */
+        else if (!strcmp(ap->a_id, "BSEG"))
+        {
+            bseg_ap = ap->a_ap;            //BSEG_BYTES
+            for (axp=ap->a_axp; axp; axp=axp->a_axp)
+                ap->a_size += axp->a_size;
+            bseg_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
+            ap->a_ap = bseg_ap->a_ap;      //removed BSEG_BYTES from list
+            bseg_ap->a_ap = abs_ap->a_ap;
+            abs_ap->a_ap = bseg_ap;        //inserted BSEG_BYTES after abs
+            bseg_ap = ap;                  //BSEG
+        }
+        else if (!strcmp(ap->a_id, "DSEG"))
+        {
+            dseg_ap = ap; /*Need it later*/
+            dram_start = ap->a_addr;
+        }
+        else if (!strcmp(ap->a_id, "ISEG"))
+        {
+            iram_start = ap->a_addr;
+        }
         ap = ap->a_ap;
     }
     if (gs0_ap)
@@ -582,6 +612,10 @@ VOID lnkarea2 (void)
             rloc[locIndex] = lnksect2(ap, locIndex);
         }
 
+        if (!strcmp(ap->a_id, "BSEG_BYTES"))
+        {
+            bseg_ap->a_addr = (ap->a_axp->a_addr - 0x20) * 8; /*Bytes to bits*/
+        }
         /*
          * Create symbols called:
          *  s_<areaname>    the start address of the area
@@ -595,7 +629,7 @@ VOID lnkarea2 (void)
 
             *temp = 's';
             sp = lkpsym(temp, 1);
-            sp->s_addr = ap->a_addr ;
+            sp->s_addr = ap->a_addr;
             sp->s_type |= S_DEF;
             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
 
@@ -607,16 +641,6 @@ VOID lnkarea2 (void)
             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
         }
 
-        /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
-        to compute the byte size of BSEG_BYTES: */
-        if (!strcmp(ap->a_id, "BSEG"))
-        {
-            ap->a_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
-        }
-        else if (!strcmp(ap->a_id, "DSEG"))
-        {
-            dseg_ap=ap; /*Need it later to set its correct size*/
-        }
         ap = ap->a_ap;
     }
 
@@ -714,7 +738,7 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
 {
     register Addr_T size, addr;
     register struct areax *taxp;
-    int j, k, ramlimit;
+    int j, k, ramlimit, ramstart;
     char fchar=' ', dchar='a';
     char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
                   " in internal RAM for area %s.\n";
@@ -724,17 +748,21 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
     /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
     if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
     {
-        if((iram_size<=0)||(iram_size>0x100))
-            ramlimit=0x100;
+        ramstart = iram_start;
+
+        if ((iram_size <= 0) || (ramstart + iram_size > 0x100))
+            ramlimit = 0x100;
         else
-            ramlimit=iram_size;
+            ramlimit = ramstart + iram_size;
     }
     else
     {
-        if((iram_size<=0)||(iram_size>0x80))
-            ramlimit=0x80;
+        ramstart = dram_start;
+
+        if ((iram_size <= 0) || (ramstart + iram_size > 0x80))
+            ramlimit = 0x80;
         else
-            ramlimit=iram_size;
+            ramlimit = ramstart + iram_size;
     }
 
     size = 0;
@@ -790,28 +818,35 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
     {
         while (taxp)
         {
+            if(taxp->a_size == 0)
+            {
+                taxp = taxp->a_axp;
+                continue;
+            }
+
             if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
             {
                 addr=(fchar-'0')*8;
                 taxp->a_addr=addr;
                 size=taxp->a_size;
-                for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
+                for(j=addr; (j<(int)(addr+size)) && (j<ramlimit); j++)
                     idatamap[j]=fchar;
             }
             else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
             {
                 /*Find the size of the space currently used for this areax overlay*/
-                for(j=0, size=0; j<ramlimit; j++)
+                for(j=ramstart, size=0; j<ramlimit; j++)
                     if(idatamap[j]==fchar) size++;
 
                 if( (fchar=='S') && (stacksize==0) )
                 {
                    /*Search for the largest space available and use it for stack*/
-                    for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
+                    for(j=ramstart, k=0, taxp->a_size=0; j<ramlimit; j++)
                     {
                         if(idatamap[j]==' ')
                         {
-                            if((++k)>(int)taxp->a_size) taxp->a_size=k;
+                            if((++k)>(int)taxp->a_size)
+                                taxp->a_size=k;
                         }
                         else
                         {
@@ -827,37 +862,26 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
                 {
                     size=(int)taxp->a_size;
 
-                    for(j=0; j<ramlimit; j++)
+                    for(j=ramstart; j<ramlimit; j++)
                         if(idatamap[j]==fchar) idatamap[j]=' ';
 
                     /*Search for a space large enough in data memory for this overlay areax*/
-                    for(j=0, k=0; j<ramlimit; j++)
+                    for(j=ramstart, k=0; j<ramlimit; j++)
                     {
                         if(idatamap[j]==' ')
                             k++;
                         else
                             k=0;
-                        if(k==(int)taxp->a_size) break;
-                    }
-
                     if(k==(int)taxp->a_size)
-                    {
-                        taxp->a_addr = j-k+1;
-                        if(addr<(unsigned int)ramlimit)
-                        {
-                            for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
-                            if(j>=0) addr=j+1;
-                        }
+                            break;
                     }
 
                     /*Mark the memory used for overlay*/
                     if(k==(int)taxp->a_size)
                     {
-                        for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
+                        addr = j-k+1;
+                        for(j=addr; (j<(int)(addr+size)); j++)
                             idatamap[j]=fchar;
-
-                        /*Set the new size of the data memory area*/
-                        size=ramlimit-addr;
                     }
                     else /*Couldn't find a chunk big enough: report the problem.*/
                     {
@@ -866,23 +890,12 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
                         lkerr++;
                     }
                 }
-
-                for(j=0; j<ramlimit; j++)
-                {
-                    if (idatamap[j]==fchar)
-                    {
-                        addr=j;
-                        tap->a_addr=addr;
-                        taxp->a_addr=addr;
-                        break;
-                    }
-                }
             }
             else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
             {
                 /*Find the size of the space currently used for this areax overlay*/
-                for(j=0x20, size=0; j<0x30; j++)
-                    if(idatamap[j]==fchar) size++;
+//              for(j=0x20, size=0; j<0x30; j++)
+//                  if(idatamap[j]==fchar) size++;
 
                 /*If more space required, release the previously allocated areax in
                 internal RAM and search for a bigger one*/
@@ -900,27 +913,16 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
                             k++;
                         else
                             k=0;
-                        if(k==(int)taxp->a_size) break;
-                    }
-
-                    if(k==(int)taxp->a_size)
-                    {
-                        taxp->a_addr = j-k+1;
-                        if(addr<(unsigned int)0x30)
-                        {
-                            for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--);
-                            if(j>=0x20) addr=j+1;
-                        }
+                        if(k==(int)taxp->a_size)
+                            break;
                     }
 
                     /*Mark the memory used for overlay*/
-                    if(k==(int)taxp->a_size)
+                    if(k==(int)size)
                     {
-                        for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
+                        addr = j-k+1;
+                        for(j=addr; (j<(int)(addr+size)); j++)
                             idatamap[j]=fchar;
-
-                        /*Set the new size of the data memory area*/
-                        size=ramlimit-addr;
                     }
                     else /*Couldn't find a chunk big enough: report the problem.*/
                     {
@@ -929,17 +931,6 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
                         lkerr++;
                     }
                 }
-
-                for(j=0x20; j<0x30; j++)
-                {
-                    if (idatamap[j]==fchar)
-                    {
-                        addr=j;
-                        tap->a_addr=addr;
-                        taxp->a_addr=addr;
-                        break;
-                    }
-                }
             }
             else /*Overlay areas not in internal ram*/
             {
@@ -948,6 +939,13 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
             }
             taxp = taxp->a_axp;
         }
+        /*Now set all overlayed areax to the same start address*/
+        taxp = tap->a_axp;
+        while (taxp)
+        {
+            taxp->a_addr = addr;
+            taxp = taxp->a_axp;
+        }
     }
     else if (tap->a_flag & A_ABS) /* Absolute sections */
     {
@@ -955,14 +953,19 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
         {
             if (locIndex == 0)
             {
-                for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
-                    idatamap[j] = 'A';
+                for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<256); j++)
+                {
+                    if (idatamap[j] == ' ')
+                        idatamap[j] = 'A';
+                    else
+                        fprintf(stderr, "memory overlap at 0x%X for %s\n", j, tap->a_id);
+                }
             }
-            if (locIndex == 1)
+            else if (locIndex == 1)
             {
                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
             }
-            if (locIndex == 2)
+            else if (locIndex == 2)
             {
                 allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
             }
@@ -988,24 +991,21 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
                 if(taxp->a_size)
                 {
                     /*Search for a space large enough in internal RAM for this areax*/
-                    for(j=0, k=0; j<ramlimit; j++)
+                    for(j=ramstart, k=0; j<ramlimit; j++)
                     {
                         if(idatamap[j]==' ')
                             k++;
                         else
                             k=0;
-                        if(k==(int)taxp->a_size) break;
+                        if(k==(int)taxp->a_size)
+                            break;
                     }
 
                     if(k==(int)taxp->a_size)
                     {
                         taxp->a_addr = j-k+1;
-                        if(addr<(unsigned int)ramlimit)
-                        {
-                            for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
-                            if(j>=0) addr=j+1;
-                            size=ramlimit-addr;
-                        }
+
+                        size += taxp->a_size;
 
                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
                             idatamap[j]=(fchar=='D')?dchar:fchar;
@@ -1028,12 +1028,30 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
             {
                 if(taxp->a_size!=0)
                 {
-                    for(j=addr; j<((int)(addr+taxp->a_size)); j++)
-                        idatamap[j]=fchar;
-                }
+                    /*Search for a space large enough in data memory for this areax*/
+                    for(j=0x20, k=0; j<0x30; j++)
+                    {
+                        if(idatamap[j]==' ')
+                            k++;
+                        else
+                            k=0;
+                        if(k==(int)taxp->a_size) break;
+                    }
 
-                taxp->a_addr = addr;
-                addr += taxp->a_size;
+                    /*Mark the memory used*/
+                    if(k==(int)taxp->a_size)
+                    {
+                        taxp->a_addr = j-k+1;
+                        for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
+                            idatamap[j]=fchar;
+                    }
+                    else /*Couldn't find a chunk big enough: report the problem.*/
+                    {
+                        tap->a_unaloc=taxp->a_size;
+                        fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+                        lkerr++;
+                    }
+                }
                 size += taxp->a_size;
                 taxp = taxp->a_axp;
             }
@@ -1062,6 +1080,7 @@ Addr_T lnksect2 (struct area *tap, int locIndex)
         }
     }
     tap->a_size = size;
+    tap->a_addr = tap->a_axp->a_addr;
 
     if ((tap->a_flag&A_PAG) && (size > 256))
     {