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!dws\n", val->name);
545 /* PENDING: probably just 3 */
547 /* PENDING: 0x02 or 0x%02x, CDATA? */
549 "\t.byte %s,(%s >> 8),#0x02\n",
550 val->name, val->name);
556 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
559 tfprintf(oFile, "\t.byte %s,%s\n",
560 aopLiteral(val, 0),aopLiteral(val, 1));
563 /* PENDING: 0x02 or 0x%02x, CDATA? */
564 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
565 aopLiteral (val, 0), aopLiteral (val, 1));
573 if (val->sym && val->sym->isstrlit)
574 addSet (&statsg->syms, val->sym);
579 /*-----------------------------------------------------------------*/
580 /* printIvalPtr - generates initial value for pointers */
581 /*-----------------------------------------------------------------*/
582 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
587 if (ilist->type == INIT_DEEP)
588 ilist = ilist->init.deep;
590 /* function pointer */
591 if (IS_FUNC (type->next)) {
592 printIvalFuncPtr (type, ilist, oFile);
596 if (!(val = initPointer (ilist)))
599 /* if character pointer */
600 if (IS_CHAR (type->next))
601 if (printIvalCharPtr (sym, type, val, oFile))
605 if (checkType (type, val->type) != 1)
606 werror (E_INIT_WRONG);
608 /* if val is literal */
609 if (IS_LITERAL (val->etype)) {
610 switch (getSize (type)) {
612 tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
615 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
618 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
619 aopLiteral (val, 0), aopLiteral (val, 1));
625 switch (getSize (type)) {
627 tfprintf (oFile, "\t!dbs\n", val->name);
630 tfprintf (oFile, "\t!dws\n", val->name);
634 fprintf (oFile, "\t.byte %s,(%s >> 8),#0x02\n",
635 val->name, val->name);
640 /*-----------------------------------------------------------------*/
641 /* printIval - generates code for initial value */
642 /*-----------------------------------------------------------------*/
643 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
648 /* if structure then */
649 if (IS_STRUCT (type)) {
650 printIvalStruct (sym, type, ilist, oFile);
654 /* if this is a pointer */
656 printIvalPtr (sym, type, ilist, oFile);
660 /* if this is an array */
661 if (IS_ARRAY (type)) {
662 printIvalArray (sym, type, ilist, oFile);
666 /* if type is SPECIFIER */
667 if (IS_SPEC (type)) {
668 printIvalType (type, ilist, oFile);
673 /*-----------------------------------------------------------------*/
674 /* emitStaticSeg - emitcode for the static segment */
675 /*-----------------------------------------------------------------*/
676 void emitStaticSeg (memmap * map)
680 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
683 /* for all variables in this segment do */
684 for (sym = setFirstItem (map->syms); sym;
685 sym = setNextItem (map->syms)) {
687 /* if it is "extern" then do nothing */
688 if (IS_EXTERN (sym->etype))
691 /* if it is not static add it to the public
693 if (!IS_STATIC (sym->etype))
694 addSetHead (&publics, sym);
696 /* print extra debug info if required */
697 if ((options.debug || sym->level == 0) && !options.nodebug) {
699 cdbSymbol(sym,cdbFile,FALSE,FALSE);
701 if (!sym->level) { /* global */
702 if (IS_STATIC(sym->etype))
703 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
705 fprintf(code->oFile,"G$"); /* scope is global */
708 /* symbol is local */
709 fprintf(code->oFile,"L%s$",
710 (sym->localof ? sym->localof->name : "-null-"));
711 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
714 /* if it has an absolute address */
715 if (SPEC_ABSA (sym->etype)) {
716 if ((options.debug || sym->level == 0) && !options.nodebug)
717 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
719 fprintf (code->oFile, "%s\t=\t0x%04x\n",
721 SPEC_ADDR (sym->etype));
724 if ((options.debug || sym->level == 0) && !options.nodebug)
725 fprintf(code->oFile," == .\n");
727 /* if it has an initial value */
729 fprintf (code->oFile, "%s:\n", sym->rname);
731 resolveIvalSym (sym->ival);
732 printIval (sym, sym->type, sym->ival, code->oFile);
737 fprintf (code->oFile, "%s:\n", sym->rname);
738 /* special case for character strings */
739 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
740 SPEC_CVAL (sym->etype).v_char)
741 printChar (code->oFile,
742 SPEC_CVAL (sym->etype).v_char,
743 strlen(SPEC_CVAL (sym->etype).v_char)+1);
745 tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
751 /*-----------------------------------------------------------------*/
752 /* emitMaps - emits the code for the data portion the code */
753 /*-----------------------------------------------------------------*/
756 /* no special considerations for the following
757 data, idata & bit & xdata */
758 emitRegularMap (data, TRUE, TRUE);
759 emitRegularMap (idata, TRUE,TRUE);
760 emitRegularMap (bit, TRUE,FALSE);
761 emitRegularMap (xdata, TRUE,TRUE);
762 emitRegularMap (sfr, FALSE,FALSE);
763 emitRegularMap (sfrbit, FALSE,FALSE);
764 emitRegularMap (code, TRUE,FALSE);
765 emitStaticSeg (statsg);
768 /*-----------------------------------------------------------------*/
769 /* createInterruptVect - creates the interrupt vector */
770 /*-----------------------------------------------------------------*/
771 void createInterruptVect (FILE * vFile)
774 mainf = newSymbol ("main", 0);
777 /* only if the main function exists */
778 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
779 if (!options.cc_only)
784 /* if the main is only a prototype ie. no body then do nothing */
786 /* if ! compile only then main function should be present */
787 if (!options.cc_only)
792 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
793 fprintf (vFile, "__interrupt_vect:\n");
796 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
798 /* "generic" interrupt table header (if port doesn't specify one).
800 * Look suspiciously like 8051 code to me...
803 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
806 /* now for the other interrupts */
807 for (; i < maxInterrupts; i++) {
809 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
811 fprintf (vFile, "\treti\n\t.ds\t7\n");
818 ";--------------------------------------------------------\n"
819 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
823 ";--------------------------------------------------------\n"};
826 /*-----------------------------------------------------------------*/
827 /* initialComments - puts in some initial comments */
828 /*-----------------------------------------------------------------*/
829 void initialComments (FILE * afile)
833 fprintf (afile, "%s", iComments1);
834 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
835 fprintf (afile, "%s", iComments2);
838 /*-----------------------------------------------------------------*/
839 /* printPublics - generates .global for publics */
840 /*-----------------------------------------------------------------*/
841 void printPublics (FILE * afile)
845 fprintf (afile, "%s", iComments2);
846 fprintf (afile, "; publics variables in this module\n");
847 fprintf (afile, "%s", iComments2);
849 for (sym = setFirstItem (publics); sym;
850 sym = setNextItem (publics))
851 tfprintf(afile, "\t!global\n", sym->rname);
854 /*-----------------------------------------------------------------*/
855 /* emitOverlay - will emit code for the overlay stuff */
856 /*-----------------------------------------------------------------*/
857 static void emitOverlay(FILE *afile)
861 if (!elementsInSet(ovrSetSets))
862 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
864 /* for each of the sets in the overlay segment do */
865 for (ovrset = setFirstItem(ovrSetSets); ovrset;
866 ovrset = setNextItem(ovrSetSets)) {
870 if (elementsInSet(ovrset)) {
871 /* this dummy area is used to fool the assembler
872 otherwise the assembler will append each of these
873 declarations into one chunk and will not overlay
875 fprintf(afile,"\t.area _DUMMY\n");
876 /* output the area informtion */
877 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
880 for (sym = setFirstItem(ovrset); sym;
881 sym = setNextItem(ovrset)) {
883 /* if extern then do nothing */
884 if (IS_EXTERN (sym->etype))
887 /* if allocation required check is needed
888 then check if the symbol really requires
889 allocation only for local variables */
890 if (!IS_AGGREGATE(sym->type) &&
891 !(sym->_isparm && !IS_REGPARM(sym->etype))
892 && !sym->allocreq && sym->level)
895 /* if global variable & not static or extern
896 and addPublics allowed then add it to the public set */
897 if ((sym->_isparm && !IS_REGPARM(sym->etype))
898 && !IS_STATIC (sym->etype))
899 addSetHead (&publics, sym);
901 /* if extern then do nothing or is a function
903 if (IS_FUNC (sym->type))
906 /* print extra debug info if required */
907 if ((options.debug || sym->level == 0) && !options.nodebug) {
909 cdbSymbol(sym,cdbFile,FALSE,FALSE);
911 if (!sym->level) { /* global */
912 if (IS_STATIC(sym->etype))
913 fprintf(afile,"F%s$",moduleName); /* scope is file */
915 fprintf(afile,"G$"); /* scope is global */
918 /* symbol is local */
919 fprintf(afile,"L%s$",
920 (sym->localof ? sym->localof->name : "-null-"));
921 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
924 /* if is has an absolute address then generate
925 an equate for this no need to allocate space */
926 if (SPEC_ABSA (sym->etype)) {
928 if ((options.debug || sym->level == 0) && !options.nodebug)
929 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
931 fprintf (afile, "%s\t=\t0x%04x\n",
933 SPEC_ADDR (sym->etype));
936 if ((options.debug || sym->level == 0) && !options.nodebug)
937 fprintf(afile,"==.\n");
940 tfprintf(afile, "!labeldef\n", sym->rname);
941 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
948 /*-----------------------------------------------------------------*/
949 /* glue - the final glue that hold the whole thing together */
950 /*-----------------------------------------------------------------*/
955 FILE *ovrFile = tempfile();
957 addSetHead(&tmpfileSet,ovrFile);
958 /* print the global struct definitions */
960 cdbStructBlock (0,cdbFile);
963 /* PENDING: this isnt the best place but it will do */
964 if (port->general.glue_up_main) {
965 /* create the interrupt vector table */
966 createInterruptVect (vFile);
969 addSetHead(&tmpfileSet,vFile);
971 /* emit code for the all the variables declared */
973 /* do the overlay segments */
974 emitOverlay(ovrFile);
976 /* now put it all together into the assembler file */
977 /* create the assembler file name */
979 if (!options.c1mode) {
980 sprintf (buffer, srcFileName);
981 strcat (buffer, ".asm");
984 strcpy(buffer, options.out_name);
987 if (!(asmFile = fopen (buffer, "w"))) {
988 werror (E_FILE_OPEN_ERR, buffer);
992 /* initial comments */
993 initialComments (asmFile);
995 /* print module name */
996 tfprintf(asmFile, "\t!module\n", moduleName);
997 tfprintf(asmFile, "\t!fileprelude\n");
999 /* Let the port generate any global directives, etc. */
1000 if (port->genAssemblerPreamble)
1002 port->genAssemblerPreamble(asmFile);
1005 /* print the global variables in this module */
1006 printPublics (asmFile);
1008 /* copy the sfr segment */
1009 fprintf (asmFile, "%s", iComments2);
1010 fprintf (asmFile, "; special function registers\n");
1011 fprintf (asmFile, "%s", iComments2);
1012 copyFile (asmFile, sfr->oFile);
1014 /* copy the sbit segment */
1015 fprintf (asmFile, "%s", iComments2);
1016 fprintf (asmFile, "; special function bits \n");
1017 fprintf (asmFile, "%s", iComments2);
1018 copyFile (asmFile, sfrbit->oFile);
1020 /* copy the data segment */
1021 fprintf (asmFile, "%s", iComments2);
1022 fprintf (asmFile, "; internal ram data\n");
1023 fprintf (asmFile, "%s", iComments2);
1024 copyFile (asmFile, data->oFile);
1027 /* create the overlay segments */
1028 fprintf (asmFile, "%s", iComments2);
1029 fprintf (asmFile, "; overlayable items in internal ram \n");
1030 fprintf (asmFile, "%s", iComments2);
1031 copyFile (asmFile, ovrFile);
1033 /* create the stack segment MOF */
1034 if (mainf && mainf->fbody) {
1035 fprintf (asmFile, "%s", iComments2);
1036 fprintf (asmFile, "; Stack segment in internal ram \n");
1037 fprintf (asmFile, "%s", iComments2);
1038 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1039 "__start__stack:\n\t.ds\t1\n\n");
1042 /* create the idata segment */
1043 fprintf (asmFile, "%s", iComments2);
1044 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1045 fprintf (asmFile, "%s", iComments2);
1046 copyFile (asmFile, idata->oFile);
1048 /* copy the bit segment */
1049 fprintf (asmFile, "%s", iComments2);
1050 fprintf (asmFile, "; bit data\n");
1051 fprintf (asmFile, "%s", iComments2);
1052 copyFile (asmFile, bit->oFile);
1054 /* if external stack then reserve space of it */
1055 if (mainf && mainf->fbody && options.useXstack ) {
1056 fprintf (asmFile, "%s", iComments2);
1057 fprintf (asmFile, "; external stack \n");
1058 fprintf (asmFile, "%s", iComments2);
1059 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1060 fprintf (asmFile,"\t.ds 256\n");
1064 /* copy xtern ram data */
1065 fprintf (asmFile, "%s", iComments2);
1066 fprintf (asmFile, "; external ram data\n");
1067 fprintf (asmFile, "%s", iComments2);
1068 copyFile (asmFile, xdata->oFile);
1070 /* copy the interrupt vector table */
1071 if (mainf && mainf->fbody) {
1072 fprintf (asmFile, "%s", iComments2);
1073 fprintf (asmFile, "; interrupt vector \n");
1074 fprintf (asmFile, "%s", iComments2);
1075 copyFile (asmFile, vFile);
1078 /* copy global & static initialisations */
1079 fprintf (asmFile, "%s", iComments2);
1080 fprintf (asmFile, "; global & static initialisations\n");
1081 fprintf (asmFile, "%s", iComments2);
1083 /* Everywhere we generate a reference to the static_name area,
1084 * (which is currently only here), we immediately follow it with a
1085 * definition of the post_static_name area. This guarantees that
1086 * the post_static_name area will immediately follow the static_name
1089 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1090 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1091 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1093 if (mainf && mainf->fbody) {
1094 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1095 /* if external stack is specified then the
1096 higher order byte of the xdatalocation is
1097 going into P2 and the lower order going into
1099 if (options.useXstack) {
1100 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1101 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1102 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1103 (unsigned int)options.xdata_loc & 0xff);
1106 /* initialise the stack pointer */
1107 /* if the user specified a value then use it */
1108 if (options.stack_loc)
1109 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1111 /* no: we have to compute it */
1112 if (!options.stackOnData && maxRegBank <= 3)
1113 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1115 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1117 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1118 fprintf (asmFile,"\tmov\ta,dpl\n");
1119 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1120 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1121 fprintf (asmFile,"__sdcc_init_data:\n");
1124 copyFile (asmFile, statsg->oFile);
1126 if (port->general.glue_up_main && mainf && mainf->fbody)
1128 /* This code is generated in the post-static area.
1129 * This area is guaranteed to follow the static area
1130 * by the ugly shucking and jiving about 20 lines ago.
1132 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1133 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1136 /* copy over code */
1137 fprintf (asmFile, "%s", iComments2);
1138 fprintf (asmFile, "; code\n");
1139 fprintf (asmFile, "%s", iComments2);
1140 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1141 if (mainf && mainf->fbody) {
1143 /* entry point @ start of CSEG */
1144 fprintf (asmFile,"__sdcc_program_startup:\n");
1146 /* put in the call to main */
1147 fprintf(asmFile,"\tlcall\t_main\n");
1148 if (options.mainreturn) {
1150 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1151 fprintf(asmFile,"\tret\n");
1155 fprintf(asmFile,";\treturn from main will lock up\n");
1156 fprintf(asmFile,"\tsjmp .\n");
1159 copyFile (asmFile, code->oFile);
1162 applyToSet(tmpfileSet,closeTmpFiles);
1163 applyToSet(tmpfileNameSet, rmTmpFiles);
1166 /** Creates a temporary file a'la tmpfile which avoids the bugs
1167 in cygwin wrt c:\tmp.
1168 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1170 FILE *tempfile(void)
1172 const char *tmpdir = NULL;
1174 tmpdir = getenv("TMP");
1175 else if (getenv("TEMP"))
1176 tmpdir = getenv("TEMP");
1177 else if (getenv("TMPDIR"))
1178 tmpdir = getenv("TMPDIR");
1180 char *name = tempnam(tmpdir, "sdcc");
1182 FILE *fp = fopen(name, "w+b");
1184 addSetHead(&tmpfileNameSet, name);
1192 char *gc_strdup(const char *s)
1195 ALLOC_ATOMIC(ret, strlen(s)+1);