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];
103 /* set of already emitted symbols; we store only pointers to the emitted
104 * symbol names so these MUST NO BE CHANGED afterwards... */
105 static set *symbolsEmitted = NULL;
107 /*-------------------------------------------------------------------*/
108 /* emitSymbolToFile - write a symbol definition only if it is not */
109 /* already present */
110 /*-------------------------------------------------------------------*/
112 emitSymbolToFile (FILE *of, const char *name, int size)
116 /* check whether the symbol is already defined */
117 for (sym = (const char *) setFirstItem (symbolsEmitted);
119 sym = (const char *) setNextItem (symbolsEmitted))
121 if (!strcmp (sym, name))
123 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
128 /* new symbol -- define it */
129 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
130 fprintf (of, "%s\tres\t%d\n", name, size);
131 addSet (&symbolsEmitted, (void *) name);
134 /*-----------------------------------------------------------------*/
135 /* emitRegularMap - emit code for maps with no special cases */
136 /*-----------------------------------------------------------------*/
138 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
143 /* print the area name */
145 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
147 for (sym = setFirstItem (map->syms); sym;
148 sym = setNextItem (map->syms)) {
150 //printf("%s\n",sym->name);
152 /* if extern then add it into the extern list */
153 if (IS_EXTERN (sym->etype)) {
154 addSetHead (&externs, sym);
158 /* if allocation required check is needed
159 then check if the symbol really requires
160 allocation only for local variables */
161 if (arFlag && !IS_AGGREGATE (sym->type) &&
162 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
163 !sym->allocreq && sym->level)
166 /* if global variable & not static or extern
167 and addPublics allowed then add it to the public set */
168 if ((sym->level == 0 ||
169 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
171 !IS_STATIC (sym->etype))
172 addSetHead (&publics, sym);
174 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
177 /* if extern then do nothing or is a function
179 if (IS_FUNC (sym->type))
182 /* print extra debug info if required */
183 if (options.debug || sym->level == 0)
185 if (!sym->level) /* global */
186 if (IS_STATIC (sym->etype))
187 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
189 fprintf (map->oFile, "G_"); /* scope is global */
191 /* symbol is local */
192 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
193 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
197 /* if it has an absolute address then generate
198 an equate for this no need to allocate space */
199 if (SPEC_ABSA (sym->etype))
201 //if (options.debug || sym->level == 0)
202 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
204 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
206 SPEC_ADDR (sym->etype));
212 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
213 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
214 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
215 if (IS_BITVAR (sym->etype))
221 emitSymbolToFile (map->oFile, sym->rname, getSize (sym->type) & 0xffff);
226 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
228 for (i = 1; i < size; i++)
229 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
234 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
237 /* if it has a initial value then do it only if
238 it is a global variable */
239 if (sym->ival && sym->level == 0) {
242 if (IS_AGGREGATE (sym->type))
243 ival = initAggregates (sym, sym->ival, NULL);
245 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
246 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
247 codeOutFile = statsg->oFile;
249 eBBlockFromiCode (iCodeFromAst (ival));
256 /*-----------------------------------------------------------------*/
257 /* printIvalType - generates ival for int/char */
258 /*-----------------------------------------------------------------*/
260 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
265 //fprintf(stderr, "%s\n",__FUNCTION__);
267 /* if initList is deep */
268 if (ilist->type == INIT_DEEP)
269 ilist = ilist->init.deep;
271 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
272 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
275 if (!(val = list2val (ilist))) {
276 // assuming a warning has been thrown
280 if (val->type != type) {
281 val = valCastLiteral(type, floatFromVal(val));
285 ulval = (unsigned long) floatFromVal (val);
289 switch (getSize (type)) {
291 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
295 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
296 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
300 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
301 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
302 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
303 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
308 /*-----------------------------------------------------------------*/
309 /* printIvalBitFields - generate initializer for bitfields */
310 /*-----------------------------------------------------------------*/
311 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
315 initList *lilist = *ilist ;
316 unsigned long ival = 0;
322 val = list2val(lilist);
324 if (SPEC_BLEN(lsym->etype) > 8) {
325 size += ((SPEC_BLEN (lsym->etype) / 8) +
326 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
329 size = ((SPEC_BLEN (lsym->etype) / 8) +
330 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
332 i = (unsigned long)floatFromVal(val);
333 i <<= SPEC_BSTR (lsym->etype);
335 if (! ( lsym->next &&
336 (IS_BITFIELD(lsym->next->type)) &&
337 (SPEC_BSTR(lsym->next->etype)))) break;
339 lilist = lilist->next;
343 //tfprintf (oFile, "\t!db !constbyte\n",ival);
344 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
348 //tfprintf (oFile, "\t!dw !constword\n",ival);
349 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
350 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
353 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
354 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
355 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
356 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
357 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
364 /*-----------------------------------------------------------------*/
365 /* printIvalStruct - generates initial value for structures */
366 /*-----------------------------------------------------------------*/
367 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
370 initList *iloop = NULL;
372 sflds = SPEC_STRUCT (type)->fields;
375 if (ilist->type != INIT_DEEP) {
376 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
380 iloop = ilist->init.deep;
383 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
384 if (IS_BITFIELD(sflds->type)) {
385 printIvalBitFields(&sflds,&iloop,pb);
387 printIval (sym, sflds->type, iloop, pb);
391 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
396 /*-----------------------------------------------------------------*/
397 /* printIvalChar - generates initital value for character array */
398 /*-----------------------------------------------------------------*/
400 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
408 //fprintf(stderr, "%s\n",__FUNCTION__);
412 val = list2val (ilist);
414 /* if the value is a character string */
415 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
417 ilen = DCL_ELEM(val->type);
419 if (!DCL_ELEM (type))
420 DCL_ELEM (type) = ilen;
422 /* emit string constant */
423 for (remain = 0; remain < ilen; remain++) {
424 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
427 /* fill array up to desired size */
428 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
430 //tfprintf (oFile, "\t!db !constbyte\n", 0);
431 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
438 //printChar (oFile, s, strlen (s) + 1);
440 for(remain=0; remain<(int)strlen(s); remain++) {
441 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
442 //fprintf(stderr,"0x%02x ",s[remain]);
444 //fprintf(stderr,"\n");
449 /*-----------------------------------------------------------------*/
450 /* printIvalArray - generates code for array initialization */
451 /*-----------------------------------------------------------------*/
453 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
462 /* take care of the special case */
463 /* array of characters can be init */
465 if (IS_CHAR (type->next)) {
466 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
467 if (!IS_LITERAL(list2val(ilist)->etype)) {
468 werror (W_INIT_WRONG);
471 if (printIvalChar (type,
472 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
473 pb, SPEC_CVAL (sym->etype).v_char))
476 /* not the special case */
477 if (ilist->type != INIT_DEEP) {
478 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
482 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
483 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
484 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
487 printIval (sym, type->next, iloop, pb);
491 if (DCL_ELEM(type)) {
492 // pad with zeros if needed
493 if (size<DCL_ELEM(type)) {
494 size = (DCL_ELEM(type) - size) * getSize(type->next);
496 //tfprintf (oFile, "\t!db !constbyte\n", 0);
497 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
501 // we have not been given a size, but we now know it
502 DCL_ELEM (type) = size;
508 /*-----------------------------------------------------------------*/
509 /* printIvalPtr - generates code for initial value of pointers */
510 /*-----------------------------------------------------------------*/
511 extern value *initPointer (initList *, sym_link *toType);
514 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
521 fprintf (stderr, "FIXME: initializers for pointers...\n");
522 printTypeChain (type, stderr);
524 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
525 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
527 if (ilist && (ilist->type == INIT_DEEP))
528 ilist = ilist->init.deep;
530 /* function pointers */
531 if (IS_FUNC (type->next))
533 assert ( !"function pointers not yet handled" );
534 //printIvalFuncPtr (type, ilist, pb);
537 if (!(val = initPointer (ilist, type)))
540 if (IS_CHAR (type->next))
542 if (printIvalChar (type, ilist, pb, NULL)) return;
546 if (compareType (type, val->type) == 0)
548 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
549 printFromToType (val->type, type);
552 if (IS_LITERAL (val->etype))
554 switch (getSize (type))
557 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
560 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
562 case 3: /* gneric pointers */
563 assert ( !"generic pointers not yet handled" );
565 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
568 assert ( !"invaild size of value -- aborting" );
574 /* now handle symbolic values */
575 switch (getSize (type))
578 fprintf (stderr, "BYTE: %s", val->name);
581 fprintf (stderr, "WORD: %s", val->name);
584 fprintf (stderr, "LONG: %s", val->name);
587 assert ( !"invalid size of (symbolic) value -- aborting" );
591 /*-----------------------------------------------------------------*/
592 /* printIval - generates code for initial value */
593 /*-----------------------------------------------------------------*/
595 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
600 /* if structure then */
601 if (IS_STRUCT (type))
603 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
604 printIvalStruct (sym, type, ilist, pb);
608 /* if this is an array */
611 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
612 printIvalArray (sym, type, ilist, pb);
616 /* if this is a pointer */
619 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
620 printIvalPtr (sym, type, ilist, pb);
624 /* if type is SPECIFIER */
627 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
628 printIvalType (sym, type, ilist, pb);
633 extern void pCodeConstString(char *name, char *value);
634 /*-----------------------------------------------------------------*/
635 /* emitStaticSeg - emitcode for the static segment */
636 /*-----------------------------------------------------------------*/
638 pic14emitStaticSeg (memmap * map)
642 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
644 //fprintf(stderr, "%s\n",__FUNCTION__);
646 /* for all variables in this segment do */
647 for (sym = setFirstItem (map->syms); sym;
648 sym = setNextItem (map->syms))
650 /* if extern then add it into the extern list */
651 if (IS_EXTERN (sym->etype)) {
652 addSetHead (&externs, sym);
656 /* if it is not static add it to the public
658 if (!IS_STATIC (sym->etype))
659 addSetHead (&publics, sym);
661 /* print extra debug info if required */
662 if (options.debug || sym->level == 0)
666 if (IS_STATIC (sym->etype))
667 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
669 fprintf (code->oFile, "G_"); /* scope is global */
672 /* symbol is local */
673 fprintf (code->oFile, "L%s_",
674 (sym->localof ? sym->localof->name : "-null-"));
675 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
679 /* if it has an absolute address */
680 if (SPEC_ABSA (sym->etype))
682 if (options.debug || sym->level == 0)
683 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
685 fprintf (code->oFile, "%s\t=\t0x%04x\n",
687 SPEC_ADDR (sym->etype));
691 if (options.debug || sym->level == 0)
692 fprintf (code->oFile, " == .\n");
694 /* if it has an initial value */
699 fprintf (code->oFile, "%s:\n", sym->rname);
701 resolveIvalSym (sym->ival, sym->type);
702 //printIval (sym, sym->type, sym->ival, code->oFile);
703 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
705 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
707 printIval (sym, sym->type, sym->ival, pb);
714 fprintf (code->oFile, "%s:\n", sym->rname);
715 /* special case for character strings */
716 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
717 SPEC_CVAL (sym->etype).v_char)
718 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
719 /*printChar (code->oFile,
720 SPEC_CVAL (sym->etype).v_char,
721 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
723 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
731 /*-----------------------------------------------------------------*/
732 /* emitMaps - emits the code for the data portion the code */
733 /*-----------------------------------------------------------------*/
737 /* no special considerations for the following
738 data, idata & bit & xdata */
739 pic14emitRegularMap (data, TRUE, TRUE);
740 pic14emitRegularMap (idata, TRUE, TRUE);
741 pic14emitRegularMap (bit, TRUE, FALSE);
742 pic14emitRegularMap (xdata, TRUE, TRUE);
743 pic14emitRegularMap (sfr, FALSE, FALSE);
744 pic14emitRegularMap (sfrbit, FALSE, FALSE);
745 pic14emitRegularMap (code, TRUE, FALSE);
746 pic14emitStaticSeg (statsg);
749 /*-----------------------------------------------------------------*/
750 /* createInterruptVect - creates the interrupt vector */
751 /*-----------------------------------------------------------------*/
753 pic14createInterruptVect (FILE * vFile)
755 mainf = newSymbol ("main", 0);
758 /* only if the main function exists */
759 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
761 struct options *op = &options;
762 if (!(op->cc_only || noAssemble))
763 // werror (E_NO_MAIN);
764 fprintf(stderr,"WARNING: function 'main' undefined\n");
768 /* if the main is only a prototype ie. no body then do nothing */
769 if (!IFFUNC_HASBODY(mainf->type))
771 /* if ! compile only then main function should be present */
772 if (!(options.cc_only || noAssemble))
773 // werror (E_NO_MAIN);
774 fprintf(stderr,"WARNING: function 'main' undefined\n");
778 fprintf (vFile, "%s", iComments2);
779 fprintf (vFile, "; config word \n");
780 fprintf (vFile, "%s", iComments2);
781 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
783 fprintf (vFile, "%s", iComments2);
784 fprintf (vFile, "; reset vector \n");
785 fprintf (vFile, "%s", iComments2);
786 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
787 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
788 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
792 /*-----------------------------------------------------------------*/
793 /* initialComments - puts in some initial comments */
794 /*-----------------------------------------------------------------*/
796 pic14initialComments (FILE * afile)
798 initialComments (afile);
799 fprintf (afile, "; PIC port for the 14-bit core\n");
800 fprintf (afile, iComments2);
804 /*-----------------------------------------------------------------*/
805 /* printExterns - generates extern for external variables */
806 /*-----------------------------------------------------------------*/
808 pic14printExterns (FILE * afile)
812 fprintf (afile, "%s", iComments2);
813 fprintf (afile, "; extern variables in this module\n");
814 fprintf (afile, "%s", iComments2);
816 for (sym = setFirstItem (externs); sym;
817 sym = setNextItem (externs))
818 fprintf (afile, "\textern %s\n", sym->rname);
821 /*-----------------------------------------------------------------*/
822 /* printPublics - generates .global for publics */
823 /*-----------------------------------------------------------------*/
825 pic14printPublics (FILE * afile)
829 fprintf (afile, "%s", iComments2);
830 fprintf (afile, "; publics variables in this module\n");
831 fprintf (afile, "%s", iComments2);
833 for (sym = setFirstItem (publics); sym;
834 sym = setNextItem (publics)) {
836 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
837 if (!IS_BITVAR(sym->type))
838 fprintf (afile, "\tglobal %s\n", sym->rname);
840 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
841 if (!SPEC_ABSA (sym->etype))
842 fprintf (afile, "\tglobal %s\n", sym->rname);
847 /*-----------------------------------------------------------------*/
848 /* emitOverlay - will emit code for the overlay stuff */
849 /*-----------------------------------------------------------------*/
851 pic14emitOverlay (FILE * afile)
855 /* if (!elementsInSet (ovrSetSets))*/
857 /* the hack below, fixes translates for devices which
858 * only have udata_shr memory */
859 fprintf (afile, "%s\t%s\n",
860 (elementsInSet(ovrSetSets)?"":";"),
861 port->mem.overlay_name);
863 /* for each of the sets in the overlay segment do */
864 for (ovrset = setFirstItem (ovrSetSets); ovrset;
865 ovrset = setNextItem (ovrSetSets))
870 if (elementsInSet (ovrset))
872 /* this dummy area is used to fool the assembler
873 otherwise the assembler will append each of these
874 declarations into one chunk and will not overlay
877 /* I don't think this applies to us. We are using gpasm. CRF */
879 fprintf (afile, ";\t.area _DUMMY\n");
880 /* output the area informtion */
881 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
884 for (sym = setFirstItem (ovrset); sym;
885 sym = setNextItem (ovrset))
888 /* if extern then do nothing */
889 if (IS_EXTERN (sym->etype))
892 /* if allocation required check is needed
893 then check if the symbol really requires
894 allocation only for local variables */
895 if (!IS_AGGREGATE (sym->type) &&
896 !(sym->_isparm && !IS_REGPARM (sym->etype))
897 && !sym->allocreq && sym->level)
900 /* if global variable & not static or extern
901 and addPublics allowed then add it to the public set */
902 if ((sym->_isparm && !IS_REGPARM (sym->etype))
903 && !IS_STATIC (sym->etype))
904 addSetHead (&publics, sym);
906 /* if extern then do nothing or is a function
908 if (IS_FUNC (sym->type))
911 /* print extra debug info if required */
912 if (options.debug || sym->level == 0)
916 if (IS_STATIC (sym->etype))
917 fprintf (afile, "F%s_", moduleName); /* scope is file */
919 fprintf (afile, "G_"); /* scope is global */
922 /* symbol is local */
923 fprintf (afile, "L%s_",
924 (sym->localof ? sym->localof->name : "-null-"));
925 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
928 /* if is has an absolute address then generate
929 an equate for this no need to allocate space */
930 if (SPEC_ABSA (sym->etype))
933 if (options.debug || sym->level == 0)
934 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
936 fprintf (afile, "%s\t=\t0x%04x\n",
938 SPEC_ADDR (sym->etype));
942 if (options.debug || sym->level == 0)
943 fprintf (afile, "==.\n");
946 fprintf (afile, "%s:\n", sym->rname);
947 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
955 /*-----------------------------------------------------------------*/
956 /* glue - the final glue that hold the whole thing together */
957 /*-----------------------------------------------------------------*/
964 FILE *ovrFile = tempfile();
966 addSetHead(&tmpfileSet,ovrFile);
967 pCodeInitRegisters();
969 if (mainf && IFFUNC_HASBODY(mainf->type)) {
971 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
974 /* entry point @ start of CSEG */
975 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
976 /* put in the call to main */
977 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
979 if (options.mainreturn) {
981 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
982 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
986 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
987 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
993 /* At this point we've got all the code in the form of pCode structures */
994 /* Now it needs to be rearranged into the order it should be placed in the */
997 movepBlock2Head('P'); // Last
998 movepBlock2Head(code->dbName);
999 movepBlock2Head('X');
1000 movepBlock2Head(statsg->dbName); // First
1003 /* print the global struct definitions */
1009 addSetHead(&tmpfileSet,vFile);
1011 /* emit code for the all the variables declared */
1013 /* do the overlay segments */
1014 pic14emitOverlay(ovrFile);
1016 /* PENDING: this isnt the best place but it will do */
1017 if (port->general.glue_up_main) {
1018 /* create the interrupt vector table */
1019 pic14createInterruptVect (vFile);
1024 ReuseReg(); // ReuseReg where call tree permits
1033 /* now put it all together into the assembler file */
1034 /* create the assembler file name */
1036 if ((noAssemble || options.c1mode) && fullDstFileName)
1038 sprintf (buffer, fullDstFileName);
1042 sprintf (buffer, dstFileName);
1043 strcat (buffer, ".asm");
1046 if (!(asmFile = fopen (buffer, "w"))) {
1047 werror (E_FILE_OPEN_ERR, buffer);
1051 /* prepare statistics */
1052 resetpCodeStatistics ();
1054 /* initial comments */
1055 pic14initialComments (asmFile);
1057 /* print module name */
1058 fprintf (asmFile, ";\t.module %s\n", moduleName);
1060 /* Let the port generate any global directives, etc. */
1061 if (port->genAssemblerPreamble)
1063 port->genAssemblerPreamble(asmFile);
1066 /* print the extern variables in this module */
1067 pic14printExterns (asmFile);
1069 /* print the global variables in this module */
1070 pic14printPublics (asmFile);
1072 /* copy the sfr segment */
1073 fprintf (asmFile, "%s", iComments2);
1074 fprintf (asmFile, "; special function registers\n");
1075 fprintf (asmFile, "%s", iComments2);
1076 copyFile (asmFile, sfr->oFile);
1079 if (udata_section_name) {
1080 sprintf(udata_name,"%s",udata_section_name);
1082 sprintf(udata_name,"data_%s",moduleName);
1084 fprintf (asmFile, "%s", iComments2);
1085 fprintf (asmFile, "; udata\n");
1086 fprintf (asmFile, "%s", iComments2);
1087 fprintf (asmFile, "%s\tudata\n", udata_name);
1088 copyFile (asmFile, data->oFile);
1090 /* Put all variables into a cblock */
1092 writeUsedRegs(asmFile);
1094 /* create the overlay segments */
1095 fprintf (asmFile, "%s", iComments2);
1096 fprintf (asmFile, "; overlayable items in internal ram \n");
1097 fprintf (asmFile, "%s", iComments2);
1098 copyFile (asmFile, ovrFile);
1102 /* create the stack segment MOF */
1103 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1104 fprintf (asmFile, "%s", iComments2);
1105 fprintf (asmFile, "; Stack segment in internal ram \n");
1106 fprintf (asmFile, "%s", iComments2);
1107 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1108 ";__start__stack:\n;\t.ds\t1\n\n");
1111 /* create the idata segment */
1112 fprintf (asmFile, "%s", iComments2);
1113 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1114 fprintf (asmFile, "%s", iComments2);
1115 copyFile (asmFile, idata->oFile);
1117 /* if external stack then reserve space of it */
1118 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1119 fprintf (asmFile, "%s", iComments2);
1120 fprintf (asmFile, "; external stack \n");
1121 fprintf (asmFile, "%s", iComments2);
1122 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1123 fprintf (asmFile,";\t.ds 256\n");
1126 /* copy xtern ram data */
1127 fprintf (asmFile, "%s", iComments2);
1128 fprintf (asmFile, "; external ram data\n");
1129 fprintf (asmFile, "%s", iComments2);
1130 copyFile (asmFile, xdata->oFile);
1134 /* copy the bit segment */
1135 fprintf (asmFile, "%s", iComments2);
1136 fprintf (asmFile, "; bit data\n");
1137 fprintf (asmFile, "%s", iComments2);
1138 copyFile (asmFile, bit->oFile);
1140 /* copy the interrupt vector table */
1141 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1142 copyFile (asmFile, vFile);
1144 fprintf (asmFile, "%s", iComments2);
1145 fprintf (asmFile, "; interrupt and initialization code\n");
1146 fprintf (asmFile, "%s", iComments2);
1147 fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1149 /* interrupt service routine */
1150 fprintf (asmFile, "__sdcc_interrupt:\n");
1151 copypCode(asmFile, 'I');
1153 /* initialize data memory */
1154 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1155 /* FIXME: This is temporary. The idata section should be used. If
1156 not, we could add a special feature to the linker. This will
1157 work in the mean time. Put all initalized data in main.c */
1158 copypCode(asmFile, statsg->dbName);
1159 fprintf (asmFile,"\tpagesel _main\n");
1160 fprintf (asmFile,"\tgoto _main\n");
1165 /* copy global & static initialisations */
1166 fprintf (asmFile, "%s", iComments2);
1167 fprintf (asmFile, "; global & static initialisations\n");
1168 fprintf (asmFile, "%s", iComments2);
1169 copypCode(asmFile, statsg->dbName);
1173 /* copy over code */
1174 fprintf (asmFile, "%s", iComments2);
1175 fprintf (asmFile, "; code\n");
1176 fprintf (asmFile, "%s", iComments2);
1177 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1180 copypCode(asmFile, 'X');
1182 /* _main function */
1183 copypCode(asmFile, 'M');
1185 /* other functions */
1186 copypCode(asmFile, code->dbName);
1189 copypCode(asmFile, 'P');
1191 dumppCodeStatistics (asmFile);
1193 fprintf (asmFile,"\tend\n");