1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
30 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
31 #if 0 /* This should no longer be necessary. */
32 // This is a bit messy because we define link ourself
41 // No unistd.h in Borland C++
44 symbol *interrupts[256];
46 void printIval (symbol *, sym_link *, initList *, FILE *);
47 set *publics = NULL; /* public variables */
48 set *externs = NULL; /* Varibles that are declared as extern */
50 /* TODO: this should be configurable (DS803C90 uses more than 6) */
51 int maxInterrupts = 6;
54 extern char *VersionString;
55 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
56 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
58 /*-----------------------------------------------------------------*/
59 /* closeTmpFiles - closes all tmp files created by the compiler */
60 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
61 /*-----------------------------------------------------------------*/
62 DEFSETFUNC (closeTmpFiles)
72 /*-----------------------------------------------------------------*/
73 /* rmTmpFiles - closes all tmp files created by the compiler */
74 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
75 /*-----------------------------------------------------------------*/
76 DEFSETFUNC (rmTmpFiles)
88 /*-----------------------------------------------------------------*/
89 /* copyFile - copies source file to destination file */
90 /*-----------------------------------------------------------------*/
92 copyFile (FILE * dest, FILE * src)
98 if ((ch = fgetc (src)) != EOF)
103 aopLiteralLong (value * val, int offset, int size)
112 /* if it is a float then it gets tricky */
113 /* otherwise it is fairly simple */
114 if (!IS_FLOAT (val->type)) {
115 unsigned long v = floatFromVal (val);
120 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
123 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
126 /* Hmm. Too big for now. */
129 rs = Safe_calloc (1, strlen (buffer) + 1);
130 return strcpy (rs, buffer);
133 /* PENDING: For now size must be 1 */
136 /* it is type float */
137 fl.f = (float) floatFromVal (val);
139 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
141 tsprintf (buffer, "!immedbyte", fl.c[offset]);
143 rs = Safe_calloc (1, strlen (buffer) + 1);
144 return strcpy (rs, buffer);
147 /*-----------------------------------------------------------------*/
148 /* aopLiteral - string from a literal value */
149 /*-----------------------------------------------------------------*/
151 aopLiteral (value * val, int offset)
153 return aopLiteralLong (val, offset, 1);
156 /*-----------------------------------------------------------------*/
157 /* emitRegularMap - emit code for maps with no special cases */
158 /*-----------------------------------------------------------------*/
160 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
166 /* PENDING: special case here - should remove */
167 if (!strcmp (map->sname, CODE_NAME))
168 tfprintf (map->oFile, "\t!areacode\n", map->sname);
169 else if (!strcmp (map->sname, DATA_NAME))
170 tfprintf (map->oFile, "\t!areadata\n", map->sname);
171 else if (!strcmp (map->sname, HOME_NAME))
172 tfprintf (map->oFile, "\t!areahome\n", map->sname);
174 tfprintf (map->oFile, "\t!area\n", map->sname);
177 /* print the area name */
178 for (sym = setFirstItem (map->syms); sym;
179 sym = setNextItem (map->syms))
182 /* if extern then add it into the extern list */
183 if (IS_EXTERN (sym->etype))
185 addSetHead (&externs, sym);
189 /* if allocation required check is needed
190 then check if the symbol really requires
191 allocation only for local variables */
192 if (arFlag && !IS_AGGREGATE (sym->type) &&
193 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
194 !sym->allocreq && sym->level)
197 /* if global variable & not static or extern
198 and addPublics allowed then add it to the public set */
199 if ((sym->level == 0 ||
200 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
202 !IS_STATIC (sym->etype) &&
203 (sym->used || sym->fbody))
205 addSetHead (&publics, sym);
208 /* if extern then do nothing or is a function
210 if (IS_FUNC (sym->type))
213 /* print extra debug info if required */
214 if ((options.debug || sym->level == 0) && !options.nodebug)
217 cdbSymbol (sym, cdbFile, FALSE, FALSE);
219 if (!sym->level) /* global */
220 if (IS_STATIC (sym->etype))
221 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
223 fprintf (map->oFile, "G$"); /* scope is global */
225 /* symbol is local */
226 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
227 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
230 /* if is has an absolute address then generate
231 an equate for this no need to allocate space */
232 if (SPEC_ABSA (sym->etype))
234 if ((options.debug || sym->level == 0) && !options.nodebug)
235 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
237 fprintf (map->oFile, "%s\t=\t0x%04x\n",
239 SPEC_ADDR (sym->etype));
244 if ((options.debug || sym->level == 0) && !options.nodebug)
245 fprintf (map->oFile, "==.\n");
246 if (IS_STATIC (sym->etype))
247 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
249 tfprintf (map->oFile, "!labeldef\n", sym->rname);
250 tfprintf (map->oFile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
253 /* if it has an initial value then do it only if
254 it is a global variable */
255 if (sym->ival && sym->level == 0)
259 if (IS_AGGREGATE (sym->type))
260 ival = initAggregates (sym, sym->ival, NULL);
262 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
263 decorateType (resolveSymbols (list2expr (sym->ival))));
264 codeOutFile = statsg->oFile;
266 eBBlockFromiCode (iCodeFromAst (ival));
273 /*-----------------------------------------------------------------*/
274 /* initPointer - pointer initialization code massaging */
275 /*-----------------------------------------------------------------*/
277 initPointer (initList * ilist)
280 ast *expr = list2expr (ilist);
285 /* try it the oldway first */
286 if ((val = constExprValue (expr, FALSE)))
289 /* no then we have to do these cludgy checks */
290 /* pointers can be initialized with address of
291 a variable or address of an array element */
292 if (IS_AST_OP (expr) && expr->opval.op == '&')
294 /* address of symbol */
295 if (IS_AST_SYM_VALUE (expr->left))
297 val = copyValue (AST_VALUE (expr->left));
298 val->type = newLink ();
299 if (SPEC_SCLS (expr->left->etype) == S_CODE)
301 DCL_TYPE (val->type) = CPOINTER;
302 DCL_PTR_CONST (val->type) = port->mem.code_ro;
304 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
305 DCL_TYPE (val->type) = FPOINTER;
306 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
307 DCL_TYPE (val->type) = PPOINTER;
308 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
309 DCL_TYPE (val->type) = IPOINTER;
310 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
311 DCL_TYPE (val->type) = EEPPOINTER;
313 DCL_TYPE (val->type) = POINTER;
314 val->type->next = expr->left->ftype;
315 val->etype = getSpec (val->type);
319 /* if address of indexed array */
320 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
321 return valForArray (expr->left);
323 /* if address of structure element then
325 if (IS_AST_OP (expr->left) &&
326 expr->left->opval.op == '.')
328 return valForStructElem (expr->left->left,
333 (&some_struct)->element */
334 if (IS_AST_OP (expr->left) &&
335 expr->left->opval.op == PTR_OP &&
336 IS_ADDRESS_OF_OP (expr->left->left))
337 return valForStructElem (expr->left->left->left,
341 /* case 3. (((char *) &a) +/- constant) */
342 if (IS_AST_OP (expr) &&
343 (expr->opval.op == '+' || expr->opval.op == '-') &&
344 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
345 IS_AST_OP (expr->left->right) &&
346 expr->left->right->opval.op == '&' &&
347 IS_AST_LIT_VALUE (expr->right))
350 return valForCastAggr (expr->left->right->left,
351 expr->left->left->opval.lnk,
352 expr->right, expr->opval.op);
357 werror (E_INIT_WRONG);
362 /*-----------------------------------------------------------------*/
363 /* printChar - formats and prints a characater string with DB */
364 /*-----------------------------------------------------------------*/
366 printChar (FILE * ofile, char *s, int plen)
369 int len = strlen (s);
374 while (len && pplen < plen)
377 while (i && *s && pplen < plen)
379 if (*s < ' ' || *s == '\"')
383 tfprintf (ofile, "\t!ascii\n", buf);
384 tfprintf (ofile, "\t!db !constbyte\n", *s);
399 tfprintf (ofile, "\t!ascii\n", buf);
408 tfprintf (ofile, "\t!db !constbyte\n", 0);
411 /*-----------------------------------------------------------------*/
412 /* return the generic pointer high byte for a given pointer type. */
413 /*-----------------------------------------------------------------*/
415 pointerTypeToGPByte (const int p_type)
423 /* hack - if we get a generic pointer, we just assume
424 * it's an FPOINTER (i.e. in XDATA space).
433 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
441 /*-----------------------------------------------------------------*/
442 /* printPointerType - generates ival for pointer type */
443 /*-----------------------------------------------------------------*/
445 _printPointerType (FILE * oFile, const char *name)
449 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
453 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
457 /*-----------------------------------------------------------------*/
458 /* printPointerType - generates ival for pointer type */
459 /*-----------------------------------------------------------------*/
461 printPointerType (FILE * oFile, const char *name)
463 _printPointerType (oFile, name);
464 fprintf (oFile, "\n");
467 /*-----------------------------------------------------------------*/
468 /* printGPointerType - generates ival for generic pointer type */
469 /*-----------------------------------------------------------------*/
471 printGPointerType (FILE * oFile, const char *name,
472 const unsigned int type)
474 _printPointerType (oFile, name);
475 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type));
478 /*-----------------------------------------------------------------*/
479 /* printIvalType - generates ival for int/char */
480 /*-----------------------------------------------------------------*/
482 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
486 /* if initList is deep */
487 if (ilist->type == INIT_DEEP)
488 ilist = ilist->init.deep;
490 val = list2val (ilist);
491 switch (getSize (type)) {
494 tfprintf (oFile, "\t!db !constbyte\n", 0);
496 tfprintf (oFile, "\t!dbs\n",
497 aopLiteral (val, 0));
501 if (port->use_dw_for_init)
502 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
504 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
508 tfprintf (oFile, "\t!dw !constword\n", 0);
509 tfprintf (oFile, "\t!dw !constword\n", 0);
512 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
513 aopLiteral (val, 0), aopLiteral (val, 1),
514 aopLiteral (val, 2), aopLiteral (val, 3));
520 /*-----------------------------------------------------------------*/
521 /* printIvalBitFields - generate initializer for bitfields */
522 /*-----------------------------------------------------------------*/
523 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
527 initList *lilist = *ilist ;
528 unsigned long ival = 0;
534 val = list2val(lilist);
536 if (SPEC_BLEN(lsym->etype) > 8) {
537 size += ((SPEC_BLEN (lsym->etype) / 8) +
538 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
541 size = ((SPEC_BLEN (lsym->etype) / 8) +
542 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
544 i = (unsigned long)floatFromVal(val);
545 i <<= SPEC_BSTR (lsym->etype);
547 if (! ( lsym->next &&
548 (IS_BITFIELD(lsym->next->type)) &&
549 (SPEC_BSTR(lsym->next->etype)))) break;
551 lilist = lilist->next;
555 tfprintf (oFile, "\t!db !constbyte\n",ival);
559 tfprintf (oFile, "\t!dw !constword\n",ival);
562 tfprintf (oFile, "\t!db !constword,!constword\n",
563 (ival >> 8) & 0xffff, (ival & 0xffff));
570 /*-----------------------------------------------------------------*/
571 /* printIvalStruct - generates initial value for structures */
572 /*-----------------------------------------------------------------*/
574 printIvalStruct (symbol * sym, sym_link * type,
575 initList * ilist, FILE * oFile)
580 sflds = SPEC_STRUCT (type)->fields;
581 if (ilist->type != INIT_DEEP) {
582 werror (E_INIT_STRUCT, sym->name);
586 iloop = ilist->init.deep;
588 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
589 if (IS_BITFIELD(sflds->type)) {
590 printIvalBitFields(&sflds,&iloop,oFile);
592 printIval (sflds, sflds->type, iloop, oFile);
598 /*-----------------------------------------------------------------*/
599 /* printIvalChar - generates initital value for character array */
600 /*-----------------------------------------------------------------*/
602 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
610 val = list2val (ilist);
611 /* if the value is a character string */
612 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
614 if (!DCL_ELEM (type))
615 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
617 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
619 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
621 tfprintf (oFile, "\t!db !constbyte\n", 0);
629 printChar (oFile, s, strlen (s) + 1);
633 /*-----------------------------------------------------------------*/
634 /* printIvalArray - generates code for array initialization */
635 /*-----------------------------------------------------------------*/
637 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
641 int lcnt = 0, size = 0;
643 /* take care of the special case */
644 /* array of characters can be init */
646 if (IS_CHAR (type->next))
647 if (printIvalChar (type,
648 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
649 oFile, SPEC_CVAL (sym->etype).v_char))
652 /* not the special case */
653 if (ilist->type != INIT_DEEP)
655 werror (E_INIT_STRUCT, sym->name);
659 iloop = ilist->init.deep;
660 lcnt = DCL_ELEM (type);
665 printIval (sym, type->next, iloop, oFile);
666 iloop = (iloop ? iloop->next : NULL);
669 /* if not array limits given & we */
670 /* are out of initialisers then */
671 if (!DCL_ELEM (type) && !iloop)
674 /* no of elements given and we */
675 /* have generated for all of them */
680 /* if we have not been given a size */
681 if (!DCL_ELEM (type))
682 DCL_ELEM (type) = size;
687 /*-----------------------------------------------------------------*/
688 /* printIvalFuncPtr - generate initial value for function pointers */
689 /*-----------------------------------------------------------------*/
691 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
696 val = list2val (ilist);
697 /* check the types */
698 if ((dLvl = checkType (val->type, type->next)) <= 0)
700 tfprintf (oFile, "\t!dw !constword\n", 0);
704 /* now generate the name */
707 if (port->use_dw_for_init)
709 tfprintf (oFile, "\t!dws\n", val->name);
713 printPointerType (oFile, val->name);
716 else if (port->use_dw_for_init)
718 tfprintf (oFile, "\t!dws\n", val->sym->rname);
722 printPointerType (oFile, val->sym->rname);
728 /*-----------------------------------------------------------------*/
729 /* printIvalCharPtr - generates initial values for character pointers */
730 /*-----------------------------------------------------------------*/
732 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
736 /* PENDING: this is _very_ mcs51 specific, including a magic
738 It's also endin specific.
740 size = getSize (type);
742 if (val->name && strlen (val->name))
744 if (size == 1) /* This appears to be Z80 specific?? */
747 "\t!dbs\n", val->name);
749 else if (size == FPTRSIZE)
751 if (port->use_dw_for_init)
753 tfprintf (oFile, "\t!dws\n", val->name);
757 printPointerType (oFile, val->name);
760 else if (size == GPTRSIZE)
762 /* PENDING: 0x02 or 0x%02x, CDATA? */
763 printGPointerType (oFile, val->name,
764 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
765 PTR_TYPE (SPEC_OCLS (val->etype))));
769 fprintf (stderr, "*** internal error: unknown size in "
770 "printIvalCharPtr.\n");
775 /* What is this case? Are these pointers? */
779 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
782 if (port->use_dw_for_init)
783 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
785 tfprintf (oFile, "\t.byte %s,%s\n",
786 aopLiteral (val, 0), aopLiteral (val, 1));
789 /* PENDING: 0x02 or 0x%02x, CDATA? */
790 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
791 aopLiteral (val, 0), aopLiteral (val, 1));
799 if (val->sym && val->sym->isstrlit)
800 addSet (&statsg->syms, val->sym);
805 /*-----------------------------------------------------------------*/
806 /* printIvalPtr - generates initial value for pointers */
807 /*-----------------------------------------------------------------*/
809 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
815 if (ilist->type == INIT_DEEP)
816 ilist = ilist->init.deep;
818 /* function pointer */
819 if (IS_FUNC (type->next))
821 printIvalFuncPtr (type, ilist, oFile);
825 if (!(val = initPointer (ilist)))
828 /* if character pointer */
829 if (IS_CHAR (type->next))
830 if (printIvalCharPtr (sym, type, val, oFile))
834 if (checkType (type, val->type) != 1)
835 werror (E_INIT_WRONG);
837 /* if val is literal */
838 if (IS_LITERAL (val->etype))
840 switch (getSize (type))
843 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
846 if (port->use_dw_for_init)
847 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
849 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
852 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
853 aopLiteral (val, 0), aopLiteral (val, 1));
859 size = getSize (type);
861 if (size == 1) /* Z80 specific?? */
863 tfprintf (oFile, "\t!dbs\n", val->name);
865 else if (size == FPTRSIZE)
867 tfprintf (oFile, "\t!dws\n", val->name);
869 else if (size == GPTRSIZE)
871 printGPointerType (oFile, val->name,
872 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
873 PTR_TYPE (SPEC_OCLS (val->etype))));
878 /*-----------------------------------------------------------------*/
879 /* printIval - generates code for initial value */
880 /*-----------------------------------------------------------------*/
882 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
887 /* if structure then */
888 if (IS_STRUCT (type))
890 printIvalStruct (sym, type, ilist, oFile);
894 /* if this is a pointer */
897 printIvalPtr (sym, type, ilist, oFile);
901 /* if this is an array */
904 printIvalArray (sym, type, ilist, oFile);
908 /* if type is SPECIFIER */
911 printIvalType (type, ilist, oFile);
916 /*-----------------------------------------------------------------*/
917 /* emitStaticSeg - emitcode for the static segment */
918 /*-----------------------------------------------------------------*/
920 emitStaticSeg (memmap * map, FILE * out)
924 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
928 /* for all variables in this segment do */
929 for (sym = setFirstItem (map->syms); sym;
930 sym = setNextItem (map->syms))
933 /* if it is "extern" then do nothing */
934 if (IS_EXTERN (sym->etype))
937 /* if it is not static add it to the public
939 if (!IS_STATIC (sym->etype))
940 addSetHead (&publics, sym);
942 /* print extra debug info if required */
943 if ((options.debug || sym->level == 0) && !options.nodebug)
946 cdbSymbol (sym, cdbFile, FALSE, FALSE);
950 if (IS_STATIC (sym->etype))
951 fprintf (out, "F%s$", moduleName); /* scope is file */
953 fprintf (out, "G$"); /* scope is global */
956 /* symbol is local */
957 fprintf (out, "L%s$",
958 (sym->localof ? sym->localof->name : "-null-"));
959 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
962 /* if it has an absolute address */
963 if (SPEC_ABSA (sym->etype))
965 if ((options.debug || sym->level == 0) && !options.nodebug)
966 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
968 fprintf (out, "%s\t=\t0x%04x\n",
970 SPEC_ADDR (sym->etype));
974 if ((options.debug || sym->level == 0) && !options.nodebug)
975 fprintf (out, " == .\n");
977 /* if it has an initial value */
980 fprintf (out, "%s:\n", sym->rname);
982 resolveIvalSym (sym->ival);
983 printIval (sym, sym->type, sym->ival, out);
989 fprintf (out, "%s:\n", sym->rname);
990 /* special case for character strings */
991 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
992 SPEC_CVAL (sym->etype).v_char)
994 SPEC_CVAL (sym->etype).v_char,
995 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
997 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1003 /*-----------------------------------------------------------------*/
1004 /* emitMaps - emits the code for the data portion the code */
1005 /*-----------------------------------------------------------------*/
1009 /* no special considerations for the following
1010 data, idata & bit & xdata */
1011 emitRegularMap (data, TRUE, TRUE);
1012 emitRegularMap (idata, TRUE, TRUE);
1013 emitRegularMap (bit, TRUE, FALSE);
1014 emitRegularMap (xdata, TRUE, TRUE);
1015 emitRegularMap (sfr, FALSE, FALSE);
1016 emitRegularMap (sfrbit, FALSE, FALSE);
1017 emitRegularMap (home, TRUE, FALSE);
1018 emitRegularMap (code, TRUE, FALSE);
1020 emitStaticSeg (statsg, code->oFile);
1023 /*-----------------------------------------------------------------*/
1024 /* flushStatics - flush all currently defined statics out to file */
1025 /* and delete. Temporary function */
1026 /*-----------------------------------------------------------------*/
1030 emitStaticSeg (statsg, codeOutFile);
1031 statsg->syms = NULL;
1034 /*-----------------------------------------------------------------*/
1035 /* createInterruptVect - creates the interrupt vector */
1036 /*-----------------------------------------------------------------*/
1038 createInterruptVect (FILE * vFile)
1041 mainf = newSymbol ("main", 0);
1044 /* only if the main function exists */
1045 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1047 if (!options.cc_only)
1052 /* if the main is only a prototype ie. no body then do nothing */
1055 /* if ! compile only then main function should be present */
1056 if (!options.cc_only)
1061 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1062 fprintf (vFile, "__interrupt_vect:\n");
1065 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1067 /* "generic" interrupt table header (if port doesn't specify one).
1069 * Look suspiciously like 8051 code to me...
1072 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1075 /* now for the other interrupts */
1076 for (; i < maxInterrupts; i++)
1079 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1081 fprintf (vFile, "\treti\n\t.ds\t7\n");
1088 ";--------------------------------------------------------\n"
1089 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1093 ";--------------------------------------------------------\n"};
1096 /*-----------------------------------------------------------------*/
1097 /* initialComments - puts in some initial comments */
1098 /*-----------------------------------------------------------------*/
1100 initialComments (FILE * afile)
1104 fprintf (afile, "%s", iComments1);
1105 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1106 fprintf (afile, "%s", iComments2);
1109 /*-----------------------------------------------------------------*/
1110 /* printPublics - generates .global for publics */
1111 /*-----------------------------------------------------------------*/
1113 printPublics (FILE * afile)
1117 fprintf (afile, "%s", iComments2);
1118 fprintf (afile, "; Public variables in this module\n");
1119 fprintf (afile, "%s", iComments2);
1121 for (sym = setFirstItem (publics); sym;
1122 sym = setNextItem (publics))
1123 tfprintf (afile, "\t!global\n", sym->rname);
1126 /*-----------------------------------------------------------------*/
1127 /* printExterns - generates .global for externs */
1128 /*-----------------------------------------------------------------*/
1130 printExterns (FILE * afile)
1134 fprintf (afile, "%s", iComments2);
1135 fprintf (afile, "; Externals used\n");
1136 fprintf (afile, "%s", iComments2);
1138 for (sym = setFirstItem (externs); sym;
1139 sym = setNextItem (externs))
1140 tfprintf (afile, "\t!global\n", sym->rname);
1143 /*-----------------------------------------------------------------*/
1144 /* emitOverlay - will emit code for the overlay stuff */
1145 /*-----------------------------------------------------------------*/
1147 emitOverlay (FILE * afile)
1151 if (!elementsInSet (ovrSetSets))
1152 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1154 /* for each of the sets in the overlay segment do */
1155 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1156 ovrset = setNextItem (ovrSetSets))
1161 if (elementsInSet (ovrset))
1163 /* this dummy area is used to fool the assembler
1164 otherwise the assembler will append each of these
1165 declarations into one chunk and will not overlay
1167 fprintf (afile, "\t.area _DUMMY\n");
1168 /* output the area informtion */
1169 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1172 for (sym = setFirstItem (ovrset); sym;
1173 sym = setNextItem (ovrset))
1176 /* if extern then add it to the publics tabledo nothing */
1177 if (IS_EXTERN (sym->etype))
1180 /* if allocation required check is needed
1181 then check if the symbol really requires
1182 allocation only for local variables */
1183 if (!IS_AGGREGATE (sym->type) &&
1184 !(sym->_isparm && !IS_REGPARM (sym->etype))
1185 && !sym->allocreq && sym->level)
1188 /* if global variable & not static or extern
1189 and addPublics allowed then add it to the public set */
1190 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1191 && !IS_STATIC (sym->etype))
1192 addSetHead (&publics, sym);
1194 /* if extern then do nothing or is a function
1196 if (IS_FUNC (sym->type))
1199 /* print extra debug info if required */
1200 if ((options.debug || sym->level == 0) && !options.nodebug)
1203 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1207 if (IS_STATIC (sym->etype))
1208 fprintf (afile, "F%s$", moduleName); /* scope is file */
1210 fprintf (afile, "G$"); /* scope is global */
1213 /* symbol is local */
1214 fprintf (afile, "L%s$",
1215 (sym->localof ? sym->localof->name : "-null-"));
1216 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1219 /* if is has an absolute address then generate
1220 an equate for this no need to allocate space */
1221 if (SPEC_ABSA (sym->etype))
1224 if ((options.debug || sym->level == 0) && !options.nodebug)
1225 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1227 fprintf (afile, "%s\t=\t0x%04x\n",
1229 SPEC_ADDR (sym->etype));
1233 if ((options.debug || sym->level == 0) && !options.nodebug)
1234 fprintf (afile, "==.\n");
1236 /* allocate space */
1237 tfprintf (afile, "!labeldef\n", sym->rname);
1238 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1245 /*-----------------------------------------------------------------*/
1246 /* glue - the final glue that hold the whole thing together */
1247 /*-----------------------------------------------------------------*/
1253 FILE *ovrFile = tempfile ();
1255 addSetHead (&tmpfileSet, ovrFile);
1256 /* print the global struct definitions */
1257 if (options.debug && !options.nodebug)
1258 cdbStructBlock (0, cdbFile);
1260 vFile = tempfile ();
1261 /* PENDING: this isnt the best place but it will do */
1262 if (port->general.glue_up_main)
1264 /* create the interrupt vector table */
1265 createInterruptVect (vFile);
1268 addSetHead (&tmpfileSet, vFile);
1270 /* emit code for the all the variables declared */
1272 /* do the overlay segments */
1273 emitOverlay (ovrFile);
1275 /* now put it all together into the assembler file */
1276 /* create the assembler file name */
1278 if (!options.c1mode)
1280 sprintf (buffer, srcFileName);
1281 strcat (buffer, ".asm");
1285 strcpy (buffer, options.out_name);
1288 if (!(asmFile = fopen (buffer, "w")))
1290 werror (E_FILE_OPEN_ERR, buffer);
1294 /* initial comments */
1295 initialComments (asmFile);
1297 /* print module name */
1298 tfprintf (asmFile, "\t!module\n", moduleName);
1299 tfprintf (asmFile, "\t!fileprelude\n");
1301 /* Let the port generate any global directives, etc. */
1302 if (port->genAssemblerPreamble)
1304 port->genAssemblerPreamble (asmFile);
1307 /* print the global variables in this module */
1308 printPublics (asmFile);
1309 if (port->assembler.externGlobal)
1310 printExterns (asmFile);
1312 /* copy the sfr segment */
1313 fprintf (asmFile, "%s", iComments2);
1314 fprintf (asmFile, "; special function registers\n");
1315 fprintf (asmFile, "%s", iComments2);
1316 copyFile (asmFile, sfr->oFile);
1318 /* copy the sbit segment */
1319 fprintf (asmFile, "%s", iComments2);
1320 fprintf (asmFile, "; special function bits \n");
1321 fprintf (asmFile, "%s", iComments2);
1322 copyFile (asmFile, sfrbit->oFile);
1324 /* copy the data segment */
1325 fprintf (asmFile, "%s", iComments2);
1326 fprintf (asmFile, "; internal ram data\n");
1327 fprintf (asmFile, "%s", iComments2);
1328 copyFile (asmFile, data->oFile);
1331 /* create the overlay segments */
1332 fprintf (asmFile, "%s", iComments2);
1333 fprintf (asmFile, "; overlayable items in internal ram \n");
1334 fprintf (asmFile, "%s", iComments2);
1335 copyFile (asmFile, ovrFile);
1337 /* create the stack segment MOF */
1338 if (mainf && mainf->fbody)
1340 fprintf (asmFile, "%s", iComments2);
1341 fprintf (asmFile, "; Stack segment in internal ram \n");
1342 fprintf (asmFile, "%s", iComments2);
1343 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1344 "__start__stack:\n\t.ds\t1\n\n");
1347 /* create the idata segment */
1348 fprintf (asmFile, "%s", iComments2);
1349 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1350 fprintf (asmFile, "%s", iComments2);
1351 copyFile (asmFile, idata->oFile);
1353 /* copy the bit segment */
1354 fprintf (asmFile, "%s", iComments2);
1355 fprintf (asmFile, "; bit data\n");
1356 fprintf (asmFile, "%s", iComments2);
1357 copyFile (asmFile, bit->oFile);
1359 /* if external stack then reserve space of it */
1360 if (mainf && mainf->fbody && options.useXstack)
1362 fprintf (asmFile, "%s", iComments2);
1363 fprintf (asmFile, "; external stack \n");
1364 fprintf (asmFile, "%s", iComments2);
1365 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1366 fprintf (asmFile, "\t.ds 256\n");
1370 /* copy xtern ram data */
1371 fprintf (asmFile, "%s", iComments2);
1372 fprintf (asmFile, "; external ram data\n");
1373 fprintf (asmFile, "%s", iComments2);
1374 copyFile (asmFile, xdata->oFile);
1376 /* copy the interrupt vector table */
1377 if (mainf && mainf->fbody)
1379 fprintf (asmFile, "%s", iComments2);
1380 fprintf (asmFile, "; interrupt vector \n");
1381 fprintf (asmFile, "%s", iComments2);
1382 copyFile (asmFile, vFile);
1385 /* copy global & static initialisations */
1386 fprintf (asmFile, "%s", iComments2);
1387 fprintf (asmFile, "; global & static initialisations\n");
1388 fprintf (asmFile, "%s", iComments2);
1390 /* Everywhere we generate a reference to the static_name area,
1391 * (which is currently only here), we immediately follow it with a
1392 * definition of the post_static_name area. This guarantees that
1393 * the post_static_name area will immediately follow the static_name
1396 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1397 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1398 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1400 if (mainf && mainf->fbody)
1402 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1403 /* if external stack is specified then the
1404 higher order byte of the xdatalocation is
1405 going into P2 and the lower order going into
1407 if (options.useXstack)
1409 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1410 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1411 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1412 (unsigned int) options.xdata_loc & 0xff);
1415 /* initialise the stack pointer */
1416 /* if the user specified a value then use it */
1417 if (options.stack_loc)
1418 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1420 /* no: we have to compute it */
1421 if (!options.stackOnData && maxRegBank <= 3)
1422 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1424 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1426 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1427 fprintf (asmFile, "\tmov\ta,dpl\n");
1428 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1429 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1430 fprintf (asmFile, "__sdcc_init_data:\n");
1433 copyFile (asmFile, statsg->oFile);
1435 if (port->general.glue_up_main && mainf && mainf->fbody)
1437 /* This code is generated in the post-static area.
1438 * This area is guaranteed to follow the static area
1439 * by the ugly shucking and jiving about 20 lines ago.
1441 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1442 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1448 "%s", iComments2, iComments2);
1449 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1450 copyFile (asmFile, home->oFile);
1452 /* copy over code */
1453 fprintf (asmFile, "%s", iComments2);
1454 fprintf (asmFile, "; code\n");
1455 fprintf (asmFile, "%s", iComments2);
1456 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1457 if (mainf && mainf->fbody)
1460 /* entry point @ start of CSEG */
1461 fprintf (asmFile, "__sdcc_program_startup:\n");
1463 /* put in the call to main */
1464 fprintf (asmFile, "\tlcall\t_main\n");
1465 if (options.mainreturn)
1468 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1469 fprintf (asmFile, "\tret\n");
1475 fprintf (asmFile, ";\treturn from main will lock up\n");
1476 fprintf (asmFile, "\tsjmp .\n");
1479 copyFile (asmFile, code->oFile);
1482 applyToSet (tmpfileSet, closeTmpFiles);
1483 applyToSet (tmpfileNameSet, rmTmpFiles);
1486 /** Creates a temporary file a'la tmpfile which avoids the bugs
1487 in cygwin wrt c:\tmp.
1488 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1493 #if !defined(_MSC_VER)
1494 const char *tmpdir = NULL;
1496 tmpdir = getenv ("TMP");
1497 else if (getenv ("TEMP"))
1498 tmpdir = getenv ("TEMP");
1499 else if (getenv ("TMPDIR"))
1500 tmpdir = getenv ("TMPDIR");
1503 char *name = tempnam (tmpdir, "sdcc");
1506 FILE *fp = fopen (name, "w+b");
1509 addSetHead (&tmpfileNameSet, name);
1520 gc_strdup (const char *s)
1523 ret = Safe_calloc (1, strlen (s) + 1);