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 );
617 fprintf(stderr, "\n");
621 /* if it is "extern" then do nothing */
622 if (IS_EXTERN (sym->etype)) {
624 /* do not emit if it is a config word declaration */
625 if(!SPEC_ABSA(sym->etype)
626 || (SPEC_ABSA(sym->etype) && !IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))))
627 checkAddSym(&externs, sym);
631 /* if it is not static add it to the public
633 if (!IS_STATIC (sym->etype)) {
635 /* do not emit if it is a config word declaration */
636 if(!SPEC_ABSA(sym->etype)
637 || (SPEC_ABSA(sym->etype) && !IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))))
638 checkAddSym(&publics, sym);
642 /* print extra debug info if required */
643 if (options.debug || sym->level == 0)
645 /* NOTE to me - cdbFile may be null in which case,
646 * the sym name will be printed to stdout. oh well */
648 cdbSymbol (sym, cdbFile, FALSE, FALSE);
652 if (IS_STATIC (sym->etype))
653 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
655 fprintf (code->oFile, "G_"); /* scope is global */
658 /* symbol is local */
659 fprintf (code->oFile, "L%s_",
660 (sym->localof ? sym->localof->name : "-null-"));
661 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
666 /* if it has an absolute address */
667 if (SPEC_ABSA (sym->etype))
669 fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
670 __FILE__, __LINE__, sym->name);
672 if (options.debug || sym->level == 0)
673 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
675 fprintf (code->oFile, "%s\t=\t0x%04x\n",
677 SPEC_ADDR (sym->etype));
681 fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
682 __FILE__, __LINE__, sym->name);
684 if (options.debug || sym->level == 0)
685 fprintf (code->oFile, " == .\n");
687 /* if it has an initial value */
692 fprintf (code->oFile, "%s:\n", sym->rname);
694 resolveIvalSym (sym->ival, sym->type);
695 //printIval (sym, sym->type, sym->ival, code->oFile);
696 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
698 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
700 printIval (sym, sym->type, sym->ival, pb);
708 fprintf (code->oFile, "%s:\n", sym->rname);
709 /* special case for character strings */
710 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
711 SPEC_CVAL (sym->etype).v_char)
712 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
713 /*printChar (code->oFile,
714 SPEC_CVAL (sym->etype).v_char,
715 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
717 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
725 /*-----------------------------------------------------------------*/
726 /* emitMaps - emits the code for the data portion the code */
727 /*-----------------------------------------------------------------*/
731 /* no special considerations for the following
732 data, idata & bit & xdata */
733 pic16emitRegularMap (data, TRUE, TRUE);
734 pic16emitRegularMap (idata, TRUE, TRUE);
735 pic16emitRegularMap (bit, TRUE, FALSE);
736 pic16emitRegularMap (xdata, TRUE, TRUE);
737 pic16emitRegularMap (sfr, FALSE, FALSE);
738 pic16emitRegularMap (sfrbit, FALSE, FALSE);
739 pic16emitRegularMap (code, TRUE, FALSE);
740 pic16emitStaticSeg (statsg);
743 /*-----------------------------------------------------------------*/
744 /* createInterruptVect - creates the interrupt vector */
745 /*-----------------------------------------------------------------*/
747 pic16createInterruptVect (FILE * vFile)
749 /* if the main is only a prototype ie. no body then do nothing */
751 if (!IFFUNC_HASBODY(mainf->type)) {
752 /* if ! compile only then main function should be present */
753 if (!options.cc_only)
759 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
760 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
761 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
762 fprintf (vFile, "__interrupt_vect:\n");
764 /* this is an overkill since WE are the port,
765 * and we know if we have a genIVT function! */
767 port->genIVT(vFile, interrupts, maxInterrupts);
774 /*-----------------------------------------------------------------*/
775 /* initialComments - puts in some initial comments */
776 /*-----------------------------------------------------------------*/
778 pic16initialComments (FILE * afile)
780 initialComments (afile);
781 fprintf (afile, "; PIC port for the 16-bit core\n");
782 fprintf (afile, iComments2);
786 /*-----------------------------------------------------------------*/
787 /* printPublics - generates global declarations for publics */
788 /*-----------------------------------------------------------------*/
790 pic16printPublics (FILE *afile)
794 fprintf (afile, "%s", iComments2);
795 fprintf (afile, "; public variables in this module\n");
796 fprintf (afile, "%s", iComments2);
798 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
799 fprintf(afile, "\tglobal %s\n", sym->rname);
802 /*-----------------------------------------------------------------*/
803 /* printExterns - generates extern declarations for externs */
804 /*-----------------------------------------------------------------*/
806 pic16_printExterns(FILE *afile)
810 fprintf(afile, "%s", iComments2);
811 fprintf(afile, "; extern variables in this module\n");
812 fprintf(afile, "%s", iComments2);
814 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
815 fprintf(afile, "\textern %s\n", sym->rname);
817 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
818 fprintf(afile, "\textern _%s\n", sym->name);
821 /*-----------------------------------------------------------------*/
822 /* emitOverlay - will emit code for the overlay stuff */
823 /*-----------------------------------------------------------------*/
825 pic16emitOverlay (FILE * afile)
829 if (!elementsInSet (ovrSetSets))
830 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
832 /* for each of the sets in the overlay segment do */
833 for (ovrset = setFirstItem (ovrSetSets); ovrset;
834 ovrset = setNextItem (ovrSetSets))
839 if (elementsInSet (ovrset))
841 /* this dummy area is used to fool the assembler
842 otherwise the assembler will append each of these
843 declarations into one chunk and will not overlay
845 fprintf (afile, ";\t.area _DUMMY\n");
846 /* output the area informtion */
847 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
850 for (sym = setFirstItem (ovrset); sym;
851 sym = setNextItem (ovrset))
854 /* if extern then do nothing */
855 if (IS_EXTERN (sym->etype))
858 /* if allocation required check is needed
859 then check if the symbol really requires
860 allocation only for local variables */
861 if (!IS_AGGREGATE (sym->type) &&
862 !(sym->_isparm && !IS_REGPARM (sym->etype))
863 && !sym->allocreq && sym->level)
866 /* if global variable & not static or extern
867 and addPublics allowed then add it to the public set */
868 if ((sym->_isparm && !IS_REGPARM (sym->etype))
869 && !IS_STATIC (sym->etype)) {
870 checkAddSym(&publics, sym);
871 // addSetHead (&publics, sym);
874 /* if extern then do nothing or is a function
876 if (IS_FUNC (sym->type))
880 /* print extra debug info if required */
881 if (options.debug || sym->level == 0)
884 cdbSymbol (sym, cdbFile, FALSE, FALSE);
888 if (IS_STATIC (sym->etype))
889 fprintf (afile, "F%s_", moduleName); /* scope is file */
891 fprintf (afile, "G_"); /* scope is global */
894 /* symbol is local */
895 fprintf (afile, "L%s_",
896 (sym->localof ? sym->localof->name : "-null-"));
897 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
901 /* if is has an absolute address then generate
902 an equate for this no need to allocate space */
903 if (SPEC_ABSA (sym->etype))
906 if (options.debug || sym->level == 0)
907 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
909 fprintf (afile, "%s\t=\t0x%04x\n",
911 SPEC_ADDR (sym->etype));
915 if (options.debug || sym->level == 0)
916 fprintf (afile, "==.\n");
919 fprintf (afile, "%s:\n", sym->rname);
920 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
928 /*-----------------------------------------------------------------*/
929 /* glue - the final glue that hold the whole thing together */
930 /*-----------------------------------------------------------------*/
937 FILE *ovrFile = tempfile();
940 mainf = newSymbol ("main", 0);
943 mainf = findSymWithLevel(SymbolTab, mainf);
945 /* only if the main function exists */
946 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
947 if (!options.cc_only)
953 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
955 addSetHead(&tmpfileSet,ovrFile);
956 pic16_pCodeInitRegisters();
958 if (mainf && IFFUNC_HASBODY(mainf->type)) {
959 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
963 /* entry point @ start of CSEG */
964 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup\t;VR1",-1));
967 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
968 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
969 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
970 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
973 /* put in the call to main */
974 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
976 if (options.mainreturn) {
977 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
978 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
980 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
981 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
985 /* At this point we've got all the code in the form of pCode structures */
986 /* Now it needs to be rearranged into the order it should be placed in the */
989 pic16_movepBlock2Head('P'); // Last
990 pic16_movepBlock2Head(code->dbName);
991 pic16_movepBlock2Head('X');
992 pic16_movepBlock2Head(statsg->dbName); // First
994 /* print the global struct definitions */
995 // if (options.debug)
996 // cdbStructBlock (0); //,cdbFile);
999 /* PENDING: this isnt the best place but it will do */
1000 if (port->general.glue_up_main) {
1001 /* create the interrupt vector table */
1002 pic16createInterruptVect (vFile);
1005 addSetHead(&tmpfileSet,vFile);
1007 /* emit code for the all the variables declared */
1009 /* do the overlay segments */
1010 pic16emitOverlay(ovrFile);
1011 pic16_AnalyzepCode('*');
1016 sprintf(buffer, dstFileName);
1017 strcat(buffer, ".calltree");
1018 cFile = fopen(buffer, "w");
1019 pic16_printCallTree( cFile );
1024 pic16_InlinepCode();
1025 pic16_AnalyzepCode('*');
1027 if(pic16_debug_verbose)
1030 /* now put it all together into the assembler file */
1031 /* create the assembler file name */
1032 if ((noAssemble || options.c1mode) && fullDstFileName) {
1033 sprintf (buffer, fullDstFileName);
1035 sprintf (buffer, dstFileName);
1036 strcat (buffer, ".asm");
1039 if (!(asmFile = fopen (buffer, "w"))) {
1040 werror (E_FILE_OPEN_ERR, buffer);
1044 /* initial comments */
1045 pic16initialComments (asmFile);
1047 /* print module name */
1048 // fprintf (asmFile, ";\t.module %s\n", moduleName);
1049 fprintf(asmFile, "#FILE\t\"%s\"\n", fullSrcFileName);
1051 /* Let the port generate any global directives, etc. */
1052 if (port->genAssemblerPreamble) {
1053 port->genAssemblerPreamble(asmFile);
1056 /* print the extern variables to this module */
1057 pic16_printExterns(asmFile);
1059 /* print the global variables in this module */
1060 pic16printPublics (asmFile);
1063 /* copy the sfr segment */
1064 fprintf (asmFile, "%s", iComments2);
1065 fprintf (asmFile, "; special function registers\n");
1066 fprintf (asmFile, "%s", iComments2);
1067 copyFile (asmFile, sfr->oFile);
1071 /* Put all variables into a cblock */
1072 pic16_AnalyzeBanking();
1073 pic16_writeUsedRegs(asmFile);
1075 /* create the overlay segments */
1076 fprintf (asmFile, "%s", iComments2);
1077 fprintf (asmFile, "; overlayable items in internal ram \n");
1078 fprintf (asmFile, "%s", iComments2);
1079 copyFile (asmFile, ovrFile);
1081 /* create the stack segment MOF */
1082 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1083 fprintf (asmFile, "%s", iComments2);
1084 fprintf (asmFile, "; Stack segment in internal ram \n");
1085 fprintf (asmFile, "%s", iComments2);
1086 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1087 ";__start__stack:\n;\t.ds\t1\n\n");
1091 /* no indirect data in pic */
1092 /* create the idata segment */
1093 fprintf (asmFile, "%s", iComments2);
1094 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1095 fprintf (asmFile, "%s", iComments2);
1096 copyFile (asmFile, idata->oFile);
1101 /* no xdata in pic */
1102 /* if external stack then reserve space of it */
1103 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1104 fprintf (asmFile, "%s", iComments2);
1105 fprintf (asmFile, "; external stack \n");
1106 fprintf (asmFile, "%s", iComments2);
1107 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1108 fprintf (asmFile,";\t.ds 256\n");
1113 /* no xdata in pic */
1114 /* copy xtern ram data */
1115 fprintf (asmFile, "%s", iComments2);
1116 fprintf (asmFile, "; external ram data\n");
1117 fprintf (asmFile, "%s", iComments2);
1118 copyFile (asmFile, xdata->oFile);
1121 /* copy the bit segment */
1122 fprintf (asmFile, "%s", iComments2);
1123 fprintf (asmFile, "; bit data\n");
1124 fprintf (asmFile, "%s", iComments2);
1125 copyFile (asmFile, bit->oFile);
1128 /* copy the interrupt vector table */
1129 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1130 fprintf (asmFile, "%s", iComments2);
1131 fprintf (asmFile, "; interrupt vector \n");
1132 fprintf (asmFile, "%s", iComments2);
1133 copyFile (asmFile, vFile);
1136 /* copy global & static initialisations */
1137 fprintf (asmFile, "%s", iComments2);
1138 fprintf (asmFile, "; global & static initialisations\n");
1139 fprintf (asmFile, "%s", iComments2);
1142 /* FIXME 8051 Legacy -- VR */
1143 /* Everywhere we generate a reference to the static_name area,
1144 * (which is currently only here), we immediately follow it with a
1145 * definition of the post_static_name area. This guarantees that
1146 * the post_static_name area will immediately follow the static_name
1149 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1150 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1151 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1155 /* copy over code */
1156 fprintf (asmFile, "%s", iComments2);
1157 fprintf (asmFile, "\tcode\n");
1158 fprintf (asmFile, "%s", iComments2);
1161 fprintf(asmFile, "; A code from now on!\n");
1162 pic16_copypCode(asmFile, 'A');
1165 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1166 fprintf(asmFile, "\tcode\n");
1167 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1170 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1171 /* if external stack is specified then the
1172 * higher order byte of the xdatalocation is
1173 * going into P2 and the lower order going into */
1175 if (options.useXstack) {
1176 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1177 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1178 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1179 (unsigned int)options.xdata_loc & 0xff);
1184 // copyFile (stderr, code->oFile);
1186 fprintf(asmFile, "; I code from now on!\n");
1187 pic16_copypCode(asmFile, 'I');
1189 // if(pic16_debug_verbose)
1190 fprintf(asmFile, "; dbName from now on!\n");
1191 pic16_copypCode(asmFile, statsg->dbName);
1194 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1195 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\t;VR2\n");
1199 // if(pic16_debug_verbose)
1200 fprintf(asmFile, "; X code from now on!\n");
1201 pic16_copypCode(asmFile, 'X');
1203 // if(pic16_debug_verbose)
1204 fprintf(asmFile, "; M code from now on!\n");
1205 pic16_copypCode(asmFile, 'M');
1208 pic16_copypCode(asmFile, code->dbName);
1210 pic16_copypCode(asmFile, 'P');
1212 fprintf (asmFile,"\tend\n");