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 */
35 /* TODO: this should be configurable (DS803C90 uses more than 6) */
36 int maxInterrupts = 6;
37 extern int maxRegBank ;
39 extern char *VersionString;
40 extern FILE *codeOutFile;
41 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
42 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
43 /*-----------------------------------------------------------------*/
44 /* closeTmpFiles - closes all tmp files created by the compiler */
45 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
46 /*-----------------------------------------------------------------*/
47 DEFSETFUNC(closeTmpFiles)
57 /*-----------------------------------------------------------------*/
58 /* rmTmpFiles - closes all tmp files created by the compiler */
59 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
60 /*-----------------------------------------------------------------*/
61 DEFSETFUNC(rmTmpFiles)
72 /*-----------------------------------------------------------------*/
73 /* copyFile - copies source file to destination file */
74 /*-----------------------------------------------------------------*/
75 void copyFile (FILE * dest, FILE * src)
81 if ((ch = fgetc (src)) != EOF)
85 char *aopLiteralLong(value *val, int offset, int size)
93 /* if it is a float then it gets tricky */
94 /* otherwise it is fairly simple */
95 if (!IS_FLOAT(val->type)) {
96 unsigned long v = floatFromVal(val);
101 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
104 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
107 /* Hmm. Too big for now. */
110 ALLOC_ATOMIC(rs,strlen(buffer)+1);
111 return strcpy (rs,buffer);
114 /* PENDING: For now size must be 1 */
117 /* it is type float */
118 fl.f = (float) floatFromVal(val);
120 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
122 tsprintf(buffer, "!immedbyte", fl.c[offset]);
124 ALLOC_ATOMIC(rs,strlen(buffer)+1);
125 return strcpy (rs,buffer);
128 /*-----------------------------------------------------------------*/
129 /* aopLiteral - string from a literal value */
130 /*-----------------------------------------------------------------*/
131 char *aopLiteral (value *val, int offset)
133 return aopLiteralLong(val, offset, 1);
136 /*-----------------------------------------------------------------*/
137 /* emitRegularMap - emit code for maps with no special cases */
138 /*-----------------------------------------------------------------*/
139 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
144 /* PENDING: special case here - should remove */
145 if (!strcmp(map->sname, DATA_NAME))
146 tfprintf(map->oFile, "\t!areadata\n", map->sname);
148 tfprintf(map->oFile, "\t!area\n", map->sname);
151 /* print the area name */
152 for (sym = setFirstItem (map->syms); sym;
153 sym = setNextItem (map->syms)) {
155 /* if extern then do nothing */
156 if (IS_EXTERN (sym->etype))
159 /* if allocation required check is needed
160 then check if the symbol really requires
161 allocation only for local variables */
162 if (arFlag && !IS_AGGREGATE(sym->type) &&
163 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
164 !sym->allocreq && sym->level)
167 /* if global variable & not static or extern
168 and addPublics allowed then add it to the public set */
169 if ((sym->level == 0 ||
170 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
172 !IS_STATIC (sym->etype))
173 addSetHead (&publics, sym);
175 /* if extern then do nothing or is a function
177 if (IS_FUNC (sym->type))
180 /* print extra debug info if required */
181 if ((options.debug || sym->level == 0) && !options.nodebug) {
183 cdbSymbol(sym,cdbFile,FALSE,FALSE);
185 if (!sym->level) /* global */
186 if (IS_STATIC(sym->etype))
187 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
189 fprintf(map->oFile,"G$"); /* scope is global */
191 /* symbol is local */
192 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
193 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
196 /* if is has an absolute address then generate
197 an equate for this no need to allocate space */
198 if (SPEC_ABSA (sym->etype)) {
199 if ((options.debug || sym->level == 0) && !options.nodebug)
200 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
202 fprintf (map->oFile, "%s\t=\t0x%04x\n",
204 SPEC_ADDR (sym->etype));
208 if ((options.debug || sym->level == 0) && !options.nodebug)
209 fprintf(map->oFile,"==.\n");
210 tfprintf(map->oFile, "!labeldef\n", sym->rname);
211 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
214 /* if it has a initial value then do it only if
215 it is a global variable */
216 if (sym->ival && sym->level == 0) {
219 if (IS_AGGREGATE (sym->type))
220 ival = initAggregates (sym, sym->ival, NULL);
222 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
223 decorateType (resolveSymbols (list2expr (sym->ival))));
224 codeOutFile = statsg->oFile;
225 eBBlockFromiCode (iCodeFromAst (ival));
232 /*-----------------------------------------------------------------*/
233 /* initPointer - pointer initialization code massaging */
234 /*-----------------------------------------------------------------*/
235 value *initPointer (initList *ilist)
238 ast *expr = list2expr(ilist);
243 /* try it the oldway first */
244 if ((val = constExprValue(expr,FALSE)))
247 /* no then we have to do these cludgy checks */
248 /* pointers can be initialized with address of
249 a variable or address of an array element */
250 if (IS_AST_OP(expr) && expr->opval.op == '&') {
251 /* address of symbol */
252 if (IS_AST_SYM_VALUE(expr->left)) {
253 val = copyValue(AST_VALUE(expr->left));
254 val->type = newLink();
255 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
256 DCL_TYPE(val->type) = CPOINTER ;
257 DCL_PTR_CONST(val->type) = port->mem.code_ro;
260 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
261 DCL_TYPE(val->type) = FPOINTER;
263 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
264 DCL_TYPE(val->type) = PPOINTER ;
266 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
267 DCL_TYPE(val->type) = IPOINTER ;
269 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
270 DCL_TYPE(val->type) = EEPPOINTER ;
272 DCL_TYPE(val->type) = POINTER ;
273 val->type->next = expr->left->ftype;
274 val->etype = getSpec(val->type);
278 /* if address of indexed array */
279 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
280 return valForArray(expr->left);
282 /* if address of structure element then
284 if (IS_AST_OP(expr->left) &&
285 expr->left->opval.op == '.' ) {
286 return valForStructElem(expr->left->left,
291 (&some_struct)->element */
292 if (IS_AST_OP(expr->left) &&
293 expr->left->opval.op == PTR_OP &&
294 IS_ADDRESS_OF_OP(expr->left->left))
295 return valForStructElem(expr->left->left->left,
300 werror(E_INIT_WRONG);
305 /*-----------------------------------------------------------------*/
306 /* printChar - formats and prints a characater string with DB */
307 /*-----------------------------------------------------------------*/
308 void printChar (FILE * ofile, char *s, int plen)
311 int len = strlen (s);
316 while (len && pplen < plen) {
318 while (i && *s && pplen < plen) {
319 if (*s < ' ' || *s == '\"') {
322 tfprintf(ofile, "\t!ascii\n", buf);
323 tfprintf(ofile, "\t!db\n", *s);
336 tfprintf(ofile, "\t!ascii\n", buf);
344 tfprintf(ofile, "\t!db\n", 0);
347 /*-----------------------------------------------------------------*/
348 /* printIvalType - generates ival for int/char */
349 /*-----------------------------------------------------------------*/
350 void printIvalType (link * type, initList * ilist, FILE * oFile)
354 /* if initList is deep */
355 if (ilist->type == INIT_DEEP)
356 ilist = ilist->init.deep;
358 val = list2val (ilist);
359 switch (getSize (type)) {
362 tfprintf(oFile, "\t!db\n", 0);
364 tfprintf(oFile, "\t!dbs\n",
365 aopLiteral (val, 0));
369 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
373 tfprintf (oFile, "\t!dw\n", 0);
374 tfprintf (oFile, "\t!dw\n", 0);
377 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
378 aopLiteral (val, 0), aopLiteral (val, 1),
379 aopLiteral (val, 2), aopLiteral (val, 3));
385 /*-----------------------------------------------------------------*/
386 /* printIvalStruct - generates initial value for structures */
387 /*-----------------------------------------------------------------*/
388 void printIvalStruct (symbol * sym,link * type,
389 initList * ilist, FILE * oFile)
394 sflds = SPEC_STRUCT (type)->fields;
395 if (ilist->type != INIT_DEEP) {
396 werror (E_INIT_STRUCT, sym->name);
400 iloop = ilist->init.deep;
402 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
403 printIval (sflds, sflds->type, iloop, oFile);
408 /*-----------------------------------------------------------------*/
409 /* printIvalChar - generates initital value for character array */
410 /*-----------------------------------------------------------------*/
411 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
418 val = list2val (ilist);
419 /* if the value is a character string */
420 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
421 if (!DCL_ELEM (type))
422 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
424 /* if size mismatch */
425 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
426 /* werror (E_ARRAY_BOUND); */
428 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
430 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
432 tfprintf (oFile, "\t!db\n", 0);
440 printChar (oFile, s,strlen(s)+1);
444 /*-----------------------------------------------------------------*/
445 /* printIvalArray - generates code for array initialization */
446 /*-----------------------------------------------------------------*/
447 void printIvalArray (symbol * sym, link * type, initList * ilist,
451 int lcnt = 0, size = 0;
453 /* take care of the special case */
454 /* array of characters can be init */
456 if (IS_CHAR (type->next))
457 if (printIvalChar (type,
458 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
459 oFile, SPEC_CVAL (sym->etype).v_char))
462 /* not the special case */
463 if (ilist->type != INIT_DEEP) {
464 werror (E_INIT_STRUCT, sym->name);
468 iloop = ilist->init.deep;
469 lcnt = DCL_ELEM (type);
473 printIval (sym, type->next, iloop, oFile);
474 iloop = (iloop ? iloop->next : NULL);
477 /* if not array limits given & we */
478 /* are out of initialisers then */
479 if (!DCL_ELEM (type) && !iloop)
482 /* no of elements given and we */
483 /* have generated for all of them */
488 /* if we have not been given a size */
489 if (!DCL_ELEM (type))
490 DCL_ELEM (type) = size;
495 /*-----------------------------------------------------------------*/
496 /* printIvalFuncPtr - generate initial value for function pointers */
497 /*-----------------------------------------------------------------*/
498 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
503 val = list2val (ilist);
504 /* check the types */
505 if ((dLvl = checkType (val->type, type->next)) <= 0) {
506 tfprintf(oFile, "\t!dw\n", 0);
510 /* now generate the name */
512 if (IS_LITERAL (val->etype))
513 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
515 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name,val->name);
518 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->sym->rname,val->sym->rname);
523 /*-----------------------------------------------------------------*/
524 /* printIvalCharPtr - generates initial values for character pointers */
525 /*-----------------------------------------------------------------*/
526 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
530 /* PENDING: this is _very_ mcs51 specific, including a magic
532 It's also endin specific.
534 size = getSize (type);
536 if (val->name && strlen(val->name)) {
540 "\t!dbs\n", val->name) ;
543 tfprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
545 /* PENDING: probably just 3 */
547 /* PENDING: 0x02 or 0x%02x, CDATA? */
549 "\t.byte %s,(%s >> 8),#0x%02x\n",
550 val->name, val->name, (IS_PTR(val->type) ? DCL_TYPE(val->type) :
551 PTR_TYPE(SPEC_OCLS(val->etype))));
557 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
560 tfprintf(oFile, "\t.byte %s,%s\n",
561 aopLiteral(val, 0),aopLiteral(val, 1));
564 /* PENDING: 0x02 or 0x%02x, CDATA? */
565 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
566 aopLiteral (val, 0), aopLiteral (val, 1));
574 if (val->sym && val->sym->isstrlit)
575 addSet (&statsg->syms, val->sym);
580 /*-----------------------------------------------------------------*/
581 /* printIvalPtr - generates initial value for pointers */
582 /*-----------------------------------------------------------------*/
583 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
588 if (ilist->type == INIT_DEEP)
589 ilist = ilist->init.deep;
591 /* function pointer */
592 if (IS_FUNC (type->next)) {
593 printIvalFuncPtr (type, ilist, oFile);
597 if (!(val = initPointer (ilist)))
600 /* if character pointer */
601 if (IS_CHAR (type->next))
602 if (printIvalCharPtr (sym, type, val, oFile))
606 if (checkType (type, val->type) != 1)
607 werror (E_INIT_WRONG);
609 /* if val is literal */
610 if (IS_LITERAL (val->etype)) {
611 switch (getSize (type)) {
613 tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
616 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
619 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
620 aopLiteral (val, 0), aopLiteral (val, 1));
626 switch (getSize (type)) {
628 tfprintf (oFile, "\t!dbs\n", val->name);
631 tfprintf (oFile, "\t!dws\n", val->name);
635 fprintf (oFile, "\t.byte %s,(%s >> 8),#0x%02x\n",
636 val->name, val->name,(IS_PTR(val->type) ? DCL_TYPE(val->type) :
637 PTR_TYPE(SPEC_OCLS(val->etype))));
642 /*-----------------------------------------------------------------*/
643 /* printIval - generates code for initial value */
644 /*-----------------------------------------------------------------*/
645 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
650 /* if structure then */
651 if (IS_STRUCT (type)) {
652 printIvalStruct (sym, type, ilist, oFile);
656 /* if this is a pointer */
658 printIvalPtr (sym, type, ilist, oFile);
662 /* if this is an array */
663 if (IS_ARRAY (type)) {
664 printIvalArray (sym, type, ilist, oFile);
668 /* if type is SPECIFIER */
669 if (IS_SPEC (type)) {
670 printIvalType (type, ilist, oFile);
675 /*-----------------------------------------------------------------*/
676 /* emitStaticSeg - emitcode for the static segment */
677 /*-----------------------------------------------------------------*/
678 void emitStaticSeg (memmap * map)
682 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
685 /* for all variables in this segment do */
686 for (sym = setFirstItem (map->syms); sym;
687 sym = setNextItem (map->syms)) {
689 /* if it is "extern" then do nothing */
690 if (IS_EXTERN (sym->etype))
693 /* if it is not static add it to the public
695 if (!IS_STATIC (sym->etype))
696 addSetHead (&publics, sym);
698 /* print extra debug info if required */
699 if ((options.debug || sym->level == 0) && !options.nodebug) {
701 cdbSymbol(sym,cdbFile,FALSE,FALSE);
703 if (!sym->level) { /* global */
704 if (IS_STATIC(sym->etype))
705 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
707 fprintf(code->oFile,"G$"); /* scope is global */
710 /* symbol is local */
711 fprintf(code->oFile,"L%s$",
712 (sym->localof ? sym->localof->name : "-null-"));
713 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
716 /* if it has an absolute address */
717 if (SPEC_ABSA (sym->etype)) {
718 if ((options.debug || sym->level == 0) && !options.nodebug)
719 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
721 fprintf (code->oFile, "%s\t=\t0x%04x\n",
723 SPEC_ADDR (sym->etype));
726 if ((options.debug || sym->level == 0) && !options.nodebug)
727 fprintf(code->oFile," == .\n");
729 /* if it has an initial value */
731 fprintf (code->oFile, "%s:\n", sym->rname);
733 resolveIvalSym (sym->ival);
734 printIval (sym, sym->type, sym->ival, code->oFile);
739 fprintf (code->oFile, "%s:\n", sym->rname);
740 /* special case for character strings */
741 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
742 SPEC_CVAL (sym->etype).v_char)
743 printChar (code->oFile,
744 SPEC_CVAL (sym->etype).v_char,
745 strlen(SPEC_CVAL (sym->etype).v_char)+1);
747 tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
753 /*-----------------------------------------------------------------*/
754 /* emitMaps - emits the code for the data portion the code */
755 /*-----------------------------------------------------------------*/
758 /* no special considerations for the following
759 data, idata & bit & xdata */
760 emitRegularMap (data, TRUE, TRUE);
761 emitRegularMap (idata, TRUE,TRUE);
762 emitRegularMap (bit, TRUE,FALSE);
763 emitRegularMap (xdata, TRUE,TRUE);
764 emitRegularMap (sfr, FALSE,FALSE);
765 emitRegularMap (sfrbit, FALSE,FALSE);
766 emitRegularMap (code, TRUE,FALSE);
767 emitStaticSeg (statsg);
770 /*-----------------------------------------------------------------*/
771 /* createInterruptVect - creates the interrupt vector */
772 /*-----------------------------------------------------------------*/
773 void createInterruptVect (FILE * vFile)
776 mainf = newSymbol ("main", 0);
779 /* only if the main function exists */
780 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
781 if (!options.cc_only)
786 /* if the main is only a prototype ie. no body then do nothing */
788 /* if ! compile only then main function should be present */
789 if (!options.cc_only)
794 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
795 fprintf (vFile, "__interrupt_vect:\n");
798 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
800 /* "generic" interrupt table header (if port doesn't specify one).
802 * Look suspiciously like 8051 code to me...
805 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
808 /* now for the other interrupts */
809 for (; i < maxInterrupts; i++) {
811 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
813 fprintf (vFile, "\treti\n\t.ds\t7\n");
820 ";--------------------------------------------------------\n"
821 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
825 ";--------------------------------------------------------\n"};
828 /*-----------------------------------------------------------------*/
829 /* initialComments - puts in some initial comments */
830 /*-----------------------------------------------------------------*/
831 void initialComments (FILE * afile)
835 fprintf (afile, "%s", iComments1);
836 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
837 fprintf (afile, "%s", iComments2);
840 /*-----------------------------------------------------------------*/
841 /* printPublics - generates .global for publics */
842 /*-----------------------------------------------------------------*/
843 void printPublics (FILE * afile)
847 fprintf (afile, "%s", iComments2);
848 fprintf (afile, "; publics variables in this module\n");
849 fprintf (afile, "%s", iComments2);
851 for (sym = setFirstItem (publics); sym;
852 sym = setNextItem (publics))
853 tfprintf(afile, "\t!global\n", sym->rname);
856 /*-----------------------------------------------------------------*/
857 /* emitOverlay - will emit code for the overlay stuff */
858 /*-----------------------------------------------------------------*/
859 static void emitOverlay(FILE *afile)
863 if (!elementsInSet(ovrSetSets))
864 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
866 /* for each of the sets in the overlay segment do */
867 for (ovrset = setFirstItem(ovrSetSets); ovrset;
868 ovrset = setNextItem(ovrSetSets)) {
872 if (elementsInSet(ovrset)) {
873 /* this dummy area is used to fool the assembler
874 otherwise the assembler will append each of these
875 declarations into one chunk and will not overlay
877 fprintf(afile,"\t.area _DUMMY\n");
878 /* output the area informtion */
879 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
882 for (sym = setFirstItem(ovrset); sym;
883 sym = setNextItem(ovrset)) {
885 /* if extern then do nothing */
886 if (IS_EXTERN (sym->etype))
889 /* if allocation required check is needed
890 then check if the symbol really requires
891 allocation only for local variables */
892 if (!IS_AGGREGATE(sym->type) &&
893 !(sym->_isparm && !IS_REGPARM(sym->etype))
894 && !sym->allocreq && sym->level)
897 /* if global variable & not static or extern
898 and addPublics allowed then add it to the public set */
899 if ((sym->_isparm && !IS_REGPARM(sym->etype))
900 && !IS_STATIC (sym->etype))
901 addSetHead (&publics, sym);
903 /* if extern then do nothing or is a function
905 if (IS_FUNC (sym->type))
908 /* print extra debug info if required */
909 if ((options.debug || sym->level == 0) && !options.nodebug) {
911 cdbSymbol(sym,cdbFile,FALSE,FALSE);
913 if (!sym->level) { /* global */
914 if (IS_STATIC(sym->etype))
915 fprintf(afile,"F%s$",moduleName); /* scope is file */
917 fprintf(afile,"G$"); /* scope is global */
920 /* symbol is local */
921 fprintf(afile,"L%s$",
922 (sym->localof ? sym->localof->name : "-null-"));
923 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
926 /* if is has an absolute address then generate
927 an equate for this no need to allocate space */
928 if (SPEC_ABSA (sym->etype)) {
930 if ((options.debug || sym->level == 0) && !options.nodebug)
931 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
933 fprintf (afile, "%s\t=\t0x%04x\n",
935 SPEC_ADDR (sym->etype));
938 if ((options.debug || sym->level == 0) && !options.nodebug)
939 fprintf(afile,"==.\n");
942 tfprintf(afile, "!labeldef\n", sym->rname);
943 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
950 /*-----------------------------------------------------------------*/
951 /* glue - the final glue that hold the whole thing together */
952 /*-----------------------------------------------------------------*/
957 FILE *ovrFile = tempfile();
959 addSetHead(&tmpfileSet,ovrFile);
960 /* print the global struct definitions */
962 cdbStructBlock (0,cdbFile);
965 /* PENDING: this isnt the best place but it will do */
966 if (port->general.glue_up_main) {
967 /* create the interrupt vector table */
968 createInterruptVect (vFile);
971 addSetHead(&tmpfileSet,vFile);
973 /* emit code for the all the variables declared */
975 /* do the overlay segments */
976 emitOverlay(ovrFile);
978 /* now put it all together into the assembler file */
979 /* create the assembler file name */
981 if (!options.c1mode) {
982 sprintf (buffer, srcFileName);
983 strcat (buffer, ".asm");
986 strcpy(buffer, options.out_name);
989 if (!(asmFile = fopen (buffer, "w"))) {
990 werror (E_FILE_OPEN_ERR, buffer);
994 /* initial comments */
995 initialComments (asmFile);
997 /* print module name */
998 tfprintf(asmFile, "\t!module\n", moduleName);
999 tfprintf(asmFile, "\t!fileprelude\n");
1001 /* Let the port generate any global directives, etc. */
1002 if (port->genAssemblerPreamble)
1004 port->genAssemblerPreamble(asmFile);
1007 /* print the global variables in this module */
1008 printPublics (asmFile);
1010 /* copy the sfr segment */
1011 fprintf (asmFile, "%s", iComments2);
1012 fprintf (asmFile, "; special function registers\n");
1013 fprintf (asmFile, "%s", iComments2);
1014 copyFile (asmFile, sfr->oFile);
1016 /* copy the sbit segment */
1017 fprintf (asmFile, "%s", iComments2);
1018 fprintf (asmFile, "; special function bits \n");
1019 fprintf (asmFile, "%s", iComments2);
1020 copyFile (asmFile, sfrbit->oFile);
1022 /* copy the data segment */
1023 fprintf (asmFile, "%s", iComments2);
1024 fprintf (asmFile, "; internal ram data\n");
1025 fprintf (asmFile, "%s", iComments2);
1026 copyFile (asmFile, data->oFile);
1029 /* create the overlay segments */
1030 fprintf (asmFile, "%s", iComments2);
1031 fprintf (asmFile, "; overlayable items in internal ram \n");
1032 fprintf (asmFile, "%s", iComments2);
1033 copyFile (asmFile, ovrFile);
1035 /* create the stack segment MOF */
1036 if (mainf && mainf->fbody) {
1037 fprintf (asmFile, "%s", iComments2);
1038 fprintf (asmFile, "; Stack segment in internal ram \n");
1039 fprintf (asmFile, "%s", iComments2);
1040 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1041 "__start__stack:\n\t.ds\t1\n\n");
1044 /* create the idata segment */
1045 fprintf (asmFile, "%s", iComments2);
1046 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1047 fprintf (asmFile, "%s", iComments2);
1048 copyFile (asmFile, idata->oFile);
1050 /* copy the bit segment */
1051 fprintf (asmFile, "%s", iComments2);
1052 fprintf (asmFile, "; bit data\n");
1053 fprintf (asmFile, "%s", iComments2);
1054 copyFile (asmFile, bit->oFile);
1056 /* if external stack then reserve space of it */
1057 if (mainf && mainf->fbody && options.useXstack ) {
1058 fprintf (asmFile, "%s", iComments2);
1059 fprintf (asmFile, "; external stack \n");
1060 fprintf (asmFile, "%s", iComments2);
1061 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1062 fprintf (asmFile,"\t.ds 256\n");
1066 /* copy xtern ram data */
1067 fprintf (asmFile, "%s", iComments2);
1068 fprintf (asmFile, "; external ram data\n");
1069 fprintf (asmFile, "%s", iComments2);
1070 copyFile (asmFile, xdata->oFile);
1072 /* copy the interrupt vector table */
1073 if (mainf && mainf->fbody) {
1074 fprintf (asmFile, "%s", iComments2);
1075 fprintf (asmFile, "; interrupt vector \n");
1076 fprintf (asmFile, "%s", iComments2);
1077 copyFile (asmFile, vFile);
1080 /* copy global & static initialisations */
1081 fprintf (asmFile, "%s", iComments2);
1082 fprintf (asmFile, "; global & static initialisations\n");
1083 fprintf (asmFile, "%s", iComments2);
1085 /* Everywhere we generate a reference to the static_name area,
1086 * (which is currently only here), we immediately follow it with a
1087 * definition of the post_static_name area. This guarantees that
1088 * the post_static_name area will immediately follow the static_name
1091 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1092 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1093 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1095 if (mainf && mainf->fbody) {
1096 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1097 /* if external stack is specified then the
1098 higher order byte of the xdatalocation is
1099 going into P2 and the lower order going into
1101 if (options.useXstack) {
1102 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1103 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1104 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1105 (unsigned int)options.xdata_loc & 0xff);
1108 /* initialise the stack pointer */
1109 /* if the user specified a value then use it */
1110 if (options.stack_loc)
1111 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1113 /* no: we have to compute it */
1114 if (!options.stackOnData && maxRegBank <= 3)
1115 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1117 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1119 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1120 fprintf (asmFile,"\tmov\ta,dpl\n");
1121 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1122 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1123 fprintf (asmFile,"__sdcc_init_data:\n");
1126 copyFile (asmFile, statsg->oFile);
1128 if (port->general.glue_up_main && mainf && mainf->fbody)
1130 /* This code is generated in the post-static area.
1131 * This area is guaranteed to follow the static area
1132 * by the ugly shucking and jiving about 20 lines ago.
1134 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1135 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1138 /* copy over code */
1139 fprintf (asmFile, "%s", iComments2);
1140 fprintf (asmFile, "; code\n");
1141 fprintf (asmFile, "%s", iComments2);
1142 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1143 if (mainf && mainf->fbody) {
1145 /* entry point @ start of CSEG */
1146 fprintf (asmFile,"__sdcc_program_startup:\n");
1148 /* put in the call to main */
1149 fprintf(asmFile,"\tlcall\t_main\n");
1150 if (options.mainreturn) {
1152 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1153 fprintf(asmFile,"\tret\n");
1157 fprintf(asmFile,";\treturn from main will lock up\n");
1158 fprintf(asmFile,"\tsjmp .\n");
1161 copyFile (asmFile, code->oFile);
1164 applyToSet(tmpfileSet,closeTmpFiles);
1165 applyToSet(tmpfileNameSet, rmTmpFiles);
1168 /** Creates a temporary file a'la tmpfile which avoids the bugs
1169 in cygwin wrt c:\tmp.
1170 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1172 FILE *tempfile(void)
1174 const char *tmpdir = NULL;
1176 tmpdir = getenv("TMP");
1177 else if (getenv("TEMP"))
1178 tmpdir = getenv("TEMP");
1179 else if (getenv("TMPDIR"))
1180 tmpdir = getenv("TMPDIR");
1182 char *name = tempnam(tmpdir, "sdcc");
1184 FILE *fp = fopen(name, "w+b");
1186 addSetHead(&tmpfileNameSet, name);
1194 char *gc_strdup(const char *s)
1197 ALLOC_ATOMIC(ret, strlen(s)+1);