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[256];
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))
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 SPEC_CONST(newSym->etype)=1;
293 SPEC_STAT(newSym->etype)=1;
294 resolveIvalSym(newSym->ival);
296 // add it to the "XINIT (CODE)" segment
297 addSet(&xinit->syms, newSym);
300 if (IS_AGGREGATE (sym->type)) {
301 ival = initAggregates (sym, sym->ival, NULL);
303 if (getNelements(sym->type, sym->ival)>1) {
304 werror (W_EXCESS_INITIALIZERS, "scalar",
305 sym->name, sym->lineDef);
307 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
308 decorateType (resolveSymbols (list2expr (sym->ival))));
310 codeOutFile = statsg->oFile;
313 // set ival's lineno to where the symbol was defined
314 setAstLineno (ival, lineno=sym->lineDef);
315 // check if this is not a constant expression
316 if (!constExprTree(ival)) {
317 werror (E_CONST_EXPECTED, "found expression");
318 // but try to do it anyway
321 eBBlockFromiCode (iCodeFromAst (ival));
328 /* if is has an absolute address then generate
329 an equate for this no need to allocate space */
330 if (SPEC_ABSA (sym->etype))
334 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
336 if (TARGET_IS_XA51) {
339 } else if (map==bit || map==sfrbit) {
343 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
345 SPEC_ADDR (sym->etype));
348 int size = getSize (sym->type);
350 werror(E_UNKNOWN_SIZE,sym->name);
354 fprintf (map->oFile, "==.\n");
356 if (IS_STATIC (sym->etype))
357 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
359 tfprintf (map->oFile, "!labeldef\n", sym->rname);
360 tfprintf (map->oFile, "\t!ds\n",
361 (unsigned int) size & 0xffff);
366 /*-----------------------------------------------------------------*/
367 /* initPointer - pointer initialization code massaging */
368 /*-----------------------------------------------------------------*/
370 initPointer (initList * ilist, sym_link *toType)
373 ast *expr = list2expr (ilist);
378 /* try it the oldway first */
379 if ((val = constExprValue (expr, FALSE)))
382 /* ( ptr + constant ) */
383 if (IS_AST_OP (expr) &&
384 (expr->opval.op == '+' || expr->opval.op == '-') &&
385 IS_AST_SYM_VALUE (expr->left) &&
386 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
387 compareType(toType, expr->left->ftype) &&
388 IS_AST_LIT_VALUE (expr->right)) {
389 return valForCastAggr (expr->left, expr->left->ftype,
395 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
396 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
397 if (compareType(toType, expr->left->ftype)!=1) {
398 werror (W_INIT_WRONG);
399 printFromToType(expr->left->ftype, toType);
405 /* no then we have to do these cludgy checks */
406 /* pointers can be initialized with address of
407 a variable or address of an array element */
408 if (IS_AST_OP (expr) && expr->opval.op == '&') {
409 /* address of symbol */
410 if (IS_AST_SYM_VALUE (expr->left)) {
411 val = copyValue (AST_VALUE (expr->left));
412 val->type = newLink (DECLARATOR);
413 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
414 DCL_TYPE (val->type) = CPOINTER;
415 DCL_PTR_CONST (val->type) = port->mem.code_ro;
417 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
418 DCL_TYPE (val->type) = FPOINTER;
419 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
420 DCL_TYPE (val->type) = PPOINTER;
421 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
422 DCL_TYPE (val->type) = IPOINTER;
423 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
424 DCL_TYPE (val->type) = EEPPOINTER;
426 DCL_TYPE (val->type) = POINTER;
427 val->type->next = expr->left->ftype;
428 val->etype = getSpec (val->type);
432 /* if address of indexed array */
433 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
434 return valForArray (expr->left);
436 /* if address of structure element then
438 if (IS_AST_OP (expr->left) &&
439 expr->left->opval.op == '.') {
440 return valForStructElem (expr->left->left,
445 (&some_struct)->element */
446 if (IS_AST_OP (expr->left) &&
447 expr->left->opval.op == PTR_OP &&
448 IS_ADDRESS_OF_OP (expr->left->left)) {
449 return valForStructElem (expr->left->left->left,
453 /* case 3. (((char *) &a) +/- constant) */
454 if (IS_AST_OP (expr) &&
455 (expr->opval.op == '+' || expr->opval.op == '-') &&
456 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
457 IS_AST_OP (expr->left->right) &&
458 expr->left->right->opval.op == '&' &&
459 IS_AST_LIT_VALUE (expr->right)) {
461 return valForCastAggr (expr->left->right->left,
462 expr->left->left->opval.lnk,
463 expr->right, expr->opval.op);
466 /* case 4. (char *)(array type) */
467 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
468 IS_ARRAY(expr->right->ftype)) {
470 val = copyValue (AST_VALUE (expr->right));
471 val->type = newLink (DECLARATOR);
472 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
473 DCL_TYPE (val->type) = CPOINTER;
474 DCL_PTR_CONST (val->type) = port->mem.code_ro;
476 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
477 DCL_TYPE (val->type) = FPOINTER;
478 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
479 DCL_TYPE (val->type) = PPOINTER;
480 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
481 DCL_TYPE (val->type) = IPOINTER;
482 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
483 DCL_TYPE (val->type) = EEPPOINTER;
485 DCL_TYPE (val->type) = POINTER;
486 val->type->next = expr->right->ftype->next;
487 val->etype = getSpec (val->type);
491 werror (E_INCOMPAT_PTYPES);
496 /*-----------------------------------------------------------------*/
497 /* printChar - formats and prints a characater string with DB */
498 /*-----------------------------------------------------------------*/
500 printChar (FILE * ofile, char *s, int plen)
503 int len = strlen (s);
508 while (len && pplen < plen)
511 while (i && *s && pplen < plen)
513 if (*s < ' ' || *s == '\"' || *s=='\\')
517 tfprintf (ofile, "\t!ascii\n", buf);
518 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
533 tfprintf (ofile, "\t!ascii\n", buf);
542 tfprintf (ofile, "\t!db !constbyte\n", 0);
545 /*-----------------------------------------------------------------*/
546 /* return the generic pointer high byte for a given pointer type. */
547 /*-----------------------------------------------------------------*/
549 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
557 werror (E_CANNOT_USE_GENERIC_POINTER,
558 iname ? iname : "<null>",
559 oname ? oname : "<null>");
566 return GPTYPE_XSTACK;
568 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
576 /*-----------------------------------------------------------------*/
577 /* printPointerType - generates ival for pointer type */
578 /*-----------------------------------------------------------------*/
580 _printPointerType (FILE * oFile, const char *name)
582 if (options.model == MODEL_FLAT24)
584 if (port->little_endian)
585 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
587 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
591 if (port->little_endian)
592 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
594 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
598 /*-----------------------------------------------------------------*/
599 /* printPointerType - generates ival for pointer type */
600 /*-----------------------------------------------------------------*/
602 printPointerType (FILE * oFile, const char *name)
604 _printPointerType (oFile, name);
605 fprintf (oFile, "\n");
608 /*-----------------------------------------------------------------*/
609 /* printGPointerType - generates ival for generic pointer type */
610 /*-----------------------------------------------------------------*/
612 printGPointerType (FILE * oFile, const char *iname, const char *oname,
613 const unsigned int type)
615 _printPointerType (oFile, iname);
616 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
619 /*-----------------------------------------------------------------*/
620 /* printIvalType - generates ival for int/char */
621 /*-----------------------------------------------------------------*/
623 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
627 /* if initList is deep */
628 if (ilist->type == INIT_DEEP)
629 ilist = ilist->init.deep;
631 if (!(val = list2val (ilist))) {
632 // assuming a warning has been thrown
636 if (val->type != type) {
637 val = valCastLiteral(type, floatFromVal(val));
640 switch (getSize (type)) {
643 tfprintf (oFile, "\t!db !constbyte\n", 0);
645 tfprintf (oFile, "\t!dbs\n",
646 aopLiteral (val, 0));
650 if (port->use_dw_for_init)
651 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
652 else if (port->little_endian)
653 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
655 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
659 tfprintf (oFile, "\t!dw !constword\n", 0);
660 tfprintf (oFile, "\t!dw !constword\n", 0);
662 else if (port->little_endian) {
663 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
664 aopLiteral (val, 0), aopLiteral (val, 1),
665 aopLiteral (val, 2), aopLiteral (val, 3));
668 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
669 aopLiteral (val, 3), aopLiteral (val, 2),
670 aopLiteral (val, 1), aopLiteral (val, 0));
676 /*-----------------------------------------------------------------*/
677 /* printIvalBitFields - generate initializer for bitfields */
678 /*-----------------------------------------------------------------*/
679 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
683 initList *lilist = *ilist ;
684 unsigned long ival = 0;
690 val = list2val(lilist);
692 if (SPEC_BLEN(lsym->etype) > 8) {
693 size += ((SPEC_BLEN (lsym->etype) / 8) +
694 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
697 size = ((SPEC_BLEN (lsym->etype) / 8) +
698 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
700 i = (unsigned long)floatFromVal(val);
701 i <<= SPEC_BSTR (lsym->etype);
703 if (! ( lsym->next &&
704 (IS_BITFIELD(lsym->next->type)) &&
705 (SPEC_BSTR(lsym->next->etype)))) break;
707 lilist = lilist->next;
711 tfprintf (oFile, "\t!db !constbyte\n",ival);
715 tfprintf (oFile, "\t!dw !constword\n",ival);
717 case 4: /* EEP: why is this db and not dw? */
718 tfprintf (oFile, "\t!db !constword,!constword\n",
719 (ival >> 8) & 0xffff, (ival & 0xffff));
726 /*-----------------------------------------------------------------*/
727 /* printIvalStruct - generates initial value for structures */
728 /*-----------------------------------------------------------------*/
730 printIvalStruct (symbol * sym, sym_link * type,
731 initList * ilist, FILE * oFile)
736 sflds = SPEC_STRUCT (type)->fields;
737 if (ilist->type != INIT_DEEP) {
738 werror (E_INIT_STRUCT, sym->name);
742 iloop = ilist->init.deep;
744 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
745 if (IS_BITFIELD(sflds->type)) {
746 printIvalBitFields(&sflds,&iloop,oFile);
748 printIval (sym, sflds->type, iloop, oFile);
752 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
757 /*-----------------------------------------------------------------*/
758 /* printIvalChar - generates initital value for character array */
759 /*-----------------------------------------------------------------*/
761 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
769 val = list2val (ilist);
770 /* if the value is a character string */
771 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
773 if (!DCL_ELEM (type))
774 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
776 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
778 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
780 tfprintf (oFile, "\t!db !constbyte\n", 0);
788 printChar (oFile, s, strlen (s) + 1);
792 /*-----------------------------------------------------------------*/
793 /* printIvalArray - generates code for array initialization */
794 /*-----------------------------------------------------------------*/
796 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
802 /* take care of the special case */
803 /* array of characters can be init */
805 if (IS_CHAR (type->next)) {
806 if (!IS_LITERAL(list2val(ilist)->etype)) {
807 werror (E_CONST_EXPECTED);
810 if (printIvalChar (type,
811 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
812 oFile, SPEC_CVAL (sym->etype).v_char))
815 /* not the special case */
816 if (ilist->type != INIT_DEEP)
818 werror (E_INIT_STRUCT, sym->name);
822 for (iloop=ilist->init.deep; iloop; iloop=iloop->next)
824 printIval (sym, type->next, iloop, oFile);
826 if (++size > DCL_ELEM(type)) {
827 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
832 if (DCL_ELEM(type)) {
833 // pad with zeros if needed
834 if (size<DCL_ELEM(type)) {
835 size = (DCL_ELEM(type) - size) * getSize(type->next);
837 tfprintf (oFile, "\t!db !constbyte\n", 0);
841 // we have not been given a size, but we now know it
842 DCL_ELEM (type) = size;
848 /*-----------------------------------------------------------------*/
849 /* printIvalFuncPtr - generate initial value for function pointers */
850 /*-----------------------------------------------------------------*/
852 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
857 val = list2val (ilist);
860 // an error has been thrown allready
864 if (IS_LITERAL(val->etype)) {
865 if (compareType(type,val->etype)==0) {
866 werror (E_INCOMPAT_TYPES);
867 printFromToType (val->type, type);
869 printIvalCharPtr (NULL, type, val, oFile);
873 /* check the types */
874 if ((dLvl = compareType (val->type, type->next)) <= 0)
876 tfprintf (oFile, "\t!dw !constword\n", 0);
880 /* now generate the name */
883 if (port->use_dw_for_init)
885 tfprintf (oFile, "\t!dws\n", val->name);
889 printPointerType (oFile, val->name);
892 else if (port->use_dw_for_init)
894 tfprintf (oFile, "\t!dws\n", val->sym->rname);
898 printPointerType (oFile, val->sym->rname);
904 /*-----------------------------------------------------------------*/
905 /* printIvalCharPtr - generates initial values for character pointers */
906 /*-----------------------------------------------------------------*/
908 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
912 /* PENDING: this is _very_ mcs51 specific, including a magic
914 It's also endin specific.
916 size = getSize (type);
918 if (val->name && strlen (val->name))
920 if (size == 1) /* This appears to be Z80 specific?? */
923 "\t!dbs\n", val->name);
925 else if (size == FPTRSIZE)
927 if (port->use_dw_for_init)
929 tfprintf (oFile, "\t!dws\n", val->name);
933 printPointerType (oFile, val->name);
936 else if (size == GPTRSIZE)
939 if (IS_PTR (val->type)) {
940 type = DCL_TYPE (val->type);
942 type = PTR_TYPE (SPEC_OCLS (val->etype));
944 if (val->sym && val->sym->isstrlit) {
945 // this is a literal string
948 printGPointerType (oFile, val->name, sym->name, type);
952 fprintf (stderr, "*** internal error: unknown size in "
953 "printIvalCharPtr.\n");
958 // these are literals assigned to pointers
962 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
965 if (port->use_dw_for_init)
966 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
967 else if (port->little_endian)
968 tfprintf (oFile, "\t.byte %s,%s\n",
969 aopLiteral (val, 0), aopLiteral (val, 1));
971 tfprintf (oFile, "\t.byte %s,%s\n",
972 aopLiteral (val, 1), aopLiteral (val, 0));
975 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
976 // non-zero mcs51 generic pointer
977 werror (E_LITERAL_GENERIC);
979 if (port->little_endian) {
980 fprintf (oFile, "\t.byte %s,%s,%s\n",
983 aopLiteral (val, 2));
985 fprintf (oFile, "\t.byte %s,%s,%s\n",
988 aopLiteral (val, 0));
992 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
993 // non-zero ds390 generic pointer
994 werror (E_LITERAL_GENERIC);
996 if (port->little_endian) {
997 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1000 aopLiteral (val, 2),
1001 aopLiteral (val, 3));
1003 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1004 aopLiteral (val, 3),
1005 aopLiteral (val, 2),
1006 aopLiteral (val, 1),
1007 aopLiteral (val, 0));
1015 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1016 addSet (&statsg->syms, val->sym);
1022 /*-----------------------------------------------------------------*/
1023 /* printIvalPtr - generates initial value for pointers */
1024 /*-----------------------------------------------------------------*/
1026 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1032 if (ilist->type == INIT_DEEP)
1033 ilist = ilist->init.deep;
1035 /* function pointer */
1036 if (IS_FUNC (type->next))
1038 printIvalFuncPtr (type, ilist, oFile);
1042 if (!(val = initPointer (ilist, type)))
1045 /* if character pointer */
1046 if (IS_CHAR (type->next))
1047 if (printIvalCharPtr (sym, type, val, oFile))
1050 /* check the type */
1051 if (compareType (type, val->type) == 0) {
1052 werror (W_INIT_WRONG);
1053 printFromToType (val->type, type);
1056 /* if val is literal */
1057 if (IS_LITERAL (val->etype))
1059 switch (getSize (type))
1062 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1065 if (port->use_dw_for_init)
1066 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1067 else if (port->little_endian)
1068 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1070 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1072 case 3: // how about '390??
1073 if (port->little_endian)
1075 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1076 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1080 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1081 aopLiteral (val, 1), aopLiteral (val, 0), GPTYPE_CODE);
1088 size = getSize (type);
1090 if (size == 1) /* Z80 specific?? */
1092 tfprintf (oFile, "\t!dbs\n", val->name);
1094 else if (size == FPTRSIZE)
1096 if (port->use_dw_for_init) {
1097 tfprintf (oFile, "\t!dws\n", val->name);
1099 printPointerType (oFile, val->name);
1102 else if (size == GPTRSIZE)
1104 printGPointerType (oFile, val->name, sym->name,
1105 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1106 PTR_TYPE (SPEC_OCLS (val->etype))));
1111 /*-----------------------------------------------------------------*/
1112 /* printIval - generates code for initial value */
1113 /*-----------------------------------------------------------------*/
1115 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1122 /* update line number for error msgs */
1123 lineno=sym->lineDef;
1125 /* if structure then */
1126 if (IS_STRUCT (type))
1128 printIvalStruct (sym, type, ilist, oFile);
1132 /* if this is an array */
1133 if (IS_ARRAY (type))
1135 printIvalArray (sym, type, ilist, oFile);
1139 // not an aggregate, ilist must be a node
1140 if (ilist->type!=INIT_NODE) {
1141 // or a 1-element list
1142 if (ilist->init.deep->next) {
1143 werror (W_EXCESS_INITIALIZERS, "scalar",
1144 sym->name, sym->lineDef);
1146 ilist=ilist->init.deep;
1150 // and the type must match
1151 itype=ilist->init.node->ftype;
1153 if (compareType(type, itype)==0) {
1154 // special case for literal strings
1155 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1156 // which are really code pointers
1157 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1160 werror (E_TYPE_MISMATCH, "assignment", " ");
1161 printFromToType(itype, type);
1165 /* if this is a pointer */
1168 printIvalPtr (sym, type, ilist, oFile);
1172 /* if type is SPECIFIER */
1175 printIvalType (sym, type, ilist, oFile);
1180 /*-----------------------------------------------------------------*/
1181 /* emitStaticSeg - emitcode for the static segment */
1182 /*-----------------------------------------------------------------*/
1184 emitStaticSeg (memmap * map, FILE * out)
1188 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1190 /* for all variables in this segment do */
1191 for (sym = setFirstItem (map->syms); sym;
1192 sym = setNextItem (map->syms))
1195 /* if it is "extern" then do nothing */
1196 if (IS_EXTERN (sym->etype))
1199 /* if it is not static add it to the public
1201 if (!IS_STATIC (sym->etype))
1203 addSetHead (&publics, sym);
1206 /* print extra debug info if required */
1207 if (options.debug) {
1211 if (IS_STATIC (sym->etype))
1212 fprintf (out, "F%s$", moduleName); /* scope is file */
1214 fprintf (out, "G$"); /* scope is global */
1217 /* symbol is local */
1218 fprintf (out, "L%s$",
1219 (sym->localof ? sym->localof->name : "-null-"));
1220 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1223 /* if it has an absolute address */
1224 if (SPEC_ABSA (sym->etype))
1227 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1229 fprintf (out, "%s\t=\t0x%04x\n",
1231 SPEC_ADDR (sym->etype));
1236 fprintf (out, " == .\n");
1238 /* if it has an initial value */
1241 fprintf (out, "%s:\n", sym->rname);
1243 resolveIvalSym (sym->ival);
1244 printIval (sym, sym->type, sym->ival, out);
1246 /* if sym is a simple string and sym->ival is a string,
1247 WE don't need it anymore */
1248 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1249 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1250 list2val(sym->ival)->sym->isstrlit) {
1251 freeStringSymbol(list2val(sym->ival)->sym);
1255 /* allocate space */
1256 int size = getSize (sym->type);
1259 werror(E_UNKNOWN_SIZE,sym->name);
1261 fprintf (out, "%s:\n", sym->rname);
1262 /* special case for character strings */
1263 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1264 SPEC_CVAL (sym->etype).v_char)
1266 SPEC_CVAL (sym->etype).v_char,
1267 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1269 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1275 /*-----------------------------------------------------------------*/
1276 /* emitMaps - emits the code for the data portion the code */
1277 /*-----------------------------------------------------------------*/
1282 /* no special considerations for the following
1283 data, idata & bit & xdata */
1284 emitRegularMap (data, TRUE, TRUE);
1285 emitRegularMap (idata, TRUE, TRUE);
1286 emitRegularMap (bit, TRUE, FALSE);
1287 emitRegularMap (xdata, TRUE, TRUE);
1288 if (port->genXINIT) {
1289 emitRegularMap (xidata, TRUE, TRUE);
1291 emitRegularMap (sfr, FALSE, FALSE);
1292 emitRegularMap (sfrbit, FALSE, FALSE);
1293 emitRegularMap (home, TRUE, FALSE);
1294 emitRegularMap (code, TRUE, FALSE);
1296 emitStaticSeg (statsg, code->oFile);
1297 if (port->genXINIT) {
1298 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1299 emitStaticSeg (xinit, code->oFile);
1304 /*-----------------------------------------------------------------*/
1305 /* flushStatics - flush all currently defined statics out to file */
1306 /* and delete. Temporary function */
1307 /*-----------------------------------------------------------------*/
1311 emitStaticSeg (statsg, codeOutFile);
1312 statsg->syms = NULL;
1315 /*-----------------------------------------------------------------*/
1316 /* createInterruptVect - creates the interrupt vector */
1317 /*-----------------------------------------------------------------*/
1319 createInterruptVect (FILE * vFile)
1322 mainf = newSymbol ("main", 0);
1325 /* only if the main function exists */
1326 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1328 if (!options.cc_only && !noAssemble && !options.c1mode)
1333 /* if the main is only a prototype ie. no body then do nothing */
1334 if (!IFFUNC_HASBODY(mainf->type))
1336 /* if ! compile only then main function should be present */
1337 if (!options.cc_only && !noAssemble)
1342 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1343 fprintf (vFile, "__interrupt_vect:\n");
1346 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1348 /* "generic" interrupt table header (if port doesn't specify one).
1349 * Look suspiciously like 8051 code to me...
1352 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1355 /* now for the other interrupts */
1356 for (; i < maxInterrupts; i++)
1359 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1361 fprintf (vFile, "\treti\n\t.ds\t7\n");
1368 ";--------------------------------------------------------\n"
1369 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1373 ";--------------------------------------------------------\n"};
1376 /*-----------------------------------------------------------------*/
1377 /* initialComments - puts in some initial comments */
1378 /*-----------------------------------------------------------------*/
1380 initialComments (FILE * afile)
1384 fprintf (afile, "%s", iComments1);
1385 fprintf (afile, "; Version " SDCC_VERSION_STR " %s\n", asctime (localtime (&t)));
1386 fprintf (afile, "%s", iComments2);
1389 /*-----------------------------------------------------------------*/
1390 /* printPublics - generates .global for publics */
1391 /*-----------------------------------------------------------------*/
1393 printPublics (FILE * afile)
1397 fprintf (afile, "%s", iComments2);
1398 fprintf (afile, "; Public variables in this module\n");
1399 fprintf (afile, "%s", iComments2);
1401 for (sym = setFirstItem (publics); sym;
1402 sym = setNextItem (publics))
1403 tfprintf (afile, "\t!global\n", sym->rname);
1406 /*-----------------------------------------------------------------*/
1407 /* printExterns - generates .global for externs */
1408 /*-----------------------------------------------------------------*/
1410 printExterns (FILE * afile)
1414 fprintf (afile, "%s", iComments2);
1415 fprintf (afile, "; Externals used\n");
1416 fprintf (afile, "%s", iComments2);
1418 for (sym = setFirstItem (externs); sym;
1419 sym = setNextItem (externs))
1420 tfprintf (afile, "\t!extern\n", sym->rname);
1423 /*-----------------------------------------------------------------*/
1424 /* emitOverlay - will emit code for the overlay stuff */
1425 /*-----------------------------------------------------------------*/
1427 emitOverlay (FILE * afile)
1431 if (!elementsInSet (ovrSetSets))
1432 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1434 /* for each of the sets in the overlay segment do */
1435 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1436 ovrset = setNextItem (ovrSetSets))
1441 if (elementsInSet (ovrset))
1443 /* output the area informtion */
1444 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1447 for (sym = setFirstItem (ovrset); sym;
1448 sym = setNextItem (ovrset))
1450 /* if extern then it is in the publics table: do nothing */
1451 if (IS_EXTERN (sym->etype))
1454 /* if allocation required check is needed
1455 then check if the symbol really requires
1456 allocation only for local variables */
1457 if (!IS_AGGREGATE (sym->type) &&
1458 !(sym->_isparm && !IS_REGPARM (sym->etype))
1459 && !sym->allocreq && sym->level)
1462 /* if global variable & not static or extern
1463 and addPublics allowed then add it to the public set */
1464 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1465 && !IS_STATIC (sym->etype))
1467 addSetHead (&publics, sym);
1470 /* if extern then do nothing or is a function
1472 if (IS_FUNC (sym->type))
1475 /* print extra debug info if required */
1480 if (IS_STATIC (sym->etype))
1481 fprintf (afile, "F%s$", moduleName); /* scope is file */
1483 fprintf (afile, "G$"); /* scope is global */
1486 /* symbol is local */
1487 fprintf (afile, "L%s$",
1488 (sym->localof ? sym->localof->name : "-null-"));
1489 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1492 /* if is has an absolute address then generate
1493 an equate for this no need to allocate space */
1494 if (SPEC_ABSA (sym->etype))
1498 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1500 fprintf (afile, "%s\t=\t0x%04x\n",
1502 SPEC_ADDR (sym->etype));
1505 int size = getSize(sym->type);
1508 werror(E_UNKNOWN_SIZE,sym->name);
1511 fprintf (afile, "==.\n");
1513 /* allocate space */
1514 tfprintf (afile, "!labeldef\n", sym->rname);
1515 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1523 /*-----------------------------------------------------------------*/
1524 /* spacesToUnderscores - replace spaces with underscores */
1525 /*-----------------------------------------------------------------*/
1527 spacesToUnderscores (char *dest, const char *src, size_t len)
1532 assert(dest != NULL);
1533 assert(src != NULL);
1537 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1538 *p++ = isspace(*src) ? '_' : *src;
1546 /*-----------------------------------------------------------------*/
1547 /* glue - the final glue that hold the whole thing together */
1548 /*-----------------------------------------------------------------*/
1554 FILE *ovrFile = tempfile ();
1555 char moduleBuf[PATH_MAX];
1558 if(port->general.glue_up_main &&
1559 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1561 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1568 addSetHead (&tmpfileSet, ovrFile);
1569 /* print the global struct definitions */
1573 vFile = tempfile ();
1574 /* PENDING: this isnt the best place but it will do */
1575 if (port->general.glue_up_main)
1577 /* create the interrupt vector table */
1578 createInterruptVect (vFile);
1581 addSetHead (&tmpfileSet, vFile);
1583 /* emit code for the all the variables declared */
1585 /* do the overlay segments */
1586 emitOverlay (ovrFile);
1588 outputDebugSymbols();
1590 /* now put it all together into the assembler file */
1591 /* create the assembler file name */
1593 /* -o option overrides default name? */
1594 if ((noAssemble || options.c1mode) && fullDstFileName)
1596 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1600 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1601 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1604 if (!(asmFile = fopen (scratchFileName, "w")))
1606 werror (E_FILE_OPEN_ERR, scratchFileName);
1610 /* initial comments */
1611 initialComments (asmFile);
1613 /* print module name */
1614 tfprintf (asmFile, "\t!module\n",
1615 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1618 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1620 switch(options.model)
1622 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1623 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1624 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1625 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1626 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1627 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1630 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1631 if(options.useXstack) fprintf (asmFile, " --xstack");
1632 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1633 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1634 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1635 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1636 fprintf (asmFile, "\n");
1638 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 )
1640 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1643 tfprintf (asmFile, "\t!fileprelude\n");
1645 /* Let the port generate any global directives, etc. */
1646 if (port->genAssemblerPreamble)
1648 port->genAssemblerPreamble (asmFile);
1651 /* print the global variables in this module */
1652 printPublics (asmFile);
1653 if (port->assembler.externGlobal)
1654 printExterns (asmFile);
1658 /* copy the sfr segment */
1659 fprintf (asmFile, "%s", iComments2);
1660 fprintf (asmFile, "; special function registers\n");
1661 fprintf (asmFile, "%s", iComments2);
1662 copyFile (asmFile, sfr->oFile);
1664 /* copy the sbit segment */
1665 fprintf (asmFile, "%s", iComments2);
1666 fprintf (asmFile, "; special function bits \n");
1667 fprintf (asmFile, "%s", iComments2);
1668 copyFile (asmFile, sfrbit->oFile);
1670 /*JCF: Create the areas for the register banks*/
1671 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1673 fprintf (asmFile, "%s", iComments2);
1674 fprintf (asmFile, "; overlayable register banks \n");
1675 fprintf (asmFile, "%s", iComments2);
1677 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1678 if(RegBankUsed[1]||options.parms_in_bank1)
1679 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1681 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1683 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1687 /* copy the data segment */
1688 fprintf (asmFile, "%s", iComments2);
1689 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1690 fprintf (asmFile, "%s", iComments2);
1691 copyFile (asmFile, data->oFile);
1694 /* create the overlay segments */
1696 fprintf (asmFile, "%s", iComments2);
1697 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1698 fprintf (asmFile, "%s", iComments2);
1699 copyFile (asmFile, ovrFile);
1702 /* create the stack segment MOF */
1703 if (mainf && IFFUNC_HASBODY(mainf->type))
1705 fprintf (asmFile, "%s", iComments2);
1706 fprintf (asmFile, "; Stack segment in internal ram \n");
1707 fprintf (asmFile, "%s", iComments2);
1708 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1709 "__start__stack:\n\t.ds\t1\n\n");
1712 /* create the idata segment */
1713 if ( (idata) && (mcs51_like) ) {
1714 fprintf (asmFile, "%s", iComments2);
1715 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1716 fprintf (asmFile, "%s", iComments2);
1717 copyFile (asmFile, idata->oFile);
1720 /* copy the bit segment */
1722 fprintf (asmFile, "%s", iComments2);
1723 fprintf (asmFile, "; bit data\n");
1724 fprintf (asmFile, "%s", iComments2);
1725 copyFile (asmFile, bit->oFile);
1728 /* if external stack then reserve space of it */
1729 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1731 fprintf (asmFile, "%s", iComments2);
1732 fprintf (asmFile, "; external stack \n");
1733 fprintf (asmFile, "%s", iComments2);
1734 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1735 fprintf (asmFile, "\t.ds 256\n");
1739 /* copy xtern ram data */
1741 fprintf (asmFile, "%s", iComments2);
1742 fprintf (asmFile, "; external ram data\n");
1743 fprintf (asmFile, "%s", iComments2);
1744 copyFile (asmFile, xdata->oFile);
1747 /* copy xternal initialized ram data */
1748 fprintf (asmFile, "%s", iComments2);
1749 fprintf (asmFile, "; external initialized ram data\n");
1750 fprintf (asmFile, "%s", iComments2);
1751 copyFile (asmFile, xidata->oFile);
1753 /* If the port wants to generate any extra areas, let it do so. */
1754 if (port->extraAreas.genExtraAreaDeclaration)
1756 port->extraAreas.genExtraAreaDeclaration(asmFile,
1757 mainf && IFFUNC_HASBODY(mainf->type));
1760 /* copy the interrupt vector table */
1761 if (mainf && IFFUNC_HASBODY(mainf->type))
1763 fprintf (asmFile, "%s", iComments2);
1764 fprintf (asmFile, "; interrupt vector \n");
1765 fprintf (asmFile, "%s", iComments2);
1766 copyFile (asmFile, vFile);
1769 /* copy global & static initialisations */
1770 fprintf (asmFile, "%s", iComments2);
1771 fprintf (asmFile, "; global & static initialisations\n");
1772 fprintf (asmFile, "%s", iComments2);
1774 /* Everywhere we generate a reference to the static_name area,
1775 * (which is currently only here), we immediately follow it with a
1776 * definition of the post_static_name area. This guarantees that
1777 * the post_static_name area will immediately follow the static_name
1780 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1781 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1782 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1784 if (mainf && IFFUNC_HASBODY(mainf->type))
1786 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1787 /* if external stack is specified then the
1788 higher order byte of the xdatalocation is
1789 going into P2 and the lower order going into
1791 if (options.useXstack)
1793 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1794 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1795 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1796 (unsigned int) options.xdata_loc & 0xff);
1799 // This should probably be a port option, but I'm being lazy.
1800 // on the 400, the firmware boot loader gives us a valid stack
1801 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1802 if (!TARGET_IS_DS400)
1804 /* initialise the stack pointer. JCF: aslink takes care of the location */
1805 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1808 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1809 fprintf (asmFile, "\tmov\ta,dpl\n");
1810 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1811 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1812 fprintf (asmFile, "__sdcc_init_data:\n");
1814 // if the port can copy the XINIT segment to XISEG
1815 if (port->genXINIT) {
1816 port->genXINIT(asmFile);
1820 copyFile (asmFile, statsg->oFile);
1822 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1824 /* This code is generated in the post-static area.
1825 * This area is guaranteed to follow the static area
1826 * by the ugly shucking and jiving about 20 lines ago.
1828 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1829 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1835 "%s", iComments2, iComments2);
1836 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1837 copyFile (asmFile, home->oFile);
1839 /* copy over code */
1840 fprintf (asmFile, "%s", iComments2);
1841 fprintf (asmFile, "; code\n");
1842 fprintf (asmFile, "%s", iComments2);
1843 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1844 if (mainf && IFFUNC_HASBODY(mainf->type))
1847 /* entry point @ start of CSEG */
1848 fprintf (asmFile, "__sdcc_program_startup:\n");
1850 /* put in the call to main */
1851 fprintf (asmFile, "\tlcall\t_main\n");
1852 if (options.mainreturn)
1855 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1856 fprintf (asmFile, "\tret\n");
1862 fprintf (asmFile, ";\treturn from main will lock up\n");
1863 fprintf (asmFile, "\tsjmp .\n");
1866 copyFile (asmFile, code->oFile);
1868 if (port->genAssemblerEnd) {
1869 port->genAssemblerEnd(asmFile);
1877 /** Creates a temporary file with unoque file name
1879 - TMP, TEMP, TMPDIR env. varibles
1880 - if Un*x system: /usr/tmp and /tmp
1881 - root directory using mkstemp() if avaliable
1882 - default location using tempnam()
1885 tempfileandname(char *fname, size_t len)
1887 #define TEMPLATE "sdccXXXXXX"
1888 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1890 const char *tmpdir = NULL;
1893 if ((tmpdir = getenv ("TMP")) == NULL)
1894 if ((tmpdir = getenv ("TEMP")) == NULL)
1895 tmpdir = getenv ("TMPDIR");
1899 static int warning_emitted;
1904 if (!warning_emitted)
1906 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1907 warning_emitted = 1;
1913 /* try with /usr/tmp and /tmp on Un*x systems */
1914 struct stat statbuf;
1916 if (tmpdir == NULL) {
1917 if (stat("/usr/tmp", &statbuf) != -1)
1918 tmpdir = "/usr/tmp";
1919 else if (stat("/tmp", &statbuf) != -1)
1927 char fnamebuf[PATH_MAX];
1930 if (fname == NULL || len == 0) {
1932 len = sizeof fnamebuf;
1936 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1938 assert(name_len < len);
1939 if (!(name_len < len)) /* in NDEBUG is defined */
1940 return -1; /* buffer too small, temporary file can not be created */
1942 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1945 name_len = TEMPLATE_LEN;
1947 assert(name_len < len);
1948 if (!(name_len < len)) /* in NDEBUG is defined */
1949 return -1; /* buffer too small, temporary file can not be created */
1951 strcpy(fname, TEMPLATE);
1954 fd = mkstemp(fname);
1958 char *name = tempnam(tmpdir, "sdcc");
1961 perror("Can't create temporary file name");
1965 assert(strlen(name) < len);
1966 if (!(strlen(name) < len)) /* in NDEBUG is defined */
1967 return -1; /* buffer too small, temporary file can not be created */
1969 strcpy(fname, name);
1971 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
1973 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
1979 perror("Can't create temporary file");
1987 /** Create a temporary file name
1993 static char fnamebuf[PATH_MAX];
1995 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1996 fprintf(stderr, "Can't create temporary file name!");
2007 /** Create a temporary file and add it to tmpfileNameSet,
2008 so that it is removed explicitly by rm_tmpfiles()
2009 or implicitly at program extit.
2017 char fnamebuf[PATH_MAX];
2019 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2020 fprintf(stderr, "Can't create temporary file!");
2024 tmp = Safe_strdup(fnamebuf);
2026 addSetHead(&tmpfileNameSet, tmp);
2028 if ((fp = fdopen(fd, "w+b")) == NULL) {
2029 perror("Can't create temporary file!");