1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 symbol *interrupts[256];
30 /*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
31 void printIval (symbol *, link *, initList *, FILE *);
33 set *publics = NULL; /* public variables */
34 set *externs = NULL; /* Varibles that are declared as extern */
36 /* TODO: this should be configurable (DS803C90 uses more than 6) */
37 int maxInterrupts = 6;
39 extern int maxRegBank ;
41 extern char *VersionString;
42 extern FILE *codeOutFile;
43 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
44 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
45 /*-----------------------------------------------------------------*/
46 /* closeTmpFiles - closes all tmp files created by the compiler */
47 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
48 /*-----------------------------------------------------------------*/
49 DEFSETFUNC(closeTmpFiles)
59 /*-----------------------------------------------------------------*/
60 /* rmTmpFiles - closes all tmp files created by the compiler */
61 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
62 /*-----------------------------------------------------------------*/
63 DEFSETFUNC(rmTmpFiles)
74 /*-----------------------------------------------------------------*/
75 /* copyFile - copies source file to destination file */
76 /*-----------------------------------------------------------------*/
77 void copyFile (FILE * dest, FILE * src)
83 if ((ch = fgetc (src)) != EOF)
87 char *aopLiteralLong(value *val, int offset, int size)
95 /* if it is a float then it gets tricky */
96 /* otherwise it is fairly simple */
97 if (!IS_FLOAT(val->type)) {
98 unsigned long v = floatFromVal(val);
103 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
106 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
109 /* Hmm. Too big for now. */
112 ALLOC_ATOMIC(rs,strlen(buffer)+1);
113 return strcpy (rs,buffer);
116 /* PENDING: For now size must be 1 */
119 /* it is type float */
120 fl.f = (float) floatFromVal(val);
122 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
124 tsprintf(buffer, "!immedbyte", fl.c[offset]);
126 ALLOC_ATOMIC(rs,strlen(buffer)+1);
127 return strcpy (rs,buffer);
130 /*-----------------------------------------------------------------*/
131 /* aopLiteral - string from a literal value */
132 /*-----------------------------------------------------------------*/
133 char *aopLiteral (value *val, int offset)
135 return aopLiteralLong(val, offset, 1);
138 /*-----------------------------------------------------------------*/
139 /* emitRegularMap - emit code for maps with no special cases */
140 /*-----------------------------------------------------------------*/
141 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
146 /* PENDING: special case here - should remove */
147 if (!strcmp(map->sname, DATA_NAME))
148 tfprintf(map->oFile, "\t!areadata\n", map->sname);
150 tfprintf(map->oFile, "\t!area\n", map->sname);
153 /* print the area name */
154 for (sym = setFirstItem (map->syms); sym;
155 sym = setNextItem (map->syms)) {
157 /* if extern then add it into the extern list */
158 if (IS_EXTERN (sym->etype)) {
159 addSetHead (&externs, sym);
163 /* if allocation required check is needed
164 then check if the symbol really requires
165 allocation only for local variables */
166 if (arFlag && !IS_AGGREGATE(sym->type) &&
167 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
168 !sym->allocreq && sym->level)
171 /* if global variable & not static or extern
172 and addPublics allowed then add it to the public set */
173 if ((sym->level == 0 ||
174 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
176 !IS_STATIC (sym->etype))
177 addSetHead (&publics, sym);
179 /* if extern then do nothing or is a function
181 if (IS_FUNC (sym->type))
184 /* print extra debug info if required */
185 if ((options.debug || sym->level == 0) && !options.nodebug) {
187 cdbSymbol(sym,cdbFile,FALSE,FALSE);
189 if (!sym->level) /* global */
190 if (IS_STATIC(sym->etype))
191 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
193 fprintf(map->oFile,"G$"); /* scope is global */
195 /* symbol is local */
196 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
197 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
200 /* if is has an absolute address then generate
201 an equate for this no need to allocate space */
202 if (SPEC_ABSA (sym->etype)) {
203 if ((options.debug || sym->level == 0) && !options.nodebug)
204 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
206 fprintf (map->oFile, "%s\t=\t0x%04x\n",
208 SPEC_ADDR (sym->etype));
212 if ((options.debug || sym->level == 0) && !options.nodebug)
213 fprintf(map->oFile,"==.\n");
214 if (IS_STATIC(sym->etype))
215 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
217 tfprintf(map->oFile, "!labeldef\n", sym->rname);
218 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
221 /* if it has a initial value then do it only if
222 it is a global variable */
223 if (sym->ival && sym->level == 0) {
226 if (IS_AGGREGATE (sym->type))
227 ival = initAggregates (sym, sym->ival, NULL);
229 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
230 decorateType (resolveSymbols (list2expr (sym->ival))));
231 codeOutFile = statsg->oFile;
233 eBBlockFromiCode (iCodeFromAst (ival));
241 /*-----------------------------------------------------------------*/
242 /* initPointer - pointer initialization code massaging */
243 /*-----------------------------------------------------------------*/
244 value *initPointer (initList *ilist)
247 ast *expr = list2expr(ilist);
252 /* try it the oldway first */
253 if ((val = constExprValue(expr,FALSE)))
256 /* no then we have to do these cludgy checks */
257 /* pointers can be initialized with address of
258 a variable or address of an array element */
259 if (IS_AST_OP(expr) && expr->opval.op == '&') {
260 /* address of symbol */
261 if (IS_AST_SYM_VALUE(expr->left)) {
262 val = copyValue(AST_VALUE(expr->left));
263 val->type = newLink();
264 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
265 DCL_TYPE(val->type) = CPOINTER ;
266 DCL_PTR_CONST(val->type) = port->mem.code_ro;
269 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
270 DCL_TYPE(val->type) = FPOINTER;
272 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
273 DCL_TYPE(val->type) = PPOINTER ;
275 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
276 DCL_TYPE(val->type) = IPOINTER ;
278 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
279 DCL_TYPE(val->type) = EEPPOINTER ;
281 DCL_TYPE(val->type) = POINTER ;
282 val->type->next = expr->left->ftype;
283 val->etype = getSpec(val->type);
287 /* if address of indexed array */
288 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
289 return valForArray(expr->left);
291 /* if address of structure element then
293 if (IS_AST_OP(expr->left) &&
294 expr->left->opval.op == '.' ) {
295 return valForStructElem(expr->left->left,
300 (&some_struct)->element */
301 if (IS_AST_OP(expr->left) &&
302 expr->left->opval.op == PTR_OP &&
303 IS_ADDRESS_OF_OP(expr->left->left))
304 return valForStructElem(expr->left->left->left,
308 /* case 3. (((char *) &a) +/- constant) */
309 if (IS_AST_OP(expr) &&
310 (expr->opval.op == '+' || expr->opval.op == '-') &&
311 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
312 IS_AST_OP(expr->left->right) &&
313 expr->left->right->opval.op == '&' &&
314 IS_AST_LIT_VALUE(expr->right)) {
316 return valForCastAggr(expr->left->right->left,
317 expr->left->left->opval.lnk,
318 expr->right,expr->opval.op);
323 werror(E_INIT_WRONG);
328 /*-----------------------------------------------------------------*/
329 /* printChar - formats and prints a characater string with DB */
330 /*-----------------------------------------------------------------*/
331 void printChar (FILE * ofile, char *s, int plen)
334 int len = strlen (s);
339 while (len && pplen < plen) {
341 while (i && *s && pplen < plen) {
342 if (*s < ' ' || *s == '\"') {
345 tfprintf(ofile, "\t!ascii\n", buf);
346 tfprintf(ofile, "\t!db\n", *s);
359 tfprintf(ofile, "\t!ascii\n", buf);
368 tfprintf(ofile, "\t!db\n", 0);
371 /*-----------------------------------------------------------------*/
372 /* printIvalType - generates ival for int/char */
373 /*-----------------------------------------------------------------*/
374 void printIvalType (link * type, initList * ilist, FILE * oFile)
378 /* if initList is deep */
379 if (ilist->type == INIT_DEEP)
380 ilist = ilist->init.deep;
382 val = list2val (ilist);
383 switch (getSize (type)) {
386 tfprintf(oFile, "\t!db\n", 0);
388 tfprintf(oFile, "\t!dbs\n",
389 aopLiteral (val, 0));
393 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
397 tfprintf (oFile, "\t!dw\n", 0);
398 tfprintf (oFile, "\t!dw\n", 0);
401 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
402 aopLiteral (val, 0), aopLiteral (val, 1),
403 aopLiteral (val, 2), aopLiteral (val, 3));
409 /*-----------------------------------------------------------------*/
410 /* printIvalStruct - generates initial value for structures */
411 /*-----------------------------------------------------------------*/
412 void printIvalStruct (symbol * sym,link * type,
413 initList * ilist, FILE * oFile)
418 sflds = SPEC_STRUCT (type)->fields;
419 if (ilist->type != INIT_DEEP) {
420 werror (E_INIT_STRUCT, sym->name);
424 iloop = ilist->init.deep;
426 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
427 printIval (sflds, sflds->type, iloop, oFile);
432 /*-----------------------------------------------------------------*/
433 /* printIvalChar - generates initital value for character array */
434 /*-----------------------------------------------------------------*/
435 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
442 val = list2val (ilist);
443 /* if the value is a character string */
444 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
445 if (!DCL_ELEM (type))
446 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
448 /* if size mismatch */
449 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
450 /* werror (E_ARRAY_BOUND); */
452 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
454 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
456 tfprintf (oFile, "\t!db\n", 0);
464 printChar (oFile, s,strlen(s)+1);
468 /*-----------------------------------------------------------------*/
469 /* printIvalArray - generates code for array initialization */
470 /*-----------------------------------------------------------------*/
471 void printIvalArray (symbol * sym, link * type, initList * ilist,
475 int lcnt = 0, size = 0;
477 /* take care of the special case */
478 /* array of characters can be init */
480 if (IS_CHAR (type->next))
481 if (printIvalChar (type,
482 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
483 oFile, SPEC_CVAL (sym->etype).v_char))
486 /* not the special case */
487 if (ilist->type != INIT_DEEP) {
488 werror (E_INIT_STRUCT, sym->name);
492 iloop = ilist->init.deep;
493 lcnt = DCL_ELEM (type);
497 printIval (sym, type->next, iloop, oFile);
498 iloop = (iloop ? iloop->next : NULL);
501 /* if not array limits given & we */
502 /* are out of initialisers then */
503 if (!DCL_ELEM (type) && !iloop)
506 /* no of elements given and we */
507 /* have generated for all of them */
512 /* if we have not been given a size */
513 if (!DCL_ELEM (type))
514 DCL_ELEM (type) = size;
519 /*-----------------------------------------------------------------*/
520 /* printIvalFuncPtr - generate initial value for function pointers */
521 /*-----------------------------------------------------------------*/
522 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
527 val = list2val (ilist);
528 /* check the types */
529 if ((dLvl = checkType (val->type, type->next)) <= 0) {
530 tfprintf(oFile, "\t!dw\n", 0);
534 /* now generate the name */
536 if (port->use_dw_for_init)
537 tfprintf(oFile, "\t!dw %s\n", val->name);
539 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name,val->name);
542 if (port->use_dw_for_init)
543 tfprintf(oFile, "\t!dws\n", val->sym->rname);
545 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->sym->rname,val->sym->rname);
550 /*-----------------------------------------------------------------*/
551 /* printIvalCharPtr - generates initial values for character pointers */
552 /*-----------------------------------------------------------------*/
553 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
557 /* PENDING: this is _very_ mcs51 specific, including a magic
559 It's also endin specific.
561 size = getSize (type);
563 if (val->name && strlen(val->name)) {
567 "\t!dbs\n", val->name) ;
570 if (port->use_dw_for_init)
571 tfprintf(oFile, "\t!dws\n", val->name);
573 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
575 /* PENDING: probably just 3 */
577 /* PENDING: 0x02 or 0x%02x, CDATA? */
579 "\t.byte %s,(%s >> 8),#0x%02x\n",
580 val->name, val->name, (IS_PTR(val->type) ? DCL_TYPE(val->type) :
581 PTR_TYPE(SPEC_OCLS(val->etype))));
587 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
590 tfprintf(oFile, "\t.byte %s,%s\n",
591 aopLiteral(val, 0),aopLiteral(val, 1));
594 /* PENDING: 0x02 or 0x%02x, CDATA? */
595 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
596 aopLiteral (val, 0), aopLiteral (val, 1));
604 if (val->sym && val->sym->isstrlit)
605 addSet (&statsg->syms, val->sym);
610 /*-----------------------------------------------------------------*/
611 /* printIvalPtr - generates initial value for pointers */
612 /*-----------------------------------------------------------------*/
613 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
618 if (ilist->type == INIT_DEEP)
619 ilist = ilist->init.deep;
621 /* function pointer */
622 if (IS_FUNC (type->next)) {
623 printIvalFuncPtr (type, ilist, oFile);
627 if (!(val = initPointer (ilist)))
630 /* if character pointer */
631 if (IS_CHAR (type->next))
632 if (printIvalCharPtr (sym, type, val, oFile))
636 if (checkType (type, val->type) != 1)
637 werror (E_INIT_WRONG);
639 /* if val is literal */
640 if (IS_LITERAL (val->etype)) {
641 switch (getSize (type)) {
643 tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
646 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
649 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
650 aopLiteral (val, 0), aopLiteral (val, 1));
656 switch (getSize (type)) {
658 tfprintf (oFile, "\t!dbs\n", val->name);
661 tfprintf (oFile, "\t!dws\n", val->name);
665 fprintf (oFile, "\t.byte %s,(%s >> 8),#0x%02x\n",
666 val->name, val->name,(IS_PTR(val->type) ? DCL_TYPE(val->type) :
667 PTR_TYPE(SPEC_OCLS(val->etype))));
672 /*-----------------------------------------------------------------*/
673 /* printIval - generates code for initial value */
674 /*-----------------------------------------------------------------*/
675 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
680 /* if structure then */
681 if (IS_STRUCT (type)) {
682 printIvalStruct (sym, type, ilist, oFile);
686 /* if this is a pointer */
688 printIvalPtr (sym, type, ilist, oFile);
692 /* if this is an array */
693 if (IS_ARRAY (type)) {
694 printIvalArray (sym, type, ilist, oFile);
698 /* if type is SPECIFIER */
699 if (IS_SPEC (type)) {
700 printIvalType (type, ilist, oFile);
705 /*-----------------------------------------------------------------*/
706 /* emitStaticSeg - emitcode for the static segment */
707 /*-----------------------------------------------------------------*/
708 void emitStaticSeg (memmap * map)
712 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
715 /* for all variables in this segment do */
716 for (sym = setFirstItem (map->syms); sym;
717 sym = setNextItem (map->syms)) {
719 /* if it is "extern" then do nothing */
720 if (IS_EXTERN (sym->etype))
723 /* if it is not static add it to the public
725 if (!IS_STATIC (sym->etype))
726 addSetHead (&publics, sym);
728 /* print extra debug info if required */
729 if ((options.debug || sym->level == 0) && !options.nodebug) {
731 cdbSymbol(sym,cdbFile,FALSE,FALSE);
733 if (!sym->level) { /* global */
734 if (IS_STATIC(sym->etype))
735 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
737 fprintf(code->oFile,"G$"); /* scope is global */
740 /* symbol is local */
741 fprintf(code->oFile,"L%s$",
742 (sym->localof ? sym->localof->name : "-null-"));
743 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
746 /* if it has an absolute address */
747 if (SPEC_ABSA (sym->etype)) {
748 if ((options.debug || sym->level == 0) && !options.nodebug)
749 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
751 fprintf (code->oFile, "%s\t=\t0x%04x\n",
753 SPEC_ADDR (sym->etype));
756 if ((options.debug || sym->level == 0) && !options.nodebug)
757 fprintf(code->oFile," == .\n");
759 /* if it has an initial value */
761 fprintf (code->oFile, "%s:\n", sym->rname);
763 resolveIvalSym (sym->ival);
764 printIval (sym, sym->type, sym->ival, code->oFile);
769 fprintf (code->oFile, "%s:\n", sym->rname);
770 /* special case for character strings */
771 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
772 SPEC_CVAL (sym->etype).v_char)
773 printChar (code->oFile,
774 SPEC_CVAL (sym->etype).v_char,
775 strlen(SPEC_CVAL (sym->etype).v_char)+1);
777 tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
783 /*-----------------------------------------------------------------*/
784 /* emitMaps - emits the code for the data portion the code */
785 /*-----------------------------------------------------------------*/
788 /* no special considerations for the following
789 data, idata & bit & xdata */
790 emitRegularMap (data, TRUE, TRUE);
791 emitRegularMap (idata, TRUE,TRUE);
792 emitRegularMap (bit, TRUE,FALSE);
793 emitRegularMap (xdata, TRUE,TRUE);
794 emitRegularMap (sfr, FALSE,FALSE);
795 emitRegularMap (sfrbit, FALSE,FALSE);
796 emitRegularMap (code, TRUE,FALSE);
797 emitStaticSeg (statsg);
800 /*-----------------------------------------------------------------*/
801 /* createInterruptVect - creates the interrupt vector */
802 /*-----------------------------------------------------------------*/
803 void createInterruptVect (FILE * vFile)
806 mainf = newSymbol ("main", 0);
809 /* only if the main function exists */
810 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
811 if (!options.cc_only)
816 /* if the main is only a prototype ie. no body then do nothing */
818 /* if ! compile only then main function should be present */
819 if (!options.cc_only)
824 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
825 fprintf (vFile, "__interrupt_vect:\n");
828 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
830 /* "generic" interrupt table header (if port doesn't specify one).
832 * Look suspiciously like 8051 code to me...
835 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
838 /* now for the other interrupts */
839 for (; i < maxInterrupts; i++) {
841 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
843 fprintf (vFile, "\treti\n\t.ds\t7\n");
850 ";--------------------------------------------------------\n"
851 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
855 ";--------------------------------------------------------\n"};
858 /*-----------------------------------------------------------------*/
859 /* initialComments - puts in some initial comments */
860 /*-----------------------------------------------------------------*/
861 void initialComments (FILE * afile)
865 fprintf (afile, "%s", iComments1);
866 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
867 fprintf (afile, "%s", iComments2);
870 /*-----------------------------------------------------------------*/
871 /* printPublics - generates .global for publics */
872 /*-----------------------------------------------------------------*/
873 void printPublics (FILE * afile)
877 fprintf (afile, "%s", iComments2);
878 fprintf (afile, "; Public variables in this module\n");
879 fprintf (afile, "%s", iComments2);
881 for (sym = setFirstItem (publics); sym;
882 sym = setNextItem (publics))
883 tfprintf(afile, "\t!global\n", sym->rname);
886 /*-----------------------------------------------------------------*/
887 /* printExterns - generates .global for externs */
888 /*-----------------------------------------------------------------*/
889 void printExterns (FILE * afile)
893 fprintf (afile, "%s", iComments2);
894 fprintf (afile, "; Externals used\n");
895 fprintf (afile, "%s", iComments2);
897 for (sym = setFirstItem (externs); sym;
898 sym = setNextItem (externs))
899 tfprintf(afile, "\t!global\n", sym->rname);
902 /*-----------------------------------------------------------------*/
903 /* emitOverlay - will emit code for the overlay stuff */
904 /*-----------------------------------------------------------------*/
905 static void emitOverlay(FILE *afile)
909 if (!elementsInSet(ovrSetSets))
910 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
912 /* for each of the sets in the overlay segment do */
913 for (ovrset = setFirstItem(ovrSetSets); ovrset;
914 ovrset = setNextItem(ovrSetSets)) {
918 if (elementsInSet(ovrset)) {
919 /* this dummy area is used to fool the assembler
920 otherwise the assembler will append each of these
921 declarations into one chunk and will not overlay
923 fprintf(afile,"\t.area _DUMMY\n");
924 /* output the area informtion */
925 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
928 for (sym = setFirstItem(ovrset); sym;
929 sym = setNextItem(ovrset)) {
931 /* if extern then add it to the publics tabledo nothing */
932 if (IS_EXTERN (sym->etype))
935 /* if allocation required check is needed
936 then check if the symbol really requires
937 allocation only for local variables */
938 if (!IS_AGGREGATE(sym->type) &&
939 !(sym->_isparm && !IS_REGPARM(sym->etype))
940 && !sym->allocreq && sym->level)
943 /* if global variable & not static or extern
944 and addPublics allowed then add it to the public set */
945 if ((sym->_isparm && !IS_REGPARM(sym->etype))
946 && !IS_STATIC (sym->etype))
947 addSetHead (&publics, sym);
949 /* if extern then do nothing or is a function
951 if (IS_FUNC (sym->type))
954 /* print extra debug info if required */
955 if ((options.debug || sym->level == 0) && !options.nodebug) {
957 cdbSymbol(sym,cdbFile,FALSE,FALSE);
959 if (!sym->level) { /* global */
960 if (IS_STATIC(sym->etype))
961 fprintf(afile,"F%s$",moduleName); /* scope is file */
963 fprintf(afile,"G$"); /* scope is global */
966 /* symbol is local */
967 fprintf(afile,"L%s$",
968 (sym->localof ? sym->localof->name : "-null-"));
969 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
972 /* if is has an absolute address then generate
973 an equate for this no need to allocate space */
974 if (SPEC_ABSA (sym->etype)) {
976 if ((options.debug || sym->level == 0) && !options.nodebug)
977 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
979 fprintf (afile, "%s\t=\t0x%04x\n",
981 SPEC_ADDR (sym->etype));
984 if ((options.debug || sym->level == 0) && !options.nodebug)
985 fprintf(afile,"==.\n");
988 tfprintf(afile, "!labeldef\n", sym->rname);
989 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
996 /*-----------------------------------------------------------------*/
997 /* glue - the final glue that hold the whole thing together */
998 /*-----------------------------------------------------------------*/
1003 FILE *ovrFile = tempfile();
1005 addSetHead(&tmpfileSet,ovrFile);
1006 /* print the global struct definitions */
1008 cdbStructBlock (0,cdbFile);
1011 /* PENDING: this isnt the best place but it will do */
1012 if (port->general.glue_up_main) {
1013 /* create the interrupt vector table */
1014 createInterruptVect (vFile);
1017 addSetHead(&tmpfileSet,vFile);
1019 /* emit code for the all the variables declared */
1021 /* do the overlay segments */
1022 emitOverlay(ovrFile);
1024 /* now put it all together into the assembler file */
1025 /* create the assembler file name */
1027 if (!options.c1mode) {
1028 sprintf (buffer, srcFileName);
1029 strcat (buffer, ".asm");
1032 strcpy(buffer, options.out_name);
1035 if (!(asmFile = fopen (buffer, "w"))) {
1036 werror (E_FILE_OPEN_ERR, buffer);
1040 /* initial comments */
1041 initialComments (asmFile);
1043 /* print module name */
1044 tfprintf(asmFile, "\t!module\n", moduleName);
1045 tfprintf(asmFile, "\t!fileprelude\n");
1047 /* Let the port generate any global directives, etc. */
1048 if (port->genAssemblerPreamble)
1050 port->genAssemblerPreamble(asmFile);
1053 /* print the global variables in this module */
1054 printPublics (asmFile);
1055 if (port->assembler.externGlobal)
1056 printExterns (asmFile);
1058 /* copy the sfr segment */
1059 fprintf (asmFile, "%s", iComments2);
1060 fprintf (asmFile, "; special function registers\n");
1061 fprintf (asmFile, "%s", iComments2);
1062 copyFile (asmFile, sfr->oFile);
1064 /* copy the sbit segment */
1065 fprintf (asmFile, "%s", iComments2);
1066 fprintf (asmFile, "; special function bits \n");
1067 fprintf (asmFile, "%s", iComments2);
1068 copyFile (asmFile, sfrbit->oFile);
1070 /* copy the data segment */
1071 fprintf (asmFile, "%s", iComments2);
1072 fprintf (asmFile, "; internal ram data\n");
1073 fprintf (asmFile, "%s", iComments2);
1074 copyFile (asmFile, data->oFile);
1077 /* create the overlay segments */
1078 fprintf (asmFile, "%s", iComments2);
1079 fprintf (asmFile, "; overlayable items in internal ram \n");
1080 fprintf (asmFile, "%s", iComments2);
1081 copyFile (asmFile, ovrFile);
1083 /* create the stack segment MOF */
1084 if (mainf && mainf->fbody) {
1085 fprintf (asmFile, "%s", iComments2);
1086 fprintf (asmFile, "; Stack segment in internal ram \n");
1087 fprintf (asmFile, "%s", iComments2);
1088 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1089 "__start__stack:\n\t.ds\t1\n\n");
1092 /* create the idata segment */
1093 fprintf (asmFile, "%s", iComments2);
1094 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1095 fprintf (asmFile, "%s", iComments2);
1096 copyFile (asmFile, idata->oFile);
1098 /* copy the bit segment */
1099 fprintf (asmFile, "%s", iComments2);
1100 fprintf (asmFile, "; bit data\n");
1101 fprintf (asmFile, "%s", iComments2);
1102 copyFile (asmFile, bit->oFile);
1104 /* if external stack then reserve space of it */
1105 if (mainf && mainf->fbody && options.useXstack ) {
1106 fprintf (asmFile, "%s", iComments2);
1107 fprintf (asmFile, "; external stack \n");
1108 fprintf (asmFile, "%s", iComments2);
1109 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1110 fprintf (asmFile,"\t.ds 256\n");
1114 /* copy xtern ram data */
1115 fprintf (asmFile, "%s", iComments2);
1116 fprintf (asmFile, "; external ram data\n");
1117 fprintf (asmFile, "%s", iComments2);
1118 copyFile (asmFile, xdata->oFile);
1120 /* copy the interrupt vector table */
1121 if (mainf && mainf->fbody) {
1122 fprintf (asmFile, "%s", iComments2);
1123 fprintf (asmFile, "; interrupt vector \n");
1124 fprintf (asmFile, "%s", iComments2);
1125 copyFile (asmFile, vFile);
1128 /* copy global & static initialisations */
1129 fprintf (asmFile, "%s", iComments2);
1130 fprintf (asmFile, "; global & static initialisations\n");
1131 fprintf (asmFile, "%s", iComments2);
1133 /* Everywhere we generate a reference to the static_name area,
1134 * (which is currently only here), we immediately follow it with a
1135 * definition of the post_static_name area. This guarantees that
1136 * the post_static_name area will immediately follow the static_name
1139 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1140 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1141 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1143 if (mainf && mainf->fbody) {
1144 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1145 /* if external stack is specified then the
1146 higher order byte of the xdatalocation is
1147 going into P2 and the lower order going into
1149 if (options.useXstack) {
1150 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1151 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1152 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1153 (unsigned int)options.xdata_loc & 0xff);
1156 /* initialise the stack pointer */
1157 /* if the user specified a value then use it */
1158 if (options.stack_loc)
1159 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1161 /* no: we have to compute it */
1162 if (!options.stackOnData && maxRegBank <= 3)
1163 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1165 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1167 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1168 fprintf (asmFile,"\tmov\ta,dpl\n");
1169 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1170 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1171 fprintf (asmFile,"__sdcc_init_data:\n");
1174 copyFile (asmFile, statsg->oFile);
1176 if (port->general.glue_up_main && mainf && mainf->fbody)
1178 /* This code is generated in the post-static area.
1179 * This area is guaranteed to follow the static area
1180 * by the ugly shucking and jiving about 20 lines ago.
1182 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1183 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1186 /* copy over code */
1187 fprintf (asmFile, "%s", iComments2);
1188 fprintf (asmFile, "; code\n");
1189 fprintf (asmFile, "%s", iComments2);
1190 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1191 if (mainf && mainf->fbody) {
1193 /* entry point @ start of CSEG */
1194 fprintf (asmFile,"__sdcc_program_startup:\n");
1196 /* put in the call to main */
1197 fprintf(asmFile,"\tlcall\t_main\n");
1198 if (options.mainreturn) {
1200 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1201 fprintf(asmFile,"\tret\n");
1205 fprintf(asmFile,";\treturn from main will lock up\n");
1206 fprintf(asmFile,"\tsjmp .\n");
1209 copyFile (asmFile, code->oFile);
1212 applyToSet(tmpfileSet,closeTmpFiles);
1213 applyToSet(tmpfileNameSet, rmTmpFiles);
1216 /** Creates a temporary file a'la tmpfile which avoids the bugs
1217 in cygwin wrt c:\tmp.
1218 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1220 FILE *tempfile(void)
1222 const char *tmpdir = NULL;
1224 tmpdir = getenv("TMP");
1225 else if (getenv("TEMP"))
1226 tmpdir = getenv("TEMP");
1227 else if (getenv("TMPDIR"))
1228 tmpdir = getenv("TMPDIR");
1230 char *name = tempnam(tmpdir, "sdcc");
1232 FILE *fp = fopen(name, "w+b");
1234 addSetHead(&tmpfileNameSet, name);
1242 char *gc_strdup(const char *s)
1245 ALLOC_ATOMIC(ret, strlen(s)+1);