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\taggregate: %d\n",
136 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
137 IS_AGGREGATE(sym->type));
138 printTypeChain( sym->type, stderr );
139 fprintf(stderr, "\n");
142 // if(PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
146 /* if extern then add to externs */
147 if (IS_EXTERN (sym->etype)) {
148 checkAddSym(&externs, sym);
152 /* if allocation required check is needed
153 * then check if the symbol really requires
154 * allocation only for local variables */
155 if (arFlag && !IS_AGGREGATE (sym->type) &&
156 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
157 !sym->allocreq && sym->level) {
159 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
164 /* if global variable & not static or extern
165 * and addPublics allowed then add it to the public set */
166 if ((sym->used) && (sym->level == 0 ||
167 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
169 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
171 checkAddSym(&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 if(IS_AGGREGATE(sym->type)) {
276 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
278 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
280 if(checkAddReg(&pic16_rel_udata, reg)) {
281 addSetHead(&publics, sym);
284 addSetHead(&publics, sym);
289 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
290 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
291 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
292 if (IS_BITVAR (sym->etype)) {
295 fprintf (map->oFile, "\t%s\n", sym->rname);
296 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
297 for (i = 1; i < size; i++)
298 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
301 fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
305 /* FIXME -- VR Fix the following, so that syms to be placed
306 * in the idata section and let linker decide about their fate */
308 /* if it has an initial value then do it only if
309 it is a global variable */
311 if (sym->ival && sym->level == 0) {
315 if(SPEC_OCLS(sym->etype)==data) {
316 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
319 if(SPEC_OCLS(sym->etype)==code) {
320 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
324 // fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
326 if (IS_AGGREGATE (sym->type)) {
327 if(SPEC_ABSA(sym->etype))
328 addSet(&fix_idataSymSet, copySymbol(sym));
330 addSet(&rel_idataSymSet, copySymbol(sym));
331 // ival = initAggregates (sym, sym->ival, NULL);
333 if(SPEC_ABSA(sym->etype))
334 addSet(&fix_idataSymSet, copySymbol(sym));
336 addSet(&rel_idataSymSet, copySymbol(sym));
338 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
339 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
343 setAstLineno(ival, sym->lineDef);
344 codeOutFile = statsg->oFile;
346 eBBlockFromiCode (iCodeFromAst (ival));
354 /*-----------------------------------------------------------------*/
355 /* printIvalType - generates ival for int/char */
356 /*-----------------------------------------------------------------*/
358 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
363 //fprintf(stderr, "%s\n",__FUNCTION__);
365 /* if initList is deep */
366 if (ilist->type == INIT_DEEP)
367 ilist = ilist->init.deep;
369 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
370 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
373 if (!(val = list2val (ilist))) {
374 // assuming a warning has been thrown
378 if (val->type != type) {
379 val = valCastLiteral(type, floatFromVal(val));
383 ulval = (unsigned long) floatFromVal (val);
387 switch (getSize (type)) {
389 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
390 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
394 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
395 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
396 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
397 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
401 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
402 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
403 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
404 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
405 pic16_emitDB(pb, BYTE_IN_LONG(ulval,0));
406 pic16_emitDB(pb, BYTE_IN_LONG(ulval,1));
407 pic16_emitDB(pb, BYTE_IN_LONG(ulval,2));
408 pic16_emitDB(pb, BYTE_IN_LONG(ulval,3));
413 /*-----------------------------------------------------------------*/
414 /* printIvalChar - generates initital value for character array */
415 /*-----------------------------------------------------------------*/
417 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
425 // fprintf(stderr, "%s\n",__FUNCTION__);
429 val = list2val (ilist);
430 /* if the value is a character string */
431 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
433 if (!DCL_ELEM (type))
434 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
436 for(remain=0; remain<DCL_ELEM(type); remain++)
437 pic16_emitDB(pb, SPEC_CVAL(val->etype).v_char[ remain ]);
439 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
441 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
445 //tfprintf (oFile, "\t!db !constbyte\n", 0);
446 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
456 //printChar (oFile, s, strlen (s) + 1);
458 for(remain=0; remain<strlen(s); remain++)
460 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
461 //fprintf(stderr,"0x%02x ",s[remain]);
462 pic16_emitDB(pb, s[remain]);
464 //fprintf(stderr,"\n");
469 /*-----------------------------------------------------------------*/
470 /* printIvalArray - generates code for array initialization */
471 /*-----------------------------------------------------------------*/
473 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
477 int lcnt = 0, size = 0;
483 /* take care of the special case */
484 /* array of characters can be init */
486 if (IS_CHAR (type->next)) {
487 fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
488 if (!IS_LITERAL(list2val(ilist)->etype)) {
489 werror (W_INIT_WRONG);
493 fprintf(stderr, "%s:%d adding %s to idata\n", __FILE__, __LINE__, sym->name);
494 if(SPEC_ABSA(sym->etype))
495 addSet(&fix_idataSymSet, copySymbol(sym));
497 addSet(&rel_idataSymSet, copySymbol(sym));
499 if (printIvalChar (type,
500 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
501 pb, SPEC_CVAL (sym->etype).v_char))
504 /* not the special case */
505 if (ilist->type != INIT_DEEP)
507 werror (E_INIT_STRUCT, sym->name);
511 iloop = ilist->init.deep;
512 lcnt = DCL_ELEM (type);
516 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
518 printIval (sym, type->next, iloop, pb);
519 iloop = (iloop ? iloop->next : NULL);
522 /* if not array limits given & we */
523 /* are out of initialisers then */
524 if (!DCL_ELEM (type) && !iloop)
527 /* no of elements given and we */
528 /* have generated for all of them */
530 /* if initializers left */
532 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
538 /* if we have not been given a size */
539 if (!DCL_ELEM (type))
540 DCL_ELEM (type) = size;
547 /*-----------------------------------------------------------------*/
548 /* printIval - generates code for initial value */
549 /*-----------------------------------------------------------------*/
551 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
556 // fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
558 /* if structure then */
559 if (IS_STRUCT (type))
561 //fprintf(stderr,"%s struct\n",__FUNCTION__);
562 //printIvalStruct (sym, type, ilist, oFile);
563 fprintf(stderr, "%s:%d: PIC16 port error: structure initialisation is not implemented yet.\n",
569 /* if this is a pointer */
572 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
573 //printIvalPtr (sym, type, ilist, oFile);
574 fprintf(stderr, "%s:%d: PIC16 port error: pointer initialisation is not implemented yet.\n",
580 /* if this is an array */
583 //fprintf(stderr,"%s array\n",__FUNCTION__);
584 printIvalArray (sym, type, ilist, pb);
588 /* if type is SPECIFIER */
591 //fprintf(stderr,"%s spec\n",__FUNCTION__);
592 printIvalType (sym, type, ilist, pb);
597 int PIC16_IS_CONFIG_ADDRESS(int address)
600 return (address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd);
603 /*-----------------------------------------------------------------*/
604 /* emitStaticSeg - emitcode for the static segment */
605 /*-----------------------------------------------------------------*/
607 pic16emitStaticSeg (memmap * map)
611 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
613 //fprintf(stderr, "%s\n",__FUNCTION__);
615 /* for all variables in this segment do */
616 for (sym = setFirstItem (map->syms); sym;
617 sym = setNextItem (map->syms))
621 fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
622 printTypeChain( sym->type, stderr );
623 fprintf(stderr, "\n");
626 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
628 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
629 (int) floatFromVal(list2val(sym->ival)));
634 /* if it is "extern" then do nothing */
635 if (IS_EXTERN (sym->etype)) {
637 /* do not emit if it is a config word declaration */
638 if(!SPEC_ABSA(sym->etype)
639 || (SPEC_ABSA(sym->etype) && !PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))))
640 checkAddSym(&externs, sym);
644 /* if it is not static add it to the public
646 if (!IS_STATIC (sym->etype)) {
647 /* do not emit if it is a config word declaration */
648 checkAddSym(&publics, sym);
652 /* print extra debug info if required */
653 if (options.debug || sym->level == 0)
655 /* NOTE to me - cdbFile may be null in which case,
656 * the sym name will be printed to stdout. oh well */
658 cdbSymbol (sym, cdbFile, FALSE, FALSE);
662 if (IS_STATIC (sym->etype))
663 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
665 fprintf (code->oFile, "G_"); /* scope is global */
668 /* symbol is local */
669 fprintf (code->oFile, "L%s_",
670 (sym->localof ? sym->localof->name : "-null-"));
671 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
676 /* if it has an absolute address */
677 if (SPEC_ABSA (sym->etype))
679 fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
680 __FILE__, __LINE__, sym->name);
682 if (options.debug || sym->level == 0)
683 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
685 fprintf (code->oFile, "%s\t=\t0x%04x\n",
687 SPEC_ADDR (sym->etype));
689 /* if it has an initial value */
698 resolveIvalSym (sym->ival, sym->type);
699 asym = newSymbol(sym->rname, 0);
700 abSym = Safe_calloc(1, sizeof(absSym));
701 abSym->name = Safe_strdup( sym->rname );
702 abSym->address = SPEC_ADDR( sym->etype );
703 addSet(&absSymSet, abSym);
705 pb = pic16_newpCodeChain(NULL, 'A',pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
708 pcf = pic16_newpCodeFunction(moduleName, asym->name);
709 PCF(pcf)->absblock = 1;
711 pic16_addpCode2pBlock(pb,pcf);
712 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
713 printIval (sym, sym->type, sym->ival, pb);
716 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
723 fprintf (code->oFile, "%s:\n", sym->rname);
724 /* special case for character strings */
725 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
726 SPEC_CVAL (sym->etype).v_char)
727 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
728 /*printChar (code->oFile,
729 SPEC_CVAL (sym->etype).v_char,
730 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
732 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
736 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
737 // __FILE__, __LINE__, sym->name);
739 if (options.debug || sym->level == 0)
740 fprintf (code->oFile, " == .\n");
742 /* if it has an initial value */
747 fprintf (code->oFile, "%s:\n", sym->rname);
749 resolveIvalSym (sym->ival, sym->type);
750 //printIval (sym, sym->type, sym->ival, code->oFile);
751 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
753 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
755 printIval (sym, sym->type, sym->ival, pb);
763 fprintf (code->oFile, "%s:\n", sym->rname);
764 /* special case for character strings */
765 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
766 SPEC_CVAL (sym->etype).v_char)
767 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
768 /*printChar (code->oFile,
769 SPEC_CVAL (sym->etype).v_char,
770 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
772 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
780 /*-----------------------------------------------------------------*/
781 /* pic16_emitConfigRegs - emits the configuration registers */
782 /*-----------------------------------------------------------------*/
783 void pic16_emitConfigRegs(FILE *of)
787 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
788 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
789 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
790 pic16->cwInfo.confAddrStart+i,
791 pic16->cwInfo.crInfo[i].value);
798 /* no special considerations for the following
799 data, idata & bit & xdata */
800 pic16emitRegularMap (data, TRUE, TRUE);
801 pic16emitRegularMap (idata, TRUE, TRUE);
802 pic16emitRegularMap (bit, TRUE, FALSE);
803 pic16emitRegularMap (xdata, TRUE, TRUE);
804 pic16emitRegularMap (sfr, FALSE, FALSE);
805 pic16emitRegularMap (sfrbit, FALSE, FALSE);
806 pic16emitRegularMap (code, TRUE, FALSE);
807 pic16emitStaticSeg (statsg);
810 /*-----------------------------------------------------------------*/
811 /* createInterruptVect - creates the interrupt vector */
812 /*-----------------------------------------------------------------*/
814 pic16createInterruptVect (FILE * vFile)
816 /* if the main is only a prototype ie. no body then do nothing */
818 if (!IFFUNC_HASBODY(mainf->type)) {
819 /* if ! compile only then main function should be present */
820 if (!options.cc_only)
826 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
827 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
828 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
829 fprintf (vFile, "__interrupt_vect:\n");
831 /* this is an overkill since WE are the port,
832 * and we know if we have a genIVT function! */
834 port->genIVT(vFile, interrupts, maxInterrupts);
841 /*-----------------------------------------------------------------*/
842 /* pic16initialComments - puts in some initial comments */
843 /*-----------------------------------------------------------------*/
845 pic16initialComments (FILE * afile)
847 initialComments (afile);
848 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
849 fprintf (afile, iComments2);
853 /*-----------------------------------------------------------------*/
854 /* printPublics - generates global declarations for publics */
855 /*-----------------------------------------------------------------*/
857 pic16printPublics (FILE *afile)
861 fprintf (afile, "%s", iComments2);
862 fprintf (afile, "; public variables in this module\n");
863 fprintf (afile, "%s", iComments2);
865 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
866 fprintf(afile, "\tglobal %s\n", sym->rname);
869 /*-----------------------------------------------------------------*/
870 /* printExterns - generates extern declarations for externs */
871 /*-----------------------------------------------------------------*/
873 pic16_printExterns(FILE *afile)
877 fprintf(afile, "%s", iComments2);
878 fprintf(afile, "; extern variables in this module\n");
879 fprintf(afile, "%s", iComments2);
881 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
882 fprintf(afile, "\textern %s\n", sym->rname);
884 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
885 fprintf(afile, "\textern _%s\n", sym->name);
888 /*-----------------------------------------------------------------*/
889 /* emitOverlay - will emit code for the overlay stuff */
890 /*-----------------------------------------------------------------*/
892 pic16emitOverlay (FILE * afile)
896 if (!elementsInSet (ovrSetSets))
897 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
899 /* for each of the sets in the overlay segment do */
900 for (ovrset = setFirstItem (ovrSetSets); ovrset;
901 ovrset = setNextItem (ovrSetSets))
906 if (elementsInSet (ovrset))
908 /* this dummy area is used to fool the assembler
909 otherwise the assembler will append each of these
910 declarations into one chunk and will not overlay
912 fprintf (afile, ";\t.area _DUMMY\n");
913 /* output the area informtion */
914 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
917 for (sym = setFirstItem (ovrset); sym;
918 sym = setNextItem (ovrset))
921 /* if extern then do nothing */
922 if (IS_EXTERN (sym->etype))
925 /* if allocation required check is needed
926 then check if the symbol really requires
927 allocation only for local variables */
928 if (!IS_AGGREGATE (sym->type) &&
929 !(sym->_isparm && !IS_REGPARM (sym->etype))
930 && !sym->allocreq && sym->level)
933 /* if global variable & not static or extern
934 and addPublics allowed then add it to the public set */
935 if ((sym->_isparm && !IS_REGPARM (sym->etype))
936 && !IS_STATIC (sym->etype)) {
937 checkAddSym(&publics, sym);
938 // addSetHead (&publics, sym);
941 /* if extern then do nothing or is a function
943 if (IS_FUNC (sym->type))
947 /* print extra debug info if required */
948 if (options.debug || sym->level == 0)
951 cdbSymbol (sym, cdbFile, FALSE, FALSE);
955 if (IS_STATIC (sym->etype))
956 fprintf (afile, "F%s_", moduleName); /* scope is file */
958 fprintf (afile, "G_"); /* scope is global */
961 /* symbol is local */
962 fprintf (afile, "L%s_",
963 (sym->localof ? sym->localof->name : "-null-"));
964 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
968 /* if is has an absolute address then generate
969 an equate for this no need to allocate space */
970 if (SPEC_ABSA (sym->etype))
973 if (options.debug || sym->level == 0)
974 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
976 fprintf (afile, "%s\t=\t0x%04x\n",
978 SPEC_ADDR (sym->etype));
982 if (options.debug || sym->level == 0)
983 fprintf (afile, "==.\n");
986 fprintf (afile, "%s:\n", sym->rname);
987 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
995 /*-----------------------------------------------------------------*/
996 /* glue - the final glue that hold the whole thing together */
997 /*-----------------------------------------------------------------*/
1004 FILE *ovrFile = tempfile();
1007 mainf = newSymbol ("main", 0);
1010 mainf = findSymWithLevel(SymbolTab, mainf);
1012 /* only if the main function exists */
1013 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
1014 if (!options.cc_only)
1020 // fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
1022 addSetHead(&tmpfileSet,ovrFile);
1023 pic16_pCodeInitRegisters();
1025 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1026 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1028 pic16_addpBlock(pb);
1030 /* entry point @ start of CSEG */
1031 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1034 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1035 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
1036 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1037 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
1040 /* put in the call to main */
1041 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1043 if (options.mainreturn) {
1044 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1045 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1047 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1048 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1052 /* At this point we've got all the code in the form of pCode structures */
1053 /* Now it needs to be rearranged into the order it should be placed in the */
1056 pic16_movepBlock2Head('P'); // Last
1057 pic16_movepBlock2Head(code->dbName);
1058 pic16_movepBlock2Head('X');
1059 pic16_movepBlock2Head(statsg->dbName); // First
1061 /* print the global struct definitions */
1062 // if (options.debug)
1063 // cdbStructBlock (0); //,cdbFile);
1066 /* PENDING: this isnt the best place but it will do */
1067 if (port->general.glue_up_main) {
1068 /* create the interrupt vector table */
1069 pic16createInterruptVect (vFile);
1072 addSetHead(&tmpfileSet,vFile);
1074 /* emit code for the all the variables declared */
1076 /* do the overlay segments */
1077 pic16emitOverlay(ovrFile);
1078 pic16_AnalyzepCode('*');
1083 sprintf(buffer, dstFileName);
1084 strcat(buffer, ".calltree");
1085 cFile = fopen(buffer, "w");
1086 pic16_printCallTree( cFile );
1091 pic16_InlinepCode();
1092 pic16_AnalyzepCode('*');
1094 if(pic16_debug_verbose)
1097 /* now put it all together into the assembler file */
1098 /* create the assembler file name */
1099 if ((noAssemble || options.c1mode) && fullDstFileName) {
1100 sprintf (buffer, fullDstFileName);
1102 sprintf (buffer, dstFileName);
1103 strcat (buffer, ".asm");
1106 if (!(asmFile = fopen (buffer, "w"))) {
1107 werror (E_FILE_OPEN_ERR, buffer);
1111 /* initial comments */
1112 pic16initialComments (asmFile);
1114 /* print module name */
1115 fprintf(asmFile, "#FILE\t\"%s\"\n", fullSrcFileName);
1117 /* Let the port generate any global directives, etc. */
1118 if (port->genAssemblerPreamble) {
1119 port->genAssemblerPreamble(asmFile);
1122 /* print the extern variables to this module */
1123 pic16_printExterns(asmFile);
1125 /* print the global variables in this module */
1126 pic16printPublics (asmFile);
1129 /* copy the sfr segment */
1130 fprintf (asmFile, "%s", iComments2);
1131 fprintf (asmFile, "; special function registers\n");
1132 fprintf (asmFile, "%s", iComments2);
1133 copyFile (asmFile, sfr->oFile);
1137 /* Put all variables into a cblock */
1138 pic16_AnalyzeBanking();
1139 pic16_writeUsedRegs(asmFile);
1142 /* create the overlay segments */
1143 fprintf (asmFile, "%s", iComments2);
1144 fprintf (asmFile, "; overlayable items in internal ram \n");
1145 fprintf (asmFile, "%s", iComments2);
1146 copyFile (asmFile, ovrFile);
1151 /* create the stack segment MOF */
1152 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1153 fprintf (asmFile, "%s", iComments2);
1154 fprintf (asmFile, "; Stack segment in internal ram \n");
1155 fprintf (asmFile, "%s", iComments2);
1156 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1157 ";__start__stack:\n;\t.ds\t1\n\n");
1162 /* no indirect data in pic */
1163 /* create the idata segment */
1164 fprintf (asmFile, "%s", iComments2);
1165 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1166 fprintf (asmFile, "%s", iComments2);
1167 copyFile (asmFile, idata->oFile);
1172 /* no xdata in pic */
1173 /* if external stack then reserve space of it */
1174 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1175 fprintf (asmFile, "%s", iComments2);
1176 fprintf (asmFile, "; external stack \n");
1177 fprintf (asmFile, "%s", iComments2);
1178 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1179 fprintf (asmFile,";\t.ds 256\n");
1184 /* no xdata in pic */
1185 /* copy xtern ram data */
1186 fprintf (asmFile, "%s", iComments2);
1187 fprintf (asmFile, "; external ram data\n");
1188 fprintf (asmFile, "%s", iComments2);
1189 copyFile (asmFile, xdata->oFile);
1193 /* copy the bit segment */
1194 fprintf (asmFile, "%s", iComments2);
1195 fprintf (asmFile, "; bit data\n");
1196 fprintf (asmFile, "%s", iComments2);
1197 copyFile (asmFile, bit->oFile);
1200 /* copy the interrupt vector table */
1201 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1202 fprintf (asmFile, "%s", iComments2);
1203 fprintf (asmFile, "; interrupt vector \n");
1204 fprintf (asmFile, "%s", iComments2);
1205 copyFile (asmFile, vFile);
1208 /* copy global & static initialisations */
1209 fprintf (asmFile, "%s", iComments2);
1210 fprintf (asmFile, "; global & static initialisations\n");
1211 fprintf (asmFile, "%s", iComments2);
1214 /* copy over code */
1215 fprintf (asmFile, "%s", iComments2);
1216 fprintf (asmFile, "\tcode\n");
1217 fprintf (asmFile, "%s", iComments2);
1220 if(pic16_debug_verbose)
1221 fprintf(asmFile, "; A code from now on!\n");
1222 pic16_copypCode(asmFile, 'A');
1225 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1226 fprintf(asmFile, "\tcode\n");
1227 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1230 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1231 /* if external stack is specified then the
1232 * higher order byte of the xdatalocation is
1233 * going into P2 and the lower order going into */
1235 if (options.useXstack) {
1236 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1237 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1238 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1239 (unsigned int)options.xdata_loc & 0xff);
1244 // copyFile (stderr, code->oFile);
1246 fprintf(asmFile, "; I code from now on!\n");
1247 pic16_copypCode(asmFile, 'I');
1249 if(pic16_debug_verbose)
1250 fprintf(asmFile, "; dbName from now on!\n");
1251 pic16_copypCode(asmFile, statsg->dbName);
1254 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1255 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1259 if(pic16_debug_verbose)
1260 fprintf(asmFile, "; X code from now on!\n");
1261 pic16_copypCode(asmFile, 'X');
1263 if(pic16_debug_verbose)
1264 fprintf(asmFile, "; M code from now on!\n");
1265 pic16_copypCode(asmFile, 'M');
1268 pic16_copypCode(asmFile, code->dbName);
1270 pic16_copypCode(asmFile, 'P');
1272 fprintf (asmFile,"\tend\n");