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));
365 int size = getSize (sym->type) + sym->flexArrayLength;
367 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
371 fprintf (map->oFile, "==.\n");
373 if (IS_STATIC (sym->etype) || sym->level)
374 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
376 tfprintf (map->oFile, "!labeldef\n", sym->rname);
377 tfprintf (map->oFile, "\t!ds\n",
378 (unsigned int) size & 0xffff);
383 /*-----------------------------------------------------------------*/
384 /* initPointer - pointer initialization code massaging */
385 /*-----------------------------------------------------------------*/
387 initPointer (initList * ilist, sym_link *toType)
393 return valCastLiteral(toType, 0.0);
396 expr = list2expr (ilist);
401 /* try it the old way first */
402 if ((val = constExprValue (expr, FALSE)))
405 /* ( ptr + constant ) */
406 if (IS_AST_OP (expr) &&
407 (expr->opval.op == '+' || expr->opval.op == '-') &&
408 IS_AST_SYM_VALUE (expr->left) &&
409 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
410 compareType(toType, expr->left->ftype) &&
411 IS_AST_LIT_VALUE (expr->right)) {
412 return valForCastAggr (expr->left, expr->left->ftype,
418 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
419 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
420 if (compareType(toType, expr->left->ftype)!=1) {
421 werror (W_INIT_WRONG);
422 printFromToType(expr->left->ftype, toType);
428 /* no then we have to do these cludgy checks */
429 /* pointers can be initialized with address of
430 a variable or address of an array element */
431 if (IS_AST_OP (expr) && expr->opval.op == '&') {
432 /* address of symbol */
433 if (IS_AST_SYM_VALUE (expr->left)) {
434 val = AST_VALUE (expr->left);
435 val->type = newLink (DECLARATOR);
436 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
437 DCL_TYPE (val->type) = CPOINTER;
438 DCL_PTR_CONST (val->type) = port->mem.code_ro;
440 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
441 DCL_TYPE (val->type) = FPOINTER;
442 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
443 DCL_TYPE (val->type) = PPOINTER;
444 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
445 DCL_TYPE (val->type) = IPOINTER;
446 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
447 DCL_TYPE (val->type) = EEPPOINTER;
449 DCL_TYPE (val->type) = POINTER;
450 val->type->next = expr->left->ftype;
451 val->etype = getSpec (val->type);
455 /* if address of indexed array */
456 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
457 return valForArray (expr->left);
459 /* if address of structure element then
461 if (IS_AST_OP (expr->left) &&
462 expr->left->opval.op == '.') {
463 return valForStructElem (expr->left->left,
468 (&some_struct)->element */
469 if (IS_AST_OP (expr->left) &&
470 expr->left->opval.op == PTR_OP &&
471 IS_ADDRESS_OF_OP (expr->left->left)) {
472 return valForStructElem (expr->left->left->left,
476 /* case 3. (((char *) &a) +/- constant) */
477 if (IS_AST_OP (expr) &&
478 (expr->opval.op == '+' || expr->opval.op == '-') &&
479 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
480 IS_AST_OP (expr->left->right) &&
481 expr->left->right->opval.op == '&' &&
482 IS_AST_LIT_VALUE (expr->right)) {
484 return valForCastAggr (expr->left->right->left,
485 expr->left->left->opval.lnk,
486 expr->right, expr->opval.op);
489 /* case 4. (char *)(array type) */
490 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
491 IS_ARRAY(expr->right->ftype)) {
493 val = copyValue (AST_VALUE (expr->right));
494 val->type = newLink (DECLARATOR);
495 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
496 DCL_TYPE (val->type) = CPOINTER;
497 DCL_PTR_CONST (val->type) = port->mem.code_ro;
499 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
500 DCL_TYPE (val->type) = FPOINTER;
501 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
502 DCL_TYPE (val->type) = PPOINTER;
503 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
504 DCL_TYPE (val->type) = IPOINTER;
505 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
506 DCL_TYPE (val->type) = EEPPOINTER;
508 DCL_TYPE (val->type) = POINTER;
509 val->type->next = expr->right->ftype->next;
510 val->etype = getSpec (val->type);
515 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
517 werror (E_INCOMPAT_PTYPES);
522 /*-----------------------------------------------------------------*/
523 /* printChar - formats and prints a characater string with DB */
524 /*-----------------------------------------------------------------*/
526 printChar (FILE * ofile, char *s, int plen)
534 while (len && pplen < plen)
537 while (i && pplen < plen)
539 if (*s < ' ' || *s == '\"' || *s=='\\')
543 tfprintf (ofile, "\t!ascii\n", buf);
544 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
559 tfprintf (ofile, "\t!ascii\n", buf);
570 tfprintf (ofile, "\t!db !constbyte\n", 0);
575 /*-----------------------------------------------------------------*/
576 /* return the generic pointer high byte for a given pointer type. */
577 /*-----------------------------------------------------------------*/
579 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
587 werror (E_CANNOT_USE_GENERIC_POINTER,
588 iname ? iname : "<null>",
589 oname ? oname : "<null>");
596 return GPTYPE_XSTACK;
598 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
606 /*-----------------------------------------------------------------*/
607 /* printPointerType - generates ival for pointer type */
608 /*-----------------------------------------------------------------*/
610 _printPointerType (FILE * oFile, const char *name)
612 if (options.model == MODEL_FLAT24)
614 if (port->little_endian)
615 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
617 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
621 if (port->little_endian)
622 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
624 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
628 /*-----------------------------------------------------------------*/
629 /* printPointerType - generates ival for pointer type */
630 /*-----------------------------------------------------------------*/
632 printPointerType (FILE * oFile, const char *name)
634 _printPointerType (oFile, name);
635 fprintf (oFile, "\n");
638 /*-----------------------------------------------------------------*/
639 /* printGPointerType - generates ival for generic pointer type */
640 /*-----------------------------------------------------------------*/
642 printGPointerType (FILE * oFile, const char *iname, const char *oname,
643 const unsigned int type)
645 _printPointerType (oFile, iname);
646 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
649 /*-----------------------------------------------------------------*/
650 /* printIvalType - generates ival for int/char */
651 /*-----------------------------------------------------------------*/
653 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
657 /* if initList is deep */
658 if (ilist && (ilist->type == INIT_DEEP))
659 ilist = ilist->init.deep;
661 if (!(val = list2val (ilist))) {
662 // assuming a warning has been thrown
666 if (val->type != type) {
667 val = valCastLiteral(type, floatFromVal(val));
670 switch (getSize (type)) {
673 tfprintf (oFile, "\t!db !constbyte\n", 0);
675 tfprintf (oFile, "\t!dbs\n",
676 aopLiteral (val, 0));
680 if (port->use_dw_for_init)
681 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
682 else if (port->little_endian)
683 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
685 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
689 tfprintf (oFile, "\t!dw !constword\n", 0);
690 tfprintf (oFile, "\t!dw !constword\n", 0);
692 else if (port->little_endian) {
693 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
694 aopLiteral (val, 0), aopLiteral (val, 1),
695 aopLiteral (val, 2), aopLiteral (val, 3));
698 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
699 aopLiteral (val, 3), aopLiteral (val, 2),
700 aopLiteral (val, 1), aopLiteral (val, 0));
706 /*-----------------------------------------------------------------*/
707 /* printIvalBitFields - generate initializer for bitfields */
708 /*-----------------------------------------------------------------*/
709 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
713 initList *lilist = *ilist ;
714 unsigned long ival = 0;
720 val = list2val(lilist);
722 if (SPEC_BLEN(lsym->etype) > 8) {
723 size += ((SPEC_BLEN (lsym->etype) / 8) +
724 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
727 size = ((SPEC_BLEN (lsym->etype) / 8) +
728 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
730 i = (unsigned long)floatFromVal(val);
731 i <<= SPEC_BSTR (lsym->etype);
733 if (! ( lsym->next &&
734 (IS_BITFIELD(lsym->next->type)) &&
735 (SPEC_BSTR(lsym->next->etype)))) break;
737 lilist = lilist->next;
741 tfprintf (oFile, "\t!db !constbyte\n",ival);
745 tfprintf (oFile, "\t!dw !constword\n",ival);
747 case 4: /* EEP: why is this db and not dw? */
748 tfprintf (oFile, "\t!db !constword,!constword\n",
749 (ival >> 8) & 0xffff, (ival & 0xffff));
756 /*-----------------------------------------------------------------*/
757 /* printIvalStruct - generates initial value for structures */
758 /*-----------------------------------------------------------------*/
760 printIvalStruct (symbol * sym, sym_link * type,
761 initList * ilist, FILE * oFile)
764 initList *iloop = NULL;
766 sflds = SPEC_STRUCT (type)->fields;
769 if (ilist->type != INIT_DEEP) {
770 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
774 iloop = ilist->init.deep;
777 if (SPEC_STRUCT (type)->type == UNION) {
778 printIval (sym, sflds->type, iloop, oFile);
781 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
782 if (IS_BITFIELD(sflds->type)) {
783 printIvalBitFields(&sflds,&iloop,oFile);
785 printIval (sym, sflds->type, iloop, oFile);
790 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
795 /*-----------------------------------------------------------------*/
796 /* printIvalChar - generates initital value for character array */
797 /*-----------------------------------------------------------------*/
799 printIvalChar (symbol * sym, sym_link * type, initList * ilist, FILE * oFile, char *s)
802 unsigned int size = DCL_ELEM (type);
806 val = list2val (ilist);
807 /* if the value is a character string */
808 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
812 /* we have not been given a size, but now we know it */
813 size = strlen (SPEC_CVAL (val->etype).v_char) + 1;
814 /* but first check, if it's a flexible array */
815 if (sym && IS_STRUCT (sym->type))
816 sym->flexArrayLength = size;
818 DCL_ELEM (type) = size;
821 printChar (oFile, SPEC_CVAL (val->etype).v_char, size);
829 printChar (oFile, s, strlen (s) + 1);
833 /*-----------------------------------------------------------------*/
834 /* printIvalArray - generates code for array initialization */
835 /*-----------------------------------------------------------------*/
837 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
842 unsigned int size = 0;
845 /* take care of the special case */
846 /* array of characters can be init */
848 if (IS_CHAR (type->next)) {
849 val = list2val(ilist);
851 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
854 if (!IS_LITERAL(val->etype)) {
855 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
858 if (printIvalChar (sym, type,
859 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
860 oFile, SPEC_CVAL (sym->etype).v_char))
863 /* not the special case */
864 if (ilist->type != INIT_DEEP) {
865 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
869 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
870 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
871 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
874 printIval (sym, type->next, iloop, oFile);
878 if (DCL_ELEM(type)) {
879 // pad with zeros if needed
880 if (size<DCL_ELEM(type)) {
881 size = (DCL_ELEM(type) - size) * getSize(type->next);
883 tfprintf (oFile, "\t!db !constbyte\n", 0);
887 /* we have not been given a size, but now we know it */
888 /* but first check, if it's a flexible array */
889 if (IS_STRUCT (sym->type))
890 sym->flexArrayLength = size * getSize (type->next);
892 DCL_ELEM (type) = size;
898 /*-----------------------------------------------------------------*/
899 /* printIvalFuncPtr - generate initial value for function pointers */
900 /*-----------------------------------------------------------------*/
902 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
908 val = list2val (ilist);
910 val = valCastLiteral(type, 0.0);
913 // an error has been thrown already
917 if (IS_LITERAL(val->etype)) {
918 if (compareType(type, val->etype) == 0) {
919 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
920 printFromToType (val->type, type);
922 printIvalCharPtr (NULL, type, val, oFile);
926 /* check the types */
927 if ((dLvl = compareType (val->type, type->next)) <= 0)
929 tfprintf (oFile, "\t!dw !constword\n", 0);
933 /* now generate the name */
936 if (port->use_dw_for_init)
938 tfprintf (oFile, "\t!dws\n", val->name);
942 printPointerType (oFile, val->name);
945 else if (port->use_dw_for_init)
947 tfprintf (oFile, "\t!dws\n", val->sym->rname);
951 printPointerType (oFile, val->sym->rname);
957 /*-----------------------------------------------------------------*/
958 /* printIvalCharPtr - generates initial values for character pointers */
959 /*-----------------------------------------------------------------*/
961 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
965 /* PENDING: this is _very_ mcs51 specific, including a magic
967 It's also endin specific.
969 size = getSize (type);
971 if (val->name && strlen (val->name))
973 if (size == 1) /* This appears to be Z80 specific?? */
976 "\t!dbs\n", val->name);
978 else if (size == FPTRSIZE)
980 if (port->use_dw_for_init)
982 tfprintf (oFile, "\t!dws\n", val->name);
986 printPointerType (oFile, val->name);
989 else if (size == GPTRSIZE)
992 if (IS_PTR (val->type)) {
993 type = DCL_TYPE (val->type);
995 type = PTR_TYPE (SPEC_OCLS (val->etype));
997 if (val->sym && val->sym->isstrlit) {
998 // this is a literal string
1001 printGPointerType (oFile, val->name, sym->name, type);
1005 fprintf (stderr, "*** internal error: unknown size in "
1006 "printIvalCharPtr.\n");
1011 // these are literals assigned to pointers
1015 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
1018 if (port->use_dw_for_init)
1019 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
1020 else if (port->little_endian)
1021 tfprintf (oFile, "\t.byte %s,%s\n",
1022 aopLiteral (val, 0), aopLiteral (val, 1));
1024 tfprintf (oFile, "\t.byte %s,%s\n",
1025 aopLiteral (val, 1), aopLiteral (val, 0));
1028 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1029 // non-zero mcs51 generic pointer
1030 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1032 if (port->little_endian) {
1033 fprintf (oFile, "\t.byte %s,%s,%s\n",
1034 aopLiteral (val, 0),
1035 aopLiteral (val, 1),
1036 aopLiteral (val, 2));
1038 fprintf (oFile, "\t.byte %s,%s,%s\n",
1039 aopLiteral (val, 2),
1040 aopLiteral (val, 1),
1041 aopLiteral (val, 0));
1045 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1046 // non-zero ds390 generic pointer
1047 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1049 if (port->little_endian) {
1050 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1051 aopLiteral (val, 0),
1052 aopLiteral (val, 1),
1053 aopLiteral (val, 2),
1054 aopLiteral (val, 3));
1056 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1057 aopLiteral (val, 3),
1058 aopLiteral (val, 2),
1059 aopLiteral (val, 1),
1060 aopLiteral (val, 0));
1068 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1069 addSet (&statsg->syms, val->sym);
1075 /*-----------------------------------------------------------------*/
1076 /* printIvalPtr - generates initial value for pointers */
1077 /*-----------------------------------------------------------------*/
1079 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1085 if (ilist && (ilist->type == INIT_DEEP))
1086 ilist = ilist->init.deep;
1088 /* function pointer */
1089 if (IS_FUNC (type->next))
1091 printIvalFuncPtr (type, ilist, oFile);
1095 if (!(val = initPointer (ilist, type)))
1098 /* if character pointer */
1099 if (IS_CHAR (type->next))
1100 if (printIvalCharPtr (sym, type, val, oFile))
1103 /* check the type */
1104 if (compareType (type, val->type) == 0) {
1105 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1106 printFromToType (val->type, type);
1109 /* if val is literal */
1110 if (IS_LITERAL (val->etype))
1112 switch (getSize (type))
1115 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1118 if (port->use_dw_for_init)
1119 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1120 else if (port->little_endian)
1121 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1123 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1125 case 3: // how about '390??
1126 fprintf (oFile, "; generic printIvalPtr\n");
1127 if (port->little_endian)
1129 fprintf (oFile, "\t.byte %s,%s",
1130 aopLiteral (val, 0), aopLiteral (val, 1));
1134 fprintf (oFile, "\t.byte %s,%s",
1135 aopLiteral (val, 1), aopLiteral (val, 0));
1137 if (IS_GENPTR (val->type))
1138 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1139 else if (IS_PTR (val->type))
1140 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1142 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1148 size = getSize (type);
1150 if (size == 1) /* Z80 specific?? */
1152 tfprintf (oFile, "\t!dbs\n", val->name);
1154 else if (size == FPTRSIZE)
1156 if (port->use_dw_for_init) {
1157 tfprintf (oFile, "\t!dws\n", val->name);
1159 printPointerType (oFile, val->name);
1162 else if (size == GPTRSIZE)
1164 printGPointerType (oFile, val->name, sym->name,
1165 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1166 PTR_TYPE (SPEC_OCLS (val->etype))));
1171 /*-----------------------------------------------------------------*/
1172 /* printIval - generates code for initial value */
1173 /*-----------------------------------------------------------------*/
1175 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1179 /* if structure then */
1180 if (IS_STRUCT (type))
1182 printIvalStruct (sym, type, ilist, oFile);
1186 /* if this is an array */
1187 if (IS_ARRAY (type))
1189 printIvalArray (sym, type, ilist, oFile);
1195 // not an aggregate, ilist must be a node
1196 if (ilist->type!=INIT_NODE) {
1197 // or a 1-element list
1198 if (ilist->init.deep->next) {
1199 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1202 ilist=ilist->init.deep;
1206 // and the type must match
1207 itype=ilist->init.node->ftype;
1209 if (compareType(type, itype)==0) {
1210 // special case for literal strings
1211 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1212 // which are really code pointers
1213 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1216 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1217 printFromToType(itype, type);
1222 /* if this is a pointer */
1225 printIvalPtr (sym, type, ilist, oFile);
1229 /* if type is SPECIFIER */
1232 printIvalType (sym, type, ilist, oFile);
1237 /*-----------------------------------------------------------------*/
1238 /* emitStaticSeg - emitcode for the static segment */
1239 /*-----------------------------------------------------------------*/
1241 emitStaticSeg (memmap * map, FILE * out)
1245 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1247 /* for all variables in this segment do */
1248 for (sym = setFirstItem (map->syms); sym;
1249 sym = setNextItem (map->syms))
1252 /* if it is "extern" then do nothing */
1253 if (IS_EXTERN (sym->etype))
1256 /* if it is not static add it to the public table */
1257 if (!IS_STATIC (sym->etype))
1259 addSetHead (&publics, sym);
1262 /* print extra debug info if required */
1263 if (options.debug) {
1267 if (IS_STATIC (sym->etype))
1268 fprintf (out, "F%s$", moduleName); /* scope is file */
1270 fprintf (out, "G$"); /* scope is global */
1273 /* symbol is local */
1274 fprintf (out, "L%s$",
1275 (sym->localof ? sym->localof->name : "-null-"));
1276 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1279 /* if it has an absolute address and no initializer */
1280 if (SPEC_ABSA (sym->etype) && !sym->ival)
1283 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1285 fprintf (out, "%s\t=\t0x%04x\n",
1287 SPEC_ADDR (sym->etype));
1292 fprintf (out, " == .\n");
1294 /* if it has an initial value */
1297 if (SPEC_ABSA (sym->etype))
1299 tfprintf (out, "\t!org\n", SPEC_ADDR (sym->etype));
1301 fprintf (out, "%s:\n", sym->rname);
1303 resolveIvalSym (sym->ival, sym->type);
1304 printIval (sym, sym->type, sym->ival, out);
1306 /* if sym is a simple string and sym->ival is a string,
1307 WE don't need it anymore */
1308 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1309 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1310 list2val(sym->ival)->sym->isstrlit) {
1311 freeStringSymbol(list2val(sym->ival)->sym);
1315 /* allocate space */
1316 int size = getSize (sym->type);
1319 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1321 fprintf (out, "%s:\n", sym->rname);
1322 /* special case for character strings */
1323 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1324 SPEC_CVAL (sym->etype).v_char)
1326 SPEC_CVAL (sym->etype).v_char,
1329 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1335 /*-----------------------------------------------------------------*/
1336 /* emitMaps - emits the code for the data portion the code */
1337 /*-----------------------------------------------------------------*/
1341 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1342 /* ports but let's be conservative - EEP */
1345 /* no special considerations for the following
1346 data, idata & bit & xdata */
1347 emitRegularMap (data, TRUE, TRUE);
1348 emitRegularMap (idata, TRUE, TRUE);
1349 emitRegularMap (bit, TRUE, TRUE);
1350 emitRegularMap (pdata, TRUE, TRUE);
1351 emitRegularMap (xdata, TRUE, TRUE);
1352 if (port->genXINIT) {
1353 emitRegularMap (xidata, TRUE, TRUE);
1355 emitRegularMap (sfr, publicsfr, FALSE);
1356 emitRegularMap (sfrbit, publicsfr, FALSE);
1357 emitRegularMap (home, TRUE, FALSE);
1358 emitRegularMap (code, TRUE, FALSE);
1360 if (options.const_seg) {
1361 tfprintf (code->oFile, "\t!area\n", options.const_seg);
1363 emitStaticSeg (statsg, code->oFile);
1364 if (port->genXINIT) {
1365 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1366 emitStaticSeg (xinit, code->oFile);
1368 tfprintf (code->oFile, "\t!area\n", c_abs->sname);
1369 emitStaticSeg (c_abs, code->oFile);
1373 /*-----------------------------------------------------------------*/
1374 /* flushStatics - flush all currently defined statics out to file */
1375 /* and delete. Temporary function */
1376 /*-----------------------------------------------------------------*/
1380 emitStaticSeg (statsg, codeOutFile);
1381 statsg->syms = NULL;
1384 /*-----------------------------------------------------------------*/
1385 /* createInterruptVect - creates the interrupt vector */
1386 /*-----------------------------------------------------------------*/
1388 createInterruptVect (FILE * vFile)
1390 mainf = newSymbol ("main", 0);
1393 /* only if the main function exists */
1394 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1396 if (!options.cc_only && !noAssemble && !options.c1mode)
1401 /* if the main is only a prototype ie. no body then do nothing */
1402 if (!IFFUNC_HASBODY(mainf->type))
1404 /* if ! compile only then main function should be present */
1405 if (!options.cc_only && !noAssemble)
1410 tfprintf (vFile, "\t!areacode\n", HOME_NAME);
1411 fprintf (vFile, "__interrupt_vect:\n");
1414 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1416 /* There's no such thing as a "generic" interrupt table header. */
1423 ";--------------------------------------------------------\n"
1424 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1428 ";--------------------------------------------------------\n"};
1431 /*-----------------------------------------------------------------*/
1432 /* initialComments - puts in some initial comments */
1433 /*-----------------------------------------------------------------*/
1435 initialComments (FILE * afile)
1439 fprintf (afile, "%s", iComments1);
1440 fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber(), __DATE__);
1441 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1442 fprintf (afile, "%s", iComments2);
1445 /*-----------------------------------------------------------------*/
1446 /* printPublics - generates .global for publics */
1447 /*-----------------------------------------------------------------*/
1449 printPublics (FILE * afile)
1453 fprintf (afile, "%s", iComments2);
1454 fprintf (afile, "; Public variables in this module\n");
1455 fprintf (afile, "%s", iComments2);
1457 for (sym = setFirstItem (publics); sym;
1458 sym = setNextItem (publics))
1459 tfprintf (afile, "\t!global\n", sym->rname);
1462 /*-----------------------------------------------------------------*/
1463 /* printExterns - generates .global for externs */
1464 /*-----------------------------------------------------------------*/
1466 printExterns (FILE * afile)
1470 fprintf (afile, "%s", iComments2);
1471 fprintf (afile, "; Externals used\n");
1472 fprintf (afile, "%s", iComments2);
1474 for (sym = setFirstItem (externs); sym;
1475 sym = setNextItem (externs))
1476 tfprintf (afile, "\t!extern\n", sym->rname);
1479 /*-----------------------------------------------------------------*/
1480 /* emitOverlay - will emit code for the overlay stuff */
1481 /*-----------------------------------------------------------------*/
1483 emitOverlay (FILE * afile)
1487 if (!elementsInSet (ovrSetSets))
1488 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1490 /* for each of the sets in the overlay segment do */
1491 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1492 ovrset = setNextItem (ovrSetSets))
1497 if (elementsInSet (ovrset))
1499 /* output the area informtion */
1500 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1503 for (sym = setFirstItem (ovrset); sym;
1504 sym = setNextItem (ovrset))
1506 /* if extern then it is in the publics table: do nothing */
1507 if (IS_EXTERN (sym->etype))
1510 /* if allocation required check is needed
1511 then check if the symbol really requires
1512 allocation only for local variables */
1513 if (!IS_AGGREGATE (sym->type) &&
1514 !(sym->_isparm && !IS_REGPARM (sym->etype))
1515 && !sym->allocreq && sym->level)
1518 /* if global variable & not static or extern
1519 and addPublics allowed then add it to the public set */
1520 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1521 && !IS_STATIC (sym->etype))
1523 addSetHead (&publics, sym);
1526 /* if extern then do nothing or is a function
1528 if (IS_FUNC (sym->type))
1531 /* print extra debug info if required */
1536 if (IS_STATIC (sym->etype))
1537 fprintf (afile, "F%s$", moduleName); /* scope is file */
1539 fprintf (afile, "G$"); /* scope is global */
1542 /* symbol is local */
1543 fprintf (afile, "L%s$",
1544 (sym->localof ? sym->localof->name : "-null-"));
1545 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1548 /* if is has an absolute address then generate
1549 an equate for this no need to allocate space */
1550 if (SPEC_ABSA (sym->etype))
1554 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1556 fprintf (afile, "%s\t=\t0x%04x\n",
1558 SPEC_ADDR (sym->etype));
1561 int size = getSize(sym->type);
1564 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1567 fprintf (afile, "==.\n");
1569 /* allocate space */
1570 tfprintf (afile, "!labeldef\n", sym->rname);
1571 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1579 /*-----------------------------------------------------------------*/
1580 /* spacesToUnderscores - replace spaces with underscores */
1581 /*-----------------------------------------------------------------*/
1583 spacesToUnderscores (char *dest, const char *src, size_t len)
1588 assert(dest != NULL);
1589 assert(src != NULL);
1593 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1594 *p++ = isspace((unsigned char)*src) ? '_' : *src;
1602 /*-----------------------------------------------------------------*/
1603 /* glue - the final glue that hold the whole thing together */
1604 /*-----------------------------------------------------------------*/
1610 FILE *ovrFile = tempfile ();
1611 char moduleBuf[PATH_MAX];
1614 if(port->general.glue_up_main &&
1615 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1617 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1624 addSetHead (&tmpfileSet, ovrFile);
1625 /* print the global struct definitions */
1629 vFile = tempfile ();
1630 /* PENDING: this isn't the best place but it will do */
1631 if (port->general.glue_up_main)
1633 /* create the interrupt vector table */
1634 createInterruptVect (vFile);
1637 addSetHead (&tmpfileSet, vFile);
1639 /* emit code for the all the variables declared */
1641 /* do the overlay segments */
1642 emitOverlay (ovrFile);
1644 outputDebugSymbols();
1646 /* now put it all together into the assembler file */
1647 /* create the assembler file name */
1649 /* -o option overrides default name? */
1650 if ((noAssemble || options.c1mode) && fullDstFileName)
1652 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1656 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1657 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1660 if (!(asmFile = fopen (scratchFileName, "w")))
1662 werror (E_FILE_OPEN_ERR, scratchFileName);
1666 /* initial comments */
1667 initialComments (asmFile);
1669 /* print module name */
1670 tfprintf (asmFile, "\t!module\n",
1671 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1674 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1676 switch(options.model)
1678 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1679 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1680 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1681 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1682 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1683 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1686 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1687 if(options.useXstack) fprintf (asmFile, " --xstack");
1688 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1689 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1690 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1691 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1692 fprintf (asmFile, "\n");
1694 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1696 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1699 tfprintf (asmFile, "\t!fileprelude\n");
1701 /* Let the port generate any global directives, etc. */
1702 if (port->genAssemblerPreamble)
1704 port->genAssemblerPreamble (asmFile);
1707 /* print the global variables in this module */
1708 printPublics (asmFile);
1709 if (port->assembler.externGlobal)
1710 printExterns (asmFile);
1713 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1715 /* copy the sfr segment */
1716 fprintf (asmFile, "%s", iComments2);
1717 fprintf (asmFile, "; special function registers\n");
1718 fprintf (asmFile, "%s", iComments2);
1719 copyFile (asmFile, sfr->oFile);
1724 /* copy the sbit segment */
1725 fprintf (asmFile, "%s", iComments2);
1726 fprintf (asmFile, "; special function bits\n");
1727 fprintf (asmFile, "%s", iComments2);
1728 copyFile (asmFile, sfrbit->oFile);
1730 /*JCF: Create the areas for the register banks*/
1731 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1733 fprintf (asmFile, "%s", iComments2);
1734 fprintf (asmFile, "; overlayable register banks\n");
1735 fprintf (asmFile, "%s", iComments2);
1737 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1738 if(RegBankUsed[1]||options.parms_in_bank1)
1739 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1741 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1743 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1747 fprintf (asmFile, "%s", iComments2);
1748 fprintf (asmFile, "; overlayable bit register bank\n");
1749 fprintf (asmFile, "%s", iComments2);
1750 fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
1751 fprintf (asmFile, "bits:\n\t.ds 1\n");
1752 fprintf (asmFile, "\tb0 = bits[0]\n");
1753 fprintf (asmFile, "\tb1 = bits[1]\n");
1754 fprintf (asmFile, "\tb2 = bits[2]\n");
1755 fprintf (asmFile, "\tb3 = bits[3]\n");
1756 fprintf (asmFile, "\tb4 = bits[4]\n");
1757 fprintf (asmFile, "\tb5 = bits[5]\n");
1758 fprintf (asmFile, "\tb6 = bits[6]\n");
1759 fprintf (asmFile, "\tb7 = bits[7]\n");
1763 /* copy the data segment */
1764 fprintf (asmFile, "%s", iComments2);
1765 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1766 fprintf (asmFile, "%s", iComments2);
1767 copyFile (asmFile, data->oFile);
1770 /* create the overlay segments */
1772 fprintf (asmFile, "%s", iComments2);
1773 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1774 fprintf (asmFile, "%s", iComments2);
1775 copyFile (asmFile, ovrFile);
1778 /* create the stack segment MOF */
1779 if (mainf && IFFUNC_HASBODY(mainf->type))
1781 fprintf (asmFile, "%s", iComments2);
1782 fprintf (asmFile, "; Stack segment in internal ram \n");
1783 fprintf (asmFile, "%s", iComments2);
1784 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1785 "__start__stack:\n\t.ds\t1\n\n");
1788 /* create the idata segment */
1789 if ( (idata) && (mcs51_like) ) {
1790 fprintf (asmFile, "%s", iComments2);
1791 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1792 fprintf (asmFile, "%s", iComments2);
1793 copyFile (asmFile, idata->oFile);
1796 /* copy the bit segment */
1798 fprintf (asmFile, "%s", iComments2);
1799 fprintf (asmFile, "; bit data\n");
1800 fprintf (asmFile, "%s", iComments2);
1801 copyFile (asmFile, bit->oFile);
1804 /* copy paged external ram data */
1807 fprintf (asmFile, "%s", iComments2);
1808 fprintf (asmFile, "; paged external ram data\n");
1809 fprintf (asmFile, "%s", iComments2);
1810 copyFile (asmFile, pdata->oFile);
1813 /* if external stack then reserve space for it */
1814 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1816 fprintf (asmFile, "%s", iComments2);
1817 fprintf (asmFile, "; external stack \n");
1818 fprintf (asmFile, "%s", iComments2);
1819 fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
1820 "__start__xstack:\n\t.ds\t1\n\n");
1823 /* copy external ram data */
1825 fprintf (asmFile, "%s", iComments2);
1826 fprintf (asmFile, "; external ram data\n");
1827 fprintf (asmFile, "%s", iComments2);
1828 copyFile (asmFile, xdata->oFile);
1831 /* copy external initialized ram data */
1832 fprintf (asmFile, "%s", iComments2);
1833 fprintf (asmFile, "; external initialized ram data\n");
1834 fprintf (asmFile, "%s", iComments2);
1835 copyFile (asmFile, xidata->oFile);
1837 /* If the port wants to generate any extra areas, let it do so. */
1838 if (port->extraAreas.genExtraAreaDeclaration)
1840 port->extraAreas.genExtraAreaDeclaration(asmFile,
1841 mainf && IFFUNC_HASBODY(mainf->type));
1844 /* copy the interrupt vector table */
1845 if (mainf && IFFUNC_HASBODY(mainf->type))
1847 fprintf (asmFile, "%s", iComments2);
1848 fprintf (asmFile, "; interrupt vector \n");
1849 fprintf (asmFile, "%s", iComments2);
1850 copyFile (asmFile, vFile);
1853 /* copy global & static initialisations */
1854 fprintf (asmFile, "%s", iComments2);
1855 fprintf (asmFile, "; global & static initialisations\n");
1856 fprintf (asmFile, "%s", iComments2);
1858 /* Everywhere we generate a reference to the static_name area,
1859 * (which is currently only here), we immediately follow it with a
1860 * definition of the post_static_name area. This guarantees that
1861 * the post_static_name area will immediately follow the static_name
1864 tfprintf (asmFile, "\t!area\n", port->mem.home_name);
1865 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1866 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1867 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1869 if (mainf && IFFUNC_HASBODY(mainf->type))
1871 if (port->genInitStartup)
1873 port->genInitStartup(asmFile);
1877 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1878 /* if external stack is specified then the
1879 higher order byte of the xdatalocation is
1880 going into P2 and the lower order going into
1882 if (options.useXstack)
1884 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1885 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1886 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1887 (unsigned int) options.xdata_loc & 0xff);
1890 // This should probably be a port option, but I'm being lazy.
1891 // on the 400, the firmware boot loader gives us a valid stack
1892 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1893 if (!TARGET_IS_DS400)
1895 /* initialise the stack pointer. JCF: aslink takes care of the location */
1896 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1899 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1900 fprintf (asmFile, "\tmov\ta,dpl\n");
1901 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1902 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1903 fprintf (asmFile, "__sdcc_init_data:\n");
1905 // if the port can copy the XINIT segment to XISEG
1908 port->genXINIT(asmFile);
1913 copyFile (asmFile, statsg->oFile);
1915 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1917 /* This code is generated in the post-static area.
1918 * This area is guaranteed to follow the static area
1919 * by the ugly shucking and jiving about 20 lines ago.
1921 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1922 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1928 "%s", iComments2, iComments2);
1929 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1930 copyFile (asmFile, home->oFile);
1932 if (mainf && IFFUNC_HASBODY(mainf->type))
1934 /* entry point @ start of HOME */
1935 fprintf (asmFile, "__sdcc_program_startup:\n");
1937 /* put in jump or call to main */
1938 if (options.mainreturn)
1940 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1941 fprintf (asmFile, ";\treturn from main will return to caller\n");
1945 fprintf (asmFile, "\tlcall\t_main\n");
1946 fprintf (asmFile, ";\treturn from main will lock up\n");
1947 fprintf (asmFile, "\tsjmp .\n");
1950 /* copy over code */
1951 fprintf (asmFile, "%s", iComments2);
1952 fprintf (asmFile, "; code\n");
1953 fprintf (asmFile, "%s", iComments2);
1954 tfprintf (asmFile, "\t!areacode\n", options.code_seg);
1955 copyFile (asmFile, code->oFile);
1957 if (port->genAssemblerEnd) {
1958 port->genAssemblerEnd(asmFile);
1966 /** Creates a temporary file with unique file name
1968 - TMP, TEMP, TMPDIR env. variables
1969 - if Un*x system: /usr/tmp and /tmp
1970 - root directory using mkstemp() if available
1971 - default location using tempnam()
1974 tempfileandname(char *fname, size_t len)
1976 #define TEMPLATE "sdccXXXXXX"
1977 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1979 const char *tmpdir = NULL;
1982 if ((tmpdir = getenv ("TMP")) == NULL)
1983 if ((tmpdir = getenv ("TEMP")) == NULL)
1984 tmpdir = getenv ("TMPDIR");
1988 static int warning_emitted;
1993 if (!warning_emitted)
1995 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1996 warning_emitted = 1;
2002 /* try with /usr/tmp and /tmp on Un*x systems */
2003 struct stat statbuf;
2005 if (tmpdir == NULL) {
2006 if (stat("/usr/tmp", &statbuf) != -1)
2007 tmpdir = "/usr/tmp";
2008 else if (stat("/tmp", &statbuf) != -1)
2016 char fnamebuf[PATH_MAX];
2019 if (fname == NULL || len == 0) {
2021 len = sizeof fnamebuf;
2025 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
2027 assert(name_len < len);
2028 if (!(name_len < len)) /* in NDEBUG is defined */
2029 return -1; /* buffer too small, temporary file can not be created */
2031 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
2034 name_len = TEMPLATE_LEN;
2036 assert(name_len < len);
2037 if (!(name_len < len)) /* in NDEBUG is defined */
2038 return -1; /* buffer too small, temporary file can not be created */
2040 strcpy(fname, TEMPLATE);
2043 fd = mkstemp(fname);
2047 char *name = tempnam(tmpdir, "sdcc");
2050 perror("Can't create temporary file name");
2054 assert(strlen(name) < len);
2055 if (!(strlen(name) < len)) /* in NDEBUG is defined */
2056 return -1; /* buffer too small, temporary file can not be created */
2058 strcpy(fname, name);
2060 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2062 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2068 perror("Can't create temporary file");
2076 /** Create a temporary file name
2082 static char fnamebuf[PATH_MAX];
2084 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2085 fprintf(stderr, "Can't create temporary file name!");
2096 /** Create a temporary file and add it to tmpfileNameSet,
2097 so that it is removed explicitly by rm_tmpfiles()
2098 or implicitly at program extit.
2106 char fnamebuf[PATH_MAX];
2108 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2109 fprintf(stderr, "Can't create temporary file!");
2113 tmp = Safe_strdup(fnamebuf);
2115 addSetHead(&tmpfileNameSet, tmp);
2117 if ((fp = fdopen(fd, "w+b")) == NULL) {
2118 perror("Can't create temporary file!");