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 // This is a bit messy because we define link ourself
35 // No unistd.h in Borland C++
38 symbol *interrupts[256];
40 void printIval (symbol *, link *, initList *, FILE *);
41 set *publics = NULL; /* public variables */
42 set *externs = NULL; /* Varibles that are declared as extern */
44 /* TODO: this should be configurable (DS803C90 uses more than 6) */
45 int maxInterrupts = 6;
48 extern char *VersionString;
49 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
50 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
52 /*-----------------------------------------------------------------*/
53 /* closeTmpFiles - closes all tmp files created by the compiler */
54 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
55 /*-----------------------------------------------------------------*/
56 DEFSETFUNC(closeTmpFiles)
66 /*-----------------------------------------------------------------*/
67 /* rmTmpFiles - closes all tmp files created by the compiler */
68 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
69 /*-----------------------------------------------------------------*/
70 DEFSETFUNC(rmTmpFiles)
81 /*-----------------------------------------------------------------*/
82 /* copyFile - copies source file to destination file */
83 /*-----------------------------------------------------------------*/
84 void copyFile (FILE * dest, FILE * src)
90 if ((ch = fgetc (src)) != EOF)
94 char *aopLiteralLong(value *val, int offset, int size)
102 /* if it is a float then it gets tricky */
103 /* otherwise it is fairly simple */
104 if (!IS_FLOAT(val->type)) {
105 unsigned long v = floatFromVal(val);
110 tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
113 tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
116 /* Hmm. Too big for now. */
119 ALLOC_ATOMIC(rs,strlen(buffer)+1);
120 return strcpy (rs,buffer);
123 /* PENDING: For now size must be 1 */
126 /* it is type float */
127 fl.f = (float) floatFromVal(val);
129 tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
131 tsprintf(buffer, "!immedbyte", fl.c[offset]);
133 ALLOC_ATOMIC(rs,strlen(buffer)+1);
134 return strcpy (rs,buffer);
137 /*-----------------------------------------------------------------*/
138 /* aopLiteral - string from a literal value */
139 /*-----------------------------------------------------------------*/
140 char *aopLiteral (value *val, int offset)
142 return aopLiteralLong(val, offset, 1);
145 /*-----------------------------------------------------------------*/
146 /* emitRegularMap - emit code for maps with no special cases */
147 /*-----------------------------------------------------------------*/
148 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
153 /* PENDING: special case here - should remove */
154 if (!strcmp(map->sname, CODE_NAME))
155 tfprintf(map->oFile, "\t!areacode\n", map->sname);
156 else if (!strcmp(map->sname, DATA_NAME))
157 tfprintf(map->oFile, "\t!areadata\n", map->sname);
158 else if (!strcmp(map->sname, HOME_NAME))
159 tfprintf(map->oFile, "\t!areahome\n", map->sname);
161 tfprintf(map->oFile, "\t!area\n", map->sname);
164 /* print the area name */
165 for (sym = setFirstItem (map->syms); sym;
166 sym = setNextItem (map->syms)) {
168 /* if extern then add it into the extern list */
169 if (IS_EXTERN (sym->etype)) {
170 addSetHead (&externs, sym);
174 /* if allocation required check is needed
175 then check if the symbol really requires
176 allocation only for local variables */
177 if (arFlag && !IS_AGGREGATE(sym->type) &&
178 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
179 !sym->allocreq && sym->level)
182 /* if global variable & not static or extern
183 and addPublics allowed then add it to the public set */
184 if ((sym->level == 0 ||
185 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
187 !IS_STATIC (sym->etype) &&
188 (sym->used || sym->fbody)) {
189 addSetHead (&publics, sym);
192 /* if extern then do nothing or is a function
194 if (IS_FUNC (sym->type))
197 /* print extra debug info if required */
198 if ((options.debug || sym->level == 0) && !options.nodebug) {
200 cdbSymbol(sym,cdbFile,FALSE,FALSE);
202 if (!sym->level) /* global */
203 if (IS_STATIC(sym->etype))
204 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
206 fprintf(map->oFile,"G$"); /* scope is global */
208 /* symbol is local */
209 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
210 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
213 /* if is has an absolute address then generate
214 an equate for this no need to allocate space */
215 if (SPEC_ABSA (sym->etype)) {
216 if ((options.debug || sym->level == 0) && !options.nodebug)
217 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
219 fprintf (map->oFile, "%s\t=\t0x%04x\n",
221 SPEC_ADDR (sym->etype));
225 if ((options.debug || sym->level == 0) && !options.nodebug)
226 fprintf(map->oFile,"==.\n");
227 if (IS_STATIC(sym->etype))
228 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
230 tfprintf(map->oFile, "!labeldef\n", sym->rname);
231 tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
234 /* if it has an initial value then do it only if
235 it is a global variable */
236 if (sym->ival && sym->level == 0) {
239 if (IS_AGGREGATE (sym->type))
240 ival = initAggregates (sym, sym->ival, NULL);
242 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
243 decorateType (resolveSymbols (list2expr (sym->ival))));
244 codeOutFile = statsg->oFile;
246 eBBlockFromiCode (iCodeFromAst (ival));
253 /*-----------------------------------------------------------------*/
254 /* initPointer - pointer initialization code massaging */
255 /*-----------------------------------------------------------------*/
256 value *initPointer (initList *ilist)
259 ast *expr = list2expr(ilist);
264 /* try it the oldway first */
265 if ((val = constExprValue(expr,FALSE)))
268 /* no then we have to do these cludgy checks */
269 /* pointers can be initialized with address of
270 a variable or address of an array element */
271 if (IS_AST_OP(expr) && expr->opval.op == '&') {
272 /* address of symbol */
273 if (IS_AST_SYM_VALUE(expr->left)) {
274 val = copyValue(AST_VALUE(expr->left));
275 val->type = newLink();
276 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
277 DCL_TYPE(val->type) = CPOINTER ;
278 DCL_PTR_CONST(val->type) = port->mem.code_ro;
281 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
282 DCL_TYPE(val->type) = FPOINTER;
284 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
285 DCL_TYPE(val->type) = PPOINTER ;
287 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
288 DCL_TYPE(val->type) = IPOINTER ;
290 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
291 DCL_TYPE(val->type) = EEPPOINTER ;
293 DCL_TYPE(val->type) = POINTER ;
294 val->type->next = expr->left->ftype;
295 val->etype = getSpec(val->type);
299 /* if address of indexed array */
300 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
301 return valForArray(expr->left);
303 /* if address of structure element then
305 if (IS_AST_OP(expr->left) &&
306 expr->left->opval.op == '.' ) {
307 return valForStructElem(expr->left->left,
312 (&some_struct)->element */
313 if (IS_AST_OP(expr->left) &&
314 expr->left->opval.op == PTR_OP &&
315 IS_ADDRESS_OF_OP(expr->left->left))
316 return valForStructElem(expr->left->left->left,
320 /* case 3. (((char *) &a) +/- constant) */
321 if (IS_AST_OP(expr) &&
322 (expr->opval.op == '+' || expr->opval.op == '-') &&
323 IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
324 IS_AST_OP(expr->left->right) &&
325 expr->left->right->opval.op == '&' &&
326 IS_AST_LIT_VALUE(expr->right)) {
328 return valForCastAggr(expr->left->right->left,
329 expr->left->left->opval.lnk,
330 expr->right,expr->opval.op);
335 werror(E_INIT_WRONG);
340 /*-----------------------------------------------------------------*/
341 /* printChar - formats and prints a characater string with DB */
342 /*-----------------------------------------------------------------*/
343 void printChar (FILE * ofile, char *s, int plen)
346 int len = strlen (s);
351 while (len && pplen < plen) {
353 while (i && *s && pplen < plen) {
354 if (*s < ' ' || *s == '\"') {
357 tfprintf(ofile, "\t!ascii\n", buf);
358 tfprintf(ofile, "\t!db !constbyte\n", *s);
371 tfprintf(ofile, "\t!ascii\n", buf);
380 tfprintf(ofile, "\t!db !constbyte\n", 0);
383 /*-----------------------------------------------------------------*/
384 /* return the generic pointer high byte for a given pointer type. */
385 /*-----------------------------------------------------------------*/
386 int pointerTypeToGPByte(const int p_type)
394 /* hack - if we get a generic pointer, we just assume
395 * it's an FPOINTER (i.e. in XDATA space).
404 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
412 /*-----------------------------------------------------------------*/
413 /* printPointerType - generates ival for pointer type */
414 /*-----------------------------------------------------------------*/
415 void _printPointerType(FILE *oFile, const char *name)
419 fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
423 fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
427 /*-----------------------------------------------------------------*/
428 /* printPointerType - generates ival for pointer type */
429 /*-----------------------------------------------------------------*/
430 void printPointerType(FILE *oFile, const char *name)
432 _printPointerType(oFile, name);
433 fprintf(oFile, "\n");
436 /*-----------------------------------------------------------------*/
437 /* printGPointerType - generates ival for generic pointer type */
438 /*-----------------------------------------------------------------*/
439 void printGPointerType(FILE *oFile, const char *name,
440 const unsigned int type)
442 _printPointerType(oFile,name);
443 fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type));
446 /*-----------------------------------------------------------------*/
447 /* printIvalType - generates ival for int/char */
448 /*-----------------------------------------------------------------*/
449 void printIvalType (link * type, initList * ilist, FILE * oFile)
453 /* if initList is deep */
454 if (ilist->type == INIT_DEEP)
455 ilist = ilist->init.deep;
457 val = list2val (ilist);
458 switch (getSize (type)) {
461 tfprintf(oFile, "\t!db !constbyte\n", 0);
463 tfprintf(oFile, "\t!dbs\n",
464 aopLiteral (val, 0));
468 if (port->use_dw_for_init)
469 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
471 fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
475 tfprintf (oFile, "\t!dw !constword\n", 0);
476 tfprintf (oFile, "\t!dw !constword\n", 0);
479 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
480 aopLiteral (val, 0), aopLiteral (val, 1),
481 aopLiteral (val, 2), aopLiteral (val, 3));
487 /*-----------------------------------------------------------------*/
488 /* printIvalStruct - generates initial value for structures */
489 /*-----------------------------------------------------------------*/
490 void printIvalStruct (symbol * sym,link * type,
491 initList * ilist, FILE * oFile)
496 sflds = SPEC_STRUCT (type)->fields;
497 if (ilist->type != INIT_DEEP) {
498 werror (E_INIT_STRUCT, sym->name);
502 iloop = ilist->init.deep;
504 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
505 printIval (sflds, sflds->type, iloop, oFile);
510 /*-----------------------------------------------------------------*/
511 /* printIvalChar - generates initital value for character array */
512 /*-----------------------------------------------------------------*/
513 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
520 val = list2val (ilist);
521 /* if the value is a character string */
522 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
523 if (!DCL_ELEM (type))
524 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
526 /* if size mismatch */
527 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
528 /* werror (E_ARRAY_BOUND); */
530 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
532 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
534 tfprintf (oFile, "\t!db !constbyte\n", 0);
542 printChar (oFile, s,strlen(s)+1);
546 /*-----------------------------------------------------------------*/
547 /* printIvalArray - generates code for array initialization */
548 /*-----------------------------------------------------------------*/
549 void printIvalArray (symbol * sym, link * type, initList * ilist,
553 int lcnt = 0, size = 0;
555 /* take care of the special case */
556 /* array of characters can be init */
558 if (IS_CHAR (type->next))
559 if (printIvalChar (type,
560 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
561 oFile, SPEC_CVAL (sym->etype).v_char))
564 /* not the special case */
565 if (ilist->type != INIT_DEEP) {
566 werror (E_INIT_STRUCT, sym->name);
570 iloop = ilist->init.deep;
571 lcnt = DCL_ELEM (type);
575 printIval (sym, type->next, iloop, oFile);
576 iloop = (iloop ? iloop->next : NULL);
579 /* if not array limits given & we */
580 /* are out of initialisers then */
581 if (!DCL_ELEM (type) && !iloop)
584 /* no of elements given and we */
585 /* have generated for all of them */
590 /* if we have not been given a size */
591 if (!DCL_ELEM (type))
592 DCL_ELEM (type) = size;
597 /*-----------------------------------------------------------------*/
598 /* printIvalFuncPtr - generate initial value for function pointers */
599 /*-----------------------------------------------------------------*/
600 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
605 val = list2val (ilist);
606 /* check the types */
607 if ((dLvl = checkType (val->type, type->next)) <= 0) {
608 tfprintf(oFile, "\t!dw !constword\n", 0);
612 /* now generate the name */
614 if (port->use_dw_for_init)
616 tfprintf(oFile, "\t!dws\n", val->name);
620 printPointerType(oFile, val->name);
624 if (port->use_dw_for_init)
626 tfprintf(oFile, "\t!dws\n", val->sym->rname);
630 printPointerType(oFile, val->sym->rname);
636 /*-----------------------------------------------------------------*/
637 /* printIvalCharPtr - generates initial values for character pointers */
638 /*-----------------------------------------------------------------*/
639 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
643 /* PENDING: this is _very_ mcs51 specific, including a magic
645 It's also endin specific.
647 size = getSize (type);
649 if (val->name && strlen(val->name)) {
650 if (size == 1) /* This appears to be Z80 specific?? */
653 "\t!dbs\n", val->name);
655 else if (size == FPTRSIZE)
657 if (port->use_dw_for_init)
659 tfprintf(oFile, "\t!dws\n", val->name);
663 printPointerType(oFile, val->name);
666 else if (size == GPTRSIZE)
668 /* PENDING: 0x02 or 0x%02x, CDATA? */
669 printGPointerType(oFile, val->name,
670 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
671 PTR_TYPE(SPEC_OCLS(val->etype))));
675 fprintf(stderr, "*** internal error: unknown size in "
676 "printIvalCharPtr.\n");
680 /* What is this case? Are these pointers? */
683 tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
686 if (port->use_dw_for_init)
687 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
689 tfprintf(oFile, "\t.byte %s,%s\n",
690 aopLiteral(val, 0),aopLiteral(val, 1));
693 /* PENDING: 0x02 or 0x%02x, CDATA? */
694 fprintf(oFile, "\t.byte %s,%s,#0x02\n",
695 aopLiteral (val, 0), aopLiteral (val, 1));
703 if (val->sym && val->sym->isstrlit)
704 addSet (&statsg->syms, val->sym);
709 /*-----------------------------------------------------------------*/
710 /* printIvalPtr - generates initial value for pointers */
711 /*-----------------------------------------------------------------*/
712 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
718 if (ilist->type == INIT_DEEP)
719 ilist = ilist->init.deep;
721 /* function pointer */
722 if (IS_FUNC (type->next)) {
723 printIvalFuncPtr (type, ilist, oFile);
727 if (!(val = initPointer (ilist)))
730 /* if character pointer */
731 if (IS_CHAR (type->next))
732 if (printIvalCharPtr (sym, type, val, oFile))
736 if (checkType (type, val->type) != 1)
737 werror (E_INIT_WRONG);
739 /* if val is literal */
740 if (IS_LITERAL (val->etype)) {
741 switch (getSize (type)) {
743 tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
746 if (port->use_dw_for_init)
747 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
749 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
752 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
753 aopLiteral (val, 0), aopLiteral (val, 1));
759 size = getSize (type);
761 if (size == 1) /* Z80 specific?? */
763 tfprintf (oFile, "\t!dbs\n", val->name);
765 else if (size == FPTRSIZE)
767 tfprintf (oFile, "\t!dws\n", val->name);
769 else if (size == GPTRSIZE)
771 printGPointerType(oFile, val->name,
772 (IS_PTR(val->type) ? DCL_TYPE(val->type) :
773 PTR_TYPE(SPEC_OCLS(val->etype))));
778 /*-----------------------------------------------------------------*/
779 /* printIval - generates code for initial value */
780 /*-----------------------------------------------------------------*/
781 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
786 /* if structure then */
787 if (IS_STRUCT (type)) {
788 printIvalStruct (sym, type, ilist, oFile);
792 /* if this is a pointer */
794 printIvalPtr (sym, type, ilist, oFile);
798 /* if this is an array */
799 if (IS_ARRAY (type)) {
800 printIvalArray (sym, type, ilist, oFile);
804 /* if type is SPECIFIER */
805 if (IS_SPEC (type)) {
806 printIvalType (type, ilist, oFile);
811 /*-----------------------------------------------------------------*/
812 /* emitStaticSeg - emitcode for the static segment */
813 /*-----------------------------------------------------------------*/
814 void emitStaticSeg(memmap * map, FILE *out)
818 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
822 /* for all variables in this segment do */
823 for (sym = setFirstItem (map->syms); sym;
824 sym = setNextItem (map->syms)) {
826 /* if it is "extern" then do nothing */
827 if (IS_EXTERN (sym->etype))
830 /* if it is not static add it to the public
832 if (!IS_STATIC (sym->etype))
833 addSetHead (&publics, sym);
835 /* print extra debug info if required */
836 if ((options.debug || sym->level == 0) && !options.nodebug) {
838 cdbSymbol(sym,cdbFile,FALSE,FALSE);
840 if (!sym->level) { /* global */
841 if (IS_STATIC(sym->etype))
842 fprintf(out,"F%s$",moduleName); /* scope is file */
844 fprintf(out,"G$"); /* scope is global */
847 /* symbol is local */
849 (sym->localof ? sym->localof->name : "-null-"));
850 fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
853 /* if it has an absolute address */
854 if (SPEC_ABSA (sym->etype)) {
855 if ((options.debug || sym->level == 0) && !options.nodebug)
856 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
858 fprintf (out, "%s\t=\t0x%04x\n",
860 SPEC_ADDR (sym->etype));
863 if ((options.debug || sym->level == 0) && !options.nodebug)
864 fprintf(out," == .\n");
866 /* if it has an initial value */
868 fprintf (out, "%s:\n", sym->rname);
870 resolveIvalSym (sym->ival);
871 printIval (sym, sym->type, sym->ival, out);
876 fprintf (out, "%s:\n", sym->rname);
877 /* special case for character strings */
878 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
879 SPEC_CVAL (sym->etype).v_char)
881 SPEC_CVAL (sym->etype).v_char,
882 strlen(SPEC_CVAL (sym->etype).v_char)+1);
884 tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
890 /*-----------------------------------------------------------------*/
891 /* emitMaps - emits the code for the data portion the code */
892 /*-----------------------------------------------------------------*/
895 /* no special considerations for the following
896 data, idata & bit & xdata */
897 emitRegularMap (data, TRUE, TRUE);
898 emitRegularMap (idata, TRUE,TRUE);
899 emitRegularMap (bit, TRUE,FALSE);
900 emitRegularMap (xdata, TRUE,TRUE);
901 emitRegularMap (sfr, FALSE,FALSE);
902 emitRegularMap (sfrbit, FALSE,FALSE);
903 emitRegularMap (home, TRUE,FALSE);
904 emitRegularMap (code, TRUE,FALSE);
906 emitStaticSeg (statsg, code->oFile);
909 /*-----------------------------------------------------------------*/
910 /* flushStatics - flush all currently defined statics out to file */
911 /* and delete. Temporary function */
912 /*-----------------------------------------------------------------*/
913 void flushStatics(void)
915 emitStaticSeg(statsg, codeOutFile);
919 /*-----------------------------------------------------------------*/
920 /* createInterruptVect - creates the interrupt vector */
921 /*-----------------------------------------------------------------*/
922 void createInterruptVect (FILE * vFile)
925 mainf = newSymbol ("main", 0);
928 /* only if the main function exists */
929 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
930 if (!options.cc_only)
935 /* if the main is only a prototype ie. no body then do nothing */
937 /* if ! compile only then main function should be present */
938 if (!options.cc_only)
943 tfprintf(vFile, "\t!areacode\n", CODE_NAME);
944 fprintf (vFile, "__interrupt_vect:\n");
947 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
949 /* "generic" interrupt table header (if port doesn't specify one).
951 * Look suspiciously like 8051 code to me...
954 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
957 /* now for the other interrupts */
958 for (; i < maxInterrupts; i++) {
960 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
962 fprintf (vFile, "\treti\n\t.ds\t7\n");
969 ";--------------------------------------------------------\n"
970 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
974 ";--------------------------------------------------------\n"};
977 /*-----------------------------------------------------------------*/
978 /* initialComments - puts in some initial comments */
979 /*-----------------------------------------------------------------*/
980 void initialComments (FILE * afile)
984 fprintf (afile, "%s", iComments1);
985 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
986 fprintf (afile, "%s", iComments2);
989 /*-----------------------------------------------------------------*/
990 /* printPublics - generates .global for publics */
991 /*-----------------------------------------------------------------*/
992 void printPublics (FILE * afile)
996 fprintf (afile, "%s", iComments2);
997 fprintf (afile, "; Public variables in this module\n");
998 fprintf (afile, "%s", iComments2);
1000 for (sym = setFirstItem (publics); sym;
1001 sym = setNextItem (publics))
1002 tfprintf(afile, "\t!global\n", sym->rname);
1005 /*-----------------------------------------------------------------*/
1006 /* printExterns - generates .global for externs */
1007 /*-----------------------------------------------------------------*/
1008 void printExterns (FILE * afile)
1012 fprintf (afile, "%s", iComments2);
1013 fprintf (afile, "; Externals used\n");
1014 fprintf (afile, "%s", iComments2);
1016 for (sym = setFirstItem (externs); sym;
1017 sym = setNextItem (externs))
1018 tfprintf(afile, "\t!global\n", sym->rname);
1021 /*-----------------------------------------------------------------*/
1022 /* emitOverlay - will emit code for the overlay stuff */
1023 /*-----------------------------------------------------------------*/
1024 static void emitOverlay(FILE *afile)
1028 if (!elementsInSet(ovrSetSets))
1029 tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1031 /* for each of the sets in the overlay segment do */
1032 for (ovrset = setFirstItem(ovrSetSets); ovrset;
1033 ovrset = setNextItem(ovrSetSets)) {
1037 if (elementsInSet(ovrset)) {
1038 /* this dummy area is used to fool the assembler
1039 otherwise the assembler will append each of these
1040 declarations into one chunk and will not overlay
1042 fprintf(afile,"\t.area _DUMMY\n");
1043 /* output the area informtion */
1044 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1047 for (sym = setFirstItem(ovrset); sym;
1048 sym = setNextItem(ovrset)) {
1050 /* if extern then add it to the publics tabledo nothing */
1051 if (IS_EXTERN (sym->etype))
1054 /* if allocation required check is needed
1055 then check if the symbol really requires
1056 allocation only for local variables */
1057 if (!IS_AGGREGATE(sym->type) &&
1058 !(sym->_isparm && !IS_REGPARM(sym->etype))
1059 && !sym->allocreq && sym->level)
1062 /* if global variable & not static or extern
1063 and addPublics allowed then add it to the public set */
1064 if ((sym->_isparm && !IS_REGPARM(sym->etype))
1065 && !IS_STATIC (sym->etype))
1066 addSetHead (&publics, sym);
1068 /* if extern then do nothing or is a function
1070 if (IS_FUNC (sym->type))
1073 /* print extra debug info if required */
1074 if ((options.debug || sym->level == 0) && !options.nodebug) {
1076 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1078 if (!sym->level) { /* global */
1079 if (IS_STATIC(sym->etype))
1080 fprintf(afile,"F%s$",moduleName); /* scope is file */
1082 fprintf(afile,"G$"); /* scope is global */
1085 /* symbol is local */
1086 fprintf(afile,"L%s$",
1087 (sym->localof ? sym->localof->name : "-null-"));
1088 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1091 /* if is has an absolute address then generate
1092 an equate for this no need to allocate space */
1093 if (SPEC_ABSA (sym->etype)) {
1095 if ((options.debug || sym->level == 0) && !options.nodebug)
1096 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
1098 fprintf (afile, "%s\t=\t0x%04x\n",
1100 SPEC_ADDR (sym->etype));
1103 if ((options.debug || sym->level == 0) && !options.nodebug)
1104 fprintf(afile,"==.\n");
1106 /* allocate space */
1107 tfprintf(afile, "!labeldef\n", sym->rname);
1108 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1115 /*-----------------------------------------------------------------*/
1116 /* glue - the final glue that hold the whole thing together */
1117 /*-----------------------------------------------------------------*/
1122 FILE *ovrFile = tempfile();
1124 addSetHead(&tmpfileSet,ovrFile);
1125 /* print the global struct definitions */
1126 if (options.debug && !options.nodebug)
1127 cdbStructBlock (0,cdbFile);
1130 /* PENDING: this isnt the best place but it will do */
1131 if (port->general.glue_up_main) {
1132 /* create the interrupt vector table */
1133 createInterruptVect (vFile);
1136 addSetHead(&tmpfileSet,vFile);
1138 /* emit code for the all the variables declared */
1140 /* do the overlay segments */
1141 emitOverlay(ovrFile);
1143 /* now put it all together into the assembler file */
1144 /* create the assembler file name */
1146 if (!options.c1mode) {
1147 sprintf (buffer, srcFileName);
1148 strcat (buffer, ".asm");
1151 strcpy(buffer, options.out_name);
1154 if (!(asmFile = fopen (buffer, "w"))) {
1155 werror (E_FILE_OPEN_ERR, buffer);
1159 /* initial comments */
1160 initialComments (asmFile);
1162 /* print module name */
1163 tfprintf(asmFile, "\t!module\n", moduleName);
1164 tfprintf(asmFile, "\t!fileprelude\n");
1166 /* Let the port generate any global directives, etc. */
1167 if (port->genAssemblerPreamble)
1169 port->genAssemblerPreamble(asmFile);
1172 /* print the global variables in this module */
1173 printPublics (asmFile);
1174 if (port->assembler.externGlobal)
1175 printExterns (asmFile);
1177 /* copy the sfr segment */
1178 fprintf (asmFile, "%s", iComments2);
1179 fprintf (asmFile, "; special function registers\n");
1180 fprintf (asmFile, "%s", iComments2);
1181 copyFile (asmFile, sfr->oFile);
1183 /* copy the sbit segment */
1184 fprintf (asmFile, "%s", iComments2);
1185 fprintf (asmFile, "; special function bits \n");
1186 fprintf (asmFile, "%s", iComments2);
1187 copyFile (asmFile, sfrbit->oFile);
1189 /* copy the data segment */
1190 fprintf (asmFile, "%s", iComments2);
1191 fprintf (asmFile, "; internal ram data\n");
1192 fprintf (asmFile, "%s", iComments2);
1193 copyFile (asmFile, data->oFile);
1196 /* create the overlay segments */
1197 fprintf (asmFile, "%s", iComments2);
1198 fprintf (asmFile, "; overlayable items in internal ram \n");
1199 fprintf (asmFile, "%s", iComments2);
1200 copyFile (asmFile, ovrFile);
1202 /* create the stack segment MOF */
1203 if (mainf && mainf->fbody) {
1204 fprintf (asmFile, "%s", iComments2);
1205 fprintf (asmFile, "; Stack segment in internal ram \n");
1206 fprintf (asmFile, "%s", iComments2);
1207 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1208 "__start__stack:\n\t.ds\t1\n\n");
1211 /* create the idata segment */
1212 fprintf (asmFile, "%s", iComments2);
1213 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1214 fprintf (asmFile, "%s", iComments2);
1215 copyFile (asmFile, idata->oFile);
1217 /* copy the bit segment */
1218 fprintf (asmFile, "%s", iComments2);
1219 fprintf (asmFile, "; bit data\n");
1220 fprintf (asmFile, "%s", iComments2);
1221 copyFile (asmFile, bit->oFile);
1223 /* if external stack then reserve space of it */
1224 if (mainf && mainf->fbody && options.useXstack ) {
1225 fprintf (asmFile, "%s", iComments2);
1226 fprintf (asmFile, "; external stack \n");
1227 fprintf (asmFile, "%s", iComments2);
1228 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1229 fprintf (asmFile,"\t.ds 256\n");
1233 /* copy xtern ram data */
1234 fprintf (asmFile, "%s", iComments2);
1235 fprintf (asmFile, "; external ram data\n");
1236 fprintf (asmFile, "%s", iComments2);
1237 copyFile (asmFile, xdata->oFile);
1239 /* copy the interrupt vector table */
1240 if (mainf && mainf->fbody) {
1241 fprintf (asmFile, "%s", iComments2);
1242 fprintf (asmFile, "; interrupt vector \n");
1243 fprintf (asmFile, "%s", iComments2);
1244 copyFile (asmFile, vFile);
1247 /* copy global & static initialisations */
1248 fprintf (asmFile, "%s", iComments2);
1249 fprintf (asmFile, "; global & static initialisations\n");
1250 fprintf (asmFile, "%s", iComments2);
1252 /* Everywhere we generate a reference to the static_name area,
1253 * (which is currently only here), we immediately follow it with a
1254 * definition of the post_static_name area. This guarantees that
1255 * the post_static_name area will immediately follow the static_name
1258 tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1259 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1260 tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1262 if (mainf && mainf->fbody) {
1263 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1264 /* if external stack is specified then the
1265 higher order byte of the xdatalocation is
1266 going into P2 and the lower order going into
1268 if (options.useXstack) {
1269 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1270 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1271 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1272 (unsigned int)options.xdata_loc & 0xff);
1275 /* initialise the stack pointer */
1276 /* if the user specified a value then use it */
1277 if (options.stack_loc)
1278 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1280 /* no: we have to compute it */
1281 if (!options.stackOnData && maxRegBank <= 3)
1282 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1284 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1286 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1287 fprintf (asmFile,"\tmov\ta,dpl\n");
1288 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1289 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1290 fprintf (asmFile,"__sdcc_init_data:\n");
1293 copyFile (asmFile, statsg->oFile);
1295 if (port->general.glue_up_main && mainf && mainf->fbody)
1297 /* This code is generated in the post-static area.
1298 * This area is guaranteed to follow the static area
1299 * by the ugly shucking and jiving about 20 lines ago.
1301 tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1302 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1308 "%s", iComments2, iComments2);
1309 tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1310 copyFile (asmFile, home->oFile);
1312 /* copy over code */
1313 fprintf (asmFile, "%s", iComments2);
1314 fprintf (asmFile, "; code\n");
1315 fprintf (asmFile, "%s", iComments2);
1316 tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1317 if (mainf && mainf->fbody) {
1319 /* entry point @ start of CSEG */
1320 fprintf (asmFile,"__sdcc_program_startup:\n");
1322 /* put in the call to main */
1323 fprintf(asmFile,"\tlcall\t_main\n");
1324 if (options.mainreturn) {
1326 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1327 fprintf(asmFile,"\tret\n");
1331 fprintf(asmFile,";\treturn from main will lock up\n");
1332 fprintf(asmFile,"\tsjmp .\n");
1335 copyFile (asmFile, code->oFile);
1338 applyToSet(tmpfileSet,closeTmpFiles);
1339 applyToSet(tmpfileNameSet, rmTmpFiles);
1342 /** Creates a temporary file a'la tmpfile which avoids the bugs
1343 in cygwin wrt c:\tmp.
1344 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1346 FILE *tempfile(void)
1348 const char *tmpdir = NULL;
1350 tmpdir = getenv("TMP");
1351 else if (getenv("TEMP"))
1352 tmpdir = getenv("TEMP");
1353 else if (getenv("TMPDIR"))
1354 tmpdir = getenv("TMPDIR");
1356 char *name = tempnam(tmpdir, "sdcc");
1358 FILE *fp = fopen(name, "w+b");
1361 addSetHead(&tmpfileNameSet, name);
1370 char *gc_strdup(const char *s)
1373 ALLOC_ATOMIC(ret, strlen(s)+1);