+2004-01-04 Jesus Calvino-Fraga <jesusc@ece.ubc.ca>
+
+ * as/mcs51/aslink.h, as/mcs51/lkarea.c, as/mcs51/lkdata.c,
+ as/mcs51/lkmain.c, as/mcs51/lkmem.c: 8051 linker can now pack
+ variables in unused register banks. Also the SSEG is placed
+ wherever there is enough space for it, and IDATA can be anywhere
+ in internal RAM. For now compile using -Wl-Y[stack_size].
+ The mem file is different for this option as well, since it
+ makes no sense of talking about DSEG lenght.
+
2004-01-02 Vangelis Rokas <vrokas@otenet.gr>
* src/SDCClrange.c: fixed bug 869095 that caused segfault
struct areax *a_axp; /* Area extension link */
Addr_T a_addr; /* Beginning address of area */
Addr_T a_size; /* Total size of the area */
+ Addr_T a_unaloc; /* Total number of unalocated bytes, for error reporting */
char a_type; /* Area subtype */
char a_flag; /* Flag byte */
char a_id[NCPS]; /* Name */
*/
extern int sflag; /* JCF: Memory usage output flag
*/
+extern int packflag_and_stacksize; /* Pack data memory flag
+ */
extern int jflag; /* NoICE output flag
*/
extern int xflag; /* Map file radix type flag
/* lkarea.c */
extern VOID lkparea();
extern VOID lnkarea();
+extern VOID lnkarea2();
extern VOID lnksect();
extern VOID newarea();
/* JCF: lkmem.c */
extern int summary(struct area * xp);
+extern int summary2(struct area * xp);
/* JCF: lkaomf51.c */
extern void SaveLinkedFilePath(char * filepath);
lkerr++;
}
}
+
+void lnksect2 (struct area *tap, int rloc);
+char idatamap[256];
+
+/*Modified version of the functions for packing variables in internal data memory*/
+VOID lnkarea2 (void)
+{
+ Addr_T rloc[4]={0, 0, 0, 0};
+ int locIndex;
+ char temp[NCPS];
+ struct sym *sp;
+ int j;
+ struct area *dseg_ap=NULL;
+ struct sym *sp_dseg_s, *sp_dseg_l;
+
+ for(j=0; j<256; j++) idatamap[j]=' ';
+
+ ap = areap;
+ while (ap)
+ {
+ /* Determine memory space */
+ if (ap->a_flag & A_CODE) locIndex = 1;
+ else if (ap->a_flag & A_XDATA) locIndex = 2;
+ else if (ap->a_flag & A_BIT) locIndex = 3;
+ else locIndex = 0;
+
+ if (ap->a_flag&A_ABS) /* Absolute sections */
+ {
+ lnksect2(ap, locIndex);
+ }
+ else /* Relocatable sections */
+ {
+ if (ap->a_type == 0)
+ {
+ ap->a_addr=rloc[locIndex];
+ ap->a_type=1;
+ }
+
+ lnksect2(ap, locIndex);
+ rloc[locIndex] = ap->a_addr + ap->a_size;
+ }
+
+ /*
+ * Create symbols called:
+ * s_<areaname> the start address of the area
+ * l_<areaname> the length of the area
+ */
+
+ if (! symeq(ap->a_id, _abs_))
+ {
+ strncpy(temp+2,ap->a_id,NCPS-2);
+ *(temp+1) = '_';
+
+ *temp = 's';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_addr ;
+ sp->s_type |= S_DEF;
+ if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
+
+ *temp = 'l';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_size;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+ 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/8)+((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;
+ }
+
+ /*Compute the size of DSEG*/
+ dseg_ap->a_addr=0;
+ dseg_ap->a_size=0;
+ for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
+ sp_dseg_s->s_addr=0;
+ sp_dseg_l->s_addr=dseg_ap->a_size;
+
+#if 0
+ /*Print the memory map*/
+ fprintf(stderr, "Internal RAM layout:\n"
+ " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
+ for(j=0; j<256; j++)
+ {
+ if(j%16==0) fprintf(stderr, "\n0x%02x:|", j);
+ fprintf(stderr, "%c|", idatamap[j]);
+ }
+ fprintf(stderr, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
+#endif
+}
+
+void lnksect2 (struct area *tap, int rloc)
+{
+ register Addr_T size, addr;
+ register struct areax *taxp;
+ int j, k, ramlimit;
+ char fchar, dchar='a';
+ char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
+ " in internal RAM for area %s.\n";
+
+ tap->a_unaloc=0;
+
+ /*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;
+ else
+ ramlimit=iram_size;
+ }
+ else
+ {
+ ramlimit=0x80;
+ }
+
+ size = 0;
+ addr = tap->a_addr;
+ if ((tap->a_flag&A_PAG) && (addr & 0xFF))
+ {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+ taxp = tap->a_axp;
+
+ /*Use a letter to identify each area in the internal RAM layout map*/
+ if(rloc==0)
+ {
+ /**/ if(!strcmp(tap->a_id, "DSEG"))
+ fchar='D'; /*It will be converted to letters 'a' to 'z' latter for each areax*/
+ else if(!strcmp(tap->a_id, "ISEG"))
+ fchar='I';
+ else if(!strcmp(tap->a_id, "SSEG"))
+ fchar='S';
+ else if(!strcmp(tap->a_id, "OSEG"))
+ fchar='Q';
+ else if(!strcmp(tap->a_id, "REG_BANK_0"))
+ fchar='0';
+ else if(!strcmp(tap->a_id, "REG_BANK_1"))
+ fchar='1';
+ else if(!strcmp(tap->a_id, "REG_BANK_2"))
+ fchar='2';
+ else if(!strcmp(tap->a_id, "REG_BANK_3"))
+ fchar='3';
+ else if(!strcmp(tap->a_id, "BSEG_BYTES"))
+ fchar='B';
+ else
+ fchar=' ';/*???*/
+ }
+ else
+ {
+ fchar=' ';
+ }
+
+ if (tap->a_flag&A_OVR) /* Overlayed sections */
+ {
+ while (taxp)
+ {
+ 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++)
+ 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++)
+ 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=0; 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++)
+ {
+ 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;
+ }
+ }
+
+ /*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++)
+ 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=0; j<ramlimit; 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;
+ if (taxp->a_size > size) size = taxp->a_size;
+ }
+ taxp = taxp->a_axp;
+ }
+ }
+ else /* Concatenated sections */
+ {
+ while (taxp)
+ {
+ if( (fchar=='D') || (fchar=='I') )
+ {
+ if(taxp->a_size)
+ {
+ /*Search for a space large enough in internal RAM for this areax*/
+ for(j=0, 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;
+ size=ramlimit-addr;
+ }
+
+ for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
+ idatamap[j]=(fchar=='D')?dchar:fchar;
+ if((taxp->a_size>0)&&(fchar=='D'))dchar++;
+ if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
+ }
+ else /*We are in trouble, there is not enough memory for an areax chunk*/
+ {
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ tap->a_unaloc+=taxp->a_size;
+ fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+ lkerr++;
+ }
+ }
+ taxp = taxp->a_axp;
+ }
+ else if(fchar=='B')
+ {
+ if(taxp->a_size!=0)
+ {
+ for(j=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_addr+taxp->a_size)); j++)
+ idatamap[j]=fchar;
+ }
+
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ else /*For concatenated BIT, CODE, and XRAM areax's*/
+ {
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ }
+ }
+ tap->a_size = size;
+
+ if ((tap->a_flag&A_PAG) && (size > 256))
+ {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
+ lkerr++;
+ }
+}
*/
int sflag; /* JCF: Memory usage output flag
*/
+int packflag_and_stacksize=0; /* JCF: Pack internal memory flag
+ */
int aflag; /* Overlapping area warning flag
*/
int jflag; /* NoICE output flag
{
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",
"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;
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;
+ }
}
}
/*
* Link all area addresses.
*/
- lnkarea();
+ if(!packflag_and_stacksize)
+ lnkarea();
+ else
+ lnkarea2();
/*
* Process global definitions.
*/
map();
if (sflag) /*JCF: memory usage summary output*/
- if(summary(areap))lkexit(1);
+ {
+ if(!packflag_and_stacksize)
+ {
+ if(summary(areap)) lkexit(1);
+ }
+ else
+ {
+ if(summary2(areap)) lkexit(1);
+ }
+ }
- if (iram_size)
+ if ((iram_size) && (!packflag_and_stacksize))
iramcheck();
/*
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;
return(0);
case 'z':
- case 'Z':
+ case 'Z':
dflag = 1;
return(0);
default:
fclose(of);
return toreturn;
}
+
+extern char idatamap[]; //0:not used, 1:used
+
+
+int summary2(struct area * areap)
+{
+ #define EQ(A,B) !as_strcmpi((A),(B))
+ #define MIN_STACK 16
+
+ char buff[128];
+ int j, toreturn=0;
+ long int Stack_Start=0;
+
+ struct area * xp;
+ FILE * of;
+
+ /*Artifacts used for printing*/
+ char start[15], end[15], size[15], max[15];
+ char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
+ char line[]="---------------------";
+
+ typedef struct
+ {
+ unsigned long Start;
+ unsigned long Size;
+ unsigned long Max;
+ char Name[NCPS];
+ unsigned long flag;
+ } _Mem;
+
+ _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(rflag) /*For the DS390*/
+ {
+ XRam.Max=0x1000000; /*24 bits*/
+ XRam.Start=0xffffff;
+ Rom.Max=0x1000000;
+ Rom.Start=0xffffff;
+ }
+
+ /* 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, "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;
+ }
+
+ xp=xp->a_ap;
+ }
+
+ /*Report the Ram totals*/
+ fprintf(of, "Internal RAM layout:\n");
+ fprintf(of, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
+ for(j=0; j<256; j++)
+ {
+ if(j%16==0) fprintf(of, "\n0x%02x:|", j);
+ fprintf(of, "%c|", idatamap[j]);
+ }
+ fprintf(of, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
+
+ for(j=0; j<256; j++)
+ {
+ if(idatamap[j]=='S')
+ {
+ Stack_Start=j;
+ break;
+ }
+ }
+
+ xp=areap;
+ while (xp)
+ {
+ if(xp->a_unaloc>0)
+ {
+ fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
+ " in internal RAM for area %s.",
+ xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
+ toreturn=1;
+ }
+ xp=xp->a_ap;
+ }
+
+ /*Report the position of the begining of the stack*/
+ if(Stack_Start!=256)
+ fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
+ rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1);
+ else
+ fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
+
+ fprintf(of, "\n\nOther memory:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+ fprintf(of, format, line, line, line, line, line);
+
+ /*Report XRam totals:*/
+ sprintf(start, "0x%04lx", XRam.Start);
+ if(XRam.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04lx", XRam.Size+XRam.Start-1);
+ sprintf(size, "%5lu", XRam.Size);
+ sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
+ fprintf(of, format, XRam.Name, start, end, size, max);
+
+ /*Report Rom/Flash totals:*/
+ sprintf(start, "0x%04lx", Rom.Start);
+ if(Rom.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04lx", Rom.Size+Rom.Start-1);
+ sprintf(size, "%5lu", Rom.Size);
+ sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
+ fprintf(of, format, Rom.Name, start, end, size, max);
+
+ /*Report any excess:*/
+ if( ((XRam.Start+XRam.Size)>XRam.Max) ||
+ (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
+ {
+ sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ if( ((Rom.Start+Rom.Size)>Rom.Max) ||
+ (((int)Rom.Size>code_size)&&(code_size>=0)) )
+ {
+ sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+
+ fclose(of);
+ return toreturn;
+}