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)
87 /*-----------------------------------------------------------------*/
88 /* copyFile - copies source file to destination file */
89 /*-----------------------------------------------------------------*/
90 void copyFile (FILE * dest, FILE * src)
96 if ((ch = fgetc (src)) != EOF)
100 char *aopLiteralLong(value *val, int offset, int size)
108 /* if it is a float then it gets tricky */
109 /* otherwise it is fairly simple */
110 if (!IS_FLOAT(val->type)) {
111 unsigned long v = floatFromVal(val);
116 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
119 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
122 /* Hmm. Too big for now. */
125 rs = Safe_calloc(strlen(buffer)+1);
126 return strcpy (rs,buffer);
129 /* PENDING: For now size must be 1 */
132 /* it is type float */
133 fl.f = (float) floatFromVal(val);
135 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
137 tsprintf(buffer, "!immedbyte", fl.c[offset]);
139 rs = Safe_calloc(strlen(buffer)+1);
140 return strcpy (rs,buffer);
143 /*-----------------------------------------------------------------*/
144 /* aopLiteral - string from a literal value */
145 /*-----------------------------------------------------------------*/
146 char *aopLiteral (value *val, int offset)
148 return aopLiteralLong(val, offset, 1);
151 /*-----------------------------------------------------------------*/
152 /* emitRegularMap - emit code for maps with no special cases */
153 /*-----------------------------------------------------------------*/
154 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
159 /* PENDING: special case here - should remove */
160 if (!strcmp(map->sname, CODE_NAME))
161 tfprintf(map->oFile, "\t!areacode\n", map->sname);
162 else if (!strcmp(map->sname, DATA_NAME))
163 tfprintf(map->oFile, "\t!areadata\n", map->sname);
164 else if (!strcmp(map->sname, HOME_NAME))
165 tfprintf(map->oFile, "\t!areahome\n", map->sname);
167 tfprintf(map->oFile, "\t!area\n", map->sname);
170 /* print the area name */
171 for (sym = setFirstItem (map->syms); sym;
172 sym = setNextItem (map->syms)) {
174 /* if extern then add it into the extern list */
175 if (IS_EXTERN (sym->etype)) {
176 addSetHead (&externs, sym);
180 /* if allocation required check is needed
181 then check if the symbol really requires
182 allocation only for local variables */
183 if (arFlag && !IS_AGGREGATE(sym->type) &&
184 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
185 !sym->allocreq && sym->level)
188 /* if global variable & not static or extern
189 and addPublics allowed then add it to the public set */
190 if ((sym->level == 0 ||
191 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
193 !IS_STATIC (sym->etype) &&
194 (sym->used || sym->fbody)) {
195 addSetHead (&publics, sym);
198 /* if extern then do nothing or is a function
200 if (IS_FUNC (sym->type))
203 /* print extra debug info if required */
204 if ((options.debug || sym->level == 0) && !options.nodebug) {
206 cdbSymbol(sym,cdbFile,FALSE,FALSE);
208 if (!sym->level) /* global */
209 if (IS_STATIC(sym->etype))
210 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
212 fprintf(map->oFile,"G$"); /* scope is global */
214 /* symbol is local */
215 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
216 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
219 /* if is has an absolute address then generate
220 an equate for this no need to allocate space */
221 if (SPEC_ABSA (sym->etype)) {
222 if ((options.debug || sym->level == 0) && !options.nodebug)
223 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
225 fprintf (map->oFile, "%s\t=\t0x%04x\n",
227 SPEC_ADDR (sym->etype));
231 if ((options.debug || sym->level == 0) && !options.nodebug)
232 fprintf(map->oFile,"==.\n");
233 if (IS_STATIC(sym->etype))
234 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
236 tfprintf(map->oFile, "!labeldef\n", sym->rname);
237 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
240 /* if it has an initial value then do it only if
241 it is a global variable */
242 if (sym->ival && sym->level == 0) {
245 if (IS_AGGREGATE (sym->type))
246 ival = initAggregates (sym, sym->ival, NULL);
248 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
249 decorateType (resolveSymbols (list2expr (sym->ival))));
250 codeOutFile = statsg->oFile;
252 eBBlockFromiCode (iCodeFromAst (ival));
259 /*-----------------------------------------------------------------*/
260 /* initPointer - pointer initialization code massaging */
261 /*-----------------------------------------------------------------*/
262 value *initPointer (initList *ilist)
265 ast *expr = list2expr(ilist);
270 /* try it the oldway first */
271 if ((val = constExprValue(expr,FALSE)))
274 /* no then we have to do these cludgy checks */
275 /* pointers can be initialized with address of
276 a variable or address of an array element */
277 if (IS_AST_OP(expr) && expr->opval.op == '&') {
278 /* address of symbol */
279 if (IS_AST_SYM_VALUE(expr->left)) {
280 val = copyValue(AST_VALUE(expr->left));
281 val->type = newLink();
282 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
283 DCL_TYPE(val->type) = CPOINTER ;
284 DCL_PTR_CONST(val->type) = port->mem.code_ro;
287 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
288 DCL_TYPE(val->type) = FPOINTER;
290 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
291 DCL_TYPE(val->type) = PPOINTER ;
293 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
294 DCL_TYPE(val->type) = IPOINTER ;
296 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
297 DCL_TYPE(val->type) = EEPPOINTER ;
299 DCL_TYPE(val->type) = POINTER ;
300 val->type->next = expr->left->ftype;
301 val->etype = getSpec(val->type);
305 /* if address of indexed array */
306 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
307 return valForArray(expr->left);
309 /* if address of structure element then
311 if (IS_AST_OP(expr->left) &&
312 expr->left->opval.op == '.' ) {
313 return valForStructElem(expr->left->left,
318 (&some_struct)->element */
319 if (IS_AST_OP(expr->left) &&
320 expr->left->opval.op == PTR_OP &&
321 IS_ADDRESS_OF_OP(expr->left->left))
322 return valForStructElem(expr->left->left->left,
326 /* case 3. (((char *) &a) +/- constant) */
327 if (IS_AST_OP(expr) &&
328 (expr->opval.op == '+' || expr->opval.op == '-') &&
329 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
330 IS_AST_OP(expr->left->right) &&
331 expr->left->right->opval.op == '&' &&
332 IS_AST_LIT_VALUE(expr->right)) {
334 return valForCastAggr(expr->left->right->left,
335 expr->left->left->opval.lnk,
336 expr->right,expr->opval.op);
341 werror(E_INIT_WRONG);
346 /*-----------------------------------------------------------------*/
347 /* printChar - formats and prints a characater string with DB */
348 /*-----------------------------------------------------------------*/
349 void printChar (FILE * ofile, char *s, int plen)
352 int len = strlen (s);
357 while (len && pplen < plen) {
359 while (i && *s && pplen < plen) {
360 if (*s < ' ' || *s == '\"') {
363 tfprintf(ofile, "\t!ascii\n", buf);
364 tfprintf(ofile, "\t!db !constbyte\n", *s);
377 tfprintf(ofile, "\t!ascii\n", buf);
386 tfprintf(ofile, "\t!db !constbyte\n", 0);
389 /*-----------------------------------------------------------------*/
390 /* return the generic pointer high byte for a given pointer type. */
391 /*-----------------------------------------------------------------*/
392 int pointerTypeToGPByte(const int p_type)
400 /* hack - if we get a generic pointer, we just assume
401 * it's an FPOINTER (i.e. in XDATA space).
410 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
418 /*-----------------------------------------------------------------*/
419 /* printPointerType - generates ival for pointer type */
420 /*-----------------------------------------------------------------*/
421 void _printPointerType(FILE *oFile, const char *name)
425 fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
429 fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
433 /*-----------------------------------------------------------------*/
434 /* printPointerType - generates ival for pointer type */
435 /*-----------------------------------------------------------------*/
436 void printPointerType(FILE *oFile, const char *name)
438 _printPointerType(oFile, name);
439 fprintf(oFile, "\n");
442 /*-----------------------------------------------------------------*/
443 /* printGPointerType - generates ival for generic pointer type */
444 /*-----------------------------------------------------------------*/
445 void printGPointerType(FILE *oFile, const char *name,
446 const unsigned int type)
448 _printPointerType(oFile,name);
449 fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type));
452 /*-----------------------------------------------------------------*/
453 /* printIvalType - generates ival for int/char */
454 /*-----------------------------------------------------------------*/
455 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
459 /* if initList is deep */
460 if (ilist->type == INIT_DEEP)
461 ilist = ilist->init.deep;
463 val = list2val (ilist);
464 switch (getSize (type)) {
467 tfprintf(oFile, "\t!db !constbyte\n", 0);
469 tfprintf(oFile, "\t!dbs\n",
470 aopLiteral (val, 0));
474 if (port->use_dw_for_init)
475 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
477 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
481 tfprintf (oFile, "\t!dw !constword\n", 0);
482 tfprintf (oFile, "\t!dw !constword\n", 0);
485 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
486 aopLiteral (val, 0), aopLiteral (val, 1),
487 aopLiteral (val, 2), aopLiteral (val, 3));
493 /*-----------------------------------------------------------------*/
494 /* printIvalStruct - generates initial value for structures */
495 /*-----------------------------------------------------------------*/
496 void printIvalStruct (symbol * sym,sym_link * type,
497 initList * ilist, FILE * oFile)
502 sflds = SPEC_STRUCT (type)->fields;
503 if (ilist->type != INIT_DEEP) {
504 werror (E_INIT_STRUCT, sym->name);
508 iloop = ilist->init.deep;
510 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
511 printIval (sflds, sflds->type, iloop, oFile);
516 /*-----------------------------------------------------------------*/
517 /* printIvalChar - generates initital value for character array */
518 /*-----------------------------------------------------------------*/
519 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
526 val = list2val (ilist);
527 /* if the value is a character string */
528 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
529 if (!DCL_ELEM (type))
530 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
532 /* if size mismatch */
533 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
534 /* werror (E_ARRAY_BOUND); */
536 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
538 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
540 tfprintf (oFile, "\t!db !constbyte\n", 0);
548 printChar (oFile, s,strlen(s)+1);
552 /*-----------------------------------------------------------------*/
553 /* printIvalArray - generates code for array initialization */
554 /*-----------------------------------------------------------------*/
555 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
559 int lcnt = 0, size = 0;
561 /* take care of the special case */
562 /* array of characters can be init */
564 if (IS_CHAR (type->next))
565 if (printIvalChar (type,
566 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
567 oFile, SPEC_CVAL (sym->etype).v_char))
570 /* not the special case */
571 if (ilist->type != INIT_DEEP) {
572 werror (E_INIT_STRUCT, sym->name);
576 iloop = ilist->init.deep;
577 lcnt = DCL_ELEM (type);
581 printIval (sym, type->next, iloop, oFile);
582 iloop = (iloop ? iloop->next : NULL);
585 /* if not array limits given & we */
586 /* are out of initialisers then */
587 if (!DCL_ELEM (type) && !iloop)
590 /* no of elements given and we */
591 /* have generated for all of them */
596 /* if we have not been given a size */
597 if (!DCL_ELEM (type))
598 DCL_ELEM (type) = size;
603 /*-----------------------------------------------------------------*/
604 /* printIvalFuncPtr - generate initial value for function pointers */
605 /*-----------------------------------------------------------------*/
606 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
611 val = list2val (ilist);
612 /* check the types */
613 if ((dLvl = checkType (val->type, type->next)) <= 0) {
614 tfprintf(oFile, "\t!dw !constword\n", 0);
618 /* now generate the name */
620 if (port->use_dw_for_init)
622 tfprintf(oFile, "\t!dws\n", val->name);
626 printPointerType(oFile, val->name);
630 if (port->use_dw_for_init)
632 tfprintf(oFile, "\t!dws\n", val->sym->rname);
636 printPointerType(oFile, val->sym->rname);
642 /*-----------------------------------------------------------------*/
643 /* printIvalCharPtr - generates initial values for character pointers */
644 /*-----------------------------------------------------------------*/
645 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
649 /* PENDING: this is _very_ mcs51 specific, including a magic
651 It's also endin specific.
653 size = getSize (type);
655 if (val->name && strlen(val->name)) {
656 if (size == 1) /* This appears to be Z80 specific?? */
659 "\t!dbs\n", val->name);
661 else if (size == FPTRSIZE)
663 if (port->use_dw_for_init)
665 tfprintf(oFile, "\t!dws\n", val->name);
669 printPointerType(oFile, val->name);
672 else if (size == GPTRSIZE)
674 /* PENDING: 0x02 or 0x%02x, CDATA? */
675 printGPointerType(oFile, val->name,
676 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
677 PTR_TYPE(SPEC_OCLS(val->etype))));
681 fprintf(stderr, "*** internal error: unknown size in "
682 "printIvalCharPtr.\n");
686 /* What is this case? Are these pointers? */
689 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
692 if (port->use_dw_for_init)
693 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
695 tfprintf(oFile, "\t.byte %s,%s\n",
696 aopLiteral(val, 0),aopLiteral(val, 1));
699 /* PENDING: 0x02 or 0x%02x, CDATA? */
700 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
701 aopLiteral (val, 0), aopLiteral (val, 1));
709 if (val->sym && val->sym->isstrlit)
710 addSet (&statsg->syms, val->sym);
715 /*-----------------------------------------------------------------*/
716 /* printIvalPtr - generates initial value for pointers */
717 /*-----------------------------------------------------------------*/
718 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
724 if (ilist->type == INIT_DEEP)
725 ilist = ilist->init.deep;
727 /* function pointer */
728 if (IS_FUNC (type->next)) {
729 printIvalFuncPtr (type, ilist, oFile);
733 if (!(val = initPointer (ilist)))
736 /* if character pointer */
737 if (IS_CHAR (type->next))
738 if (printIvalCharPtr (sym, type, val, oFile))
742 if (checkType (type, val->type) != 1)
743 werror (E_INIT_WRONG);
745 /* if val is literal */
746 if (IS_LITERAL (val->etype)) {
747 switch (getSize (type)) {
749 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
752 if (port->use_dw_for_init)
753 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
755 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
758 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
759 aopLiteral (val, 0), aopLiteral (val, 1));
765 size = getSize (type);
767 if (size == 1) /* Z80 specific?? */
769 tfprintf (oFile, "\t!dbs\n", val->name);
771 else if (size == FPTRSIZE)
773 tfprintf (oFile, "\t!dws\n", val->name);
775 else if (size == GPTRSIZE)
777 printGPointerType(oFile, val->name,
778 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
779 PTR_TYPE(SPEC_OCLS(val->etype))));
784 /*-----------------------------------------------------------------*/
785 /* printIval - generates code for initial value */
786 /*-----------------------------------------------------------------*/
787 void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
792 /* if structure then */
793 if (IS_STRUCT (type)) {
794 printIvalStruct (sym, type, ilist, oFile);
798 /* if this is a pointer */
800 printIvalPtr (sym, type, ilist, oFile);
804 /* if this is an array */
805 if (IS_ARRAY (type)) {
806 printIvalArray (sym, type, ilist, oFile);
810 /* if type is SPECIFIER */
811 if (IS_SPEC (type)) {
812 printIvalType (type, ilist, oFile);
817 /*-----------------------------------------------------------------*/
818 /* emitStaticSeg - emitcode for the static segment */
819 /*-----------------------------------------------------------------*/
820 void emitStaticSeg(memmap * map, FILE *out)
824 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
828 /* for all variables in this segment do */
829 for (sym = setFirstItem (map->syms); sym;
830 sym = setNextItem (map->syms)) {
832 /* if it is "extern" then do nothing */
833 if (IS_EXTERN (sym->etype))
836 /* if it is not static add it to the public
838 if (!IS_STATIC (sym->etype))
839 addSetHead (&publics, sym);
841 /* print extra debug info if required */
842 if ((options.debug || sym->level == 0) && !options.nodebug) {
844 cdbSymbol(sym,cdbFile,FALSE,FALSE);
846 if (!sym->level) { /* global */
847 if (IS_STATIC(sym->etype))
848 fprintf(out,"F%s$",moduleName); /* scope is file */
850 fprintf(out,"G$"); /* scope is global */
853 /* symbol is local */
855 (sym->localof ? sym->localof->name : "-null-"));
856 fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
859 /* if it has an absolute address */
860 if (SPEC_ABSA (sym->etype)) {
861 if ((options.debug || sym->level == 0) && !options.nodebug)
862 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
864 fprintf (out, "%s\t=\t0x%04x\n",
866 SPEC_ADDR (sym->etype));
869 if ((options.debug || sym->level == 0) && !options.nodebug)
870 fprintf(out," == .\n");
872 /* if it has an initial value */
874 fprintf (out, "%s:\n", sym->rname);
876 resolveIvalSym (sym->ival);
877 printIval (sym, sym->type, sym->ival, out);
882 fprintf (out, "%s:\n", sym->rname);
883 /* special case for character strings */
884 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
885 SPEC_CVAL (sym->etype).v_char)
887 SPEC_CVAL (sym->etype).v_char,
888 strlen(SPEC_CVAL (sym->etype).v_char)+1);
890 tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
896 /*-----------------------------------------------------------------*/
897 /* emitMaps - emits the code for the data portion the code */
898 /*-----------------------------------------------------------------*/
901 /* no special considerations for the following
902 data, idata & bit & xdata */
903 emitRegularMap (data, TRUE, TRUE);
904 emitRegularMap (idata, TRUE,TRUE);
905 emitRegularMap (bit, TRUE,FALSE);
906 emitRegularMap (xdata, TRUE,TRUE);
907 emitRegularMap (sfr, FALSE,FALSE);
908 emitRegularMap (sfrbit, FALSE,FALSE);
909 emitRegularMap (home, TRUE,FALSE);
910 emitRegularMap (code, TRUE,FALSE);
912 emitStaticSeg (statsg, code->oFile);
915 /*-----------------------------------------------------------------*/
916 /* flushStatics - flush all currently defined statics out to file */
917 /* and delete. Temporary function */
918 /*-----------------------------------------------------------------*/
919 void flushStatics(void)
921 emitStaticSeg(statsg, codeOutFile);
925 /*-----------------------------------------------------------------*/
926 /* createInterruptVect - creates the interrupt vector */
927 /*-----------------------------------------------------------------*/
928 void createInterruptVect (FILE * vFile)
931 mainf = newSymbol ("main", 0);
934 /* only if the main function exists */
935 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
936 if (!options.cc_only)
941 /* if the main is only a prototype ie. no body then do nothing */
943 /* if ! compile only then main function should be present */
944 if (!options.cc_only)
949 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
950 fprintf (vFile, "__interrupt_vect:\n");
953 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
955 /* "generic" interrupt table header (if port doesn't specify one).
957 * Look suspiciously like 8051 code to me...
960 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
963 /* now for the other interrupts */
964 for (; i < maxInterrupts; i++) {
966 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
968 fprintf (vFile, "\treti\n\t.ds\t7\n");
975 ";--------------------------------------------------------\n"
976 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
980 ";--------------------------------------------------------\n"};
983 /*-----------------------------------------------------------------*/
984 /* initialComments - puts in some initial comments */
985 /*-----------------------------------------------------------------*/
986 void initialComments (FILE * afile)
990 fprintf (afile, "%s", iComments1);
991 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
992 fprintf (afile, "%s", iComments2);
995 /*-----------------------------------------------------------------*/
996 /* printPublics - generates .global for publics */
997 /*-----------------------------------------------------------------*/
998 void printPublics (FILE * afile)
1002 fprintf (afile, "%s", iComments2);
1003 fprintf (afile, "; Public variables in this module\n");
1004 fprintf (afile, "%s", iComments2);
1006 for (sym = setFirstItem (publics); sym;
1007 sym = setNextItem (publics))
1008 tfprintf(afile, "\t!global\n", sym->rname);
1011 /*-----------------------------------------------------------------*/
1012 /* printExterns - generates .global for externs */
1013 /*-----------------------------------------------------------------*/
1014 void printExterns (FILE * afile)
1018 fprintf (afile, "%s", iComments2);
1019 fprintf (afile, "; Externals used\n");
1020 fprintf (afile, "%s", iComments2);
1022 for (sym = setFirstItem (externs); sym;
1023 sym = setNextItem (externs))
1024 tfprintf(afile, "\t!global\n", sym->rname);
1027 /*-----------------------------------------------------------------*/
1028 /* emitOverlay - will emit code for the overlay stuff */
1029 /*-----------------------------------------------------------------*/
1030 static void emitOverlay(FILE *afile)
1034 if (!elementsInSet(ovrSetSets))
1035 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1037 /* for each of the sets in the overlay segment do */
1038 for (ovrset = setFirstItem(ovrSetSets); ovrset;
1039 ovrset = setNextItem(ovrSetSets)) {
1043 if (elementsInSet(ovrset)) {
1044 /* this dummy area is used to fool the assembler
1045 otherwise the assembler will append each of these
1046 declarations into one chunk and will not overlay
1048 fprintf(afile,"\t.area _DUMMY\n");
1049 /* output the area informtion */
1050 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1053 for (sym = setFirstItem(ovrset); sym;
1054 sym = setNextItem(ovrset)) {
1056 /* if extern then add it to the publics tabledo nothing */
1057 if (IS_EXTERN (sym->etype))
1060 /* if allocation required check is needed
1061 then check if the symbol really requires
1062 allocation only for local variables */
1063 if (!IS_AGGREGATE(sym->type) &&
1064 !(sym->_isparm && !IS_REGPARM(sym->etype))
1065 && !sym->allocreq && sym->level)
1068 /* if global variable & not static or extern
1069 and addPublics allowed then add it to the public set */
1070 if ((sym->_isparm && !IS_REGPARM(sym->etype))
1071 && !IS_STATIC (sym->etype))
1072 addSetHead (&publics, sym);
1074 /* if extern then do nothing or is a function
1076 if (IS_FUNC (sym->type))
1079 /* print extra debug info if required */
1080 if ((options.debug || sym->level == 0) && !options.nodebug) {
1082 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1084 if (!sym->level) { /* global */
1085 if (IS_STATIC(sym->etype))
1086 fprintf(afile,"F%s$",moduleName); /* scope is file */
1088 fprintf(afile,"G$"); /* scope is global */
1091 /* symbol is local */
1092 fprintf(afile,"L%s$",
1093 (sym->localof ? sym->localof->name : "-null-"));
1094 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1097 /* if is has an absolute address then generate
1098 an equate for this no need to allocate space */
1099 if (SPEC_ABSA (sym->etype)) {
1101 if ((options.debug || sym->level == 0) && !options.nodebug)
1102 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1104 fprintf (afile, "%s\t=\t0x%04x\n",
1106 SPEC_ADDR (sym->etype));
1109 if ((options.debug || sym->level == 0) && !options.nodebug)
1110 fprintf(afile,"==.\n");
1112 /* allocate space */
1113 tfprintf(afile, "!labeldef\n", sym->rname);
1114 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1121 /*-----------------------------------------------------------------*/
1122 /* glue - the final glue that hold the whole thing together */
1123 /*-----------------------------------------------------------------*/
1128 FILE *ovrFile = tempfile();
1130 addSetHead(&tmpfileSet,ovrFile);
1131 /* print the global struct definitions */
1132 if (options.debug && !options.nodebug)
1133 cdbStructBlock (0,cdbFile);
1136 /* PENDING: this isnt the best place but it will do */
1137 if (port->general.glue_up_main) {
1138 /* create the interrupt vector table */
1139 createInterruptVect (vFile);
1142 addSetHead(&tmpfileSet,vFile);
1144 /* emit code for the all the variables declared */
1146 /* do the overlay segments */
1147 emitOverlay(ovrFile);
1149 /* now put it all together into the assembler file */
1150 /* create the assembler file name */
1152 if (!options.c1mode) {
1153 sprintf (buffer, srcFileName);
1154 strcat (buffer, ".asm");
1157 strcpy(buffer, options.out_name);
1160 if (!(asmFile = fopen (buffer, "w"))) {
1161 werror (E_FILE_OPEN_ERR, buffer);
1165 /* initial comments */
1166 initialComments (asmFile);
1168 /* print module name */
1169 tfprintf(asmFile, "\t!module\n", moduleName);
1170 tfprintf(asmFile, "\t!fileprelude\n");
1172 /* Let the port generate any global directives, etc. */
1173 if (port->genAssemblerPreamble)
1175 port->genAssemblerPreamble(asmFile);
1178 /* print the global variables in this module */
1179 printPublics (asmFile);
1180 if (port->assembler.externGlobal)
1181 printExterns (asmFile);
1183 /* copy the sfr segment */
1184 fprintf (asmFile, "%s", iComments2);
1185 fprintf (asmFile, "; special function registers\n");
1186 fprintf (asmFile, "%s", iComments2);
1187 copyFile (asmFile, sfr->oFile);
1189 /* copy the sbit segment */
1190 fprintf (asmFile, "%s", iComments2);
1191 fprintf (asmFile, "; special function bits \n");
1192 fprintf (asmFile, "%s", iComments2);
1193 copyFile (asmFile, sfrbit->oFile);
1195 /* copy the data segment */
1196 fprintf (asmFile, "%s", iComments2);
1197 fprintf (asmFile, "; internal ram data\n");
1198 fprintf (asmFile, "%s", iComments2);
1199 copyFile (asmFile, data->oFile);
1202 /* create the overlay segments */
1203 fprintf (asmFile, "%s", iComments2);
1204 fprintf (asmFile, "; overlayable items in internal ram \n");
1205 fprintf (asmFile, "%s", iComments2);
1206 copyFile (asmFile, ovrFile);
1208 /* create the stack segment MOF */
1209 if (mainf && mainf->fbody) {
1210 fprintf (asmFile, "%s", iComments2);
1211 fprintf (asmFile, "; Stack segment in internal ram \n");
1212 fprintf (asmFile, "%s", iComments2);
1213 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1214 "__start__stack:\n\t.ds\t1\n\n");
1217 /* create the idata segment */
1218 fprintf (asmFile, "%s", iComments2);
1219 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1220 fprintf (asmFile, "%s", iComments2);
1221 copyFile (asmFile, idata->oFile);
1223 /* copy the bit segment */
1224 fprintf (asmFile, "%s", iComments2);
1225 fprintf (asmFile, "; bit data\n");
1226 fprintf (asmFile, "%s", iComments2);
1227 copyFile (asmFile, bit->oFile);
1229 /* if external stack then reserve space of it */
1230 if (mainf && mainf->fbody && options.useXstack ) {
1231 fprintf (asmFile, "%s", iComments2);
1232 fprintf (asmFile, "; external stack \n");
1233 fprintf (asmFile, "%s", iComments2);
1234 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1235 fprintf (asmFile,"\t.ds 256\n");
1239 /* copy xtern ram data */
1240 fprintf (asmFile, "%s", iComments2);
1241 fprintf (asmFile, "; external ram data\n");
1242 fprintf (asmFile, "%s", iComments2);
1243 copyFile (asmFile, xdata->oFile);
1245 /* copy the interrupt vector table */
1246 if (mainf && mainf->fbody) {
1247 fprintf (asmFile, "%s", iComments2);
1248 fprintf (asmFile, "; interrupt vector \n");
1249 fprintf (asmFile, "%s", iComments2);
1250 copyFile (asmFile, vFile);
1253 /* copy global & static initialisations */
1254 fprintf (asmFile, "%s", iComments2);
1255 fprintf (asmFile, "; global & static initialisations\n");
1256 fprintf (asmFile, "%s", iComments2);
1258 /* Everywhere we generate a reference to the static_name area,
1259 * (which is currently only here), we immediately follow it with a
1260 * definition of the post_static_name area. This guarantees that
1261 * the post_static_name area will immediately follow the static_name
1264 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1265 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1266 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1268 if (mainf && mainf->fbody) {
1269 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1270 /* if external stack is specified then the
1271 higher order byte of the xdatalocation is
1272 going into P2 and the lower order going into
1274 if (options.useXstack) {
1275 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1276 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1277 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1278 (unsigned int)options.xdata_loc & 0xff);
1281 /* initialise the stack pointer */
1282 /* if the user specified a value then use it */
1283 if (options.stack_loc)
1284 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1286 /* no: we have to compute it */
1287 if (!options.stackOnData && maxRegBank <= 3)
1288 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1290 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1292 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1293 fprintf (asmFile,"\tmov\ta,dpl\n");
1294 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1295 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1296 fprintf (asmFile,"__sdcc_init_data:\n");
1299 copyFile (asmFile, statsg->oFile);
1301 if (port->general.glue_up_main && mainf && mainf->fbody)
1303 /* This code is generated in the post-static area.
1304 * This area is guaranteed to follow the static area
1305 * by the ugly shucking and jiving about 20 lines ago.
1307 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1308 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1314 "%s", iComments2, iComments2);
1315 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1316 copyFile (asmFile, home->oFile);
1318 /* copy over code */
1319 fprintf (asmFile, "%s", iComments2);
1320 fprintf (asmFile, "; code\n");
1321 fprintf (asmFile, "%s", iComments2);
1322 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1323 if (mainf && mainf->fbody) {
1325 /* entry point @ start of CSEG */
1326 fprintf (asmFile,"__sdcc_program_startup:\n");
1328 /* put in the call to main */
1329 fprintf(asmFile,"\tlcall\t_main\n");
1330 if (options.mainreturn) {
1332 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1333 fprintf(asmFile,"\tret\n");
1337 fprintf(asmFile,";\treturn from main will lock up\n");
1338 fprintf(asmFile,"\tsjmp .\n");
1341 copyFile (asmFile, code->oFile);
1344 applyToSet(tmpfileSet,closeTmpFiles);
1345 applyToSet(tmpfileNameSet, rmTmpFiles);
1348 /** Creates a temporary file a'la tmpfile which avoids the bugs
1349 in cygwin wrt c:\tmp.
1350 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1352 FILE *tempfile(void)
1354 #if !defined(_MSC_VER)
1355 const char *tmpdir = NULL;
1357 tmpdir = getenv("TMP");
1358 else if (getenv("TEMP"))
1359 tmpdir = getenv("TEMP");
1360 else if (getenv("TMPDIR"))
1361 tmpdir = getenv("TMPDIR");
1363 char *name = tempnam(tmpdir, "sdcc");
1365 FILE *fp = fopen(name, "w+b");
1368 addSetHead(&tmpfileNameSet, name);
1378 char *gc_strdup(const char *s)
1381 ret = Safe_calloc(strlen(s)+1);