1 /*-------------------------------------------------------------------------
3 SDCCglue.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"
34 #ifdef WORDS_BIGENDIAN
35 #define _ENDIAN(x) (3-x)
37 #define _ENDIAN(x) (x)
40 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
42 extern symbol *interrupts[256];
43 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
47 extern unsigned maxInterrupts;
48 extern int maxRegBank;
50 extern char *VersionString;
51 extern FILE *codeOutFile;
52 extern set *tmpfileSet;
53 extern set *tmpfileNameSet;
54 extern char *iComments1;
55 extern char *iComments2;
56 //extern void emitStaticSeg (memmap * map);
58 extern DEFSETFUNC (closeTmpFiles);
59 extern DEFSETFUNC (rmTmpFiles);
61 extern void AnalyzeBanking (void);
62 extern void copyFile (FILE * dest, FILE * src);
63 extern void ReuseReg(void);
64 extern void InlinepCode(void);
65 extern void writeUsedRegs(FILE *);
67 extern void initialComments (FILE * afile);
68 extern void printPublics (FILE * afile);
70 extern void printChar (FILE * ofile, char *s, int plen);
71 void pCodeInitRegisters(void);
72 int getConfigWord(int address);
74 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
76 /*-----------------------------------------------------------------*/
77 /* aopLiteral - string from a literal value */
78 /*-----------------------------------------------------------------*/
79 int pic14aopLiteral (value *val, int offset)
86 /* if it is a float then it gets tricky */
87 /* otherwise it is fairly simple */
88 if (!IS_FLOAT(val->type)) {
89 unsigned long v = (unsigned long) floatFromVal(val);
91 return ( (v >> (offset * 8)) & 0xff);
94 /* it is type float */
95 fl.f = (float) floatFromVal(val);
96 #ifdef WORDS_BIGENDIAN
97 return fl.c[3-offset];
104 /* Check whether the given reg is shared amongst all .o files of a project.
105 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
106 int is_shared_address (int addr)
108 return ((addr > Gstack_base_addr - 18)
109 && (addr <= Gstack_base_addr));
113 is_shared (regs *reg)
116 return is_shared_address (reg->address);
119 /* set of already emitted symbols; we store only pointers to the emitted
120 * symbol names so these MUST NO BE CHANGED afterwards... */
121 static set *symbolsEmitted = NULL;
123 /*-------------------------------------------------------------------*/
124 /* emitSymbolToFile - write a symbol definition only if it is not */
125 /* already present */
126 /*-------------------------------------------------------------------*/
128 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
131 static unsigned int sec_idx = 0;
133 /* check whether the symbol is already defined */
134 for (sym = (const char *) setFirstItem (symbolsEmitted);
136 sym = (const char *) setNextItem (symbolsEmitted))
138 if (!strcmp (sym, name))
140 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
145 /* new symbol -- define it */
146 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
148 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
151 /* we place each symbol into a section of its own to allow the linker
152 * to distribute the data into all available memory banks */
153 if (!section_type) section_type = "udata";
156 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
157 if (is_shared_address (addr))
159 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
160 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName, sec_idx++, section_type, addr);
161 fprintf (of, "%s\tres\t%d\n", name, size);
165 /* EQUs cannot be exported... */
166 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
169 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
170 fprintf (of, "udata_%s_%u\t%s\n", moduleName, sec_idx++, section_type);
171 fprintf (of, "%s\tres\t%d\n", name, size);
175 addSet (&symbolsEmitted, (void *) name);
178 /*-----------------------------------------------------------------*/
179 /* emitRegularMap - emit code for maps with no special cases */
180 /*-----------------------------------------------------------------*/
182 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
187 /* print the area name */
189 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
191 for (sym = setFirstItem (map->syms); sym;
192 sym = setNextItem (map->syms)) {
194 //printf("%s\n",sym->name);
196 /* if extern then add it into the extern list */
197 if (IS_EXTERN (sym->etype)) {
198 addSetHead (&externs, sym);
202 /* if allocation required check is needed
203 then check if the symbol really requires
204 allocation only for local variables */
205 if (arFlag && !IS_AGGREGATE (sym->type) &&
206 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
207 !sym->allocreq && sym->level)
210 /* if global variable & not static or extern
211 and addPublics allowed then add it to the public set */
212 if ((sym->level == 0 ||
213 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
215 !IS_STATIC (sym->etype))
216 addSetHead (&publics, sym);
218 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
221 /* if extern then do nothing or is a function
223 if (IS_FUNC (sym->type))
226 /* print extra debug info if required */
227 if (options.debug || sym->level == 0)
229 if (!sym->level) /* global */
230 if (IS_STATIC (sym->etype))
231 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
233 fprintf (map->oFile, "G_"); /* scope is global */
235 /* symbol is local */
236 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
237 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
241 /* if it has an absolute address then generate
242 an equate for this no need to allocate space */
243 if (SPEC_ABSA (sym->etype))
245 //if (options.debug || sym->level == 0)
246 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
248 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
250 SPEC_ADDR (sym->etype));
256 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
257 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
258 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
259 if (IS_BITVAR (sym->etype))
265 emitSymbolToFile (map->oFile, sym->rname, NULL, getSize (sym->type) & 0xffff, -1, 0, 0);
270 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
272 for (i = 1; i < size; i++)
273 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
278 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
281 /* if it has a initial value then do it only if
282 it is a global variable */
283 if (sym->ival && sym->level == 0) {
286 if (IS_AGGREGATE (sym->type))
287 ival = initAggregates (sym, sym->ival, NULL);
289 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
290 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
291 codeOutFile = statsg->oFile;
293 eBBlockFromiCode (iCodeFromAst (ival));
300 /*-----------------------------------------------------------------*/
301 /* printIvalType - generates ival for int/char */
302 /*-----------------------------------------------------------------*/
304 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
309 //fprintf(stderr, "%s\n",__FUNCTION__);
311 /* if initList is deep */
312 if (ilist->type == INIT_DEEP)
313 ilist = ilist->init.deep;
315 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
316 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
319 if (!(val = list2val (ilist))) {
320 // assuming a warning has been thrown
324 if (val->type != type) {
325 val = valCastLiteral(type, floatFromVal(val));
329 ulval = (unsigned long) floatFromVal (val);
333 switch (getSize (type)) {
335 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
339 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
340 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
344 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
345 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
346 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
347 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
352 /*-----------------------------------------------------------------*/
353 /* printIvalBitFields - generate initializer for bitfields */
354 /*-----------------------------------------------------------------*/
355 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
359 initList *lilist = *ilist ;
360 unsigned long ival = 0;
366 val = list2val(lilist);
368 if (SPEC_BLEN(lsym->etype) > 8) {
369 size += ((SPEC_BLEN (lsym->etype) / 8) +
370 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
373 size = ((SPEC_BLEN (lsym->etype) / 8) +
374 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
376 i = (unsigned long)floatFromVal(val);
377 i <<= SPEC_BSTR (lsym->etype);
379 if (! ( lsym->next &&
380 (IS_BITFIELD(lsym->next->type)) &&
381 (SPEC_BSTR(lsym->next->etype)))) break;
383 lilist = lilist->next;
387 //tfprintf (oFile, "\t!db !constbyte\n",ival);
388 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
392 //tfprintf (oFile, "\t!dw !constword\n",ival);
393 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
394 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
397 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
398 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
399 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
400 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
401 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
408 /*-----------------------------------------------------------------*/
409 /* printIvalStruct - generates initial value for structures */
410 /*-----------------------------------------------------------------*/
411 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
414 initList *iloop = NULL;
416 sflds = SPEC_STRUCT (type)->fields;
419 if (ilist->type != INIT_DEEP) {
420 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
424 iloop = ilist->init.deep;
427 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
428 if (IS_BITFIELD(sflds->type)) {
429 printIvalBitFields(&sflds,&iloop,pb);
431 printIval (sym, sflds->type, iloop, pb);
435 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
440 /*-----------------------------------------------------------------*/
441 /* printIvalChar - generates initital value for character array */
442 /*-----------------------------------------------------------------*/
444 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
452 //fprintf(stderr, "%s\n",__FUNCTION__);
456 val = list2val (ilist);
458 /* if the value is a character string */
459 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
461 ilen = DCL_ELEM(val->type);
463 if (!DCL_ELEM (type))
464 DCL_ELEM (type) = ilen;
466 /* emit string constant */
467 for (remain = 0; remain < ilen; remain++) {
468 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
471 /* fill array up to desired size */
472 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
474 //tfprintf (oFile, "\t!db !constbyte\n", 0);
475 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
482 //printChar (oFile, s, strlen (s) + 1);
484 for(remain=0; remain<(int)strlen(s); remain++) {
485 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
486 //fprintf(stderr,"0x%02x ",s[remain]);
488 //fprintf(stderr,"\n");
493 /*-----------------------------------------------------------------*/
494 /* printIvalArray - generates code for array initialization */
495 /*-----------------------------------------------------------------*/
497 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
506 /* take care of the special case */
507 /* array of characters can be init */
509 if (IS_CHAR (type->next)) {
510 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
511 if (!IS_LITERAL(list2val(ilist)->etype)) {
512 werror (W_INIT_WRONG);
515 if (printIvalChar (type,
516 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
517 pb, SPEC_CVAL (sym->etype).v_char))
520 /* not the special case */
521 if (ilist->type != INIT_DEEP) {
522 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
526 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
527 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
528 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
531 printIval (sym, type->next, iloop, pb);
535 if (DCL_ELEM(type)) {
536 // pad with zeros if needed
537 if (size<DCL_ELEM(type)) {
538 size = (DCL_ELEM(type) - size) * getSize(type->next);
540 //tfprintf (oFile, "\t!db !constbyte\n", 0);
541 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
545 // we have not been given a size, but we now know it
546 DCL_ELEM (type) = size;
552 /*-----------------------------------------------------------------*/
553 /* printIvalPtr - generates code for initial value of pointers */
554 /*-----------------------------------------------------------------*/
555 extern value *initPointer (initList *, sym_link *toType);
558 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
565 fprintf (stderr, "FIXME: initializers for pointers...\n");
566 printTypeChain (type, stderr);
568 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
569 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
571 if (ilist && (ilist->type == INIT_DEEP))
572 ilist = ilist->init.deep;
574 /* function pointers */
575 if (IS_FUNC (type->next))
577 assert ( !"function pointers not yet handled" );
578 //printIvalFuncPtr (type, ilist, pb);
581 if (!(val = initPointer (ilist, type)))
584 if (IS_CHAR (type->next))
586 if (printIvalChar (type, ilist, pb, NULL)) return;
590 if (compareType (type, val->type) == 0)
592 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
593 printFromToType (val->type, type);
596 if (IS_LITERAL (val->etype))
598 switch (getSize (type))
601 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
604 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
606 case 3: /* gneric pointers */
607 assert ( !"generic pointers not yet handled" );
609 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
612 assert ( !"invaild size of value -- aborting" );
618 /* now handle symbolic values */
619 switch (getSize (type))
622 fprintf (stderr, "BYTE: %s", val->name);
625 fprintf (stderr, "WORD: %s", val->name);
628 fprintf (stderr, "LONG: %s", val->name);
631 assert ( !"invalid size of (symbolic) value -- aborting" );
635 /*-----------------------------------------------------------------*/
636 /* printIval - generates code for initial value */
637 /*-----------------------------------------------------------------*/
639 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
644 /* if structure then */
645 if (IS_STRUCT (type))
647 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
648 printIvalStruct (sym, type, ilist, pb);
652 /* if this is an array */
655 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
656 printIvalArray (sym, type, ilist, pb);
660 /* if this is a pointer */
663 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
664 printIvalPtr (sym, type, ilist, pb);
668 /* if type is SPECIFIER */
671 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
672 printIvalType (sym, type, ilist, pb);
677 extern void pCodeConstString(char *name, char *value);
678 /*-----------------------------------------------------------------*/
679 /* emitStaticSeg - emitcode for the static segment */
680 /*-----------------------------------------------------------------*/
682 pic14emitStaticSeg (memmap * map)
686 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
688 //fprintf(stderr, "%s\n",__FUNCTION__);
690 /* for all variables in this segment do */
691 for (sym = setFirstItem (map->syms); sym;
692 sym = setNextItem (map->syms))
694 /* if extern then add it into the extern list */
695 if (IS_EXTERN (sym->etype)) {
696 addSetHead (&externs, sym);
700 /* if it is not static add it to the public
702 if (!IS_STATIC (sym->etype))
703 addSetHead (&publics, sym);
705 /* print extra debug info if required */
706 if (options.debug || sym->level == 0)
710 if (IS_STATIC (sym->etype))
711 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
713 fprintf (code->oFile, "G_"); /* scope is global */
716 /* symbol is local */
717 fprintf (code->oFile, "L%s_",
718 (sym->localof ? sym->localof->name : "-null-"));
719 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
723 /* if it has an absolute address */
724 if (SPEC_ABSA (sym->etype))
726 if (options.debug || sym->level == 0)
727 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
729 fprintf (code->oFile, "%s\t=\t0x%04x\n",
731 SPEC_ADDR (sym->etype));
735 if (options.debug || sym->level == 0)
736 fprintf (code->oFile, " == .\n");
738 /* if it has an initial value */
743 fprintf (code->oFile, "%s:\n", sym->rname);
745 resolveIvalSym (sym->ival, sym->type);
746 //printIval (sym, sym->type, sym->ival, code->oFile);
747 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
749 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
751 printIval (sym, sym->type, sym->ival, pb);
758 fprintf (code->oFile, "%s:\n", sym->rname);
759 /* special case for character strings */
760 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
761 SPEC_CVAL (sym->etype).v_char)
762 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
763 /*printChar (code->oFile,
764 SPEC_CVAL (sym->etype).v_char,
765 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
767 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
775 /*-----------------------------------------------------------------*/
776 /* emitMaps - emits the code for the data portion the code */
777 /*-----------------------------------------------------------------*/
781 /* no special considerations for the following
782 data, idata & bit & xdata */
783 pic14emitRegularMap (data, TRUE, TRUE);
784 pic14emitRegularMap (idata, TRUE, TRUE);
785 pic14emitRegularMap (bit, TRUE, FALSE);
786 pic14emitRegularMap (xdata, TRUE, TRUE);
787 pic14emitRegularMap (sfr, FALSE, FALSE);
788 pic14emitRegularMap (sfrbit, FALSE, FALSE);
789 pic14emitRegularMap (code, TRUE, FALSE);
790 pic14emitStaticSeg (statsg);
793 /*-----------------------------------------------------------------*/
794 /* createInterruptVect - creates the interrupt vector */
795 /*-----------------------------------------------------------------*/
797 pic14createInterruptVect (FILE * vFile)
799 mainf = newSymbol ("main", 0);
802 /* only if the main function exists */
803 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
805 struct options *op = &options;
806 if (!(op->cc_only || noAssemble))
807 // werror (E_NO_MAIN);
808 fprintf(stderr,"WARNING: function 'main' undefined\n");
812 /* if the main is only a prototype ie. no body then do nothing */
813 if (!IFFUNC_HASBODY(mainf->type))
815 /* if ! compile only then main function should be present */
816 if (!(options.cc_only || noAssemble))
817 // werror (E_NO_MAIN);
818 fprintf(stderr,"WARNING: function 'main' undefined\n");
822 fprintf (vFile, "%s", iComments2);
823 fprintf (vFile, "; config word \n");
824 fprintf (vFile, "%s", iComments2);
825 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
827 fprintf (vFile, "%s", iComments2);
828 fprintf (vFile, "; reset vector \n");
829 fprintf (vFile, "%s", iComments2);
830 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
831 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
832 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
836 /*-----------------------------------------------------------------*/
837 /* initialComments - puts in some initial comments */
838 /*-----------------------------------------------------------------*/
840 pic14initialComments (FILE * afile)
842 initialComments (afile);
843 fprintf (afile, "; PIC port for the 14-bit core\n");
844 fprintf (afile, iComments2);
848 /*-----------------------------------------------------------------*/
849 /* printExterns - generates extern for external variables */
850 /*-----------------------------------------------------------------*/
852 pic14printExterns (FILE * afile)
856 fprintf (afile, "%s", iComments2);
857 fprintf (afile, "; extern variables in this module\n");
858 fprintf (afile, "%s", iComments2);
860 for (sym = setFirstItem (externs); sym;
861 sym = setNextItem (externs))
862 fprintf (afile, "\textern %s\n", sym->rname);
865 /*-----------------------------------------------------------------*/
866 /* printPublics - generates .global for publics */
867 /*-----------------------------------------------------------------*/
869 pic14printPublics (FILE * afile)
873 fprintf (afile, "%s", iComments2);
874 fprintf (afile, "; publics variables in this module\n");
875 fprintf (afile, "%s", iComments2);
877 for (sym = setFirstItem (publics); sym;
878 sym = setNextItem (publics)) {
880 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
881 if (!IS_BITVAR(sym->type))
882 fprintf (afile, "\tglobal %s\n", sym->rname);
884 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
885 if (!SPEC_ABSA (sym->etype))
886 fprintf (afile, "\tglobal %s\n", sym->rname);
891 /*-----------------------------------------------------------------*/
892 /* emitOverlay - will emit code for the overlay stuff */
893 /*-----------------------------------------------------------------*/
895 pic14emitOverlay (FILE * afile)
899 /* if (!elementsInSet (ovrSetSets))*/
901 /* the hack below, fixes translates for devices which
902 * only have udata_shr memory */
903 fprintf (afile, "%s\t%s\n",
904 (elementsInSet(ovrSetSets)?"":";"),
905 port->mem.overlay_name);
907 /* for each of the sets in the overlay segment do */
908 for (ovrset = setFirstItem (ovrSetSets); ovrset;
909 ovrset = setNextItem (ovrSetSets))
914 if (elementsInSet (ovrset))
916 /* this dummy area is used to fool the assembler
917 otherwise the assembler will append each of these
918 declarations into one chunk and will not overlay
921 /* I don't think this applies to us. We are using gpasm. CRF */
923 fprintf (afile, ";\t.area _DUMMY\n");
924 /* output the area informtion */
925 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
928 for (sym = setFirstItem (ovrset); sym;
929 sym = setNextItem (ovrset))
932 /* if extern then do nothing */
933 if (IS_EXTERN (sym->etype))
936 /* if allocation required check is needed
937 then check if the symbol really requires
938 allocation only for local variables */
939 if (!IS_AGGREGATE (sym->type) &&
940 !(sym->_isparm && !IS_REGPARM (sym->etype))
941 && !sym->allocreq && sym->level)
944 /* if global variable & not static or extern
945 and addPublics allowed then add it to the public set */
946 if ((sym->_isparm && !IS_REGPARM (sym->etype))
947 && !IS_STATIC (sym->etype))
948 addSetHead (&publics, sym);
950 /* if extern then do nothing or is a function
952 if (IS_FUNC (sym->type))
955 /* print extra debug info if required */
956 if (options.debug || sym->level == 0)
960 if (IS_STATIC (sym->etype))
961 fprintf (afile, "F%s_", moduleName); /* scope is file */
963 fprintf (afile, "G_"); /* scope is global */
966 /* symbol is local */
967 fprintf (afile, "L%s_",
968 (sym->localof ? sym->localof->name : "-null-"));
969 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
972 /* if is has an absolute address then generate
973 an equate for this no need to allocate space */
974 if (SPEC_ABSA (sym->etype))
977 if (options.debug || sym->level == 0)
978 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
980 fprintf (afile, "%s\t=\t0x%04x\n",
982 SPEC_ADDR (sym->etype));
986 if (options.debug || sym->level == 0)
987 fprintf (afile, "==.\n");
990 fprintf (afile, "%s:\n", sym->rname);
991 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
999 /*-----------------------------------------------------------------*/
1000 /* glue - the final glue that hold the whole thing together */
1001 /*-----------------------------------------------------------------*/
1005 char udata_name[80];
1008 FILE *ovrFile = tempfile();
1010 addSetHead(&tmpfileSet,ovrFile);
1011 pCodeInitRegisters();
1013 /* check for main() */
1014 mainf = newSymbol ("main", 0);
1016 mainf = findSymWithLevel (SymbolTab, mainf);
1018 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1020 /* main missing -- import stack from main module */
1021 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1022 pic14_options.isLibrarySource = 1;
1026 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1028 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1031 /* entry point @ start of CSEG */
1032 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1033 /* put in the call to main */
1034 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1036 if (options.mainreturn) {
1038 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1039 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1043 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1044 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1050 /* At this point we've got all the code in the form of pCode structures */
1051 /* Now it needs to be rearranged into the order it should be placed in the */
1054 movepBlock2Head('P'); // Last
1055 movepBlock2Head(code->dbName);
1056 movepBlock2Head('X');
1057 movepBlock2Head(statsg->dbName); // First
1060 /* print the global struct definitions */
1066 addSetHead(&tmpfileSet,vFile);
1068 /* emit code for the all the variables declared */
1070 /* do the overlay segments */
1071 pic14emitOverlay(ovrFile);
1073 /* PENDING: this isnt the best place but it will do */
1074 if (port->general.glue_up_main) {
1075 /* create the interrupt vector table */
1076 pic14createInterruptVect (vFile);
1081 ReuseReg(); // ReuseReg where call tree permits
1090 /* now put it all together into the assembler file */
1091 /* create the assembler file name */
1093 if ((noAssemble || options.c1mode) && fullDstFileName)
1095 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 /* prepare statistics */
1109 resetpCodeStatistics ();
1111 /* initial comments */
1112 pic14initialComments (asmFile);
1114 /* print module name */
1115 fprintf (asmFile, ";\t.module %s\n", moduleName);
1117 /* Let the port generate any global directives, etc. */
1118 if (port->genAssemblerPreamble)
1120 port->genAssemblerPreamble(asmFile);
1123 /* print the extern variables in this module */
1124 pic14printExterns (asmFile);
1126 /* print the global variables in this module */
1127 pic14printPublics (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);
1136 if (udata_section_name) {
1137 sprintf(udata_name,"%s",udata_section_name);
1139 sprintf(udata_name,"data_%s",moduleName);
1141 fprintf (asmFile, "%s", iComments2);
1142 fprintf (asmFile, "; udata\n");
1143 fprintf (asmFile, "%s", iComments2);
1144 fprintf (asmFile, "%s\tudata\n", udata_name);
1145 copyFile (asmFile, data->oFile);
1147 /* Put all variables into a cblock */
1149 writeUsedRegs(asmFile);
1151 /* create the overlay segments */
1152 fprintf (asmFile, "%s", iComments2);
1153 fprintf (asmFile, "; overlayable items in internal ram \n");
1154 fprintf (asmFile, "%s", iComments2);
1155 copyFile (asmFile, ovrFile);
1159 /* create the stack segment MOF */
1160 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1161 fprintf (asmFile, "%s", iComments2);
1162 fprintf (asmFile, "; Stack segment in internal ram \n");
1163 fprintf (asmFile, "%s", iComments2);
1164 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1165 ";__start__stack:\n;\t.ds\t1\n\n");
1168 /* create the idata segment */
1169 fprintf (asmFile, "%s", iComments2);
1170 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1171 fprintf (asmFile, "%s", iComments2);
1172 copyFile (asmFile, idata->oFile);
1174 /* if external stack then reserve space of it */
1175 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1176 fprintf (asmFile, "%s", iComments2);
1177 fprintf (asmFile, "; external stack \n");
1178 fprintf (asmFile, "%s", iComments2);
1179 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1180 fprintf (asmFile,";\t.ds 256\n");
1183 /* copy xtern ram data */
1184 fprintf (asmFile, "%s", iComments2);
1185 fprintf (asmFile, "; external ram data\n");
1186 fprintf (asmFile, "%s", iComments2);
1187 copyFile (asmFile, xdata->oFile);
1191 /* copy the bit segment */
1192 fprintf (asmFile, "%s", iComments2);
1193 fprintf (asmFile, "; bit data\n");
1194 fprintf (asmFile, "%s", iComments2);
1195 copyFile (asmFile, bit->oFile);
1197 /* copy the interrupt vector table */
1198 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1199 copyFile (asmFile, vFile);
1201 fprintf (asmFile, "%s", iComments2);
1202 fprintf (asmFile, "; interrupt and initialization code\n");
1203 fprintf (asmFile, "%s", iComments2);
1204 fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1206 /* interrupt service routine */
1207 fprintf (asmFile, "__sdcc_interrupt\n");
1208 copypCode(asmFile, 'I');
1210 /* initialize data memory */
1211 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1212 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1213 /* FIXME: This is temporary. The idata section should be used. If
1214 not, we could add a special feature to the linker. This will
1215 work in the mean time. Put all initalized data in main.c */
1216 copypCode(asmFile, statsg->dbName);
1217 fprintf (asmFile,"\tpagesel _main\n");
1218 fprintf (asmFile,"\tgoto _main\n");
1223 /* copy global & static initialisations */
1224 fprintf (asmFile, "%s", iComments2);
1225 fprintf (asmFile, "; global & static initialisations\n");
1226 fprintf (asmFile, "%s", iComments2);
1227 copypCode(asmFile, statsg->dbName);
1231 /* copy over code */
1232 fprintf (asmFile, "%s", iComments2);
1233 fprintf (asmFile, "; code\n");
1234 fprintf (asmFile, "%s", iComments2);
1235 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1238 copypCode(asmFile, 'X');
1240 /* _main function */
1241 copypCode(asmFile, 'M');
1243 /* other functions */
1244 copypCode(asmFile, code->dbName);
1247 copypCode(asmFile, 'P');
1249 dumppCodeStatistics (asmFile);
1251 fprintf (asmFile,"\tend\n");