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, CODE_NAME))
148 tfprintf(map->oFile, "\t!areacode\n", map->sname);
149 else if (!strcmp(map->sname, DATA_NAME))
150 tfprintf(map->oFile, "\t!areadata\n", map->sname);
151 else if (!strcmp(map->sname, HOME_NAME))
152 tfprintf(map->oFile, "\t!areahome\n", map->sname);
154 tfprintf(map->oFile, "\t!area\n", map->sname);
157 /* print the area name */
158 for (sym = setFirstItem (map->syms); sym;
159 sym = setNextItem (map->syms)) {
161 /* if extern then add it into the extern list */
162 if (IS_EXTERN (sym->etype)) {
163 addSetHead (&externs, sym);
167 /* if allocation required check is needed
168 then check if the symbol really requires
169 allocation only for local variables */
170 if (arFlag && !IS_AGGREGATE(sym->type) &&
171 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
172 !sym->allocreq && sym->level)
175 /* if global variable & not static or extern
176 and addPublics allowed then add it to the public set */
177 if ((sym->level == 0 ||
178 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
180 !IS_STATIC (sym->etype))
181 addSetHead (&publics, sym);
183 /* if extern then do nothing or is a function
185 if (IS_FUNC (sym->type))
188 /* print extra debug info if required */
189 if ((options.debug || sym->level == 0) && !options.nodebug) {
191 cdbSymbol(sym,cdbFile,FALSE,FALSE);
193 if (!sym->level) /* global */
194 if (IS_STATIC(sym->etype))
195 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
197 fprintf(map->oFile,"G$"); /* scope is global */
199 /* symbol is local */
200 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
201 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
204 /* if is has an absolute address then generate
205 an equate for this no need to allocate space */
206 if (SPEC_ABSA (sym->etype)) {
207 if ((options.debug || sym->level == 0) && !options.nodebug)
208 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
210 fprintf (map->oFile, "%s\t=\t0x%04x\n",
212 SPEC_ADDR (sym->etype));
216 if ((options.debug || sym->level == 0) && !options.nodebug)
217 fprintf(map->oFile,"==.\n");
218 if (IS_STATIC(sym->etype))
219 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
221 tfprintf(map->oFile, "!labeldef\n", sym->rname);
222 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
225 /* if it has a initial value then do it only if
226 it is a global variable */
227 if (sym->ival && sym->level == 0) {
230 if (IS_AGGREGATE (sym->type))
231 ival = initAggregates (sym, sym->ival, NULL);
233 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
234 decorateType (resolveSymbols (list2expr (sym->ival))));
235 codeOutFile = statsg->oFile;
237 eBBlockFromiCode (iCodeFromAst (ival));
245 /*-----------------------------------------------------------------*/
246 /* initPointer - pointer initialization code massaging */
247 /*-----------------------------------------------------------------*/
248 value *initPointer (initList *ilist)
251 ast *expr = list2expr(ilist);
256 /* try it the oldway first */
257 if ((val = constExprValue(expr,FALSE)))
260 /* no then we have to do these cludgy checks */
261 /* pointers can be initialized with address of
262 a variable or address of an array element */
263 if (IS_AST_OP(expr) && expr->opval.op == '&') {
264 /* address of symbol */
265 if (IS_AST_SYM_VALUE(expr->left)) {
266 val = copyValue(AST_VALUE(expr->left));
267 val->type = newLink();
268 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
269 DCL_TYPE(val->type) = CPOINTER ;
270 DCL_PTR_CONST(val->type) = port->mem.code_ro;
273 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
274 DCL_TYPE(val->type) = FPOINTER;
276 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
277 DCL_TYPE(val->type) = PPOINTER ;
279 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
280 DCL_TYPE(val->type) = IPOINTER ;
282 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
283 DCL_TYPE(val->type) = EEPPOINTER ;
285 DCL_TYPE(val->type) = POINTER ;
286 val->type->next = expr->left->ftype;
287 val->etype = getSpec(val->type);
291 /* if address of indexed array */
292 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
293 return valForArray(expr->left);
295 /* if address of structure element then
297 if (IS_AST_OP(expr->left) &&
298 expr->left->opval.op == '.' ) {
299 return valForStructElem(expr->left->left,
304 (&some_struct)->element */
305 if (IS_AST_OP(expr->left) &&
306 expr->left->opval.op == PTR_OP &&
307 IS_ADDRESS_OF_OP(expr->left->left))
308 return valForStructElem(expr->left->left->left,
312 /* case 3. (((char *) &a) +/- constant) */
313 if (IS_AST_OP(expr) &&
314 (expr->opval.op == '+' || expr->opval.op == '-') &&
315 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
316 IS_AST_OP(expr->left->right) &&
317 expr->left->right->opval.op == '&' &&
318 IS_AST_LIT_VALUE(expr->right)) {
320 return valForCastAggr(expr->left->right->left,
321 expr->left->left->opval.lnk,
322 expr->right,expr->opval.op);
327 werror(E_INIT_WRONG);
332 /*-----------------------------------------------------------------*/
333 /* printChar - formats and prints a characater string with DB */
334 /*-----------------------------------------------------------------*/
335 void printChar (FILE * ofile, char *s, int plen)
338 int len = strlen (s);
343 while (len && pplen < plen) {
345 while (i && *s && pplen < plen) {
346 if (*s < ' ' || *s == '\"') {
349 tfprintf(ofile, "\t!ascii\n", buf);
350 tfprintf(ofile, "\t!db !constbyte\n", *s);
363 tfprintf(ofile, "\t!ascii\n", buf);
372 tfprintf(ofile, "\t!db !constbyte\n", 0);
375 /*-----------------------------------------------------------------*/
376 /* printIvalType - generates ival for int/char */
377 /*-----------------------------------------------------------------*/
378 void printIvalType (link * type, initList * ilist, FILE * oFile)
382 /* if initList is deep */
383 if (ilist->type == INIT_DEEP)
384 ilist = ilist->init.deep;
386 val = list2val (ilist);
387 switch (getSize (type)) {
390 tfprintf(oFile, "\t!db !constbyte\n", 0);
392 tfprintf(oFile, "\t!dbs\n",
393 aopLiteral (val, 0));
397 if (port->use_dw_for_init)
398 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
400 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
404 tfprintf (oFile, "\t!dw !constword\n", 0);
405 tfprintf (oFile, "\t!dw !constword\n", 0);
408 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
409 aopLiteral (val, 0), aopLiteral (val, 1),
410 aopLiteral (val, 2), aopLiteral (val, 3));
416 /*-----------------------------------------------------------------*/
417 /* printIvalStruct - generates initial value for structures */
418 /*-----------------------------------------------------------------*/
419 void printIvalStruct (symbol * sym,link * type,
420 initList * ilist, FILE * oFile)
425 sflds = SPEC_STRUCT (type)->fields;
426 if (ilist->type != INIT_DEEP) {
427 werror (E_INIT_STRUCT, sym->name);
431 iloop = ilist->init.deep;
433 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
434 printIval (sflds, sflds->type, iloop, oFile);
439 /*-----------------------------------------------------------------*/
440 /* printIvalChar - generates initital value for character array */
441 /*-----------------------------------------------------------------*/
442 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
449 val = list2val (ilist);
450 /* if the value is a character string */
451 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
452 if (!DCL_ELEM (type))
453 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
455 /* if size mismatch */
456 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
457 /* werror (E_ARRAY_BOUND); */
459 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
461 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
463 tfprintf (oFile, "\t!db !constbyte\n", 0);
471 printChar (oFile, s,strlen(s)+1);
475 /*-----------------------------------------------------------------*/
476 /* printIvalArray - generates code for array initialization */
477 /*-----------------------------------------------------------------*/
478 void printIvalArray (symbol * sym, link * type, initList * ilist,
482 int lcnt = 0, size = 0;
484 /* take care of the special case */
485 /* array of characters can be init */
487 if (IS_CHAR (type->next))
488 if (printIvalChar (type,
489 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
490 oFile, SPEC_CVAL (sym->etype).v_char))
493 /* not the special case */
494 if (ilist->type != INIT_DEEP) {
495 werror (E_INIT_STRUCT, sym->name);
499 iloop = ilist->init.deep;
500 lcnt = DCL_ELEM (type);
504 printIval (sym, type->next, iloop, oFile);
505 iloop = (iloop ? iloop->next : NULL);
508 /* if not array limits given & we */
509 /* are out of initialisers then */
510 if (!DCL_ELEM (type) && !iloop)
513 /* no of elements given and we */
514 /* have generated for all of them */
519 /* if we have not been given a size */
520 if (!DCL_ELEM (type))
521 DCL_ELEM (type) = size;
526 /*-----------------------------------------------------------------*/
527 /* printIvalFuncPtr - generate initial value for function pointers */
528 /*-----------------------------------------------------------------*/
529 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
534 val = list2val (ilist);
535 /* check the types */
536 if ((dLvl = checkType (val->type, type->next)) <= 0) {
537 tfprintf(oFile, "\t!dw !constword\n", 0);
541 /* now generate the name */
543 if (port->use_dw_for_init)
544 tfprintf(oFile, "\t!dws\n", val->name);
546 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name,val->name);
549 if (port->use_dw_for_init)
550 tfprintf(oFile, "\t!dws\n", val->sym->rname);
552 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->sym->rname,val->sym->rname);
557 /*-----------------------------------------------------------------*/
558 /* printIvalCharPtr - generates initial values for character pointers */
559 /*-----------------------------------------------------------------*/
560 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
564 /* PENDING: this is _very_ mcs51 specific, including a magic
566 It's also endin specific.
568 size = getSize (type);
570 if (val->name && strlen(val->name)) {
574 "\t!dbs\n", val->name) ;
577 if (port->use_dw_for_init)
578 tfprintf(oFile, "\t!dws\n", val->name);
580 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
582 /* PENDING: probably just 3 */
584 /* PENDING: 0x02 or 0x%02x, CDATA? */
586 "\t.byte %s,(%s >> 8),#0x%02x\n",
587 val->name, val->name, (IS_PTR(val->type) ? DCL_TYPE(val->type) :
588 PTR_TYPE(SPEC_OCLS(val->etype))));
594 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
597 if (port->use_dw_for_init)
598 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
600 tfprintf(oFile, "\t.byte %s,%s\n",
601 aopLiteral(val, 0),aopLiteral(val, 1));
604 /* PENDING: 0x02 or 0x%02x, CDATA? */
605 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
606 aopLiteral (val, 0), aopLiteral (val, 1));
614 if (val->sym && val->sym->isstrlit)
615 addSet (&statsg->syms, val->sym);
620 /*-----------------------------------------------------------------*/
621 /* printIvalPtr - generates initial value for pointers */
622 /*-----------------------------------------------------------------*/
623 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
628 if (ilist->type == INIT_DEEP)
629 ilist = ilist->init.deep;
631 /* function pointer */
632 if (IS_FUNC (type->next)) {
633 printIvalFuncPtr (type, ilist, oFile);
637 if (!(val = initPointer (ilist)))
640 /* if character pointer */
641 if (IS_CHAR (type->next))
642 if (printIvalCharPtr (sym, type, val, oFile))
646 if (checkType (type, val->type) != 1)
647 werror (E_INIT_WRONG);
649 /* if val is literal */
650 if (IS_LITERAL (val->etype)) {
651 switch (getSize (type)) {
653 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
656 if (port->use_dw_for_init)
657 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
659 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
662 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
663 aopLiteral (val, 0), aopLiteral (val, 1));
669 switch (getSize (type)) {
671 tfprintf (oFile, "\t!dbs\n", val->name);
674 tfprintf (oFile, "\t!dws\n", val->name);
678 fprintf (oFile, "\t.byte %s,(%s >> 8),#0x%02x\n",
679 val->name, val->name,(IS_PTR(val->type) ? DCL_TYPE(val->type) :
680 PTR_TYPE(SPEC_OCLS(val->etype))));
685 /*-----------------------------------------------------------------*/
686 /* printIval - generates code for initial value */
687 /*-----------------------------------------------------------------*/
688 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
693 /* if structure then */
694 if (IS_STRUCT (type)) {
695 printIvalStruct (sym, type, ilist, oFile);
699 /* if this is a pointer */
701 printIvalPtr (sym, type, ilist, oFile);
705 /* if this is an array */
706 if (IS_ARRAY (type)) {
707 printIvalArray (sym, type, ilist, oFile);
711 /* if type is SPECIFIER */
712 if (IS_SPEC (type)) {
713 printIvalType (type, ilist, oFile);
718 /*-----------------------------------------------------------------*/
719 /* emitStaticSeg - emitcode for the static segment */
720 /*-----------------------------------------------------------------*/
721 void emitStaticSeg (memmap * map)
725 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
728 codeOutFile = code->oFile;
730 /* for all variables in this segment do */
731 for (sym = setFirstItem (map->syms); sym;
732 sym = setNextItem (map->syms)) {
734 /* if it is "extern" then do nothing */
735 if (IS_EXTERN (sym->etype))
738 /* if it is not static add it to the public
740 if (!IS_STATIC (sym->etype))
741 addSetHead (&publics, sym);
743 /* print extra debug info if required */
744 if ((options.debug || sym->level == 0) && !options.nodebug) {
746 cdbSymbol(sym,cdbFile,FALSE,FALSE);
748 if (!sym->level) { /* global */
749 if (IS_STATIC(sym->etype))
750 fprintf(codeOutFile,"F%s$",moduleName); /* scope is file */
752 fprintf(codeOutFile,"G$"); /* scope is global */
755 /* symbol is local */
756 fprintf(codeOutFile,"L%s$",
757 (sym->localof ? sym->localof->name : "-null-"));
758 fprintf(codeOutFile,"%s$%d$%d",sym->name,sym->level,sym->block);
761 /* if it has an absolute address */
762 if (SPEC_ABSA (sym->etype)) {
763 if ((options.debug || sym->level == 0) && !options.nodebug)
764 fprintf(codeOutFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
766 fprintf (codeOutFile, "%s\t=\t0x%04x\n",
768 SPEC_ADDR (sym->etype));
771 if ((options.debug || sym->level == 0) && !options.nodebug)
772 fprintf(codeOutFile," == .\n");
774 /* if it has an initial value */
776 fprintf (codeOutFile, "%s:\n", sym->rname);
778 resolveIvalSym (sym->ival);
779 printIval (sym, sym->type, sym->ival, codeOutFile);
784 fprintf (codeOutFile, "%s:\n", sym->rname);
785 /* special case for character strings */
786 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
787 SPEC_CVAL (sym->etype).v_char)
788 printChar (codeOutFile,
789 SPEC_CVAL (sym->etype).v_char,
790 strlen(SPEC_CVAL (sym->etype).v_char)+1);
792 tfprintf(codeOutFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
798 /*-----------------------------------------------------------------*/
799 /* emitMaps - emits the code for the data portion the code */
800 /*-----------------------------------------------------------------*/
803 /* no special considerations for the following
804 data, idata & bit & xdata */
805 emitRegularMap (data, TRUE, TRUE);
806 emitRegularMap (idata, TRUE,TRUE);
807 emitRegularMap (bit, TRUE,FALSE);
808 emitRegularMap (xdata, TRUE,TRUE);
809 emitRegularMap (sfr, FALSE,FALSE);
810 emitRegularMap (sfrbit, FALSE,FALSE);
811 emitRegularMap (home, TRUE,FALSE);
812 emitRegularMap (code, TRUE,FALSE);
813 emitStaticSeg (statsg);
816 /*-----------------------------------------------------------------*/
817 /* flushStatics - flush all currently defined statics out to file */
818 /* and delete. Temporary function */
819 /*-----------------------------------------------------------------*/
820 void flushStatics(void)
822 emitStaticSeg(statsg);
826 /*-----------------------------------------------------------------*/
827 /* createInterruptVect - creates the interrupt vector */
828 /*-----------------------------------------------------------------*/
829 void createInterruptVect (FILE * vFile)
832 mainf = newSymbol ("main", 0);
835 /* only if the main function exists */
836 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
837 if (!options.cc_only)
842 /* if the main is only a prototype ie. no body then do nothing */
844 /* if ! compile only then main function should be present */
845 if (!options.cc_only)
850 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
851 fprintf (vFile, "__interrupt_vect:\n");
854 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
856 /* "generic" interrupt table header (if port doesn't specify one).
858 * Look suspiciously like 8051 code to me...
861 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
864 /* now for the other interrupts */
865 for (; i < maxInterrupts; i++) {
867 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
869 fprintf (vFile, "\treti\n\t.ds\t7\n");
876 ";--------------------------------------------------------\n"
877 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
881 ";--------------------------------------------------------\n"};
884 /*-----------------------------------------------------------------*/
885 /* initialComments - puts in some initial comments */
886 /*-----------------------------------------------------------------*/
887 void initialComments (FILE * afile)
891 fprintf (afile, "%s", iComments1);
892 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
893 fprintf (afile, "%s", iComments2);
896 /*-----------------------------------------------------------------*/
897 /* printPublics - generates .global for publics */
898 /*-----------------------------------------------------------------*/
899 void printPublics (FILE * afile)
903 fprintf (afile, "%s", iComments2);
904 fprintf (afile, "; Public variables in this module\n");
905 fprintf (afile, "%s", iComments2);
907 for (sym = setFirstItem (publics); sym;
908 sym = setNextItem (publics))
909 tfprintf(afile, "\t!global\n", sym->rname);
912 /*-----------------------------------------------------------------*/
913 /* printExterns - generates .global for externs */
914 /*-----------------------------------------------------------------*/
915 void printExterns (FILE * afile)
919 fprintf (afile, "%s", iComments2);
920 fprintf (afile, "; Externals used\n");
921 fprintf (afile, "%s", iComments2);
923 for (sym = setFirstItem (externs); sym;
924 sym = setNextItem (externs))
925 tfprintf(afile, "\t!global\n", sym->rname);
928 /*-----------------------------------------------------------------*/
929 /* emitOverlay - will emit code for the overlay stuff */
930 /*-----------------------------------------------------------------*/
931 static void emitOverlay(FILE *afile)
935 if (!elementsInSet(ovrSetSets))
936 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
938 /* for each of the sets in the overlay segment do */
939 for (ovrset = setFirstItem(ovrSetSets); ovrset;
940 ovrset = setNextItem(ovrSetSets)) {
944 if (elementsInSet(ovrset)) {
945 /* this dummy area is used to fool the assembler
946 otherwise the assembler will append each of these
947 declarations into one chunk and will not overlay
949 fprintf(afile,"\t.area _DUMMY\n");
950 /* output the area informtion */
951 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
954 for (sym = setFirstItem(ovrset); sym;
955 sym = setNextItem(ovrset)) {
957 /* if extern then add it to the publics tabledo nothing */
958 if (IS_EXTERN (sym->etype))
961 /* if allocation required check is needed
962 then check if the symbol really requires
963 allocation only for local variables */
964 if (!IS_AGGREGATE(sym->type) &&
965 !(sym->_isparm && !IS_REGPARM(sym->etype))
966 && !sym->allocreq && sym->level)
969 /* if global variable & not static or extern
970 and addPublics allowed then add it to the public set */
971 if ((sym->_isparm && !IS_REGPARM(sym->etype))
972 && !IS_STATIC (sym->etype))
973 addSetHead (&publics, sym);
975 /* if extern then do nothing or is a function
977 if (IS_FUNC (sym->type))
980 /* print extra debug info if required */
981 if ((options.debug || sym->level == 0) && !options.nodebug) {
983 cdbSymbol(sym,cdbFile,FALSE,FALSE);
985 if (!sym->level) { /* global */
986 if (IS_STATIC(sym->etype))
987 fprintf(afile,"F%s$",moduleName); /* scope is file */
989 fprintf(afile,"G$"); /* scope is global */
992 /* symbol is local */
993 fprintf(afile,"L%s$",
994 (sym->localof ? sym->localof->name : "-null-"));
995 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
998 /* if is has an absolute address then generate
999 an equate for this no need to allocate space */
1000 if (SPEC_ABSA (sym->etype)) {
1002 if ((options.debug || sym->level == 0) && !options.nodebug)
1003 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1005 fprintf (afile, "%s\t=\t0x%04x\n",
1007 SPEC_ADDR (sym->etype));
1010 if ((options.debug || sym->level == 0) && !options.nodebug)
1011 fprintf(afile,"==.\n");
1013 /* allocate space */
1014 tfprintf(afile, "!labeldef\n", sym->rname);
1015 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1022 /*-----------------------------------------------------------------*/
1023 /* glue - the final glue that hold the whole thing together */
1024 /*-----------------------------------------------------------------*/
1029 FILE *ovrFile = tempfile();
1031 addSetHead(&tmpfileSet,ovrFile);
1032 /* print the global struct definitions */
1034 cdbStructBlock (0,cdbFile);
1037 /* PENDING: this isnt the best place but it will do */
1038 if (port->general.glue_up_main) {
1039 /* create the interrupt vector table */
1040 createInterruptVect (vFile);
1043 addSetHead(&tmpfileSet,vFile);
1045 /* emit code for the all the variables declared */
1047 /* do the overlay segments */
1048 emitOverlay(ovrFile);
1050 /* now put it all together into the assembler file */
1051 /* create the assembler file name */
1053 if (!options.c1mode) {
1054 sprintf (buffer, srcFileName);
1055 strcat (buffer, ".asm");
1058 strcpy(buffer, options.out_name);
1061 if (!(asmFile = fopen (buffer, "w"))) {
1062 werror (E_FILE_OPEN_ERR, buffer);
1066 /* initial comments */
1067 initialComments (asmFile);
1069 /* print module name */
1070 tfprintf(asmFile, "\t!module\n", moduleName);
1071 tfprintf(asmFile, "\t!fileprelude\n");
1073 /* Let the port generate any global directives, etc. */
1074 if (port->genAssemblerPreamble)
1076 port->genAssemblerPreamble(asmFile);
1079 /* print the global variables in this module */
1080 printPublics (asmFile);
1081 if (port->assembler.externGlobal)
1082 printExterns (asmFile);
1084 /* copy the sfr segment */
1085 fprintf (asmFile, "%s", iComments2);
1086 fprintf (asmFile, "; special function registers\n");
1087 fprintf (asmFile, "%s", iComments2);
1088 copyFile (asmFile, sfr->oFile);
1090 /* copy the sbit segment */
1091 fprintf (asmFile, "%s", iComments2);
1092 fprintf (asmFile, "; special function bits \n");
1093 fprintf (asmFile, "%s", iComments2);
1094 copyFile (asmFile, sfrbit->oFile);
1096 /* copy the data segment */
1097 fprintf (asmFile, "%s", iComments2);
1098 fprintf (asmFile, "; internal ram data\n");
1099 fprintf (asmFile, "%s", iComments2);
1100 copyFile (asmFile, data->oFile);
1103 /* create the overlay segments */
1104 fprintf (asmFile, "%s", iComments2);
1105 fprintf (asmFile, "; overlayable items in internal ram \n");
1106 fprintf (asmFile, "%s", iComments2);
1107 copyFile (asmFile, ovrFile);
1109 /* create the stack segment MOF */
1110 if (mainf && mainf->fbody) {
1111 fprintf (asmFile, "%s", iComments2);
1112 fprintf (asmFile, "; Stack segment in internal ram \n");
1113 fprintf (asmFile, "%s", iComments2);
1114 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1115 "__start__stack:\n\t.ds\t1\n\n");
1118 /* create the idata segment */
1119 fprintf (asmFile, "%s", iComments2);
1120 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1121 fprintf (asmFile, "%s", iComments2);
1122 copyFile (asmFile, idata->oFile);
1124 /* copy the bit segment */
1125 fprintf (asmFile, "%s", iComments2);
1126 fprintf (asmFile, "; bit data\n");
1127 fprintf (asmFile, "%s", iComments2);
1128 copyFile (asmFile, bit->oFile);
1130 /* if external stack then reserve space of it */
1131 if (mainf && mainf->fbody && options.useXstack ) {
1132 fprintf (asmFile, "%s", iComments2);
1133 fprintf (asmFile, "; external stack \n");
1134 fprintf (asmFile, "%s", iComments2);
1135 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1136 fprintf (asmFile,"\t.ds 256\n");
1140 /* copy xtern ram data */
1141 fprintf (asmFile, "%s", iComments2);
1142 fprintf (asmFile, "; external ram data\n");
1143 fprintf (asmFile, "%s", iComments2);
1144 copyFile (asmFile, xdata->oFile);
1146 /* copy the interrupt vector table */
1147 if (mainf && mainf->fbody) {
1148 fprintf (asmFile, "%s", iComments2);
1149 fprintf (asmFile, "; interrupt vector \n");
1150 fprintf (asmFile, "%s", iComments2);
1151 copyFile (asmFile, vFile);
1154 /* copy global & static initialisations */
1155 fprintf (asmFile, "%s", iComments2);
1156 fprintf (asmFile, "; global & static initialisations\n");
1157 fprintf (asmFile, "%s", iComments2);
1159 /* Everywhere we generate a reference to the static_name area,
1160 * (which is currently only here), we immediately follow it with a
1161 * definition of the post_static_name area. This guarantees that
1162 * the post_static_name area will immediately follow the static_name
1165 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1166 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1167 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1169 if (mainf && mainf->fbody) {
1170 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1171 /* if external stack is specified then the
1172 higher order byte of the xdatalocation is
1173 going into P2 and the lower order going into
1175 if (options.useXstack) {
1176 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1177 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1178 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1179 (unsigned int)options.xdata_loc & 0xff);
1182 /* initialise the stack pointer */
1183 /* if the user specified a value then use it */
1184 if (options.stack_loc)
1185 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1187 /* no: we have to compute it */
1188 if (!options.stackOnData && maxRegBank <= 3)
1189 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1191 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1193 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1194 fprintf (asmFile,"\tmov\ta,dpl\n");
1195 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1196 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1197 fprintf (asmFile,"__sdcc_init_data:\n");
1200 copyFile (asmFile, statsg->oFile);
1202 if (port->general.glue_up_main && mainf && mainf->fbody)
1204 /* This code is generated in the post-static area.
1205 * This area is guaranteed to follow the static area
1206 * by the ugly shucking and jiving about 20 lines ago.
1208 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1209 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1215 "%s", iComments2, iComments2);
1216 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1217 copyFile (asmFile, home->oFile);
1219 /* copy over code */
1220 fprintf (asmFile, "%s", iComments2);
1221 fprintf (asmFile, "; code\n");
1222 fprintf (asmFile, "%s", iComments2);
1223 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1224 if (mainf && mainf->fbody) {
1226 /* entry point @ start of CSEG */
1227 fprintf (asmFile,"__sdcc_program_startup:\n");
1229 /* put in the call to main */
1230 fprintf(asmFile,"\tlcall\t_main\n");
1231 if (options.mainreturn) {
1233 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1234 fprintf(asmFile,"\tret\n");
1238 fprintf(asmFile,";\treturn from main will lock up\n");
1239 fprintf(asmFile,"\tsjmp .\n");
1242 copyFile (asmFile, code->oFile);
1245 applyToSet(tmpfileSet,closeTmpFiles);
1246 applyToSet(tmpfileNameSet, rmTmpFiles);
1249 /** Creates a temporary file a'la tmpfile which avoids the bugs
1250 in cygwin wrt c:\tmp.
1251 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1253 FILE *tempfile(void)
1255 const char *tmpdir = NULL;
1257 tmpdir = getenv("TMP");
1258 else if (getenv("TEMP"))
1259 tmpdir = getenv("TEMP");
1260 else if (getenv("TMPDIR"))
1261 tmpdir = getenv("TMPDIR");
1263 char *name = tempnam(tmpdir, "sdcc");
1265 FILE *fp = fopen(name, "w+b");
1267 addSetHead(&tmpfileNameSet, name);
1275 char *gc_strdup(const char *s)
1278 ALLOC_ATOMIC(ret, strlen(s)+1);