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 0 /* This should no longer be necessary. */
31 // This is a bit messy because we define link ourself
39 // No unistd.h in Borland C++
42 symbol *interrupts[256];
44 void printIval (symbol *, sym_link *, initList *, FILE *);
45 set *publics = NULL; /* public variables */
46 set *externs = NULL; /* Varibles that are declared as extern */
48 /* TODO: this should be configurable (DS803C90 uses more than 6) */
49 int maxInterrupts = 6;
52 extern char *VersionString;
53 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
54 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
56 /*-----------------------------------------------------------------*/
57 /* closeTmpFiles - closes all tmp files created by the compiler */
58 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
59 /*-----------------------------------------------------------------*/
60 DEFSETFUNC(closeTmpFiles)
70 /*-----------------------------------------------------------------*/
71 /* rmTmpFiles - closes all tmp files created by the compiler */
72 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
73 /*-----------------------------------------------------------------*/
74 DEFSETFUNC(rmTmpFiles)
85 /*-----------------------------------------------------------------*/
86 /* copyFile - copies source file to destination file */
87 /*-----------------------------------------------------------------*/
88 void copyFile (FILE * dest, FILE * src)
94 if ((ch = fgetc (src)) != EOF)
98 char *aopLiteralLong(value *val, int offset, int size)
106 /* if it is a float then it gets tricky */
107 /* otherwise it is fairly simple */
108 if (!IS_FLOAT(val->type)) {
109 unsigned long v = floatFromVal(val);
114 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
117 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
120 /* Hmm. Too big for now. */
123 ALLOC_ATOMIC(rs,strlen(buffer)+1);
124 return strcpy (rs,buffer);
127 /* PENDING: For now size must be 1 */
130 /* it is type float */
131 fl.f = (float) floatFromVal(val);
133 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
135 tsprintf(buffer, "!immedbyte", fl.c[offset]);
137 ALLOC_ATOMIC(rs,strlen(buffer)+1);
138 return strcpy (rs,buffer);
141 /*-----------------------------------------------------------------*/
142 /* aopLiteral - string from a literal value */
143 /*-----------------------------------------------------------------*/
144 char *aopLiteral (value *val, int offset)
146 return aopLiteralLong(val, offset, 1);
149 /*-----------------------------------------------------------------*/
150 /* emitRegularMap - emit code for maps with no special cases */
151 /*-----------------------------------------------------------------*/
152 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
157 /* PENDING: special case here - should remove */
158 if (!strcmp(map->sname, CODE_NAME))
159 tfprintf(map->oFile, "\t!areacode\n", map->sname);
160 else if (!strcmp(map->sname, DATA_NAME))
161 tfprintf(map->oFile, "\t!areadata\n", map->sname);
162 else if (!strcmp(map->sname, HOME_NAME))
163 tfprintf(map->oFile, "\t!areahome\n", map->sname);
165 tfprintf(map->oFile, "\t!area\n", map->sname);
168 /* print the area name */
169 for (sym = setFirstItem (map->syms); sym;
170 sym = setNextItem (map->syms)) {
172 /* if extern then add it into the extern list */
173 if (IS_EXTERN (sym->etype)) {
174 addSetHead (&externs, sym);
178 /* if allocation required check is needed
179 then check if the symbol really requires
180 allocation only for local variables */
181 if (arFlag && !IS_AGGREGATE(sym->type) &&
182 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
183 !sym->allocreq && sym->level)
186 /* if global variable & not static or extern
187 and addPublics allowed then add it to the public set */
188 if ((sym->level == 0 ||
189 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
191 !IS_STATIC (sym->etype) &&
192 (sym->used || sym->fbody)) {
193 addSetHead (&publics, sym);
196 /* if extern then do nothing or is a function
198 if (IS_FUNC (sym->type))
201 /* print extra debug info if required */
202 if ((options.debug || sym->level == 0) && !options.nodebug) {
204 cdbSymbol(sym,cdbFile,FALSE,FALSE);
206 if (!sym->level) /* global */
207 if (IS_STATIC(sym->etype))
208 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
210 fprintf(map->oFile,"G$"); /* scope is global */
212 /* symbol is local */
213 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
214 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
217 /* if is has an absolute address then generate
218 an equate for this no need to allocate space */
219 if (SPEC_ABSA (sym->etype)) {
220 if ((options.debug || sym->level == 0) && !options.nodebug)
221 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
223 fprintf (map->oFile, "%s\t=\t0x%04x\n",
225 SPEC_ADDR (sym->etype));
229 if ((options.debug || sym->level == 0) && !options.nodebug)
230 fprintf(map->oFile,"==.\n");
231 if (IS_STATIC(sym->etype))
232 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
234 tfprintf(map->oFile, "!labeldef\n", sym->rname);
235 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
238 /* if it has an initial value then do it only if
239 it is a global variable */
240 if (sym->ival && sym->level == 0) {
243 if (IS_AGGREGATE (sym->type))
244 ival = initAggregates (sym, sym->ival, NULL);
246 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
247 decorateType (resolveSymbols (list2expr (sym->ival))));
248 codeOutFile = statsg->oFile;
250 eBBlockFromiCode (iCodeFromAst (ival));
257 /*-----------------------------------------------------------------*/
258 /* initPointer - pointer initialization code massaging */
259 /*-----------------------------------------------------------------*/
260 value *initPointer (initList *ilist)
263 ast *expr = list2expr(ilist);
268 /* try it the oldway first */
269 if ((val = constExprValue(expr,FALSE)))
272 /* no then we have to do these cludgy checks */
273 /* pointers can be initialized with address of
274 a variable or address of an array element */
275 if (IS_AST_OP(expr) && expr->opval.op == '&') {
276 /* address of symbol */
277 if (IS_AST_SYM_VALUE(expr->left)) {
278 val = copyValue(AST_VALUE(expr->left));
279 val->type = newLink();
280 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
281 DCL_TYPE(val->type) = CPOINTER ;
282 DCL_PTR_CONST(val->type) = port->mem.code_ro;
285 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
286 DCL_TYPE(val->type) = FPOINTER;
288 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
289 DCL_TYPE(val->type) = PPOINTER ;
291 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
292 DCL_TYPE(val->type) = IPOINTER ;
294 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
295 DCL_TYPE(val->type) = EEPPOINTER ;
297 DCL_TYPE(val->type) = POINTER ;
298 val->type->next = expr->left->ftype;
299 val->etype = getSpec(val->type);
303 /* if address of indexed array */
304 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
305 return valForArray(expr->left);
307 /* if address of structure element then
309 if (IS_AST_OP(expr->left) &&
310 expr->left->opval.op == '.' ) {
311 return valForStructElem(expr->left->left,
316 (&some_struct)->element */
317 if (IS_AST_OP(expr->left) &&
318 expr->left->opval.op == PTR_OP &&
319 IS_ADDRESS_OF_OP(expr->left->left))
320 return valForStructElem(expr->left->left->left,
324 /* case 3. (((char *) &a) +/- constant) */
325 if (IS_AST_OP(expr) &&
326 (expr->opval.op == '+' || expr->opval.op == '-') &&
327 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
328 IS_AST_OP(expr->left->right) &&
329 expr->left->right->opval.op == '&' &&
330 IS_AST_LIT_VALUE(expr->right)) {
332 return valForCastAggr(expr->left->right->left,
333 expr->left->left->opval.lnk,
334 expr->right,expr->opval.op);
339 werror(E_INIT_WRONG);
344 /*-----------------------------------------------------------------*/
345 /* printChar - formats and prints a characater string with DB */
346 /*-----------------------------------------------------------------*/
347 void printChar (FILE * ofile, char *s, int plen)
350 int len = strlen (s);
355 while (len && pplen < plen) {
357 while (i && *s && pplen < plen) {
358 if (*s < ' ' || *s == '\"') {
361 tfprintf(ofile, "\t!ascii\n", buf);
362 tfprintf(ofile, "\t!db !constbyte\n", *s);
375 tfprintf(ofile, "\t!ascii\n", buf);
384 tfprintf(ofile, "\t!db !constbyte\n", 0);
387 /*-----------------------------------------------------------------*/
388 /* return the generic pointer high byte for a given pointer type. */
389 /*-----------------------------------------------------------------*/
390 int pointerTypeToGPByte(const int p_type)
398 /* hack - if we get a generic pointer, we just assume
399 * it's an FPOINTER (i.e. in XDATA space).
408 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
416 /*-----------------------------------------------------------------*/
417 /* printPointerType - generates ival for pointer type */
418 /*-----------------------------------------------------------------*/
419 void _printPointerType(FILE *oFile, const char *name)
423 fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
427 fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
431 /*-----------------------------------------------------------------*/
432 /* printPointerType - generates ival for pointer type */
433 /*-----------------------------------------------------------------*/
434 void printPointerType(FILE *oFile, const char *name)
436 _printPointerType(oFile, name);
437 fprintf(oFile, "\n");
440 /*-----------------------------------------------------------------*/
441 /* printGPointerType - generates ival for generic pointer type */
442 /*-----------------------------------------------------------------*/
443 void printGPointerType(FILE *oFile, const char *name,
444 const unsigned int type)
446 _printPointerType(oFile,name);
447 fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type));
450 /*-----------------------------------------------------------------*/
451 /* printIvalType - generates ival for int/char */
452 /*-----------------------------------------------------------------*/
453 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
457 /* if initList is deep */
458 if (ilist->type == INIT_DEEP)
459 ilist = ilist->init.deep;
461 val = list2val (ilist);
462 switch (getSize (type)) {
465 tfprintf(oFile, "\t!db !constbyte\n", 0);
467 tfprintf(oFile, "\t!dbs\n",
468 aopLiteral (val, 0));
472 if (port->use_dw_for_init)
473 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
475 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
479 tfprintf (oFile, "\t!dw !constword\n", 0);
480 tfprintf (oFile, "\t!dw !constword\n", 0);
483 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
484 aopLiteral (val, 0), aopLiteral (val, 1),
485 aopLiteral (val, 2), aopLiteral (val, 3));
491 /*-----------------------------------------------------------------*/
492 /* printIvalStruct - generates initial value for structures */
493 /*-----------------------------------------------------------------*/
494 void printIvalStruct (symbol * sym,sym_link * type,
495 initList * ilist, FILE * oFile)
500 sflds = SPEC_STRUCT (type)->fields;
501 if (ilist->type != INIT_DEEP) {
502 werror (E_INIT_STRUCT, sym->name);
506 iloop = ilist->init.deep;
508 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
509 printIval (sflds, sflds->type, iloop, oFile);
514 /*-----------------------------------------------------------------*/
515 /* printIvalChar - generates initital value for character array */
516 /*-----------------------------------------------------------------*/
517 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
524 val = list2val (ilist);
525 /* if the value is a character string */
526 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
527 if (!DCL_ELEM (type))
528 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
530 /* if size mismatch */
531 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
532 /* werror (E_ARRAY_BOUND); */
534 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
536 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
538 tfprintf (oFile, "\t!db !constbyte\n", 0);
546 printChar (oFile, s,strlen(s)+1);
550 /*-----------------------------------------------------------------*/
551 /* printIvalArray - generates code for array initialization */
552 /*-----------------------------------------------------------------*/
553 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
557 int lcnt = 0, size = 0;
559 /* take care of the special case */
560 /* array of characters can be init */
562 if (IS_CHAR (type->next))
563 if (printIvalChar (type,
564 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
565 oFile, SPEC_CVAL (sym->etype).v_char))
568 /* not the special case */
569 if (ilist->type != INIT_DEEP) {
570 werror (E_INIT_STRUCT, sym->name);
574 iloop = ilist->init.deep;
575 lcnt = DCL_ELEM (type);
579 printIval (sym, type->next, iloop, oFile);
580 iloop = (iloop ? iloop->next : NULL);
583 /* if not array limits given & we */
584 /* are out of initialisers then */
585 if (!DCL_ELEM (type) && !iloop)
588 /* no of elements given and we */
589 /* have generated for all of them */
594 /* if we have not been given a size */
595 if (!DCL_ELEM (type))
596 DCL_ELEM (type) = size;
601 /*-----------------------------------------------------------------*/
602 /* printIvalFuncPtr - generate initial value for function pointers */
603 /*-----------------------------------------------------------------*/
604 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
609 val = list2val (ilist);
610 /* check the types */
611 if ((dLvl = checkType (val->type, type->next)) <= 0) {
612 tfprintf(oFile, "\t!dw !constword\n", 0);
616 /* now generate the name */
618 if (port->use_dw_for_init)
620 tfprintf(oFile, "\t!dws\n", val->name);
624 printPointerType(oFile, val->name);
628 if (port->use_dw_for_init)
630 tfprintf(oFile, "\t!dws\n", val->sym->rname);
634 printPointerType(oFile, val->sym->rname);
640 /*-----------------------------------------------------------------*/
641 /* printIvalCharPtr - generates initial values for character pointers */
642 /*-----------------------------------------------------------------*/
643 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
647 /* PENDING: this is _very_ mcs51 specific, including a magic
649 It's also endin specific.
651 size = getSize (type);
653 if (val->name && strlen(val->name)) {
654 if (size == 1) /* This appears to be Z80 specific?? */
657 "\t!dbs\n", val->name);
659 else if (size == FPTRSIZE)
661 if (port->use_dw_for_init)
663 tfprintf(oFile, "\t!dws\n", val->name);
667 printPointerType(oFile, val->name);
670 else if (size == GPTRSIZE)
672 /* PENDING: 0x02 or 0x%02x, CDATA? */
673 printGPointerType(oFile, val->name,
674 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
675 PTR_TYPE(SPEC_OCLS(val->etype))));
679 fprintf(stderr, "*** internal error: unknown size in "
680 "printIvalCharPtr.\n");
684 /* What is this case? Are these pointers? */
687 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
690 if (port->use_dw_for_init)
691 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
693 tfprintf(oFile, "\t.byte %s,%s\n",
694 aopLiteral(val, 0),aopLiteral(val, 1));
697 /* PENDING: 0x02 or 0x%02x, CDATA? */
698 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
699 aopLiteral (val, 0), aopLiteral (val, 1));
707 if (val->sym && val->sym->isstrlit)
708 addSet (&statsg->syms, val->sym);
713 /*-----------------------------------------------------------------*/
714 /* printIvalPtr - generates initial value for pointers */
715 /*-----------------------------------------------------------------*/
716 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
722 if (ilist->type == INIT_DEEP)
723 ilist = ilist->init.deep;
725 /* function pointer */
726 if (IS_FUNC (type->next)) {
727 printIvalFuncPtr (type, ilist, oFile);
731 if (!(val = initPointer (ilist)))
734 /* if character pointer */
735 if (IS_CHAR (type->next))
736 if (printIvalCharPtr (sym, type, val, oFile))
740 if (checkType (type, val->type) != 1)
741 werror (E_INIT_WRONG);
743 /* if val is literal */
744 if (IS_LITERAL (val->etype)) {
745 switch (getSize (type)) {
747 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
750 if (port->use_dw_for_init)
751 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
753 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
756 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
757 aopLiteral (val, 0), aopLiteral (val, 1));
763 size = getSize (type);
765 if (size == 1) /* Z80 specific?? */
767 tfprintf (oFile, "\t!dbs\n", val->name);
769 else if (size == FPTRSIZE)
771 tfprintf (oFile, "\t!dws\n", val->name);
773 else if (size == GPTRSIZE)
775 printGPointerType(oFile, val->name,
776 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
777 PTR_TYPE(SPEC_OCLS(val->etype))));
782 /*-----------------------------------------------------------------*/
783 /* printIval - generates code for initial value */
784 /*-----------------------------------------------------------------*/
785 void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
790 /* if structure then */
791 if (IS_STRUCT (type)) {
792 printIvalStruct (sym, type, ilist, oFile);
796 /* if this is a pointer */
798 printIvalPtr (sym, type, ilist, oFile);
802 /* if this is an array */
803 if (IS_ARRAY (type)) {
804 printIvalArray (sym, type, ilist, oFile);
808 /* if type is SPECIFIER */
809 if (IS_SPEC (type)) {
810 printIvalType (type, ilist, oFile);
815 /*-----------------------------------------------------------------*/
816 /* emitStaticSeg - emitcode for the static segment */
817 /*-----------------------------------------------------------------*/
818 void emitStaticSeg(memmap * map, FILE *out)
822 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
826 /* for all variables in this segment do */
827 for (sym = setFirstItem (map->syms); sym;
828 sym = setNextItem (map->syms)) {
830 /* if it is "extern" then do nothing */
831 if (IS_EXTERN (sym->etype))
834 /* if it is not static add it to the public
836 if (!IS_STATIC (sym->etype))
837 addSetHead (&publics, sym);
839 /* print extra debug info if required */
840 if ((options.debug || sym->level == 0) && !options.nodebug) {
842 cdbSymbol(sym,cdbFile,FALSE,FALSE);
844 if (!sym->level) { /* global */
845 if (IS_STATIC(sym->etype))
846 fprintf(out,"F%s$",moduleName); /* scope is file */
848 fprintf(out,"G$"); /* scope is global */
851 /* symbol is local */
853 (sym->localof ? sym->localof->name : "-null-"));
854 fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
857 /* if it has an absolute address */
858 if (SPEC_ABSA (sym->etype)) {
859 if ((options.debug || sym->level == 0) && !options.nodebug)
860 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
862 fprintf (out, "%s\t=\t0x%04x\n",
864 SPEC_ADDR (sym->etype));
867 if ((options.debug || sym->level == 0) && !options.nodebug)
868 fprintf(out," == .\n");
870 /* if it has an initial value */
872 fprintf (out, "%s:\n", sym->rname);
874 resolveIvalSym (sym->ival);
875 printIval (sym, sym->type, sym->ival, out);
880 fprintf (out, "%s:\n", sym->rname);
881 /* special case for character strings */
882 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
883 SPEC_CVAL (sym->etype).v_char)
885 SPEC_CVAL (sym->etype).v_char,
886 strlen(SPEC_CVAL (sym->etype).v_char)+1);
888 tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
894 /*-----------------------------------------------------------------*/
895 /* emitMaps - emits the code for the data portion the code */
896 /*-----------------------------------------------------------------*/
899 /* no special considerations for the following
900 data, idata & bit & xdata */
901 emitRegularMap (data, TRUE, TRUE);
902 emitRegularMap (idata, TRUE,TRUE);
903 emitRegularMap (bit, TRUE,FALSE);
904 emitRegularMap (xdata, TRUE,TRUE);
905 emitRegularMap (sfr, FALSE,FALSE);
906 emitRegularMap (sfrbit, FALSE,FALSE);
907 emitRegularMap (home, TRUE,FALSE);
908 emitRegularMap (code, TRUE,FALSE);
910 emitStaticSeg (statsg, code->oFile);
913 /*-----------------------------------------------------------------*/
914 /* flushStatics - flush all currently defined statics out to file */
915 /* and delete. Temporary function */
916 /*-----------------------------------------------------------------*/
917 void flushStatics(void)
919 emitStaticSeg(statsg, codeOutFile);
923 /*-----------------------------------------------------------------*/
924 /* createInterruptVect - creates the interrupt vector */
925 /*-----------------------------------------------------------------*/
926 void createInterruptVect (FILE * vFile)
929 mainf = newSymbol ("main", 0);
932 /* only if the main function exists */
933 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
934 if (!options.cc_only)
939 /* if the main is only a prototype ie. no body then do nothing */
941 /* if ! compile only then main function should be present */
942 if (!options.cc_only)
947 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
948 fprintf (vFile, "__interrupt_vect:\n");
951 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
953 /* "generic" interrupt table header (if port doesn't specify one).
955 * Look suspiciously like 8051 code to me...
958 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
961 /* now for the other interrupts */
962 for (; i < maxInterrupts; i++) {
964 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
966 fprintf (vFile, "\treti\n\t.ds\t7\n");
973 ";--------------------------------------------------------\n"
974 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
978 ";--------------------------------------------------------\n"};
981 /*-----------------------------------------------------------------*/
982 /* initialComments - puts in some initial comments */
983 /*-----------------------------------------------------------------*/
984 void initialComments (FILE * afile)
988 fprintf (afile, "%s", iComments1);
989 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
990 fprintf (afile, "%s", iComments2);
993 /*-----------------------------------------------------------------*/
994 /* printPublics - generates .global for publics */
995 /*-----------------------------------------------------------------*/
996 void printPublics (FILE * afile)
1000 fprintf (afile, "%s", iComments2);
1001 fprintf (afile, "; Public variables in this module\n");
1002 fprintf (afile, "%s", iComments2);
1004 for (sym = setFirstItem (publics); sym;
1005 sym = setNextItem (publics))
1006 tfprintf(afile, "\t!global\n", sym->rname);
1009 /*-----------------------------------------------------------------*/
1010 /* printExterns - generates .global for externs */
1011 /*-----------------------------------------------------------------*/
1012 void printExterns (FILE * afile)
1016 fprintf (afile, "%s", iComments2);
1017 fprintf (afile, "; Externals used\n");
1018 fprintf (afile, "%s", iComments2);
1020 for (sym = setFirstItem (externs); sym;
1021 sym = setNextItem (externs))
1022 tfprintf(afile, "\t!global\n", sym->rname);
1025 /*-----------------------------------------------------------------*/
1026 /* emitOverlay - will emit code for the overlay stuff */
1027 /*-----------------------------------------------------------------*/
1028 static void emitOverlay(FILE *afile)
1032 if (!elementsInSet(ovrSetSets))
1033 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1035 /* for each of the sets in the overlay segment do */
1036 for (ovrset = setFirstItem(ovrSetSets); ovrset;
1037 ovrset = setNextItem(ovrSetSets)) {
1041 if (elementsInSet(ovrset)) {
1042 /* this dummy area is used to fool the assembler
1043 otherwise the assembler will append each of these
1044 declarations into one chunk and will not overlay
1046 fprintf(afile,"\t.area _DUMMY\n");
1047 /* output the area informtion */
1048 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1051 for (sym = setFirstItem(ovrset); sym;
1052 sym = setNextItem(ovrset)) {
1054 /* if extern then add it to the publics tabledo nothing */
1055 if (IS_EXTERN (sym->etype))
1058 /* if allocation required check is needed
1059 then check if the symbol really requires
1060 allocation only for local variables */
1061 if (!IS_AGGREGATE(sym->type) &&
1062 !(sym->_isparm && !IS_REGPARM(sym->etype))
1063 && !sym->allocreq && sym->level)
1066 /* if global variable & not static or extern
1067 and addPublics allowed then add it to the public set */
1068 if ((sym->_isparm && !IS_REGPARM(sym->etype))
1069 && !IS_STATIC (sym->etype))
1070 addSetHead (&publics, sym);
1072 /* if extern then do nothing or is a function
1074 if (IS_FUNC (sym->type))
1077 /* print extra debug info if required */
1078 if ((options.debug || sym->level == 0) && !options.nodebug) {
1080 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1082 if (!sym->level) { /* global */
1083 if (IS_STATIC(sym->etype))
1084 fprintf(afile,"F%s$",moduleName); /* scope is file */
1086 fprintf(afile,"G$"); /* scope is global */
1089 /* symbol is local */
1090 fprintf(afile,"L%s$",
1091 (sym->localof ? sym->localof->name : "-null-"));
1092 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1095 /* if is has an absolute address then generate
1096 an equate for this no need to allocate space */
1097 if (SPEC_ABSA (sym->etype)) {
1099 if ((options.debug || sym->level == 0) && !options.nodebug)
1100 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1102 fprintf (afile, "%s\t=\t0x%04x\n",
1104 SPEC_ADDR (sym->etype));
1107 if ((options.debug || sym->level == 0) && !options.nodebug)
1108 fprintf(afile,"==.\n");
1110 /* allocate space */
1111 tfprintf(afile, "!labeldef\n", sym->rname);
1112 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1119 /*-----------------------------------------------------------------*/
1120 /* glue - the final glue that hold the whole thing together */
1121 /*-----------------------------------------------------------------*/
1126 FILE *ovrFile = tempfile();
1128 addSetHead(&tmpfileSet,ovrFile);
1129 /* print the global struct definitions */
1130 if (options.debug && !options.nodebug)
1131 cdbStructBlock (0,cdbFile);
1134 /* PENDING: this isnt the best place but it will do */
1135 if (port->general.glue_up_main) {
1136 /* create the interrupt vector table */
1137 createInterruptVect (vFile);
1140 addSetHead(&tmpfileSet,vFile);
1142 /* emit code for the all the variables declared */
1144 /* do the overlay segments */
1145 emitOverlay(ovrFile);
1147 /* now put it all together into the assembler file */
1148 /* create the assembler file name */
1150 if (!options.c1mode) {
1151 sprintf (buffer, srcFileName);
1152 strcat (buffer, ".asm");
1155 strcpy(buffer, options.out_name);
1158 if (!(asmFile = fopen (buffer, "w"))) {
1159 werror (E_FILE_OPEN_ERR, buffer);
1163 /* initial comments */
1164 initialComments (asmFile);
1166 /* print module name */
1167 tfprintf(asmFile, "\t!module\n", moduleName);
1168 tfprintf(asmFile, "\t!fileprelude\n");
1170 /* Let the port generate any global directives, etc. */
1171 if (port->genAssemblerPreamble)
1173 port->genAssemblerPreamble(asmFile);
1176 /* print the global variables in this module */
1177 printPublics (asmFile);
1178 if (port->assembler.externGlobal)
1179 printExterns (asmFile);
1181 /* copy the sfr segment */
1182 fprintf (asmFile, "%s", iComments2);
1183 fprintf (asmFile, "; special function registers\n");
1184 fprintf (asmFile, "%s", iComments2);
1185 copyFile (asmFile, sfr->oFile);
1187 /* copy the sbit segment */
1188 fprintf (asmFile, "%s", iComments2);
1189 fprintf (asmFile, "; special function bits \n");
1190 fprintf (asmFile, "%s", iComments2);
1191 copyFile (asmFile, sfrbit->oFile);
1193 /* copy the data segment */
1194 fprintf (asmFile, "%s", iComments2);
1195 fprintf (asmFile, "; internal ram data\n");
1196 fprintf (asmFile, "%s", iComments2);
1197 copyFile (asmFile, data->oFile);
1200 /* create the overlay segments */
1201 fprintf (asmFile, "%s", iComments2);
1202 fprintf (asmFile, "; overlayable items in internal ram \n");
1203 fprintf (asmFile, "%s", iComments2);
1204 copyFile (asmFile, ovrFile);
1206 /* create the stack segment MOF */
1207 if (mainf && mainf->fbody) {
1208 fprintf (asmFile, "%s", iComments2);
1209 fprintf (asmFile, "; Stack segment in internal ram \n");
1210 fprintf (asmFile, "%s", iComments2);
1211 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1212 "__start__stack:\n\t.ds\t1\n\n");
1215 /* create the idata segment */
1216 fprintf (asmFile, "%s", iComments2);
1217 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1218 fprintf (asmFile, "%s", iComments2);
1219 copyFile (asmFile, idata->oFile);
1221 /* copy the bit segment */
1222 fprintf (asmFile, "%s", iComments2);
1223 fprintf (asmFile, "; bit data\n");
1224 fprintf (asmFile, "%s", iComments2);
1225 copyFile (asmFile, bit->oFile);
1227 /* if external stack then reserve space of it */
1228 if (mainf && mainf->fbody && options.useXstack ) {
1229 fprintf (asmFile, "%s", iComments2);
1230 fprintf (asmFile, "; external stack \n");
1231 fprintf (asmFile, "%s", iComments2);
1232 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1233 fprintf (asmFile,"\t.ds 256\n");
1237 /* copy xtern ram data */
1238 fprintf (asmFile, "%s", iComments2);
1239 fprintf (asmFile, "; external ram data\n");
1240 fprintf (asmFile, "%s", iComments2);
1241 copyFile (asmFile, xdata->oFile);
1243 /* copy the interrupt vector table */
1244 if (mainf && mainf->fbody) {
1245 fprintf (asmFile, "%s", iComments2);
1246 fprintf (asmFile, "; interrupt vector \n");
1247 fprintf (asmFile, "%s", iComments2);
1248 copyFile (asmFile, vFile);
1251 /* copy global & static initialisations */
1252 fprintf (asmFile, "%s", iComments2);
1253 fprintf (asmFile, "; global & static initialisations\n");
1254 fprintf (asmFile, "%s", iComments2);
1256 /* Everywhere we generate a reference to the static_name area,
1257 * (which is currently only here), we immediately follow it with a
1258 * definition of the post_static_name area. This guarantees that
1259 * the post_static_name area will immediately follow the static_name
1262 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1263 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1264 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1266 if (mainf && mainf->fbody) {
1267 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1268 /* if external stack is specified then the
1269 higher order byte of the xdatalocation is
1270 going into P2 and the lower order going into
1272 if (options.useXstack) {
1273 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1274 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1275 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1276 (unsigned int)options.xdata_loc & 0xff);
1279 /* initialise the stack pointer */
1280 /* if the user specified a value then use it */
1281 if (options.stack_loc)
1282 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1284 /* no: we have to compute it */
1285 if (!options.stackOnData && maxRegBank <= 3)
1286 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1288 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1290 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1291 fprintf (asmFile,"\tmov\ta,dpl\n");
1292 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1293 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1294 fprintf (asmFile,"__sdcc_init_data:\n");
1297 copyFile (asmFile, statsg->oFile);
1299 if (port->general.glue_up_main && mainf && mainf->fbody)
1301 /* This code is generated in the post-static area.
1302 * This area is guaranteed to follow the static area
1303 * by the ugly shucking and jiving about 20 lines ago.
1305 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1306 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1312 "%s", iComments2, iComments2);
1313 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1314 copyFile (asmFile, home->oFile);
1316 /* copy over code */
1317 fprintf (asmFile, "%s", iComments2);
1318 fprintf (asmFile, "; code\n");
1319 fprintf (asmFile, "%s", iComments2);
1320 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1321 if (mainf && mainf->fbody) {
1323 /* entry point @ start of CSEG */
1324 fprintf (asmFile,"__sdcc_program_startup:\n");
1326 /* put in the call to main */
1327 fprintf(asmFile,"\tlcall\t_main\n");
1328 if (options.mainreturn) {
1330 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1331 fprintf(asmFile,"\tret\n");
1335 fprintf(asmFile,";\treturn from main will lock up\n");
1336 fprintf(asmFile,"\tsjmp .\n");
1339 copyFile (asmFile, code->oFile);
1342 applyToSet(tmpfileSet,closeTmpFiles);
1343 applyToSet(tmpfileNameSet, rmTmpFiles);
1346 /** Creates a temporary file a'la tmpfile which avoids the bugs
1347 in cygwin wrt c:\tmp.
1348 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1350 FILE *tempfile(void)
1352 const char *tmpdir = NULL;
1354 tmpdir = getenv("TMP");
1355 else if (getenv("TEMP"))
1356 tmpdir = getenv("TEMP");
1357 else if (getenv("TMPDIR"))
1358 tmpdir = getenv("TMPDIR");
1360 char *name = tempnam(tmpdir, "sdcc");
1362 FILE *fp = fopen(name, "w+b");
1365 addSetHead(&tmpfileNameSet, name);
1374 char *gc_strdup(const char *s)
1377 ALLOC_ATOMIC(ret, strlen(s)+1);