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 -------------------------------------------------------------------------*/
38 symbol *interrupts[INTNO_MAX+1];
40 void printIval (symbol *, sym_link *, initList *, FILE *);
41 set *publics = NULL; /* public variables */
42 set *externs = NULL; /* Variables that are declared as extern */
44 unsigned maxInterrupts = 0;
47 set *pipeSet = NULL; /* set of pipes */
48 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
49 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
51 /*-----------------------------------------------------------------*/
52 /* closePipes - closes all pipes created by the compiler */
53 /*-----------------------------------------------------------------*/
54 DEFSETFUNC (closePipes)
67 /*-----------------------------------------------------------------*/
68 /* closeTmpFiles - closes all tmp files created by the compiler */
69 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
70 /*-----------------------------------------------------------------*/
71 DEFSETFUNC (closeTmpFiles)
84 /*-----------------------------------------------------------------*/
85 /* rmTmpFiles - unlinks all tmp files created by the compiler */
86 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
87 /*-----------------------------------------------------------------*/
88 DEFSETFUNC (rmTmpFiles)
102 /*-----------------------------------------------------------------*/
103 /* rm_tmpfiles - close and remove temporary files and delete sets */
104 /*-----------------------------------------------------------------*/
108 /* close temporary files */
109 applyToSet (pipeSet, closePipes);
110 /* close temporary files */
111 deleteSet (&pipeSet);
113 applyToSet (tmpfileSet, closeTmpFiles);
114 /* remove temporary files */
115 applyToSet (tmpfileNameSet, rmTmpFiles);
116 /* delete temorary file sets */
117 deleteSet (&tmpfileSet);
118 deleteSet (&tmpfileNameSet);
121 /*-----------------------------------------------------------------*/
122 /* copyFile - copies source file to destination file */
123 /*-----------------------------------------------------------------*/
125 copyFile (FILE * dest, FILE * src)
131 if ((ch = fgetc (src)) != EOF)
136 aopLiteralLong (value * val, int offset, int size)
145 // assuming we have been warned before
149 /* if it is a float then it gets tricky */
150 /* otherwise it is fairly simple */
151 if (!IS_FLOAT (val->type)) {
152 unsigned long v = (unsigned long) floatFromVal (val);
157 tsprintf (buffer, sizeof(buffer),
158 "!immedbyte", (unsigned int) v & 0xff);
161 tsprintf (buffer, sizeof(buffer),
162 "!immedword", (unsigned int) v & 0xffff);
165 /* Hmm. Too big for now. */
168 return Safe_strdup (buffer);
171 /* PENDING: For now size must be 1 */
174 /* it is type float */
175 fl.f = (float) floatFromVal (val);
176 #ifdef WORDS_BIGENDIAN
177 tsprintf (buffer, sizeof(buffer),
178 "!immedbyte", fl.c[3 - offset]);
180 tsprintf (buffer, sizeof(buffer),
181 "!immedbyte", fl.c[offset]);
183 return Safe_strdup (buffer);
186 /*-----------------------------------------------------------------*/
187 /* aopLiteral - string from a literal value */
188 /*-----------------------------------------------------------------*/
190 aopLiteral (value * val, int offset)
192 return aopLiteralLong (val, offset, 1);
195 /*-----------------------------------------------------------------*/
196 /* emitRegularMap - emit code for maps with no special cases */
197 /*-----------------------------------------------------------------*/
199 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
209 /* PENDING: special case here - should remove */
210 if (!strcmp (map->sname, CODE_NAME))
211 tfprintf (map->oFile, "\t!areacode\n", map->sname);
212 else if (!strcmp (map->sname, DATA_NAME))
213 tfprintf (map->oFile, "\t!areadata\n", map->sname);
214 else if (!strcmp (map->sname, HOME_NAME))
215 tfprintf (map->oFile, "\t!areahome\n", map->sname);
217 tfprintf (map->oFile, "\t!area\n", map->sname);
220 for (sym = setFirstItem (map->syms); sym;
221 sym = setNextItem (map->syms))
225 /* if extern then add it into the extern list */
226 if (IS_EXTERN (sym->etype))
228 addSetHead (&externs, sym);
232 /* if allocation required check is needed
233 then check if the symbol really requires
234 allocation only for local variables */
236 if (arFlag && !IS_AGGREGATE (sym->type) &&
237 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
238 !sym->allocreq && sym->level)
241 /* for bitvar locals and parameters */
242 if (!arFlag && !sym->allocreq && sym->level
243 && !SPEC_ABSA (sym->etype)) {
247 /* if global variable & not static or extern
248 and addPublics allowed then add it to the public set */
249 if ((sym->level == 0 ||
250 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
252 !IS_STATIC (sym->etype) &&
253 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
255 addSetHead (&publics, sym);
258 /* if extern then do nothing or is a function
260 if (IS_FUNC (sym->type) && !(sym->isitmp))
263 /* print extra debug info if required */
266 if (!sym->level) /* global */
268 if (IS_STATIC (sym->etype))
269 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
271 fprintf (map->oFile, "G$"); /* scope is global */
275 /* symbol is local */
276 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
278 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
281 /* if it has an initial value then do it only if
282 it is a global variable */
283 if (sym->ival && sym->level == 0) {
284 if (SPEC_OCLS(sym->etype)==xidata) {
285 /* create a new "XINIT (CODE)" symbol, that will be emitted later
287 newSym=copySymbol (sym);
288 SPEC_OCLS(newSym->etype)=xinit;
289 SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
290 SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
291 if (IS_SPEC (newSym->type))
292 SPEC_CONST (newSym->type) = 1;
294 DCL_PTR_CONST (newSym->type) = 1;
295 SPEC_STAT(newSym->etype)=1;
296 resolveIvalSym(newSym->ival, newSym->type);
298 // add it to the "XINIT (CODE)" segment
299 addSet(&xinit->syms, newSym);
301 if (!SPEC_ABSA (sym->etype))
303 FILE *tmpFile = tempfile ();
304 addSetHead (&tmpfileSet, tmpFile);
305 // before allocation we must parse the sym->ival tree
306 // but without actually generating initialization code
308 resolveIvalSym (sym->ival, sym->type);
309 printIval (sym, sym->type, sym->ival, tmpFile);
315 if (IS_AGGREGATE (sym->type)) {
316 ival = initAggregates (sym, sym->ival, NULL);
318 if (getNelements(sym->type, sym->ival)>1) {
319 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
322 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
323 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
325 codeOutFile = statsg->oFile;
328 // set ival's lineno to where the symbol was defined
329 setAstLineno (ival, lineno=sym->lineDef);
330 // check if this is not a constant expression
331 if (!constExprTree(ival)) {
332 werror (E_CONST_EXPECTED, "found expression");
333 // but try to do it anyway
336 if (!astErrors(ival))
337 eBBlockFromiCode (iCodeFromAst (ival));
344 /* if it has an absolute address then generate
345 an equate for this no need to allocate space */
346 if (SPEC_ABSA (sym->etype))
350 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
352 if (TARGET_IS_XA51) {
355 } else if (map==bit || map==sfrbit) {
359 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
361 SPEC_ADDR (sym->etype));
364 int size = getSize (sym->type) + sym->flexArrayLength;
366 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
370 fprintf (map->oFile, "==.\n");
372 if (IS_STATIC (sym->etype))
373 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
375 tfprintf (map->oFile, "!labeldef\n", sym->rname);
376 tfprintf (map->oFile, "\t!ds\n",
377 (unsigned int) size & 0xffff);
382 /*-----------------------------------------------------------------*/
383 /* initPointer - pointer initialization code massaging */
384 /*-----------------------------------------------------------------*/
386 initPointer (initList * ilist, sym_link *toType)
392 return valCastLiteral(toType, 0.0);
395 expr = list2expr (ilist);
400 /* try it the old way first */
401 if ((val = constExprValue (expr, FALSE)))
404 /* ( ptr + constant ) */
405 if (IS_AST_OP (expr) &&
406 (expr->opval.op == '+' || expr->opval.op == '-') &&
407 IS_AST_SYM_VALUE (expr->left) &&
408 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
409 compareType(toType, expr->left->ftype) &&
410 IS_AST_LIT_VALUE (expr->right)) {
411 return valForCastAggr (expr->left, expr->left->ftype,
417 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
418 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
419 if (compareType(toType, expr->left->ftype)!=1) {
420 werror (W_INIT_WRONG);
421 printFromToType(expr->left->ftype, toType);
427 /* no then we have to do these cludgy checks */
428 /* pointers can be initialized with address of
429 a variable or address of an array element */
430 if (IS_AST_OP (expr) && expr->opval.op == '&') {
431 /* address of symbol */
432 if (IS_AST_SYM_VALUE (expr->left)) {
433 val = copyValue (AST_VALUE (expr->left));
434 val->type = newLink (DECLARATOR);
435 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
436 DCL_TYPE (val->type) = CPOINTER;
437 DCL_PTR_CONST (val->type) = port->mem.code_ro;
439 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
440 DCL_TYPE (val->type) = FPOINTER;
441 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
442 DCL_TYPE (val->type) = PPOINTER;
443 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
444 DCL_TYPE (val->type) = IPOINTER;
445 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
446 DCL_TYPE (val->type) = EEPPOINTER;
448 DCL_TYPE (val->type) = POINTER;
449 val->type->next = expr->left->ftype;
450 val->etype = getSpec (val->type);
454 /* if address of indexed array */
455 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
456 return valForArray (expr->left);
458 /* if address of structure element then
460 if (IS_AST_OP (expr->left) &&
461 expr->left->opval.op == '.') {
462 return valForStructElem (expr->left->left,
467 (&some_struct)->element */
468 if (IS_AST_OP (expr->left) &&
469 expr->left->opval.op == PTR_OP &&
470 IS_ADDRESS_OF_OP (expr->left->left)) {
471 return valForStructElem (expr->left->left->left,
475 /* case 3. (((char *) &a) +/- constant) */
476 if (IS_AST_OP (expr) &&
477 (expr->opval.op == '+' || expr->opval.op == '-') &&
478 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
479 IS_AST_OP (expr->left->right) &&
480 expr->left->right->opval.op == '&' &&
481 IS_AST_LIT_VALUE (expr->right)) {
483 return valForCastAggr (expr->left->right->left,
484 expr->left->left->opval.lnk,
485 expr->right, expr->opval.op);
488 /* case 4. (char *)(array type) */
489 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
490 IS_ARRAY(expr->right->ftype)) {
492 val = copyValue (AST_VALUE (expr->right));
493 val->type = newLink (DECLARATOR);
494 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
495 DCL_TYPE (val->type) = CPOINTER;
496 DCL_PTR_CONST (val->type) = port->mem.code_ro;
498 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
499 DCL_TYPE (val->type) = FPOINTER;
500 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
501 DCL_TYPE (val->type) = PPOINTER;
502 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
503 DCL_TYPE (val->type) = IPOINTER;
504 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
505 DCL_TYPE (val->type) = EEPPOINTER;
507 DCL_TYPE (val->type) = POINTER;
508 val->type->next = expr->right->ftype->next;
509 val->etype = getSpec (val->type);
514 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
516 werror (E_INCOMPAT_PTYPES);
521 /*-----------------------------------------------------------------*/
522 /* printChar - formats and prints a characater string with DB */
523 /*-----------------------------------------------------------------*/
525 printChar (FILE * ofile, char *s, int plen)
533 while (len && pplen < plen)
536 while (i && pplen < plen)
538 if (*s < ' ' || *s == '\"' || *s=='\\')
542 tfprintf (ofile, "\t!ascii\n", buf);
543 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
558 tfprintf (ofile, "\t!ascii\n", buf);
569 tfprintf (ofile, "\t!db !constbyte\n", 0);
574 /*-----------------------------------------------------------------*/
575 /* return the generic pointer high byte for a given pointer type. */
576 /*-----------------------------------------------------------------*/
578 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
586 werror (E_CANNOT_USE_GENERIC_POINTER,
587 iname ? iname : "<null>",
588 oname ? oname : "<null>");
595 return GPTYPE_XSTACK;
597 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
605 /*-----------------------------------------------------------------*/
606 /* printPointerType - generates ival for pointer type */
607 /*-----------------------------------------------------------------*/
609 _printPointerType (FILE * oFile, const char *name)
611 if (options.model == MODEL_FLAT24)
613 if (port->little_endian)
614 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
616 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
620 if (port->little_endian)
621 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
623 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
627 /*-----------------------------------------------------------------*/
628 /* printPointerType - generates ival for pointer type */
629 /*-----------------------------------------------------------------*/
631 printPointerType (FILE * oFile, const char *name)
633 _printPointerType (oFile, name);
634 fprintf (oFile, "\n");
637 /*-----------------------------------------------------------------*/
638 /* printGPointerType - generates ival for generic pointer type */
639 /*-----------------------------------------------------------------*/
641 printGPointerType (FILE * oFile, const char *iname, const char *oname,
642 const unsigned int type)
644 _printPointerType (oFile, iname);
645 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
648 /*-----------------------------------------------------------------*/
649 /* printIvalType - generates ival for int/char */
650 /*-----------------------------------------------------------------*/
652 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
656 /* if initList is deep */
657 if (ilist && (ilist->type == INIT_DEEP))
658 ilist = ilist->init.deep;
660 if (!(val = list2val (ilist))) {
661 // assuming a warning has been thrown
665 if (val->type != type) {
666 val = valCastLiteral(type, floatFromVal(val));
669 switch (getSize (type)) {
672 tfprintf (oFile, "\t!db !constbyte\n", 0);
674 tfprintf (oFile, "\t!dbs\n",
675 aopLiteral (val, 0));
679 if (port->use_dw_for_init)
680 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
681 else if (port->little_endian)
682 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
684 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
688 tfprintf (oFile, "\t!dw !constword\n", 0);
689 tfprintf (oFile, "\t!dw !constword\n", 0);
691 else if (port->little_endian) {
692 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
693 aopLiteral (val, 0), aopLiteral (val, 1),
694 aopLiteral (val, 2), aopLiteral (val, 3));
697 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
698 aopLiteral (val, 3), aopLiteral (val, 2),
699 aopLiteral (val, 1), aopLiteral (val, 0));
705 /*-----------------------------------------------------------------*/
706 /* printIvalBitFields - generate initializer for bitfields */
707 /*-----------------------------------------------------------------*/
708 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
712 initList *lilist = *ilist ;
713 unsigned long ival = 0;
719 val = list2val(lilist);
721 if (SPEC_BLEN(lsym->etype) > 8) {
722 size += ((SPEC_BLEN (lsym->etype) / 8) +
723 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
726 size = ((SPEC_BLEN (lsym->etype) / 8) +
727 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
729 i = (unsigned long)floatFromVal(val);
730 i <<= SPEC_BSTR (lsym->etype);
732 if (! ( lsym->next &&
733 (IS_BITFIELD(lsym->next->type)) &&
734 (SPEC_BSTR(lsym->next->etype)))) break;
736 lilist = lilist->next;
740 tfprintf (oFile, "\t!db !constbyte\n",ival);
744 tfprintf (oFile, "\t!dw !constword\n",ival);
746 case 4: /* EEP: why is this db and not dw? */
747 tfprintf (oFile, "\t!db !constword,!constword\n",
748 (ival >> 8) & 0xffff, (ival & 0xffff));
755 /*-----------------------------------------------------------------*/
756 /* printIvalStruct - generates initial value for structures */
757 /*-----------------------------------------------------------------*/
759 printIvalStruct (symbol * sym, sym_link * type,
760 initList * ilist, FILE * oFile)
763 initList *iloop = NULL;
765 sflds = SPEC_STRUCT (type)->fields;
768 if (ilist->type != INIT_DEEP) {
769 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
773 iloop = ilist->init.deep;
776 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
777 if (IS_BITFIELD(sflds->type)) {
778 printIvalBitFields(&sflds,&iloop,oFile);
780 printIval (sym, sflds->type, iloop, oFile);
784 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
789 /*-----------------------------------------------------------------*/
790 /* printIvalChar - generates initital value for character array */
791 /*-----------------------------------------------------------------*/
793 printIvalChar (symbol * sym, sym_link * type, initList * ilist, FILE * oFile, char *s)
796 unsigned int size = DCL_ELEM (type);
800 val = list2val (ilist);
801 /* if the value is a character string */
802 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
806 /* we have not been given a size, but now we know it */
807 size = strlen (SPEC_CVAL (val->etype).v_char) + 1;
808 /* but first check, if it's a flexible array */
809 if (sym && IS_STRUCT (sym->type))
810 sym->flexArrayLength = size;
812 DCL_ELEM (type) = size;
815 printChar (oFile, SPEC_CVAL (val->etype).v_char, size);
823 printChar (oFile, s, strlen (s) + 1);
827 /*-----------------------------------------------------------------*/
828 /* printIvalArray - generates code for array initialization */
829 /*-----------------------------------------------------------------*/
831 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
835 unsigned int size = 0;
838 /* take care of the special case */
839 /* array of characters can be init */
841 if (IS_CHAR (type->next)) {
842 if (!IS_LITERAL(list2val(ilist)->etype)) {
843 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
846 if (printIvalChar (sym, type,
847 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
848 oFile, SPEC_CVAL (sym->etype).v_char))
851 /* not the special case */
852 if (ilist->type != INIT_DEEP) {
853 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
857 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
858 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
859 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
862 printIval (sym, type->next, iloop, oFile);
866 if (DCL_ELEM(type)) {
867 // pad with zeros if needed
868 if (size<DCL_ELEM(type)) {
869 size = (DCL_ELEM(type) - size) * getSize(type->next);
871 tfprintf (oFile, "\t!db !constbyte\n", 0);
875 /* we have not been given a size, but now we know it */
876 /* but first check, if it's a flexible array */
877 if (IS_STRUCT (sym->type))
878 sym->flexArrayLength = size * getSize (type->next);
880 DCL_ELEM (type) = size;
886 /*-----------------------------------------------------------------*/
887 /* printIvalFuncPtr - generate initial value for function pointers */
888 /*-----------------------------------------------------------------*/
890 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
896 val = list2val (ilist);
898 val = valCastLiteral(type, 0.0);
901 // an error has been thrown already
905 if (IS_LITERAL(val->etype)) {
906 if (compareType(type, val->etype) == 0) {
907 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
908 printFromToType (val->type, type);
910 printIvalCharPtr (NULL, type, val, oFile);
914 /* check the types */
915 if ((dLvl = compareType (val->type, type->next)) <= 0)
917 tfprintf (oFile, "\t!dw !constword\n", 0);
921 /* now generate the name */
924 if (port->use_dw_for_init)
926 tfprintf (oFile, "\t!dws\n", val->name);
930 printPointerType (oFile, val->name);
933 else if (port->use_dw_for_init)
935 tfprintf (oFile, "\t!dws\n", val->sym->rname);
939 printPointerType (oFile, val->sym->rname);
945 /*-----------------------------------------------------------------*/
946 /* printIvalCharPtr - generates initial values for character pointers */
947 /*-----------------------------------------------------------------*/
949 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
953 /* PENDING: this is _very_ mcs51 specific, including a magic
955 It's also endin specific.
957 size = getSize (type);
959 if (val->name && strlen (val->name))
961 if (size == 1) /* This appears to be Z80 specific?? */
964 "\t!dbs\n", val->name);
966 else if (size == FPTRSIZE)
968 if (port->use_dw_for_init)
970 tfprintf (oFile, "\t!dws\n", val->name);
974 printPointerType (oFile, val->name);
977 else if (size == GPTRSIZE)
980 if (IS_PTR (val->type)) {
981 type = DCL_TYPE (val->type);
983 type = PTR_TYPE (SPEC_OCLS (val->etype));
985 if (val->sym && val->sym->isstrlit) {
986 // this is a literal string
989 printGPointerType (oFile, val->name, sym->name, type);
993 fprintf (stderr, "*** internal error: unknown size in "
994 "printIvalCharPtr.\n");
999 // these are literals assigned to pointers
1003 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
1006 if (port->use_dw_for_init)
1007 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
1008 else if (port->little_endian)
1009 tfprintf (oFile, "\t.byte %s,%s\n",
1010 aopLiteral (val, 0), aopLiteral (val, 1));
1012 tfprintf (oFile, "\t.byte %s,%s\n",
1013 aopLiteral (val, 1), aopLiteral (val, 0));
1016 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1017 // non-zero mcs51 generic pointer
1018 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1020 if (port->little_endian) {
1021 fprintf (oFile, "\t.byte %s,%s,%s\n",
1022 aopLiteral (val, 0),
1023 aopLiteral (val, 1),
1024 aopLiteral (val, 2));
1026 fprintf (oFile, "\t.byte %s,%s,%s\n",
1027 aopLiteral (val, 2),
1028 aopLiteral (val, 1),
1029 aopLiteral (val, 0));
1033 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1034 // non-zero ds390 generic pointer
1035 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1037 if (port->little_endian) {
1038 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1039 aopLiteral (val, 0),
1040 aopLiteral (val, 1),
1041 aopLiteral (val, 2),
1042 aopLiteral (val, 3));
1044 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1045 aopLiteral (val, 3),
1046 aopLiteral (val, 2),
1047 aopLiteral (val, 1),
1048 aopLiteral (val, 0));
1056 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1057 addSet (&statsg->syms, val->sym);
1063 /*-----------------------------------------------------------------*/
1064 /* printIvalPtr - generates initial value for pointers */
1065 /*-----------------------------------------------------------------*/
1067 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1073 if (ilist && (ilist->type == INIT_DEEP))
1074 ilist = ilist->init.deep;
1076 /* function pointer */
1077 if (IS_FUNC (type->next))
1079 printIvalFuncPtr (type, ilist, oFile);
1083 if (!(val = initPointer (ilist, type)))
1086 /* if character pointer */
1087 if (IS_CHAR (type->next))
1088 if (printIvalCharPtr (sym, type, val, oFile))
1091 /* check the type */
1092 if (compareType (type, val->type) == 0) {
1093 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1094 printFromToType (val->type, type);
1097 /* if val is literal */
1098 if (IS_LITERAL (val->etype))
1100 switch (getSize (type))
1103 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1106 if (port->use_dw_for_init)
1107 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1108 else if (port->little_endian)
1109 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1111 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1113 case 3: // how about '390??
1114 fprintf (oFile, "; generic printIvalPtr\n");
1115 if (port->little_endian)
1117 fprintf (oFile, "\t.byte %s,%s",
1118 aopLiteral (val, 0), aopLiteral (val, 1));
1122 fprintf (oFile, "\t.byte %s,%s",
1123 aopLiteral (val, 1), aopLiteral (val, 0));
1125 if (IS_GENPTR (val->type))
1126 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1127 else if (IS_PTR (val->type))
1128 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1130 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1136 size = getSize (type);
1138 if (size == 1) /* Z80 specific?? */
1140 tfprintf (oFile, "\t!dbs\n", val->name);
1142 else if (size == FPTRSIZE)
1144 if (port->use_dw_for_init) {
1145 tfprintf (oFile, "\t!dws\n", val->name);
1147 printPointerType (oFile, val->name);
1150 else if (size == GPTRSIZE)
1152 printGPointerType (oFile, val->name, sym->name,
1153 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1154 PTR_TYPE (SPEC_OCLS (val->etype))));
1159 /*-----------------------------------------------------------------*/
1160 /* printIval - generates code for initial value */
1161 /*-----------------------------------------------------------------*/
1163 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1167 /* if structure then */
1168 if (IS_STRUCT (type))
1170 printIvalStruct (sym, type, ilist, oFile);
1174 /* if this is an array */
1175 if (IS_ARRAY (type))
1177 printIvalArray (sym, type, ilist, oFile);
1183 // not an aggregate, ilist must be a node
1184 if (ilist->type!=INIT_NODE) {
1185 // or a 1-element list
1186 if (ilist->init.deep->next) {
1187 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1190 ilist=ilist->init.deep;
1194 // and the type must match
1195 itype=ilist->init.node->ftype;
1197 if (compareType(type, itype)==0) {
1198 // special case for literal strings
1199 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1200 // which are really code pointers
1201 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1204 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1205 printFromToType(itype, type);
1210 /* if this is a pointer */
1213 printIvalPtr (sym, type, ilist, oFile);
1217 /* if type is SPECIFIER */
1220 printIvalType (sym, type, ilist, oFile);
1225 /*-----------------------------------------------------------------*/
1226 /* emitStaticSeg - emitcode for the static segment */
1227 /*-----------------------------------------------------------------*/
1229 emitStaticSeg (memmap * map, FILE * out)
1233 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1235 /* for all variables in this segment do */
1236 for (sym = setFirstItem (map->syms); sym;
1237 sym = setNextItem (map->syms))
1240 /* if it is "extern" then do nothing */
1241 if (IS_EXTERN (sym->etype))
1244 /* if it is not static add it to the public
1246 if (!IS_STATIC (sym->etype))
1248 addSetHead (&publics, sym);
1251 /* print extra debug info if required */
1252 if (options.debug) {
1256 if (IS_STATIC (sym->etype))
1257 fprintf (out, "F%s$", moduleName); /* scope is file */
1259 fprintf (out, "G$"); /* scope is global */
1262 /* symbol is local */
1263 fprintf (out, "L%s$",
1264 (sym->localof ? sym->localof->name : "-null-"));
1265 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1268 /* if it has an absolute address */
1269 if (SPEC_ABSA (sym->etype))
1272 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1274 fprintf (out, "%s\t=\t0x%04x\n",
1276 SPEC_ADDR (sym->etype));
1281 fprintf (out, " == .\n");
1283 /* if it has an initial value */
1286 fprintf (out, "%s:\n", sym->rname);
1288 resolveIvalSym (sym->ival, sym->type);
1289 printIval (sym, sym->type, sym->ival, out);
1291 /* if sym is a simple string and sym->ival is a string,
1292 WE don't need it anymore */
1293 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1294 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1295 list2val(sym->ival)->sym->isstrlit) {
1296 freeStringSymbol(list2val(sym->ival)->sym);
1300 /* allocate space */
1301 int size = getSize (sym->type);
1304 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1306 fprintf (out, "%s:\n", sym->rname);
1307 /* special case for character strings */
1308 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1309 SPEC_CVAL (sym->etype).v_char)
1311 SPEC_CVAL (sym->etype).v_char,
1314 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1320 /*-----------------------------------------------------------------*/
1321 /* emitMaps - emits the code for the data portion the code */
1322 /*-----------------------------------------------------------------*/
1326 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1327 /* ports but let's be conservative - EEP */
1330 /* no special considerations for the following
1331 data, idata & bit & xdata */
1332 emitRegularMap (data, TRUE, TRUE);
1333 emitRegularMap (idata, TRUE, TRUE);
1334 emitRegularMap (bit, TRUE, TRUE);
1335 emitRegularMap (pdata, TRUE, TRUE);
1336 emitRegularMap (xdata, TRUE, TRUE);
1337 if (port->genXINIT) {
1338 emitRegularMap (xidata, TRUE, TRUE);
1340 emitRegularMap (sfr, publicsfr, FALSE);
1341 emitRegularMap (sfrbit, publicsfr, FALSE);
1342 emitRegularMap (home, TRUE, FALSE);
1343 emitRegularMap (code, TRUE, FALSE);
1345 if (options.const_seg) {
1346 tfprintf (code->oFile, "\t!area\n", options.const_seg);
1348 emitStaticSeg (statsg, code->oFile);
1349 if (port->genXINIT) {
1350 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1351 emitStaticSeg (xinit, code->oFile);
1356 /*-----------------------------------------------------------------*/
1357 /* flushStatics - flush all currently defined statics out to file */
1358 /* and delete. Temporary function */
1359 /*-----------------------------------------------------------------*/
1363 emitStaticSeg (statsg, codeOutFile);
1364 statsg->syms = NULL;
1367 /*-----------------------------------------------------------------*/
1368 /* createInterruptVect - creates the interrupt vector */
1369 /*-----------------------------------------------------------------*/
1371 createInterruptVect (FILE * vFile)
1373 mainf = newSymbol ("main", 0);
1376 /* only if the main function exists */
1377 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1379 if (!options.cc_only && !noAssemble && !options.c1mode)
1384 /* if the main is only a prototype ie. no body then do nothing */
1385 if (!IFFUNC_HASBODY(mainf->type))
1387 /* if ! compile only then main function should be present */
1388 if (!options.cc_only && !noAssemble)
1393 tfprintf (vFile, "\t!areacode\n", HOME_NAME);
1394 fprintf (vFile, "__interrupt_vect:\n");
1397 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1399 /* There's no such thing as a "generic" interrupt table header. */
1406 ";--------------------------------------------------------\n"
1407 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1411 ";--------------------------------------------------------\n"};
1414 /*-----------------------------------------------------------------*/
1415 /* initialComments - puts in some initial comments */
1416 /*-----------------------------------------------------------------*/
1418 initialComments (FILE * afile)
1422 fprintf (afile, "%s", iComments1);
1423 fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber(), __DATE__);
1424 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1425 fprintf (afile, "%s", iComments2);
1428 /*-----------------------------------------------------------------*/
1429 /* printPublics - generates .global for publics */
1430 /*-----------------------------------------------------------------*/
1432 printPublics (FILE * afile)
1436 fprintf (afile, "%s", iComments2);
1437 fprintf (afile, "; Public variables in this module\n");
1438 fprintf (afile, "%s", iComments2);
1440 for (sym = setFirstItem (publics); sym;
1441 sym = setNextItem (publics))
1442 tfprintf (afile, "\t!global\n", sym->rname);
1445 /*-----------------------------------------------------------------*/
1446 /* printExterns - generates .global for externs */
1447 /*-----------------------------------------------------------------*/
1449 printExterns (FILE * afile)
1453 fprintf (afile, "%s", iComments2);
1454 fprintf (afile, "; Externals used\n");
1455 fprintf (afile, "%s", iComments2);
1457 for (sym = setFirstItem (externs); sym;
1458 sym = setNextItem (externs))
1459 tfprintf (afile, "\t!extern\n", sym->rname);
1462 /*-----------------------------------------------------------------*/
1463 /* emitOverlay - will emit code for the overlay stuff */
1464 /*-----------------------------------------------------------------*/
1466 emitOverlay (FILE * afile)
1470 if (!elementsInSet (ovrSetSets))
1471 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1473 /* for each of the sets in the overlay segment do */
1474 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1475 ovrset = setNextItem (ovrSetSets))
1480 if (elementsInSet (ovrset))
1482 /* output the area informtion */
1483 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1486 for (sym = setFirstItem (ovrset); sym;
1487 sym = setNextItem (ovrset))
1489 /* if extern then it is in the publics table: do nothing */
1490 if (IS_EXTERN (sym->etype))
1493 /* if allocation required check is needed
1494 then check if the symbol really requires
1495 allocation only for local variables */
1496 if (!IS_AGGREGATE (sym->type) &&
1497 !(sym->_isparm && !IS_REGPARM (sym->etype))
1498 && !sym->allocreq && sym->level)
1501 /* if global variable & not static or extern
1502 and addPublics allowed then add it to the public set */
1503 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1504 && !IS_STATIC (sym->etype))
1506 addSetHead (&publics, sym);
1509 /* if extern then do nothing or is a function
1511 if (IS_FUNC (sym->type))
1514 /* print extra debug info if required */
1519 if (IS_STATIC (sym->etype))
1520 fprintf (afile, "F%s$", moduleName); /* scope is file */
1522 fprintf (afile, "G$"); /* scope is global */
1525 /* symbol is local */
1526 fprintf (afile, "L%s$",
1527 (sym->localof ? sym->localof->name : "-null-"));
1528 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1531 /* if is has an absolute address then generate
1532 an equate for this no need to allocate space */
1533 if (SPEC_ABSA (sym->etype))
1537 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1539 fprintf (afile, "%s\t=\t0x%04x\n",
1541 SPEC_ADDR (sym->etype));
1544 int size = getSize(sym->type);
1547 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1550 fprintf (afile, "==.\n");
1552 /* allocate space */
1553 tfprintf (afile, "!labeldef\n", sym->rname);
1554 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1562 /*-----------------------------------------------------------------*/
1563 /* spacesToUnderscores - replace spaces with underscores */
1564 /*-----------------------------------------------------------------*/
1566 spacesToUnderscores (char *dest, const char *src, size_t len)
1571 assert(dest != NULL);
1572 assert(src != NULL);
1576 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1577 *p++ = isspace((unsigned char)*src) ? '_' : *src;
1585 /*-----------------------------------------------------------------*/
1586 /* glue - the final glue that hold the whole thing together */
1587 /*-----------------------------------------------------------------*/
1593 FILE *ovrFile = tempfile ();
1594 char moduleBuf[PATH_MAX];
1597 if(port->general.glue_up_main &&
1598 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1600 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1607 addSetHead (&tmpfileSet, ovrFile);
1608 /* print the global struct definitions */
1612 vFile = tempfile ();
1613 /* PENDING: this isn't the best place but it will do */
1614 if (port->general.glue_up_main)
1616 /* create the interrupt vector table */
1617 createInterruptVect (vFile);
1620 addSetHead (&tmpfileSet, vFile);
1622 /* emit code for the all the variables declared */
1624 /* do the overlay segments */
1625 emitOverlay (ovrFile);
1627 outputDebugSymbols();
1629 /* now put it all together into the assembler file */
1630 /* create the assembler file name */
1632 /* -o option overrides default name? */
1633 if ((noAssemble || options.c1mode) && fullDstFileName)
1635 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1639 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1640 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1643 if (!(asmFile = fopen (scratchFileName, "w")))
1645 werror (E_FILE_OPEN_ERR, scratchFileName);
1649 /* initial comments */
1650 initialComments (asmFile);
1652 /* print module name */
1653 tfprintf (asmFile, "\t!module\n",
1654 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1657 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1659 switch(options.model)
1661 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1662 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1663 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1664 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1665 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1666 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1669 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1670 if(options.useXstack) fprintf (asmFile, " --xstack");
1671 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1672 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1673 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1674 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1675 fprintf (asmFile, "\n");
1677 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1679 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1682 tfprintf (asmFile, "\t!fileprelude\n");
1684 /* Let the port generate any global directives, etc. */
1685 if (port->genAssemblerPreamble)
1687 port->genAssemblerPreamble (asmFile);
1690 /* print the global variables in this module */
1691 printPublics (asmFile);
1692 if (port->assembler.externGlobal)
1693 printExterns (asmFile);
1696 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1698 /* copy the sfr segment */
1699 fprintf (asmFile, "%s", iComments2);
1700 fprintf (asmFile, "; special function registers\n");
1701 fprintf (asmFile, "%s", iComments2);
1702 copyFile (asmFile, sfr->oFile);
1707 /* copy the sbit segment */
1708 fprintf (asmFile, "%s", iComments2);
1709 fprintf (asmFile, "; special function bits\n");
1710 fprintf (asmFile, "%s", iComments2);
1711 copyFile (asmFile, sfrbit->oFile);
1713 /*JCF: Create the areas for the register banks*/
1714 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1716 fprintf (asmFile, "%s", iComments2);
1717 fprintf (asmFile, "; overlayable register banks\n");
1718 fprintf (asmFile, "%s", iComments2);
1720 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1721 if(RegBankUsed[1]||options.parms_in_bank1)
1722 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1724 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1726 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1730 fprintf (asmFile, "%s", iComments2);
1731 fprintf (asmFile, "; overlayable bit register bank\n");
1732 fprintf (asmFile, "%s", iComments2);
1733 fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
1734 fprintf (asmFile, "bits:\n\t.ds 1\n");
1735 fprintf (asmFile, "\tb0 = bits[0]\n");
1736 fprintf (asmFile, "\tb1 = bits[1]\n");
1737 fprintf (asmFile, "\tb2 = bits[2]\n");
1738 fprintf (asmFile, "\tb3 = bits[3]\n");
1739 fprintf (asmFile, "\tb4 = bits[4]\n");
1740 fprintf (asmFile, "\tb5 = bits[5]\n");
1741 fprintf (asmFile, "\tb6 = bits[6]\n");
1742 fprintf (asmFile, "\tb7 = bits[7]\n");
1746 /* copy the data segment */
1747 fprintf (asmFile, "%s", iComments2);
1748 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1749 fprintf (asmFile, "%s", iComments2);
1750 copyFile (asmFile, data->oFile);
1753 /* create the overlay segments */
1755 fprintf (asmFile, "%s", iComments2);
1756 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1757 fprintf (asmFile, "%s", iComments2);
1758 copyFile (asmFile, ovrFile);
1761 /* create the stack segment MOF */
1762 if (mainf && IFFUNC_HASBODY(mainf->type))
1764 fprintf (asmFile, "%s", iComments2);
1765 fprintf (asmFile, "; Stack segment in internal ram \n");
1766 fprintf (asmFile, "%s", iComments2);
1767 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1768 "__start__stack:\n\t.ds\t1\n\n");
1771 /* create the idata segment */
1772 if ( (idata) && (mcs51_like) ) {
1773 fprintf (asmFile, "%s", iComments2);
1774 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1775 fprintf (asmFile, "%s", iComments2);
1776 copyFile (asmFile, idata->oFile);
1779 /* copy the bit segment */
1781 fprintf (asmFile, "%s", iComments2);
1782 fprintf (asmFile, "; bit data\n");
1783 fprintf (asmFile, "%s", iComments2);
1784 copyFile (asmFile, bit->oFile);
1787 /* copy paged external ram data */
1790 fprintf (asmFile, "%s", iComments2);
1791 fprintf (asmFile, "; paged external ram data\n");
1792 fprintf (asmFile, "%s", iComments2);
1793 copyFile (asmFile, pdata->oFile);
1796 /* if external stack then reserve space for it */
1797 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1799 fprintf (asmFile, "%s", iComments2);
1800 fprintf (asmFile, "; external stack \n");
1801 fprintf (asmFile, "%s", iComments2);
1802 fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
1803 "__start__xstack:\n\t.ds\t1\n\n");
1806 /* copy external ram data */
1808 fprintf (asmFile, "%s", iComments2);
1809 fprintf (asmFile, "; external ram data\n");
1810 fprintf (asmFile, "%s", iComments2);
1811 copyFile (asmFile, xdata->oFile);
1814 /* copy external initialized ram data */
1815 fprintf (asmFile, "%s", iComments2);
1816 fprintf (asmFile, "; external initialized ram data\n");
1817 fprintf (asmFile, "%s", iComments2);
1818 copyFile (asmFile, xidata->oFile);
1820 /* If the port wants to generate any extra areas, let it do so. */
1821 if (port->extraAreas.genExtraAreaDeclaration)
1823 port->extraAreas.genExtraAreaDeclaration(asmFile,
1824 mainf && IFFUNC_HASBODY(mainf->type));
1827 /* copy the interrupt vector table */
1828 if (mainf && IFFUNC_HASBODY(mainf->type))
1830 fprintf (asmFile, "%s", iComments2);
1831 fprintf (asmFile, "; interrupt vector \n");
1832 fprintf (asmFile, "%s", iComments2);
1833 copyFile (asmFile, vFile);
1836 /* copy global & static initialisations */
1837 fprintf (asmFile, "%s", iComments2);
1838 fprintf (asmFile, "; global & static initialisations\n");
1839 fprintf (asmFile, "%s", iComments2);
1841 /* Everywhere we generate a reference to the static_name area,
1842 * (which is currently only here), we immediately follow it with a
1843 * definition of the post_static_name area. This guarantees that
1844 * the post_static_name area will immediately follow the static_name
1847 tfprintf (asmFile, "\t!area\n", port->mem.home_name);
1848 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1849 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1850 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1852 if (mainf && IFFUNC_HASBODY(mainf->type))
1854 if (port->genInitStartup)
1856 port->genInitStartup(asmFile);
1860 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1861 /* if external stack is specified then the
1862 higher order byte of the xdatalocation is
1863 going into P2 and the lower order going into
1865 if (options.useXstack)
1867 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1868 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1869 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1870 (unsigned int) options.xdata_loc & 0xff);
1873 // This should probably be a port option, but I'm being lazy.
1874 // on the 400, the firmware boot loader gives us a valid stack
1875 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1876 if (!TARGET_IS_DS400)
1878 /* initialise the stack pointer. JCF: aslink takes care of the location */
1879 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1882 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1883 fprintf (asmFile, "\tmov\ta,dpl\n");
1884 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1885 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1886 fprintf (asmFile, "__sdcc_init_data:\n");
1888 // if the port can copy the XINIT segment to XISEG
1891 port->genXINIT(asmFile);
1896 copyFile (asmFile, statsg->oFile);
1898 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1900 /* This code is generated in the post-static area.
1901 * This area is guaranteed to follow the static area
1902 * by the ugly shucking and jiving about 20 lines ago.
1904 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1905 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1911 "%s", iComments2, iComments2);
1912 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1913 copyFile (asmFile, home->oFile);
1915 if (mainf && IFFUNC_HASBODY(mainf->type))
1918 /* entry point @ start of HOME */
1919 fprintf (asmFile, "__sdcc_program_startup:\n");
1921 /* put in jump or call to main */
1922 if (options.mainreturn)
1924 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1925 fprintf (asmFile, ";\treturn from main will return to caller\n");
1929 fprintf (asmFile, "\tlcall\t_main\n");
1930 fprintf (asmFile, ";\treturn from main will lock up\n");
1931 fprintf (asmFile, "\tsjmp .\n");
1934 /* copy over code */
1935 fprintf (asmFile, "%s", iComments2);
1936 fprintf (asmFile, "; code\n");
1937 fprintf (asmFile, "%s", iComments2);
1938 tfprintf (asmFile, "\t!areacode\n", options.code_seg);
1939 copyFile (asmFile, code->oFile);
1941 if (port->genAssemblerEnd) {
1942 port->genAssemblerEnd(asmFile);
1950 /** Creates a temporary file with unique file name
1952 - TMP, TEMP, TMPDIR env. variables
1953 - if Un*x system: /usr/tmp and /tmp
1954 - root directory using mkstemp() if available
1955 - default location using tempnam()
1958 tempfileandname(char *fname, size_t len)
1960 #define TEMPLATE "sdccXXXXXX"
1961 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1963 const char *tmpdir = NULL;
1966 if ((tmpdir = getenv ("TMP")) == NULL)
1967 if ((tmpdir = getenv ("TEMP")) == NULL)
1968 tmpdir = getenv ("TMPDIR");
1972 static int warning_emitted;
1977 if (!warning_emitted)
1979 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1980 warning_emitted = 1;
1986 /* try with /usr/tmp and /tmp on Un*x systems */
1987 struct stat statbuf;
1989 if (tmpdir == NULL) {
1990 if (stat("/usr/tmp", &statbuf) != -1)
1991 tmpdir = "/usr/tmp";
1992 else if (stat("/tmp", &statbuf) != -1)
2000 char fnamebuf[PATH_MAX];
2003 if (fname == NULL || len == 0) {
2005 len = sizeof fnamebuf;
2009 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
2011 assert(name_len < len);
2012 if (!(name_len < len)) /* in NDEBUG is defined */
2013 return -1; /* buffer too small, temporary file can not be created */
2015 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
2018 name_len = TEMPLATE_LEN;
2020 assert(name_len < len);
2021 if (!(name_len < len)) /* in NDEBUG is defined */
2022 return -1; /* buffer too small, temporary file can not be created */
2024 strcpy(fname, TEMPLATE);
2027 fd = mkstemp(fname);
2031 char *name = tempnam(tmpdir, "sdcc");
2034 perror("Can't create temporary file name");
2038 assert(strlen(name) < len);
2039 if (!(strlen(name) < len)) /* in NDEBUG is defined */
2040 return -1; /* buffer too small, temporary file can not be created */
2042 strcpy(fname, name);
2044 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2046 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2052 perror("Can't create temporary file");
2060 /** Create a temporary file name
2066 static char fnamebuf[PATH_MAX];
2068 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2069 fprintf(stderr, "Can't create temporary file name!");
2080 /** Create a temporary file and add it to tmpfileNameSet,
2081 so that it is removed explicitly by rm_tmpfiles()
2082 or implicitly at program extit.
2090 char fnamebuf[PATH_MAX];
2092 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2093 fprintf(stderr, "Can't create temporary file!");
2097 tmp = Safe_strdup(fnamebuf);
2099 addSetHead(&tmpfileNameSet, tmp);
2101 if ((fp = fdopen(fd, "w+b")) == NULL) {
2102 perror("Can't create temporary file!");