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 */
35 /* TODO: this should be configurable (DS803C90 uses more than 6) */
36 int maxInterrupts = 6;
37 extern int maxRegBank ;
39 extern char *VersionString;
40 extern FILE *codeOutFile;
41 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
42 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
43 /*-----------------------------------------------------------------*/
44 /* closeTmpFiles - closes all tmp files created by the compiler */
45 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
46 /*-----------------------------------------------------------------*/
47 DEFSETFUNC(closeTmpFiles)
57 /*-----------------------------------------------------------------*/
58 /* rmTmpFiles - closes all tmp files created by the compiler */
59 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
60 /*-----------------------------------------------------------------*/
61 DEFSETFUNC(rmTmpFiles)
72 /*-----------------------------------------------------------------*/
73 /* copyFile - copies source file to destination file */
74 /*-----------------------------------------------------------------*/
75 void copyFile (FILE * dest, FILE * src)
81 if ((ch = fgetc (src)) != EOF)
85 char *aopLiteralLong(value *val, int offset, int size)
93 /* if it is a float then it gets tricky */
94 /* otherwise it is fairly simple */
95 if (!IS_FLOAT(val->type)) {
96 unsigned long v = floatFromVal(val);
101 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
104 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
107 /* Hmm. Too big for now. */
110 ALLOC_ATOMIC(rs,strlen(buffer)+1);
111 return strcpy (rs,buffer);
114 /* PENDING: For now size must be 1 */
117 /* it is type float */
118 fl.f = (float) floatFromVal(val);
120 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
122 tsprintf(buffer, "!immedbyte", fl.c[offset]);
124 ALLOC_ATOMIC(rs,strlen(buffer)+1);
125 return strcpy (rs,buffer);
128 /*-----------------------------------------------------------------*/
129 /* aopLiteral - string from a literal value */
130 /*-----------------------------------------------------------------*/
131 char *aopLiteral (value *val, int offset)
133 return aopLiteralLong(val, offset, 1);
136 /*-----------------------------------------------------------------*/
137 /* emitRegularMap - emit code for maps with no special cases */
138 /*-----------------------------------------------------------------*/
139 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
144 tfprintf(map->oFile, "\t!area\n", map->sname);
146 /* print the area name */
147 for (sym = setFirstItem (map->syms); sym;
148 sym = setNextItem (map->syms)) {
150 /* if extern then do nothing */
151 if (IS_EXTERN (sym->etype))
154 /* if allocation required check is needed
155 then check if the symbol really requires
156 allocation only for local variables */
157 if (arFlag && !IS_AGGREGATE(sym->type) &&
158 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
159 !sym->allocreq && sym->level)
162 /* if global variable & not static or extern
163 and addPublics allowed then add it to the public set */
164 if ((sym->level == 0 ||
165 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
167 !IS_STATIC (sym->etype))
168 addSetHead (&publics, sym);
170 /* if extern then do nothing or is a function
172 if (IS_FUNC (sym->type))
175 /* print extra debug info if required */
176 if ((options.debug || sym->level == 0) && !options.nodebug) {
178 cdbSymbol(sym,cdbFile,FALSE,FALSE);
180 if (!sym->level) /* global */
181 if (IS_STATIC(sym->etype))
182 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
184 fprintf(map->oFile,"G$"); /* scope is global */
186 /* symbol is local */
187 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
188 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
191 /* if is has an absolute address then generate
192 an equate for this no need to allocate space */
193 if (SPEC_ABSA (sym->etype)) {
194 if ((options.debug || sym->level == 0) && !options.nodebug)
195 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
197 fprintf (map->oFile, "%s\t=\t0x%04x\n",
199 SPEC_ADDR (sym->etype));
203 if ((options.debug || sym->level == 0) && !options.nodebug)
204 fprintf(map->oFile,"==.\n");
205 tfprintf(map->oFile, "!labeldef\n", sym->rname);
206 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
209 /* if it has a initial value then do it only if
210 it is a global variable */
211 if (sym->ival && sym->level == 0) {
214 if (IS_AGGREGATE (sym->type))
215 ival = initAggregates (sym, sym->ival, NULL);
217 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
218 decorateType (resolveSymbols (list2expr (sym->ival))));
219 codeOutFile = statsg->oFile;
220 eBBlockFromiCode (iCodeFromAst (ival));
227 /*-----------------------------------------------------------------*/
228 /* initPointer - pointer initialization code massaging */
229 /*-----------------------------------------------------------------*/
230 value *initPointer (initList *ilist)
233 ast *expr = list2expr(ilist);
238 /* try it the oldway first */
239 if ((val = constExprValue(expr,FALSE)))
242 /* no then we have to do these cludgy checks */
243 /* pointers can be initialized with address of
244 a variable or address of an array element */
245 if (IS_AST_OP(expr) && expr->opval.op == '&') {
246 /* address of symbol */
247 if (IS_AST_SYM_VALUE(expr->left)) {
248 val = copyValue(AST_VALUE(expr->left));
249 val->type = newLink();
250 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
251 DCL_TYPE(val->type) = CPOINTER ;
252 DCL_PTR_CONST(val->type) = port->mem.code_ro;
255 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
256 DCL_TYPE(val->type) = FPOINTER;
258 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
259 DCL_TYPE(val->type) = PPOINTER ;
261 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
262 DCL_TYPE(val->type) = IPOINTER ;
264 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
265 DCL_TYPE(val->type) = EEPPOINTER ;
267 DCL_TYPE(val->type) = POINTER ;
268 val->type->next = expr->left->ftype;
269 val->etype = getSpec(val->type);
273 /* if address of indexed array */
274 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
275 return valForArray(expr->left);
277 /* if address of structure element then
279 if (IS_AST_OP(expr->left) &&
280 expr->left->opval.op == '.' ) {
281 return valForStructElem(expr->left->left,
286 (&some_struct)->element */
287 if (IS_AST_OP(expr->left) &&
288 expr->left->opval.op == PTR_OP &&
289 IS_ADDRESS_OF_OP(expr->left->left))
290 return valForStructElem(expr->left->left->left,
295 werror(E_INIT_WRONG);
300 /*-----------------------------------------------------------------*/
301 /* printChar - formats and prints a characater string with DB */
302 /*-----------------------------------------------------------------*/
303 void printChar (FILE * ofile, char *s, int plen)
306 int len = strlen (s);
311 while (len && pplen < plen) {
313 while (i && *s && pplen < plen) {
314 if (*s < ' ' || *s == '\"') {
317 tfprintf(ofile, "\t!ascii\n", buf);
318 tfprintf(ofile, "\t!db\n", *s);
331 tfprintf(ofile, "\t!ascii\n", buf);
339 tfprintf(ofile, "\t!db\n", 0);
342 /*-----------------------------------------------------------------*/
343 /* printIvalType - generates ival for int/char */
344 /*-----------------------------------------------------------------*/
345 void printIvalType (link * type, initList * ilist, FILE * oFile)
349 /* if initList is deep */
350 if (ilist->type == INIT_DEEP)
351 ilist = ilist->init.deep;
353 val = list2val (ilist);
354 switch (getSize (type)) {
357 tfprintf(oFile, "\t!db\n", 0);
359 tfprintf(oFile, "\t!dbs\n",
360 aopLiteral (val, 0));
364 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
368 tfprintf (oFile, "\t!dw\n", 0);
369 tfprintf (oFile, "\t!dw\n", 0);
372 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
373 aopLiteral (val, 0), aopLiteral (val, 1),
374 aopLiteral (val, 2), aopLiteral (val, 3));
380 /*-----------------------------------------------------------------*/
381 /* printIvalStruct - generates initial value for structures */
382 /*-----------------------------------------------------------------*/
383 void printIvalStruct (symbol * sym,link * type,
384 initList * ilist, FILE * oFile)
389 sflds = SPEC_STRUCT (type)->fields;
390 if (ilist->type != INIT_DEEP) {
391 werror (E_INIT_STRUCT, sym->name);
395 iloop = ilist->init.deep;
397 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
398 printIval (sflds, sflds->type, iloop, oFile);
403 /*-----------------------------------------------------------------*/
404 /* printIvalChar - generates initital value for character array */
405 /*-----------------------------------------------------------------*/
406 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
413 val = list2val (ilist);
414 /* if the value is a character string */
415 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
416 if (!DCL_ELEM (type))
417 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
419 /* if size mismatch */
420 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
421 /* werror (E_ARRAY_BOUND); */
423 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
425 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
427 tfprintf (oFile, "\t!db\n", 0);
435 printChar (oFile, s,strlen(s)+1);
439 /*-----------------------------------------------------------------*/
440 /* printIvalArray - generates code for array initialization */
441 /*-----------------------------------------------------------------*/
442 void printIvalArray (symbol * sym, link * type, initList * ilist,
446 int lcnt = 0, size = 0;
448 /* take care of the special case */
449 /* array of characters can be init */
451 if (IS_CHAR (type->next))
452 if (printIvalChar (type,
453 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
454 oFile, SPEC_CVAL (sym->etype).v_char))
457 /* not the special case */
458 if (ilist->type != INIT_DEEP) {
459 werror (E_INIT_STRUCT, sym->name);
463 iloop = ilist->init.deep;
464 lcnt = DCL_ELEM (type);
468 printIval (sym, type->next, iloop, oFile);
469 iloop = (iloop ? iloop->next : NULL);
472 /* if not array limits given & we */
473 /* are out of initialisers then */
474 if (!DCL_ELEM (type) && !iloop)
477 /* no of elements given and we */
478 /* have generated for all of them */
483 /* if we have not been given a size */
484 if (!DCL_ELEM (type))
485 DCL_ELEM (type) = size;
490 /*-----------------------------------------------------------------*/
491 /* printIvalFuncPtr - generate initial value for function pointers */
492 /*-----------------------------------------------------------------*/
493 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
498 val = list2val (ilist);
499 /* check the types */
500 if ((dLvl = checkType (val->type, type->next)) <= 0) {
501 tfprintf(oFile, "\t!dw\n", 0);
505 /* now generate the name */
507 if (IS_LITERAL (val->etype))
508 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
510 tfprintf(oFile, "\t!dws\n", val->name);
513 tfprintf(oFile, "\t!dws\n", val->sym->rname);
518 /*-----------------------------------------------------------------*/
519 /* printIvalCharPtr - generates initial values for character pointers */
520 /*-----------------------------------------------------------------*/
521 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
525 /* PENDING: this is _very_ mcs51 specific, including a magic
527 It's also endin specific.
529 size = getSize (type);
531 if (val->name && strlen(val->name)) {
535 "\t!dbs\n", val->name) ;
538 tfprintf(oFile, "\t!dws\n", val->name);
540 /* PENDING: probably just 3 */
542 /* PENDING: 0x02 or 0x%02x, CDATA? */
544 "\t.byte %s,(%s >> 8),#0x02\n",
545 val->name, val->name);
551 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
554 tfprintf(oFile, "\t!dws\n",
555 aopLiteralLong(val, 0, 2));
558 /* PENDING: 0x02 or 0x%02x, CDATA? */
559 fprintf(oFile, "\t.byte %s,%s,0x02\n",
560 aopLiteral (val, 0), aopLiteral (val, 1));
568 if (val->sym && val->sym->isstrlit)
569 addSet (&statsg->syms, val->sym);
574 /*-----------------------------------------------------------------*/
575 /* printIvalPtr - generates initial value for pointers */
576 /*-----------------------------------------------------------------*/
577 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
582 if (ilist->type == INIT_DEEP)
583 ilist = ilist->init.deep;
585 /* function pointer */
586 if (IS_FUNC (type->next)) {
587 printIvalFuncPtr (type, ilist, oFile);
591 if (!(val = initPointer (ilist)))
594 /* if character pointer */
595 if (IS_CHAR (type->next))
596 if (printIvalCharPtr (sym, type, val, oFile))
600 if (checkType (type, val->type) != 1)
601 werror (E_INIT_WRONG);
603 /* if val is literal */
604 if (IS_LITERAL (val->etype)) {
605 switch (getSize (type)) {
607 tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
610 tfprintf (oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
613 fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
614 aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
620 switch (getSize (type)) {
622 tfprintf (oFile, "\t!dbs\n", val->name);
625 tfprintf (oFile, "\t!dws\n", val->name);
629 fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
630 val->name, val->name, DCL_TYPE(val->type));
635 /*-----------------------------------------------------------------*/
636 /* printIval - generates code for initial value */
637 /*-----------------------------------------------------------------*/
638 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
643 /* if structure then */
644 if (IS_STRUCT (type)) {
645 printIvalStruct (sym, type, ilist, oFile);
649 /* if this is a pointer */
651 printIvalPtr (sym, type, ilist, oFile);
655 /* if this is an array */
656 if (IS_ARRAY (type)) {
657 printIvalArray (sym, type, ilist, oFile);
661 /* if type is SPECIFIER */
662 if (IS_SPEC (type)) {
663 printIvalType (type, ilist, oFile);
668 /*-----------------------------------------------------------------*/
669 /* emitStaticSeg - emitcode for the static segment */
670 /*-----------------------------------------------------------------*/
671 void emitStaticSeg (memmap * map)
675 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
678 /* for all variables in this segment do */
679 for (sym = setFirstItem (map->syms); sym;
680 sym = setNextItem (map->syms)) {
682 /* if it is "extern" then do nothing */
683 if (IS_EXTERN (sym->etype))
686 /* if it is not static add it to the public
688 if (!IS_STATIC (sym->etype))
689 addSetHead (&publics, sym);
691 /* print extra debug info if required */
692 if ((options.debug || sym->level == 0) && !options.nodebug) {
694 cdbSymbol(sym,cdbFile,FALSE,FALSE);
696 if (!sym->level) { /* global */
697 if (IS_STATIC(sym->etype))
698 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
700 fprintf(code->oFile,"G$"); /* scope is global */
703 /* symbol is local */
704 fprintf(code->oFile,"L%s$",
705 (sym->localof ? sym->localof->name : "-null-"));
706 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
709 /* if it has an absolute address */
710 if (SPEC_ABSA (sym->etype)) {
711 if ((options.debug || sym->level == 0) && !options.nodebug)
712 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
714 fprintf (code->oFile, "%s\t=\t0x%04x\n",
716 SPEC_ADDR (sym->etype));
719 if ((options.debug || sym->level == 0) && !options.nodebug)
720 fprintf(code->oFile," == .\n");
722 /* if it has an initial value */
724 fprintf (code->oFile, "%s:\n", sym->rname);
726 resolveIvalSym (sym->ival);
727 printIval (sym, sym->type, sym->ival, code->oFile);
732 fprintf (code->oFile, "%s:\n", sym->rname);
733 /* special case for character strings */
734 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
735 SPEC_CVAL (sym->etype).v_char)
736 printChar (code->oFile,
737 SPEC_CVAL (sym->etype).v_char,
738 strlen(SPEC_CVAL (sym->etype).v_char)+1);
740 tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
746 /*-----------------------------------------------------------------*/
747 /* emitMaps - emits the code for the data portion the code */
748 /*-----------------------------------------------------------------*/
751 /* no special considerations for the following
752 data, idata & bit & xdata */
753 emitRegularMap (data, TRUE, TRUE);
754 emitRegularMap (idata, TRUE,TRUE);
755 emitRegularMap (bit, TRUE,FALSE);
756 emitRegularMap (xdata, TRUE,TRUE);
757 emitRegularMap (sfr, FALSE,FALSE);
758 emitRegularMap (sfrbit, FALSE,FALSE);
759 emitRegularMap (code, TRUE,FALSE);
760 emitStaticSeg (statsg);
763 /*-----------------------------------------------------------------*/
764 /* createInterruptVect - creates the interrupt vector */
765 /*-----------------------------------------------------------------*/
766 void createInterruptVect (FILE * vFile)
769 mainf = newSymbol ("main", 0);
772 /* only if the main function exists */
773 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
774 if (!options.cc_only)
779 /* if the main is only a prototype ie. no body then do nothing */
781 /* if ! compile only then main function should be present */
782 if (!options.cc_only)
787 tfprintf(vFile, "\t!area\n", CODE_NAME);
788 fprintf (vFile, "__interrupt_vect:\n");
791 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
793 /* "generic" interrupt table header (if port doesn't specify one).
795 * Look suspiciously like 8051 code to me...
798 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
801 /* now for the other interrupts */
802 for (; i < maxInterrupts; i++) {
804 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
806 fprintf (vFile, "\treti\n\t.ds\t7\n");
813 ";--------------------------------------------------------\n"
814 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
818 ";--------------------------------------------------------\n"};
821 /*-----------------------------------------------------------------*/
822 /* initialComments - puts in some initial comments */
823 /*-----------------------------------------------------------------*/
824 void initialComments (FILE * afile)
828 fprintf (afile, "%s", iComments1);
829 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
830 fprintf (afile, "%s", iComments2);
833 /*-----------------------------------------------------------------*/
834 /* printPublics - generates .global for publics */
835 /*-----------------------------------------------------------------*/
836 void printPublics (FILE * afile)
840 fprintf (afile, "%s", iComments2);
841 fprintf (afile, "; publics variables in this module\n");
842 fprintf (afile, "%s", iComments2);
844 for (sym = setFirstItem (publics); sym;
845 sym = setNextItem (publics))
846 tfprintf(afile, "\t!global\n", sym->rname);
849 /*-----------------------------------------------------------------*/
850 /* emitOverlay - will emit code for the overlay stuff */
851 /*-----------------------------------------------------------------*/
852 static void emitOverlay(FILE *afile)
856 if (!elementsInSet(ovrSetSets))
857 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
859 /* for each of the sets in the overlay segment do */
860 for (ovrset = setFirstItem(ovrSetSets); ovrset;
861 ovrset = setNextItem(ovrSetSets)) {
865 if (elementsInSet(ovrset)) {
866 /* this dummy area is used to fool the assembler
867 otherwise the assembler will append each of these
868 declarations into one chunk and will not overlay
870 fprintf(afile,"\t.area _DUMMY\n");
871 /* output the area informtion */
872 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
875 for (sym = setFirstItem(ovrset); sym;
876 sym = setNextItem(ovrset)) {
878 /* if extern then do nothing */
879 if (IS_EXTERN (sym->etype))
882 /* if allocation required check is needed
883 then check if the symbol really requires
884 allocation only for local variables */
885 if (!IS_AGGREGATE(sym->type) &&
886 !(sym->_isparm && !IS_REGPARM(sym->etype))
887 && !sym->allocreq && sym->level)
890 /* if global variable & not static or extern
891 and addPublics allowed then add it to the public set */
892 if ((sym->_isparm && !IS_REGPARM(sym->etype))
893 && !IS_STATIC (sym->etype))
894 addSetHead (&publics, sym);
896 /* if extern then do nothing or is a function
898 if (IS_FUNC (sym->type))
901 /* print extra debug info if required */
902 if ((options.debug || sym->level == 0) && !options.nodebug) {
904 cdbSymbol(sym,cdbFile,FALSE,FALSE);
906 if (!sym->level) { /* global */
907 if (IS_STATIC(sym->etype))
908 fprintf(afile,"F%s$",moduleName); /* scope is file */
910 fprintf(afile,"G$"); /* scope is global */
913 /* symbol is local */
914 fprintf(afile,"L%s$",
915 (sym->localof ? sym->localof->name : "-null-"));
916 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
919 /* if is has an absolute address then generate
920 an equate for this no need to allocate space */
921 if (SPEC_ABSA (sym->etype)) {
923 if ((options.debug || sym->level == 0) && !options.nodebug)
924 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
926 fprintf (afile, "%s\t=\t0x%04x\n",
928 SPEC_ADDR (sym->etype));
931 if ((options.debug || sym->level == 0) && !options.nodebug)
932 fprintf(afile,"==.\n");
935 tfprintf(afile, "\t!labeldef\n", sym->rname);
936 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
943 /*-----------------------------------------------------------------*/
944 /* glue - the final glue that hold the whole thing together */
945 /*-----------------------------------------------------------------*/
950 FILE *ovrFile = tempfile();
952 addSetHead(&tmpfileSet,ovrFile);
953 /* print the global struct definitions */
955 cdbStructBlock (0,cdbFile);
958 /* PENDING: this isnt the best place but it will do */
959 if (port->general.glue_up_main) {
960 /* create the interrupt vector table */
961 createInterruptVect (vFile);
964 addSetHead(&tmpfileSet,vFile);
966 /* emit code for the all the variables declared */
968 /* do the overlay segments */
969 emitOverlay(ovrFile);
971 /* now put it all together into the assembler file */
972 /* create the assembler file name */
974 if (!options.c1mode) {
975 sprintf (buffer, srcFileName);
976 strcat (buffer, ".asm");
979 strcpy(buffer, options.out_name);
982 if (!(asmFile = fopen (buffer, "w"))) {
983 werror (E_FILE_OPEN_ERR, buffer);
987 /* initial comments */
988 initialComments (asmFile);
990 /* print module name */
991 tfprintf(asmFile, "\t!module\n", moduleName);
992 tfprintf(asmFile, "\t!fileprelude\n");
994 /* Let the port generate any global directives, etc. */
995 if (port->genAssemblerPreamble)
997 port->genAssemblerPreamble(asmFile);
1000 /* print the global variables in this module */
1001 printPublics (asmFile);
1003 /* copy the sfr segment */
1004 fprintf (asmFile, "%s", iComments2);
1005 fprintf (asmFile, "; special function registers\n");
1006 fprintf (asmFile, "%s", iComments2);
1007 copyFile (asmFile, sfr->oFile);
1009 /* copy the sbit segment */
1010 fprintf (asmFile, "%s", iComments2);
1011 fprintf (asmFile, "; special function bits \n");
1012 fprintf (asmFile, "%s", iComments2);
1013 copyFile (asmFile, sfrbit->oFile);
1015 /* copy the data segment */
1016 fprintf (asmFile, "%s", iComments2);
1017 fprintf (asmFile, "; internal ram data\n");
1018 fprintf (asmFile, "%s", iComments2);
1019 copyFile (asmFile, data->oFile);
1022 /* create the overlay segments */
1023 fprintf (asmFile, "%s", iComments2);
1024 fprintf (asmFile, "; overlayable items in internal ram \n");
1025 fprintf (asmFile, "%s", iComments2);
1026 copyFile (asmFile, ovrFile);
1028 /* create the stack segment MOF */
1029 if (mainf && mainf->fbody) {
1030 fprintf (asmFile, "%s", iComments2);
1031 fprintf (asmFile, "; Stack segment in internal ram \n");
1032 fprintf (asmFile, "%s", iComments2);
1033 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1034 "__start__stack:\n\t.ds\t1\n\n");
1037 /* create the idata segment */
1038 fprintf (asmFile, "%s", iComments2);
1039 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1040 fprintf (asmFile, "%s", iComments2);
1041 copyFile (asmFile, idata->oFile);
1043 /* copy the bit segment */
1044 fprintf (asmFile, "%s", iComments2);
1045 fprintf (asmFile, "; bit data\n");
1046 fprintf (asmFile, "%s", iComments2);
1047 copyFile (asmFile, bit->oFile);
1049 /* if external stack then reserve space of it */
1050 if (mainf && mainf->fbody && options.useXstack ) {
1051 fprintf (asmFile, "%s", iComments2);
1052 fprintf (asmFile, "; external stack \n");
1053 fprintf (asmFile, "%s", iComments2);
1054 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1055 fprintf (asmFile,"\t.ds 256\n");
1059 /* copy xtern ram data */
1060 fprintf (asmFile, "%s", iComments2);
1061 fprintf (asmFile, "; external ram data\n");
1062 fprintf (asmFile, "%s", iComments2);
1063 copyFile (asmFile, xdata->oFile);
1065 /* copy the interrupt vector table */
1066 if (mainf && mainf->fbody) {
1067 fprintf (asmFile, "%s", iComments2);
1068 fprintf (asmFile, "; interrupt vector \n");
1069 fprintf (asmFile, "%s", iComments2);
1070 copyFile (asmFile, vFile);
1073 /* copy global & static initialisations */
1074 fprintf (asmFile, "%s", iComments2);
1075 fprintf (asmFile, "; global & static initialisations\n");
1076 fprintf (asmFile, "%s", iComments2);
1078 /* Everywhere we generate a reference to the static_name area,
1079 * (which is currently only here), we immediately follow it with a
1080 * definition of the post_static_name area. This guarantees that
1081 * the post_static_name area will immediately follow the static_name
1084 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1085 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1086 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1088 if (mainf && mainf->fbody) {
1089 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1090 /* if external stack is specified then the
1091 higher order byte of the xdatalocation is
1092 going into P2 and the lower order going into
1094 if (options.useXstack) {
1095 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1096 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1097 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1098 (unsigned int)options.xdata_loc & 0xff);
1101 /* initialise the stack pointer */
1102 /* if the user specified a value then use it */
1103 if (options.stack_loc)
1104 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1106 /* no: we have to compute it */
1107 if (!options.stackOnData && maxRegBank <= 3)
1108 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1110 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1112 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1113 fprintf (asmFile,"\tmov\ta,dpl\n");
1114 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1115 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1116 fprintf (asmFile,"__sdcc_init_data:\n");
1119 copyFile (asmFile, statsg->oFile);
1121 if (port->general.glue_up_main && mainf && mainf->fbody)
1123 /* This code is generated in the post-static area.
1124 * This area is guaranteed to follow the static area
1125 * by the ugly shucking and jiving about 20 lines ago.
1127 tfprintf(asmFile, "\t!area %s\n", port->mem.post_static_name);
1128 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1131 /* copy over code */
1132 fprintf (asmFile, "%s", iComments2);
1133 fprintf (asmFile, "; code\n");
1134 fprintf (asmFile, "%s", iComments2);
1135 tfprintf(asmFile, "\t!area\n", port->mem.code_name);
1136 if (mainf && mainf->fbody) {
1138 /* entry point @ start of CSEG */
1139 fprintf (asmFile,"__sdcc_program_startup:\n");
1141 /* put in the call to main */
1142 fprintf(asmFile,"\tlcall\t_main\n");
1143 if (options.mainreturn) {
1145 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1146 fprintf(asmFile,"\tret\n");
1150 fprintf(asmFile,";\treturn from main will lock up\n");
1151 fprintf(asmFile,"\tsjmp .\n");
1154 copyFile (asmFile, code->oFile);
1157 applyToSet(tmpfileSet,closeTmpFiles);
1158 applyToSet(tmpfileNameSet, rmTmpFiles);
1161 /** Creates a temporary file a'la tmpfile which avoids the bugs
1162 in cygwin wrt c:\tmp.
1163 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1165 FILE *tempfile(void)
1167 const char *tmpdir = NULL;
1169 tmpdir = getenv("TMP");
1170 else if (getenv("TEMP"))
1171 tmpdir = getenv("TEMP");
1172 else if (getenv("TMPDIR"))
1173 tmpdir = getenv("TMPDIR");
1175 char *name = tempnam(tmpdir, "sdcc");
1177 FILE *fp = fopen(name, "w+b");
1179 addSetHead(&tmpfileNameSet, name);