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 addSetHead(&externs, sym);
137 /* if allocation required check is needed
138 * then check if the symbol really requires
139 * allocation only for local variables */
140 if (arFlag && !IS_AGGREGATE (sym->type) &&
141 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
142 !sym->allocreq && sym->level) {
144 fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
149 /* if global variable & not static or extern
150 * and addPublics allowed then add it to the public set */
151 if ((sym->used) && (sym->level == 0 ||
152 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
154 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
157 addSetHead (&publics, sym);
159 // reg = pic16_allocRegByName(sym->name, sym->size); //( operandFromSymbol( sym ));
160 // checkAddReg(&pic16_rel_udata, reg);
163 if(IS_STATIC(sym->etype)) {
165 /* add it to udata list */
167 fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
168 sym->name, sym->rname, sym->remat);
170 //, OP_SYMBOL(operandFromSymbol(sym))->name);
171 reg = pic16_allocDirReg( operandFromSymbol( sym ));
172 checkAddReg(&pic16_rel_udata, reg);
175 /* if extern then do nothing or is a function
177 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
178 if(SPEC_OCLS(sym->etype) == code) {
179 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
180 addSetHead(&publics, sym);
186 /* print extra debug info if required */
187 if (options.debug || sym->level == 0) {
188 cdbWriteSymbol (sym); //, cdbFile, FALSE, FALSE);
190 if (!sym->level) /* global */
191 if (IS_STATIC (sym->etype))
192 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
194 fprintf (map->oFile, "G_"); /* scope is global */
196 /* symbol is local */
197 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
198 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
203 * The equates are nice, but do not allow relocatable objects to
204 * be created in the form that I (VR) want to make SDCC to work */
206 /* if is has an absolute address then generate
207 an equate for this no need to allocate space */
208 if (SPEC_ABSA (sym->etype)) {
209 // if (options.debug || sym->level == 0)
210 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
211 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
213 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
215 SPEC_ADDR (sym->etype));
217 /* emit only if it is global */
218 if(sym->level == 0) {
222 reg = pic16_dirregWithName( sym->name );
224 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
225 // __FUNCTION__, __LINE__, sym->name);
227 op = operandFromSymbol( sym );
228 reg = pic16_allocDirReg( op );
230 if(checkAddReg(&pic16_fix_udata, reg)) {
231 /* and add to globals list if not exist */
232 addSetHead(&publics, sym);
238 if(!sym->used && (sym->level == 0)) {
241 /* symbol not used, just declared probably, but its in
242 * level 0, so we must declare it fine as global */
244 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
245 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
246 if(checkAddReg(&pic16_rel_udata, reg)) {
247 addSetHead(&publics, sym);
248 // addSetHead(&externs, sym);
253 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
254 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
255 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
256 if (IS_BITVAR (sym->etype)) {
259 fprintf (map->oFile, "\t%s\n", sym->rname);
260 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
261 for (i = 1; i < size; i++)
262 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
265 // fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
268 /* FIXME -- VR Fix the following, so that syms to be placed
269 * in the idata section and let linker decide about their fate */
271 /* if it has an initial value then do it only if
272 it is a global variable */
275 if (sym->ival && sym->level == 0) {
278 // if(SPEC_OCLS(sym->etype)==data) {
279 // fprintf(stderr, "%s: sym %s placed in data\n", map->sname, sym->name);
282 // fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
284 if (IS_AGGREGATE (sym->type))
285 ival = initAggregates (sym, sym->ival, NULL);
287 addSet(&idataSymSet, copySymbol(sym));
288 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
289 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
291 codeOutFile = statsg->oFile;
293 eBBlockFromiCode (iCodeFromAst (ival));
301 /*-----------------------------------------------------------------*/
302 /* printIvalType - generates ival for int/char */
303 /*-----------------------------------------------------------------*/
305 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
310 //fprintf(stderr, "%s\n",__FUNCTION__);
312 /* if initList is deep */
313 if (ilist->type == INIT_DEEP)
314 ilist = ilist->init.deep;
316 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
317 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
320 if (!(val = list2val (ilist))) {
321 // assuming a warning has been thrown
325 if (val->type != type) {
326 val = valCastLiteral(type, floatFromVal(val));
330 ulval = (unsigned long) floatFromVal (val);
334 switch (getSize (type)) {
336 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
337 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
341 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
342 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
343 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
344 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
348 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
349 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
350 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
351 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
352 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
353 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
354 pic16_emitDB(pb, BYTE_IN_LONG(ulval,2));
355 pic16_emitDB(pb, BYTE_IN_LONG(ulval,3));
360 /*-----------------------------------------------------------------*/
361 /* printIvalChar - generates initital value for character array */
362 /*-----------------------------------------------------------------*/
364 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
372 // fprintf(stderr, "%s\n",__FUNCTION__);
376 val = list2val (ilist);
377 /* if the value is a character string */
378 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
380 if (!DCL_ELEM (type))
381 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
383 //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
384 //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
385 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
387 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
391 //tfprintf (oFile, "\t!db !constbyte\n", 0);
392 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
402 //printChar (oFile, s, strlen (s) + 1);
404 for(remain=0; remain<strlen(s); remain++)
406 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
407 //fprintf(stderr,"0x%02x ",s[remain]);
408 pic16_emitDB(pb, s[remain]);
410 //fprintf(stderr,"\n");
415 /*-----------------------------------------------------------------*/
416 /* printIvalArray - generates code for array initialization */
417 /*-----------------------------------------------------------------*/
419 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
423 int lcnt = 0, size = 0;
429 /* take care of the special case */
430 /* array of characters can be init */
432 if (IS_CHAR (type->next)) {
433 fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
434 if (!IS_LITERAL(list2val(ilist)->etype)) {
435 werror (W_INIT_WRONG);
438 if (printIvalChar (type,
439 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
440 pb, SPEC_CVAL (sym->etype).v_char))
443 /* not the special case */
444 if (ilist->type != INIT_DEEP)
446 werror (E_INIT_STRUCT, sym->name);
450 iloop = ilist->init.deep;
451 lcnt = DCL_ELEM (type);
455 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
457 printIval (sym, type->next, iloop, pb);
458 iloop = (iloop ? iloop->next : NULL);
461 /* if not array limits given & we */
462 /* are out of initialisers then */
463 if (!DCL_ELEM (type) && !iloop)
466 /* no of elements given and we */
467 /* have generated for all of them */
469 /* if initializers left */
471 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
477 /* if we have not been given a size */
478 if (!DCL_ELEM (type))
479 DCL_ELEM (type) = size;
484 /*-----------------------------------------------------------------*/
485 /* printIval - generates code for initial value */
486 /*-----------------------------------------------------------------*/
488 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
493 /* if structure then */
494 if (IS_STRUCT (type))
496 //fprintf(stderr,"%s struct\n",__FUNCTION__);
497 //printIvalStruct (sym, type, ilist, oFile);
501 /* if this is a pointer */
504 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
505 //printIvalPtr (sym, type, ilist, oFile);
509 /* if this is an array */
512 //fprintf(stderr,"%s array\n",__FUNCTION__);
513 printIvalArray (sym, type, ilist, pb);
517 /* if type is SPECIFIER */
520 //fprintf(stderr,"%s spec\n",__FUNCTION__);
521 printIvalType (sym, type, ilist, pb);
526 extern void pic16_pCodeConstString(char *name, char *value);
527 /*-----------------------------------------------------------------*/
528 /* emitStaticSeg - emitcode for the static segment */
529 /*-----------------------------------------------------------------*/
531 pic16emitStaticSeg (memmap * map)
535 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
537 //fprintf(stderr, "%s\n",__FUNCTION__);
539 /* for all variables in this segment do */
540 for (sym = setFirstItem (map->syms); sym;
541 sym = setNextItem (map->syms))
545 fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
546 printTypeChain( sym->type, stderr );
551 /* if it is "extern" then do nothing */
552 if (IS_EXTERN (sym->etype)) {
553 addSetHead(&externs, sym);
557 /* if it is not static add it to the public
559 if (!IS_STATIC (sym->etype))
560 addSetHead (&publics, sym);
563 /* print extra debug info if required */
564 if (options.debug || sym->level == 0)
566 /* NOTE to me - cdbFile may be null in which case,
567 * the sym name will be printed to stdout. oh well */
569 cdbSymbol (sym, cdbFile, FALSE, FALSE);
573 if (IS_STATIC (sym->etype))
574 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
576 fprintf (code->oFile, "G_"); /* scope is global */
579 /* symbol is local */
580 fprintf (code->oFile, "L%s_",
581 (sym->localof ? sym->localof->name : "-null-"));
582 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
587 /* if it has an absolute address */
588 if (SPEC_ABSA (sym->etype))
590 if (options.debug || sym->level == 0)
591 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
593 fprintf (code->oFile, "%s\t=\t0x%04x\n",
595 SPEC_ADDR (sym->etype));
599 if (options.debug || sym->level == 0)
600 fprintf (code->oFile, " == .\n");
602 /* if it has an initial value */
607 fprintf (code->oFile, "%s:\n", sym->rname);
609 resolveIvalSym (sym->ival, sym->type);
610 //printIval (sym, sym->type, sym->ival, code->oFile);
611 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
613 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
615 printIval (sym, sym->type, sym->ival, pb);
623 fprintf (code->oFile, "%s:\n", sym->rname);
624 /* special case for character strings */
625 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
626 SPEC_CVAL (sym->etype).v_char)
627 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
628 /*printChar (code->oFile,
629 SPEC_CVAL (sym->etype).v_char,
630 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
632 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
640 /*-----------------------------------------------------------------*/
641 /* emitMaps - emits the code for the data portion the code */
642 /*-----------------------------------------------------------------*/
646 /* no special considerations for the following
647 data, idata & bit & xdata */
648 pic16emitRegularMap (data, TRUE, TRUE);
649 pic16emitRegularMap (idata, TRUE, TRUE);
650 pic16emitRegularMap (bit, TRUE, FALSE);
651 pic16emitRegularMap (xdata, TRUE, TRUE);
652 pic16emitRegularMap (sfr, FALSE, FALSE);
653 pic16emitRegularMap (sfrbit, FALSE, FALSE);
654 pic16emitRegularMap (code, TRUE, FALSE);
655 pic16emitStaticSeg (statsg);
658 /*-----------------------------------------------------------------*/
659 /* createInterruptVect - creates the interrupt vector */
660 /*-----------------------------------------------------------------*/
662 pic16createInterruptVect (FILE * vFile)
664 /* if the main is only a prototype ie. no body then do nothing */
666 if (!IFFUNC_HASBODY(mainf->type)) {
667 /* if ! compile only then main function should be present */
668 if (!options.cc_only)
674 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
675 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
676 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
677 fprintf (vFile, "__interrupt_vect:\n");
679 /* this is an overkill since WE are the port,
680 * and we know if we have a genIVT function! */
682 port->genIVT(vFile, interrupts, maxInterrupts);
689 /*-----------------------------------------------------------------*/
690 /* initialComments - puts in some initial comments */
691 /*-----------------------------------------------------------------*/
693 pic16initialComments (FILE * afile)
695 initialComments (afile);
696 fprintf (afile, "; PIC port for the 16-bit core\n");
697 fprintf (afile, iComments2);
701 /*-----------------------------------------------------------------*/
702 /* printPublics - generates global declarations for publics */
703 /*-----------------------------------------------------------------*/
705 pic16printPublics (FILE *afile)
709 fprintf (afile, "%s", iComments2);
710 fprintf (afile, "; public variables in this module\n");
711 fprintf (afile, "%s", iComments2);
713 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
714 fprintf(afile, "\tglobal %s\n", sym->rname);
717 /*-----------------------------------------------------------------*/
718 /* printExterns - generates extern declarations for externs */
719 /*-----------------------------------------------------------------*/
721 pic16_printExterns(FILE *afile)
725 fprintf(afile, "%s", iComments2);
726 fprintf(afile, "; extern variables in this module\n");
727 fprintf(afile, "%s", iComments2);
729 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
730 fprintf(afile, "\textern %s\n", sym->rname);
732 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
733 fprintf(afile, "\textern _%s\n", sym->name);
736 /*-----------------------------------------------------------------*/
737 /* emitOverlay - will emit code for the overlay stuff */
738 /*-----------------------------------------------------------------*/
740 pic16emitOverlay (FILE * afile)
744 if (!elementsInSet (ovrSetSets))
745 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
747 /* for each of the sets in the overlay segment do */
748 for (ovrset = setFirstItem (ovrSetSets); ovrset;
749 ovrset = setNextItem (ovrSetSets))
754 if (elementsInSet (ovrset))
756 /* this dummy area is used to fool the assembler
757 otherwise the assembler will append each of these
758 declarations into one chunk and will not overlay
760 fprintf (afile, ";\t.area _DUMMY\n");
761 /* output the area informtion */
762 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
765 for (sym = setFirstItem (ovrset); sym;
766 sym = setNextItem (ovrset))
769 /* if extern then do nothing */
770 if (IS_EXTERN (sym->etype))
773 /* if allocation required check is needed
774 then check if the symbol really requires
775 allocation only for local variables */
776 if (!IS_AGGREGATE (sym->type) &&
777 !(sym->_isparm && !IS_REGPARM (sym->etype))
778 && !sym->allocreq && sym->level)
781 /* if global variable & not static or extern
782 and addPublics allowed then add it to the public set */
783 if ((sym->_isparm && !IS_REGPARM (sym->etype))
784 && !IS_STATIC (sym->etype))
785 addSetHead (&publics, sym);
787 /* if extern then do nothing or is a function
789 if (IS_FUNC (sym->type))
793 /* print extra debug info if required */
794 if (options.debug || sym->level == 0)
797 cdbSymbol (sym, cdbFile, FALSE, FALSE);
801 if (IS_STATIC (sym->etype))
802 fprintf (afile, "F%s_", moduleName); /* scope is file */
804 fprintf (afile, "G_"); /* scope is global */
807 /* symbol is local */
808 fprintf (afile, "L%s_",
809 (sym->localof ? sym->localof->name : "-null-"));
810 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
814 /* if is has an absolute address then generate
815 an equate for this no need to allocate space */
816 if (SPEC_ABSA (sym->etype))
819 if (options.debug || sym->level == 0)
820 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
822 fprintf (afile, "%s\t=\t0x%04x\n",
824 SPEC_ADDR (sym->etype));
828 if (options.debug || sym->level == 0)
829 fprintf (afile, "==.\n");
832 fprintf (afile, "%s:\n", sym->rname);
833 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
841 /*-----------------------------------------------------------------*/
842 /* glue - the final glue that hold the whole thing together */
843 /*-----------------------------------------------------------------*/
850 FILE *ovrFile = tempfile();
853 mainf = newSymbol ("main", 0);
856 mainf = findSymWithLevel(SymbolTab, mainf);
858 /* only if the main function exists */
859 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
860 if (!options.cc_only)
866 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
868 addSetHead(&tmpfileSet,ovrFile);
869 pic16_pCodeInitRegisters();
871 if (mainf && IFFUNC_HASBODY(mainf->type)) {
872 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
876 /* entry point @ start of CSEG */
877 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup\t;VR1",-1));
880 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
881 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
882 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
883 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
886 /* put in the call to main */
887 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
889 if (options.mainreturn) {
890 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
891 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
893 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
894 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
898 /* At this point we've got all the code in the form of pCode structures */
899 /* Now it needs to be rearranged into the order it should be placed in the */
902 pic16_movepBlock2Head('P'); // Last
903 pic16_movepBlock2Head(code->dbName);
904 pic16_movepBlock2Head('X');
905 pic16_movepBlock2Head(statsg->dbName); // First
907 /* print the global struct definitions */
908 // if (options.debug)
909 // cdbStructBlock (0); //,cdbFile);
912 /* PENDING: this isnt the best place but it will do */
913 if (port->general.glue_up_main) {
914 /* create the interrupt vector table */
915 pic16createInterruptVect (vFile);
918 addSetHead(&tmpfileSet,vFile);
920 /* emit code for the all the variables declared */
922 /* do the overlay segments */
923 pic16emitOverlay(ovrFile);
924 pic16_AnalyzepCode('*');
929 sprintf(buffer, dstFileName);
930 strcat(buffer, ".calltree");
931 cFile = fopen(buffer, "w");
932 pic16_printCallTree( cFile );
938 pic16_AnalyzepCode('*');
940 if(pic16_debug_verbose)
943 /* now put it all together into the assembler file */
944 /* create the assembler file name */
945 if ((noAssemble || options.c1mode) && fullDstFileName) {
946 sprintf (buffer, fullDstFileName);
948 sprintf (buffer, dstFileName);
949 strcat (buffer, ".asm");
952 if (!(asmFile = fopen (buffer, "w"))) {
953 werror (E_FILE_OPEN_ERR, buffer);
957 /* initial comments */
958 pic16initialComments (asmFile);
960 /* print module name */
961 fprintf (asmFile, ";\t.module %s\n", moduleName);
963 /* Let the port generate any global directives, etc. */
964 if (port->genAssemblerPreamble) {
965 port->genAssemblerPreamble(asmFile);
968 /* print the extern variables to this module */
969 pic16_printExterns(asmFile);
971 /* print the global variables in this module */
972 pic16printPublics (asmFile);
975 /* copy the sfr segment */
976 fprintf (asmFile, "%s", iComments2);
977 fprintf (asmFile, "; special function registers\n");
978 fprintf (asmFile, "%s", iComments2);
979 copyFile (asmFile, sfr->oFile);
983 /* Put all variables into a cblock */
984 pic16_AnalyzeBanking();
985 pic16_writeUsedRegs(asmFile);
987 /* create the overlay segments */
988 fprintf (asmFile, "%s", iComments2);
989 fprintf (asmFile, "; overlayable items in internal ram \n");
990 fprintf (asmFile, "%s", iComments2);
991 copyFile (asmFile, ovrFile);
993 /* create the stack segment MOF */
994 if (mainf && IFFUNC_HASBODY(mainf->type)) {
995 fprintf (asmFile, "%s", iComments2);
996 fprintf (asmFile, "; Stack segment in internal ram \n");
997 fprintf (asmFile, "%s", iComments2);
998 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
999 ";__start__stack:\n;\t.ds\t1\n\n");
1003 /* no indirect data in pic */
1004 /* create the idata segment */
1005 fprintf (asmFile, "%s", iComments2);
1006 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1007 fprintf (asmFile, "%s", iComments2);
1008 copyFile (asmFile, idata->oFile);
1013 /* no xdata in pic */
1014 /* if external stack then reserve space of it */
1015 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1016 fprintf (asmFile, "%s", iComments2);
1017 fprintf (asmFile, "; external stack \n");
1018 fprintf (asmFile, "%s", iComments2);
1019 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1020 fprintf (asmFile,";\t.ds 256\n");
1025 /* no xdata in pic */
1026 /* copy xtern ram data */
1027 fprintf (asmFile, "%s", iComments2);
1028 fprintf (asmFile, "; external ram data\n");
1029 fprintf (asmFile, "%s", iComments2);
1030 copyFile (asmFile, xdata->oFile);
1033 /* copy the bit segment */
1034 fprintf (asmFile, "%s", iComments2);
1035 fprintf (asmFile, "; bit data\n");
1036 fprintf (asmFile, "%s", iComments2);
1037 copyFile (asmFile, bit->oFile);
1040 /* copy the interrupt vector table */
1041 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1042 fprintf (asmFile, "%s", iComments2);
1043 fprintf (asmFile, "; interrupt vector \n");
1044 fprintf (asmFile, "%s", iComments2);
1045 copyFile (asmFile, vFile);
1048 /* copy global & static initialisations */
1049 fprintf (asmFile, "%s", iComments2);
1050 fprintf (asmFile, "; global & static initialisations\n");
1051 fprintf (asmFile, "%s", iComments2);
1054 /* FIXME 8051 Legacy -- VR */
1055 /* Everywhere we generate a reference to the static_name area,
1056 * (which is currently only here), we immediately follow it with a
1057 * definition of the post_static_name area. This guarantees that
1058 * the post_static_name area will immediately follow the static_name
1061 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1062 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1063 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1067 /* copy over code */
1068 fprintf (asmFile, "%s", iComments2);
1069 fprintf (asmFile, "\tcode\n");
1070 fprintf (asmFile, "%s", iComments2);
1073 fprintf(asmFile, "; A code from now on!\n");
1074 pic16_copypCode(asmFile, 'A');
1077 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1078 fprintf (asmFile,"__sdcc_gsinit_startup:\t\t;VRokas\n");
1081 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1082 /* if external stack is specified then the
1083 * higher order byte of the xdatalocation is
1084 * going into P2 and the lower order going into */
1086 if (options.useXstack) {
1087 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1088 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1089 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1090 (unsigned int)options.xdata_loc & 0xff);
1095 // copyFile (stderr, code->oFile);
1097 fprintf(asmFile, "; I code from now on!\n");
1098 pic16_copypCode(asmFile, 'I');
1100 // if(pic16_debug_verbose)
1101 fprintf(asmFile, "; dbName from now on!\n");
1102 pic16_copypCode(asmFile, statsg->dbName);
1105 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1106 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\t;VR2\n");
1110 // if(pic16_debug_verbose)
1111 fprintf(asmFile, "; X code from now on!\n");
1112 pic16_copypCode(asmFile, 'X');
1114 // if(pic16_debug_verbose)
1115 fprintf(asmFile, "; M code from now on!\n");
1116 pic16_copypCode(asmFile, 'M');
1119 pic16_copypCode(asmFile, code->dbName);
1121 pic16_copypCode(asmFile, 'P');
1123 fprintf (asmFile,"\tend\n");