* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[fw/sdcc] / as / mcs51 / lkarea.c
index 07b29fc1ddb410d61b557f849885eefe31938f97..3913ae83af8e168f7a0bb542a27d2080cf34e5d8 100644 (file)
@@ -198,6 +198,7 @@ lkparea(char *id)
 
     ap = areap;
     axp = (struct areax *) new (sizeof(struct areax));
+    axp->a_addr = -1; /* default: no address yet */
     while (ap) {
         if (symeq(id, ap->a_id)) {
             taxp = ap->a_axp;
@@ -381,7 +382,7 @@ lnkarea()
         /*JCF: 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/8)+((ap->a_size+7)/8); /*Bits to bytes*/
+            ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/
         }
         else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
         else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
@@ -484,6 +485,7 @@ lnksect(register struct area *tap)
 
 void lnksect2 (struct area *tap, int rloc);
 char idatamap[256];
+long codemap[524288];
 
 /*Modified version of the functions for packing variables in internal data memory*/
 VOID lnkarea2 (void)
@@ -493,10 +495,28 @@ VOID lnkarea2 (void)
     char temp[NCPS];
     struct sym *sp;
     int j;
-    struct area *dseg_ap=NULL;
+    struct area *dseg_ap = NULL;
+    struct area *abs_ap = NULL;
     struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
 
     for(j=0; j<256; j++) idatamap[j]=' ';
+    memset(codemap, 0, sizeof(codemap));
+
+    /* first sort all absolute areas to the front */
+    ap = areap;
+    /* no need to check first area, it's in front anyway */
+    while (ap && ap->a_ap)
+    {
+        if (ap->a_ap->a_flag & A_ABS)
+        {/* next area is absolute, move it to front,
+            reversed sequence is no problem for absolutes */
+            abs_ap = ap->a_ap;
+            ap->a_ap = abs_ap->a_ap;
+            abs_ap->a_ap = areap;
+            areap = abs_ap;
+        }
+        ap = ap->a_ap;
+    }
 
     ap = areap;
     while (ap)
@@ -552,7 +572,7 @@ VOID lnkarea2 (void)
         to compute the byte size of BSEG_BYTES: */
         if (!strcmp(ap->a_id, "BSEG"))
         {
-            ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
+            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"))
         {
@@ -644,6 +664,8 @@ void lnksect2 (struct area *tap, int rloc)
             fchar='3';
         else if(!strcmp(tap->a_id, "BSEG_BYTES"))
             fchar='B';
+        else if(!strcmp(tap->a_id, "BIT_BANK"))
+            fchar='T';
         else
             fchar=' ';/*???*/
     }
@@ -731,7 +753,7 @@ void lnksect2 (struct area *tap, int rloc)
                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
                         lkerr++;
                     }
-               }
+                }
 
                 for(j=0; j<ramlimit; j++)
                 {
@@ -744,6 +766,69 @@ void lnksect2 (struct area *tap, int rloc)
                     }
                 }
             }
+            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++;
+
+                /*If more space required, release the previously allocated areax in
+                internal RAM and search for a bigger one*/
+                if((int)taxp->a_size>size)
+                {
+                    size=(int)taxp->a_size;
+
+                    for(j=0x20; j<0x30; j++)
+                        if(idatamap[j]==fchar) idatamap[j]=' ';
+
+                    /*Search for a space large enough in data memory for this overlay areax*/
+                    for(j=0x20, k=0; j<0x30; 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)0x30)
+                        {
+                            for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--);
+                            if(j>=0x20) addr=j+1;
+                        }
+                    }
+
+                    /*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<0x30); 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.*/
+                    {
+                        tap->a_unaloc=taxp->a_size;
+                        fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+                        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*/
             {
                 taxp->a_addr = addr;
@@ -801,7 +886,7 @@ void lnksect2 (struct area *tap, int rloc)
             {
                 if(taxp->a_size!=0)
                 {
-                    for(j=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_addr+taxp->a_size)); j++)
+                    for(j=addr; j<((int)(addr+taxp->a_size)); j++)
                         idatamap[j]=fchar;
                 }
 
@@ -816,6 +901,32 @@ void lnksect2 (struct area *tap, int rloc)
                 {
                     taxp->a_size = 256-(addr & 0xFF);
                 }
+                //should find next unused address now!!!
+                //but let's first just warn for overlaps
+                if (rloc == 1)
+                {
+                    int a = addr;
+                    int i = addr >> 5;
+                    int j = (addr + taxp->a_size) >> 5;
+                    long mask = -(1 << (addr & 0x1F));
+
+                    while (i < j)
+                    {
+                        if (codemap[i] & mask)
+                        {
+                            fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id);
+                        }
+                        codemap[i++] |= mask;
+                        mask = 0xFFFFFFFF;
+                        a += 32;
+                    }
+                    mask &= (1 << ((addr + taxp->a_size) & 0x1F)) - 1;
+                    if (codemap[i] & mask)
+                    {
+                        fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id);
+                    }
+                    codemap[i] |= mask;
+                }
                 taxp->a_addr = addr;
                 addr += taxp->a_size;
                 size += taxp->a_size;