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 *rel_idataSymSet=NULL;
65 set *fix_idataSymSet=NULL;
67 extern DEFSETFUNC (closeTmpFiles);
68 extern DEFSETFUNC (rmTmpFiles);
70 extern void pic16_AnalyzeBanking (void);
71 extern void copyFile (FILE * dest, FILE * src);
72 extern void pic16_InlinepCode(void);
73 extern void pic16_writeUsedRegs(FILE *);
75 extern void initialComments (FILE * afile);
76 extern void printPublics (FILE * afile);
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);
82 extern void pic16_pCodeConstString(char *name, char *value);
84 /*-----------------------------------------------------------------*/
85 /* aopLiteral - string from a literal value */
86 /*-----------------------------------------------------------------*/
87 int pic16aopLiteral (value *val, int offset)
94 /* if it is a float then it gets tricky */
95 /* otherwise it is fairly simple */
96 if (!IS_FLOAT(val->type)) {
97 unsigned long v = (unsigned long) floatFromVal(val);
99 return ( (v >> (offset * 8)) & 0xff);
102 /* it is type float */
103 fl.f = (float) floatFromVal(val);
104 #ifdef WORDS_BIGENDIAN
105 return fl.c[3-offset];
114 char tbuffer[512], *tbuf=tbuffer;;
117 /*-----------------------------------------------------------------*/
118 /* emitRegularMap - emit code for maps with no special cases */
119 /*-----------------------------------------------------------------*/
121 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
124 // int i, size, bitvars = 0;;
126 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
129 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
130 /* print the area name */
132 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
135 fprintf(stderr, "\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\n",
136 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype));
137 printTypeChain( sym->type, stderr );
138 fprintf(stderr, "\n");
141 // if(PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
145 /* if extern then add to externs */
146 if (IS_EXTERN (sym->etype)) {
147 checkAddSym(&externs, sym);
151 /* if allocation required check is needed
152 * then check if the symbol really requires
153 * allocation only for local variables */
154 if (arFlag && !IS_AGGREGATE (sym->type) &&
155 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
156 !sym->allocreq && sym->level) {
158 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
163 /* if global variable & not static or extern
164 * and addPublics allowed then add it to the public set */
165 if ((sym->used) && (sym->level == 0 ||
166 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
168 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
170 checkAddSym(&publics, sym);
171 // addSetHead(&publics, sym);
173 if(IS_STATIC(sym->etype)
174 && !(sym->ival && !sym->level)
177 /* add it to udata list */
179 // fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
180 // sym->name, sym->rname, sym->remat);
182 //, OP_SYMBOL(operandFromSymbol(sym))->name);
183 #define SET_IMPLICIT 1
186 if(IS_STRUCT(sym->type))
190 reg = pic16_allocDirReg( operandFromSymbol( sym ));
191 checkAddReg(&pic16_rel_udata, reg);
194 /* if extern then do nothing or is a function
196 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
197 if(SPEC_OCLS(sym->etype) == code) {
198 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
199 checkAddSym(&publics, sym);
205 /* print extra debug info if required */
206 if (options.debug || sym->level == 0) {
207 cdbWriteSymbol (sym); //, cdbFile, FALSE, FALSE);
209 if (!sym->level) /* global */
210 if (IS_STATIC (sym->etype))
211 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
213 fprintf (map->oFile, "G_"); /* scope is global */
215 /* symbol is local */
216 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
217 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
222 /* if is has an absolute address then generate
223 an equate for this no need to allocate space */
224 if (SPEC_ABSA (sym->etype)) {
225 // if (options.debug || sym->level == 0)
226 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
227 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
229 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
231 SPEC_ADDR (sym->etype));
233 /* emit only if it is global */
234 if(sym->level == 0) {
237 reg = pic16_dirregWithName( sym->name );
240 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
241 // __FUNCTION__, __LINE__, sym->name);
243 /* if IS_STRUCT is omitted the following
244 * fixes structures but break char/int etc */
246 if(IS_STRUCT(sym->type))
247 sym->implicit = 1; // mark as implicit
250 reg = pic16_allocDirReg( operandFromSymbol(sym) );
252 if(checkAddReg(&pic16_fix_udata, reg)) {
253 /* and add to globals list if not exist */
254 addSet(&publics, sym);
258 addSet(&publics, sym);
262 if(!sym->used && (sym->level == 0)) {
265 /* symbol not used, just declared probably, but its in
266 * level 0, so we must declare it fine as global */
268 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
271 if(IS_STRUCT(sym->type))
272 sym->implicit = 1; // mark as implicit
275 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
276 if(checkAddReg(&pic16_rel_udata, reg)) {
277 addSetHead(&publics, sym);
280 addSetHead(&publics, sym);
285 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
286 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
287 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
288 if (IS_BITVAR (sym->etype)) {
291 fprintf (map->oFile, "\t%s\n", sym->rname);
292 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
293 for (i = 1; i < size; i++)
294 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
297 fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
301 /* FIXME -- VR Fix the following, so that syms to be placed
302 * in the idata section and let linker decide about their fate */
304 /* if it has an initial value then do it only if
305 it is a global variable */
307 if (sym->ival && sym->level == 0) {
311 if(SPEC_OCLS(sym->etype)==data) {
312 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
315 if(SPEC_OCLS(sym->etype)==code) {
316 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
320 // fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
322 if (IS_AGGREGATE (sym->type)) {
323 if(SPEC_ABSA(sym->etype))
324 addSet(&fix_idataSymSet, copySymbol(sym));
326 addSet(&rel_idataSymSet, copySymbol(sym));
327 // ival = initAggregates (sym, sym->ival, NULL);
329 if(SPEC_ABSA(sym->etype))
330 addSet(&fix_idataSymSet, copySymbol(sym));
332 addSet(&rel_idataSymSet, copySymbol(sym));
334 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
335 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
339 setAstLineno(ival, sym->lineDef);
340 codeOutFile = statsg->oFile;
342 eBBlockFromiCode (iCodeFromAst (ival));
350 /*-----------------------------------------------------------------*/
351 /* printIvalType - generates ival for int/char */
352 /*-----------------------------------------------------------------*/
354 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
359 //fprintf(stderr, "%s\n",__FUNCTION__);
361 /* if initList is deep */
362 if (ilist->type == INIT_DEEP)
363 ilist = ilist->init.deep;
365 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
366 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
369 if (!(val = list2val (ilist))) {
370 // assuming a warning has been thrown
374 if (val->type != type) {
375 val = valCastLiteral(type, floatFromVal(val));
379 ulval = (unsigned long) floatFromVal (val);
383 switch (getSize (type)) {
385 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
386 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
390 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
391 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
392 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
393 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
397 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
398 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
399 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
400 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
401 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
402 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
403 pic16_emitDB(pb, BYTE_IN_LONG(ulval,2));
404 pic16_emitDB(pb, BYTE_IN_LONG(ulval,3));
409 /*-----------------------------------------------------------------*/
410 /* printIvalChar - generates initital value for character array */
411 /*-----------------------------------------------------------------*/
413 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
421 // fprintf(stderr, "%s\n",__FUNCTION__);
425 val = list2val (ilist);
426 /* if the value is a character string */
427 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
429 if (!DCL_ELEM (type))
430 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
432 for(remain=0; remain<DCL_ELEM(type); remain++)
433 pic16_emitDB(pb, SPEC_CVAL(val->etype).v_char[ remain ]);
435 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
437 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
441 //tfprintf (oFile, "\t!db !constbyte\n", 0);
442 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
452 //printChar (oFile, s, strlen (s) + 1);
454 for(remain=0; remain<strlen(s); remain++)
456 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
457 //fprintf(stderr,"0x%02x ",s[remain]);
458 pic16_emitDB(pb, s[remain]);
460 //fprintf(stderr,"\n");
465 /*-----------------------------------------------------------------*/
466 /* printIvalArray - generates code for array initialization */
467 /*-----------------------------------------------------------------*/
469 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
473 int lcnt = 0, size = 0;
479 /* take care of the special case */
480 /* array of characters can be init */
482 if (IS_CHAR (type->next)) {
483 fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
484 if (!IS_LITERAL(list2val(ilist)->etype)) {
485 werror (W_INIT_WRONG);
489 fprintf(stderr, "%s:%d adding %s to idata\n", __FILE__, __LINE__, sym->name);
490 if(SPEC_ABSA(sym->etype))
491 addSet(&fix_idataSymSet, copySymbol(sym));
493 addSet(&rel_idataSymSet, copySymbol(sym));
495 if (printIvalChar (type,
496 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
497 pb, SPEC_CVAL (sym->etype).v_char))
500 /* not the special case */
501 if (ilist->type != INIT_DEEP)
503 werror (E_INIT_STRUCT, sym->name);
507 iloop = ilist->init.deep;
508 lcnt = DCL_ELEM (type);
512 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
514 printIval (sym, type->next, iloop, pb);
515 iloop = (iloop ? iloop->next : NULL);
518 /* if not array limits given & we */
519 /* are out of initialisers then */
520 if (!DCL_ELEM (type) && !iloop)
523 /* no of elements given and we */
524 /* have generated for all of them */
526 /* if initializers left */
528 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
534 /* if we have not been given a size */
535 if (!DCL_ELEM (type))
536 DCL_ELEM (type) = size;
543 /*-----------------------------------------------------------------*/
544 /* printIval - generates code for initial value */
545 /*-----------------------------------------------------------------*/
547 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
552 // fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
554 /* if structure then */
555 if (IS_STRUCT (type))
557 //fprintf(stderr,"%s struct\n",__FUNCTION__);
558 //printIvalStruct (sym, type, ilist, oFile);
559 fprintf(stderr, "%s:%d: PIC16 port error: structure initialisation is not implemented yet.\n",
565 /* if this is a pointer */
568 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
569 //printIvalPtr (sym, type, ilist, oFile);
570 fprintf(stderr, "%s:%d: PIC16 port error: pointer initialisation is not implemented yet.\n",
576 /* if this is an array */
579 //fprintf(stderr,"%s array\n",__FUNCTION__);
580 printIvalArray (sym, type, ilist, pb);
584 /* if type is SPECIFIER */
587 //fprintf(stderr,"%s spec\n",__FUNCTION__);
588 printIvalType (sym, type, ilist, pb);
593 int PIC16_IS_CONFIG_ADDRESS(int address)
596 return (address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd);
599 /*-----------------------------------------------------------------*/
600 /* emitStaticSeg - emitcode for the static segment */
601 /*-----------------------------------------------------------------*/
603 pic16emitStaticSeg (memmap * map)
607 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
609 //fprintf(stderr, "%s\n",__FUNCTION__);
611 /* for all variables in this segment do */
612 for (sym = setFirstItem (map->syms); sym;
613 sym = setNextItem (map->syms))
617 fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
618 printTypeChain( sym->type, stderr );
619 fprintf(stderr, "\n");
622 if(SPEC_ABSA(sym->etype)
623 && (SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))) {
625 pic16_assignConfigWordValue(SPEC_ADDR (sym->etype),
626 (int) floatFromVal(list2val( sym->ival )));
631 /* if it is "extern" then do nothing */
632 if (IS_EXTERN (sym->etype)) {
634 /* do not emit if it is a config word declaration */
635 if(!SPEC_ABSA(sym->etype)
636 || (SPEC_ABSA(sym->etype) && !PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))))
637 checkAddSym(&externs, sym);
641 /* if it is not static add it to the public
643 if (!IS_STATIC (sym->etype)) {
644 /* do not emit if it is a config word declaration */
645 checkAddSym(&publics, sym);
649 /* print extra debug info if required */
650 if (options.debug || sym->level == 0)
652 /* NOTE to me - cdbFile may be null in which case,
653 * the sym name will be printed to stdout. oh well */
655 cdbSymbol (sym, cdbFile, FALSE, FALSE);
659 if (IS_STATIC (sym->etype))
660 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
662 fprintf (code->oFile, "G_"); /* scope is global */
665 /* symbol is local */
666 fprintf (code->oFile, "L%s_",
667 (sym->localof ? sym->localof->name : "-null-"));
668 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
673 /* if it has an absolute address */
674 if (SPEC_ABSA (sym->etype))
676 fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
677 __FILE__, __LINE__, sym->name);
679 if (options.debug || sym->level == 0)
680 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
682 fprintf (code->oFile, "%s\t=\t0x%04x\n",
684 SPEC_ADDR (sym->etype));
686 /* if it has an initial value */
695 resolveIvalSym (sym->ival, sym->type);
696 asym = newSymbol(sym->rname, 0);
697 abSym = Safe_calloc(1, sizeof(absSym));
698 abSym->name = Safe_strdup( sym->rname );
699 abSym->address = SPEC_ADDR( sym->etype );
700 addSet(&absSymSet, abSym);
702 pb = pic16_newpCodeChain(NULL, 'A',pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
705 pcf = pic16_newpCodeFunction(moduleName, asym->name);
706 PCF(pcf)->absblock = 1;
708 pic16_addpCode2pBlock(pb,pcf);
709 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
710 printIval (sym, sym->type, sym->ival, pb);
713 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
720 fprintf (code->oFile, "%s:\n", sym->rname);
721 /* special case for character strings */
722 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
723 SPEC_CVAL (sym->etype).v_char)
724 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
725 /*printChar (code->oFile,
726 SPEC_CVAL (sym->etype).v_char,
727 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
729 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
733 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
734 // __FILE__, __LINE__, sym->name);
736 if (options.debug || sym->level == 0)
737 fprintf (code->oFile, " == .\n");
739 /* if it has an initial value */
744 fprintf (code->oFile, "%s:\n", sym->rname);
746 resolveIvalSym (sym->ival, sym->type);
747 //printIval (sym, sym->type, sym->ival, code->oFile);
748 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
750 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
752 printIval (sym, sym->type, sym->ival, pb);
760 fprintf (code->oFile, "%s:\n", sym->rname);
761 /* special case for character strings */
762 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
763 SPEC_CVAL (sym->etype).v_char)
764 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
765 /*printChar (code->oFile,
766 SPEC_CVAL (sym->etype).v_char,
767 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
769 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
777 /*-----------------------------------------------------------------*/
778 /* pic16_emitConfigRegs - emits the configuration registers */
779 /*-----------------------------------------------------------------*/
780 void pic16_emitConfigRegs(FILE *of)
784 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
785 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
786 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
787 pic16->cwInfo.confAddrStart+i,
788 pic16->cwInfo.crInfo[i].value);
795 /* no special considerations for the following
796 data, idata & bit & xdata */
797 pic16emitRegularMap (data, TRUE, TRUE);
798 pic16emitRegularMap (idata, TRUE, TRUE);
799 pic16emitRegularMap (bit, TRUE, FALSE);
800 pic16emitRegularMap (xdata, TRUE, TRUE);
801 pic16emitRegularMap (sfr, FALSE, FALSE);
802 pic16emitRegularMap (sfrbit, FALSE, FALSE);
803 pic16emitRegularMap (code, TRUE, FALSE);
804 pic16emitStaticSeg (statsg);
807 /*-----------------------------------------------------------------*/
808 /* createInterruptVect - creates the interrupt vector */
809 /*-----------------------------------------------------------------*/
811 pic16createInterruptVect (FILE * vFile)
813 /* if the main is only a prototype ie. no body then do nothing */
815 if (!IFFUNC_HASBODY(mainf->type)) {
816 /* if ! compile only then main function should be present */
817 if (!options.cc_only)
823 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
824 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
825 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
826 fprintf (vFile, "__interrupt_vect:\n");
828 /* this is an overkill since WE are the port,
829 * and we know if we have a genIVT function! */
831 port->genIVT(vFile, interrupts, maxInterrupts);
838 /*-----------------------------------------------------------------*/
839 /* pic16initialComments - puts in some initial comments */
840 /*-----------------------------------------------------------------*/
842 pic16initialComments (FILE * afile)
844 initialComments (afile);
845 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
846 fprintf (afile, iComments2);
850 /*-----------------------------------------------------------------*/
851 /* printPublics - generates global declarations for publics */
852 /*-----------------------------------------------------------------*/
854 pic16printPublics (FILE *afile)
858 fprintf (afile, "%s", iComments2);
859 fprintf (afile, "; public variables in this module\n");
860 fprintf (afile, "%s", iComments2);
862 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
863 fprintf(afile, "\tglobal %s\n", sym->rname);
866 /*-----------------------------------------------------------------*/
867 /* printExterns - generates extern declarations for externs */
868 /*-----------------------------------------------------------------*/
870 pic16_printExterns(FILE *afile)
874 fprintf(afile, "%s", iComments2);
875 fprintf(afile, "; extern variables in this module\n");
876 fprintf(afile, "%s", iComments2);
878 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
879 fprintf(afile, "\textern %s\n", sym->rname);
881 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
882 fprintf(afile, "\textern _%s\n", sym->name);
885 /*-----------------------------------------------------------------*/
886 /* emitOverlay - will emit code for the overlay stuff */
887 /*-----------------------------------------------------------------*/
889 pic16emitOverlay (FILE * afile)
893 if (!elementsInSet (ovrSetSets))
894 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
896 /* for each of the sets in the overlay segment do */
897 for (ovrset = setFirstItem (ovrSetSets); ovrset;
898 ovrset = setNextItem (ovrSetSets))
903 if (elementsInSet (ovrset))
905 /* this dummy area is used to fool the assembler
906 otherwise the assembler will append each of these
907 declarations into one chunk and will not overlay
909 fprintf (afile, ";\t.area _DUMMY\n");
910 /* output the area informtion */
911 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
914 for (sym = setFirstItem (ovrset); sym;
915 sym = setNextItem (ovrset))
918 /* if extern then do nothing */
919 if (IS_EXTERN (sym->etype))
922 /* if allocation required check is needed
923 then check if the symbol really requires
924 allocation only for local variables */
925 if (!IS_AGGREGATE (sym->type) &&
926 !(sym->_isparm && !IS_REGPARM (sym->etype))
927 && !sym->allocreq && sym->level)
930 /* if global variable & not static or extern
931 and addPublics allowed then add it to the public set */
932 if ((sym->_isparm && !IS_REGPARM (sym->etype))
933 && !IS_STATIC (sym->etype)) {
934 checkAddSym(&publics, sym);
935 // addSetHead (&publics, sym);
938 /* if extern then do nothing or is a function
940 if (IS_FUNC (sym->type))
944 /* print extra debug info if required */
945 if (options.debug || sym->level == 0)
948 cdbSymbol (sym, cdbFile, FALSE, FALSE);
952 if (IS_STATIC (sym->etype))
953 fprintf (afile, "F%s_", moduleName); /* scope is file */
955 fprintf (afile, "G_"); /* scope is global */
958 /* symbol is local */
959 fprintf (afile, "L%s_",
960 (sym->localof ? sym->localof->name : "-null-"));
961 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
965 /* if is has an absolute address then generate
966 an equate for this no need to allocate space */
967 if (SPEC_ABSA (sym->etype))
970 if (options.debug || sym->level == 0)
971 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
973 fprintf (afile, "%s\t=\t0x%04x\n",
975 SPEC_ADDR (sym->etype));
979 if (options.debug || sym->level == 0)
980 fprintf (afile, "==.\n");
983 fprintf (afile, "%s:\n", sym->rname);
984 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
992 /*-----------------------------------------------------------------*/
993 /* glue - the final glue that hold the whole thing together */
994 /*-----------------------------------------------------------------*/
1001 FILE *ovrFile = tempfile();
1004 mainf = newSymbol ("main", 0);
1007 mainf = findSymWithLevel(SymbolTab, mainf);
1009 /* only if the main function exists */
1010 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
1011 if (!options.cc_only)
1017 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
1019 addSetHead(&tmpfileSet,ovrFile);
1020 pic16_pCodeInitRegisters();
1022 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1023 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1025 pic16_addpBlock(pb);
1027 /* entry point @ start of CSEG */
1028 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1031 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1032 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
1033 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1034 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
1037 /* put in the call to main */
1038 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1040 if (options.mainreturn) {
1041 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1042 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1044 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1045 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1049 /* At this point we've got all the code in the form of pCode structures */
1050 /* Now it needs to be rearranged into the order it should be placed in the */
1053 pic16_movepBlock2Head('P'); // Last
1054 pic16_movepBlock2Head(code->dbName);
1055 pic16_movepBlock2Head('X');
1056 pic16_movepBlock2Head(statsg->dbName); // First
1058 /* print the global struct definitions */
1059 // if (options.debug)
1060 // cdbStructBlock (0); //,cdbFile);
1063 /* PENDING: this isnt the best place but it will do */
1064 if (port->general.glue_up_main) {
1065 /* create the interrupt vector table */
1066 pic16createInterruptVect (vFile);
1069 addSetHead(&tmpfileSet,vFile);
1071 /* emit code for the all the variables declared */
1073 /* do the overlay segments */
1074 pic16emitOverlay(ovrFile);
1075 pic16_AnalyzepCode('*');
1080 sprintf(buffer, dstFileName);
1081 strcat(buffer, ".calltree");
1082 cFile = fopen(buffer, "w");
1083 pic16_printCallTree( cFile );
1088 pic16_InlinepCode();
1089 pic16_AnalyzepCode('*');
1091 if(pic16_debug_verbose)
1094 /* now put it all together into the assembler file */
1095 /* create the assembler file name */
1096 if ((noAssemble || options.c1mode) && fullDstFileName) {
1097 sprintf (buffer, fullDstFileName);
1099 sprintf (buffer, dstFileName);
1100 strcat (buffer, ".asm");
1103 if (!(asmFile = fopen (buffer, "w"))) {
1104 werror (E_FILE_OPEN_ERR, buffer);
1108 /* initial comments */
1109 pic16initialComments (asmFile);
1111 /* print module name */
1112 fprintf(asmFile, "#FILE\t\"%s\"\n", fullSrcFileName);
1114 /* Let the port generate any global directives, etc. */
1115 if (port->genAssemblerPreamble) {
1116 port->genAssemblerPreamble(asmFile);
1119 /* print the extern variables to this module */
1120 pic16_printExterns(asmFile);
1122 /* print the global variables in this module */
1123 pic16printPublics (asmFile);
1126 /* copy the sfr segment */
1127 fprintf (asmFile, "%s", iComments2);
1128 fprintf (asmFile, "; special function registers\n");
1129 fprintf (asmFile, "%s", iComments2);
1130 copyFile (asmFile, sfr->oFile);
1134 /* Put all variables into a cblock */
1135 pic16_AnalyzeBanking();
1136 pic16_writeUsedRegs(asmFile);
1139 /* create the overlay segments */
1140 fprintf (asmFile, "%s", iComments2);
1141 fprintf (asmFile, "; overlayable items in internal ram \n");
1142 fprintf (asmFile, "%s", iComments2);
1143 copyFile (asmFile, ovrFile);
1148 /* create the stack segment MOF */
1149 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1150 fprintf (asmFile, "%s", iComments2);
1151 fprintf (asmFile, "; Stack segment in internal ram \n");
1152 fprintf (asmFile, "%s", iComments2);
1153 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1154 ";__start__stack:\n;\t.ds\t1\n\n");
1159 /* no indirect data in pic */
1160 /* create the idata segment */
1161 fprintf (asmFile, "%s", iComments2);
1162 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1163 fprintf (asmFile, "%s", iComments2);
1164 copyFile (asmFile, idata->oFile);
1169 /* no xdata in pic */
1170 /* if external stack then reserve space of it */
1171 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1172 fprintf (asmFile, "%s", iComments2);
1173 fprintf (asmFile, "; external stack \n");
1174 fprintf (asmFile, "%s", iComments2);
1175 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1176 fprintf (asmFile,";\t.ds 256\n");
1181 /* no xdata in pic */
1182 /* copy xtern ram data */
1183 fprintf (asmFile, "%s", iComments2);
1184 fprintf (asmFile, "; external ram data\n");
1185 fprintf (asmFile, "%s", iComments2);
1186 copyFile (asmFile, xdata->oFile);
1190 /* copy the bit segment */
1191 fprintf (asmFile, "%s", iComments2);
1192 fprintf (asmFile, "; bit data\n");
1193 fprintf (asmFile, "%s", iComments2);
1194 copyFile (asmFile, bit->oFile);
1197 /* copy the interrupt vector table */
1198 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1199 fprintf (asmFile, "%s", iComments2);
1200 fprintf (asmFile, "; interrupt vector \n");
1201 fprintf (asmFile, "%s", iComments2);
1202 copyFile (asmFile, vFile);
1205 /* copy global & static initialisations */
1206 fprintf (asmFile, "%s", iComments2);
1207 fprintf (asmFile, "; global & static initialisations\n");
1208 fprintf (asmFile, "%s", iComments2);
1211 /* copy over code */
1212 fprintf (asmFile, "%s", iComments2);
1213 fprintf (asmFile, "\tcode\n");
1214 fprintf (asmFile, "%s", iComments2);
1217 if(pic16_debug_verbose)
1218 fprintf(asmFile, "; A code from now on!\n");
1219 pic16_copypCode(asmFile, 'A');
1222 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1223 fprintf(asmFile, "\tcode\n");
1224 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1227 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1228 /* if external stack is specified then the
1229 * higher order byte of the xdatalocation is
1230 * going into P2 and the lower order going into */
1232 if (options.useXstack) {
1233 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1234 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1235 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1236 (unsigned int)options.xdata_loc & 0xff);
1241 // copyFile (stderr, code->oFile);
1243 fprintf(asmFile, "; I code from now on!\n");
1244 pic16_copypCode(asmFile, 'I');
1246 if(pic16_debug_verbose)
1247 fprintf(asmFile, "; dbName from now on!\n");
1248 pic16_copypCode(asmFile, statsg->dbName);
1251 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1252 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1256 if(pic16_debug_verbose)
1257 fprintf(asmFile, "; X code from now on!\n");
1258 pic16_copypCode(asmFile, 'X');
1260 if(pic16_debug_verbose)
1261 fprintf(asmFile, "; M code from now on!\n");
1262 pic16_copypCode(asmFile, 'M');
1265 pic16_copypCode(asmFile, code->dbName);
1267 pic16_copypCode(asmFile, 'P');
1269 fprintf (asmFile,"\tend\n");