1 /*-------------------------------------------------------------------------
3 glue.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"
38 #ifdef WORDS_BIGENDIAN
39 #define _ENDIAN(x) (3-x)
41 #define _ENDIAN(x) (x)
44 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
46 extern symbol *interrupts[256];
47 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
51 extern unsigned maxInterrupts;
52 extern int maxRegBank;
54 extern char *VersionString;
55 extern FILE *codeOutFile;
56 extern set *tmpfileSet;
57 extern set *tmpfileNameSet;
58 extern char *iComments1;
59 extern char *iComments2;
60 //extern void emitStaticSeg (memmap * map);
64 set *idataSymSet=NULL;
66 extern DEFSETFUNC (closeTmpFiles);
67 extern DEFSETFUNC (rmTmpFiles);
69 extern void pic16_AnalyzeBanking (void);
70 extern void copyFile (FILE * dest, FILE * src);
71 extern void pic16_InlinepCode(void);
72 extern void pic16_writeUsedRegs(FILE *);
74 extern void initialComments (FILE * afile);
75 extern void printPublics (FILE * afile);
77 extern void printChar (FILE * ofile, char *s, int plen);
78 void pic16_pCodeInitRegisters(void);
79 pCodeOp *pic16_popGetLit(unsigned int lit);
80 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2);
81 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
83 /*-----------------------------------------------------------------*/
84 /* aopLiteral - string from a literal value */
85 /*-----------------------------------------------------------------*/
86 int pic16aopLiteral (value *val, int offset)
93 /* if it is a float then it gets tricky */
94 /* otherwise it is fairly simple */
95 if (!IS_FLOAT(val->type)) {
96 unsigned long v = (unsigned long) floatFromVal(val);
98 return ( (v >> (offset * 8)) & 0xff);
101 /* it is type float */
102 fl.f = (float) floatFromVal(val);
103 #ifdef WORDS_BIGENDIAN
104 return fl.c[3-offset];
113 char tbuffer[512], *tbuf=tbuffer;;
116 /*-----------------------------------------------------------------*/
117 /* emitRegularMap - emit code for maps with no special cases */
118 /*-----------------------------------------------------------------*/
120 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
123 int i, size, bitvars = 0;;
125 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
128 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
130 /* print the area name */
131 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
134 fprintf(stderr, "\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\n",
135 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype));
136 printTypeChain( sym->type, stderr );
137 fprintf(stderr, "\n");
139 /* if extern then add to externs */
140 if (IS_EXTERN (sym->etype)) {
141 checkAddSym(&externs, sym);
145 /* if allocation required check is needed
146 * then check if the symbol really requires
147 * allocation only for local variables */
148 if (arFlag && !IS_AGGREGATE (sym->type) &&
149 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
150 !sym->allocreq && sym->level) {
152 fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
157 /* if global variable & not static or extern
158 * and addPublics allowed then add it to the public set */
159 if ((sym->used) && (sym->level == 0 ||
160 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
162 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
164 checkAddSym(&publics, sym);
165 // addSetHead(&publics, sym);
167 if(IS_STATIC(sym->etype)) {
169 /* add it to udata list */
171 fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
172 sym->name, sym->rname, sym->remat);
174 //, OP_SYMBOL(operandFromSymbol(sym))->name);
175 #define SET_IMPLICIT 1
178 if(IS_STRUCT(sym->type))
182 reg = pic16_allocDirReg( operandFromSymbol( sym ));
183 checkAddReg(&pic16_rel_udata, reg);
186 /* if extern then do nothing or is a function
188 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
189 if(SPEC_OCLS(sym->etype) == code) {
190 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
191 checkAddSym(&publics, sym);
192 // addSetHead(&publics, sym);
198 /* print extra debug info if required */
199 if (options.debug || sym->level == 0) {
200 cdbWriteSymbol (sym); //, cdbFile, FALSE, FALSE);
202 if (!sym->level) /* global */
203 if (IS_STATIC (sym->etype))
204 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
206 fprintf (map->oFile, "G_"); /* scope is global */
208 /* symbol is local */
209 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
210 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
215 * The equates are nice, but do not allow relocatable objects to
216 * be created in the form that I (VR) want to make SDCC to work */
218 /* if is has an absolute address then generate
219 an equate for this no need to allocate space */
220 if (SPEC_ABSA (sym->etype)) {
221 // if (options.debug || sym->level == 0)
222 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
223 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
225 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
227 SPEC_ADDR (sym->etype));
229 /* emit only if it is global */
230 if(sym->level == 0) {
233 reg = pic16_dirregWithName( sym->name );
236 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
237 // __FUNCTION__, __LINE__, sym->name);
239 /* if IS_STRUCT is omitted the following
240 * fixes structures but break char/int etc */
242 if(IS_STRUCT(sym->type))
243 sym->implicit = 1; // mark as implicit
245 reg = pic16_allocDirReg( operandFromSymbol(sym) );
247 if(checkAddReg(&pic16_fix_udata, reg)) {
248 /* and add to globals list if not exist */
249 addSet(&publics, sym);
255 if(!sym->used && (sym->level == 0)) {
258 /* symbol not used, just declared probably, but its in
259 * level 0, so we must declare it fine as global */
261 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
264 if(IS_STRUCT(sym->type))
265 sym->implicit = 1; // mark as implicit
267 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
268 if(checkAddReg(&pic16_rel_udata, reg)) {
269 addSetHead(&publics, sym);
270 // addSetHead(&externs, sym);
275 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
276 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
277 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
278 if (IS_BITVAR (sym->etype)) {
281 fprintf (map->oFile, "\t%s\n", sym->rname);
282 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
283 for (i = 1; i < size; i++)
284 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
287 // fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
290 /* FIXME -- VR Fix the following, so that syms to be placed
291 * in the idata section and let linker decide about their fate */
293 /* if it has an initial value then do it only if
294 it is a global variable */
297 if (sym->ival && sym->level == 0) {
300 // if(SPEC_OCLS(sym->etype)==data) {
301 // fprintf(stderr, "%s: sym %s placed in data\n", map->sname, sym->name);
304 // fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
306 if (IS_AGGREGATE (sym->type))
307 ival = initAggregates (sym, sym->ival, NULL);
310 tic = iCodeFromAst(decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
313 && !IS_CODEPTR(sym->type)
314 && IS_AGGREGATE(OP_SYMBOL(IC_LEFT(tic))->type)) {
316 fprintf(stderr, "symbol %s is a non-code pointer with aggregate initialiser\n", sym->name);
318 nsym = copySymbol( sym );
319 sprintf(tbuffer, "_tempbuf_%s", sym->name);
320 strcpy(nsym->name, tbuffer);
322 // nsym->name = Safe_strdup( tbuf );
324 codeOutFile = statsg->oFile;
326 /* assignment of temporary buffer initialiser */
327 ival = initAggregates(nsym, nsym->ival, NULL);
330 ival = newNode ('=', newAst_VALUE(symbolVal (nsym)),
331 decorateType (resolveSymbols (list2expr (nsym->ival)), RESULT_CHECK));
334 fprintf(stderr, "%s:%d: iCode: %s\n", __FILE__, __LINE__,
335 strdup( printILine(iCodeFromAst(ival) )));
337 eBBlockFromiCode(iCodeFromAst(ival));
339 /* assignment of symbol to temporary buffer */
340 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
341 newAst_VALUE(symbolVal(nsym)));
343 fprintf(stderr, "%s:%d: iCode: %s\n", __FILE__, __LINE__,
344 strdup( printILine(iCodeFromAst(ival) )));
347 eBBlockFromiCode(iCodeFromAst(ival));
353 addSet(&idataSymSet, copySymbol(sym));
354 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
355 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
360 codeOutFile = statsg->oFile;
362 eBBlockFromiCode (iCodeFromAst (ival));
371 /*-----------------------------------------------------------------*/
372 /* printIvalType - generates ival for int/char */
373 /*-----------------------------------------------------------------*/
375 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
380 //fprintf(stderr, "%s\n",__FUNCTION__);
382 /* if initList is deep */
383 if (ilist->type == INIT_DEEP)
384 ilist = ilist->init.deep;
386 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
387 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
390 if (!(val = list2val (ilist))) {
391 // assuming a warning has been thrown
395 if (val->type != type) {
396 val = valCastLiteral(type, floatFromVal(val));
400 ulval = (unsigned long) floatFromVal (val);
404 switch (getSize (type)) {
406 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
407 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
411 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
412 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
413 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
414 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
418 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
419 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
420 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
421 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
422 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
423 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
424 pic16_emitDB(pb, BYTE_IN_LONG(ulval,2));
425 pic16_emitDB(pb, BYTE_IN_LONG(ulval,3));
430 /*-----------------------------------------------------------------*/
431 /* printIvalChar - generates initital value for character array */
432 /*-----------------------------------------------------------------*/
434 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
442 // fprintf(stderr, "%s\n",__FUNCTION__);
446 val = list2val (ilist);
447 /* if the value is a character string */
448 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
450 if (!DCL_ELEM (type))
451 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
453 //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
454 //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
455 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
457 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
461 //tfprintf (oFile, "\t!db !constbyte\n", 0);
462 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
472 //printChar (oFile, s, strlen (s) + 1);
474 for(remain=0; remain<strlen(s); remain++)
476 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
477 //fprintf(stderr,"0x%02x ",s[remain]);
478 pic16_emitDB(pb, s[remain]);
480 //fprintf(stderr,"\n");
485 /*-----------------------------------------------------------------*/
486 /* printIvalArray - generates code for array initialization */
487 /*-----------------------------------------------------------------*/
489 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
493 int lcnt = 0, size = 0;
499 /* take care of the special case */
500 /* array of characters can be init */
502 if (IS_CHAR (type->next)) {
503 fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
504 if (!IS_LITERAL(list2val(ilist)->etype)) {
505 werror (W_INIT_WRONG);
508 if (printIvalChar (type,
509 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
510 pb, SPEC_CVAL (sym->etype).v_char))
513 /* not the special case */
514 if (ilist->type != INIT_DEEP)
516 werror (E_INIT_STRUCT, sym->name);
520 iloop = ilist->init.deep;
521 lcnt = DCL_ELEM (type);
525 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
527 printIval (sym, type->next, iloop, pb);
528 iloop = (iloop ? iloop->next : NULL);
531 /* if not array limits given & we */
532 /* are out of initialisers then */
533 if (!DCL_ELEM (type) && !iloop)
536 /* no of elements given and we */
537 /* have generated for all of them */
539 /* if initializers left */
541 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
547 /* if we have not been given a size */
548 if (!DCL_ELEM (type))
549 DCL_ELEM (type) = size;
554 /*-----------------------------------------------------------------*/
555 /* printIval - generates code for initial value */
556 /*-----------------------------------------------------------------*/
558 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
563 /* if structure then */
564 if (IS_STRUCT (type))
566 //fprintf(stderr,"%s struct\n",__FUNCTION__);
567 //printIvalStruct (sym, type, ilist, oFile);
571 /* if this is a pointer */
574 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
575 //printIvalPtr (sym, type, ilist, oFile);
579 /* if this is an array */
582 //fprintf(stderr,"%s array\n",__FUNCTION__);
583 printIvalArray (sym, type, ilist, pb);
587 /* if type is SPECIFIER */
590 //fprintf(stderr,"%s spec\n",__FUNCTION__);
591 printIvalType (sym, type, ilist, pb);
596 extern void pic16_pCodeConstString(char *name, char *value);
597 /*-----------------------------------------------------------------*/
598 /* emitStaticSeg - emitcode for the static segment */
599 /*-----------------------------------------------------------------*/
601 pic16emitStaticSeg (memmap * map)
605 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
607 //fprintf(stderr, "%s\n",__FUNCTION__);
609 /* for all variables in this segment do */
610 for (sym = setFirstItem (map->syms); sym;
611 sym = setNextItem (map->syms))
615 fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
616 printTypeChain( sym->type, stderr );
621 /* if it is "extern" then do nothing */
622 if (IS_EXTERN (sym->etype)) {
623 checkAddSym(&externs, sym);
624 // addSetHead(&externs, sym);
628 /* if it is not static add it to the public
630 if (!IS_STATIC (sym->etype)) {
631 checkAddSym(&publics, sym);
632 // addSetHead (&publics, sym);
636 /* print extra debug info if required */
637 if (options.debug || sym->level == 0)
639 /* NOTE to me - cdbFile may be null in which case,
640 * the sym name will be printed to stdout. oh well */
642 cdbSymbol (sym, cdbFile, FALSE, FALSE);
646 if (IS_STATIC (sym->etype))
647 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
649 fprintf (code->oFile, "G_"); /* scope is global */
652 /* symbol is local */
653 fprintf (code->oFile, "L%s_",
654 (sym->localof ? sym->localof->name : "-null-"));
655 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
660 /* if it has an absolute address */
661 if (SPEC_ABSA (sym->etype))
663 if (options.debug || sym->level == 0)
664 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
666 fprintf (code->oFile, "%s\t=\t0x%04x\n",
668 SPEC_ADDR (sym->etype));
672 if (options.debug || sym->level == 0)
673 fprintf (code->oFile, " == .\n");
675 /* if it has an initial value */
680 fprintf (code->oFile, "%s:\n", sym->rname);
682 resolveIvalSym (sym->ival, sym->type);
683 //printIval (sym, sym->type, sym->ival, code->oFile);
684 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
686 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
688 printIval (sym, sym->type, sym->ival, pb);
696 fprintf (code->oFile, "%s:\n", sym->rname);
697 /* special case for character strings */
698 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
699 SPEC_CVAL (sym->etype).v_char)
700 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
701 /*printChar (code->oFile,
702 SPEC_CVAL (sym->etype).v_char,
703 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
705 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
713 /*-----------------------------------------------------------------*/
714 /* emitMaps - emits the code for the data portion the code */
715 /*-----------------------------------------------------------------*/
719 /* no special considerations for the following
720 data, idata & bit & xdata */
721 pic16emitRegularMap (data, TRUE, TRUE);
722 pic16emitRegularMap (idata, TRUE, TRUE);
723 pic16emitRegularMap (bit, TRUE, FALSE);
724 pic16emitRegularMap (xdata, TRUE, TRUE);
725 pic16emitRegularMap (sfr, FALSE, FALSE);
726 pic16emitRegularMap (sfrbit, FALSE, FALSE);
727 pic16emitRegularMap (code, TRUE, FALSE);
728 pic16emitStaticSeg (statsg);
731 /*-----------------------------------------------------------------*/
732 /* createInterruptVect - creates the interrupt vector */
733 /*-----------------------------------------------------------------*/
735 pic16createInterruptVect (FILE * vFile)
737 /* if the main is only a prototype ie. no body then do nothing */
739 if (!IFFUNC_HASBODY(mainf->type)) {
740 /* if ! compile only then main function should be present */
741 if (!options.cc_only)
747 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
748 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
749 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
750 fprintf (vFile, "__interrupt_vect:\n");
752 /* this is an overkill since WE are the port,
753 * and we know if we have a genIVT function! */
755 port->genIVT(vFile, interrupts, maxInterrupts);
762 /*-----------------------------------------------------------------*/
763 /* initialComments - puts in some initial comments */
764 /*-----------------------------------------------------------------*/
766 pic16initialComments (FILE * afile)
768 initialComments (afile);
769 fprintf (afile, "; PIC port for the 16-bit core\n");
770 fprintf (afile, iComments2);
774 /*-----------------------------------------------------------------*/
775 /* printPublics - generates global declarations for publics */
776 /*-----------------------------------------------------------------*/
778 pic16printPublics (FILE *afile)
782 fprintf (afile, "%s", iComments2);
783 fprintf (afile, "; public variables in this module\n");
784 fprintf (afile, "%s", iComments2);
786 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
787 fprintf(afile, "\tglobal %s\n", sym->rname);
790 /*-----------------------------------------------------------------*/
791 /* printExterns - generates extern declarations for externs */
792 /*-----------------------------------------------------------------*/
794 pic16_printExterns(FILE *afile)
798 fprintf(afile, "%s", iComments2);
799 fprintf(afile, "; extern variables in this module\n");
800 fprintf(afile, "%s", iComments2);
802 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
803 fprintf(afile, "\textern %s\n", sym->rname);
805 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
806 fprintf(afile, "\textern _%s\n", sym->name);
809 /*-----------------------------------------------------------------*/
810 /* emitOverlay - will emit code for the overlay stuff */
811 /*-----------------------------------------------------------------*/
813 pic16emitOverlay (FILE * afile)
817 if (!elementsInSet (ovrSetSets))
818 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
820 /* for each of the sets in the overlay segment do */
821 for (ovrset = setFirstItem (ovrSetSets); ovrset;
822 ovrset = setNextItem (ovrSetSets))
827 if (elementsInSet (ovrset))
829 /* this dummy area is used to fool the assembler
830 otherwise the assembler will append each of these
831 declarations into one chunk and will not overlay
833 fprintf (afile, ";\t.area _DUMMY\n");
834 /* output the area informtion */
835 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
838 for (sym = setFirstItem (ovrset); sym;
839 sym = setNextItem (ovrset))
842 /* if extern then do nothing */
843 if (IS_EXTERN (sym->etype))
846 /* if allocation required check is needed
847 then check if the symbol really requires
848 allocation only for local variables */
849 if (!IS_AGGREGATE (sym->type) &&
850 !(sym->_isparm && !IS_REGPARM (sym->etype))
851 && !sym->allocreq && sym->level)
854 /* if global variable & not static or extern
855 and addPublics allowed then add it to the public set */
856 if ((sym->_isparm && !IS_REGPARM (sym->etype))
857 && !IS_STATIC (sym->etype)) {
858 checkAddSym(&publics, sym);
859 // addSetHead (&publics, sym);
862 /* if extern then do nothing or is a function
864 if (IS_FUNC (sym->type))
868 /* print extra debug info if required */
869 if (options.debug || sym->level == 0)
872 cdbSymbol (sym, cdbFile, FALSE, FALSE);
876 if (IS_STATIC (sym->etype))
877 fprintf (afile, "F%s_", moduleName); /* scope is file */
879 fprintf (afile, "G_"); /* scope is global */
882 /* symbol is local */
883 fprintf (afile, "L%s_",
884 (sym->localof ? sym->localof->name : "-null-"));
885 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
889 /* if is has an absolute address then generate
890 an equate for this no need to allocate space */
891 if (SPEC_ABSA (sym->etype))
894 if (options.debug || sym->level == 0)
895 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
897 fprintf (afile, "%s\t=\t0x%04x\n",
899 SPEC_ADDR (sym->etype));
903 if (options.debug || sym->level == 0)
904 fprintf (afile, "==.\n");
907 fprintf (afile, "%s:\n", sym->rname);
908 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
916 /*-----------------------------------------------------------------*/
917 /* glue - the final glue that hold the whole thing together */
918 /*-----------------------------------------------------------------*/
925 FILE *ovrFile = tempfile();
928 mainf = newSymbol ("main", 0);
931 mainf = findSymWithLevel(SymbolTab, mainf);
933 /* only if the main function exists */
934 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
935 if (!options.cc_only)
941 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
943 addSetHead(&tmpfileSet,ovrFile);
944 pic16_pCodeInitRegisters();
946 if (mainf && IFFUNC_HASBODY(mainf->type)) {
947 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
951 /* entry point @ start of CSEG */
952 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup\t;VR1",-1));
955 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
956 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
957 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
958 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
961 /* put in the call to main */
962 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
964 if (options.mainreturn) {
965 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
966 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
968 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
969 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
973 /* At this point we've got all the code in the form of pCode structures */
974 /* Now it needs to be rearranged into the order it should be placed in the */
977 pic16_movepBlock2Head('P'); // Last
978 pic16_movepBlock2Head(code->dbName);
979 pic16_movepBlock2Head('X');
980 pic16_movepBlock2Head(statsg->dbName); // First
982 /* print the global struct definitions */
983 // if (options.debug)
984 // cdbStructBlock (0); //,cdbFile);
987 /* PENDING: this isnt the best place but it will do */
988 if (port->general.glue_up_main) {
989 /* create the interrupt vector table */
990 pic16createInterruptVect (vFile);
993 addSetHead(&tmpfileSet,vFile);
995 /* emit code for the all the variables declared */
997 /* do the overlay segments */
998 pic16emitOverlay(ovrFile);
999 pic16_AnalyzepCode('*');
1004 sprintf(buffer, dstFileName);
1005 strcat(buffer, ".calltree");
1006 cFile = fopen(buffer, "w");
1007 pic16_printCallTree( cFile );
1012 pic16_InlinepCode();
1013 pic16_AnalyzepCode('*');
1015 if(pic16_debug_verbose)
1018 /* now put it all together into the assembler file */
1019 /* create the assembler file name */
1020 if ((noAssemble || options.c1mode) && fullDstFileName) {
1021 sprintf (buffer, fullDstFileName);
1023 sprintf (buffer, dstFileName);
1024 strcat (buffer, ".asm");
1027 if (!(asmFile = fopen (buffer, "w"))) {
1028 werror (E_FILE_OPEN_ERR, buffer);
1032 /* initial comments */
1033 pic16initialComments (asmFile);
1035 /* print module name */
1036 fprintf (asmFile, ";\t.module %s\n", moduleName);
1038 /* Let the port generate any global directives, etc. */
1039 if (port->genAssemblerPreamble) {
1040 port->genAssemblerPreamble(asmFile);
1043 /* print the extern variables to this module */
1044 pic16_printExterns(asmFile);
1046 /* print the global variables in this module */
1047 pic16printPublics (asmFile);
1050 /* copy the sfr segment */
1051 fprintf (asmFile, "%s", iComments2);
1052 fprintf (asmFile, "; special function registers\n");
1053 fprintf (asmFile, "%s", iComments2);
1054 copyFile (asmFile, sfr->oFile);
1058 /* Put all variables into a cblock */
1059 pic16_AnalyzeBanking();
1060 pic16_writeUsedRegs(asmFile);
1062 /* create the overlay segments */
1063 fprintf (asmFile, "%s", iComments2);
1064 fprintf (asmFile, "; overlayable items in internal ram \n");
1065 fprintf (asmFile, "%s", iComments2);
1066 copyFile (asmFile, ovrFile);
1068 /* create the stack segment MOF */
1069 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1070 fprintf (asmFile, "%s", iComments2);
1071 fprintf (asmFile, "; Stack segment in internal ram \n");
1072 fprintf (asmFile, "%s", iComments2);
1073 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1074 ";__start__stack:\n;\t.ds\t1\n\n");
1078 /* no indirect data in pic */
1079 /* create the idata segment */
1080 fprintf (asmFile, "%s", iComments2);
1081 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1082 fprintf (asmFile, "%s", iComments2);
1083 copyFile (asmFile, idata->oFile);
1088 /* no xdata in pic */
1089 /* if external stack then reserve space of it */
1090 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1091 fprintf (asmFile, "%s", iComments2);
1092 fprintf (asmFile, "; external stack \n");
1093 fprintf (asmFile, "%s", iComments2);
1094 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1095 fprintf (asmFile,";\t.ds 256\n");
1100 /* no xdata in pic */
1101 /* copy xtern ram data */
1102 fprintf (asmFile, "%s", iComments2);
1103 fprintf (asmFile, "; external ram data\n");
1104 fprintf (asmFile, "%s", iComments2);
1105 copyFile (asmFile, xdata->oFile);
1108 /* copy the bit segment */
1109 fprintf (asmFile, "%s", iComments2);
1110 fprintf (asmFile, "; bit data\n");
1111 fprintf (asmFile, "%s", iComments2);
1112 copyFile (asmFile, bit->oFile);
1115 /* copy the interrupt vector table */
1116 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1117 fprintf (asmFile, "%s", iComments2);
1118 fprintf (asmFile, "; interrupt vector \n");
1119 fprintf (asmFile, "%s", iComments2);
1120 copyFile (asmFile, vFile);
1123 /* copy global & static initialisations */
1124 fprintf (asmFile, "%s", iComments2);
1125 fprintf (asmFile, "; global & static initialisations\n");
1126 fprintf (asmFile, "%s", iComments2);
1129 /* FIXME 8051 Legacy -- VR */
1130 /* Everywhere we generate a reference to the static_name area,
1131 * (which is currently only here), we immediately follow it with a
1132 * definition of the post_static_name area. This guarantees that
1133 * the post_static_name area will immediately follow the static_name
1136 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1137 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1138 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1142 /* copy over code */
1143 fprintf (asmFile, "%s", iComments2);
1144 fprintf (asmFile, "\tcode\n");
1145 fprintf (asmFile, "%s", iComments2);
1148 fprintf(asmFile, "; A code from now on!\n");
1149 pic16_copypCode(asmFile, 'A');
1152 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1153 fprintf(asmFile, "\tcode\n");
1154 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1157 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1158 /* if external stack is specified then the
1159 * higher order byte of the xdatalocation is
1160 * going into P2 and the lower order going into */
1162 if (options.useXstack) {
1163 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1164 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1165 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1166 (unsigned int)options.xdata_loc & 0xff);
1171 // copyFile (stderr, code->oFile);
1173 fprintf(asmFile, "; I code from now on!\n");
1174 pic16_copypCode(asmFile, 'I');
1176 // if(pic16_debug_verbose)
1177 fprintf(asmFile, "; dbName from now on!\n");
1178 pic16_copypCode(asmFile, statsg->dbName);
1181 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1182 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\t;VR2\n");
1186 // if(pic16_debug_verbose)
1187 fprintf(asmFile, "; X code from now on!\n");
1188 pic16_copypCode(asmFile, 'X');
1190 // if(pic16_debug_verbose)
1191 fprintf(asmFile, "; M code from now on!\n");
1192 pic16_copypCode(asmFile, 'M');
1195 pic16_copypCode(asmFile, code->dbName);
1197 pic16_copypCode(asmFile, 'P');
1199 fprintf (asmFile,"\tend\n");