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 -------------------------------------------------------------------------*/
25 #include "../common.h"
32 #ifdef WORDS_BIGENDIAN
33 #define _ENDIAN(x) (3-x)
35 #define _ENDIAN(x) (x)
38 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
40 extern symbol *interrupts[256];
41 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
45 extern unsigned maxInterrupts;
46 extern int maxRegBank;
48 extern char *VersionString;
49 extern FILE *codeOutFile;
50 extern set *tmpfileSet;
51 extern set *tmpfileNameSet;
52 extern char *iComments1;
53 extern char *iComments2;
54 //extern void emitStaticSeg (memmap * map);
56 extern DEFSETFUNC (closeTmpFiles);
57 extern DEFSETFUNC (rmTmpFiles);
59 extern void AnalyzeBanking (void);
60 extern void copyFile (FILE * dest, FILE * src);
61 extern void ReuseReg(void);
62 extern void InlinepCode(void);
63 extern void writeUsedRegs(FILE *);
65 extern void initialComments (FILE * afile);
66 extern void printPublics (FILE * afile);
68 extern void printChar (FILE * ofile, char *s, int plen);
69 void pCodeInitRegisters(void);
70 int getConfigWord(int address);
72 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value */
76 /*-----------------------------------------------------------------*/
77 int pic14aopLiteral (value *val, int offset)
84 /* if it is a float then it gets tricky */
85 /* otherwise it is fairly simple */
86 if (!IS_FLOAT(val->type)) {
87 unsigned long v = (unsigned long) floatFromVal(val);
89 return ( (v >> (offset * 8)) & 0xff);
92 /* it is type float */
93 fl.f = (float) floatFromVal(val);
94 #ifdef WORDS_BIGENDIAN
95 return fl.c[3-offset];
103 /*-----------------------------------------------------------------*/
104 /* emitRegularMap - emit code for maps with no special cases */
105 /*-----------------------------------------------------------------*/
107 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
112 /* print the area name */
114 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
116 for (sym = setFirstItem (map->syms); sym;
117 sym = setNextItem (map->syms)) {
119 //printf("%s\n",sym->name);
121 /* if extern then add it into the extern list */
122 if (IS_EXTERN (sym->etype)) {
123 addSetHead (&externs, sym);
127 /* if allocation required check is needed
128 then check if the symbol really requires
129 allocation only for local variables */
130 if (arFlag && !IS_AGGREGATE (sym->type) &&
131 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
132 !sym->allocreq && sym->level)
135 /* if global variable & not static or extern
136 and addPublics allowed then add it to the public set */
137 if ((sym->level == 0 ||
138 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
140 !IS_STATIC (sym->etype))
141 addSetHead (&publics, sym);
143 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
146 /* if extern then do nothing or is a function
148 if (IS_FUNC (sym->type))
151 /* print extra debug info if required */
152 if (options.debug || sym->level == 0)
154 if (!sym->level) /* global */
155 if (IS_STATIC (sym->etype))
156 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
158 fprintf (map->oFile, "G_"); /* scope is global */
160 /* symbol is local */
161 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
162 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
166 /* if it has an absolute address then generate
167 an equate for this no need to allocate space */
168 if (SPEC_ABSA (sym->etype))
170 //if (options.debug || sym->level == 0)
171 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
173 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
175 SPEC_ADDR (sym->etype));
181 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
182 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
183 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
184 if (IS_BITVAR (sym->etype))
190 fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
195 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
197 for (i = 1; i < size; i++)
198 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
203 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
206 /* if it has a initial value then do it only if
207 it is a global variable */
208 if (sym->ival && sym->level == 0) {
211 if (IS_AGGREGATE (sym->type))
212 ival = initAggregates (sym, sym->ival, NULL);
214 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
215 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
216 codeOutFile = statsg->oFile;
218 eBBlockFromiCode (iCodeFromAst (ival));
225 /*-----------------------------------------------------------------*/
226 /* printIvalType - generates ival for int/char */
227 /*-----------------------------------------------------------------*/
229 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
234 //fprintf(stderr, "%s\n",__FUNCTION__);
236 /* if initList is deep */
237 if (ilist->type == INIT_DEEP)
238 ilist = ilist->init.deep;
240 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
241 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
244 if (!(val = list2val (ilist))) {
245 // assuming a warning has been thrown
249 if (val->type != type) {
250 val = valCastLiteral(type, floatFromVal(val));
254 ulval = (unsigned long) floatFromVal (val);
258 switch (getSize (type)) {
260 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
264 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
265 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
269 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
270 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
271 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
272 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
277 /*-----------------------------------------------------------------*/
278 /* printIvalBitFields - generate initializer for bitfields */
279 /*-----------------------------------------------------------------*/
280 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
284 initList *lilist = *ilist ;
285 unsigned long ival = 0;
291 val = list2val(lilist);
293 if (SPEC_BLEN(lsym->etype) > 8) {
294 size += ((SPEC_BLEN (lsym->etype) / 8) +
295 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
298 size = ((SPEC_BLEN (lsym->etype) / 8) +
299 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
301 i = (unsigned long)floatFromVal(val);
302 i <<= SPEC_BSTR (lsym->etype);
304 if (! ( lsym->next &&
305 (IS_BITFIELD(lsym->next->type)) &&
306 (SPEC_BSTR(lsym->next->etype)))) break;
308 lilist = lilist->next;
312 //tfprintf (oFile, "\t!db !constbyte\n",ival);
313 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
317 //tfprintf (oFile, "\t!dw !constword\n",ival);
318 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
319 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
322 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
323 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
324 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
325 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
326 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
333 /*-----------------------------------------------------------------*/
334 /* printIvalStruct - generates initial value for structures */
335 /*-----------------------------------------------------------------*/
336 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
339 initList *iloop = NULL;
341 sflds = SPEC_STRUCT (type)->fields;
344 if (ilist->type != INIT_DEEP) {
345 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
349 iloop = ilist->init.deep;
352 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
353 if (IS_BITFIELD(sflds->type)) {
354 printIvalBitFields(&sflds,&iloop,pb);
356 printIval (sym, sflds->type, iloop, pb);
360 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
365 /*-----------------------------------------------------------------*/
366 /* printIvalChar - generates initital value for character array */
367 /*-----------------------------------------------------------------*/
369 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
377 //fprintf(stderr, "%s\n",__FUNCTION__);
381 val = list2val (ilist);
383 /* if the value is a character string */
384 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
386 ilen = DCL_ELEM(val->type);
388 if (!DCL_ELEM (type))
389 DCL_ELEM (type) = ilen;
391 /* emit string constant */
392 for (remain = 0; remain < ilen; remain++) {
393 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
396 /* fill array up to desired size */
397 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
399 //tfprintf (oFile, "\t!db !constbyte\n", 0);
400 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
407 //printChar (oFile, s, strlen (s) + 1);
409 for(remain=0; remain<(int)strlen(s); remain++) {
410 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
411 //fprintf(stderr,"0x%02x ",s[remain]);
413 //fprintf(stderr,"\n");
418 /*-----------------------------------------------------------------*/
419 /* printIvalArray - generates code for array initialization */
420 /*-----------------------------------------------------------------*/
422 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
431 /* take care of the special case */
432 /* array of characters can be init */
434 if (IS_CHAR (type->next)) {
435 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
436 if (!IS_LITERAL(list2val(ilist)->etype)) {
437 werror (W_INIT_WRONG);
440 if (printIvalChar (type,
441 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
442 pb, SPEC_CVAL (sym->etype).v_char))
445 /* not the special case */
446 if (ilist->type != INIT_DEEP) {
447 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
451 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
452 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
453 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
456 printIval (sym, type->next, iloop, pb);
460 if (DCL_ELEM(type)) {
461 // pad with zeros if needed
462 if (size<DCL_ELEM(type)) {
463 size = (DCL_ELEM(type) - size) * getSize(type->next);
465 //tfprintf (oFile, "\t!db !constbyte\n", 0);
466 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
470 // we have not been given a size, but we now know it
471 DCL_ELEM (type) = size;
477 /*-----------------------------------------------------------------*/
478 /* printIval - generates code for initial value */
479 /*-----------------------------------------------------------------*/
481 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
486 /* if structure then */
487 if (IS_STRUCT (type))
489 //fprintf(stderr,"%s struct\n",__FUNCTION__);
490 printIvalStruct (sym, type, ilist, pb);
494 /* if this is a pointer */
497 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
498 //printIvalPtr (sym, type, ilist, oFile);
502 /* if this is an array */
505 //fprintf(stderr,"%s array\n",__FUNCTION__);
506 printIvalArray (sym, type, ilist, pb);
510 /* if type is SPECIFIER */
513 //fprintf(stderr,"%s spec\n",__FUNCTION__);
514 printIvalType (sym, type, ilist, pb);
519 extern void pCodeConstString(char *name, char *value);
520 /*-----------------------------------------------------------------*/
521 /* emitStaticSeg - emitcode for the static segment */
522 /*-----------------------------------------------------------------*/
524 pic14emitStaticSeg (memmap * map)
528 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
530 //fprintf(stderr, "%s\n",__FUNCTION__);
532 /* for all variables in this segment do */
533 for (sym = setFirstItem (map->syms); sym;
534 sym = setNextItem (map->syms))
536 /* if extern then add it into the extern list */
537 if (IS_EXTERN (sym->etype)) {
538 addSetHead (&externs, sym);
542 /* if it is not static add it to the public
544 if (!IS_STATIC (sym->etype))
545 addSetHead (&publics, sym);
547 /* print extra debug info if required */
548 if (options.debug || sym->level == 0)
552 if (IS_STATIC (sym->etype))
553 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
555 fprintf (code->oFile, "G_"); /* scope is global */
558 /* symbol is local */
559 fprintf (code->oFile, "L%s_",
560 (sym->localof ? sym->localof->name : "-null-"));
561 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
565 /* if it has an absolute address */
566 if (SPEC_ABSA (sym->etype))
568 if (options.debug || sym->level == 0)
569 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
571 fprintf (code->oFile, "%s\t=\t0x%04x\n",
573 SPEC_ADDR (sym->etype));
577 if (options.debug || sym->level == 0)
578 fprintf (code->oFile, " == .\n");
580 /* if it has an initial value */
585 fprintf (code->oFile, "%s:\n", sym->rname);
587 resolveIvalSym (sym->ival, sym->type);
588 //printIval (sym, sym->type, sym->ival, code->oFile);
589 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
591 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
593 printIval (sym, sym->type, sym->ival, pb);
600 fprintf (code->oFile, "%s:\n", sym->rname);
601 /* special case for character strings */
602 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
603 SPEC_CVAL (sym->etype).v_char)
604 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
605 /*printChar (code->oFile,
606 SPEC_CVAL (sym->etype).v_char,
607 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
609 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
617 /*-----------------------------------------------------------------*/
618 /* emitMaps - emits the code for the data portion the code */
619 /*-----------------------------------------------------------------*/
623 /* no special considerations for the following
624 data, idata & bit & xdata */
625 pic14emitRegularMap (data, TRUE, TRUE);
626 pic14emitRegularMap (idata, TRUE, TRUE);
627 pic14emitRegularMap (bit, TRUE, FALSE);
628 pic14emitRegularMap (xdata, TRUE, TRUE);
629 pic14emitRegularMap (sfr, FALSE, FALSE);
630 pic14emitRegularMap (sfrbit, FALSE, FALSE);
631 pic14emitRegularMap (code, TRUE, FALSE);
632 pic14emitStaticSeg (statsg);
635 /*-----------------------------------------------------------------*/
636 /* createInterruptVect - creates the interrupt vector */
637 /*-----------------------------------------------------------------*/
639 pic14createInterruptVect (FILE * vFile)
641 mainf = newSymbol ("main", 0);
644 /* only if the main function exists */
645 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
647 struct options *op = &options;
648 if (!(op->cc_only || noAssemble))
649 // werror (E_NO_MAIN);
650 fprintf(stderr,"WARNING: function 'main' undefined\n");
654 /* if the main is only a prototype ie. no body then do nothing */
655 if (!IFFUNC_HASBODY(mainf->type))
657 /* if ! compile only then main function should be present */
658 if (!(options.cc_only || noAssemble))
659 // werror (E_NO_MAIN);
660 fprintf(stderr,"WARNING: function 'main' undefined\n");
664 fprintf (vFile, "%s", iComments2);
665 fprintf (vFile, "; config word \n");
666 fprintf (vFile, "%s", iComments2);
667 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
669 fprintf (vFile, "%s", iComments2);
670 fprintf (vFile, "; reset vector \n");
671 fprintf (vFile, "%s", iComments2);
672 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
673 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
674 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
678 /*-----------------------------------------------------------------*/
679 /* initialComments - puts in some initial comments */
680 /*-----------------------------------------------------------------*/
682 pic14initialComments (FILE * afile)
684 initialComments (afile);
685 fprintf (afile, "; PIC port for the 14-bit core\n");
686 fprintf (afile, iComments2);
690 /*-----------------------------------------------------------------*/
691 /* printExterns - generates extern for external variables */
692 /*-----------------------------------------------------------------*/
694 pic14printExterns (FILE * afile)
698 fprintf (afile, "%s", iComments2);
699 fprintf (afile, "; extern variables in this module\n");
700 fprintf (afile, "%s", iComments2);
702 for (sym = setFirstItem (externs); sym;
703 sym = setNextItem (externs))
704 fprintf (afile, "\textern %s\n", sym->rname);
707 /*-----------------------------------------------------------------*/
708 /* printPublics - generates .global for publics */
709 /*-----------------------------------------------------------------*/
711 pic14printPublics (FILE * afile)
715 fprintf (afile, "%s", iComments2);
716 fprintf (afile, "; publics variables in this module\n");
717 fprintf (afile, "%s", iComments2);
719 for (sym = setFirstItem (publics); sym;
720 sym = setNextItem (publics)) {
722 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
723 if (!IS_BITVAR(sym->type))
724 fprintf (afile, "\tglobal %s\n", sym->rname);
726 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
727 if (!SPEC_ABSA (sym->etype))
728 fprintf (afile, "\tglobal %s\n", sym->rname);
733 /*-----------------------------------------------------------------*/
734 /* emitOverlay - will emit code for the overlay stuff */
735 /*-----------------------------------------------------------------*/
737 pic14emitOverlay (FILE * afile)
741 /* if (!elementsInSet (ovrSetSets))*/
743 /* the hack below, fixes translates for devices which
744 * only have udata_shr memory */
745 fprintf (afile, "%s\t%s\n",
746 (elementsInSet(ovrSetSets)?"":";"),
747 port->mem.overlay_name);
749 /* for each of the sets in the overlay segment do */
750 for (ovrset = setFirstItem (ovrSetSets); ovrset;
751 ovrset = setNextItem (ovrSetSets))
756 if (elementsInSet (ovrset))
758 /* this dummy area is used to fool the assembler
759 otherwise the assembler will append each of these
760 declarations into one chunk and will not overlay
763 /* I don't think this applies to us. We are using gpasm. CRF */
765 fprintf (afile, ";\t.area _DUMMY\n");
766 /* output the area informtion */
767 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
770 for (sym = setFirstItem (ovrset); sym;
771 sym = setNextItem (ovrset))
774 /* if extern then do nothing */
775 if (IS_EXTERN (sym->etype))
778 /* if allocation required check is needed
779 then check if the symbol really requires
780 allocation only for local variables */
781 if (!IS_AGGREGATE (sym->type) &&
782 !(sym->_isparm && !IS_REGPARM (sym->etype))
783 && !sym->allocreq && sym->level)
786 /* if global variable & not static or extern
787 and addPublics allowed then add it to the public set */
788 if ((sym->_isparm && !IS_REGPARM (sym->etype))
789 && !IS_STATIC (sym->etype))
790 addSetHead (&publics, sym);
792 /* if extern then do nothing or is a function
794 if (IS_FUNC (sym->type))
797 /* print extra debug info if required */
798 if (options.debug || sym->level == 0)
802 if (IS_STATIC (sym->etype))
803 fprintf (afile, "F%s_", moduleName); /* scope is file */
805 fprintf (afile, "G_"); /* scope is global */
808 /* symbol is local */
809 fprintf (afile, "L%s_",
810 (sym->localof ? sym->localof->name : "-null-"));
811 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
814 /* if is has an absolute address then generate
815 an equate for this no need to allocate space */
816 if (SPEC_ABSA (sym->etype))
819 if (options.debug || sym->level == 0)
820 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
822 fprintf (afile, "%s\t=\t0x%04x\n",
824 SPEC_ADDR (sym->etype));
828 if (options.debug || sym->level == 0)
829 fprintf (afile, "==.\n");
832 fprintf (afile, "%s:\n", sym->rname);
833 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
841 /*-----------------------------------------------------------------*/
842 /* glue - the final glue that hold the whole thing together */
843 /*-----------------------------------------------------------------*/
850 FILE *ovrFile = tempfile();
852 addSetHead(&tmpfileSet,ovrFile);
853 pCodeInitRegisters();
855 if (mainf && IFFUNC_HASBODY(mainf->type)) {
857 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
860 /* entry point @ start of CSEG */
861 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
862 /* put in the call to main */
863 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
865 if (options.mainreturn) {
867 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
868 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
872 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
873 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
879 /* At this point we've got all the code in the form of pCode structures */
880 /* Now it needs to be rearranged into the order it should be placed in the */
883 movepBlock2Head('P'); // Last
884 movepBlock2Head(code->dbName);
885 movepBlock2Head('X');
886 movepBlock2Head(statsg->dbName); // First
889 /* print the global struct definitions */
895 addSetHead(&tmpfileSet,vFile);
897 /* emit code for the all the variables declared */
899 /* do the overlay segments */
900 pic14emitOverlay(ovrFile);
902 /* PENDING: this isnt the best place but it will do */
903 if (port->general.glue_up_main) {
904 /* create the interrupt vector table */
905 pic14createInterruptVect (vFile);
910 ReuseReg(); // ReuseReg where call tree permits
919 /* now put it all together into the assembler file */
920 /* create the assembler file name */
922 if ((noAssemble || options.c1mode) && fullDstFileName)
924 sprintf (buffer, fullDstFileName);
928 sprintf (buffer, dstFileName);
929 strcat (buffer, ".asm");
932 if (!(asmFile = fopen (buffer, "w"))) {
933 werror (E_FILE_OPEN_ERR, buffer);
937 /* initial comments */
938 pic14initialComments (asmFile);
940 /* print module name */
941 fprintf (asmFile, ";\t.module %s\n", moduleName);
943 /* Let the port generate any global directives, etc. */
944 if (port->genAssemblerPreamble)
946 port->genAssemblerPreamble(asmFile);
949 /* print the extern variables in this module */
950 pic14printExterns (asmFile);
952 /* print the global variables in this module */
953 pic14printPublics (asmFile);
955 /* copy the sfr segment */
956 fprintf (asmFile, "%s", iComments2);
957 fprintf (asmFile, "; special function registers\n");
958 fprintf (asmFile, "%s", iComments2);
959 copyFile (asmFile, sfr->oFile);
962 if (udata_section_name) {
963 sprintf(udata_name,"%s",udata_section_name);
965 sprintf(udata_name,"data_%s",moduleName);
967 fprintf (asmFile, "%s", iComments2);
968 fprintf (asmFile, "; udata\n");
969 fprintf (asmFile, "%s", iComments2);
970 fprintf (asmFile, "%s\tudata\n", udata_name);
971 copyFile (asmFile, data->oFile);
973 /* Put all variables into a cblock */
975 writeUsedRegs(asmFile);
977 /* create the overlay segments */
978 fprintf (asmFile, "%s", iComments2);
979 fprintf (asmFile, "; overlayable items in internal ram \n");
980 fprintf (asmFile, "%s", iComments2);
981 copyFile (asmFile, ovrFile);
985 /* create the stack segment MOF */
986 if (mainf && IFFUNC_HASBODY(mainf->type)) {
987 fprintf (asmFile, "%s", iComments2);
988 fprintf (asmFile, "; Stack segment in internal ram \n");
989 fprintf (asmFile, "%s", iComments2);
990 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
991 ";__start__stack:\n;\t.ds\t1\n\n");
994 /* create the idata segment */
995 fprintf (asmFile, "%s", iComments2);
996 fprintf (asmFile, "; indirectly addressable internal ram data\n");
997 fprintf (asmFile, "%s", iComments2);
998 copyFile (asmFile, idata->oFile);
1000 /* if external stack then reserve space of it */
1001 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1002 fprintf (asmFile, "%s", iComments2);
1003 fprintf (asmFile, "; external stack \n");
1004 fprintf (asmFile, "%s", iComments2);
1005 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1006 fprintf (asmFile,";\t.ds 256\n");
1009 /* copy xtern ram data */
1010 fprintf (asmFile, "%s", iComments2);
1011 fprintf (asmFile, "; external ram data\n");
1012 fprintf (asmFile, "%s", iComments2);
1013 copyFile (asmFile, xdata->oFile);
1017 /* copy the bit segment */
1018 fprintf (asmFile, "%s", iComments2);
1019 fprintf (asmFile, "; bit data\n");
1020 fprintf (asmFile, "%s", iComments2);
1021 copyFile (asmFile, bit->oFile);
1023 /* copy the interrupt vector table */
1024 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1025 copyFile (asmFile, vFile);
1027 fprintf (asmFile, "%s", iComments2);
1028 fprintf (asmFile, "; interrupt and initialization code\n");
1029 fprintf (asmFile, "%s", iComments2);
1030 fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1032 /* interrupt service routine */
1033 fprintf (asmFile, "__sdcc_interrupt:\n");
1034 copypCode(asmFile, 'I');
1036 /* initialize data memory */
1037 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1038 /* FIXME: This is temporary. The idata section should be used. If
1039 not, we could add a special feature to the linker. This will
1040 work in the mean time. Put all initalized data in main.c */
1041 copypCode(asmFile, statsg->dbName);
1042 fprintf (asmFile,"\tpagesel _main\n");
1043 fprintf (asmFile,"\tgoto _main\n");
1048 /* copy global & static initialisations */
1049 fprintf (asmFile, "%s", iComments2);
1050 fprintf (asmFile, "; global & static initialisations\n");
1051 fprintf (asmFile, "%s", iComments2);
1052 copypCode(asmFile, statsg->dbName);
1056 /* copy over code */
1057 fprintf (asmFile, "%s", iComments2);
1058 fprintf (asmFile, "; code\n");
1059 fprintf (asmFile, "%s", iComments2);
1060 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1063 copypCode(asmFile, 'X');
1065 /* _main function */
1066 copypCode(asmFile, 'M');
1068 /* other functions */
1069 copypCode(asmFile, code->dbName);
1072 copypCode(asmFile, 'P');
1074 fprintf (asmFile,"\tend\n");