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"
35 #ifdef WORDS_BIGENDIAN
36 #define _ENDIAN(x) (3-x)
38 #define _ENDIAN(x) (x)
41 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 extern symbol *interrupts[256];
44 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
48 extern unsigned maxInterrupts;
49 extern int maxRegBank;
51 extern char *VersionString;
52 extern FILE *codeOutFile;
53 extern set *tmpfileSet;
54 extern set *tmpfileNameSet;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
61 set *idataSymSet=NULL;
63 extern DEFSETFUNC (closeTmpFiles);
64 extern DEFSETFUNC (rmTmpFiles);
66 extern void pic16_AnalyzeBanking (void);
67 extern void copyFile (FILE * dest, FILE * src);
68 extern void pic16_InlinepCode(void);
69 extern void pic16_writeUsedRegs(FILE *);
71 extern void initialComments (FILE * afile);
72 extern void printPublics (FILE * afile);
74 extern void printChar (FILE * ofile, char *s, int plen);
75 void pic16_pCodeInitRegisters(void);
76 pCodeOp *pic16_popGetLit(unsigned int lit);
77 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2);
78 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
80 /*-----------------------------------------------------------------*/
81 /* aopLiteral - string from a literal value */
82 /*-----------------------------------------------------------------*/
83 int pic16aopLiteral (value *val, int offset)
90 /* if it is a float then it gets tricky */
91 /* otherwise it is fairly simple */
92 if (!IS_FLOAT(val->type)) {
93 unsigned long v = (unsigned long) floatFromVal(val);
95 return ( (v >> (offset * 8)) & 0xff);
98 /* it is type float */
99 fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101 return fl.c[3-offset];
108 /*-----------------------------------------------------------------*/
109 /* emitRegularMap - emit code for maps with no special cases */
110 /*-----------------------------------------------------------------*/
112 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
115 int i, size, bitvars = 0;;
117 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
120 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
122 /* print the area name */
123 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
125 fprintf(stderr, "\t%s: sym: %s\tused: %d\textern: %d\n",
126 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype));
127 printTypeChain( sym->type, stderr );
130 /* if extern then add to externs */
131 if (IS_EXTERN (sym->etype)) {
132 // if(sym->used) // fixme
133 checkAddSym(&externs, sym);
134 // addSetHead(&externs, sym);
138 /* if allocation required check is needed
139 * then check if the symbol really requires
140 * allocation only for local variables */
141 if (arFlag && !IS_AGGREGATE (sym->type) &&
142 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
143 !sym->allocreq && sym->level) {
145 fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
150 /* if global variable & not static or extern
151 * and addPublics allowed then add it to the public set */
152 if ((sym->used) && (sym->level == 0 ||
153 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
155 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
158 checkAddSym(&publics, sym);
159 // addSetHead(&publics, sym);
161 // reg = pic16_allocRegByName(sym->name, sym->size); //( operandFromSymbol( sym ));
162 // checkAddReg(&pic16_rel_udata, reg);
165 if(IS_STATIC(sym->etype)) {
167 /* add it to udata list */
169 fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
170 sym->name, sym->rname, sym->remat);
172 //, OP_SYMBOL(operandFromSymbol(sym))->name);
173 reg = pic16_allocDirReg( operandFromSymbol( sym ));
174 checkAddReg(&pic16_rel_udata, reg);
177 /* if extern then do nothing or is a function
179 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
180 if(SPEC_OCLS(sym->etype) == code) {
181 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
182 checkAddSym(&publics, sym);
183 // addSetHead(&publics, sym);
189 /* print extra debug info if required */
190 if (options.debug || sym->level == 0) {
191 cdbWriteSymbol (sym); //, cdbFile, FALSE, FALSE);
193 if (!sym->level) /* global */
194 if (IS_STATIC (sym->etype))
195 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
197 fprintf (map->oFile, "G_"); /* scope is global */
199 /* symbol is local */
200 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
201 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
206 * The equates are nice, but do not allow relocatable objects to
207 * be created in the form that I (VR) want to make SDCC to work */
209 /* if is has an absolute address then generate
210 an equate for this no need to allocate space */
211 if (SPEC_ABSA (sym->etype)) {
212 // if (options.debug || sym->level == 0)
213 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
214 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
216 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
218 SPEC_ADDR (sym->etype));
220 /* emit only if it is global */
221 if(sym->level == 0) {
225 reg = pic16_dirregWithName( sym->name );
227 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
228 // __FUNCTION__, __LINE__, sym->name);
230 op = operandFromSymbol( sym );
231 reg = pic16_allocDirReg( op );
233 if(checkAddReg(&pic16_fix_udata, reg)) {
234 /* and add to globals list if not exist */
235 addSetHead(&publics, sym);
241 if(!sym->used && (sym->level == 0)) {
244 /* symbol not used, just declared probably, but its in
245 * level 0, so we must declare it fine as global */
247 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
248 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
249 if(checkAddReg(&pic16_rel_udata, reg)) {
250 addSetHead(&publics, sym);
251 // addSetHead(&externs, sym);
256 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
257 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
258 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
259 if (IS_BITVAR (sym->etype)) {
262 fprintf (map->oFile, "\t%s\n", sym->rname);
263 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
264 for (i = 1; i < size; i++)
265 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
268 // fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
271 /* FIXME -- VR Fix the following, so that syms to be placed
272 * in the idata section and let linker decide about their fate */
274 /* if it has an initial value then do it only if
275 it is a global variable */
278 if (sym->ival && sym->level == 0) {
281 // if(SPEC_OCLS(sym->etype)==data) {
282 // fprintf(stderr, "%s: sym %s placed in data\n", map->sname, sym->name);
285 // fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
287 if (IS_AGGREGATE (sym->type))
288 ival = initAggregates (sym, sym->ival, NULL);
290 addSet(&idataSymSet, copySymbol(sym));
291 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
292 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
294 codeOutFile = statsg->oFile;
296 eBBlockFromiCode (iCodeFromAst (ival));
304 /*-----------------------------------------------------------------*/
305 /* printIvalType - generates ival for int/char */
306 /*-----------------------------------------------------------------*/
308 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
313 //fprintf(stderr, "%s\n",__FUNCTION__);
315 /* if initList is deep */
316 if (ilist->type == INIT_DEEP)
317 ilist = ilist->init.deep;
319 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
320 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
323 if (!(val = list2val (ilist))) {
324 // assuming a warning has been thrown
328 if (val->type != type) {
329 val = valCastLiteral(type, floatFromVal(val));
333 ulval = (unsigned long) floatFromVal (val);
337 switch (getSize (type)) {
339 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
340 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
344 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
345 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
346 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
347 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
351 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
352 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
353 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
354 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
355 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
356 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
357 pic16_emitDB(pb, BYTE_IN_LONG(ulval,2));
358 pic16_emitDB(pb, BYTE_IN_LONG(ulval,3));
363 /*-----------------------------------------------------------------*/
364 /* printIvalChar - generates initital value for character array */
365 /*-----------------------------------------------------------------*/
367 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
375 // fprintf(stderr, "%s\n",__FUNCTION__);
379 val = list2val (ilist);
380 /* if the value is a character string */
381 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
383 if (!DCL_ELEM (type))
384 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
386 //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
387 //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
388 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
390 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
394 //tfprintf (oFile, "\t!db !constbyte\n", 0);
395 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
405 //printChar (oFile, s, strlen (s) + 1);
407 for(remain=0; remain<strlen(s); remain++)
409 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
410 //fprintf(stderr,"0x%02x ",s[remain]);
411 pic16_emitDB(pb, s[remain]);
413 //fprintf(stderr,"\n");
418 /*-----------------------------------------------------------------*/
419 /* printIvalArray - generates code for array initialization */
420 /*-----------------------------------------------------------------*/
422 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
426 int lcnt = 0, size = 0;
432 /* take care of the special case */
433 /* array of characters can be init */
435 if (IS_CHAR (type->next)) {
436 fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
437 if (!IS_LITERAL(list2val(ilist)->etype)) {
438 werror (W_INIT_WRONG);
441 if (printIvalChar (type,
442 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
443 pb, SPEC_CVAL (sym->etype).v_char))
446 /* not the special case */
447 if (ilist->type != INIT_DEEP)
449 werror (E_INIT_STRUCT, sym->name);
453 iloop = ilist->init.deep;
454 lcnt = DCL_ELEM (type);
458 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
460 printIval (sym, type->next, iloop, pb);
461 iloop = (iloop ? iloop->next : NULL);
464 /* if not array limits given & we */
465 /* are out of initialisers then */
466 if (!DCL_ELEM (type) && !iloop)
469 /* no of elements given and we */
470 /* have generated for all of them */
472 /* if initializers left */
474 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
480 /* if we have not been given a size */
481 if (!DCL_ELEM (type))
482 DCL_ELEM (type) = size;
487 /*-----------------------------------------------------------------*/
488 /* printIval - generates code for initial value */
489 /*-----------------------------------------------------------------*/
491 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
496 /* if structure then */
497 if (IS_STRUCT (type))
499 //fprintf(stderr,"%s struct\n",__FUNCTION__);
500 //printIvalStruct (sym, type, ilist, oFile);
504 /* if this is a pointer */
507 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
508 //printIvalPtr (sym, type, ilist, oFile);
512 /* if this is an array */
515 //fprintf(stderr,"%s array\n",__FUNCTION__);
516 printIvalArray (sym, type, ilist, pb);
520 /* if type is SPECIFIER */
523 //fprintf(stderr,"%s spec\n",__FUNCTION__);
524 printIvalType (sym, type, ilist, pb);
529 extern void pic16_pCodeConstString(char *name, char *value);
530 /*-----------------------------------------------------------------*/
531 /* emitStaticSeg - emitcode for the static segment */
532 /*-----------------------------------------------------------------*/
534 pic16emitStaticSeg (memmap * map)
538 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
540 //fprintf(stderr, "%s\n",__FUNCTION__);
542 /* for all variables in this segment do */
543 for (sym = setFirstItem (map->syms); sym;
544 sym = setNextItem (map->syms))
548 fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
549 printTypeChain( sym->type, stderr );
554 /* if it is "extern" then do nothing */
555 if (IS_EXTERN (sym->etype)) {
556 checkAddSym(&externs, sym);
557 // addSetHead(&externs, sym);
561 /* if it is not static add it to the public
563 if (!IS_STATIC (sym->etype)) {
564 checkAddSym(&publics, sym);
565 // addSetHead (&publics, sym);
569 /* print extra debug info if required */
570 if (options.debug || sym->level == 0)
572 /* NOTE to me - cdbFile may be null in which case,
573 * the sym name will be printed to stdout. oh well */
575 cdbSymbol (sym, cdbFile, FALSE, FALSE);
579 if (IS_STATIC (sym->etype))
580 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
582 fprintf (code->oFile, "G_"); /* scope is global */
585 /* symbol is local */
586 fprintf (code->oFile, "L%s_",
587 (sym->localof ? sym->localof->name : "-null-"));
588 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
593 /* if it has an absolute address */
594 if (SPEC_ABSA (sym->etype))
596 if (options.debug || sym->level == 0)
597 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
599 fprintf (code->oFile, "%s\t=\t0x%04x\n",
601 SPEC_ADDR (sym->etype));
605 if (options.debug || sym->level == 0)
606 fprintf (code->oFile, " == .\n");
608 /* if it has an initial value */
613 fprintf (code->oFile, "%s:\n", sym->rname);
615 resolveIvalSym (sym->ival, sym->type);
616 //printIval (sym, sym->type, sym->ival, code->oFile);
617 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
619 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
621 printIval (sym, sym->type, sym->ival, pb);
629 fprintf (code->oFile, "%s:\n", sym->rname);
630 /* special case for character strings */
631 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
632 SPEC_CVAL (sym->etype).v_char)
633 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
634 /*printChar (code->oFile,
635 SPEC_CVAL (sym->etype).v_char,
636 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
638 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
646 /*-----------------------------------------------------------------*/
647 /* emitMaps - emits the code for the data portion the code */
648 /*-----------------------------------------------------------------*/
652 /* no special considerations for the following
653 data, idata & bit & xdata */
654 pic16emitRegularMap (data, TRUE, TRUE);
655 pic16emitRegularMap (idata, TRUE, TRUE);
656 pic16emitRegularMap (bit, TRUE, FALSE);
657 pic16emitRegularMap (xdata, TRUE, TRUE);
658 pic16emitRegularMap (sfr, FALSE, FALSE);
659 pic16emitRegularMap (sfrbit, FALSE, FALSE);
660 pic16emitRegularMap (code, TRUE, FALSE);
661 pic16emitStaticSeg (statsg);
664 /*-----------------------------------------------------------------*/
665 /* createInterruptVect - creates the interrupt vector */
666 /*-----------------------------------------------------------------*/
668 pic16createInterruptVect (FILE * vFile)
670 /* if the main is only a prototype ie. no body then do nothing */
672 if (!IFFUNC_HASBODY(mainf->type)) {
673 /* if ! compile only then main function should be present */
674 if (!options.cc_only)
680 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
681 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
682 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
683 fprintf (vFile, "__interrupt_vect:\n");
685 /* this is an overkill since WE are the port,
686 * and we know if we have a genIVT function! */
688 port->genIVT(vFile, interrupts, maxInterrupts);
695 /*-----------------------------------------------------------------*/
696 /* initialComments - puts in some initial comments */
697 /*-----------------------------------------------------------------*/
699 pic16initialComments (FILE * afile)
701 initialComments (afile);
702 fprintf (afile, "; PIC port for the 16-bit core\n");
703 fprintf (afile, iComments2);
707 /*-----------------------------------------------------------------*/
708 /* printPublics - generates global declarations for publics */
709 /*-----------------------------------------------------------------*/
711 pic16printPublics (FILE *afile)
715 fprintf (afile, "%s", iComments2);
716 fprintf (afile, "; public variables in this module\n");
717 fprintf (afile, "%s", iComments2);
719 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
720 fprintf(afile, "\tglobal %s\n", sym->rname);
723 /*-----------------------------------------------------------------*/
724 /* printExterns - generates extern declarations for externs */
725 /*-----------------------------------------------------------------*/
727 pic16_printExterns(FILE *afile)
731 fprintf(afile, "%s", iComments2);
732 fprintf(afile, "; extern variables in this module\n");
733 fprintf(afile, "%s", iComments2);
735 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
736 fprintf(afile, "\textern %s\n", sym->rname);
738 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
739 fprintf(afile, "\textern _%s\n", sym->name);
742 /*-----------------------------------------------------------------*/
743 /* emitOverlay - will emit code for the overlay stuff */
744 /*-----------------------------------------------------------------*/
746 pic16emitOverlay (FILE * afile)
750 if (!elementsInSet (ovrSetSets))
751 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
753 /* for each of the sets in the overlay segment do */
754 for (ovrset = setFirstItem (ovrSetSets); ovrset;
755 ovrset = setNextItem (ovrSetSets))
760 if (elementsInSet (ovrset))
762 /* this dummy area is used to fool the assembler
763 otherwise the assembler will append each of these
764 declarations into one chunk and will not overlay
766 fprintf (afile, ";\t.area _DUMMY\n");
767 /* output the area informtion */
768 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
771 for (sym = setFirstItem (ovrset); sym;
772 sym = setNextItem (ovrset))
775 /* if extern then do nothing */
776 if (IS_EXTERN (sym->etype))
779 /* if allocation required check is needed
780 then check if the symbol really requires
781 allocation only for local variables */
782 if (!IS_AGGREGATE (sym->type) &&
783 !(sym->_isparm && !IS_REGPARM (sym->etype))
784 && !sym->allocreq && sym->level)
787 /* if global variable & not static or extern
788 and addPublics allowed then add it to the public set */
789 if ((sym->_isparm && !IS_REGPARM (sym->etype))
790 && !IS_STATIC (sym->etype)) {
791 checkAddSym(&publics, sym);
792 // addSetHead (&publics, sym);
795 /* if extern then do nothing or is a function
797 if (IS_FUNC (sym->type))
801 /* print extra debug info if required */
802 if (options.debug || sym->level == 0)
805 cdbSymbol (sym, cdbFile, FALSE, FALSE);
809 if (IS_STATIC (sym->etype))
810 fprintf (afile, "F%s_", moduleName); /* scope is file */
812 fprintf (afile, "G_"); /* scope is global */
815 /* symbol is local */
816 fprintf (afile, "L%s_",
817 (sym->localof ? sym->localof->name : "-null-"));
818 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
822 /* if is has an absolute address then generate
823 an equate for this no need to allocate space */
824 if (SPEC_ABSA (sym->etype))
827 if (options.debug || sym->level == 0)
828 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
830 fprintf (afile, "%s\t=\t0x%04x\n",
832 SPEC_ADDR (sym->etype));
836 if (options.debug || sym->level == 0)
837 fprintf (afile, "==.\n");
840 fprintf (afile, "%s:\n", sym->rname);
841 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
849 /*-----------------------------------------------------------------*/
850 /* glue - the final glue that hold the whole thing together */
851 /*-----------------------------------------------------------------*/
858 FILE *ovrFile = tempfile();
861 mainf = newSymbol ("main", 0);
864 mainf = findSymWithLevel(SymbolTab, mainf);
866 /* only if the main function exists */
867 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
868 if (!options.cc_only)
874 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
876 addSetHead(&tmpfileSet,ovrFile);
877 pic16_pCodeInitRegisters();
879 if (mainf && IFFUNC_HASBODY(mainf->type)) {
880 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
884 /* entry point @ start of CSEG */
885 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup\t;VR1",-1));
888 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
889 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
890 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
891 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
894 /* put in the call to main */
895 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
897 if (options.mainreturn) {
898 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
899 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
901 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
902 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
906 /* At this point we've got all the code in the form of pCode structures */
907 /* Now it needs to be rearranged into the order it should be placed in the */
910 pic16_movepBlock2Head('P'); // Last
911 pic16_movepBlock2Head(code->dbName);
912 pic16_movepBlock2Head('X');
913 pic16_movepBlock2Head(statsg->dbName); // First
915 /* print the global struct definitions */
916 // if (options.debug)
917 // cdbStructBlock (0); //,cdbFile);
920 /* PENDING: this isnt the best place but it will do */
921 if (port->general.glue_up_main) {
922 /* create the interrupt vector table */
923 pic16createInterruptVect (vFile);
926 addSetHead(&tmpfileSet,vFile);
928 /* emit code for the all the variables declared */
930 /* do the overlay segments */
931 pic16emitOverlay(ovrFile);
932 pic16_AnalyzepCode('*');
937 sprintf(buffer, dstFileName);
938 strcat(buffer, ".calltree");
939 cFile = fopen(buffer, "w");
940 pic16_printCallTree( cFile );
946 pic16_AnalyzepCode('*');
948 if(pic16_debug_verbose)
951 /* now put it all together into the assembler file */
952 /* create the assembler file name */
953 if ((noAssemble || options.c1mode) && fullDstFileName) {
954 sprintf (buffer, fullDstFileName);
956 sprintf (buffer, dstFileName);
957 strcat (buffer, ".asm");
960 if (!(asmFile = fopen (buffer, "w"))) {
961 werror (E_FILE_OPEN_ERR, buffer);
965 /* initial comments */
966 pic16initialComments (asmFile);
968 /* print module name */
969 fprintf (asmFile, ";\t.module %s\n", moduleName);
971 /* Let the port generate any global directives, etc. */
972 if (port->genAssemblerPreamble) {
973 port->genAssemblerPreamble(asmFile);
976 /* print the extern variables to this module */
977 pic16_printExterns(asmFile);
979 /* print the global variables in this module */
980 pic16printPublics (asmFile);
983 /* copy the sfr segment */
984 fprintf (asmFile, "%s", iComments2);
985 fprintf (asmFile, "; special function registers\n");
986 fprintf (asmFile, "%s", iComments2);
987 copyFile (asmFile, sfr->oFile);
991 /* Put all variables into a cblock */
992 pic16_AnalyzeBanking();
993 pic16_writeUsedRegs(asmFile);
995 /* create the overlay segments */
996 fprintf (asmFile, "%s", iComments2);
997 fprintf (asmFile, "; overlayable items in internal ram \n");
998 fprintf (asmFile, "%s", iComments2);
999 copyFile (asmFile, ovrFile);
1001 /* create the stack segment MOF */
1002 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1003 fprintf (asmFile, "%s", iComments2);
1004 fprintf (asmFile, "; Stack segment in internal ram \n");
1005 fprintf (asmFile, "%s", iComments2);
1006 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1007 ";__start__stack:\n;\t.ds\t1\n\n");
1011 /* no indirect data in pic */
1012 /* create the idata segment */
1013 fprintf (asmFile, "%s", iComments2);
1014 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1015 fprintf (asmFile, "%s", iComments2);
1016 copyFile (asmFile, idata->oFile);
1021 /* no xdata in pic */
1022 /* if external stack then reserve space of it */
1023 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1024 fprintf (asmFile, "%s", iComments2);
1025 fprintf (asmFile, "; external stack \n");
1026 fprintf (asmFile, "%s", iComments2);
1027 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1028 fprintf (asmFile,";\t.ds 256\n");
1033 /* no xdata in pic */
1034 /* copy xtern ram data */
1035 fprintf (asmFile, "%s", iComments2);
1036 fprintf (asmFile, "; external ram data\n");
1037 fprintf (asmFile, "%s", iComments2);
1038 copyFile (asmFile, xdata->oFile);
1041 /* copy the bit segment */
1042 fprintf (asmFile, "%s", iComments2);
1043 fprintf (asmFile, "; bit data\n");
1044 fprintf (asmFile, "%s", iComments2);
1045 copyFile (asmFile, bit->oFile);
1048 /* copy the interrupt vector table */
1049 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1050 fprintf (asmFile, "%s", iComments2);
1051 fprintf (asmFile, "; interrupt vector \n");
1052 fprintf (asmFile, "%s", iComments2);
1053 copyFile (asmFile, vFile);
1056 /* copy global & static initialisations */
1057 fprintf (asmFile, "%s", iComments2);
1058 fprintf (asmFile, "; global & static initialisations\n");
1059 fprintf (asmFile, "%s", iComments2);
1062 /* FIXME 8051 Legacy -- VR */
1063 /* Everywhere we generate a reference to the static_name area,
1064 * (which is currently only here), we immediately follow it with a
1065 * definition of the post_static_name area. This guarantees that
1066 * the post_static_name area will immediately follow the static_name
1069 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1070 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1071 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1075 /* copy over code */
1076 fprintf (asmFile, "%s", iComments2);
1077 fprintf (asmFile, "\tcode\n");
1078 fprintf (asmFile, "%s", iComments2);
1081 fprintf(asmFile, "; A code from now on!\n");
1082 pic16_copypCode(asmFile, 'A');
1085 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1086 fprintf (asmFile,"__sdcc_gsinit_startup:\t\t;VRokas\n");
1089 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1090 /* if external stack is specified then the
1091 * higher order byte of the xdatalocation is
1092 * going into P2 and the lower order going into */
1094 if (options.useXstack) {
1095 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1096 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1097 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1098 (unsigned int)options.xdata_loc & 0xff);
1103 // copyFile (stderr, code->oFile);
1105 fprintf(asmFile, "; I code from now on!\n");
1106 pic16_copypCode(asmFile, 'I');
1108 // if(pic16_debug_verbose)
1109 fprintf(asmFile, "; dbName from now on!\n");
1110 pic16_copypCode(asmFile, statsg->dbName);
1113 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1114 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\t;VR2\n");
1118 // if(pic16_debug_verbose)
1119 fprintf(asmFile, "; X code from now on!\n");
1120 pic16_copypCode(asmFile, 'X');
1122 // if(pic16_debug_verbose)
1123 fprintf(asmFile, "; M code from now on!\n");
1124 pic16_copypCode(asmFile, 'M');
1127 pic16_copypCode(asmFile, code->dbName);
1129 pic16_copypCode(asmFile, 'P');
1131 fprintf (asmFile,"\tend\n");