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);
367 tfprintf(ofile, "\t!db\n", 0);
370 /*-----------------------------------------------------------------*/
371 /* printIvalType - generates ival for int/char */
372 /*-----------------------------------------------------------------*/
373 void printIvalType (link * type, initList * ilist, FILE * oFile)
377 /* if initList is deep */
378 if (ilist->type == INIT_DEEP)
379 ilist = ilist->init.deep;
381 val = list2val (ilist);
382 switch (getSize (type)) {
385 tfprintf(oFile, "\t!db\n", 0);
387 tfprintf(oFile, "\t!dbs\n",
388 aopLiteral (val, 0));
392 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
396 tfprintf (oFile, "\t!dw\n", 0);
397 tfprintf (oFile, "\t!dw\n", 0);
400 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
401 aopLiteral (val, 0), aopLiteral (val, 1),
402 aopLiteral (val, 2), aopLiteral (val, 3));
408 /*-----------------------------------------------------------------*/
409 /* printIvalStruct - generates initial value for structures */
410 /*-----------------------------------------------------------------*/
411 void printIvalStruct (symbol * sym,link * type,
412 initList * ilist, FILE * oFile)
417 sflds = SPEC_STRUCT (type)->fields;
418 if (ilist->type != INIT_DEEP) {
419 werror (E_INIT_STRUCT, sym->name);
423 iloop = ilist->init.deep;
425 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
426 printIval (sflds, sflds->type, iloop, oFile);
431 /*-----------------------------------------------------------------*/
432 /* printIvalChar - generates initital value for character array */
433 /*-----------------------------------------------------------------*/
434 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
441 val = list2val (ilist);
442 /* if the value is a character string */
443 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
444 if (!DCL_ELEM (type))
445 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
447 /* if size mismatch */
448 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
449 /* werror (E_ARRAY_BOUND); */
451 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
453 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
455 tfprintf (oFile, "\t!db\n", 0);
463 printChar (oFile, s,strlen(s)+1);
467 /*-----------------------------------------------------------------*/
468 /* printIvalArray - generates code for array initialization */
469 /*-----------------------------------------------------------------*/
470 void printIvalArray (symbol * sym, link * type, initList * ilist,
474 int lcnt = 0, size = 0;
476 /* take care of the special case */
477 /* array of characters can be init */
479 if (IS_CHAR (type->next))
480 if (printIvalChar (type,
481 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
482 oFile, SPEC_CVAL (sym->etype).v_char))
485 /* not the special case */
486 if (ilist->type != INIT_DEEP) {
487 werror (E_INIT_STRUCT, sym->name);
491 iloop = ilist->init.deep;
492 lcnt = DCL_ELEM (type);
496 printIval (sym, type->next, iloop, oFile);
497 iloop = (iloop ? iloop->next : NULL);
500 /* if not array limits given & we */
501 /* are out of initialisers then */
502 if (!DCL_ELEM (type) && !iloop)
505 /* no of elements given and we */
506 /* have generated for all of them */
511 /* if we have not been given a size */
512 if (!DCL_ELEM (type))
513 DCL_ELEM (type) = size;
518 /*-----------------------------------------------------------------*/
519 /* printIvalFuncPtr - generate initial value for function pointers */
520 /*-----------------------------------------------------------------*/
521 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
526 val = list2val (ilist);
527 /* check the types */
528 if ((dLvl = checkType (val->type, type->next)) <= 0) {
529 tfprintf(oFile, "\t!dw\n", 0);
533 /* now generate the name */
535 if (port->use_dw_for_init)
536 tfprintf(oFile, "\t!dw %s\n", val->name);
538 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name,val->name);
541 if (port->use_dw_for_init)
542 tfprintf(oFile, "\t!dws\n", val->sym->rname);
544 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->sym->rname,val->sym->rname);
549 /*-----------------------------------------------------------------*/
550 /* printIvalCharPtr - generates initial values for character pointers */
551 /*-----------------------------------------------------------------*/
552 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
556 /* PENDING: this is _very_ mcs51 specific, including a magic
558 It's also endin specific.
560 size = getSize (type);
562 if (val->name && strlen(val->name)) {
566 "\t!dbs\n", val->name) ;
569 if (port->use_dw_for_init)
570 tfprintf(oFile, "\t!dws\n", val->name);
572 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
574 /* PENDING: probably just 3 */
576 /* PENDING: 0x02 or 0x%02x, CDATA? */
578 "\t.byte %s,(%s >> 8),#0x%02x\n",
579 val->name, val->name, (IS_PTR(val->type) ? DCL_TYPE(val->type) :
580 PTR_TYPE(SPEC_OCLS(val->etype))));
586 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
589 tfprintf(oFile, "\t.byte %s,%s\n",
590 aopLiteral(val, 0),aopLiteral(val, 1));
593 /* PENDING: 0x02 or 0x%02x, CDATA? */
594 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
595 aopLiteral (val, 0), aopLiteral (val, 1));
603 if (val->sym && val->sym->isstrlit)
604 addSet (&statsg->syms, val->sym);
609 /*-----------------------------------------------------------------*/
610 /* printIvalPtr - generates initial value for pointers */
611 /*-----------------------------------------------------------------*/
612 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
617 if (ilist->type == INIT_DEEP)
618 ilist = ilist->init.deep;
620 /* function pointer */
621 if (IS_FUNC (type->next)) {
622 printIvalFuncPtr (type, ilist, oFile);
626 if (!(val = initPointer (ilist)))
629 /* if character pointer */
630 if (IS_CHAR (type->next))
631 if (printIvalCharPtr (sym, type, val, oFile))
635 if (checkType (type, val->type) != 1)
636 werror (E_INIT_WRONG);
638 /* if val is literal */
639 if (IS_LITERAL (val->etype)) {
640 switch (getSize (type)) {
642 tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
645 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
648 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
649 aopLiteral (val, 0), aopLiteral (val, 1));
655 switch (getSize (type)) {
657 tfprintf (oFile, "\t!dbs\n", val->name);
660 tfprintf (oFile, "\t!dws\n", val->name);
664 fprintf (oFile, "\t.byte %s,(%s >> 8),#0x%02x\n",
665 val->name, val->name,(IS_PTR(val->type) ? DCL_TYPE(val->type) :
666 PTR_TYPE(SPEC_OCLS(val->etype))));
671 /*-----------------------------------------------------------------*/
672 /* printIval - generates code for initial value */
673 /*-----------------------------------------------------------------*/
674 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
679 /* if structure then */
680 if (IS_STRUCT (type)) {
681 printIvalStruct (sym, type, ilist, oFile);
685 /* if this is a pointer */
687 printIvalPtr (sym, type, ilist, oFile);
691 /* if this is an array */
692 if (IS_ARRAY (type)) {
693 printIvalArray (sym, type, ilist, oFile);
697 /* if type is SPECIFIER */
698 if (IS_SPEC (type)) {
699 printIvalType (type, ilist, oFile);
704 /*-----------------------------------------------------------------*/
705 /* emitStaticSeg - emitcode for the static segment */
706 /*-----------------------------------------------------------------*/
707 void emitStaticSeg (memmap * map)
711 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
714 /* for all variables in this segment do */
715 for (sym = setFirstItem (map->syms); sym;
716 sym = setNextItem (map->syms)) {
718 /* if it is "extern" then do nothing */
719 if (IS_EXTERN (sym->etype))
722 /* if it is not static add it to the public
724 if (!IS_STATIC (sym->etype))
725 addSetHead (&publics, sym);
727 /* print extra debug info if required */
728 if ((options.debug || sym->level == 0) && !options.nodebug) {
730 cdbSymbol(sym,cdbFile,FALSE,FALSE);
732 if (!sym->level) { /* global */
733 if (IS_STATIC(sym->etype))
734 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
736 fprintf(code->oFile,"G$"); /* scope is global */
739 /* symbol is local */
740 fprintf(code->oFile,"L%s$",
741 (sym->localof ? sym->localof->name : "-null-"));
742 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
745 /* if it has an absolute address */
746 if (SPEC_ABSA (sym->etype)) {
747 if ((options.debug || sym->level == 0) && !options.nodebug)
748 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
750 fprintf (code->oFile, "%s\t=\t0x%04x\n",
752 SPEC_ADDR (sym->etype));
755 if ((options.debug || sym->level == 0) && !options.nodebug)
756 fprintf(code->oFile," == .\n");
758 /* if it has an initial value */
760 fprintf (code->oFile, "%s:\n", sym->rname);
762 resolveIvalSym (sym->ival);
763 printIval (sym, sym->type, sym->ival, code->oFile);
768 fprintf (code->oFile, "%s:\n", sym->rname);
769 /* special case for character strings */
770 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
771 SPEC_CVAL (sym->etype).v_char)
772 printChar (code->oFile,
773 SPEC_CVAL (sym->etype).v_char,
774 strlen(SPEC_CVAL (sym->etype).v_char)+1);
776 tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
782 /*-----------------------------------------------------------------*/
783 /* emitMaps - emits the code for the data portion the code */
784 /*-----------------------------------------------------------------*/
787 /* no special considerations for the following
788 data, idata & bit & xdata */
789 emitRegularMap (data, TRUE, TRUE);
790 emitRegularMap (idata, TRUE,TRUE);
791 emitRegularMap (bit, TRUE,FALSE);
792 emitRegularMap (xdata, TRUE,TRUE);
793 emitRegularMap (sfr, FALSE,FALSE);
794 emitRegularMap (sfrbit, FALSE,FALSE);
795 emitRegularMap (code, TRUE,FALSE);
796 emitStaticSeg (statsg);
799 /*-----------------------------------------------------------------*/
800 /* createInterruptVect - creates the interrupt vector */
801 /*-----------------------------------------------------------------*/
802 void createInterruptVect (FILE * vFile)
805 mainf = newSymbol ("main", 0);
808 /* only if the main function exists */
809 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
810 if (!options.cc_only)
815 /* if the main is only a prototype ie. no body then do nothing */
817 /* if ! compile only then main function should be present */
818 if (!options.cc_only)
823 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
824 fprintf (vFile, "__interrupt_vect:\n");
827 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
829 /* "generic" interrupt table header (if port doesn't specify one).
831 * Look suspiciously like 8051 code to me...
834 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
837 /* now for the other interrupts */
838 for (; i < maxInterrupts; i++) {
840 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
842 fprintf (vFile, "\treti\n\t.ds\t7\n");
849 ";--------------------------------------------------------\n"
850 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
854 ";--------------------------------------------------------\n"};
857 /*-----------------------------------------------------------------*/
858 /* initialComments - puts in some initial comments */
859 /*-----------------------------------------------------------------*/
860 void initialComments (FILE * afile)
864 fprintf (afile, "%s", iComments1);
865 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
866 fprintf (afile, "%s", iComments2);
869 /*-----------------------------------------------------------------*/
870 /* printPublics - generates .global for publics */
871 /*-----------------------------------------------------------------*/
872 void printPublics (FILE * afile)
876 fprintf (afile, "%s", iComments2);
877 fprintf (afile, "; Public variables in this module\n");
878 fprintf (afile, "%s", iComments2);
880 for (sym = setFirstItem (publics); sym;
881 sym = setNextItem (publics))
882 tfprintf(afile, "\t!global\n", sym->rname);
885 /*-----------------------------------------------------------------*/
886 /* printExterns - generates .global for externs */
887 /*-----------------------------------------------------------------*/
888 void printExterns (FILE * afile)
892 fprintf (afile, "%s", iComments2);
893 fprintf (afile, "; Externals used\n");
894 fprintf (afile, "%s", iComments2);
896 for (sym = setFirstItem (externs); sym;
897 sym = setNextItem (externs))
898 tfprintf(afile, "\t!global\n", sym->rname);
901 /*-----------------------------------------------------------------*/
902 /* emitOverlay - will emit code for the overlay stuff */
903 /*-----------------------------------------------------------------*/
904 static void emitOverlay(FILE *afile)
908 if (!elementsInSet(ovrSetSets))
909 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
911 /* for each of the sets in the overlay segment do */
912 for (ovrset = setFirstItem(ovrSetSets); ovrset;
913 ovrset = setNextItem(ovrSetSets)) {
917 if (elementsInSet(ovrset)) {
918 /* this dummy area is used to fool the assembler
919 otherwise the assembler will append each of these
920 declarations into one chunk and will not overlay
922 fprintf(afile,"\t.area _DUMMY\n");
923 /* output the area informtion */
924 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
927 for (sym = setFirstItem(ovrset); sym;
928 sym = setNextItem(ovrset)) {
930 /* if extern then add it to the publics tabledo nothing */
931 if (IS_EXTERN (sym->etype))
934 /* if allocation required check is needed
935 then check if the symbol really requires
936 allocation only for local variables */
937 if (!IS_AGGREGATE(sym->type) &&
938 !(sym->_isparm && !IS_REGPARM(sym->etype))
939 && !sym->allocreq && sym->level)
942 /* if global variable & not static or extern
943 and addPublics allowed then add it to the public set */
944 if ((sym->_isparm && !IS_REGPARM(sym->etype))
945 && !IS_STATIC (sym->etype))
946 addSetHead (&publics, sym);
948 /* if extern then do nothing or is a function
950 if (IS_FUNC (sym->type))
953 /* print extra debug info if required */
954 if ((options.debug || sym->level == 0) && !options.nodebug) {
956 cdbSymbol(sym,cdbFile,FALSE,FALSE);
958 if (!sym->level) { /* global */
959 if (IS_STATIC(sym->etype))
960 fprintf(afile,"F%s$",moduleName); /* scope is file */
962 fprintf(afile,"G$"); /* scope is global */
965 /* symbol is local */
966 fprintf(afile,"L%s$",
967 (sym->localof ? sym->localof->name : "-null-"));
968 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
971 /* if is has an absolute address then generate
972 an equate for this no need to allocate space */
973 if (SPEC_ABSA (sym->etype)) {
975 if ((options.debug || sym->level == 0) && !options.nodebug)
976 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
978 fprintf (afile, "%s\t=\t0x%04x\n",
980 SPEC_ADDR (sym->etype));
983 if ((options.debug || sym->level == 0) && !options.nodebug)
984 fprintf(afile,"==.\n");
987 tfprintf(afile, "!labeldef\n", sym->rname);
988 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
995 /*-----------------------------------------------------------------*/
996 /* glue - the final glue that hold the whole thing together */
997 /*-----------------------------------------------------------------*/
1002 FILE *ovrFile = tempfile();
1004 addSetHead(&tmpfileSet,ovrFile);
1005 /* print the global struct definitions */
1007 cdbStructBlock (0,cdbFile);
1010 /* PENDING: this isnt the best place but it will do */
1011 if (port->general.glue_up_main) {
1012 /* create the interrupt vector table */
1013 createInterruptVect (vFile);
1016 addSetHead(&tmpfileSet,vFile);
1018 /* emit code for the all the variables declared */
1020 /* do the overlay segments */
1021 emitOverlay(ovrFile);
1023 /* now put it all together into the assembler file */
1024 /* create the assembler file name */
1026 if (!options.c1mode) {
1027 sprintf (buffer, srcFileName);
1028 strcat (buffer, ".asm");
1031 strcpy(buffer, options.out_name);
1034 if (!(asmFile = fopen (buffer, "w"))) {
1035 werror (E_FILE_OPEN_ERR, buffer);
1039 /* initial comments */
1040 initialComments (asmFile);
1042 /* print module name */
1043 tfprintf(asmFile, "\t!module\n", moduleName);
1044 tfprintf(asmFile, "\t!fileprelude\n");
1046 /* Let the port generate any global directives, etc. */
1047 if (port->genAssemblerPreamble)
1049 port->genAssemblerPreamble(asmFile);
1052 /* print the global variables in this module */
1053 printPublics (asmFile);
1054 if (port->assembler.externGlobal)
1055 printExterns (asmFile);
1057 /* copy the sfr segment */
1058 fprintf (asmFile, "%s", iComments2);
1059 fprintf (asmFile, "; special function registers\n");
1060 fprintf (asmFile, "%s", iComments2);
1061 copyFile (asmFile, sfr->oFile);
1063 /* copy the sbit segment */
1064 fprintf (asmFile, "%s", iComments2);
1065 fprintf (asmFile, "; special function bits \n");
1066 fprintf (asmFile, "%s", iComments2);
1067 copyFile (asmFile, sfrbit->oFile);
1069 /* copy the data segment */
1070 fprintf (asmFile, "%s", iComments2);
1071 fprintf (asmFile, "; internal ram data\n");
1072 fprintf (asmFile, "%s", iComments2);
1073 copyFile (asmFile, data->oFile);
1076 /* create the overlay segments */
1077 fprintf (asmFile, "%s", iComments2);
1078 fprintf (asmFile, "; overlayable items in internal ram \n");
1079 fprintf (asmFile, "%s", iComments2);
1080 copyFile (asmFile, ovrFile);
1082 /* create the stack segment MOF */
1083 if (mainf && mainf->fbody) {
1084 fprintf (asmFile, "%s", iComments2);
1085 fprintf (asmFile, "; Stack segment in internal ram \n");
1086 fprintf (asmFile, "%s", iComments2);
1087 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1088 "__start__stack:\n\t.ds\t1\n\n");
1091 /* create the idata segment */
1092 fprintf (asmFile, "%s", iComments2);
1093 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1094 fprintf (asmFile, "%s", iComments2);
1095 copyFile (asmFile, idata->oFile);
1097 /* copy the bit segment */
1098 fprintf (asmFile, "%s", iComments2);
1099 fprintf (asmFile, "; bit data\n");
1100 fprintf (asmFile, "%s", iComments2);
1101 copyFile (asmFile, bit->oFile);
1103 /* if external stack then reserve space of it */
1104 if (mainf && mainf->fbody && options.useXstack ) {
1105 fprintf (asmFile, "%s", iComments2);
1106 fprintf (asmFile, "; external stack \n");
1107 fprintf (asmFile, "%s", iComments2);
1108 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1109 fprintf (asmFile,"\t.ds 256\n");
1113 /* copy xtern ram data */
1114 fprintf (asmFile, "%s", iComments2);
1115 fprintf (asmFile, "; external ram data\n");
1116 fprintf (asmFile, "%s", iComments2);
1117 copyFile (asmFile, xdata->oFile);
1119 /* copy the interrupt vector table */
1120 if (mainf && mainf->fbody) {
1121 fprintf (asmFile, "%s", iComments2);
1122 fprintf (asmFile, "; interrupt vector \n");
1123 fprintf (asmFile, "%s", iComments2);
1124 copyFile (asmFile, vFile);
1127 /* copy global & static initialisations */
1128 fprintf (asmFile, "%s", iComments2);
1129 fprintf (asmFile, "; global & static initialisations\n");
1130 fprintf (asmFile, "%s", iComments2);
1132 /* Everywhere we generate a reference to the static_name area,
1133 * (which is currently only here), we immediately follow it with a
1134 * definition of the post_static_name area. This guarantees that
1135 * the post_static_name area will immediately follow the static_name
1138 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1139 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1140 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1142 if (mainf && mainf->fbody) {
1143 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1144 /* if external stack is specified then the
1145 higher order byte of the xdatalocation is
1146 going into P2 and the lower order going into
1148 if (options.useXstack) {
1149 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1150 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1151 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1152 (unsigned int)options.xdata_loc & 0xff);
1155 /* initialise the stack pointer */
1156 /* if the user specified a value then use it */
1157 if (options.stack_loc)
1158 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1160 /* no: we have to compute it */
1161 if (!options.stackOnData && maxRegBank <= 3)
1162 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1164 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1166 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1167 fprintf (asmFile,"\tmov\ta,dpl\n");
1168 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1169 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1170 fprintf (asmFile,"__sdcc_init_data:\n");
1173 copyFile (asmFile, statsg->oFile);
1175 if (port->general.glue_up_main && mainf && mainf->fbody)
1177 /* This code is generated in the post-static area.
1178 * This area is guaranteed to follow the static area
1179 * by the ugly shucking and jiving about 20 lines ago.
1181 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1182 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1185 /* copy over code */
1186 fprintf (asmFile, "%s", iComments2);
1187 fprintf (asmFile, "; code\n");
1188 fprintf (asmFile, "%s", iComments2);
1189 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1190 if (mainf && mainf->fbody) {
1192 /* entry point @ start of CSEG */
1193 fprintf (asmFile,"__sdcc_program_startup:\n");
1195 /* put in the call to main */
1196 fprintf(asmFile,"\tlcall\t_main\n");
1197 if (options.mainreturn) {
1199 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1200 fprintf(asmFile,"\tret\n");
1204 fprintf(asmFile,";\treturn from main will lock up\n");
1205 fprintf(asmFile,"\tsjmp .\n");
1208 copyFile (asmFile, code->oFile);
1211 applyToSet(tmpfileSet,closeTmpFiles);
1212 applyToSet(tmpfileNameSet, rmTmpFiles);
1215 /** Creates a temporary file a'la tmpfile which avoids the bugs
1216 in cygwin wrt c:\tmp.
1217 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1219 FILE *tempfile(void)
1221 const char *tmpdir = NULL;
1223 tmpdir = getenv("TMP");
1224 else if (getenv("TEMP"))
1225 tmpdir = getenv("TEMP");
1226 else if (getenv("TMPDIR"))
1227 tmpdir = getenv("TMPDIR");
1229 char *name = tempnam(tmpdir, "sdcc");
1231 FILE *fp = fopen(name, "w+b");
1233 addSetHead(&tmpfileNameSet, name);
1241 char *gc_strdup(const char *s)
1244 ALLOC_ATOMIC(ret, strlen(s)+1);