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 -------------------------------------------------------------------------*/
30 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
31 #if 0 /* This should no longer be necessary. */
32 // This is a bit messy because we define link ourself
41 // No unistd.h in Borland C++
44 symbol *interrupts[256];
46 void printIval (symbol *, sym_link *, initList *, FILE *);
47 set *publics = NULL; /* public variables */
48 set *externs = NULL; /* Varibles that are declared as extern */
50 /* TODO: this should be configurable (DS803C90 uses more than 6) */
51 int maxInterrupts = 6;
54 extern char *VersionString;
55 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
56 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
58 /*-----------------------------------------------------------------*/
59 /* closeTmpFiles - closes all tmp files created by the compiler */
60 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
61 /*-----------------------------------------------------------------*/
62 DEFSETFUNC (closeTmpFiles)
72 /*-----------------------------------------------------------------*/
73 /* rmTmpFiles - closes all tmp files created by the compiler */
74 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
75 /*-----------------------------------------------------------------*/
76 DEFSETFUNC (rmTmpFiles)
88 /*-----------------------------------------------------------------*/
89 /* copyFile - copies source file to destination file */
90 /*-----------------------------------------------------------------*/
92 copyFile (FILE * dest, FILE * src)
98 if ((ch = fgetc (src)) != EOF)
103 aopLiteralLong (value * val, int offset, int size)
113 /* if it is a float then it gets tricky */
114 /* otherwise it is fairly simple */
115 if (!IS_FLOAT (val->type))
117 unsigned long v = floatFromVal (val);
123 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
126 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
129 /* Hmm. Too big for now. */
132 rs = Safe_calloc (1, strlen (buffer) + 1);
133 return strcpy (rs, buffer);
136 /* PENDING: For now size must be 1 */
139 /* it is type float */
140 fl.f = (float) floatFromVal (val);
142 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
144 tsprintf (buffer, "!immedbyte", fl.c[offset]);
146 rs = Safe_calloc (1, strlen (buffer) + 1);
147 return strcpy (rs, buffer);
150 /*-----------------------------------------------------------------*/
151 /* aopLiteral - string from a literal value */
152 /*-----------------------------------------------------------------*/
154 aopLiteral (value * val, int offset)
156 return aopLiteralLong (val, offset, 1);
159 /*-----------------------------------------------------------------*/
160 /* emitRegularMap - emit code for maps with no special cases */
161 /*-----------------------------------------------------------------*/
163 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
169 /* PENDING: special case here - should remove */
170 if (!strcmp (map->sname, CODE_NAME))
171 tfprintf (map->oFile, "\t!areacode\n", map->sname);
172 else if (!strcmp (map->sname, DATA_NAME))
173 tfprintf (map->oFile, "\t!areadata\n", map->sname);
174 else if (!strcmp (map->sname, HOME_NAME))
175 tfprintf (map->oFile, "\t!areahome\n", map->sname);
177 tfprintf (map->oFile, "\t!area\n", map->sname);
180 /* print the area name */
181 for (sym = setFirstItem (map->syms); sym;
182 sym = setNextItem (map->syms))
185 /* if extern then add it into the extern list */
186 if (IS_EXTERN (sym->etype))
188 addSetHead (&externs, sym);
192 /* if allocation required check is needed
193 then check if the symbol really requires
194 allocation only for local variables */
195 if (arFlag && !IS_AGGREGATE (sym->type) &&
196 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
197 !sym->allocreq && sym->level)
200 /* if global variable & not static or extern
201 and addPublics allowed then add it to the public set */
202 if ((sym->level == 0 ||
203 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
205 !IS_STATIC (sym->etype) &&
206 (sym->used || sym->fbody))
208 addSetHead (&publics, sym);
211 /* if extern then do nothing or is a function
213 if (IS_FUNC (sym->type))
216 /* print extra debug info if required */
217 if ((options.debug || sym->level == 0) && !options.nodebug)
220 cdbSymbol (sym, cdbFile, FALSE, FALSE);
222 if (!sym->level) /* global */
223 if (IS_STATIC (sym->etype))
224 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
226 fprintf (map->oFile, "G$"); /* scope is global */
228 /* symbol is local */
229 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
230 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
233 /* if is has an absolute address then generate
234 an equate for this no need to allocate space */
235 if (SPEC_ABSA (sym->etype))
237 if ((options.debug || sym->level == 0) && !options.nodebug)
238 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
240 fprintf (map->oFile, "%s\t=\t0x%04x\n",
242 SPEC_ADDR (sym->etype));
247 if ((options.debug || sym->level == 0) && !options.nodebug)
248 fprintf (map->oFile, "==.\n");
249 if (IS_STATIC (sym->etype))
250 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
252 tfprintf (map->oFile, "!labeldef\n", sym->rname);
253 tfprintf (map->oFile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
256 /* if it has an initial value then do it only if
257 it is a global variable */
258 if (sym->ival && sym->level == 0)
262 if (IS_AGGREGATE (sym->type))
263 ival = initAggregates (sym, sym->ival, NULL);
265 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
266 decorateType (resolveSymbols (list2expr (sym->ival))));
267 codeOutFile = statsg->oFile;
269 eBBlockFromiCode (iCodeFromAst (ival));
276 /*-----------------------------------------------------------------*/
277 /* initPointer - pointer initialization code massaging */
278 /*-----------------------------------------------------------------*/
280 initPointer (initList * ilist)
283 ast *expr = list2expr (ilist);
288 /* try it the oldway first */
289 if ((val = constExprValue (expr, FALSE)))
292 /* no then we have to do these cludgy checks */
293 /* pointers can be initialized with address of
294 a variable or address of an array element */
295 if (IS_AST_OP (expr) && expr->opval.op == '&')
297 /* address of symbol */
298 if (IS_AST_SYM_VALUE (expr->left))
300 val = copyValue (AST_VALUE (expr->left));
301 val->type = newLink ();
302 if (SPEC_SCLS (expr->left->etype) == S_CODE)
304 DCL_TYPE (val->type) = CPOINTER;
305 DCL_PTR_CONST (val->type) = port->mem.code_ro;
307 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
308 DCL_TYPE (val->type) = FPOINTER;
309 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
310 DCL_TYPE (val->type) = PPOINTER;
311 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
312 DCL_TYPE (val->type) = IPOINTER;
313 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
314 DCL_TYPE (val->type) = EEPPOINTER;
316 DCL_TYPE (val->type) = POINTER;
317 val->type->next = expr->left->ftype;
318 val->etype = getSpec (val->type);
322 /* if address of indexed array */
323 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
324 return valForArray (expr->left);
326 /* if address of structure element then
328 if (IS_AST_OP (expr->left) &&
329 expr->left->opval.op == '.')
331 return valForStructElem (expr->left->left,
336 (&some_struct)->element */
337 if (IS_AST_OP (expr->left) &&
338 expr->left->opval.op == PTR_OP &&
339 IS_ADDRESS_OF_OP (expr->left->left))
340 return valForStructElem (expr->left->left->left,
344 /* case 3. (((char *) &a) +/- constant) */
345 if (IS_AST_OP (expr) &&
346 (expr->opval.op == '+' || expr->opval.op == '-') &&
347 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
348 IS_AST_OP (expr->left->right) &&
349 expr->left->right->opval.op == '&' &&
350 IS_AST_LIT_VALUE (expr->right))
353 return valForCastAggr (expr->left->right->left,
354 expr->left->left->opval.lnk,
355 expr->right, expr->opval.op);
360 werror (E_INIT_WRONG);
365 /*-----------------------------------------------------------------*/
366 /* printChar - formats and prints a characater string with DB */
367 /*-----------------------------------------------------------------*/
369 printChar (FILE * ofile, char *s, int plen)
372 int len = strlen (s);
377 while (len && pplen < plen)
380 while (i && *s && pplen < plen)
382 if (*s < ' ' || *s == '\"')
386 tfprintf (ofile, "\t!ascii\n", buf);
387 tfprintf (ofile, "\t!db !constbyte\n", *s);
402 tfprintf (ofile, "\t!ascii\n", buf);
411 tfprintf (ofile, "\t!db !constbyte\n", 0);
414 /*-----------------------------------------------------------------*/
415 /* return the generic pointer high byte for a given pointer type. */
416 /*-----------------------------------------------------------------*/
418 pointerTypeToGPByte (const int p_type)
426 /* hack - if we get a generic pointer, we just assume
427 * it's an FPOINTER (i.e. in XDATA space).
436 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
444 /*-----------------------------------------------------------------*/
445 /* printPointerType - generates ival for pointer type */
446 /*-----------------------------------------------------------------*/
448 _printPointerType (FILE * oFile, const char *name)
452 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
456 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
460 /*-----------------------------------------------------------------*/
461 /* printPointerType - generates ival for pointer type */
462 /*-----------------------------------------------------------------*/
464 printPointerType (FILE * oFile, const char *name)
466 _printPointerType (oFile, name);
467 fprintf (oFile, "\n");
470 /*-----------------------------------------------------------------*/
471 /* printGPointerType - generates ival for generic pointer type */
472 /*-----------------------------------------------------------------*/
474 printGPointerType (FILE * oFile, const char *name,
475 const unsigned int type)
477 _printPointerType (oFile, name);
478 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type));
481 /*-----------------------------------------------------------------*/
482 /* printIvalType - generates ival for int/char */
483 /*-----------------------------------------------------------------*/
485 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
489 /* if initList is deep */
490 if (ilist->type == INIT_DEEP)
491 ilist = ilist->init.deep;
493 val = list2val (ilist);
494 switch (getSize (type))
498 tfprintf (oFile, "\t!db !constbyte\n", 0);
500 tfprintf (oFile, "\t!dbs\n",
501 aopLiteral (val, 0));
505 if (port->use_dw_for_init)
506 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
508 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
513 tfprintf (oFile, "\t!dw !constword\n", 0);
514 tfprintf (oFile, "\t!dw !constword\n", 0);
518 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
519 aopLiteral (val, 0), aopLiteral (val, 1),
520 aopLiteral (val, 2), aopLiteral (val, 3));
526 /*-----------------------------------------------------------------*/
527 /* printIvalStruct - generates initial value for structures */
528 /*-----------------------------------------------------------------*/
530 printIvalStruct (symbol * sym, sym_link * type,
531 initList * ilist, FILE * oFile)
536 sflds = SPEC_STRUCT (type)->fields;
537 if (ilist->type != INIT_DEEP)
539 werror (E_INIT_STRUCT, sym->name);
543 iloop = ilist->init.deep;
545 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
546 printIval (sflds, sflds->type, iloop, oFile);
551 /*-----------------------------------------------------------------*/
552 /* printIvalChar - generates initital value for character array */
553 /*-----------------------------------------------------------------*/
555 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
563 val = list2val (ilist);
564 /* if the value is a character string */
565 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
567 if (!DCL_ELEM (type))
568 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
570 /* if size mismatch */
571 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
572 /* werror (E_ARRAY_BOUND); */
574 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
576 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
578 tfprintf (oFile, "\t!db !constbyte\n", 0);
586 printChar (oFile, s, strlen (s) + 1);
590 /*-----------------------------------------------------------------*/
591 /* printIvalArray - generates code for array initialization */
592 /*-----------------------------------------------------------------*/
594 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
598 int lcnt = 0, size = 0;
600 /* take care of the special case */
601 /* array of characters can be init */
603 if (IS_CHAR (type->next))
604 if (printIvalChar (type,
605 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
606 oFile, SPEC_CVAL (sym->etype).v_char))
609 /* not the special case */
610 if (ilist->type != INIT_DEEP)
612 werror (E_INIT_STRUCT, sym->name);
616 iloop = ilist->init.deep;
617 lcnt = DCL_ELEM (type);
622 printIval (sym, type->next, iloop, oFile);
623 iloop = (iloop ? iloop->next : NULL);
626 /* if not array limits given & we */
627 /* are out of initialisers then */
628 if (!DCL_ELEM (type) && !iloop)
631 /* no of elements given and we */
632 /* have generated for all of them */
637 /* if we have not been given a size */
638 if (!DCL_ELEM (type))
639 DCL_ELEM (type) = size;
644 /*-----------------------------------------------------------------*/
645 /* printIvalFuncPtr - generate initial value for function pointers */
646 /*-----------------------------------------------------------------*/
648 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
653 val = list2val (ilist);
654 /* check the types */
655 if ((dLvl = checkType (val->type, type->next)) <= 0)
657 tfprintf (oFile, "\t!dw !constword\n", 0);
661 /* now generate the name */
664 if (port->use_dw_for_init)
666 tfprintf (oFile, "\t!dws\n", val->name);
670 printPointerType (oFile, val->name);
673 else if (port->use_dw_for_init)
675 tfprintf (oFile, "\t!dws\n", val->sym->rname);
679 printPointerType (oFile, val->sym->rname);
685 /*-----------------------------------------------------------------*/
686 /* printIvalCharPtr - generates initial values for character pointers */
687 /*-----------------------------------------------------------------*/
689 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
693 /* PENDING: this is _very_ mcs51 specific, including a magic
695 It's also endin specific.
697 size = getSize (type);
699 if (val->name && strlen (val->name))
701 if (size == 1) /* This appears to be Z80 specific?? */
704 "\t!dbs\n", val->name);
706 else if (size == FPTRSIZE)
708 if (port->use_dw_for_init)
710 tfprintf (oFile, "\t!dws\n", val->name);
714 printPointerType (oFile, val->name);
717 else if (size == GPTRSIZE)
719 /* PENDING: 0x02 or 0x%02x, CDATA? */
720 printGPointerType (oFile, val->name,
721 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
722 PTR_TYPE (SPEC_OCLS (val->etype))));
726 fprintf (stderr, "*** internal error: unknown size in "
727 "printIvalCharPtr.\n");
732 /* What is this case? Are these pointers? */
736 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
739 if (port->use_dw_for_init)
740 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
742 tfprintf (oFile, "\t.byte %s,%s\n",
743 aopLiteral (val, 0), aopLiteral (val, 1));
746 /* PENDING: 0x02 or 0x%02x, CDATA? */
747 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
748 aopLiteral (val, 0), aopLiteral (val, 1));
756 if (val->sym && val->sym->isstrlit)
757 addSet (&statsg->syms, val->sym);
762 /*-----------------------------------------------------------------*/
763 /* printIvalPtr - generates initial value for pointers */
764 /*-----------------------------------------------------------------*/
766 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
772 if (ilist->type == INIT_DEEP)
773 ilist = ilist->init.deep;
775 /* function pointer */
776 if (IS_FUNC (type->next))
778 printIvalFuncPtr (type, ilist, oFile);
782 if (!(val = initPointer (ilist)))
785 /* if character pointer */
786 if (IS_CHAR (type->next))
787 if (printIvalCharPtr (sym, type, val, oFile))
791 if (checkType (type, val->type) != 1)
792 werror (E_INIT_WRONG);
794 /* if val is literal */
795 if (IS_LITERAL (val->etype))
797 switch (getSize (type))
800 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
803 if (port->use_dw_for_init)
804 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
806 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
809 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
810 aopLiteral (val, 0), aopLiteral (val, 1));
816 size = getSize (type);
818 if (size == 1) /* Z80 specific?? */
820 tfprintf (oFile, "\t!dbs\n", val->name);
822 else if (size == FPTRSIZE)
824 tfprintf (oFile, "\t!dws\n", val->name);
826 else if (size == GPTRSIZE)
828 printGPointerType (oFile, val->name,
829 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
830 PTR_TYPE (SPEC_OCLS (val->etype))));
835 /*-----------------------------------------------------------------*/
836 /* printIval - generates code for initial value */
837 /*-----------------------------------------------------------------*/
839 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
844 /* if structure then */
845 if (IS_STRUCT (type))
847 printIvalStruct (sym, type, ilist, oFile);
851 /* if this is a pointer */
854 printIvalPtr (sym, type, ilist, oFile);
858 /* if this is an array */
861 printIvalArray (sym, type, ilist, oFile);
865 /* if type is SPECIFIER */
868 printIvalType (type, ilist, oFile);
873 /*-----------------------------------------------------------------*/
874 /* emitStaticSeg - emitcode for the static segment */
875 /*-----------------------------------------------------------------*/
877 emitStaticSeg (memmap * map, FILE * out)
881 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
885 /* for all variables in this segment do */
886 for (sym = setFirstItem (map->syms); sym;
887 sym = setNextItem (map->syms))
890 /* if it is "extern" then do nothing */
891 if (IS_EXTERN (sym->etype))
894 /* if it is not static add it to the public
896 if (!IS_STATIC (sym->etype))
897 addSetHead (&publics, sym);
899 /* print extra debug info if required */
900 if ((options.debug || sym->level == 0) && !options.nodebug)
903 cdbSymbol (sym, cdbFile, FALSE, FALSE);
907 if (IS_STATIC (sym->etype))
908 fprintf (out, "F%s$", moduleName); /* scope is file */
910 fprintf (out, "G$"); /* scope is global */
913 /* symbol is local */
914 fprintf (out, "L%s$",
915 (sym->localof ? sym->localof->name : "-null-"));
916 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
919 /* if it has an absolute address */
920 if (SPEC_ABSA (sym->etype))
922 if ((options.debug || sym->level == 0) && !options.nodebug)
923 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
925 fprintf (out, "%s\t=\t0x%04x\n",
927 SPEC_ADDR (sym->etype));
931 if ((options.debug || sym->level == 0) && !options.nodebug)
932 fprintf (out, " == .\n");
934 /* if it has an initial value */
937 fprintf (out, "%s:\n", sym->rname);
939 resolveIvalSym (sym->ival);
940 printIval (sym, sym->type, sym->ival, out);
946 fprintf (out, "%s:\n", sym->rname);
947 /* special case for character strings */
948 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
949 SPEC_CVAL (sym->etype).v_char)
951 SPEC_CVAL (sym->etype).v_char,
952 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
954 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
960 /*-----------------------------------------------------------------*/
961 /* emitMaps - emits the code for the data portion the code */
962 /*-----------------------------------------------------------------*/
966 /* no special considerations for the following
967 data, idata & bit & xdata */
968 emitRegularMap (data, TRUE, TRUE);
969 emitRegularMap (idata, TRUE, TRUE);
970 emitRegularMap (bit, TRUE, FALSE);
971 emitRegularMap (xdata, TRUE, TRUE);
972 emitRegularMap (sfr, FALSE, FALSE);
973 emitRegularMap (sfrbit, FALSE, FALSE);
974 emitRegularMap (home, TRUE, FALSE);
975 emitRegularMap (code, TRUE, FALSE);
977 emitStaticSeg (statsg, code->oFile);
980 /*-----------------------------------------------------------------*/
981 /* flushStatics - flush all currently defined statics out to file */
982 /* and delete. Temporary function */
983 /*-----------------------------------------------------------------*/
987 emitStaticSeg (statsg, codeOutFile);
991 /*-----------------------------------------------------------------*/
992 /* createInterruptVect - creates the interrupt vector */
993 /*-----------------------------------------------------------------*/
995 createInterruptVect (FILE * vFile)
998 mainf = newSymbol ("main", 0);
1001 /* only if the main function exists */
1002 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1004 if (!options.cc_only)
1009 /* if the main is only a prototype ie. no body then do nothing */
1012 /* if ! compile only then main function should be present */
1013 if (!options.cc_only)
1018 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1019 fprintf (vFile, "__interrupt_vect:\n");
1022 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1024 /* "generic" interrupt table header (if port doesn't specify one).
1026 * Look suspiciously like 8051 code to me...
1029 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1032 /* now for the other interrupts */
1033 for (; i < maxInterrupts; i++)
1036 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1038 fprintf (vFile, "\treti\n\t.ds\t7\n");
1045 ";--------------------------------------------------------\n"
1046 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1050 ";--------------------------------------------------------\n"};
1053 /*-----------------------------------------------------------------*/
1054 /* initialComments - puts in some initial comments */
1055 /*-----------------------------------------------------------------*/
1057 initialComments (FILE * afile)
1061 fprintf (afile, "%s", iComments1);
1062 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1063 fprintf (afile, "%s", iComments2);
1066 /*-----------------------------------------------------------------*/
1067 /* printPublics - generates .global for publics */
1068 /*-----------------------------------------------------------------*/
1070 printPublics (FILE * afile)
1074 fprintf (afile, "%s", iComments2);
1075 fprintf (afile, "; Public variables in this module\n");
1076 fprintf (afile, "%s", iComments2);
1078 for (sym = setFirstItem (publics); sym;
1079 sym = setNextItem (publics))
1080 tfprintf (afile, "\t!global\n", sym->rname);
1083 /*-----------------------------------------------------------------*/
1084 /* printExterns - generates .global for externs */
1085 /*-----------------------------------------------------------------*/
1087 printExterns (FILE * afile)
1091 fprintf (afile, "%s", iComments2);
1092 fprintf (afile, "; Externals used\n");
1093 fprintf (afile, "%s", iComments2);
1095 for (sym = setFirstItem (externs); sym;
1096 sym = setNextItem (externs))
1097 tfprintf (afile, "\t!global\n", sym->rname);
1100 /*-----------------------------------------------------------------*/
1101 /* emitOverlay - will emit code for the overlay stuff */
1102 /*-----------------------------------------------------------------*/
1104 emitOverlay (FILE * afile)
1108 if (!elementsInSet (ovrSetSets))
1109 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1111 /* for each of the sets in the overlay segment do */
1112 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1113 ovrset = setNextItem (ovrSetSets))
1118 if (elementsInSet (ovrset))
1120 /* this dummy area is used to fool the assembler
1121 otherwise the assembler will append each of these
1122 declarations into one chunk and will not overlay
1124 fprintf (afile, "\t.area _DUMMY\n");
1125 /* output the area informtion */
1126 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1129 for (sym = setFirstItem (ovrset); sym;
1130 sym = setNextItem (ovrset))
1133 /* if extern then add it to the publics tabledo nothing */
1134 if (IS_EXTERN (sym->etype))
1137 /* if allocation required check is needed
1138 then check if the symbol really requires
1139 allocation only for local variables */
1140 if (!IS_AGGREGATE (sym->type) &&
1141 !(sym->_isparm && !IS_REGPARM (sym->etype))
1142 && !sym->allocreq && sym->level)
1145 /* if global variable & not static or extern
1146 and addPublics allowed then add it to the public set */
1147 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1148 && !IS_STATIC (sym->etype))
1149 addSetHead (&publics, sym);
1151 /* if extern then do nothing or is a function
1153 if (IS_FUNC (sym->type))
1156 /* print extra debug info if required */
1157 if ((options.debug || sym->level == 0) && !options.nodebug)
1160 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1164 if (IS_STATIC (sym->etype))
1165 fprintf (afile, "F%s$", moduleName); /* scope is file */
1167 fprintf (afile, "G$"); /* scope is global */
1170 /* symbol is local */
1171 fprintf (afile, "L%s$",
1172 (sym->localof ? sym->localof->name : "-null-"));
1173 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1176 /* if is has an absolute address then generate
1177 an equate for this no need to allocate space */
1178 if (SPEC_ABSA (sym->etype))
1181 if ((options.debug || sym->level == 0) && !options.nodebug)
1182 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1184 fprintf (afile, "%s\t=\t0x%04x\n",
1186 SPEC_ADDR (sym->etype));
1190 if ((options.debug || sym->level == 0) && !options.nodebug)
1191 fprintf (afile, "==.\n");
1193 /* allocate space */
1194 tfprintf (afile, "!labeldef\n", sym->rname);
1195 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1202 /*-----------------------------------------------------------------*/
1203 /* glue - the final glue that hold the whole thing together */
1204 /*-----------------------------------------------------------------*/
1210 FILE *ovrFile = tempfile ();
1212 addSetHead (&tmpfileSet, ovrFile);
1213 /* print the global struct definitions */
1214 if (options.debug && !options.nodebug)
1215 cdbStructBlock (0, cdbFile);
1217 vFile = tempfile ();
1218 /* PENDING: this isnt the best place but it will do */
1219 if (port->general.glue_up_main)
1221 /* create the interrupt vector table */
1222 createInterruptVect (vFile);
1225 addSetHead (&tmpfileSet, vFile);
1227 /* emit code for the all the variables declared */
1229 /* do the overlay segments */
1230 emitOverlay (ovrFile);
1232 /* now put it all together into the assembler file */
1233 /* create the assembler file name */
1235 if (!options.c1mode)
1237 sprintf (buffer, srcFileName);
1238 strcat (buffer, ".asm");
1242 strcpy (buffer, options.out_name);
1245 if (!(asmFile = fopen (buffer, "w")))
1247 werror (E_FILE_OPEN_ERR, buffer);
1251 /* initial comments */
1252 initialComments (asmFile);
1254 /* print module name */
1255 tfprintf (asmFile, "\t!module\n", moduleName);
1256 tfprintf (asmFile, "\t!fileprelude\n");
1258 /* Let the port generate any global directives, etc. */
1259 if (port->genAssemblerPreamble)
1261 port->genAssemblerPreamble (asmFile);
1264 /* print the global variables in this module */
1265 printPublics (asmFile);
1266 if (port->assembler.externGlobal)
1267 printExterns (asmFile);
1269 /* copy the sfr segment */
1270 fprintf (asmFile, "%s", iComments2);
1271 fprintf (asmFile, "; special function registers\n");
1272 fprintf (asmFile, "%s", iComments2);
1273 copyFile (asmFile, sfr->oFile);
1275 /* copy the sbit segment */
1276 fprintf (asmFile, "%s", iComments2);
1277 fprintf (asmFile, "; special function bits \n");
1278 fprintf (asmFile, "%s", iComments2);
1279 copyFile (asmFile, sfrbit->oFile);
1281 /* copy the data segment */
1282 fprintf (asmFile, "%s", iComments2);
1283 fprintf (asmFile, "; internal ram data\n");
1284 fprintf (asmFile, "%s", iComments2);
1285 copyFile (asmFile, data->oFile);
1288 /* create the overlay segments */
1289 fprintf (asmFile, "%s", iComments2);
1290 fprintf (asmFile, "; overlayable items in internal ram \n");
1291 fprintf (asmFile, "%s", iComments2);
1292 copyFile (asmFile, ovrFile);
1294 /* create the stack segment MOF */
1295 if (mainf && mainf->fbody)
1297 fprintf (asmFile, "%s", iComments2);
1298 fprintf (asmFile, "; Stack segment in internal ram \n");
1299 fprintf (asmFile, "%s", iComments2);
1300 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1301 "__start__stack:\n\t.ds\t1\n\n");
1304 /* create the idata segment */
1305 fprintf (asmFile, "%s", iComments2);
1306 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1307 fprintf (asmFile, "%s", iComments2);
1308 copyFile (asmFile, idata->oFile);
1310 /* copy the bit segment */
1311 fprintf (asmFile, "%s", iComments2);
1312 fprintf (asmFile, "; bit data\n");
1313 fprintf (asmFile, "%s", iComments2);
1314 copyFile (asmFile, bit->oFile);
1316 /* if external stack then reserve space of it */
1317 if (mainf && mainf->fbody && options.useXstack)
1319 fprintf (asmFile, "%s", iComments2);
1320 fprintf (asmFile, "; external stack \n");
1321 fprintf (asmFile, "%s", iComments2);
1322 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1323 fprintf (asmFile, "\t.ds 256\n");
1327 /* copy xtern ram data */
1328 fprintf (asmFile, "%s", iComments2);
1329 fprintf (asmFile, "; external ram data\n");
1330 fprintf (asmFile, "%s", iComments2);
1331 copyFile (asmFile, xdata->oFile);
1333 /* copy the interrupt vector table */
1334 if (mainf && mainf->fbody)
1336 fprintf (asmFile, "%s", iComments2);
1337 fprintf (asmFile, "; interrupt vector \n");
1338 fprintf (asmFile, "%s", iComments2);
1339 copyFile (asmFile, vFile);
1342 /* copy global & static initialisations */
1343 fprintf (asmFile, "%s", iComments2);
1344 fprintf (asmFile, "; global & static initialisations\n");
1345 fprintf (asmFile, "%s", iComments2);
1347 /* Everywhere we generate a reference to the static_name area,
1348 * (which is currently only here), we immediately follow it with a
1349 * definition of the post_static_name area. This guarantees that
1350 * the post_static_name area will immediately follow the static_name
1353 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1354 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1355 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1357 if (mainf && mainf->fbody)
1359 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1360 /* if external stack is specified then the
1361 higher order byte of the xdatalocation is
1362 going into P2 and the lower order going into
1364 if (options.useXstack)
1366 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1367 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1368 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1369 (unsigned int) options.xdata_loc & 0xff);
1372 /* initialise the stack pointer */
1373 /* if the user specified a value then use it */
1374 if (options.stack_loc)
1375 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1377 /* no: we have to compute it */
1378 if (!options.stackOnData && maxRegBank <= 3)
1379 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1381 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1383 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1384 fprintf (asmFile, "\tmov\ta,dpl\n");
1385 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1386 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1387 fprintf (asmFile, "__sdcc_init_data:\n");
1390 copyFile (asmFile, statsg->oFile);
1392 if (port->general.glue_up_main && mainf && mainf->fbody)
1394 /* This code is generated in the post-static area.
1395 * This area is guaranteed to follow the static area
1396 * by the ugly shucking and jiving about 20 lines ago.
1398 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1399 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1405 "%s", iComments2, iComments2);
1406 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1407 copyFile (asmFile, home->oFile);
1409 /* copy over code */
1410 fprintf (asmFile, "%s", iComments2);
1411 fprintf (asmFile, "; code\n");
1412 fprintf (asmFile, "%s", iComments2);
1413 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1414 if (mainf && mainf->fbody)
1417 /* entry point @ start of CSEG */
1418 fprintf (asmFile, "__sdcc_program_startup:\n");
1420 /* put in the call to main */
1421 fprintf (asmFile, "\tlcall\t_main\n");
1422 if (options.mainreturn)
1425 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1426 fprintf (asmFile, "\tret\n");
1432 fprintf (asmFile, ";\treturn from main will lock up\n");
1433 fprintf (asmFile, "\tsjmp .\n");
1436 copyFile (asmFile, code->oFile);
1439 applyToSet (tmpfileSet, closeTmpFiles);
1440 applyToSet (tmpfileNameSet, rmTmpFiles);
1443 /** Creates a temporary file a'la tmpfile which avoids the bugs
1444 in cygwin wrt c:\tmp.
1445 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1450 #if !defined(_MSC_VER)
1451 const char *tmpdir = NULL;
1453 tmpdir = getenv ("TMP");
1454 else if (getenv ("TEMP"))
1455 tmpdir = getenv ("TEMP");
1456 else if (getenv ("TMPDIR"))
1457 tmpdir = getenv ("TMPDIR");
1460 char *name = tempnam (tmpdir, "sdcc");
1463 FILE *fp = fopen (name, "w+b");
1466 addSetHead (&tmpfileNameSet, name);
1477 gc_strdup (const char *s)
1480 ret = Safe_calloc (1, strlen (s) + 1);