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; /* Varibles that are declared as extern */
44 /* TODO: this should be configurable (DS803C90 uses more than 6) */
45 unsigned maxInterrupts = 6;
48 set *pipeSet = NULL; /* set of pipes */
49 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
50 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
52 /*-----------------------------------------------------------------*/
53 /* closePipes - closes all pipes created by the compiler */
54 /*-----------------------------------------------------------------*/
55 DEFSETFUNC (closePipes)
68 /*-----------------------------------------------------------------*/
69 /* closeTmpFiles - closes all tmp files created by the compiler */
70 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
71 /*-----------------------------------------------------------------*/
72 DEFSETFUNC (closeTmpFiles)
85 /*-----------------------------------------------------------------*/
86 /* rmTmpFiles - unlinks all tmp files created by the compiler */
87 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
88 /*-----------------------------------------------------------------*/
89 DEFSETFUNC (rmTmpFiles)
103 /*-----------------------------------------------------------------*/
104 /* rm_tmpfiles - close and remove temporary files and delete sets */
105 /*-----------------------------------------------------------------*/
109 /* close temporary files */
110 applyToSet (pipeSet, closePipes);
111 /* close temporary files */
112 deleteSet (&pipeSet);
114 applyToSet (tmpfileSet, closeTmpFiles);
115 /* remove temporary files */
116 applyToSet (tmpfileNameSet, rmTmpFiles);
117 /* delete temorary file sets */
118 deleteSet (&tmpfileSet);
119 deleteSet (&tmpfileNameSet);
122 /*-----------------------------------------------------------------*/
123 /* copyFile - copies source file to destination file */
124 /*-----------------------------------------------------------------*/
126 copyFile (FILE * dest, FILE * src)
132 if ((ch = fgetc (src)) != EOF)
137 aopLiteralLong (value * val, int offset, int size)
146 // assuming we have been warned before
150 /* if it is a float then it gets tricky */
151 /* otherwise it is fairly simple */
152 if (!IS_FLOAT (val->type)) {
153 unsigned long v = (unsigned long) floatFromVal (val);
158 tsprintf (buffer, sizeof(buffer),
159 "!immedbyte", (unsigned int) v & 0xff);
162 tsprintf (buffer, sizeof(buffer),
163 "!immedword", (unsigned int) v & 0xffff);
166 /* Hmm. Too big for now. */
169 return Safe_strdup (buffer);
172 /* PENDING: For now size must be 1 */
175 /* it is type float */
176 fl.f = (float) floatFromVal (val);
177 #ifdef WORDS_BIGENDIAN
178 tsprintf (buffer, sizeof(buffer),
179 "!immedbyte", fl.c[3 - offset]);
181 tsprintf (buffer, sizeof(buffer),
182 "!immedbyte", fl.c[offset]);
184 return Safe_strdup (buffer);
187 /*-----------------------------------------------------------------*/
188 /* aopLiteral - string from a literal value */
189 /*-----------------------------------------------------------------*/
191 aopLiteral (value * val, int offset)
193 return aopLiteralLong (val, offset, 1);
196 /*-----------------------------------------------------------------*/
197 /* emitRegularMap - emit code for maps with no special cases */
198 /*-----------------------------------------------------------------*/
200 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
210 /* PENDING: special case here - should remove */
211 if (!strcmp (map->sname, CODE_NAME))
212 tfprintf (map->oFile, "\t!areacode\n", map->sname);
213 else if (!strcmp (map->sname, DATA_NAME))
214 tfprintf (map->oFile, "\t!areadata\n", map->sname);
215 else if (!strcmp (map->sname, HOME_NAME))
216 tfprintf (map->oFile, "\t!areahome\n", map->sname);
218 tfprintf (map->oFile, "\t!area\n", map->sname);
221 for (sym = setFirstItem (map->syms); sym;
222 sym = setNextItem (map->syms))
226 /* if extern then add it into the extern list */
227 if (IS_EXTERN (sym->etype))
229 addSetHead (&externs, sym);
233 /* if allocation required check is needed
234 then check if the symbol really requires
235 allocation only for local variables */
237 if (arFlag && !IS_AGGREGATE (sym->type) &&
238 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
239 !sym->allocreq && sym->level)
242 /* for bitvar locals and parameters */
243 if (!arFlag && !sym->allocreq && sym->level
244 && !SPEC_ABSA (sym->etype)) {
248 /* if global variable & not static or extern
249 and addPublics allowed then add it to the public set */
250 if ((sym->level == 0 ||
251 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
253 !IS_STATIC (sym->etype) &&
254 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
256 addSetHead (&publics, sym);
259 /* if extern then do nothing or is a function
261 if (IS_FUNC (sym->type) && !(sym->isitmp))
264 /* print extra debug info if required */
267 if (!sym->level) /* global */
269 if (IS_STATIC (sym->etype))
270 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
272 fprintf (map->oFile, "G$"); /* scope is global */
276 /* symbol is local */
277 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
279 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
282 /* if it has an initial value then do it only if
283 it is a global variable */
284 if (sym->ival && sym->level == 0) {
285 if (SPEC_OCLS(sym->etype)==xidata) {
286 /* create a new "XINIT (CODE)" symbol, that will be emitted later
288 newSym=copySymbol (sym);
289 SPEC_OCLS(newSym->etype)=xinit;
290 SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
291 SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
292 if (IS_SPEC (newSym->type))
293 SPEC_CONST (newSym->type) = 1;
295 DCL_PTR_CONST (newSym->type) = 1;
296 SPEC_STAT(newSym->etype)=1;
297 resolveIvalSym(newSym->ival, newSym->type);
299 // add it to the "XINIT (CODE)" segment
300 addSet(&xinit->syms, newSym);
302 if (!SPEC_ABSA (sym->etype))
304 FILE *tmpFile = tempfile ();
305 addSetHead (&tmpfileSet, tmpFile);
306 // before allocation we must parse the sym->ival tree
307 // but without actually generating initialization code
309 resolveIvalSym (sym->ival, sym->type);
310 printIval (sym, sym->type, sym->ival, tmpFile);
316 if (IS_AGGREGATE (sym->type)) {
317 ival = initAggregates (sym, sym->ival, NULL);
319 if (getNelements(sym->type, sym->ival)>1) {
320 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
323 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
324 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
326 codeOutFile = statsg->oFile;
329 // set ival's lineno to where the symbol was defined
330 setAstLineno (ival, lineno=sym->lineDef);
331 // check if this is not a constant expression
332 if (!constExprTree(ival)) {
333 werror (E_CONST_EXPECTED, "found expression");
334 // but try to do it anyway
337 if (!astErrors(ival))
338 eBBlockFromiCode (iCodeFromAst (ival));
345 /* if it has an absolute address then generate
346 an equate for this no need to allocate space */
347 if (SPEC_ABSA (sym->etype))
351 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
353 if (TARGET_IS_XA51) {
356 } else if (map==bit || map==sfrbit) {
360 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
362 SPEC_ADDR (sym->etype));
365 int size = getAllocSize (sym->type);
367 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
371 fprintf (map->oFile, "==.\n");
373 if (IS_STATIC (sym->etype))
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 = copyValue (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)
529 int len = strlen (s);
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 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
778 if (IS_BITFIELD(sflds->type)) {
779 printIvalBitFields(&sflds,&iloop,oFile);
781 printIval (sym, sflds->type, iloop, oFile);
785 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
790 /*-----------------------------------------------------------------*/
791 /* printIvalChar - generates initital value for character array */
792 /*-----------------------------------------------------------------*/
794 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
801 val = list2val (ilist);
802 /* if the value is a character string */
803 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
805 if (!DCL_ELEM (type))
806 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
808 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
816 printChar (oFile, s, strlen (s) + 1);
820 /*-----------------------------------------------------------------*/
821 /* printIvalArray - generates code for array initialization */
822 /*-----------------------------------------------------------------*/
824 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
831 /* take care of the special case */
832 /* array of characters can be init */
834 if (IS_CHAR (type->next)) {
835 if (!IS_LITERAL(list2val(ilist)->etype)) {
836 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
839 if (printIvalChar (type,
840 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
841 oFile, SPEC_CVAL (sym->etype).v_char))
844 /* not the special case */
845 if (ilist->type != INIT_DEEP) {
846 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
850 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
851 printIval (sym, type->next, iloop, oFile);
853 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
854 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
860 if (DCL_ELEM(type)) {
861 // pad with zeros if needed
862 if (size<DCL_ELEM(type)) {
863 size = (DCL_ELEM(type) - size) * getSize(type->next);
865 tfprintf (oFile, "\t!db !constbyte\n", 0);
869 // we have not been given a size, but we now know it
870 DCL_ELEM (type) = size;
876 /*-----------------------------------------------------------------*/
877 /* printIvalFuncPtr - generate initial value for function pointers */
878 /*-----------------------------------------------------------------*/
880 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
886 val = list2val (ilist);
888 val = valCastLiteral(type, 0.0);
891 // an error has been thrown already
895 if (IS_LITERAL(val->etype)) {
896 if (compareType(type, val->etype) == 0) {
897 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
898 printFromToType (val->type, type);
900 printIvalCharPtr (NULL, type, val, oFile);
904 /* check the types */
905 if ((dLvl = compareType (val->type, type->next)) <= 0)
907 tfprintf (oFile, "\t!dw !constword\n", 0);
911 /* now generate the name */
914 if (port->use_dw_for_init)
916 tfprintf (oFile, "\t!dws\n", val->name);
920 printPointerType (oFile, val->name);
923 else if (port->use_dw_for_init)
925 tfprintf (oFile, "\t!dws\n", val->sym->rname);
929 printPointerType (oFile, val->sym->rname);
935 /*-----------------------------------------------------------------*/
936 /* printIvalCharPtr - generates initial values for character pointers */
937 /*-----------------------------------------------------------------*/
939 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
943 /* PENDING: this is _very_ mcs51 specific, including a magic
945 It's also endin specific.
947 size = getSize (type);
949 if (val->name && strlen (val->name))
951 if (size == 1) /* This appears to be Z80 specific?? */
954 "\t!dbs\n", val->name);
956 else if (size == FPTRSIZE)
958 if (port->use_dw_for_init)
960 tfprintf (oFile, "\t!dws\n", val->name);
964 printPointerType (oFile, val->name);
967 else if (size == GPTRSIZE)
970 if (IS_PTR (val->type)) {
971 type = DCL_TYPE (val->type);
973 type = PTR_TYPE (SPEC_OCLS (val->etype));
975 if (val->sym && val->sym->isstrlit) {
976 // this is a literal string
979 printGPointerType (oFile, val->name, sym->name, type);
983 fprintf (stderr, "*** internal error: unknown size in "
984 "printIvalCharPtr.\n");
989 // these are literals assigned to pointers
993 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
996 if (port->use_dw_for_init)
997 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
998 else if (port->little_endian)
999 tfprintf (oFile, "\t.byte %s,%s\n",
1000 aopLiteral (val, 0), aopLiteral (val, 1));
1002 tfprintf (oFile, "\t.byte %s,%s\n",
1003 aopLiteral (val, 1), aopLiteral (val, 0));
1006 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1007 // non-zero mcs51 generic pointer
1008 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1010 if (port->little_endian) {
1011 fprintf (oFile, "\t.byte %s,%s,%s\n",
1012 aopLiteral (val, 0),
1013 aopLiteral (val, 1),
1014 aopLiteral (val, 2));
1016 fprintf (oFile, "\t.byte %s,%s,%s\n",
1017 aopLiteral (val, 2),
1018 aopLiteral (val, 1),
1019 aopLiteral (val, 0));
1023 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1024 // non-zero ds390 generic pointer
1025 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1027 if (port->little_endian) {
1028 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1029 aopLiteral (val, 0),
1030 aopLiteral (val, 1),
1031 aopLiteral (val, 2),
1032 aopLiteral (val, 3));
1034 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1035 aopLiteral (val, 3),
1036 aopLiteral (val, 2),
1037 aopLiteral (val, 1),
1038 aopLiteral (val, 0));
1046 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1047 addSet (&statsg->syms, val->sym);
1053 /*-----------------------------------------------------------------*/
1054 /* printIvalPtr - generates initial value for pointers */
1055 /*-----------------------------------------------------------------*/
1057 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1063 if (ilist && (ilist->type == INIT_DEEP))
1064 ilist = ilist->init.deep;
1066 /* function pointer */
1067 if (IS_FUNC (type->next))
1069 printIvalFuncPtr (type, ilist, oFile);
1073 if (!(val = initPointer (ilist, type)))
1076 /* if character pointer */
1077 if (IS_CHAR (type->next))
1078 if (printIvalCharPtr (sym, type, val, oFile))
1081 /* check the type */
1082 if (compareType (type, val->type) == 0) {
1083 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1084 printFromToType (val->type, type);
1087 /* if val is literal */
1088 if (IS_LITERAL (val->etype))
1090 switch (getSize (type))
1093 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1096 if (port->use_dw_for_init)
1097 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1098 else if (port->little_endian)
1099 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1101 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1103 case 3: // how about '390??
1104 fprintf (oFile, "; generic printIvalPtr\n");
1105 if (port->little_endian)
1107 fprintf (oFile, "\t.byte %s,%s",
1108 aopLiteral (val, 0), aopLiteral (val, 1));
1112 fprintf (oFile, "\t.byte %s,%s",
1113 aopLiteral (val, 1), aopLiteral (val, 0));
1115 if (IS_GENPTR (val->type))
1116 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1117 else if (IS_PTR (val->type))
1118 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1120 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1126 size = getSize (type);
1128 if (size == 1) /* Z80 specific?? */
1130 tfprintf (oFile, "\t!dbs\n", val->name);
1132 else if (size == FPTRSIZE)
1134 if (port->use_dw_for_init) {
1135 tfprintf (oFile, "\t!dws\n", val->name);
1137 printPointerType (oFile, val->name);
1140 else if (size == GPTRSIZE)
1142 printGPointerType (oFile, val->name, sym->name,
1143 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1144 PTR_TYPE (SPEC_OCLS (val->etype))));
1149 /*-----------------------------------------------------------------*/
1150 /* printIval - generates code for initial value */
1151 /*-----------------------------------------------------------------*/
1153 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1157 /* if structure then */
1158 if (IS_STRUCT (type))
1160 printIvalStruct (sym, type, ilist, oFile);
1164 /* if this is an array */
1165 if (IS_ARRAY (type))
1167 printIvalArray (sym, type, ilist, oFile);
1173 // not an aggregate, ilist must be a node
1174 if (ilist->type!=INIT_NODE) {
1175 // or a 1-element list
1176 if (ilist->init.deep->next) {
1177 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1180 ilist=ilist->init.deep;
1184 // and the type must match
1185 itype=ilist->init.node->ftype;
1187 if (compareType(type, itype)==0) {
1188 // special case for literal strings
1189 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1190 // which are really code pointers
1191 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1194 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1195 printFromToType(itype, type);
1200 /* if this is a pointer */
1203 printIvalPtr (sym, type, ilist, oFile);
1207 /* if type is SPECIFIER */
1210 printIvalType (sym, type, ilist, oFile);
1215 /*-----------------------------------------------------------------*/
1216 /* emitStaticSeg - emitcode for the static segment */
1217 /*-----------------------------------------------------------------*/
1219 emitStaticSeg (memmap * map, FILE * out)
1223 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1225 /* for all variables in this segment do */
1226 for (sym = setFirstItem (map->syms); sym;
1227 sym = setNextItem (map->syms))
1230 /* if it is "extern" then do nothing */
1231 if (IS_EXTERN (sym->etype))
1234 /* if it is not static add it to the public
1236 if (!IS_STATIC (sym->etype))
1238 addSetHead (&publics, sym);
1241 /* print extra debug info if required */
1242 if (options.debug) {
1246 if (IS_STATIC (sym->etype))
1247 fprintf (out, "F%s$", moduleName); /* scope is file */
1249 fprintf (out, "G$"); /* scope is global */
1252 /* symbol is local */
1253 fprintf (out, "L%s$",
1254 (sym->localof ? sym->localof->name : "-null-"));
1255 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1258 /* if it has an absolute address */
1259 if (SPEC_ABSA (sym->etype))
1262 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1264 fprintf (out, "%s\t=\t0x%04x\n",
1266 SPEC_ADDR (sym->etype));
1271 fprintf (out, " == .\n");
1273 /* if it has an initial value */
1276 fprintf (out, "%s:\n", sym->rname);
1278 resolveIvalSym (sym->ival, sym->type);
1279 printIval (sym, sym->type, sym->ival, out);
1281 /* if sym is a simple string and sym->ival is a string,
1282 WE don't need it anymore */
1283 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1284 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1285 list2val(sym->ival)->sym->isstrlit) {
1286 freeStringSymbol(list2val(sym->ival)->sym);
1290 /* allocate space */
1291 int size = getSize (sym->type);
1294 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1296 fprintf (out, "%s:\n", sym->rname);
1297 /* special case for character strings */
1298 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1299 SPEC_CVAL (sym->etype).v_char)
1301 SPEC_CVAL (sym->etype).v_char,
1304 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1310 /*-----------------------------------------------------------------*/
1311 /* emitMaps - emits the code for the data portion the code */
1312 /*-----------------------------------------------------------------*/
1316 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1317 /* ports but let's be conservative - EEP */
1320 /* no special considerations for the following
1321 data, idata & bit & xdata */
1322 emitRegularMap (data, TRUE, TRUE);
1323 emitRegularMap (idata, TRUE, TRUE);
1324 emitRegularMap (bit, TRUE, FALSE);
1325 emitRegularMap (xdata, TRUE, TRUE);
1326 if (port->genXINIT) {
1327 emitRegularMap (xidata, TRUE, TRUE);
1329 emitRegularMap (sfr, publicsfr, FALSE);
1330 emitRegularMap (sfrbit, publicsfr, FALSE);
1331 emitRegularMap (home, TRUE, FALSE);
1332 emitRegularMap (code, TRUE, FALSE);
1334 emitStaticSeg (statsg, code->oFile);
1335 if (port->genXINIT) {
1336 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1337 emitStaticSeg (xinit, code->oFile);
1342 /*-----------------------------------------------------------------*/
1343 /* flushStatics - flush all currently defined statics out to file */
1344 /* and delete. Temporary function */
1345 /*-----------------------------------------------------------------*/
1349 emitStaticSeg (statsg, codeOutFile);
1350 statsg->syms = NULL;
1353 /*-----------------------------------------------------------------*/
1354 /* createInterruptVect - creates the interrupt vector */
1355 /*-----------------------------------------------------------------*/
1357 createInterruptVect (FILE * vFile)
1360 mainf = newSymbol ("main", 0);
1363 /* only if the main function exists */
1364 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1366 if (!options.cc_only && !noAssemble && !options.c1mode)
1371 /* if the main is only a prototype ie. no body then do nothing */
1372 if (!IFFUNC_HASBODY(mainf->type))
1374 /* if ! compile only then main function should be present */
1375 if (!options.cc_only && !noAssemble)
1380 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1381 fprintf (vFile, "__interrupt_vect:\n");
1384 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1386 /* "generic" interrupt table header (if port doesn't specify one).
1387 * Look suspiciously like 8051 code to me...
1390 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1392 /* now for the other interrupts */
1393 for (; i < maxInterrupts; i++)
1397 fprintf (vFile, "\tljmp\t%s\n", interrupts[i]->rname);
1398 if ( i != maxInterrupts - 1 )
1399 fprintf (vFile, "\t.ds\t5\n");
1403 fprintf (vFile, "\treti\n");
1404 if ( i != maxInterrupts - 1 )
1405 fprintf (vFile, "\t.ds\t7\n");
1413 ";--------------------------------------------------------\n"
1414 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1418 ";--------------------------------------------------------\n"};
1421 /*-----------------------------------------------------------------*/
1422 /* initialComments - puts in some initial comments */
1423 /*-----------------------------------------------------------------*/
1425 initialComments (FILE * afile)
1429 fprintf (afile, "%s", iComments1);
1430 fprintf (afile, "; Version " SDCC_VERSION_STR " (%s)\n", __DATE__);
1431 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1432 fprintf (afile, "%s", iComments2);
1435 /*-----------------------------------------------------------------*/
1436 /* printPublics - generates .global for publics */
1437 /*-----------------------------------------------------------------*/
1439 printPublics (FILE * afile)
1443 fprintf (afile, "%s", iComments2);
1444 fprintf (afile, "; Public variables in this module\n");
1445 fprintf (afile, "%s", iComments2);
1447 for (sym = setFirstItem (publics); sym;
1448 sym = setNextItem (publics))
1449 tfprintf (afile, "\t!global\n", sym->rname);
1452 /*-----------------------------------------------------------------*/
1453 /* printExterns - generates .global for externs */
1454 /*-----------------------------------------------------------------*/
1456 printExterns (FILE * afile)
1460 fprintf (afile, "%s", iComments2);
1461 fprintf (afile, "; Externals used\n");
1462 fprintf (afile, "%s", iComments2);
1464 for (sym = setFirstItem (externs); sym;
1465 sym = setNextItem (externs))
1466 tfprintf (afile, "\t!extern\n", sym->rname);
1469 /*-----------------------------------------------------------------*/
1470 /* emitOverlay - will emit code for the overlay stuff */
1471 /*-----------------------------------------------------------------*/
1473 emitOverlay (FILE * afile)
1477 if (!elementsInSet (ovrSetSets))
1478 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1480 /* for each of the sets in the overlay segment do */
1481 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1482 ovrset = setNextItem (ovrSetSets))
1487 if (elementsInSet (ovrset))
1489 /* output the area informtion */
1490 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1493 for (sym = setFirstItem (ovrset); sym;
1494 sym = setNextItem (ovrset))
1496 /* if extern then it is in the publics table: do nothing */
1497 if (IS_EXTERN (sym->etype))
1500 /* if allocation required check is needed
1501 then check if the symbol really requires
1502 allocation only for local variables */
1503 if (!IS_AGGREGATE (sym->type) &&
1504 !(sym->_isparm && !IS_REGPARM (sym->etype))
1505 && !sym->allocreq && sym->level)
1508 /* if global variable & not static or extern
1509 and addPublics allowed then add it to the public set */
1510 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1511 && !IS_STATIC (sym->etype))
1513 addSetHead (&publics, sym);
1516 /* if extern then do nothing or is a function
1518 if (IS_FUNC (sym->type))
1521 /* print extra debug info if required */
1526 if (IS_STATIC (sym->etype))
1527 fprintf (afile, "F%s$", moduleName); /* scope is file */
1529 fprintf (afile, "G$"); /* scope is global */
1532 /* symbol is local */
1533 fprintf (afile, "L%s$",
1534 (sym->localof ? sym->localof->name : "-null-"));
1535 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1538 /* if is has an absolute address then generate
1539 an equate for this no need to allocate space */
1540 if (SPEC_ABSA (sym->etype))
1544 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1546 fprintf (afile, "%s\t=\t0x%04x\n",
1548 SPEC_ADDR (sym->etype));
1551 int size = getSize(sym->type);
1554 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1557 fprintf (afile, "==.\n");
1559 /* allocate space */
1560 tfprintf (afile, "!labeldef\n", sym->rname);
1561 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1569 /*-----------------------------------------------------------------*/
1570 /* spacesToUnderscores - replace spaces with underscores */
1571 /*-----------------------------------------------------------------*/
1573 spacesToUnderscores (char *dest, const char *src, size_t len)
1578 assert(dest != NULL);
1579 assert(src != NULL);
1583 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1584 *p++ = isspace(*src) ? '_' : *src;
1592 /*-----------------------------------------------------------------*/
1593 /* glue - the final glue that hold the whole thing together */
1594 /*-----------------------------------------------------------------*/
1600 FILE *ovrFile = tempfile ();
1601 char moduleBuf[PATH_MAX];
1604 if(port->general.glue_up_main &&
1605 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1607 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1614 addSetHead (&tmpfileSet, ovrFile);
1615 /* print the global struct definitions */
1619 vFile = tempfile ();
1620 /* PENDING: this isnt the best place but it will do */
1621 if (port->general.glue_up_main)
1623 /* create the interrupt vector table */
1624 createInterruptVect (vFile);
1627 addSetHead (&tmpfileSet, vFile);
1629 /* emit code for the all the variables declared */
1631 /* do the overlay segments */
1632 emitOverlay (ovrFile);
1634 outputDebugSymbols();
1636 /* now put it all together into the assembler file */
1637 /* create the assembler file name */
1639 /* -o option overrides default name? */
1640 if ((noAssemble || options.c1mode) && fullDstFileName)
1642 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1646 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1647 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1650 if (!(asmFile = fopen (scratchFileName, "w")))
1652 werror (E_FILE_OPEN_ERR, scratchFileName);
1656 /* initial comments */
1657 initialComments (asmFile);
1659 /* print module name */
1660 tfprintf (asmFile, "\t!module\n",
1661 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1664 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1666 switch(options.model)
1668 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1669 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1670 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1671 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1672 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1673 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1676 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1677 if(options.useXstack) fprintf (asmFile, " --xstack");
1678 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1679 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1680 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1681 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1682 fprintf (asmFile, "\n");
1684 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1686 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1689 tfprintf (asmFile, "\t!fileprelude\n");
1691 /* Let the port generate any global directives, etc. */
1692 if (port->genAssemblerPreamble)
1694 port->genAssemblerPreamble (asmFile);
1697 /* print the global variables in this module */
1698 printPublics (asmFile);
1699 if (port->assembler.externGlobal)
1700 printExterns (asmFile);
1703 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1705 /* copy the sfr segment */
1706 fprintf (asmFile, "%s", iComments2);
1707 fprintf (asmFile, "; special function registers\n");
1708 fprintf (asmFile, "%s", iComments2);
1709 copyFile (asmFile, sfr->oFile);
1714 /* copy the sbit segment */
1715 fprintf (asmFile, "%s", iComments2);
1716 fprintf (asmFile, "; special function bits \n");
1717 fprintf (asmFile, "%s", iComments2);
1718 copyFile (asmFile, sfrbit->oFile);
1720 /*JCF: Create the areas for the register banks*/
1721 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1723 fprintf (asmFile, "%s", iComments2);
1724 fprintf (asmFile, "; overlayable register banks \n");
1725 fprintf (asmFile, "%s", iComments2);
1727 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1728 if(RegBankUsed[1]||options.parms_in_bank1)
1729 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1731 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1733 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1737 /* copy the data segment */
1738 fprintf (asmFile, "%s", iComments2);
1739 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1740 fprintf (asmFile, "%s", iComments2);
1741 copyFile (asmFile, data->oFile);
1744 /* create the overlay segments */
1746 fprintf (asmFile, "%s", iComments2);
1747 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1748 fprintf (asmFile, "%s", iComments2);
1749 copyFile (asmFile, ovrFile);
1752 /* create the stack segment MOF */
1753 if (mainf && IFFUNC_HASBODY(mainf->type))
1755 fprintf (asmFile, "%s", iComments2);
1756 fprintf (asmFile, "; Stack segment in internal ram \n");
1757 fprintf (asmFile, "%s", iComments2);
1758 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1759 "__start__stack:\n\t.ds\t1\n\n");
1762 /* create the idata segment */
1763 if ( (idata) && (mcs51_like) ) {
1764 fprintf (asmFile, "%s", iComments2);
1765 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1766 fprintf (asmFile, "%s", iComments2);
1767 copyFile (asmFile, idata->oFile);
1770 /* copy the bit segment */
1772 fprintf (asmFile, "%s", iComments2);
1773 fprintf (asmFile, "; bit data\n");
1774 fprintf (asmFile, "%s", iComments2);
1775 copyFile (asmFile, bit->oFile);
1778 /* if external stack then reserve space of it */
1779 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1781 fprintf (asmFile, "%s", iComments2);
1782 fprintf (asmFile, "; external stack \n");
1783 fprintf (asmFile, "%s", iComments2);
1784 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1785 fprintf (asmFile, "\t.ds 256\n");
1789 /* copy xtern ram data */
1791 fprintf (asmFile, "%s", iComments2);
1792 fprintf (asmFile, "; external ram data\n");
1793 fprintf (asmFile, "%s", iComments2);
1794 copyFile (asmFile, xdata->oFile);
1797 /* copy xternal initialized ram data */
1798 fprintf (asmFile, "%s", iComments2);
1799 fprintf (asmFile, "; external initialized ram data\n");
1800 fprintf (asmFile, "%s", iComments2);
1801 copyFile (asmFile, xidata->oFile);
1803 /* If the port wants to generate any extra areas, let it do so. */
1804 if (port->extraAreas.genExtraAreaDeclaration)
1806 port->extraAreas.genExtraAreaDeclaration(asmFile,
1807 mainf && IFFUNC_HASBODY(mainf->type));
1810 /* copy the interrupt vector table */
1811 if (mainf && IFFUNC_HASBODY(mainf->type))
1813 fprintf (asmFile, "%s", iComments2);
1814 fprintf (asmFile, "; interrupt vector \n");
1815 fprintf (asmFile, "%s", iComments2);
1816 copyFile (asmFile, vFile);
1819 /* copy global & static initialisations */
1820 fprintf (asmFile, "%s", iComments2);
1821 fprintf (asmFile, "; global & static initialisations\n");
1822 fprintf (asmFile, "%s", iComments2);
1824 /* Everywhere we generate a reference to the static_name area,
1825 * (which is currently only here), we immediately follow it with a
1826 * definition of the post_static_name area. This guarantees that
1827 * the post_static_name area will immediately follow the static_name
1830 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1831 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1832 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1834 if (mainf && IFFUNC_HASBODY(mainf->type))
1836 if (port->genInitStartup)
1838 port->genInitStartup(asmFile);
1842 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1843 /* if external stack is specified then the
1844 higher order byte of the xdatalocation is
1845 going into P2 and the lower order going into
1847 if (options.useXstack)
1849 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1850 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1851 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1852 (unsigned int) options.xdata_loc & 0xff);
1855 // This should probably be a port option, but I'm being lazy.
1856 // on the 400, the firmware boot loader gives us a valid stack
1857 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1858 if (!TARGET_IS_DS400)
1860 /* initialise the stack pointer. JCF: aslink takes care of the location */
1861 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1864 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1865 fprintf (asmFile, "\tmov\ta,dpl\n");
1866 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1867 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1868 fprintf (asmFile, "__sdcc_init_data:\n");
1870 // if the port can copy the XINIT segment to XISEG
1873 port->genXINIT(asmFile);
1878 copyFile (asmFile, statsg->oFile);
1880 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1882 /* This code is generated in the post-static area.
1883 * This area is guaranteed to follow the static area
1884 * by the ugly shucking and jiving about 20 lines ago.
1886 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1887 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1893 "%s", iComments2, iComments2);
1894 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1895 copyFile (asmFile, home->oFile);
1897 /* copy over code */
1898 fprintf (asmFile, "%s", iComments2);
1899 fprintf (asmFile, "; code\n");
1900 fprintf (asmFile, "%s", iComments2);
1901 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1902 if (mainf && IFFUNC_HASBODY(mainf->type))
1905 /* entry point @ start of CSEG */
1906 fprintf (asmFile, "__sdcc_program_startup:\n");
1908 /* put in jump or call to main */
1909 if (options.mainreturn)
1911 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1912 fprintf (asmFile, ";\treturn from main will return to caller\n");
1916 fprintf (asmFile, "\tlcall\t_main\n");
1917 fprintf (asmFile, ";\treturn from main will lock up\n");
1918 fprintf (asmFile, "\tsjmp .\n");
1921 copyFile (asmFile, code->oFile);
1923 if (port->genAssemblerEnd) {
1924 port->genAssemblerEnd(asmFile);
1932 /** Creates a temporary file with unique file name
1934 - TMP, TEMP, TMPDIR env. varibles
1935 - if Un*x system: /usr/tmp and /tmp
1936 - root directory using mkstemp() if avaliable
1937 - default location using tempnam()
1940 tempfileandname(char *fname, size_t len)
1942 #define TEMPLATE "sdccXXXXXX"
1943 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1945 const char *tmpdir = NULL;
1948 if ((tmpdir = getenv ("TMP")) == NULL)
1949 if ((tmpdir = getenv ("TEMP")) == NULL)
1950 tmpdir = getenv ("TMPDIR");
1954 static int warning_emitted;
1959 if (!warning_emitted)
1961 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1962 warning_emitted = 1;
1968 /* try with /usr/tmp and /tmp on Un*x systems */
1969 struct stat statbuf;
1971 if (tmpdir == NULL) {
1972 if (stat("/usr/tmp", &statbuf) != -1)
1973 tmpdir = "/usr/tmp";
1974 else if (stat("/tmp", &statbuf) != -1)
1982 char fnamebuf[PATH_MAX];
1985 if (fname == NULL || len == 0) {
1987 len = sizeof fnamebuf;
1991 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1993 assert(name_len < len);
1994 if (!(name_len < len)) /* in NDEBUG is defined */
1995 return -1; /* buffer too small, temporary file can not be created */
1997 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
2000 name_len = TEMPLATE_LEN;
2002 assert(name_len < len);
2003 if (!(name_len < len)) /* in NDEBUG is defined */
2004 return -1; /* buffer too small, temporary file can not be created */
2006 strcpy(fname, TEMPLATE);
2009 fd = mkstemp(fname);
2013 char *name = tempnam(tmpdir, "sdcc");
2016 perror("Can't create temporary file name");
2020 assert(strlen(name) < len);
2021 if (!(strlen(name) < len)) /* in NDEBUG is defined */
2022 return -1; /* buffer too small, temporary file can not be created */
2024 strcpy(fname, name);
2026 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2028 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2034 perror("Can't create temporary file");
2042 /** Create a temporary file name
2048 static char fnamebuf[PATH_MAX];
2050 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2051 fprintf(stderr, "Can't create temporary file name!");
2062 /** Create a temporary file and add it to tmpfileNameSet,
2063 so that it is removed explicitly by rm_tmpfiles()
2064 or implicitly at program extit.
2072 char fnamebuf[PATH_MAX];
2074 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2075 fprintf(stderr, "Can't create temporary file!");
2079 tmp = Safe_strdup(fnamebuf);
2081 addSetHead(&tmpfileNameSet, tmp);
2083 if ((fp = fdopen(fd, "w+b")) == NULL) {
2084 perror("Can't create temporary file!");