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"
33 #ifdef WORDS_BIGENDIAN
34 #define _ENDIAN(x) (3-x)
36 #define _ENDIAN(x) (x)
39 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
41 extern symbol *interrupts[256];
42 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
46 extern unsigned maxInterrupts;
47 extern int maxRegBank;
49 extern char *VersionString;
50 extern FILE *codeOutFile;
51 extern set *tmpfileSet;
52 extern set *tmpfileNameSet;
53 extern char *iComments1;
54 extern char *iComments2;
55 //extern void emitStaticSeg (memmap * map);
57 extern DEFSETFUNC (closeTmpFiles);
58 extern DEFSETFUNC (rmTmpFiles);
60 extern void AnalyzeBanking (void);
61 extern void copyFile (FILE * dest, FILE * src);
62 extern void ReuseReg(void);
63 extern void InlinepCode(void);
64 extern void writeUsedRegs(FILE *);
66 extern void initialComments (FILE * afile);
67 extern void printPublics (FILE * afile);
69 extern void printChar (FILE * ofile, char *s, int plen);
70 void pCodeInitRegisters(void);
71 int getConfigWord(int address);
73 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
75 /*-----------------------------------------------------------------*/
76 /* aopLiteral - string from a literal value */
77 /*-----------------------------------------------------------------*/
78 int pic14aopLiteral (value *val, int offset)
85 /* if it is a float then it gets tricky */
86 /* otherwise it is fairly simple */
87 if (!IS_FLOAT(val->type)) {
88 unsigned long v = (unsigned long) floatFromVal(val);
90 return ( (v >> (offset * 8)) & 0xff);
93 /* it is type float */
94 fl.f = (float) floatFromVal(val);
95 #ifdef WORDS_BIGENDIAN
96 return fl.c[3-offset];
104 /*-----------------------------------------------------------------*/
105 /* emitRegularMap - emit code for maps with no special cases */
106 /*-----------------------------------------------------------------*/
108 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
113 /* print the area name */
115 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
117 for (sym = setFirstItem (map->syms); sym;
118 sym = setNextItem (map->syms)) {
120 //printf("%s\n",sym->name);
122 /* if extern then add it into the extern list */
123 if (IS_EXTERN (sym->etype)) {
124 addSetHead (&externs, sym);
128 /* if allocation required check is needed
129 then check if the symbol really requires
130 allocation only for local variables */
131 if (arFlag && !IS_AGGREGATE (sym->type) &&
132 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
133 !sym->allocreq && sym->level)
136 /* if global variable & not static or extern
137 and addPublics allowed then add it to the public set */
138 if ((sym->level == 0 ||
139 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
141 !IS_STATIC (sym->etype))
142 addSetHead (&publics, sym);
144 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
147 /* if extern then do nothing or is a function
149 if (IS_FUNC (sym->type))
152 /* print extra debug info if required */
153 if (options.debug || sym->level == 0)
155 if (!sym->level) /* global */
156 if (IS_STATIC (sym->etype))
157 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
159 fprintf (map->oFile, "G_"); /* scope is global */
161 /* symbol is local */
162 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
163 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
167 /* if it has an absolute address then generate
168 an equate for this no need to allocate space */
169 if (SPEC_ABSA (sym->etype))
171 //if (options.debug || sym->level == 0)
172 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
174 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
176 SPEC_ADDR (sym->etype));
182 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
183 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
184 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
185 if (IS_BITVAR (sym->etype))
191 fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
196 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
198 for (i = 1; i < size; i++)
199 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
204 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
207 /* if it has a initial value then do it only if
208 it is a global variable */
209 if (sym->ival && sym->level == 0) {
212 if (IS_AGGREGATE (sym->type))
213 ival = initAggregates (sym, sym->ival, NULL);
215 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
216 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
217 codeOutFile = statsg->oFile;
219 eBBlockFromiCode (iCodeFromAst (ival));
226 /*-----------------------------------------------------------------*/
227 /* printIvalType - generates ival for int/char */
228 /*-----------------------------------------------------------------*/
230 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
235 //fprintf(stderr, "%s\n",__FUNCTION__);
237 /* if initList is deep */
238 if (ilist->type == INIT_DEEP)
239 ilist = ilist->init.deep;
241 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
242 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
245 if (!(val = list2val (ilist))) {
246 // assuming a warning has been thrown
250 if (val->type != type) {
251 val = valCastLiteral(type, floatFromVal(val));
255 ulval = (unsigned long) floatFromVal (val);
259 switch (getSize (type)) {
261 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
265 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
266 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
270 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
271 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
272 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
273 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
278 /*-----------------------------------------------------------------*/
279 /* printIvalBitFields - generate initializer for bitfields */
280 /*-----------------------------------------------------------------*/
281 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
285 initList *lilist = *ilist ;
286 unsigned long ival = 0;
292 val = list2val(lilist);
294 if (SPEC_BLEN(lsym->etype) > 8) {
295 size += ((SPEC_BLEN (lsym->etype) / 8) +
296 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
299 size = ((SPEC_BLEN (lsym->etype) / 8) +
300 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
302 i = (unsigned long)floatFromVal(val);
303 i <<= SPEC_BSTR (lsym->etype);
305 if (! ( lsym->next &&
306 (IS_BITFIELD(lsym->next->type)) &&
307 (SPEC_BSTR(lsym->next->etype)))) break;
309 lilist = lilist->next;
313 //tfprintf (oFile, "\t!db !constbyte\n",ival);
314 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
318 //tfprintf (oFile, "\t!dw !constword\n",ival);
319 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
320 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
323 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
324 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
325 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
326 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
327 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
334 /*-----------------------------------------------------------------*/
335 /* printIvalStruct - generates initial value for structures */
336 /*-----------------------------------------------------------------*/
337 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
340 initList *iloop = NULL;
342 sflds = SPEC_STRUCT (type)->fields;
345 if (ilist->type != INIT_DEEP) {
346 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
350 iloop = ilist->init.deep;
353 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
354 if (IS_BITFIELD(sflds->type)) {
355 printIvalBitFields(&sflds,&iloop,pb);
357 printIval (sym, sflds->type, iloop, pb);
361 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
366 /*-----------------------------------------------------------------*/
367 /* printIvalChar - generates initital value for character array */
368 /*-----------------------------------------------------------------*/
370 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
378 //fprintf(stderr, "%s\n",__FUNCTION__);
382 val = list2val (ilist);
384 /* if the value is a character string */
385 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
387 ilen = DCL_ELEM(val->type);
389 if (!DCL_ELEM (type))
390 DCL_ELEM (type) = ilen;
392 /* emit string constant */
393 for (remain = 0; remain < ilen; remain++) {
394 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
397 /* fill array up to desired size */
398 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
400 //tfprintf (oFile, "\t!db !constbyte\n", 0);
401 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
408 //printChar (oFile, s, strlen (s) + 1);
410 for(remain=0; remain<(int)strlen(s); remain++) {
411 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
412 //fprintf(stderr,"0x%02x ",s[remain]);
414 //fprintf(stderr,"\n");
419 /*-----------------------------------------------------------------*/
420 /* printIvalArray - generates code for array initialization */
421 /*-----------------------------------------------------------------*/
423 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
432 /* take care of the special case */
433 /* array of characters can be init */
435 if (IS_CHAR (type->next)) {
436 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
437 if (!IS_LITERAL(list2val(ilist)->etype)) {
438 werror (W_INIT_WRONG);
441 if (printIvalChar (type,
442 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
443 pb, SPEC_CVAL (sym->etype).v_char))
446 /* not the special case */
447 if (ilist->type != INIT_DEEP) {
448 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
452 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
453 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
454 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
457 printIval (sym, type->next, iloop, pb);
461 if (DCL_ELEM(type)) {
462 // pad with zeros if needed
463 if (size<DCL_ELEM(type)) {
464 size = (DCL_ELEM(type) - size) * getSize(type->next);
466 //tfprintf (oFile, "\t!db !constbyte\n", 0);
467 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
471 // we have not been given a size, but we now know it
472 DCL_ELEM (type) = size;
478 /*-----------------------------------------------------------------*/
479 /* printIvalPtr - generates code for initial value of pointers */
480 /*-----------------------------------------------------------------*/
481 extern value *initPointer (initList *, sym_link *toType);
484 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
491 fprintf (stderr, "FIXME: initializers for pointers...\n");
492 printTypeChain (type, stderr);
494 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
495 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
497 if (ilist && (ilist->type == INIT_DEEP))
498 ilist = ilist->init.deep;
500 /* function pointers */
501 if (IS_FUNC (type->next))
503 assert ( !"function pointers not yet handled" );
504 //printIvalFuncPtr (type, ilist, pb);
507 if (!(val = initPointer (ilist, type)))
510 if (IS_CHAR (type->next))
512 if (printIvalChar (type, ilist, pb, NULL)) return;
516 if (compareType (type, val->type) == 0)
518 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
519 printFromToType (val->type, type);
522 if (IS_LITERAL (val->etype))
524 switch (getSize (type))
527 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
530 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
532 case 3: /* gneric pointers */
533 assert ( !"generic pointers not yet handled" );
535 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
538 assert ( !"invaild size of value -- aborting" );
544 /* now handle symbolic values */
545 switch (getSize (type))
548 fprintf (stderr, "BYTE: %s", val->name);
551 fprintf (stderr, "WORD: %s", val->name);
554 fprintf (stderr, "LONG: %s", val->name);
557 assert ( !"invalid size of (symbolic) value -- aborting" );
561 /*-----------------------------------------------------------------*/
562 /* printIval - generates code for initial value */
563 /*-----------------------------------------------------------------*/
565 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
570 /* if structure then */
571 if (IS_STRUCT (type))
573 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
574 printIvalStruct (sym, type, ilist, pb);
578 /* if this is an array */
581 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
582 printIvalArray (sym, type, ilist, pb);
586 /* if this is a pointer */
589 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
590 printIvalPtr (sym, type, ilist, pb);
594 /* if type is SPECIFIER */
597 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
598 printIvalType (sym, type, ilist, pb);
603 extern void pCodeConstString(char *name, char *value);
604 /*-----------------------------------------------------------------*/
605 /* emitStaticSeg - emitcode for the static segment */
606 /*-----------------------------------------------------------------*/
608 pic14emitStaticSeg (memmap * map)
612 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
614 //fprintf(stderr, "%s\n",__FUNCTION__);
616 /* for all variables in this segment do */
617 for (sym = setFirstItem (map->syms); sym;
618 sym = setNextItem (map->syms))
620 /* if extern then add it into the extern list */
621 if (IS_EXTERN (sym->etype)) {
622 addSetHead (&externs, sym);
626 /* if it is not static add it to the public
628 if (!IS_STATIC (sym->etype))
629 addSetHead (&publics, sym);
631 /* print extra debug info if required */
632 if (options.debug || sym->level == 0)
636 if (IS_STATIC (sym->etype))
637 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
639 fprintf (code->oFile, "G_"); /* scope is global */
642 /* symbol is local */
643 fprintf (code->oFile, "L%s_",
644 (sym->localof ? sym->localof->name : "-null-"));
645 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
649 /* if it has an absolute address */
650 if (SPEC_ABSA (sym->etype))
652 if (options.debug || sym->level == 0)
653 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
655 fprintf (code->oFile, "%s\t=\t0x%04x\n",
657 SPEC_ADDR (sym->etype));
661 if (options.debug || sym->level == 0)
662 fprintf (code->oFile, " == .\n");
664 /* if it has an initial value */
669 fprintf (code->oFile, "%s:\n", sym->rname);
671 resolveIvalSym (sym->ival, sym->type);
672 //printIval (sym, sym->type, sym->ival, code->oFile);
673 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
675 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
677 printIval (sym, sym->type, sym->ival, pb);
684 fprintf (code->oFile, "%s:\n", sym->rname);
685 /* special case for character strings */
686 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
687 SPEC_CVAL (sym->etype).v_char)
688 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
689 /*printChar (code->oFile,
690 SPEC_CVAL (sym->etype).v_char,
691 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
693 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
701 /*-----------------------------------------------------------------*/
702 /* emitMaps - emits the code for the data portion the code */
703 /*-----------------------------------------------------------------*/
707 /* no special considerations for the following
708 data, idata & bit & xdata */
709 pic14emitRegularMap (data, TRUE, TRUE);
710 pic14emitRegularMap (idata, TRUE, TRUE);
711 pic14emitRegularMap (bit, TRUE, FALSE);
712 pic14emitRegularMap (xdata, TRUE, TRUE);
713 pic14emitRegularMap (sfr, FALSE, FALSE);
714 pic14emitRegularMap (sfrbit, FALSE, FALSE);
715 pic14emitRegularMap (code, TRUE, FALSE);
716 pic14emitStaticSeg (statsg);
719 /*-----------------------------------------------------------------*/
720 /* createInterruptVect - creates the interrupt vector */
721 /*-----------------------------------------------------------------*/
723 pic14createInterruptVect (FILE * vFile)
725 mainf = newSymbol ("main", 0);
728 /* only if the main function exists */
729 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
731 struct options *op = &options;
732 if (!(op->cc_only || noAssemble))
733 // werror (E_NO_MAIN);
734 fprintf(stderr,"WARNING: function 'main' undefined\n");
738 /* if the main is only a prototype ie. no body then do nothing */
739 if (!IFFUNC_HASBODY(mainf->type))
741 /* if ! compile only then main function should be present */
742 if (!(options.cc_only || noAssemble))
743 // werror (E_NO_MAIN);
744 fprintf(stderr,"WARNING: function 'main' undefined\n");
748 fprintf (vFile, "%s", iComments2);
749 fprintf (vFile, "; config word \n");
750 fprintf (vFile, "%s", iComments2);
751 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
753 fprintf (vFile, "%s", iComments2);
754 fprintf (vFile, "; reset vector \n");
755 fprintf (vFile, "%s", iComments2);
756 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
757 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
758 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
762 /*-----------------------------------------------------------------*/
763 /* initialComments - puts in some initial comments */
764 /*-----------------------------------------------------------------*/
766 pic14initialComments (FILE * afile)
768 initialComments (afile);
769 fprintf (afile, "; PIC port for the 14-bit core\n");
770 fprintf (afile, iComments2);
774 /*-----------------------------------------------------------------*/
775 /* printExterns - generates extern for external variables */
776 /*-----------------------------------------------------------------*/
778 pic14printExterns (FILE * afile)
782 fprintf (afile, "%s", iComments2);
783 fprintf (afile, "; extern variables in this module\n");
784 fprintf (afile, "%s", iComments2);
786 for (sym = setFirstItem (externs); sym;
787 sym = setNextItem (externs))
788 fprintf (afile, "\textern %s\n", sym->rname);
791 /*-----------------------------------------------------------------*/
792 /* printPublics - generates .global for publics */
793 /*-----------------------------------------------------------------*/
795 pic14printPublics (FILE * afile)
799 fprintf (afile, "%s", iComments2);
800 fprintf (afile, "; publics variables in this module\n");
801 fprintf (afile, "%s", iComments2);
803 for (sym = setFirstItem (publics); sym;
804 sym = setNextItem (publics)) {
806 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
807 if (!IS_BITVAR(sym->type))
808 fprintf (afile, "\tglobal %s\n", sym->rname);
810 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
811 if (!SPEC_ABSA (sym->etype))
812 fprintf (afile, "\tglobal %s\n", sym->rname);
817 /*-----------------------------------------------------------------*/
818 /* emitOverlay - will emit code for the overlay stuff */
819 /*-----------------------------------------------------------------*/
821 pic14emitOverlay (FILE * afile)
825 /* if (!elementsInSet (ovrSetSets))*/
827 /* the hack below, fixes translates for devices which
828 * only have udata_shr memory */
829 fprintf (afile, "%s\t%s\n",
830 (elementsInSet(ovrSetSets)?"":";"),
831 port->mem.overlay_name);
833 /* for each of the sets in the overlay segment do */
834 for (ovrset = setFirstItem (ovrSetSets); ovrset;
835 ovrset = setNextItem (ovrSetSets))
840 if (elementsInSet (ovrset))
842 /* this dummy area is used to fool the assembler
843 otherwise the assembler will append each of these
844 declarations into one chunk and will not overlay
847 /* I don't think this applies to us. We are using gpasm. CRF */
849 fprintf (afile, ";\t.area _DUMMY\n");
850 /* output the area informtion */
851 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
854 for (sym = setFirstItem (ovrset); sym;
855 sym = setNextItem (ovrset))
858 /* if extern then do nothing */
859 if (IS_EXTERN (sym->etype))
862 /* if allocation required check is needed
863 then check if the symbol really requires
864 allocation only for local variables */
865 if (!IS_AGGREGATE (sym->type) &&
866 !(sym->_isparm && !IS_REGPARM (sym->etype))
867 && !sym->allocreq && sym->level)
870 /* if global variable & not static or extern
871 and addPublics allowed then add it to the public set */
872 if ((sym->_isparm && !IS_REGPARM (sym->etype))
873 && !IS_STATIC (sym->etype))
874 addSetHead (&publics, sym);
876 /* if extern then do nothing or is a function
878 if (IS_FUNC (sym->type))
881 /* print extra debug info if required */
882 if (options.debug || sym->level == 0)
886 if (IS_STATIC (sym->etype))
887 fprintf (afile, "F%s_", moduleName); /* scope is file */
889 fprintf (afile, "G_"); /* scope is global */
892 /* symbol is local */
893 fprintf (afile, "L%s_",
894 (sym->localof ? sym->localof->name : "-null-"));
895 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
898 /* if is has an absolute address then generate
899 an equate for this no need to allocate space */
900 if (SPEC_ABSA (sym->etype))
903 if (options.debug || sym->level == 0)
904 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
906 fprintf (afile, "%s\t=\t0x%04x\n",
908 SPEC_ADDR (sym->etype));
912 if (options.debug || sym->level == 0)
913 fprintf (afile, "==.\n");
916 fprintf (afile, "%s:\n", sym->rname);
917 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
925 /*-----------------------------------------------------------------*/
926 /* glue - the final glue that hold the whole thing together */
927 /*-----------------------------------------------------------------*/
934 FILE *ovrFile = tempfile();
936 addSetHead(&tmpfileSet,ovrFile);
937 pCodeInitRegisters();
939 if (mainf && IFFUNC_HASBODY(mainf->type)) {
941 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
944 /* entry point @ start of CSEG */
945 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
946 /* put in the call to main */
947 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
949 if (options.mainreturn) {
951 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
952 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
956 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
957 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
963 /* At this point we've got all the code in the form of pCode structures */
964 /* Now it needs to be rearranged into the order it should be placed in the */
967 movepBlock2Head('P'); // Last
968 movepBlock2Head(code->dbName);
969 movepBlock2Head('X');
970 movepBlock2Head(statsg->dbName); // First
973 /* print the global struct definitions */
979 addSetHead(&tmpfileSet,vFile);
981 /* emit code for the all the variables declared */
983 /* do the overlay segments */
984 pic14emitOverlay(ovrFile);
986 /* PENDING: this isnt the best place but it will do */
987 if (port->general.glue_up_main) {
988 /* create the interrupt vector table */
989 pic14createInterruptVect (vFile);
994 ReuseReg(); // ReuseReg where call tree permits
1003 /* now put it all together into the assembler file */
1004 /* create the assembler file name */
1006 if ((noAssemble || options.c1mode) && fullDstFileName)
1008 sprintf (buffer, fullDstFileName);
1012 sprintf (buffer, dstFileName);
1013 strcat (buffer, ".asm");
1016 if (!(asmFile = fopen (buffer, "w"))) {
1017 werror (E_FILE_OPEN_ERR, buffer);
1021 /* prepare statistics */
1022 resetpCodeStatistics ();
1024 /* initial comments */
1025 pic14initialComments (asmFile);
1027 /* print module name */
1028 fprintf (asmFile, ";\t.module %s\n", moduleName);
1030 /* Let the port generate any global directives, etc. */
1031 if (port->genAssemblerPreamble)
1033 port->genAssemblerPreamble(asmFile);
1036 /* print the extern variables in this module */
1037 pic14printExterns (asmFile);
1039 /* print the global variables in this module */
1040 pic14printPublics (asmFile);
1042 /* copy the sfr segment */
1043 fprintf (asmFile, "%s", iComments2);
1044 fprintf (asmFile, "; special function registers\n");
1045 fprintf (asmFile, "%s", iComments2);
1046 copyFile (asmFile, sfr->oFile);
1049 if (udata_section_name) {
1050 sprintf(udata_name,"%s",udata_section_name);
1052 sprintf(udata_name,"data_%s",moduleName);
1054 fprintf (asmFile, "%s", iComments2);
1055 fprintf (asmFile, "; udata\n");
1056 fprintf (asmFile, "%s", iComments2);
1057 fprintf (asmFile, "%s\tudata\n", udata_name);
1058 copyFile (asmFile, data->oFile);
1060 /* Put all variables into a cblock */
1062 writeUsedRegs(asmFile);
1064 /* create the overlay segments */
1065 fprintf (asmFile, "%s", iComments2);
1066 fprintf (asmFile, "; overlayable items in internal ram \n");
1067 fprintf (asmFile, "%s", iComments2);
1068 copyFile (asmFile, ovrFile);
1072 /* create the stack segment MOF */
1073 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1074 fprintf (asmFile, "%s", iComments2);
1075 fprintf (asmFile, "; Stack segment in internal ram \n");
1076 fprintf (asmFile, "%s", iComments2);
1077 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1078 ";__start__stack:\n;\t.ds\t1\n\n");
1081 /* create the idata segment */
1082 fprintf (asmFile, "%s", iComments2);
1083 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1084 fprintf (asmFile, "%s", iComments2);
1085 copyFile (asmFile, idata->oFile);
1087 /* if external stack then reserve space of it */
1088 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1089 fprintf (asmFile, "%s", iComments2);
1090 fprintf (asmFile, "; external stack \n");
1091 fprintf (asmFile, "%s", iComments2);
1092 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1093 fprintf (asmFile,";\t.ds 256\n");
1096 /* copy xtern ram data */
1097 fprintf (asmFile, "%s", iComments2);
1098 fprintf (asmFile, "; external ram data\n");
1099 fprintf (asmFile, "%s", iComments2);
1100 copyFile (asmFile, xdata->oFile);
1104 /* copy the bit segment */
1105 fprintf (asmFile, "%s", iComments2);
1106 fprintf (asmFile, "; bit data\n");
1107 fprintf (asmFile, "%s", iComments2);
1108 copyFile (asmFile, bit->oFile);
1110 /* copy the interrupt vector table */
1111 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1112 copyFile (asmFile, vFile);
1114 fprintf (asmFile, "%s", iComments2);
1115 fprintf (asmFile, "; interrupt and initialization code\n");
1116 fprintf (asmFile, "%s", iComments2);
1117 fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1119 /* interrupt service routine */
1120 fprintf (asmFile, "__sdcc_interrupt:\n");
1121 copypCode(asmFile, 'I');
1123 /* initialize data memory */
1124 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1125 /* FIXME: This is temporary. The idata section should be used. If
1126 not, we could add a special feature to the linker. This will
1127 work in the mean time. Put all initalized data in main.c */
1128 copypCode(asmFile, statsg->dbName);
1129 fprintf (asmFile,"\tpagesel _main\n");
1130 fprintf (asmFile,"\tgoto _main\n");
1135 /* copy global & static initialisations */
1136 fprintf (asmFile, "%s", iComments2);
1137 fprintf (asmFile, "; global & static initialisations\n");
1138 fprintf (asmFile, "%s", iComments2);
1139 copypCode(asmFile, statsg->dbName);
1143 /* copy over code */
1144 fprintf (asmFile, "%s", iComments2);
1145 fprintf (asmFile, "; code\n");
1146 fprintf (asmFile, "%s", iComments2);
1147 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1150 copypCode(asmFile, 'X');
1152 /* _main function */
1153 copypCode(asmFile, 'M');
1155 /* other functions */
1156 copypCode(asmFile, code->dbName);
1159 copypCode(asmFile, 'P');
1161 dumppCodeStatistics (asmFile);
1163 fprintf (asmFile,"\tend\n");