4 * (C) Copyright 1989-1995
12 * - lstarea: show s_id as string rather than array [NCPS]
13 * - lstarea: show a_id as string rather than array [NCPS]
14 * 31-Oct-97 JLH: add NoICE output file genration in lstarea
15 * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
25 * The module lklist.c contains the functions which
26 * output the linker .map file and produce a relocated
29 * lklist.c contains the following functions:
38 * lklist.c contains no local variables.
41 /*)Function VOID slew(fp)
43 * FILE * fp output file handle
45 * The function slew() increments the page line counter.
46 * If the number of lines exceeds the maximum number of
47 * lines per page then a page skip and a page header are
54 * int lop current line number on page
55 * int xflag Map file radix type flag
58 * int fprintf() c_library
59 * VOID newpag() lklist.c
62 * The page line and the page count may be updated.
74 fprintf(fp, "Hexadecimal\n\n");
77 fprintf(fp, "Octal\n\n");
80 fprintf(fp, "Decimal\n\n");
82 fprintf(fp, "Area Addr Size");
83 fprintf(fp, " Decimal Bytes (Attributes)\n");
85 fprintf(fp, " Value--Global");
91 /*)Function VOID newpag()
93 * The function newpag() outputs a page skip, writes the
94 * first page header line, sets the line count to 1, and
95 * increments the page counter.
101 * int lop current line number on page
102 * int page current page number
105 * int fprintf() c_library
108 * The page and line counters are updated.
115 fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
119 /* Used for qsort call in lstsym */
120 static int _cmpSymByAddr(const void *p1, const void *p2)
122 struct sym **s1 = (struct sym **)(p1);
123 struct sym **s2 = (struct sym **)(p2);
124 int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
125 ((*s2)->s_addr + (*s2)->s_axp->a_addr);
127 /* Sort first by address, then by name. */
132 return strcmp((*s1)->s_id,(*s2)->s_id);
139 /*)Function VOID lstarea(xp)
141 * area * xp pointer to an area structure
143 * The function lstarea() creates the linker map output for
144 * the area specified by pointer xp. The generated output
145 * area header includes the area name, starting address,
146 * size of area, number of words (in decimal), and the
147 * area attributes. The symbols defined in this area are
148 * sorted by ascending address and output one per line
149 * in the selected radix.
152 * areax * oxp pointer to an area extension structure
153 * int c character value
155 * int j bubble sort update status
156 * char * ptr pointer to an id string
157 * int nmsym number of symbols in area
158 * Addr_T a0 temporary
159 * Addr_T ai temporary
160 * Addr_T aj temporary
161 * sym * sp pointer to a symbol structure
162 * sym ** p pointer to an array of
163 * pointers to symbol structures
166 * FILE *mfp Map output file handle
167 * sym *symhash[NHASH] array of pointers to NHASH
168 * linked symbol lists
169 * int xflag Map file radix type flag
172 * int fprintf() c_library
173 * VOID free() c_library
174 * char * malloc() c_library
175 * char putc() c_library
176 * VOID slew() lklist.c
179 * Map output generated.
186 register struct areax *oxp;
199 fprintf(mfp, "Hexadecimal\n\n");
202 fprintf(mfp, "Octal\n\n");
205 fprintf(mfp, "Decimal\n\n");
207 fprintf(mfp, "Area ");
208 fprintf(mfp, "Addr Size Decimal %s (Attributes)\n",
209 (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/
210 fprintf(mfp, "-------------------------------- ");
211 fprintf(mfp, "---- ---- ------- ----- ------------\n");
216 fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */
220 fprintf(mfp, " %04X %04X", ai, aj);
223 fprintf(mfp, " %06o %06o", ai, aj);
226 fprintf(mfp, " %05u %05u", ai, aj);
228 fprintf(mfp, " = %6u. %s ", aj,
229 (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/
230 if (xp->a_flag & A_ABS) {
231 fprintf(mfp, "(ABS");
233 fprintf(mfp, "(REL");
235 if (xp->a_flag & A_OVR) {
236 fprintf(mfp, ",OVR");
238 fprintf(mfp, ",CON");
240 if (xp->a_flag & A_PAG) {
241 fprintf(mfp, ",PAG");
245 if (xp->a_flag & A_CODE) {
246 fprintf(mfp, ",CODE");
249 if (xp->a_flag & A_XDATA) {
250 fprintf(mfp, ",XDATA");
253 if (xp->a_flag & A_BIT) {
254 fprintf(mfp, ",BIT");
258 if (xp->a_flag & A_PAG) {
261 if (ai || aj) { fprintf(mfp, " "); }
262 if (ai) { fprintf(mfp, " Boundary"); }
263 if (ai & aj) { fprintf(mfp, " /"); }
264 if (aj) { fprintf(mfp, " Length"); }
265 if (ai || aj) { fprintf(mfp, " Error"); }
269 * Find number of symbols in area
274 for (i=0; i<NHASH; i++) {
277 if (oxp == sp->s_axp)
290 * Allocate space for an array of pointers to symbols
293 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
295 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
301 for (i=0; i<NHASH; i++) {
304 if (oxp == sp->s_axp) {
315 * Bubble Sort of Addresses in Symbol Table Array
321 a0 = sp->s_addr + sp->s_axp->a_addr;
322 for (i=1; i<nmsym; ++i) {
324 ai = sp->s_addr + sp->s_axp->a_addr;
334 qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
338 * Symbol Table Output
342 fprintf(mfp, "\n\n");
343 fprintf(mfp, " Value Global\n");
344 fprintf(mfp, " -------- --------------------------------");
348 fprintf(mfp, " %02X:", memPage);
353 aj = sp->s_addr + sp->s_axp->a_addr;
355 fprintf(mfp, "%04X ", aj);
358 fprintf(mfp, "%06o ", aj);
361 fprintf(mfp, "%05u ", aj);
364 fprintf(mfp, "%s", ptr );
366 /* if cdb flag set the output cdb Information
367 and the symbol has a '$' sign in it then */
370 fprintf(dfp,"L:%s:%X\n",ptr,aj);
371 /* NoICE output of symbol */
372 if (jflag) DefineNoICE( ptr, aj, memPage );
383 /*)Function VOID lstarea(xp)
385 * area * xp pointer to an area structure
387 * The function lstarea() creates the linker map output for
388 * the area specified by pointer xp. The generated output
389 * area header includes the area name, starting address,
390 * size of area, number of words (in decimal), and the
391 * area attributes. The symbols defined in this area are
392 * sorted by ascending address and output four per line
393 * in the selected radix.
396 * areax * oxp pointer to an area extension structure
397 * int c character value
399 * int j bubble sort update status
400 * char * ptr pointer to an id string
401 * int nmsym number of symbols in area
402 * Addr_T a0 temporary
403 * Addr_T ai temporary
404 * Addr_T aj temporary
405 * sym * sp pointer to a symbol structure
406 * sym ** p pointer to an array of
407 * pointers to symbol structures
410 * FILE *mfp Map output file handle
411 * sym *symhash[NHASH] array of pointers to NHASH
412 * linked symbol lists
413 * int xflag Map file radix type flag
416 * int fprintf() c_library
417 * VOID free() c_library
418 * char * malloc() c_library
419 * char putc() c_library
420 * VOID slew() lklist.c
423 * Map output generated.
430 register struct areax *oxp;
445 while (ptr < &xp->a_id[NCPS]) {
446 if ((c = *ptr++) != 0) {
455 fprintf(mfp, " %04X %04X", ai, aj);
458 fprintf(mfp, " %06o %06o", ai, aj);
461 fprintf(mfp, " %05u %05u", ai, aj);
463 fprintf(mfp, " = %6u. bytes ", aj);
464 if (xp->a_flag & A_ABS) {
465 fprintf(mfp, "(ABS");
467 fprintf(mfp, "(REL");
469 if (xp->a_flag & A_OVR) {
470 fprintf(mfp, ",OVR");
472 fprintf(mfp, ",CON");
474 if (xp->a_flag & A_PAG) {
475 fprintf(mfp, ",PAG");
479 if (xp->a_flag & A_CODE) {
480 fprintf(mfp, ",CODE");
483 if (xp->a_flag & A_XDATA) {
484 fprintf(mfp, ",XDATA");
487 if (xp->a_flag & A_BIT) {
488 fprintf(mfp, ",BIT");
492 if (xp->a_flag & A_PAG) {
495 if (ai || aj) { fprintf(mfp, " "); }
496 if (ai) { fprintf(mfp, " Boundary"); }
497 if (ai & aj) { fprintf(mfp, " /"); }
498 if (aj) { fprintf(mfp, " Length"); }
499 if (ai || aj) { fprintf(mfp, " Error"); }
503 * Find number of symbols in area
508 for (i=0; i<NHASH; i++) {
511 if (oxp == sp->s_axp)
525 * Allocate space for an array of pointers to symbols
528 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
530 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
537 for (i=0; i<NHASH; i++) {
540 if (oxp == sp->s_axp) {
551 * Bubble Sort of Addresses in Symbol Table Array
557 a0 = sp->s_addr + sp->s_axp->a_addr;
558 for (i=1; i<nmsym; ++i) {
560 ai = sp->s_addr + sp->s_axp->a_addr;
570 qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
574 * Symbol Table Output
582 aj = sp->s_addr + sp->s_axp->a_addr;
584 fprintf(mfp, " %04X ", aj);
587 fprintf(mfp, "%06o ", aj);
590 fprintf(mfp, " %05u ", aj);
593 fprintf(mfp, "%s", ptr );
595 /* NoICE output of symbol */
596 if (jflag) DefineNoICE( ptr, aj, memPage );
604 /*)Function VOID lkulist(i)
606 * int i i # 0 process LST to RST file
607 * i = 0 copy remainder of LST file
608 * to RST file and close files
610 * The function lkulist() creates a relocated listing (.rst)
611 * output file from the ASxxxx assembler listing (.lst)
612 * files. The .lst file's program address and code bytes
613 * are changed to reflect the changes made by ASlink as
614 * the .rel files are combined into a single relocated
618 * Addr_T pc current program counter address
621 * int hilo byte order
622 * int gline get a line from the LST file
623 * to translate for the RST file
624 * char rb[] read listing file text line
625 * FILE *rfp The file handle to the current
627 * int rtcnt count of data words
628 * int rtflg[] output the data flag
629 * Addr_T rtval[] relocated data
630 * FILE *tfp The file handle to the current
631 * LST file being scanned
634 * int fclose() c_library
635 * int fgets() c_library
636 * int fprintf() c_library
637 * VOID lkalist() lklist.c
638 * VOID lkglist() lklist.c
641 * A .rst file is created for each available .lst
642 * file associated with a .rel file.
652 * Exit if listing file is not open
658 * Normal processing of LST to RST
662 * Evaluate current code address
665 pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
667 pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
671 * Line with only address
677 * Line with address and code
680 for (i=2; i < rtcnt; i++) {
682 lkglist(pc++, rtval[i] & 0xFF);
688 * Copy remainder of LST to RST
692 fprintf(rfp, "%s", rb);
694 while (fgets(rb, sizeof(rb), tfp) != 0) {
695 fprintf(rfp, "%s", rb);
704 /*)Function VOID lkalist(pc)
706 * int pc current program counter value
708 * The function lkalist() performs the following functions:
710 * (1) if the value of gline = 0 then the current listing
711 * file line is copied to the relocated listing file output.
713 * (2) the listing file is read line by line and copied to
714 * the relocated listing file until a valid source
715 * line number and a program counter value of the correct
716 * radix is found. The new relocated pc value is substituted
717 * and the line is written to the RST file.
721 * char str[] temporary string
724 * int gcntr data byte counter
725 * int gline get a line from the LST file
726 * to translate for the RST file
727 * char rb[] read listing file text line
728 * char *rp pointer to listing file text line
729 * FILE *rfp The file handle to the current
731 * FILE *tfp The file handle to the current
732 * LST file being scanned
736 * int fclose() c_library
737 * int fgets() c_library
738 * int fprintf() c_library
739 * int sprintf() c_library
740 * char * strncpy() c_library
743 * Lines of the LST file are copied to the RST file,
744 * the last line copied has the code address
745 * updated to reflect the program relocation.
756 * Exit if listing file is not open
758 loop: if (tfp == NULL)
762 * Copy current LST to RST
765 fprintf(rfp, "%s", rb);
770 * Clear text line buffer
772 for (i=0,rp=rb; i<sizeof(rb); i++) {
777 * Get next LST text line
779 if (fgets(rb, sizeof(rb), tfp) == NULL) {
788 * Must have an ASxxxx Listing line number
790 if (!dgt(RAD10, &rb[30], 1)) {
791 fprintf(rfp, "%s", rb);
796 * Must have an address in the expected radix
799 if (!dgt(RAD16, &rb[3], 4)) {
800 fprintf(rfp, "%s", rb);
803 sprintf(str, "%04X", pc);
804 strncpy(&rb[3], str, 4);
807 if (!dgt(RAD10, &rb[3], 5)) {
808 fprintf(rfp, "%s", rb);
811 sprintf(str, "%05d", pc);
812 strncpy(&rb[3], str, 5);
815 if (!dgt(RAD8, &rb[3], 6)) {
816 fprintf(rfp, "%s", rb);
819 sprintf(str, "%06o", pc);
820 strncpy(&rb[3], str, 6);
824 * Copy updated LST text line to RST
826 fprintf(rfp, "%s", rb);
830 /*)Function VOID lkglist(pc,v)
832 * int pc current program counter value
833 * int v value of byte at this address
835 * The function lkglist() performs the following functions:
837 * (1) if the value of gline = 1 then the listing file
838 * is read line by line and copied to the
839 * relocated listing file until a valid source
840 * line number and a program counter value of the correct
843 * (2) The new relocated values and code address are
844 * substituted and the line may be written to the RST file.
848 * char str[] temporary string
851 * int gcntr data byte counter
852 * set to -1 for a continuation line
853 * int gline get a line from the LST file
854 * to translate for the RST file
855 * char rb[] read listing file text line
856 * char *rp pointer to listing file text line
857 * FILE *rfp The file handle to the current
859 * FILE *tfp The file handle to the current
860 * LST file being scanned
864 * int fclose() c_library
865 * int fgets() c_library
866 * int fprintf() c_library
867 * int sprintf() c_library
868 * char * strncpy() c_library
871 * Lines of the LST file are copied to the RST file
872 * with updated data values and code addresses.
884 * Exit if listing file is not open
886 loop: if (tfp == NULL)
890 * Get next LST text line
894 * Clear text line buffer
896 for (i=0,rp=rb; i<sizeof(rb); i++) {
901 * Get next LST text line
903 if (fgets(rb, sizeof(rb), tfp) == NULL) {
912 * Check for a listing line number if required
915 if (!dgt(RAD10, &rb[30], 1)) {
916 fprintf(rfp, "%s", rb);
934 rp = &rb[8 + (3 * gcntr)];
937 * Number must be of proper radix
939 if (!dgt(RAD16, rp, 2)) {
940 fprintf(rfp, "%s", rb);
945 * Output new data value, overwrite relocation codes
947 sprintf(str, " %02X", v);
948 strncpy(rp-1, str, 3);
953 * Output relocated code address
956 if (dgt(RAD16, &rb[3], 4)) {
957 sprintf(str, "%04X", pc);
958 strncpy(&rb[3], str, 4);
962 * Output text line when updates finished
965 fprintf(rfp, "%s", rb);
980 rp = &rb[9 + (3 * gcntr)];
983 * Number must be of proper radix
985 if (!dgt(RAD10, rp, 3)) {
986 fprintf(rfp, "%s", rb);
991 * Output new data value, overwrite relocation codes
993 sprintf(str, " %03d", v);
994 strncpy(rp-1, str, 4);
999 * Output relocated code address
1002 if (dgt(RAD10, &rb[3], 5)) {
1003 sprintf(str, "%05d", pc);
1004 strncpy(&rb[3], str, 5);
1008 * Output text line when updates finished
1011 fprintf(rfp, "%s", rb);
1026 rp = &rb[10 + (3 * gcntr)];
1029 * Number must be of proper radix
1031 if (!dgt(RAD8, rp, 3)) {
1032 fprintf(rfp, "%s", rb);
1037 * Output new data value, overwrite relocation codes
1039 sprintf(str, " %03o", v);
1040 strncpy(rp-1, str, 4);
1045 * Output relocated code address
1048 if (dgt(RAD8, &rb[3], 6)) {
1049 sprintf(str, "%06o", pc);
1050 strncpy(&rb[3], str, 6);
1054 * Output text line when updates finished
1057 fprintf(rfp, "%s", rb);
1064 /*)Function int dgt(rdx,str,n)
1066 * int rdx radix bit code
1067 * char *str pointer to the test string
1068 * int n number of characters to check
1070 * The function dgt() verifies that the string under test
1071 * is of the specified radix.
1074 * int i loop counter
1077 * ctype[] array of character types
1093 for (i=0; i<n; i++) {
1094 if ((ctype[(int)*str++] & rdx) == 0)
1100 /*JCF: Create a memory summary file with extension .mem*/
1101 int summary(struct area * areap)
1103 #define EQ(A,B) !strcmpi((A),(B))
1104 #define MIN_STACK 16
1105 #define REPORT_ERROR(A, H) \
1107 fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
1108 fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
1112 #define REPORT_WARNING(A, H) \
1114 fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
1115 fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
1120 unsigned int Total_Last=0, k;
1125 /*Artifacts used for printing*/
1126 char start[8], end[8], size[8], max[8];
1127 char format[]=" %-16.16s %-7.7s %-7.7s %-7.7s %-7.7s\n";
1128 char line[]="---------------------";
1139 unsigned int dram[0x100];
1141 {0, 8, 8, "REG_BANK_0", 0x0001},
1142 {0x8, 8, 8, "REG_BANK_1", 0x0002},
1143 {0x10, 8, 8, "REG_BANK_2", 0x0004},
1144 {0x18, 8, 8, "REG_BANK_3", 0x0008},
1145 {0x20, 0, 16, "BSEG_BYTES", 0x0010},
1146 {0, 0, 128, "UNUSED", 0x0000},
1147 {0x7f, 0, 128, "DATA", 0x0020},
1148 {0, 0, 128, "TOTAL:", 0x0000}
1151 _Mem IRam= {0xff, 0, 128, "INDIRECT RAM", 0x0080};
1152 _Mem Stack={0xff, 0, 1, "STACK", 0x0000};
1153 _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
1154 _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
1156 if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
1164 else if(iram_size<0x80)
1166 Ram[5].Max=iram_size;
1167 Ram[6].Max=iram_size;
1168 Ram[7].Max=iram_size;
1176 IRam.Max=iram_size-0x80;
1179 for(j=0; j<(int)iram_size; j++) dram[j]=0;
1180 for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
1182 /* Open Memory Summary File*/
1183 of = afile(linkp->f_idp, "mem", 1);
1192 /**/ if (EQ(xp->a_id, "REG_BANK_0"))
1194 Ram[0].Size=xp->a_size;
1196 else if (EQ(xp->a_id, "REG_BANK_1"))
1198 Ram[1].Size=xp->a_size;
1200 else if (EQ(xp->a_id, "REG_BANK_2"))
1202 Ram[2].Size=xp->a_size;
1204 else if (EQ(xp->a_id, "REG_BANK_3"))
1206 Ram[3].Size=xp->a_size;
1208 else if (EQ(xp->a_id, "BSEG_BYTES"))
1210 Ram[4].Size=xp->a_size;
1212 else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
1214 Ram[6].Size+=xp->a_size;
1215 if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
1218 else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
1219 EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
1221 Rom.Size+=xp->a_size;
1222 if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
1225 else if (EQ(xp->a_id, "SSEG"))
1227 Stack.Size+=xp->a_size;
1228 if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
1231 else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG"))
1233 XRam.Size+=xp->a_size;
1234 if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
1237 else if (EQ(xp->a_id, "ISEG"))
1239 IRam.Size+=xp->a_size;
1240 if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
1246 for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
1247 dram[k]|=Ram[j].flag; /*Mark as used*/
1249 for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
1250 dram[k]|=IRam.flag; /*Mark as used*/
1252 /*Compute the amount of unused memory in direct data Ram. This is the
1253 gap between the last register bank or bit segment and the data segment.*/
1254 for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
1256 Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
1258 /*Compute the data Ram totals*/
1261 if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
1262 Ram[7].Size+=Ram[j].Size;
1264 Total_Last=Ram[6].Size+Ram[6].Start-1;
1266 /*Report the Ram totals*/
1267 fprintf(of, "Direct Internal RAM:\n");
1268 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
1272 if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
1273 if((j!=5) || (Ram[j].Size>0))
1275 sprintf(start, "0x%02x", Ram[j].Start);
1277 end[0]=0;/*Empty string*/
1279 sprintf(end, "0x%02x", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
1280 sprintf(size, "%5u", Ram[j].Size);
1281 sprintf(max, "%5u", Ram[j].Max);
1282 fprintf(of, format, Ram[j].Name, start, end, size, max);
1286 for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
1288 if(dram[k]!=Ram[6].flag)
1290 sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
1291 REPORT_ERROR(buff, 1);
1296 if(Ram[4].Size>Ram[4].Max)
1298 k=Ram[4].Size-Ram[4].Max;
1299 sprintf(buff, "Insufficient bit addressable memory. "
1300 "%d byte%s short.\n", k, (k==1)?"":"s");
1301 REPORT_ERROR(buff, 1);
1306 sprintf(buff, "%d bytes in DRAM wasted. "
1307 "SDCC link could use: --data-loc 0x%02x\n",
1308 Ram[5].Size, Ram[6].Start-Ram[5].Size);
1309 REPORT_WARNING(buff, 1);
1312 if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
1314 k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
1315 sprintf(buff, "Insufficient DRAM memory. "
1316 "%d byte%s short.\n", k, (k==1)?"":"s");
1317 REPORT_ERROR(buff, 1);
1320 /*Report the position of the begining of the stack*/
1321 fprintf(of, "\nStack starts at: 0x%02x", Stack.Start);
1323 /*Check that the stack pointer is landing in a safe place:*/
1324 if( (dram[Stack.Start] & 0x8000) == 0x8000 )
1327 sprintf(buff, "Stack set to unavailable memory.\n");
1328 REPORT_ERROR(buff, 1);
1330 else if(dram[Stack.Start])
1333 sprintf(buff, "Stack overlaps area ");
1334 REPORT_ERROR(buff, 1);
1337 if(dram[Stack.Start]&Ram[j].flag)
1339 sprintf(buff, "'%s'\n", Ram[j].Name);
1343 if(dram[Stack.Start]&IRam.flag)
1345 sprintf(buff, "'%s'\n", IRam.Name);
1347 REPORT_ERROR(buff, 0);
1351 for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
1352 fprintf(of, " with %d bytes available\n", k);
1355 sprintf(buff, "Only %d byte%s available for stack.\n",
1357 REPORT_WARNING(buff, 1);
1361 fprintf(of, "\nOther memory:\n");
1362 fprintf(of, format, "Name", "Start", "End", "Size", "Max");
1363 fprintf(of, format, line, line, line, line, line);
1365 /*Report IRam totals:*/
1366 sprintf(start, "0x%02x", IRam.Start);
1368 end[0]=0;/*Empty string*/
1370 sprintf(end, "0x%02x", IRam.Size+IRam.Start-1);
1371 sprintf(size, "%5u", IRam.Size);
1372 sprintf(max, "%5u", IRam.Max);
1373 fprintf(of, format, IRam.Name, start, end, size, max);
1375 /*Report XRam totals:*/
1376 sprintf(start, "0x%04x", XRam.Start);
1378 end[0]=0;/*Empty string*/
1380 sprintf(end, "0x%04x", XRam.Size+XRam.Start-1);
1381 sprintf(size, "%5u", XRam.Size);
1382 sprintf(max, "%5u", XRam.Max);
1383 fprintf(of, format, XRam.Name, start, end, size, max);
1385 /*Report Rom/Flash totals:*/
1386 sprintf(start, "0x%04x", Rom.Start);
1388 end[0]=0;/*Empty string*/
1390 sprintf(end, "0x%04x", Rom.Size+Rom.Start-1);
1391 sprintf(size, "%5u", Rom.Size);
1392 sprintf(max, "%5u", Rom.Max);
1393 fprintf(of, format, Rom.Name, start, end, size, max);
1395 /*Report any excess:*/
1396 if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
1398 sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
1399 REPORT_ERROR(buff, 1);
1401 if((XRam.Start+XRam.Size)>XRam.Max)
1403 sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
1404 REPORT_ERROR(buff, 1);
1406 if((Rom.Start+Rom.Size)>Rom.Max)
1408 sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
1409 REPORT_ERROR(buff, 1);