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 = getAllocSize (sym->type);
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 (sym_link * type, initList * ilist, FILE * oFile, char *s)
800 val = list2val (ilist);
801 /* if the value is a character string */
802 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
804 if (!DCL_ELEM (type))
805 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
807 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
815 printChar (oFile, s, strlen (s) + 1);
819 /*-----------------------------------------------------------------*/
820 /* printIvalArray - generates code for array initialization */
821 /*-----------------------------------------------------------------*/
823 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
827 unsigned int size = 0;
830 /* take care of the special case */
831 /* array of characters can be init */
833 if (IS_CHAR (type->next)) {
834 if (!IS_LITERAL(list2val(ilist)->etype)) {
835 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
838 if (printIvalChar (type,
839 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
840 oFile, SPEC_CVAL (sym->etype).v_char))
843 /* not the special case */
844 if (ilist->type != INIT_DEEP) {
845 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
849 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
850 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
851 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
854 printIval (sym, type->next, iloop, oFile);
858 if (DCL_ELEM(type)) {
859 // pad with zeros if needed
860 if (size<DCL_ELEM(type)) {
861 size = (DCL_ELEM(type) - size) * getSize(type->next);
863 tfprintf (oFile, "\t!db !constbyte\n", 0);
867 // we have not been given a size, but we now know it
868 DCL_ELEM (type) = size;
874 /*-----------------------------------------------------------------*/
875 /* printIvalFuncPtr - generate initial value for function pointers */
876 /*-----------------------------------------------------------------*/
878 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
884 val = list2val (ilist);
886 val = valCastLiteral(type, 0.0);
889 // an error has been thrown already
893 if (IS_LITERAL(val->etype)) {
894 if (compareType(type, val->etype) == 0) {
895 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
896 printFromToType (val->type, type);
898 printIvalCharPtr (NULL, type, val, oFile);
902 /* check the types */
903 if ((dLvl = compareType (val->type, type->next)) <= 0)
905 tfprintf (oFile, "\t!dw !constword\n", 0);
909 /* now generate the name */
912 if (port->use_dw_for_init)
914 tfprintf (oFile, "\t!dws\n", val->name);
918 printPointerType (oFile, val->name);
921 else if (port->use_dw_for_init)
923 tfprintf (oFile, "\t!dws\n", val->sym->rname);
927 printPointerType (oFile, val->sym->rname);
933 /*-----------------------------------------------------------------*/
934 /* printIvalCharPtr - generates initial values for character pointers */
935 /*-----------------------------------------------------------------*/
937 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
941 /* PENDING: this is _very_ mcs51 specific, including a magic
943 It's also endin specific.
945 size = getSize (type);
947 if (val->name && strlen (val->name))
949 if (size == 1) /* This appears to be Z80 specific?? */
952 "\t!dbs\n", val->name);
954 else if (size == FPTRSIZE)
956 if (port->use_dw_for_init)
958 tfprintf (oFile, "\t!dws\n", val->name);
962 printPointerType (oFile, val->name);
965 else if (size == GPTRSIZE)
968 if (IS_PTR (val->type)) {
969 type = DCL_TYPE (val->type);
971 type = PTR_TYPE (SPEC_OCLS (val->etype));
973 if (val->sym && val->sym->isstrlit) {
974 // this is a literal string
977 printGPointerType (oFile, val->name, sym->name, type);
981 fprintf (stderr, "*** internal error: unknown size in "
982 "printIvalCharPtr.\n");
987 // these are literals assigned to pointers
991 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
994 if (port->use_dw_for_init)
995 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
996 else if (port->little_endian)
997 tfprintf (oFile, "\t.byte %s,%s\n",
998 aopLiteral (val, 0), aopLiteral (val, 1));
1000 tfprintf (oFile, "\t.byte %s,%s\n",
1001 aopLiteral (val, 1), aopLiteral (val, 0));
1004 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1005 // non-zero mcs51 generic pointer
1006 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1008 if (port->little_endian) {
1009 fprintf (oFile, "\t.byte %s,%s,%s\n",
1010 aopLiteral (val, 0),
1011 aopLiteral (val, 1),
1012 aopLiteral (val, 2));
1014 fprintf (oFile, "\t.byte %s,%s,%s\n",
1015 aopLiteral (val, 2),
1016 aopLiteral (val, 1),
1017 aopLiteral (val, 0));
1021 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1022 // non-zero ds390 generic pointer
1023 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1025 if (port->little_endian) {
1026 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1027 aopLiteral (val, 0),
1028 aopLiteral (val, 1),
1029 aopLiteral (val, 2),
1030 aopLiteral (val, 3));
1032 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1033 aopLiteral (val, 3),
1034 aopLiteral (val, 2),
1035 aopLiteral (val, 1),
1036 aopLiteral (val, 0));
1044 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1045 addSet (&statsg->syms, val->sym);
1051 /*-----------------------------------------------------------------*/
1052 /* printIvalPtr - generates initial value for pointers */
1053 /*-----------------------------------------------------------------*/
1055 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1061 if (ilist && (ilist->type == INIT_DEEP))
1062 ilist = ilist->init.deep;
1064 /* function pointer */
1065 if (IS_FUNC (type->next))
1067 printIvalFuncPtr (type, ilist, oFile);
1071 if (!(val = initPointer (ilist, type)))
1074 /* if character pointer */
1075 if (IS_CHAR (type->next))
1076 if (printIvalCharPtr (sym, type, val, oFile))
1079 /* check the type */
1080 if (compareType (type, val->type) == 0) {
1081 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1082 printFromToType (val->type, type);
1085 /* if val is literal */
1086 if (IS_LITERAL (val->etype))
1088 switch (getSize (type))
1091 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1094 if (port->use_dw_for_init)
1095 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1096 else if (port->little_endian)
1097 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1099 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1101 case 3: // how about '390??
1102 fprintf (oFile, "; generic printIvalPtr\n");
1103 if (port->little_endian)
1105 fprintf (oFile, "\t.byte %s,%s",
1106 aopLiteral (val, 0), aopLiteral (val, 1));
1110 fprintf (oFile, "\t.byte %s,%s",
1111 aopLiteral (val, 1), aopLiteral (val, 0));
1113 if (IS_GENPTR (val->type))
1114 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1115 else if (IS_PTR (val->type))
1116 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1118 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1124 size = getSize (type);
1126 if (size == 1) /* Z80 specific?? */
1128 tfprintf (oFile, "\t!dbs\n", val->name);
1130 else if (size == FPTRSIZE)
1132 if (port->use_dw_for_init) {
1133 tfprintf (oFile, "\t!dws\n", val->name);
1135 printPointerType (oFile, val->name);
1138 else if (size == GPTRSIZE)
1140 printGPointerType (oFile, val->name, sym->name,
1141 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1142 PTR_TYPE (SPEC_OCLS (val->etype))));
1147 /*-----------------------------------------------------------------*/
1148 /* printIval - generates code for initial value */
1149 /*-----------------------------------------------------------------*/
1151 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1155 /* if structure then */
1156 if (IS_STRUCT (type))
1158 printIvalStruct (sym, type, ilist, oFile);
1162 /* if this is an array */
1163 if (IS_ARRAY (type))
1165 printIvalArray (sym, type, ilist, oFile);
1171 // not an aggregate, ilist must be a node
1172 if (ilist->type!=INIT_NODE) {
1173 // or a 1-element list
1174 if (ilist->init.deep->next) {
1175 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1178 ilist=ilist->init.deep;
1182 // and the type must match
1183 itype=ilist->init.node->ftype;
1185 if (compareType(type, itype)==0) {
1186 // special case for literal strings
1187 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1188 // which are really code pointers
1189 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1192 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1193 printFromToType(itype, type);
1198 /* if this is a pointer */
1201 printIvalPtr (sym, type, ilist, oFile);
1205 /* if type is SPECIFIER */
1208 printIvalType (sym, type, ilist, oFile);
1213 /*-----------------------------------------------------------------*/
1214 /* emitStaticSeg - emitcode for the static segment */
1215 /*-----------------------------------------------------------------*/
1217 emitStaticSeg (memmap * map, FILE * out)
1221 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1223 /* for all variables in this segment do */
1224 for (sym = setFirstItem (map->syms); sym;
1225 sym = setNextItem (map->syms))
1228 /* if it is "extern" then do nothing */
1229 if (IS_EXTERN (sym->etype))
1232 /* if it is not static add it to the public
1234 if (!IS_STATIC (sym->etype))
1236 addSetHead (&publics, sym);
1239 /* print extra debug info if required */
1240 if (options.debug) {
1244 if (IS_STATIC (sym->etype))
1245 fprintf (out, "F%s$", moduleName); /* scope is file */
1247 fprintf (out, "G$"); /* scope is global */
1250 /* symbol is local */
1251 fprintf (out, "L%s$",
1252 (sym->localof ? sym->localof->name : "-null-"));
1253 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1256 /* if it has an absolute address */
1257 if (SPEC_ABSA (sym->etype))
1260 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1262 fprintf (out, "%s\t=\t0x%04x\n",
1264 SPEC_ADDR (sym->etype));
1269 fprintf (out, " == .\n");
1271 /* if it has an initial value */
1274 fprintf (out, "%s:\n", sym->rname);
1276 resolveIvalSym (sym->ival, sym->type);
1277 printIval (sym, sym->type, sym->ival, out);
1279 /* if sym is a simple string and sym->ival is a string,
1280 WE don't need it anymore */
1281 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1282 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1283 list2val(sym->ival)->sym->isstrlit) {
1284 freeStringSymbol(list2val(sym->ival)->sym);
1288 /* allocate space */
1289 int size = getSize (sym->type);
1292 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1294 fprintf (out, "%s:\n", sym->rname);
1295 /* special case for character strings */
1296 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1297 SPEC_CVAL (sym->etype).v_char)
1299 SPEC_CVAL (sym->etype).v_char,
1302 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1308 /*-----------------------------------------------------------------*/
1309 /* emitMaps - emits the code for the data portion the code */
1310 /*-----------------------------------------------------------------*/
1314 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1315 /* ports but let's be conservative - EEP */
1318 /* no special considerations for the following
1319 data, idata & bit & xdata */
1320 emitRegularMap (data, TRUE, TRUE);
1321 emitRegularMap (idata, TRUE, TRUE);
1322 emitRegularMap (bit, TRUE, TRUE);
1323 emitRegularMap (pdata, TRUE, TRUE);
1324 emitRegularMap (xdata, TRUE, TRUE);
1325 if (port->genXINIT) {
1326 emitRegularMap (xidata, TRUE, TRUE);
1328 emitRegularMap (sfr, publicsfr, FALSE);
1329 emitRegularMap (sfrbit, publicsfr, FALSE);
1330 emitRegularMap (home, TRUE, FALSE);
1331 emitRegularMap (code, TRUE, FALSE);
1333 emitStaticSeg (statsg, code->oFile);
1334 if (port->genXINIT) {
1335 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1336 emitStaticSeg (xinit, code->oFile);
1341 /*-----------------------------------------------------------------*/
1342 /* flushStatics - flush all currently defined statics out to file */
1343 /* and delete. Temporary function */
1344 /*-----------------------------------------------------------------*/
1348 emitStaticSeg (statsg, codeOutFile);
1349 statsg->syms = NULL;
1352 /*-----------------------------------------------------------------*/
1353 /* createInterruptVect - creates the interrupt vector */
1354 /*-----------------------------------------------------------------*/
1356 createInterruptVect (FILE * vFile)
1358 mainf = newSymbol ("main", 0);
1361 /* only if the main function exists */
1362 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1364 if (!options.cc_only && !noAssemble && !options.c1mode)
1369 /* if the main is only a prototype ie. no body then do nothing */
1370 if (!IFFUNC_HASBODY(mainf->type))
1372 /* if ! compile only then main function should be present */
1373 if (!options.cc_only && !noAssemble)
1378 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1379 fprintf (vFile, "__interrupt_vect:\n");
1382 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1384 /* There's no such thing as a "generic" interrupt table header. */
1391 ";--------------------------------------------------------\n"
1392 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1396 ";--------------------------------------------------------\n"};
1399 /*-----------------------------------------------------------------*/
1400 /* initialComments - puts in some initial comments */
1401 /*-----------------------------------------------------------------*/
1403 initialComments (FILE * afile)
1407 fprintf (afile, "%s", iComments1);
1408 fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber(), __DATE__);
1409 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1410 fprintf (afile, "%s", iComments2);
1413 /*-----------------------------------------------------------------*/
1414 /* printPublics - generates .global for publics */
1415 /*-----------------------------------------------------------------*/
1417 printPublics (FILE * afile)
1421 fprintf (afile, "%s", iComments2);
1422 fprintf (afile, "; Public variables in this module\n");
1423 fprintf (afile, "%s", iComments2);
1425 for (sym = setFirstItem (publics); sym;
1426 sym = setNextItem (publics))
1427 tfprintf (afile, "\t!global\n", sym->rname);
1430 /*-----------------------------------------------------------------*/
1431 /* printExterns - generates .global for externs */
1432 /*-----------------------------------------------------------------*/
1434 printExterns (FILE * afile)
1438 fprintf (afile, "%s", iComments2);
1439 fprintf (afile, "; Externals used\n");
1440 fprintf (afile, "%s", iComments2);
1442 for (sym = setFirstItem (externs); sym;
1443 sym = setNextItem (externs))
1444 tfprintf (afile, "\t!extern\n", sym->rname);
1447 /*-----------------------------------------------------------------*/
1448 /* emitOverlay - will emit code for the overlay stuff */
1449 /*-----------------------------------------------------------------*/
1451 emitOverlay (FILE * afile)
1455 if (!elementsInSet (ovrSetSets))
1456 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1458 /* for each of the sets in the overlay segment do */
1459 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1460 ovrset = setNextItem (ovrSetSets))
1465 if (elementsInSet (ovrset))
1467 /* output the area informtion */
1468 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1471 for (sym = setFirstItem (ovrset); sym;
1472 sym = setNextItem (ovrset))
1474 /* if extern then it is in the publics table: do nothing */
1475 if (IS_EXTERN (sym->etype))
1478 /* if allocation required check is needed
1479 then check if the symbol really requires
1480 allocation only for local variables */
1481 if (!IS_AGGREGATE (sym->type) &&
1482 !(sym->_isparm && !IS_REGPARM (sym->etype))
1483 && !sym->allocreq && sym->level)
1486 /* if global variable & not static or extern
1487 and addPublics allowed then add it to the public set */
1488 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1489 && !IS_STATIC (sym->etype))
1491 addSetHead (&publics, sym);
1494 /* if extern then do nothing or is a function
1496 if (IS_FUNC (sym->type))
1499 /* print extra debug info if required */
1504 if (IS_STATIC (sym->etype))
1505 fprintf (afile, "F%s$", moduleName); /* scope is file */
1507 fprintf (afile, "G$"); /* scope is global */
1510 /* symbol is local */
1511 fprintf (afile, "L%s$",
1512 (sym->localof ? sym->localof->name : "-null-"));
1513 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1516 /* if is has an absolute address then generate
1517 an equate for this no need to allocate space */
1518 if (SPEC_ABSA (sym->etype))
1522 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1524 fprintf (afile, "%s\t=\t0x%04x\n",
1526 SPEC_ADDR (sym->etype));
1529 int size = getSize(sym->type);
1532 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1535 fprintf (afile, "==.\n");
1537 /* allocate space */
1538 tfprintf (afile, "!labeldef\n", sym->rname);
1539 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1547 /*-----------------------------------------------------------------*/
1548 /* spacesToUnderscores - replace spaces with underscores */
1549 /*-----------------------------------------------------------------*/
1551 spacesToUnderscores (char *dest, const char *src, size_t len)
1556 assert(dest != NULL);
1557 assert(src != NULL);
1561 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1562 *p++ = isspace(*src) ? '_' : *src;
1570 /*-----------------------------------------------------------------*/
1571 /* glue - the final glue that hold the whole thing together */
1572 /*-----------------------------------------------------------------*/
1578 FILE *ovrFile = tempfile ();
1579 char moduleBuf[PATH_MAX];
1582 if(port->general.glue_up_main &&
1583 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1585 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1592 addSetHead (&tmpfileSet, ovrFile);
1593 /* print the global struct definitions */
1597 vFile = tempfile ();
1598 /* PENDING: this isn't the best place but it will do */
1599 if (port->general.glue_up_main)
1601 /* create the interrupt vector table */
1602 createInterruptVect (vFile);
1605 addSetHead (&tmpfileSet, vFile);
1607 /* emit code for the all the variables declared */
1609 /* do the overlay segments */
1610 emitOverlay (ovrFile);
1612 outputDebugSymbols();
1614 /* now put it all together into the assembler file */
1615 /* create the assembler file name */
1617 /* -o option overrides default name? */
1618 if ((noAssemble || options.c1mode) && fullDstFileName)
1620 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1624 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1625 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1628 if (!(asmFile = fopen (scratchFileName, "w")))
1630 werror (E_FILE_OPEN_ERR, scratchFileName);
1634 /* initial comments */
1635 initialComments (asmFile);
1637 /* print module name */
1638 tfprintf (asmFile, "\t!module\n",
1639 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1642 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1644 switch(options.model)
1646 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1647 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1648 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1649 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1650 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1651 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1654 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1655 if(options.useXstack) fprintf (asmFile, " --xstack");
1656 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1657 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1658 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1659 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1660 fprintf (asmFile, "\n");
1662 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1664 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1667 tfprintf (asmFile, "\t!fileprelude\n");
1669 /* Let the port generate any global directives, etc. */
1670 if (port->genAssemblerPreamble)
1672 port->genAssemblerPreamble (asmFile);
1675 /* print the global variables in this module */
1676 printPublics (asmFile);
1677 if (port->assembler.externGlobal)
1678 printExterns (asmFile);
1681 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1683 /* copy the sfr segment */
1684 fprintf (asmFile, "%s", iComments2);
1685 fprintf (asmFile, "; special function registers\n");
1686 fprintf (asmFile, "%s", iComments2);
1687 copyFile (asmFile, sfr->oFile);
1692 /* copy the sbit segment */
1693 fprintf (asmFile, "%s", iComments2);
1694 fprintf (asmFile, "; special function bits \n");
1695 fprintf (asmFile, "%s", iComments2);
1696 copyFile (asmFile, sfrbit->oFile);
1698 /*JCF: Create the areas for the register banks*/
1699 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1701 fprintf (asmFile, "%s", iComments2);
1702 fprintf (asmFile, "; overlayable register banks \n");
1703 fprintf (asmFile, "%s", iComments2);
1705 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1706 if(RegBankUsed[1]||options.parms_in_bank1)
1707 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1709 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1711 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1715 /* copy the data segment */
1716 fprintf (asmFile, "%s", iComments2);
1717 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1718 fprintf (asmFile, "%s", iComments2);
1719 copyFile (asmFile, data->oFile);
1722 /* create the overlay segments */
1724 fprintf (asmFile, "%s", iComments2);
1725 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1726 fprintf (asmFile, "%s", iComments2);
1727 copyFile (asmFile, ovrFile);
1730 /* create the stack segment MOF */
1731 if (mainf && IFFUNC_HASBODY(mainf->type))
1733 fprintf (asmFile, "%s", iComments2);
1734 fprintf (asmFile, "; Stack segment in internal ram \n");
1735 fprintf (asmFile, "%s", iComments2);
1736 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1737 "__start__stack:\n\t.ds\t1\n\n");
1740 /* create the idata segment */
1741 if ( (idata) && (mcs51_like) ) {
1742 fprintf (asmFile, "%s", iComments2);
1743 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1744 fprintf (asmFile, "%s", iComments2);
1745 copyFile (asmFile, idata->oFile);
1748 /* copy the bit segment */
1750 fprintf (asmFile, "%s", iComments2);
1751 fprintf (asmFile, "; bit data\n");
1752 fprintf (asmFile, "%s", iComments2);
1753 copyFile (asmFile, bit->oFile);
1756 /* copy paged external ram data */
1759 fprintf (asmFile, "%s", iComments2);
1760 fprintf (asmFile, "; paged external ram data\n");
1761 fprintf (asmFile, "%s", iComments2);
1762 copyFile (asmFile, pdata->oFile);
1765 /* if external stack then reserve space for it */
1766 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1768 fprintf (asmFile, "%s", iComments2);
1769 fprintf (asmFile, "; external stack \n");
1770 fprintf (asmFile, "%s", iComments2);
1771 fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
1772 "__start__xstack:\n\t.ds\t1\n\n");
1775 /* copy external ram data */
1777 fprintf (asmFile, "%s", iComments2);
1778 fprintf (asmFile, "; external ram data\n");
1779 fprintf (asmFile, "%s", iComments2);
1780 copyFile (asmFile, xdata->oFile);
1783 /* copy external initialized ram data */
1784 fprintf (asmFile, "%s", iComments2);
1785 fprintf (asmFile, "; external initialized ram data\n");
1786 fprintf (asmFile, "%s", iComments2);
1787 copyFile (asmFile, xidata->oFile);
1789 /* If the port wants to generate any extra areas, let it do so. */
1790 if (port->extraAreas.genExtraAreaDeclaration)
1792 port->extraAreas.genExtraAreaDeclaration(asmFile,
1793 mainf && IFFUNC_HASBODY(mainf->type));
1796 /* copy the interrupt vector table */
1797 if (mainf && IFFUNC_HASBODY(mainf->type))
1799 fprintf (asmFile, "%s", iComments2);
1800 fprintf (asmFile, "; interrupt vector \n");
1801 fprintf (asmFile, "%s", iComments2);
1802 copyFile (asmFile, vFile);
1805 /* copy global & static initialisations */
1806 fprintf (asmFile, "%s", iComments2);
1807 fprintf (asmFile, "; global & static initialisations\n");
1808 fprintf (asmFile, "%s", iComments2);
1810 /* Everywhere we generate a reference to the static_name area,
1811 * (which is currently only here), we immediately follow it with a
1812 * definition of the post_static_name area. This guarantees that
1813 * the post_static_name area will immediately follow the static_name
1816 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1817 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1818 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1820 if (mainf && IFFUNC_HASBODY(mainf->type))
1822 if (port->genInitStartup)
1824 port->genInitStartup(asmFile);
1828 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1829 /* if external stack is specified then the
1830 higher order byte of the xdatalocation is
1831 going into P2 and the lower order going into
1833 if (options.useXstack)
1835 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1836 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1837 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1838 (unsigned int) options.xdata_loc & 0xff);
1841 // This should probably be a port option, but I'm being lazy.
1842 // on the 400, the firmware boot loader gives us a valid stack
1843 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1844 if (!TARGET_IS_DS400)
1846 /* initialise the stack pointer. JCF: aslink takes care of the location */
1847 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1850 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1851 fprintf (asmFile, "\tmov\ta,dpl\n");
1852 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1853 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1854 fprintf (asmFile, "__sdcc_init_data:\n");
1856 // if the port can copy the XINIT segment to XISEG
1859 port->genXINIT(asmFile);
1864 copyFile (asmFile, statsg->oFile);
1866 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1868 /* This code is generated in the post-static area.
1869 * This area is guaranteed to follow the static area
1870 * by the ugly shucking and jiving about 20 lines ago.
1872 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1873 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1879 "%s", iComments2, iComments2);
1880 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1881 copyFile (asmFile, home->oFile);
1883 /* copy over code */
1884 fprintf (asmFile, "%s", iComments2);
1885 fprintf (asmFile, "; code\n");
1886 fprintf (asmFile, "%s", iComments2);
1887 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1888 if (mainf && IFFUNC_HASBODY(mainf->type))
1891 /* entry point @ start of CSEG */
1892 fprintf (asmFile, "__sdcc_program_startup:\n");
1894 /* put in jump or call to main */
1895 if (options.mainreturn)
1897 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1898 fprintf (asmFile, ";\treturn from main will return to caller\n");
1902 fprintf (asmFile, "\tlcall\t_main\n");
1903 fprintf (asmFile, ";\treturn from main will lock up\n");
1904 fprintf (asmFile, "\tsjmp .\n");
1907 copyFile (asmFile, code->oFile);
1909 if (port->genAssemblerEnd) {
1910 port->genAssemblerEnd(asmFile);
1918 /** Creates a temporary file with unique file name
1920 - TMP, TEMP, TMPDIR env. variables
1921 - if Un*x system: /usr/tmp and /tmp
1922 - root directory using mkstemp() if available
1923 - default location using tempnam()
1926 tempfileandname(char *fname, size_t len)
1928 #define TEMPLATE "sdccXXXXXX"
1929 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1931 const char *tmpdir = NULL;
1934 if ((tmpdir = getenv ("TMP")) == NULL)
1935 if ((tmpdir = getenv ("TEMP")) == NULL)
1936 tmpdir = getenv ("TMPDIR");
1940 static int warning_emitted;
1945 if (!warning_emitted)
1947 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1948 warning_emitted = 1;
1954 /* try with /usr/tmp and /tmp on Un*x systems */
1955 struct stat statbuf;
1957 if (tmpdir == NULL) {
1958 if (stat("/usr/tmp", &statbuf) != -1)
1959 tmpdir = "/usr/tmp";
1960 else if (stat("/tmp", &statbuf) != -1)
1968 char fnamebuf[PATH_MAX];
1971 if (fname == NULL || len == 0) {
1973 len = sizeof fnamebuf;
1977 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1979 assert(name_len < len);
1980 if (!(name_len < len)) /* in NDEBUG is defined */
1981 return -1; /* buffer too small, temporary file can not be created */
1983 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1986 name_len = TEMPLATE_LEN;
1988 assert(name_len < len);
1989 if (!(name_len < len)) /* in NDEBUG is defined */
1990 return -1; /* buffer too small, temporary file can not be created */
1992 strcpy(fname, TEMPLATE);
1995 fd = mkstemp(fname);
1999 char *name = tempnam(tmpdir, "sdcc");
2002 perror("Can't create temporary file name");
2006 assert(strlen(name) < len);
2007 if (!(strlen(name) < len)) /* in NDEBUG is defined */
2008 return -1; /* buffer too small, temporary file can not be created */
2010 strcpy(fname, name);
2012 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2014 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2020 perror("Can't create temporary file");
2028 /** Create a temporary file name
2034 static char fnamebuf[PATH_MAX];
2036 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2037 fprintf(stderr, "Can't create temporary file name!");
2048 /** Create a temporary file and add it to tmpfileNameSet,
2049 so that it is removed explicitly by rm_tmpfiles()
2050 or implicitly at program extit.
2058 char fnamebuf[PATH_MAX];
2060 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2061 fprintf(stderr, "Can't create temporary file!");
2065 tmp = Safe_strdup(fnamebuf);
2067 addSetHead(&tmpfileNameSet, tmp);
2069 if ((fp = fdopen(fd, "w+b")) == NULL) {
2070 perror("Can't create temporary file!");