1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 symbol *interrupts[256];
30 /*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
31 void printIval (symbol *, link *, initList *, FILE *);
33 set *publics = NULL; /* public variables */
34 set *externs = NULL; /* Varibles that are declared as extern */
36 /* TODO: this should be configurable (DS803C90 uses more than 6) */
37 int maxInterrupts = 6;
39 extern int maxRegBank ;
41 extern char *VersionString;
42 extern FILE *codeOutFile;
43 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
44 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
46 /*-----------------------------------------------------------------*/
47 /* closeTmpFiles - closes all tmp files created by the compiler */
48 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
49 /*-----------------------------------------------------------------*/
50 DEFSETFUNC(closeTmpFiles)
60 /*-----------------------------------------------------------------*/
61 /* rmTmpFiles - closes all tmp files created by the compiler */
62 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
63 /*-----------------------------------------------------------------*/
64 DEFSETFUNC(rmTmpFiles)
75 /*-----------------------------------------------------------------*/
76 /* copyFile - copies source file to destination file */
77 /*-----------------------------------------------------------------*/
78 void copyFile (FILE * dest, FILE * src)
84 if ((ch = fgetc (src)) != EOF)
88 char *aopLiteralLong(value *val, int offset, int size)
96 /* if it is a float then it gets tricky */
97 /* otherwise it is fairly simple */
98 if (!IS_FLOAT(val->type)) {
99 unsigned long v = floatFromVal(val);
104 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
107 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
110 /* Hmm. Too big for now. */
113 ALLOC_ATOMIC(rs,strlen(buffer)+1);
114 return strcpy (rs,buffer);
117 /* PENDING: For now size must be 1 */
120 /* it is type float */
121 fl.f = (float) floatFromVal(val);
123 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
125 tsprintf(buffer, "!immedbyte", fl.c[offset]);
127 ALLOC_ATOMIC(rs,strlen(buffer)+1);
128 return strcpy (rs,buffer);
131 /*-----------------------------------------------------------------*/
132 /* aopLiteral - string from a literal value */
133 /*-----------------------------------------------------------------*/
134 char *aopLiteral (value *val, int offset)
136 return aopLiteralLong(val, offset, 1);
139 /*-----------------------------------------------------------------*/
140 /* emitRegularMap - emit code for maps with no special cases */
141 /*-----------------------------------------------------------------*/
142 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
147 /* PENDING: special case here - should remove */
148 if (!strcmp(map->sname, CODE_NAME))
149 tfprintf(map->oFile, "\t!areacode\n", map->sname);
150 else if (!strcmp(map->sname, DATA_NAME))
151 tfprintf(map->oFile, "\t!areadata\n", map->sname);
152 else if (!strcmp(map->sname, HOME_NAME))
153 tfprintf(map->oFile, "\t!areahome\n", map->sname);
155 tfprintf(map->oFile, "\t!area\n", map->sname);
158 /* print the area name */
159 for (sym = setFirstItem (map->syms); sym;
160 sym = setNextItem (map->syms)) {
162 /* if extern then add it into the extern list */
163 if (IS_EXTERN (sym->etype)) {
164 addSetHead (&externs, sym);
168 /* if allocation required check is needed
169 then check if the symbol really requires
170 allocation only for local variables */
171 if (arFlag && !IS_AGGREGATE(sym->type) &&
172 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
173 !sym->allocreq && sym->level)
176 /* if global variable & not static or extern
177 and addPublics allowed then add it to the public set */
178 if ((sym->level == 0 ||
179 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
181 !IS_STATIC (sym->etype) &&
182 (sym->used || sym->fbody)) {
183 addSetHead (&publics, sym);
186 /* if extern then do nothing or is a function
188 if (IS_FUNC (sym->type))
191 /* print extra debug info if required */
192 if ((options.debug || sym->level == 0) && !options.nodebug) {
194 cdbSymbol(sym,cdbFile,FALSE,FALSE);
196 if (!sym->level) /* global */
197 if (IS_STATIC(sym->etype))
198 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
200 fprintf(map->oFile,"G$"); /* scope is global */
202 /* symbol is local */
203 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
204 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
207 /* if is has an absolute address then generate
208 an equate for this no need to allocate space */
209 if (SPEC_ABSA (sym->etype)) {
210 if ((options.debug || sym->level == 0) && !options.nodebug)
211 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
213 fprintf (map->oFile, "%s\t=\t0x%04x\n",
215 SPEC_ADDR (sym->etype));
219 if ((options.debug || sym->level == 0) && !options.nodebug)
220 fprintf(map->oFile,"==.\n");
221 if (IS_STATIC(sym->etype))
222 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
224 tfprintf(map->oFile, "!labeldef\n", sym->rname);
225 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
228 /* if it has a initial value then do it only if
229 it is a global variable */
230 if (sym->ival && sym->level == 0) {
233 if (IS_AGGREGATE (sym->type))
234 ival = initAggregates (sym, sym->ival, NULL);
236 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
237 decorateType (resolveSymbols (list2expr (sym->ival))));
238 codeOutFile = statsg->oFile;
240 eBBlockFromiCode (iCodeFromAst (ival));
247 /*-----------------------------------------------------------------*/
248 /* initPointer - pointer initialization code massaging */
249 /*-----------------------------------------------------------------*/
250 value *initPointer (initList *ilist)
253 ast *expr = list2expr(ilist);
258 /* try it the oldway first */
259 if ((val = constExprValue(expr,FALSE)))
262 /* no then we have to do these cludgy checks */
263 /* pointers can be initialized with address of
264 a variable or address of an array element */
265 if (IS_AST_OP(expr) && expr->opval.op == '&') {
266 /* address of symbol */
267 if (IS_AST_SYM_VALUE(expr->left)) {
268 val = copyValue(AST_VALUE(expr->left));
269 val->type = newLink();
270 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
271 DCL_TYPE(val->type) = CPOINTER ;
272 DCL_PTR_CONST(val->type) = port->mem.code_ro;
275 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
276 DCL_TYPE(val->type) = FPOINTER;
278 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
279 DCL_TYPE(val->type) = PPOINTER ;
281 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
282 DCL_TYPE(val->type) = IPOINTER ;
284 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
285 DCL_TYPE(val->type) = EEPPOINTER ;
287 DCL_TYPE(val->type) = POINTER ;
288 val->type->next = expr->left->ftype;
289 val->etype = getSpec(val->type);
293 /* if address of indexed array */
294 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
295 return valForArray(expr->left);
297 /* if address of structure element then
299 if (IS_AST_OP(expr->left) &&
300 expr->left->opval.op == '.' ) {
301 return valForStructElem(expr->left->left,
306 (&some_struct)->element */
307 if (IS_AST_OP(expr->left) &&
308 expr->left->opval.op == PTR_OP &&
309 IS_ADDRESS_OF_OP(expr->left->left))
310 return valForStructElem(expr->left->left->left,
314 /* case 3. (((char *) &a) +/- constant) */
315 if (IS_AST_OP(expr) &&
316 (expr->opval.op == '+' || expr->opval.op == '-') &&
317 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
318 IS_AST_OP(expr->left->right) &&
319 expr->left->right->opval.op == '&' &&
320 IS_AST_LIT_VALUE(expr->right)) {
322 return valForCastAggr(expr->left->right->left,
323 expr->left->left->opval.lnk,
324 expr->right,expr->opval.op);
329 werror(E_INIT_WRONG);
334 /*-----------------------------------------------------------------*/
335 /* printChar - formats and prints a characater string with DB */
336 /*-----------------------------------------------------------------*/
337 void printChar (FILE * ofile, char *s, int plen)
340 int len = strlen (s);
345 while (len && pplen < plen) {
347 while (i && *s && pplen < plen) {
348 if (*s < ' ' || *s == '\"') {
351 tfprintf(ofile, "\t!ascii\n", buf);
352 tfprintf(ofile, "\t!db !constbyte\n", *s);
365 tfprintf(ofile, "\t!ascii\n", buf);
374 tfprintf(ofile, "\t!db !constbyte\n", 0);
377 /*-----------------------------------------------------------------*/
378 /* return the generic pointer high byte for a given pointer type. */
379 /*-----------------------------------------------------------------*/
380 int pointerTypeToGPByte(const int p_type)
388 /* hack - if we get a generic pointer, we just assume
389 * it's an FPOINTER (i.e. in XDATA space).
398 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
406 /*-----------------------------------------------------------------*/
407 /* printPointerType - generates ival for pointer type */
408 /*-----------------------------------------------------------------*/
409 void _printPointerType(FILE *oFile, const char *name)
413 fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
417 fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
421 /*-----------------------------------------------------------------*/
422 /* printPointerType - generates ival for pointer type */
423 /*-----------------------------------------------------------------*/
424 void printPointerType(FILE *oFile, const char *name)
426 _printPointerType(oFile, name);
427 fprintf(oFile, "\n");
430 /*-----------------------------------------------------------------*/
431 /* printGPointerType - generates ival for generic pointer type */
432 /*-----------------------------------------------------------------*/
433 void printGPointerType(FILE *oFile, const char *name,
434 const unsigned int type)
436 _printPointerType(oFile,name);
437 fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type));
440 /*-----------------------------------------------------------------*/
441 /* printIvalType - generates ival for int/char */
442 /*-----------------------------------------------------------------*/
443 void printIvalType (link * type, initList * ilist, FILE * oFile)
447 /* if initList is deep */
448 if (ilist->type == INIT_DEEP)
449 ilist = ilist->init.deep;
451 val = list2val (ilist);
452 switch (getSize (type)) {
455 tfprintf(oFile, "\t!db !constbyte\n", 0);
457 tfprintf(oFile, "\t!dbs\n",
458 aopLiteral (val, 0));
462 if (port->use_dw_for_init)
463 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
465 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
469 tfprintf (oFile, "\t!dw !constword\n", 0);
470 tfprintf (oFile, "\t!dw !constword\n", 0);
473 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
474 aopLiteral (val, 0), aopLiteral (val, 1),
475 aopLiteral (val, 2), aopLiteral (val, 3));
481 /*-----------------------------------------------------------------*/
482 /* printIvalStruct - generates initial value for structures */
483 /*-----------------------------------------------------------------*/
484 void printIvalStruct (symbol * sym,link * type,
485 initList * ilist, FILE * oFile)
490 sflds = SPEC_STRUCT (type)->fields;
491 if (ilist->type != INIT_DEEP) {
492 werror (E_INIT_STRUCT, sym->name);
496 iloop = ilist->init.deep;
498 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
499 printIval (sflds, sflds->type, iloop, oFile);
504 /*-----------------------------------------------------------------*/
505 /* printIvalChar - generates initital value for character array */
506 /*-----------------------------------------------------------------*/
507 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
514 val = list2val (ilist);
515 /* if the value is a character string */
516 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
517 if (!DCL_ELEM (type))
518 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
520 /* if size mismatch */
521 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
522 /* werror (E_ARRAY_BOUND); */
524 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
526 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
528 tfprintf (oFile, "\t!db !constbyte\n", 0);
536 printChar (oFile, s,strlen(s)+1);
540 /*-----------------------------------------------------------------*/
541 /* printIvalArray - generates code for array initialization */
542 /*-----------------------------------------------------------------*/
543 void printIvalArray (symbol * sym, link * type, initList * ilist,
547 int lcnt = 0, size = 0;
549 /* take care of the special case */
550 /* array of characters can be init */
552 if (IS_CHAR (type->next))
553 if (printIvalChar (type,
554 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
555 oFile, SPEC_CVAL (sym->etype).v_char))
558 /* not the special case */
559 if (ilist->type != INIT_DEEP) {
560 werror (E_INIT_STRUCT, sym->name);
564 iloop = ilist->init.deep;
565 lcnt = DCL_ELEM (type);
569 printIval (sym, type->next, iloop, oFile);
570 iloop = (iloop ? iloop->next : NULL);
573 /* if not array limits given & we */
574 /* are out of initialisers then */
575 if (!DCL_ELEM (type) && !iloop)
578 /* no of elements given and we */
579 /* have generated for all of them */
584 /* if we have not been given a size */
585 if (!DCL_ELEM (type))
586 DCL_ELEM (type) = size;
591 /*-----------------------------------------------------------------*/
592 /* printIvalFuncPtr - generate initial value for function pointers */
593 /*-----------------------------------------------------------------*/
594 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
599 val = list2val (ilist);
600 /* check the types */
601 if ((dLvl = checkType (val->type, type->next)) <= 0) {
602 tfprintf(oFile, "\t!dw !constword\n", 0);
606 /* now generate the name */
608 if (port->use_dw_for_init)
610 tfprintf(oFile, "\t!dws\n", val->name);
614 printPointerType(oFile, val->name);
618 if (port->use_dw_for_init)
620 tfprintf(oFile, "\t!dws\n", val->sym->rname);
624 printPointerType(oFile, val->sym->rname);
630 /*-----------------------------------------------------------------*/
631 /* printIvalCharPtr - generates initial values for character pointers */
632 /*-----------------------------------------------------------------*/
633 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
637 /* PENDING: this is _very_ mcs51 specific, including a magic
639 It's also endin specific.
641 size = getSize (type);
643 if (val->name && strlen(val->name)) {
644 if (size == 1) /* This appears to be Z80 specific?? */
647 "\t!dbs\n", val->name);
649 else if (size == FPTRSIZE)
651 if (port->use_dw_for_init)
653 tfprintf(oFile, "\t!dws\n", val->name);
657 printPointerType(oFile, val->name);
660 else if (size == GPTRSIZE)
662 /* PENDING: 0x02 or 0x%02x, CDATA? */
663 printGPointerType(oFile, val->name,
664 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
665 PTR_TYPE(SPEC_OCLS(val->etype))));
669 fprintf(stderr, "*** internal error: unknown size in "
670 "printIvalCharPtr.\n");
674 /* What is this case? Are these pointers? */
677 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
680 if (port->use_dw_for_init)
681 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
683 tfprintf(oFile, "\t.byte %s,%s\n",
684 aopLiteral(val, 0),aopLiteral(val, 1));
687 /* PENDING: 0x02 or 0x%02x, CDATA? */
688 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
689 aopLiteral (val, 0), aopLiteral (val, 1));
697 if (val->sym && val->sym->isstrlit)
698 addSet (&statsg->syms, val->sym);
703 /*-----------------------------------------------------------------*/
704 /* printIvalPtr - generates initial value for pointers */
705 /*-----------------------------------------------------------------*/
706 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
712 if (ilist->type == INIT_DEEP)
713 ilist = ilist->init.deep;
715 /* function pointer */
716 if (IS_FUNC (type->next)) {
717 printIvalFuncPtr (type, ilist, oFile);
721 if (!(val = initPointer (ilist)))
724 /* if character pointer */
725 if (IS_CHAR (type->next))
726 if (printIvalCharPtr (sym, type, val, oFile))
730 if (checkType (type, val->type) != 1)
731 werror (E_INIT_WRONG);
733 /* if val is literal */
734 if (IS_LITERAL (val->etype)) {
735 switch (getSize (type)) {
737 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
740 if (port->use_dw_for_init)
741 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
743 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
746 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
747 aopLiteral (val, 0), aopLiteral (val, 1));
753 size = getSize (type);
755 if (size == 1) /* Z80 specific?? */
757 tfprintf (oFile, "\t!dbs\n", val->name);
759 else if (size == FPTRSIZE)
761 tfprintf (oFile, "\t!dws\n", val->name);
763 else if (size == GPTRSIZE)
765 printGPointerType(oFile, val->name,
766 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
767 PTR_TYPE(SPEC_OCLS(val->etype))));
772 /*-----------------------------------------------------------------*/
773 /* printIval - generates code for initial value */
774 /*-----------------------------------------------------------------*/
775 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
780 /* if structure then */
781 if (IS_STRUCT (type)) {
782 printIvalStruct (sym, type, ilist, oFile);
786 /* if this is a pointer */
788 printIvalPtr (sym, type, ilist, oFile);
792 /* if this is an array */
793 if (IS_ARRAY (type)) {
794 printIvalArray (sym, type, ilist, oFile);
798 /* if type is SPECIFIER */
799 if (IS_SPEC (type)) {
800 printIvalType (type, ilist, oFile);
805 /*-----------------------------------------------------------------*/
806 /* emitStaticSeg - emitcode for the static segment */
807 /*-----------------------------------------------------------------*/
808 void emitStaticSeg(memmap * map, FILE *out)
812 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
816 /* for all variables in this segment do */
817 for (sym = setFirstItem (map->syms); sym;
818 sym = setNextItem (map->syms)) {
820 /* if it is "extern" then do nothing */
821 if (IS_EXTERN (sym->etype))
824 /* if it is not static add it to the public
826 if (!IS_STATIC (sym->etype))
827 addSetHead (&publics, sym);
829 /* print extra debug info if required */
830 if ((options.debug || sym->level == 0) && !options.nodebug) {
832 cdbSymbol(sym,cdbFile,FALSE,FALSE);
834 if (!sym->level) { /* global */
835 if (IS_STATIC(sym->etype))
836 fprintf(out,"F%s$",moduleName); /* scope is file */
838 fprintf(out,"G$"); /* scope is global */
841 /* symbol is local */
843 (sym->localof ? sym->localof->name : "-null-"));
844 fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
847 /* if it has an absolute address */
848 if (SPEC_ABSA (sym->etype)) {
849 if ((options.debug || sym->level == 0) && !options.nodebug)
850 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
852 fprintf (out, "%s\t=\t0x%04x\n",
854 SPEC_ADDR (sym->etype));
857 if ((options.debug || sym->level == 0) && !options.nodebug)
858 fprintf(out," == .\n");
860 /* if it has an initial value */
862 fprintf (out, "%s:\n", sym->rname);
864 resolveIvalSym (sym->ival);
865 printIval (sym, sym->type, sym->ival, out);
870 fprintf (out, "%s:\n", sym->rname);
871 /* special case for character strings */
872 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
873 SPEC_CVAL (sym->etype).v_char)
875 SPEC_CVAL (sym->etype).v_char,
876 strlen(SPEC_CVAL (sym->etype).v_char)+1);
878 tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
884 /*-----------------------------------------------------------------*/
885 /* emitMaps - emits the code for the data portion the code */
886 /*-----------------------------------------------------------------*/
889 /* no special considerations for the following
890 data, idata & bit & xdata */
891 emitRegularMap (data, TRUE, TRUE);
892 emitRegularMap (idata, TRUE,TRUE);
893 emitRegularMap (bit, TRUE,FALSE);
894 emitRegularMap (xdata, TRUE,TRUE);
895 emitRegularMap (sfr, FALSE,FALSE);
896 emitRegularMap (sfrbit, FALSE,FALSE);
897 emitRegularMap (home, TRUE,FALSE);
898 emitRegularMap (code, TRUE,FALSE);
900 emitStaticSeg (statsg, code->oFile);
903 /*-----------------------------------------------------------------*/
904 /* flushStatics - flush all currently defined statics out to file */
905 /* and delete. Temporary function */
906 /*-----------------------------------------------------------------*/
907 void flushStatics(void)
909 emitStaticSeg(statsg, codeOutFile);
913 /*-----------------------------------------------------------------*/
914 /* createInterruptVect - creates the interrupt vector */
915 /*-----------------------------------------------------------------*/
916 void createInterruptVect (FILE * vFile)
919 mainf = newSymbol ("main", 0);
922 /* only if the main function exists */
923 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
924 if (!options.cc_only)
929 /* if the main is only a prototype ie. no body then do nothing */
931 /* if ! compile only then main function should be present */
932 if (!options.cc_only)
937 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
938 fprintf (vFile, "__interrupt_vect:\n");
941 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
943 /* "generic" interrupt table header (if port doesn't specify one).
945 * Look suspiciously like 8051 code to me...
948 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
951 /* now for the other interrupts */
952 for (; i < maxInterrupts; i++) {
954 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
956 fprintf (vFile, "\treti\n\t.ds\t7\n");
963 ";--------------------------------------------------------\n"
964 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
968 ";--------------------------------------------------------\n"};
971 /*-----------------------------------------------------------------*/
972 /* initialComments - puts in some initial comments */
973 /*-----------------------------------------------------------------*/
974 void initialComments (FILE * afile)
978 fprintf (afile, "%s", iComments1);
979 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
980 fprintf (afile, "%s", iComments2);
983 /*-----------------------------------------------------------------*/
984 /* printPublics - generates .global for publics */
985 /*-----------------------------------------------------------------*/
986 void printPublics (FILE * afile)
990 fprintf (afile, "%s", iComments2);
991 fprintf (afile, "; Public variables in this module\n");
992 fprintf (afile, "%s", iComments2);
994 for (sym = setFirstItem (publics); sym;
995 sym = setNextItem (publics))
996 tfprintf(afile, "\t!global\n", sym->rname);
999 /*-----------------------------------------------------------------*/
1000 /* printExterns - generates .global for externs */
1001 /*-----------------------------------------------------------------*/
1002 void printExterns (FILE * afile)
1006 fprintf (afile, "%s", iComments2);
1007 fprintf (afile, "; Externals used\n");
1008 fprintf (afile, "%s", iComments2);
1010 for (sym = setFirstItem (externs); sym;
1011 sym = setNextItem (externs))
1012 tfprintf(afile, "\t!global\n", sym->rname);
1015 /*-----------------------------------------------------------------*/
1016 /* emitOverlay - will emit code for the overlay stuff */
1017 /*-----------------------------------------------------------------*/
1018 static void emitOverlay(FILE *afile)
1022 if (!elementsInSet(ovrSetSets))
1023 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1025 /* for each of the sets in the overlay segment do */
1026 for (ovrset = setFirstItem(ovrSetSets); ovrset;
1027 ovrset = setNextItem(ovrSetSets)) {
1031 if (elementsInSet(ovrset)) {
1032 /* this dummy area is used to fool the assembler
1033 otherwise the assembler will append each of these
1034 declarations into one chunk and will not overlay
1036 fprintf(afile,"\t.area _DUMMY\n");
1037 /* output the area informtion */
1038 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1041 for (sym = setFirstItem(ovrset); sym;
1042 sym = setNextItem(ovrset)) {
1044 /* if extern then add it to the publics tabledo nothing */
1045 if (IS_EXTERN (sym->etype))
1048 /* if allocation required check is needed
1049 then check if the symbol really requires
1050 allocation only for local variables */
1051 if (!IS_AGGREGATE(sym->type) &&
1052 !(sym->_isparm && !IS_REGPARM(sym->etype))
1053 && !sym->allocreq && sym->level)
1056 /* if global variable & not static or extern
1057 and addPublics allowed then add it to the public set */
1058 if ((sym->_isparm && !IS_REGPARM(sym->etype))
1059 && !IS_STATIC (sym->etype))
1060 addSetHead (&publics, sym);
1062 /* if extern then do nothing or is a function
1064 if (IS_FUNC (sym->type))
1067 /* print extra debug info if required */
1068 if ((options.debug || sym->level == 0) && !options.nodebug) {
1070 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1072 if (!sym->level) { /* global */
1073 if (IS_STATIC(sym->etype))
1074 fprintf(afile,"F%s$",moduleName); /* scope is file */
1076 fprintf(afile,"G$"); /* scope is global */
1079 /* symbol is local */
1080 fprintf(afile,"L%s$",
1081 (sym->localof ? sym->localof->name : "-null-"));
1082 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1085 /* if is has an absolute address then generate
1086 an equate for this no need to allocate space */
1087 if (SPEC_ABSA (sym->etype)) {
1089 if ((options.debug || sym->level == 0) && !options.nodebug)
1090 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1092 fprintf (afile, "%s\t=\t0x%04x\n",
1094 SPEC_ADDR (sym->etype));
1097 if ((options.debug || sym->level == 0) && !options.nodebug)
1098 fprintf(afile,"==.\n");
1100 /* allocate space */
1101 tfprintf(afile, "!labeldef\n", sym->rname);
1102 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1109 /*-----------------------------------------------------------------*/
1110 /* glue - the final glue that hold the whole thing together */
1111 /*-----------------------------------------------------------------*/
1116 FILE *ovrFile = tempfile();
1118 addSetHead(&tmpfileSet,ovrFile);
1119 /* print the global struct definitions */
1120 if (options.debug && !options.nodebug)
1121 cdbStructBlock (0,cdbFile);
1124 /* PENDING: this isnt the best place but it will do */
1125 if (port->general.glue_up_main) {
1126 /* create the interrupt vector table */
1127 createInterruptVect (vFile);
1130 addSetHead(&tmpfileSet,vFile);
1132 /* emit code for the all the variables declared */
1134 /* do the overlay segments */
1135 emitOverlay(ovrFile);
1137 /* now put it all together into the assembler file */
1138 /* create the assembler file name */
1140 if (!options.c1mode) {
1141 sprintf (buffer, srcFileName);
1142 strcat (buffer, ".asm");
1145 strcpy(buffer, options.out_name);
1148 if (!(asmFile = fopen (buffer, "w"))) {
1149 werror (E_FILE_OPEN_ERR, buffer);
1153 /* initial comments */
1154 initialComments (asmFile);
1156 /* print module name */
1157 tfprintf(asmFile, "\t!module\n", moduleName);
1158 tfprintf(asmFile, "\t!fileprelude\n");
1160 /* Let the port generate any global directives, etc. */
1161 if (port->genAssemblerPreamble)
1163 port->genAssemblerPreamble(asmFile);
1166 /* print the global variables in this module */
1167 printPublics (asmFile);
1168 if (port->assembler.externGlobal)
1169 printExterns (asmFile);
1171 /* copy the sfr segment */
1172 fprintf (asmFile, "%s", iComments2);
1173 fprintf (asmFile, "; special function registers\n");
1174 fprintf (asmFile, "%s", iComments2);
1175 copyFile (asmFile, sfr->oFile);
1177 /* copy the sbit segment */
1178 fprintf (asmFile, "%s", iComments2);
1179 fprintf (asmFile, "; special function bits \n");
1180 fprintf (asmFile, "%s", iComments2);
1181 copyFile (asmFile, sfrbit->oFile);
1183 /* copy the data segment */
1184 fprintf (asmFile, "%s", iComments2);
1185 fprintf (asmFile, "; internal ram data\n");
1186 fprintf (asmFile, "%s", iComments2);
1187 copyFile (asmFile, data->oFile);
1190 /* create the overlay segments */
1191 fprintf (asmFile, "%s", iComments2);
1192 fprintf (asmFile, "; overlayable items in internal ram \n");
1193 fprintf (asmFile, "%s", iComments2);
1194 copyFile (asmFile, ovrFile);
1196 /* create the stack segment MOF */
1197 if (mainf && mainf->fbody) {
1198 fprintf (asmFile, "%s", iComments2);
1199 fprintf (asmFile, "; Stack segment in internal ram \n");
1200 fprintf (asmFile, "%s", iComments2);
1201 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1202 "__start__stack:\n\t.ds\t1\n\n");
1205 /* create the idata segment */
1206 fprintf (asmFile, "%s", iComments2);
1207 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1208 fprintf (asmFile, "%s", iComments2);
1209 copyFile (asmFile, idata->oFile);
1211 /* copy the bit segment */
1212 fprintf (asmFile, "%s", iComments2);
1213 fprintf (asmFile, "; bit data\n");
1214 fprintf (asmFile, "%s", iComments2);
1215 copyFile (asmFile, bit->oFile);
1217 /* if external stack then reserve space of it */
1218 if (mainf && mainf->fbody && options.useXstack ) {
1219 fprintf (asmFile, "%s", iComments2);
1220 fprintf (asmFile, "; external stack \n");
1221 fprintf (asmFile, "%s", iComments2);
1222 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1223 fprintf (asmFile,"\t.ds 256\n");
1227 /* copy xtern ram data */
1228 fprintf (asmFile, "%s", iComments2);
1229 fprintf (asmFile, "; external ram data\n");
1230 fprintf (asmFile, "%s", iComments2);
1231 copyFile (asmFile, xdata->oFile);
1233 /* copy the interrupt vector table */
1234 if (mainf && mainf->fbody) {
1235 fprintf (asmFile, "%s", iComments2);
1236 fprintf (asmFile, "; interrupt vector \n");
1237 fprintf (asmFile, "%s", iComments2);
1238 copyFile (asmFile, vFile);
1241 /* copy global & static initialisations */
1242 fprintf (asmFile, "%s", iComments2);
1243 fprintf (asmFile, "; global & static initialisations\n");
1244 fprintf (asmFile, "%s", iComments2);
1246 /* Everywhere we generate a reference to the static_name area,
1247 * (which is currently only here), we immediately follow it with a
1248 * definition of the post_static_name area. This guarantees that
1249 * the post_static_name area will immediately follow the static_name
1252 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1253 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1254 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1256 if (mainf && mainf->fbody) {
1257 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1258 /* if external stack is specified then the
1259 higher order byte of the xdatalocation is
1260 going into P2 and the lower order going into
1262 if (options.useXstack) {
1263 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1264 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1265 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1266 (unsigned int)options.xdata_loc & 0xff);
1269 /* initialise the stack pointer */
1270 /* if the user specified a value then use it */
1271 if (options.stack_loc)
1272 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1274 /* no: we have to compute it */
1275 if (!options.stackOnData && maxRegBank <= 3)
1276 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1278 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1280 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1281 fprintf (asmFile,"\tmov\ta,dpl\n");
1282 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1283 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1284 fprintf (asmFile,"__sdcc_init_data:\n");
1287 copyFile (asmFile, statsg->oFile);
1289 if (port->general.glue_up_main && mainf && mainf->fbody)
1291 /* This code is generated in the post-static area.
1292 * This area is guaranteed to follow the static area
1293 * by the ugly shucking and jiving about 20 lines ago.
1295 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1296 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1302 "%s", iComments2, iComments2);
1303 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1304 copyFile (asmFile, home->oFile);
1306 /* copy over code */
1307 fprintf (asmFile, "%s", iComments2);
1308 fprintf (asmFile, "; code\n");
1309 fprintf (asmFile, "%s", iComments2);
1310 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1311 if (mainf && mainf->fbody) {
1313 /* entry point @ start of CSEG */
1314 fprintf (asmFile,"__sdcc_program_startup:\n");
1316 /* put in the call to main */
1317 fprintf(asmFile,"\tlcall\t_main\n");
1318 if (options.mainreturn) {
1320 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1321 fprintf(asmFile,"\tret\n");
1325 fprintf(asmFile,";\treturn from main will lock up\n");
1326 fprintf(asmFile,"\tsjmp .\n");
1329 copyFile (asmFile, code->oFile);
1332 applyToSet(tmpfileSet,closeTmpFiles);
1333 applyToSet(tmpfileNameSet, rmTmpFiles);
1336 /** Creates a temporary file a'la tmpfile which avoids the bugs
1337 in cygwin wrt c:\tmp.
1338 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1340 FILE *tempfile(void)
1342 const char *tmpdir = NULL;
1344 tmpdir = getenv("TMP");
1345 else if (getenv("TEMP"))
1346 tmpdir = getenv("TEMP");
1347 else if (getenv("TMPDIR"))
1348 tmpdir = getenv("TMPDIR");
1350 char *name = tempnam(tmpdir, "sdcc");
1352 FILE *fp = fopen(name, "w+b");
1355 addSetHead(&tmpfileNameSet, name);
1364 char *gc_strdup(const char *s)
1367 ALLOC_ATOMIC(ret, strlen(s)+1);