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 -------------------------------------------------------------------------*/
28 symbol *interrupts[256];
29 /*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
30 void printIval (symbol *, link *, initList *, FILE *);
32 set *publics = NULL; /* public variables */
34 /* TODO: this should be configurable (DS803C90 uses more than 6) */
35 int maxInterrupts = 6;
36 extern int maxRegBank ;
38 extern char *VersionString;
39 extern FILE *codeOutFile;
40 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
41 /*-----------------------------------------------------------------*/
42 /* closeTmpFiles - closes all tmp files created by the compiler */
43 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
44 /*-----------------------------------------------------------------*/
45 DEFSETFUNC(closeTmpFiles)
55 /*-----------------------------------------------------------------*/
56 /* copyFile - copies source file to destination file */
57 /*-----------------------------------------------------------------*/
58 void copyFile (FILE * dest, FILE * src)
64 if ((ch = fgetc (src)) != EOF)
68 /*-----------------------------------------------------------------*/
69 /* aopLiteral - string from a literal value */
70 /*-----------------------------------------------------------------*/
71 char *aopLiteral (value *val, int offset)
79 /* if it is a float then it gets tricky */
80 /* otherwise it is fairly simple */
81 if (!IS_FLOAT(val->type)) {
82 unsigned long v = floatFromVal(val);
85 sprintf(buffer,"#0x%02x",((char) v) & 0xff);
86 ALLOC_ATOMIC(rs,strlen(buffer)+1);
87 return strcpy (rs,buffer);
90 /* it is type float */
91 fl.f = (float) floatFromVal(val);
93 sprintf(buffer,"#0x%02x",fl.c[3-offset]);
95 sprintf(buffer,"#0x%02x",fl.c[offset]);
97 ALLOC_ATOMIC(rs,strlen(buffer)+1);
98 return strcpy (rs,buffer);
101 /*-----------------------------------------------------------------*/
102 /* emitRegularMap - emit code for maps with no special cases */
103 /*-----------------------------------------------------------------*/
104 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
109 fprintf (map->oFile, "\t.area\t%s\n", map->sname);
111 /* print the area name */
112 for (sym = setFirstItem (map->syms); sym;
113 sym = setNextItem (map->syms)) {
115 /* if extern then do nothing */
116 if (IS_EXTERN (sym->etype))
119 /* if allocation required check is needed
120 then check if the symbol really requires
121 allocation only for local variables */
122 if (arFlag && !IS_AGGREGATE(sym->type) &&
123 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
124 !sym->allocreq && sym->level)
127 /* if global variable & not static or extern
128 and addPublics allowed then add it to the public set */
129 if ((sym->level == 0 ||
130 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
132 !IS_STATIC (sym->etype))
133 addSetHead (&publics, sym);
135 /* if extern then do nothing or is a function
137 if (IS_FUNC (sym->type))
140 /* print extra debug info if required */
141 if (options.debug || sym->level == 0) {
143 cdbSymbol(sym,cdbFile,FALSE,FALSE);
145 if (!sym->level) /* global */
146 if (IS_STATIC(sym->etype))
147 fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
149 fprintf(map->oFile,"G$"); /* scope is global */
151 /* symbol is local */
152 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
153 fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
156 /* if is has an absolute address then generate
157 an equate for this no need to allocate space */
158 if (SPEC_ABSA (sym->etype)) {
159 if (options.debug || sym->level == 0)
160 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
162 fprintf (map->oFile, "%s\t=\t0x%04x\n",
164 SPEC_ADDR (sym->etype));
168 if (options.debug || sym->level == 0)
169 fprintf(map->oFile,"==.\n");
170 fprintf (map->oFile, "%s:\n", sym->rname);
171 fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
174 /* if it has a initial value then do it only if
175 it is a global variable */
176 if (sym->ival && sym->level == 0) {
179 if (IS_AGGREGATE (sym->type))
180 ival = initAggregates (sym, sym->ival, NULL);
182 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
183 decorateType (resolveSymbols (list2expr (sym->ival))));
184 codeOutFile = statsg->oFile;
185 eBBlockFromiCode (iCodeFromAst (ival));
192 /*-----------------------------------------------------------------*/
193 /* initPointer - pointer initialization code massaging */
194 /*-----------------------------------------------------------------*/
195 value *initPointer (initList *ilist)
198 ast *expr = list2expr(ilist);
203 /* try it the oldway first */
204 if ((val = constExprValue(expr,FALSE)))
207 /* no then we have to do these cludgy checks */
208 /* pointers can be initialized with address of
209 a variable or address of an array element */
210 if (IS_AST_OP(expr) && expr->opval.op == '&') {
211 /* address of symbol */
212 if (IS_AST_SYM_VALUE(expr->left)) {
213 val = copyValue(AST_VALUE(expr->left));
214 val->type = newLink();
215 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
216 DCL_TYPE(val->type) = CPOINTER ;
217 DCL_PTR_CONST(val->type) = 1;
220 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
221 DCL_TYPE(val->type) = FPOINTER;
223 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
224 DCL_TYPE(val->type) = PPOINTER ;
226 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
227 DCL_TYPE(val->type) = IPOINTER ;
229 if (SPEC_SCLS(expr->left->etype) == S_FLASH)
230 DCL_TYPE(val->type) = FLPOINTER ;
232 DCL_TYPE(val->type) = POINTER ;
233 val->type->next = expr->left->ftype;
234 val->etype = getSpec(val->type);
238 /* if address of indexed array */
239 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
240 return valForArray(expr->left);
242 /* if address of structure element then
244 if (IS_AST_OP(expr->left) &&
245 expr->left->opval.op == '.' ) {
246 return valForStructElem(expr->left->left,
251 (&some_struct)->element */
252 if (IS_AST_OP(expr->left) &&
253 expr->left->opval.op == PTR_OP &&
254 IS_ADDRESS_OF_OP(expr->left->left))
255 return valForStructElem(expr->left->left->left,
260 werror(E_INIT_WRONG);
265 /*-----------------------------------------------------------------*/
266 /* printChar - formats and prints a characater string with DB */
267 /*-----------------------------------------------------------------*/
268 void printChar (FILE * ofile, char *s, int plen)
271 int len = strlen (s);
274 while (len && pplen < plen) {
276 fprintf (ofile, "\t.ascii /");
278 while (i && *s && pplen < plen) {
279 if (*s < ' ' || *s == '/') {
280 fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
283 fprintf (ofile, "%c", *s++);
287 fprintf (ofile, "/\n");
295 fprintf(ofile,"\t.byte\t0\n");
298 /*-----------------------------------------------------------------*/
299 /* printIvalType - generates ival for int/char */
300 /*-----------------------------------------------------------------*/
301 void printIvalType (link * type, initList * ilist, FILE * oFile)
305 /* if initList is deep */
306 if (ilist->type == INIT_DEEP)
307 ilist = ilist->init.deep;
309 val = list2val (ilist);
310 switch (getSize (type)) {
313 fprintf (oFile, "\t.byte 0\n");
315 fprintf (oFile, "\t.byte %s\n",
316 aopLiteral (val, 0));
321 fprintf (oFile, "\t.word 0\n");
323 fprintf (oFile, "\t.byte %s,%s\n",
324 aopLiteral (val, 0), aopLiteral (val, 1));
329 fprintf (oFile, "\t.word 0,0\n");
331 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
332 aopLiteral (val, 0), aopLiteral (val, 1),
333 aopLiteral (val, 2), aopLiteral (val, 3));
340 /*-----------------------------------------------------------------*/
341 /* printIvalStruct - generates initial value for structures */
342 /*-----------------------------------------------------------------*/
343 void printIvalStruct (symbol * sym,link * type,
344 initList * ilist, FILE * oFile)
349 sflds = SPEC_STRUCT (type)->fields;
350 if (ilist->type != INIT_DEEP) {
351 werror (E_INIT_STRUCT, sym->name);
355 iloop = ilist->init.deep;
357 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
358 printIval (sflds, sflds->type, iloop, oFile);
363 /*-----------------------------------------------------------------*/
364 /* printIvalChar - generates initital value for character array */
365 /*-----------------------------------------------------------------*/
366 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
373 val = list2val (ilist);
374 /* if the value is a character string */
375 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
376 if (!DCL_ELEM (type))
377 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
379 /* if size mismatch */
380 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
381 /* werror (E_ARRAY_BOUND); */
383 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
385 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
387 fprintf (oFile, "\t.byte 0\n");
395 printChar (oFile, s,strlen(s)+1);
399 /*-----------------------------------------------------------------*/
400 /* printIvalArray - generates code for array initialization */
401 /*-----------------------------------------------------------------*/
402 void printIvalArray (symbol * sym, link * type, initList * ilist,
406 int lcnt = 0, size = 0;
408 /* take care of the special case */
409 /* array of characters can be init */
411 if (IS_CHAR (type->next))
412 if (printIvalChar (type,
413 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
414 oFile, SPEC_CVAL (sym->etype).v_char))
417 /* not the special case */
418 if (ilist->type != INIT_DEEP) {
419 werror (E_INIT_STRUCT, sym->name);
423 iloop = ilist->init.deep;
424 lcnt = DCL_ELEM (type);
428 printIval (sym, type->next, iloop, oFile);
429 iloop = (iloop ? iloop->next : NULL);
432 /* if not array limits given & we */
433 /* are out of initialisers then */
434 if (!DCL_ELEM (type) && !iloop)
437 /* no of elements given and we */
438 /* have generated for all of them */
443 /* if we have not been given a size */
444 if (!DCL_ELEM (type))
445 DCL_ELEM (type) = size;
450 /*-----------------------------------------------------------------*/
451 /* printIvalFuncPtr - generate initial value for function pointers */
452 /*-----------------------------------------------------------------*/
453 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
458 val = list2val (ilist);
459 /* check the types */
460 if ((dLvl = checkType (val->type, type->next)) <= 0) {
462 fprintf (oFile, "\t.word 0\n");
466 /* now generate the name */
468 if (IS_LITERAL (val->etype))
469 fprintf (oFile, "\t.byte %s,%s\n",
470 aopLiteral (val, 0), aopLiteral (val, 1));
472 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
473 val->name, val->name);
476 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
477 val->sym->rname, val->sym->rname);
482 /*-----------------------------------------------------------------*/
483 /* printIvalCharPtr - generates initial values for character pointers */
484 /*-----------------------------------------------------------------*/
485 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
489 size = getSize (type);
493 "\t.byte %s", val->name) ;
496 "\t.byte %s,(%s >> 8)",
497 val->name, val->name);
500 fprintf (oFile, ",#0x02\n");
502 fprintf (oFile, "\n");
504 if (val->sym && val->sym->isstrlit)
505 addSet (&statsg->syms, val->sym);
510 /*-----------------------------------------------------------------*/
511 /* printIvalPtr - generates initial value for pointers */
512 /*-----------------------------------------------------------------*/
513 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
518 if (ilist->type == INIT_DEEP)
519 ilist = ilist->init.deep;
521 /* function pointer */
522 if (IS_FUNC (type->next)) {
523 printIvalFuncPtr (type, ilist, oFile);
527 if (!(val = initPointer (ilist)))
530 /* if character pointer */
531 if (IS_CHAR (type->next))
532 if (printIvalCharPtr (sym, type, val, oFile))
536 if (checkType (type, val->type) != 1)
537 werror (E_INIT_WRONG);
539 /* if val is literal */
540 if (IS_LITERAL (val->etype)) {
541 switch (getSize (type)) {
543 fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
546 fprintf (oFile, "\t.byte %s,%s\n",
547 aopLiteral (val, 0), aopLiteral (val, 1));
551 fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
552 aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
558 switch (getSize (type)) {
560 fprintf (oFile, "\t.byte %s\n", val->name);
563 fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
567 fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
568 val->name, val->name, DCL_TYPE(val->type));
573 /*-----------------------------------------------------------------*/
574 /* printIval - generates code for initial value */
575 /*-----------------------------------------------------------------*/
576 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
581 /* if structure then */
582 if (IS_STRUCT (type)) {
583 printIvalStruct (sym, type, ilist, oFile);
587 /* if this is a pointer */
589 printIvalPtr (sym, type, ilist, oFile);
593 /* if this is an array */
594 if (IS_ARRAY (type)) {
595 printIvalArray (sym, type, ilist, oFile);
599 /* if type is SPECIFIER */
600 if (IS_SPEC (type)) {
601 printIvalType (type, ilist, oFile);
606 /*-----------------------------------------------------------------*/
607 /* emitStaticSeg - emitcode for the static segment */
608 /*-----------------------------------------------------------------*/
609 void emitStaticSeg (memmap * map)
613 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
616 /* for all variables in this segment do */
617 for (sym = setFirstItem (map->syms); sym;
618 sym = setNextItem (map->syms)) {
620 /* if it is "extern" then do nothing */
621 if (IS_EXTERN (sym->etype))
624 /* if it is not static add it to the public
626 if (!IS_STATIC (sym->etype))
627 addSetHead (&publics, sym);
629 /* print extra debug info if required */
630 if (options.debug || sym->level == 0) {
632 cdbSymbol(sym,cdbFile,FALSE,FALSE);
634 if (!sym->level) { /* global */
635 if (IS_STATIC(sym->etype))
636 fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
638 fprintf(code->oFile,"G$"); /* scope is global */
641 /* symbol is local */
642 fprintf(code->oFile,"L%s$",
643 (sym->localof ? sym->localof->name : "-null-"));
644 fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
647 /* if it has an absolute address */
648 if (SPEC_ABSA (sym->etype)) {
649 if (options.debug || sym->level == 0)
650 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
652 fprintf (code->oFile, "%s\t=\t0x%04x\n",
654 SPEC_ADDR (sym->etype));
657 if (options.debug || sym->level == 0)
658 fprintf(code->oFile," == .\n");
660 /* if it has an initial value */
662 fprintf (code->oFile, "%s:\n", sym->rname);
664 resolveIvalSym (sym->ival);
665 printIval (sym, sym->type, sym->ival, code->oFile);
670 fprintf (code->oFile, "%s:\n", sym->rname);
671 /* special case for character strings */
672 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
673 SPEC_CVAL (sym->etype).v_char)
674 printChar (code->oFile,
675 SPEC_CVAL (sym->etype).v_char,
676 strlen(SPEC_CVAL (sym->etype).v_char)+1);
678 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
684 /*-----------------------------------------------------------------*/
685 /* emitMaps - emits the code for the data portion the code */
686 /*-----------------------------------------------------------------*/
689 /* no special considerations for the following
690 data, idata & bit & xdata */
691 emitRegularMap (data, TRUE, TRUE);
692 emitRegularMap (idata, TRUE,TRUE);
693 emitRegularMap (bit, TRUE,FALSE);
694 emitRegularMap (xdata, TRUE,TRUE);
695 emitRegularMap (sfr, FALSE,FALSE);
696 emitRegularMap (sfrbit, FALSE,FALSE);
697 emitRegularMap (code, TRUE,FALSE);
698 emitStaticSeg (statsg);
701 /*-----------------------------------------------------------------*/
702 /* createInterruptVect - creates the interrupt vector */
703 /*-----------------------------------------------------------------*/
704 void createInterruptVect (FILE * vFile)
707 mainf = newSymbol ("main", 0);
710 /* only if the main function exists */
711 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
712 if (!options.cc_only)
717 /* if the main is only a prototype ie. no body then do nothing */
719 /* if ! compile only then main function should be present */
720 if (!options.cc_only)
725 fprintf (vFile, "\t.area\t%s\n", CODE_NAME);
726 fprintf (vFile, "__interrupt_vect:\n");
729 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
731 /* "generic" interrupt table header (if port doesn't specify one).
733 * Look suspiciously like 8051 code to me...
736 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
739 /* now for the other interrupts */
740 for (; i < maxInterrupts; i++) {
742 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
744 fprintf (vFile, "\treti\n\t.ds\t7\n");
751 ";--------------------------------------------------------\n"
752 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
756 ";--------------------------------------------------------\n"};
759 /*-----------------------------------------------------------------*/
760 /* initialComments - puts in some initial comments */
761 /*-----------------------------------------------------------------*/
762 void initialComments (FILE * afile)
766 fprintf (afile, "%s", iComments1);
767 fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
768 fprintf (afile, "%s", iComments2);
771 /*-----------------------------------------------------------------*/
772 /* printPublics - generates .global for publics */
773 /*-----------------------------------------------------------------*/
774 void printPublics (FILE * afile)
778 fprintf (afile, "%s", iComments2);
779 fprintf (afile, "; publics variables in this module\n");
780 fprintf (afile, "%s", iComments2);
782 for (sym = setFirstItem (publics); sym;
783 sym = setNextItem (publics))
784 fprintf (afile, "\t.globl %s\n", sym->rname);
787 /*-----------------------------------------------------------------*/
788 /* emitOverlay - will emit code for the overlay stuff */
789 /*-----------------------------------------------------------------*/
790 static void emitOverlay(FILE *afile)
794 if (!elementsInSet(ovrSetSets))
795 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name);
797 /* for each of the sets in the overlay segment do */
798 for (ovrset = setFirstItem(ovrSetSets); ovrset;
799 ovrset = setNextItem(ovrSetSets)) {
803 if (elementsInSet(ovrset)) {
804 /* this dummy area is used to fool the assembler
805 otherwise the assembler will append each of these
806 declarations into one chunk and will not overlay
808 fprintf(afile,"\t.area _DUMMY\n");
809 /* output the area informtion */
810 fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
813 for (sym = setFirstItem(ovrset); sym;
814 sym = setNextItem(ovrset)) {
816 /* if extern then do nothing */
817 if (IS_EXTERN (sym->etype))
820 /* if allocation required check is needed
821 then check if the symbol really requires
822 allocation only for local variables */
823 if (!IS_AGGREGATE(sym->type) &&
824 !(sym->_isparm && !IS_REGPARM(sym->etype))
825 && !sym->allocreq && sym->level)
828 /* if global variable & not static or extern
829 and addPublics allowed then add it to the public set */
830 if ((sym->_isparm && !IS_REGPARM(sym->etype))
831 && !IS_STATIC (sym->etype))
832 addSetHead (&publics, sym);
834 /* if extern then do nothing or is a function
836 if (IS_FUNC (sym->type))
839 /* print extra debug info if required */
840 if (options.debug || sym->level == 0) {
842 cdbSymbol(sym,cdbFile,FALSE,FALSE);
844 if (!sym->level) { /* global */
845 if (IS_STATIC(sym->etype))
846 fprintf(afile,"F%s$",moduleName); /* scope is file */
848 fprintf(afile,"G$"); /* scope is global */
851 /* symbol is local */
852 fprintf(afile,"L%s$",
853 (sym->localof ? sym->localof->name : "-null-"));
854 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
857 /* if is has an absolute address then generate
858 an equate for this no need to allocate space */
859 if (SPEC_ABSA (sym->etype)) {
861 if (options.debug || sym->level == 0)
862 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
864 fprintf (afile, "%s\t=\t0x%04x\n",
866 SPEC_ADDR (sym->etype));
869 if (options.debug || sym->level == 0)
870 fprintf(afile,"==.\n");
873 fprintf (afile, "%s:\n", sym->rname);
874 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
881 /*-----------------------------------------------------------------*/
882 /* glue - the final glue that hold the whole thing together */
883 /*-----------------------------------------------------------------*/
888 FILE *ovrFile = tmpfile();
890 addSetHead(&tmpfileSet,ovrFile);
891 /* print the global struct definitions */
893 cdbStructBlock (0,cdbFile);
896 /* PENDING: this isnt the best place but it will do */
897 if (port->general.glue_up_main) {
898 /* create the interrupt vector table */
899 createInterruptVect (vFile);
902 addSetHead(&tmpfileSet,vFile);
904 /* emit code for the all the variables declared */
906 /* do the overlay segments */
907 emitOverlay(ovrFile);
909 /* now put it all together into the assembler file */
910 /* create the assembler file name */
912 if (!options.c1mode) {
913 sprintf (buffer, srcFileName);
914 strcat (buffer, ".asm");
917 strcpy(buffer, options.out_name);
920 if (!(asmFile = fopen (buffer, "w"))) {
921 werror (E_FILE_OPEN_ERR, buffer);
925 /* initial comments */
926 initialComments (asmFile);
928 /* print module name */
929 fprintf (asmFile, "\t.module %s\n", moduleName);
931 /* Let the port generate any global directives, etc. */
932 if (port->genAssemblerPreamble)
934 port->genAssemblerPreamble(asmFile);
937 /* print the global variables in this module */
938 printPublics (asmFile);
940 /* copy the sfr segment */
941 fprintf (asmFile, "%s", iComments2);
942 fprintf (asmFile, "; special function registers\n");
943 fprintf (asmFile, "%s", iComments2);
944 copyFile (asmFile, sfr->oFile);
946 /* copy the sbit segment */
947 fprintf (asmFile, "%s", iComments2);
948 fprintf (asmFile, "; special function bits \n");
949 fprintf (asmFile, "%s", iComments2);
950 copyFile (asmFile, sfrbit->oFile);
952 /* copy the data segment */
953 fprintf (asmFile, "%s", iComments2);
954 fprintf (asmFile, "; internal ram data\n");
955 fprintf (asmFile, "%s", iComments2);
956 copyFile (asmFile, data->oFile);
959 /* create the overlay segments */
960 fprintf (asmFile, "%s", iComments2);
961 fprintf (asmFile, "; overlayable items in internal ram \n");
962 fprintf (asmFile, "%s", iComments2);
963 copyFile (asmFile, ovrFile);
965 /* create the stack segment MOF */
966 if (mainf && mainf->fbody) {
967 fprintf (asmFile, "%s", iComments2);
968 fprintf (asmFile, "; Stack segment in internal ram \n");
969 fprintf (asmFile, "%s", iComments2);
970 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
971 "__start__stack:\n\t.ds\t1\n\n");
974 /* create the idata segment */
975 fprintf (asmFile, "%s", iComments2);
976 fprintf (asmFile, "; indirectly addressable internal ram data\n");
977 fprintf (asmFile, "%s", iComments2);
978 copyFile (asmFile, idata->oFile);
980 /* copy the bit segment */
981 fprintf (asmFile, "%s", iComments2);
982 fprintf (asmFile, "; bit data\n");
983 fprintf (asmFile, "%s", iComments2);
984 copyFile (asmFile, bit->oFile);
986 /* if external stack then reserve space of it */
987 if (mainf && mainf->fbody && options.useXstack ) {
988 fprintf (asmFile, "%s", iComments2);
989 fprintf (asmFile, "; external stack \n");
990 fprintf (asmFile, "%s", iComments2);
991 fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
992 fprintf (asmFile,"\t.ds 256\n");
996 /* copy xtern ram data */
997 fprintf (asmFile, "%s", iComments2);
998 fprintf (asmFile, "; external ram data\n");
999 fprintf (asmFile, "%s", iComments2);
1000 copyFile (asmFile, xdata->oFile);
1002 /* copy the interrupt vector table */
1003 if (mainf && mainf->fbody) {
1004 fprintf (asmFile, "%s", iComments2);
1005 fprintf (asmFile, "; interrupt vector \n");
1006 fprintf (asmFile, "%s", iComments2);
1007 copyFile (asmFile, vFile);
1010 /* copy global & static initialisations */
1011 fprintf (asmFile, "%s", iComments2);
1012 fprintf (asmFile, "; global & static initialisations\n");
1013 fprintf (asmFile, "%s", iComments2);
1015 /* Everywhere we generate a reference to the static_name area,
1016 * (which is currently only here), we immediately follow it with a
1017 * definition of the post_static_name area. This guarantees that
1018 * the post_static_name area will immediately follow the static_name
1021 fprintf (asmFile, "\t.area %s\n", port->mem.static_name); /* MOF */
1022 fprintf (asmFile, "\t.area %s\n", port->mem.post_static_name);
1023 fprintf (asmFile, "\t.area %s\n", port->mem.static_name);
1025 if (mainf && mainf->fbody) {
1026 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1027 /* if external stack is specified then the
1028 higher order byte of the xdatalocation is
1029 going into P2 and the lower order going into
1031 if (options.useXstack) {
1032 fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1033 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1034 fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1035 (unsigned int)options.xdata_loc & 0xff);
1038 /* initialise the stack pointer */
1039 /* if the user specified a value then use it */
1040 if (options.stack_loc)
1041 fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1043 /* no: we have to compute it */
1044 if (!options.stackOnData && maxRegBank <= 3)
1045 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1047 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1049 fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1050 fprintf (asmFile,"\tmov\ta,dpl\n");
1051 fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1052 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1053 fprintf (asmFile,"__sdcc_init_data:\n");
1056 copyFile (asmFile, statsg->oFile);
1058 if (port->general.glue_up_main && mainf && mainf->fbody)
1060 /* This code is generated in the post-static area.
1061 * This area is guaranteed to follow the static area
1062 * by the ugly shucking and jiving about 20 lines ago.
1064 fprintf(asmFile, "\t.area %s\n", port->mem.post_static_name);
1065 fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1068 /* copy over code */
1069 fprintf (asmFile, "%s", iComments2);
1070 fprintf (asmFile, "; code\n");
1071 fprintf (asmFile, "%s", iComments2);
1072 fprintf (asmFile, "\t.area %s\n", port->mem.code_name);
1073 if (mainf && mainf->fbody) {
1075 /* entry point @ start of CSEG */
1076 fprintf (asmFile,"__sdcc_program_startup:\n");
1078 /* put in the call to main */
1079 fprintf(asmFile,"\tlcall\t_main\n");
1080 if (options.mainreturn) {
1082 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1083 fprintf(asmFile,"\tret\n");
1087 fprintf(asmFile,";\treturn from main will lock up\n");
1088 fprintf(asmFile,"\tsjmp .\n");
1091 copyFile (asmFile, code->oFile);
1094 applyToSet(tmpfileSet,closeTmpFiles);