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 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
30 #if 0 /* This should no longer be necessary. */
31 // This is a bit messy because we define link ourself
40 // No unistd.h in Borland C++
43 symbol *interrupts[256];
45 void printIval (symbol *, sym_link *, initList *, FILE *);
46 set *publics = NULL; /* public variables */
47 set *externs = NULL; /* Varibles that are declared as extern */
49 /* TODO: this should be configurable (DS803C90 uses more than 6) */
50 int maxInterrupts = 6;
53 extern char *VersionString;
54 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
55 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
57 /*-----------------------------------------------------------------*/
58 /* closeTmpFiles - closes all tmp files created by the compiler */
59 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
60 /*-----------------------------------------------------------------*/
61 DEFSETFUNC(closeTmpFiles)
71 /*-----------------------------------------------------------------*/
72 /* rmTmpFiles - closes all tmp files created by the compiler */
73 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
74 /*-----------------------------------------------------------------*/
75 DEFSETFUNC(rmTmpFiles)
86 /*-----------------------------------------------------------------*/
87 /* copyFile - copies source file to destination file */
88 /*-----------------------------------------------------------------*/
89 void copyFile (FILE * dest, FILE * src)
95 if ((ch = fgetc (src)) != EOF)
99 char *aopLiteralLong(value *val, int offset, int size)
107 /* if it is a float then it gets tricky */
108 /* otherwise it is fairly simple */
109 if (!IS_FLOAT(val->type)) {
110 unsigned long v = floatFromVal(val);
115 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
118 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
121 /* Hmm. Too big for now. */
124 ALLOC_ATOMIC(rs,strlen(buffer)+1);
125 return strcpy (rs,buffer);
128 /* PENDING: For now size must be 1 */
131 /* it is type float */
132 fl.f = (float) floatFromVal(val);
134 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
136 tsprintf(buffer, "!immedbyte", fl.c[offset]);
138 ALLOC_ATOMIC(rs,strlen(buffer)+1);
139 return strcpy (rs,buffer);
142 /*-----------------------------------------------------------------*/
143 /* aopLiteral - string from a literal value */
144 /*-----------------------------------------------------------------*/
145 char *aopLiteral (value *val, int offset)
147 return aopLiteralLong(val, offset, 1);
150 /*-----------------------------------------------------------------*/
151 /* emitRegularMap - emit code for maps with no special cases */
152 /*-----------------------------------------------------------------*/
153 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
158 /* PENDING: special case here - should remove */
159 if (!strcmp(map->sname, CODE_NAME))
160 tfprintf(map->oFile, "\t!areacode\n", map->sname);
161 else if (!strcmp(map->sname, DATA_NAME))
162 tfprintf(map->oFile, "\t!areadata\n", map->sname);
163 else if (!strcmp(map->sname, HOME_NAME))
164 tfprintf(map->oFile, "\t!areahome\n", map->sname);
166 tfprintf(map->oFile, "\t!area\n", map->sname);
169 /* print the area name */
170 for (sym = setFirstItem (map->syms); sym;
171 sym = setNextItem (map->syms)) {
173 /* if extern then add it into the extern list */
174 if (IS_EXTERN (sym->etype)) {
175 addSetHead (&externs, sym);
179 /* if allocation required check is needed
180 then check if the symbol really requires
181 allocation only for local variables */
182 if (arFlag && !IS_AGGREGATE(sym->type) &&
183 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
184 !sym->allocreq && sym->level)
187 /* if global variable & not static or extern
188 and addPublics allowed then add it to the public set */
189 if ((sym->level == 0 ||
190 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
192 !IS_STATIC (sym->etype) &&
193 (sym->used || sym->fbody)) {
194 addSetHead (&publics, sym);
197 /* if extern then do nothing or is a function
199 if (IS_FUNC (sym->type))
202 /* print extra debug info if required */
203 if ((options.debug || sym->level == 0) && !options.nodebug) {
205 cdbSymbol(sym,cdbFile,FALSE,FALSE);
207 if (!sym->level) /* global */
208 if (IS_STATIC(sym->etype))
209 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
211 fprintf(map->oFile,"G$"); /* scope is global */
213 /* symbol is local */
214 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
215 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
218 /* if is has an absolute address then generate
219 an equate for this no need to allocate space */
220 if (SPEC_ABSA (sym->etype)) {
221 if ((options.debug || sym->level == 0) && !options.nodebug)
222 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
224 fprintf (map->oFile, "%s\t=\t0x%04x\n",
226 SPEC_ADDR (sym->etype));
230 if ((options.debug || sym->level == 0) && !options.nodebug)
231 fprintf(map->oFile,"==.\n");
232 if (IS_STATIC(sym->etype))
233 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
235 tfprintf(map->oFile, "!labeldef\n", sym->rname);
236 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
239 /* if it has an initial value then do it only if
240 it is a global variable */
241 if (sym->ival && sym->level == 0) {
244 if (IS_AGGREGATE (sym->type))
245 ival = initAggregates (sym, sym->ival, NULL);
247 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
248 decorateType (resolveSymbols (list2expr (sym->ival))));
249 codeOutFile = statsg->oFile;
251 eBBlockFromiCode (iCodeFromAst (ival));
258 /*-----------------------------------------------------------------*/
259 /* initPointer - pointer initialization code massaging */
260 /*-----------------------------------------------------------------*/
261 value *initPointer (initList *ilist)
264 ast *expr = list2expr(ilist);
269 /* try it the oldway first */
270 if ((val = constExprValue(expr,FALSE)))
273 /* no then we have to do these cludgy checks */
274 /* pointers can be initialized with address of
275 a variable or address of an array element */
276 if (IS_AST_OP(expr) && expr->opval.op == '&') {
277 /* address of symbol */
278 if (IS_AST_SYM_VALUE(expr->left)) {
279 val = copyValue(AST_VALUE(expr->left));
280 val->type = newLink();
281 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
282 DCL_TYPE(val->type) = CPOINTER ;
283 DCL_PTR_CONST(val->type) = port->mem.code_ro;
286 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
287 DCL_TYPE(val->type) = FPOINTER;
289 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
290 DCL_TYPE(val->type) = PPOINTER ;
292 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
293 DCL_TYPE(val->type) = IPOINTER ;
295 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
296 DCL_TYPE(val->type) = EEPPOINTER ;
298 DCL_TYPE(val->type) = POINTER ;
299 val->type->next = expr->left->ftype;
300 val->etype = getSpec(val->type);
304 /* if address of indexed array */
305 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
306 return valForArray(expr->left);
308 /* if address of structure element then
310 if (IS_AST_OP(expr->left) &&
311 expr->left->opval.op == '.' ) {
312 return valForStructElem(expr->left->left,
317 (&some_struct)->element */
318 if (IS_AST_OP(expr->left) &&
319 expr->left->opval.op == PTR_OP &&
320 IS_ADDRESS_OF_OP(expr->left->left))
321 return valForStructElem(expr->left->left->left,
325 /* case 3. (((char *) &a) +/- constant) */
326 if (IS_AST_OP(expr) &&
327 (expr->opval.op == '+' || expr->opval.op == '-') &&
328 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
329 IS_AST_OP(expr->left->right) &&
330 expr->left->right->opval.op == '&' &&
331 IS_AST_LIT_VALUE(expr->right)) {
333 return valForCastAggr(expr->left->right->left,
334 expr->left->left->opval.lnk,
335 expr->right,expr->opval.op);
340 werror(E_INIT_WRONG);
345 /*-----------------------------------------------------------------*/
346 /* printChar - formats and prints a characater string with DB */
347 /*-----------------------------------------------------------------*/
348 void printChar (FILE * ofile, char *s, int plen)
351 int len = strlen (s);
356 while (len && pplen < plen) {
358 while (i && *s && pplen < plen) {
359 if (*s < ' ' || *s == '\"') {
362 tfprintf(ofile, "\t!ascii\n", buf);
363 tfprintf(ofile, "\t!db !constbyte\n", *s);
376 tfprintf(ofile, "\t!ascii\n", buf);
385 tfprintf(ofile, "\t!db !constbyte\n", 0);
388 /*-----------------------------------------------------------------*/
389 /* return the generic pointer high byte for a given pointer type. */
390 /*-----------------------------------------------------------------*/
391 int pointerTypeToGPByte(const int p_type)
399 /* hack - if we get a generic pointer, we just assume
400 * it's an FPOINTER (i.e. in XDATA space).
409 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
417 /*-----------------------------------------------------------------*/
418 /* printPointerType - generates ival for pointer type */
419 /*-----------------------------------------------------------------*/
420 void _printPointerType(FILE *oFile, const char *name)
424 fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
428 fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
432 /*-----------------------------------------------------------------*/
433 /* printPointerType - generates ival for pointer type */
434 /*-----------------------------------------------------------------*/
435 void printPointerType(FILE *oFile, const char *name)
437 _printPointerType(oFile, name);
438 fprintf(oFile, "\n");
441 /*-----------------------------------------------------------------*/
442 /* printGPointerType - generates ival for generic pointer type */
443 /*-----------------------------------------------------------------*/
444 void printGPointerType(FILE *oFile, const char *name,
445 const unsigned int type)
447 _printPointerType(oFile,name);
448 fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type));
451 /*-----------------------------------------------------------------*/
452 /* printIvalType - generates ival for int/char */
453 /*-----------------------------------------------------------------*/
454 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
458 /* if initList is deep */
459 if (ilist->type == INIT_DEEP)
460 ilist = ilist->init.deep;
462 val = list2val (ilist);
463 switch (getSize (type)) {
466 tfprintf(oFile, "\t!db !constbyte\n", 0);
468 tfprintf(oFile, "\t!dbs\n",
469 aopLiteral (val, 0));
473 if (port->use_dw_for_init)
474 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
476 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
480 tfprintf (oFile, "\t!dw !constword\n", 0);
481 tfprintf (oFile, "\t!dw !constword\n", 0);
484 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
485 aopLiteral (val, 0), aopLiteral (val, 1),
486 aopLiteral (val, 2), aopLiteral (val, 3));
492 /*-----------------------------------------------------------------*/
493 /* printIvalStruct - generates initial value for structures */
494 /*-----------------------------------------------------------------*/
495 void printIvalStruct (symbol * sym,sym_link * type,
496 initList * ilist, FILE * oFile)
501 sflds = SPEC_STRUCT (type)->fields;
502 if (ilist->type != INIT_DEEP) {
503 werror (E_INIT_STRUCT, sym->name);
507 iloop = ilist->init.deep;
509 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
510 printIval (sflds, sflds->type, iloop, oFile);
515 /*-----------------------------------------------------------------*/
516 /* printIvalChar - generates initital value for character array */
517 /*-----------------------------------------------------------------*/
518 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
525 val = list2val (ilist);
526 /* if the value is a character string */
527 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
528 if (!DCL_ELEM (type))
529 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
531 /* if size mismatch */
532 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
533 /* werror (E_ARRAY_BOUND); */
535 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
537 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
539 tfprintf (oFile, "\t!db !constbyte\n", 0);
547 printChar (oFile, s,strlen(s)+1);
551 /*-----------------------------------------------------------------*/
552 /* printIvalArray - generates code for array initialization */
553 /*-----------------------------------------------------------------*/
554 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
558 int lcnt = 0, size = 0;
560 /* take care of the special case */
561 /* array of characters can be init */
563 if (IS_CHAR (type->next))
564 if (printIvalChar (type,
565 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
566 oFile, SPEC_CVAL (sym->etype).v_char))
569 /* not the special case */
570 if (ilist->type != INIT_DEEP) {
571 werror (E_INIT_STRUCT, sym->name);
575 iloop = ilist->init.deep;
576 lcnt = DCL_ELEM (type);
580 printIval (sym, type->next, iloop, oFile);
581 iloop = (iloop ? iloop->next : NULL);
584 /* if not array limits given & we */
585 /* are out of initialisers then */
586 if (!DCL_ELEM (type) && !iloop)
589 /* no of elements given and we */
590 /* have generated for all of them */
595 /* if we have not been given a size */
596 if (!DCL_ELEM (type))
597 DCL_ELEM (type) = size;
602 /*-----------------------------------------------------------------*/
603 /* printIvalFuncPtr - generate initial value for function pointers */
604 /*-----------------------------------------------------------------*/
605 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
610 val = list2val (ilist);
611 /* check the types */
612 if ((dLvl = checkType (val->type, type->next)) <= 0) {
613 tfprintf(oFile, "\t!dw !constword\n", 0);
617 /* now generate the name */
619 if (port->use_dw_for_init)
621 tfprintf(oFile, "\t!dws\n", val->name);
625 printPointerType(oFile, val->name);
629 if (port->use_dw_for_init)
631 tfprintf(oFile, "\t!dws\n", val->sym->rname);
635 printPointerType(oFile, val->sym->rname);
641 /*-----------------------------------------------------------------*/
642 /* printIvalCharPtr - generates initial values for character pointers */
643 /*-----------------------------------------------------------------*/
644 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
648 /* PENDING: this is _very_ mcs51 specific, including a magic
650 It's also endin specific.
652 size = getSize (type);
654 if (val->name && strlen(val->name)) {
655 if (size == 1) /* This appears to be Z80 specific?? */
658 "\t!dbs\n", val->name);
660 else if (size == FPTRSIZE)
662 if (port->use_dw_for_init)
664 tfprintf(oFile, "\t!dws\n", val->name);
668 printPointerType(oFile, val->name);
671 else if (size == GPTRSIZE)
673 /* PENDING: 0x02 or 0x%02x, CDATA? */
674 printGPointerType(oFile, val->name,
675 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
676 PTR_TYPE(SPEC_OCLS(val->etype))));
680 fprintf(stderr, "*** internal error: unknown size in "
681 "printIvalCharPtr.\n");
685 /* What is this case? Are these pointers? */
688 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
691 if (port->use_dw_for_init)
692 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
694 tfprintf(oFile, "\t.byte %s,%s\n",
695 aopLiteral(val, 0),aopLiteral(val, 1));
698 /* PENDING: 0x02 or 0x%02x, CDATA? */
699 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
700 aopLiteral (val, 0), aopLiteral (val, 1));
708 if (val->sym && val->sym->isstrlit)
709 addSet (&statsg->syms, val->sym);
714 /*-----------------------------------------------------------------*/
715 /* printIvalPtr - generates initial value for pointers */
716 /*-----------------------------------------------------------------*/
717 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
723 if (ilist->type == INIT_DEEP)
724 ilist = ilist->init.deep;
726 /* function pointer */
727 if (IS_FUNC (type->next)) {
728 printIvalFuncPtr (type, ilist, oFile);
732 if (!(val = initPointer (ilist)))
735 /* if character pointer */
736 if (IS_CHAR (type->next))
737 if (printIvalCharPtr (sym, type, val, oFile))
741 if (checkType (type, val->type) != 1)
742 werror (E_INIT_WRONG);
744 /* if val is literal */
745 if (IS_LITERAL (val->etype)) {
746 switch (getSize (type)) {
748 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
751 if (port->use_dw_for_init)
752 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
754 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
757 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
758 aopLiteral (val, 0), aopLiteral (val, 1));
764 size = getSize (type);
766 if (size == 1) /* Z80 specific?? */
768 tfprintf (oFile, "\t!dbs\n", val->name);
770 else if (size == FPTRSIZE)
772 tfprintf (oFile, "\t!dws\n", val->name);
774 else if (size == GPTRSIZE)
776 printGPointerType(oFile, val->name,
777 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
778 PTR_TYPE(SPEC_OCLS(val->etype))));
783 /*-----------------------------------------------------------------*/
784 /* printIval - generates code for initial value */
785 /*-----------------------------------------------------------------*/
786 void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
791 /* if structure then */
792 if (IS_STRUCT (type)) {
793 printIvalStruct (sym, type, ilist, oFile);
797 /* if this is a pointer */
799 printIvalPtr (sym, type, ilist, oFile);
803 /* if this is an array */
804 if (IS_ARRAY (type)) {
805 printIvalArray (sym, type, ilist, oFile);
809 /* if type is SPECIFIER */
810 if (IS_SPEC (type)) {
811 printIvalType (type, ilist, oFile);
816 /*-----------------------------------------------------------------*/
817 /* emitStaticSeg - emitcode for the static segment */
818 /*-----------------------------------------------------------------*/
819 void emitStaticSeg(memmap * map, FILE *out)
823 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
827 /* for all variables in this segment do */
828 for (sym = setFirstItem (map->syms); sym;
829 sym = setNextItem (map->syms)) {
831 /* if it is "extern" then do nothing */
832 if (IS_EXTERN (sym->etype))
835 /* if it is not static add it to the public
837 if (!IS_STATIC (sym->etype))
838 addSetHead (&publics, sym);
840 /* print extra debug info if required */
841 if ((options.debug || sym->level == 0) && !options.nodebug) {
843 cdbSymbol(sym,cdbFile,FALSE,FALSE);
845 if (!sym->level) { /* global */
846 if (IS_STATIC(sym->etype))
847 fprintf(out,"F%s$",moduleName); /* scope is file */
849 fprintf(out,"G$"); /* scope is global */
852 /* symbol is local */
854 (sym->localof ? sym->localof->name : "-null-"));
855 fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
858 /* if it has an absolute address */
859 if (SPEC_ABSA (sym->etype)) {
860 if ((options.debug || sym->level == 0) && !options.nodebug)
861 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
863 fprintf (out, "%s\t=\t0x%04x\n",
865 SPEC_ADDR (sym->etype));
868 if ((options.debug || sym->level == 0) && !options.nodebug)
869 fprintf(out," == .\n");
871 /* if it has an initial value */
873 fprintf (out, "%s:\n", sym->rname);
875 resolveIvalSym (sym->ival);
876 printIval (sym, sym->type, sym->ival, out);
881 fprintf (out, "%s:\n", sym->rname);
882 /* special case for character strings */
883 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
884 SPEC_CVAL (sym->etype).v_char)
886 SPEC_CVAL (sym->etype).v_char,
887 strlen(SPEC_CVAL (sym->etype).v_char)+1);
889 tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
895 /*-----------------------------------------------------------------*/
896 /* emitMaps - emits the code for the data portion the code */
897 /*-----------------------------------------------------------------*/
900 /* no special considerations for the following
901 data, idata & bit & xdata */
902 emitRegularMap (data, TRUE, TRUE);
903 emitRegularMap (idata, TRUE,TRUE);
904 emitRegularMap (bit, TRUE,FALSE);
905 emitRegularMap (xdata, TRUE,TRUE);
906 emitRegularMap (sfr, FALSE,FALSE);
907 emitRegularMap (sfrbit, FALSE,FALSE);
908 emitRegularMap (home, TRUE,FALSE);
909 emitRegularMap (code, TRUE,FALSE);
911 emitStaticSeg (statsg, code->oFile);
914 /*-----------------------------------------------------------------*/
915 /* flushStatics - flush all currently defined statics out to file */
916 /* and delete. Temporary function */
917 /*-----------------------------------------------------------------*/
918 void flushStatics(void)
920 emitStaticSeg(statsg, codeOutFile);
924 /*-----------------------------------------------------------------*/
925 /* createInterruptVect - creates the interrupt vector */
926 /*-----------------------------------------------------------------*/
927 void createInterruptVect (FILE * vFile)
930 mainf = newSymbol ("main", 0);
933 /* only if the main function exists */
934 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
935 if (!options.cc_only)
940 /* if the main is only a prototype ie. no body then do nothing */
942 /* if ! compile only then main function should be present */
943 if (!options.cc_only)
948 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
949 fprintf (vFile, "__interrupt_vect:\n");
952 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
954 /* "generic" interrupt table header (if port doesn't specify one).
956 * Look suspiciously like 8051 code to me...
959 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
962 /* now for the other interrupts */
963 for (; i < maxInterrupts; i++) {
965 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
967 fprintf (vFile, "\treti\n\t.ds\t7\n");
974 ";--------------------------------------------------------\n"
975 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
979 ";--------------------------------------------------------\n"};
982 /*-----------------------------------------------------------------*/
983 /* initialComments - puts in some initial comments */
984 /*-----------------------------------------------------------------*/
985 void initialComments (FILE * afile)
989 fprintf (afile, "%s", iComments1);
990 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
991 fprintf (afile, "%s", iComments2);
994 /*-----------------------------------------------------------------*/
995 /* printPublics - generates .global for publics */
996 /*-----------------------------------------------------------------*/
997 void printPublics (FILE * afile)
1001 fprintf (afile, "%s", iComments2);
1002 fprintf (afile, "; Public variables in this module\n");
1003 fprintf (afile, "%s", iComments2);
1005 for (sym = setFirstItem (publics); sym;
1006 sym = setNextItem (publics))
1007 tfprintf(afile, "\t!global\n", sym->rname);
1010 /*-----------------------------------------------------------------*/
1011 /* printExterns - generates .global for externs */
1012 /*-----------------------------------------------------------------*/
1013 void printExterns (FILE * afile)
1017 fprintf (afile, "%s", iComments2);
1018 fprintf (afile, "; Externals used\n");
1019 fprintf (afile, "%s", iComments2);
1021 for (sym = setFirstItem (externs); sym;
1022 sym = setNextItem (externs))
1023 tfprintf(afile, "\t!global\n", sym->rname);
1026 /*-----------------------------------------------------------------*/
1027 /* emitOverlay - will emit code for the overlay stuff */
1028 /*-----------------------------------------------------------------*/
1029 static void emitOverlay(FILE *afile)
1033 if (!elementsInSet(ovrSetSets))
1034 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1036 /* for each of the sets in the overlay segment do */
1037 for (ovrset = setFirstItem(ovrSetSets); ovrset;
1038 ovrset = setNextItem(ovrSetSets)) {
1042 if (elementsInSet(ovrset)) {
1043 /* this dummy area is used to fool the assembler
1044 otherwise the assembler will append each of these
1045 declarations into one chunk and will not overlay
1047 fprintf(afile,"\t.area _DUMMY\n");
1048 /* output the area informtion */
1049 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1052 for (sym = setFirstItem(ovrset); sym;
1053 sym = setNextItem(ovrset)) {
1055 /* if extern then add it to the publics tabledo nothing */
1056 if (IS_EXTERN (sym->etype))
1059 /* if allocation required check is needed
1060 then check if the symbol really requires
1061 allocation only for local variables */
1062 if (!IS_AGGREGATE(sym->type) &&
1063 !(sym->_isparm && !IS_REGPARM(sym->etype))
1064 && !sym->allocreq && sym->level)
1067 /* if global variable & not static or extern
1068 and addPublics allowed then add it to the public set */
1069 if ((sym->_isparm && !IS_REGPARM(sym->etype))
1070 && !IS_STATIC (sym->etype))
1071 addSetHead (&publics, sym);
1073 /* if extern then do nothing or is a function
1075 if (IS_FUNC (sym->type))
1078 /* print extra debug info if required */
1079 if ((options.debug || sym->level == 0) && !options.nodebug) {
1081 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1083 if (!sym->level) { /* global */
1084 if (IS_STATIC(sym->etype))
1085 fprintf(afile,"F%s$",moduleName); /* scope is file */
1087 fprintf(afile,"G$"); /* scope is global */
1090 /* symbol is local */
1091 fprintf(afile,"L%s$",
1092 (sym->localof ? sym->localof->name : "-null-"));
1093 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1096 /* if is has an absolute address then generate
1097 an equate for this no need to allocate space */
1098 if (SPEC_ABSA (sym->etype)) {
1100 if ((options.debug || sym->level == 0) && !options.nodebug)
1101 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1103 fprintf (afile, "%s\t=\t0x%04x\n",
1105 SPEC_ADDR (sym->etype));
1108 if ((options.debug || sym->level == 0) && !options.nodebug)
1109 fprintf(afile,"==.\n");
1111 /* allocate space */
1112 tfprintf(afile, "!labeldef\n", sym->rname);
1113 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1120 /*-----------------------------------------------------------------*/
1121 /* glue - the final glue that hold the whole thing together */
1122 /*-----------------------------------------------------------------*/
1127 FILE *ovrFile = tempfile();
1129 addSetHead(&tmpfileSet,ovrFile);
1130 /* print the global struct definitions */
1131 if (options.debug && !options.nodebug)
1132 cdbStructBlock (0,cdbFile);
1135 /* PENDING: this isnt the best place but it will do */
1136 if (port->general.glue_up_main) {
1137 /* create the interrupt vector table */
1138 createInterruptVect (vFile);
1141 addSetHead(&tmpfileSet,vFile);
1143 /* emit code for the all the variables declared */
1145 /* do the overlay segments */
1146 emitOverlay(ovrFile);
1148 /* now put it all together into the assembler file */
1149 /* create the assembler file name */
1151 if (!options.c1mode) {
1152 sprintf (buffer, srcFileName);
1153 strcat (buffer, ".asm");
1156 strcpy(buffer, options.out_name);
1159 if (!(asmFile = fopen (buffer, "w"))) {
1160 werror (E_FILE_OPEN_ERR, buffer);
1164 /* initial comments */
1165 initialComments (asmFile);
1167 /* print module name */
1168 tfprintf(asmFile, "\t!module\n", moduleName);
1169 tfprintf(asmFile, "\t!fileprelude\n");
1171 /* Let the port generate any global directives, etc. */
1172 if (port->genAssemblerPreamble)
1174 port->genAssemblerPreamble(asmFile);
1177 /* print the global variables in this module */
1178 printPublics (asmFile);
1179 if (port->assembler.externGlobal)
1180 printExterns (asmFile);
1182 /* copy the sfr segment */
1183 fprintf (asmFile, "%s", iComments2);
1184 fprintf (asmFile, "; special function registers\n");
1185 fprintf (asmFile, "%s", iComments2);
1186 copyFile (asmFile, sfr->oFile);
1188 /* copy the sbit segment */
1189 fprintf (asmFile, "%s", iComments2);
1190 fprintf (asmFile, "; special function bits \n");
1191 fprintf (asmFile, "%s", iComments2);
1192 copyFile (asmFile, sfrbit->oFile);
1194 /* copy the data segment */
1195 fprintf (asmFile, "%s", iComments2);
1196 fprintf (asmFile, "; internal ram data\n");
1197 fprintf (asmFile, "%s", iComments2);
1198 copyFile (asmFile, data->oFile);
1201 /* create the overlay segments */
1202 fprintf (asmFile, "%s", iComments2);
1203 fprintf (asmFile, "; overlayable items in internal ram \n");
1204 fprintf (asmFile, "%s", iComments2);
1205 copyFile (asmFile, ovrFile);
1207 /* create the stack segment MOF */
1208 if (mainf && mainf->fbody) {
1209 fprintf (asmFile, "%s", iComments2);
1210 fprintf (asmFile, "; Stack segment in internal ram \n");
1211 fprintf (asmFile, "%s", iComments2);
1212 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1213 "__start__stack:\n\t.ds\t1\n\n");
1216 /* create the idata segment */
1217 fprintf (asmFile, "%s", iComments2);
1218 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1219 fprintf (asmFile, "%s", iComments2);
1220 copyFile (asmFile, idata->oFile);
1222 /* copy the bit segment */
1223 fprintf (asmFile, "%s", iComments2);
1224 fprintf (asmFile, "; bit data\n");
1225 fprintf (asmFile, "%s", iComments2);
1226 copyFile (asmFile, bit->oFile);
1228 /* if external stack then reserve space of it */
1229 if (mainf && mainf->fbody && options.useXstack ) {
1230 fprintf (asmFile, "%s", iComments2);
1231 fprintf (asmFile, "; external stack \n");
1232 fprintf (asmFile, "%s", iComments2);
1233 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1234 fprintf (asmFile,"\t.ds 256\n");
1238 /* copy xtern ram data */
1239 fprintf (asmFile, "%s", iComments2);
1240 fprintf (asmFile, "; external ram data\n");
1241 fprintf (asmFile, "%s", iComments2);
1242 copyFile (asmFile, xdata->oFile);
1244 /* copy the interrupt vector table */
1245 if (mainf && mainf->fbody) {
1246 fprintf (asmFile, "%s", iComments2);
1247 fprintf (asmFile, "; interrupt vector \n");
1248 fprintf (asmFile, "%s", iComments2);
1249 copyFile (asmFile, vFile);
1252 /* copy global & static initialisations */
1253 fprintf (asmFile, "%s", iComments2);
1254 fprintf (asmFile, "; global & static initialisations\n");
1255 fprintf (asmFile, "%s", iComments2);
1257 /* Everywhere we generate a reference to the static_name area,
1258 * (which is currently only here), we immediately follow it with a
1259 * definition of the post_static_name area. This guarantees that
1260 * the post_static_name area will immediately follow the static_name
1263 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1264 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1265 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1267 if (mainf && mainf->fbody) {
1268 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1269 /* if external stack is specified then the
1270 higher order byte of the xdatalocation is
1271 going into P2 and the lower order going into
1273 if (options.useXstack) {
1274 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1275 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1276 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1277 (unsigned int)options.xdata_loc & 0xff);
1280 /* initialise the stack pointer */
1281 /* if the user specified a value then use it */
1282 if (options.stack_loc)
1283 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1285 /* no: we have to compute it */
1286 if (!options.stackOnData && maxRegBank <= 3)
1287 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1289 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1291 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1292 fprintf (asmFile,"\tmov\ta,dpl\n");
1293 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1294 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1295 fprintf (asmFile,"__sdcc_init_data:\n");
1298 copyFile (asmFile, statsg->oFile);
1300 if (port->general.glue_up_main && mainf && mainf->fbody)
1302 /* This code is generated in the post-static area.
1303 * This area is guaranteed to follow the static area
1304 * by the ugly shucking and jiving about 20 lines ago.
1306 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1307 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1313 "%s", iComments2, iComments2);
1314 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1315 copyFile (asmFile, home->oFile);
1317 /* copy over code */
1318 fprintf (asmFile, "%s", iComments2);
1319 fprintf (asmFile, "; code\n");
1320 fprintf (asmFile, "%s", iComments2);
1321 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1322 if (mainf && mainf->fbody) {
1324 /* entry point @ start of CSEG */
1325 fprintf (asmFile,"__sdcc_program_startup:\n");
1327 /* put in the call to main */
1328 fprintf(asmFile,"\tlcall\t_main\n");
1329 if (options.mainreturn) {
1331 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1332 fprintf(asmFile,"\tret\n");
1336 fprintf(asmFile,";\treturn from main will lock up\n");
1337 fprintf(asmFile,"\tsjmp .\n");
1340 copyFile (asmFile, code->oFile);
1343 applyToSet(tmpfileSet,closeTmpFiles);
1344 applyToSet(tmpfileNameSet, rmTmpFiles);
1347 /** Creates a temporary file a'la tmpfile which avoids the bugs
1348 in cygwin wrt c:\tmp.
1349 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1351 FILE *tempfile(void)
1353 const char *tmpdir = NULL;
1355 tmpdir = getenv("TMP");
1356 else if (getenv("TEMP"))
1357 tmpdir = getenv("TEMP");
1358 else if (getenv("TMPDIR"))
1359 tmpdir = getenv("TMPDIR");
1361 char *name = tempnam(tmpdir, "sdcc");
1363 FILE *fp = fopen(name, "w+b");
1366 addSetHead(&tmpfileNameSet, name);
1375 char *gc_strdup(const char *s)
1378 ALLOC_ATOMIC(ret, strlen(s)+1);