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. */
107 is_shared_address (int addr)
109 return ((addr > Gstack_base_addr - 18)
110 && (addr <= Gstack_base_addr));
114 pic14_is_shared (regs *reg)
117 return is_shared_address (reg->address);
121 is_valid_identifier( const char *name )
127 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
128 if (!((a >= 'a' && a <= 'z')
129 || (a >= 'A' && a <= 'z')
134 while ((a = *name++))
136 if (!((a >= 'a' && a <= 'z')
137 || (a >= 'A' && a <= 'Z')
138 || (a >= '0' && a <= '9')
143 /* valid identifier */
147 /* set of already emitted symbols; we store only pointers to the emitted
148 * symbol names so these MUST NO BE CHANGED afterwards... */
149 static set *symbolsEmitted = NULL;
151 /*-------------------------------------------------------------------*/
152 /* emitSymbolToFile - write a symbol definition only if it is not */
153 /* already present */
154 /*-------------------------------------------------------------------*/
156 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
159 static unsigned int sec_idx = 0;
161 /* workaround: variables declared via `sbit' result in a numeric
162 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
163 * sbit is heavily used in the inc2h-generated header files!
165 if (!is_valid_identifier(name))
167 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
171 /* check whether the symbol is already defined */
172 for (sym = (const char *) setFirstItem (symbolsEmitted);
174 sym = (const char *) setNextItem (symbolsEmitted))
176 if (!strcmp (sym, name))
178 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
183 /* new symbol -- define it */
184 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
186 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
189 /* we place each symbol into a section of its own to allow the linker
190 * to distribute the data into all available memory banks */
191 if (!section_type) section_type = "udata";
194 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
195 if (is_shared_address (addr))
197 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
198 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName, sec_idx++, section_type, addr);
199 fprintf (of, "%s\tres\t%d\n", name, size);
203 /* EQUs cannot be exported... */
204 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
207 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
208 fprintf (of, "udata_%s_%u\t%s\n", moduleName, sec_idx++, section_type);
209 fprintf (of, "%s\tres\t%d\n", name, size);
213 addSet (&symbolsEmitted, (void *) name);
216 /*-----------------------------------------------------------------*/
217 /* emitRegularMap - emit code for maps with no special cases */
218 /*-----------------------------------------------------------------*/
220 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
225 /* print the area name */
227 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
229 for (sym = setFirstItem (map->syms); sym;
230 sym = setNextItem (map->syms)) {
232 //printf("%s\n",sym->name);
234 /* if extern then add it into the extern list */
235 if (IS_EXTERN (sym->etype)) {
236 addSetHead (&externs, sym);
240 /* if allocation required check is needed
241 then check if the symbol really requires
242 allocation only for local variables */
243 if (arFlag && !IS_AGGREGATE (sym->type) &&
244 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
245 !sym->allocreq && sym->level)
248 /* if global variable & not static or extern
249 and addPublics allowed then add it to the public set */
250 if ((sym->level == 0 ||
251 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
253 !IS_STATIC (sym->etype))
254 addSetHead (&publics, sym);
256 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
259 /* if extern then do nothing or is a function
261 if (IS_FUNC (sym->type))
264 /* print extra debug info if required */
265 if (options.debug || sym->level == 0)
267 if (!sym->level) /* global */
268 if (IS_STATIC (sym->etype))
269 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
271 fprintf (map->oFile, "G_"); /* scope is global */
273 /* symbol is local */
274 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
275 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
279 /* if it has an absolute address then generate
280 an equate for this no need to allocate space */
281 if (SPEC_ABSA (sym->etype))
283 //if (options.debug || sym->level == 0)
284 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
286 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
288 SPEC_ADDR (sym->etype));
294 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
295 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
296 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
297 if (IS_BITVAR (sym->etype))
303 emitSymbolToFile (map->oFile, sym->rname, NULL, getSize (sym->type) & 0xffff, -1, 0, 0);
308 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
310 for (i = 1; i < size; i++)
311 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
316 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
319 /* if it has a initial value then do it only if
320 it is a global variable */
321 if (sym->ival && sym->level == 0) {
324 if (IS_AGGREGATE (sym->type))
325 ival = initAggregates (sym, sym->ival, NULL);
327 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
328 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
329 codeOutFile = statsg->oFile;
331 eBBlockFromiCode (iCodeFromAst (ival));
338 /*-----------------------------------------------------------------*/
339 /* printIvalType - generates ival for int/char */
340 /*-----------------------------------------------------------------*/
342 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
347 //fprintf(stderr, "%s\n",__FUNCTION__);
349 /* if initList is deep */
350 if (ilist->type == INIT_DEEP)
351 ilist = ilist->init.deep;
353 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
354 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
357 if (!(val = list2val (ilist))) {
358 // assuming a warning has been thrown
362 if (val->type != type) {
363 val = valCastLiteral(type, floatFromVal(val));
367 ulval = (unsigned long) floatFromVal (val);
371 switch (getSize (type)) {
373 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
377 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
378 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
382 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
383 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
384 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
385 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
390 /*-----------------------------------------------------------------*/
391 /* printIvalBitFields - generate initializer for bitfields */
392 /*-----------------------------------------------------------------*/
393 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
397 initList *lilist = *ilist ;
398 unsigned long ival = 0;
404 val = list2val(lilist);
406 if (SPEC_BLEN(lsym->etype) > 8) {
407 size += ((SPEC_BLEN (lsym->etype) / 8) +
408 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
411 size = ((SPEC_BLEN (lsym->etype) / 8) +
412 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
414 i = (unsigned long)floatFromVal(val);
415 i <<= SPEC_BSTR (lsym->etype);
417 if (! ( lsym->next &&
418 (IS_BITFIELD(lsym->next->type)) &&
419 (SPEC_BSTR(lsym->next->etype)))) break;
421 lilist = lilist->next;
425 //tfprintf (oFile, "\t!db !constbyte\n",ival);
426 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
430 //tfprintf (oFile, "\t!dw !constword\n",ival);
431 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
432 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
435 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
436 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
437 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
438 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
439 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
446 /*-----------------------------------------------------------------*/
447 /* printIvalStruct - generates initial value for structures */
448 /*-----------------------------------------------------------------*/
449 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
452 initList *iloop = NULL;
454 sflds = SPEC_STRUCT (type)->fields;
457 if (ilist->type != INIT_DEEP) {
458 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
462 iloop = ilist->init.deep;
465 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
466 if (IS_BITFIELD(sflds->type)) {
467 printIvalBitFields(&sflds,&iloop,pb);
469 printIval (sym, sflds->type, iloop, pb);
473 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
478 /*-----------------------------------------------------------------*/
479 /* printIvalChar - generates initital value for character array */
480 /*-----------------------------------------------------------------*/
482 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
490 //fprintf(stderr, "%s\n",__FUNCTION__);
494 val = list2val (ilist);
496 /* if the value is a character string */
497 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
499 ilen = DCL_ELEM(val->type);
501 if (!DCL_ELEM (type))
502 DCL_ELEM (type) = ilen;
504 /* emit string constant */
505 for (remain = 0; remain < ilen; remain++) {
506 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
509 /* fill array up to desired size */
510 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
512 //tfprintf (oFile, "\t!db !constbyte\n", 0);
513 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
520 //printChar (oFile, s, strlen (s) + 1);
522 for(remain=0; remain<(int)strlen(s); remain++) {
523 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
524 //fprintf(stderr,"0x%02x ",s[remain]);
526 //fprintf(stderr,"\n");
531 /*-----------------------------------------------------------------*/
532 /* printIvalArray - generates code for array initialization */
533 /*-----------------------------------------------------------------*/
535 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
544 /* take care of the special case */
545 /* array of characters can be init */
547 if (IS_CHAR (type->next)) {
548 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
549 if (!IS_LITERAL(list2val(ilist)->etype)) {
550 werror (W_INIT_WRONG);
553 if (printIvalChar (type,
554 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
555 pb, SPEC_CVAL (sym->etype).v_char))
558 /* not the special case */
559 if (ilist->type != INIT_DEEP) {
560 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
564 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
565 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
566 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
569 printIval (sym, type->next, iloop, pb);
573 if (DCL_ELEM(type)) {
574 // pad with zeros if needed
575 if (size<DCL_ELEM(type)) {
576 size = (DCL_ELEM(type) - size) * getSize(type->next);
578 //tfprintf (oFile, "\t!db !constbyte\n", 0);
579 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
583 // we have not been given a size, but we now know it
584 DCL_ELEM (type) = size;
590 /*-----------------------------------------------------------------*/
591 /* printIvalPtr - generates code for initial value of pointers */
592 /*-----------------------------------------------------------------*/
593 extern value *initPointer (initList *, sym_link *toType);
596 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
603 fprintf (stderr, "FIXME: initializers for pointers...\n");
604 printTypeChain (type, stderr);
606 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
607 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
609 if (ilist && (ilist->type == INIT_DEEP))
610 ilist = ilist->init.deep;
612 /* function pointers */
613 if (IS_FUNC (type->next))
615 assert ( !"function pointers not yet handled" );
616 //printIvalFuncPtr (type, ilist, pb);
619 if (!(val = initPointer (ilist, type)))
622 if (IS_CHAR (type->next))
624 if (printIvalChar (type, ilist, pb, NULL)) return;
628 if (compareType (type, val->type) == 0)
630 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
631 printFromToType (val->type, type);
634 if (IS_LITERAL (val->etype))
636 switch (getSize (type))
639 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
642 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
644 case 3: /* gneric pointers */
645 assert ( !"generic pointers not yet handled" );
647 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
650 assert ( !"invaild size of value -- aborting" );
656 /* now handle symbolic values */
657 switch (getSize (type))
660 fprintf (stderr, "BYTE: %s", val->name);
663 fprintf (stderr, "WORD: %s", val->name);
666 fprintf (stderr, "LONG: %s", val->name);
669 assert ( !"invalid size of (symbolic) value -- aborting" );
673 /*-----------------------------------------------------------------*/
674 /* printIval - generates code for initial value */
675 /*-----------------------------------------------------------------*/
677 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
682 /* if structure then */
683 if (IS_STRUCT (type))
685 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
686 printIvalStruct (sym, type, ilist, pb);
690 /* if this is an array */
693 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
694 printIvalArray (sym, type, ilist, pb);
698 /* if this is a pointer */
701 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
702 printIvalPtr (sym, type, ilist, pb);
706 /* if type is SPECIFIER */
709 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
710 printIvalType (sym, type, ilist, pb);
715 extern void pCodeConstString(char *name, char *value);
716 /*-----------------------------------------------------------------*/
717 /* emitStaticSeg - emitcode for the static segment */
718 /*-----------------------------------------------------------------*/
720 pic14emitStaticSeg (memmap * map)
724 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
726 //fprintf(stderr, "%s\n",__FUNCTION__);
728 /* for all variables in this segment do */
729 for (sym = setFirstItem (map->syms); sym;
730 sym = setNextItem (map->syms))
732 /* if extern then add it into the extern list */
733 if (IS_EXTERN (sym->etype)) {
734 addSetHead (&externs, sym);
738 /* if it is not static add it to the public
740 if (!IS_STATIC (sym->etype))
741 addSetHead (&publics, sym);
743 /* print extra debug info if required */
744 if (options.debug || sym->level == 0)
748 if (IS_STATIC (sym->etype))
749 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
751 fprintf (code->oFile, "G_"); /* scope is global */
754 /* symbol is local */
755 fprintf (code->oFile, "L%s_",
756 (sym->localof ? sym->localof->name : "-null-"));
757 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
761 /* if it has an absolute address */
762 if (SPEC_ABSA (sym->etype))
764 if (options.debug || sym->level == 0)
765 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
767 fprintf (code->oFile, "%s\t=\t0x%04x\n",
769 SPEC_ADDR (sym->etype));
773 if (options.debug || sym->level == 0)
774 fprintf (code->oFile, " == .\n");
776 /* if it has an initial value */
781 fprintf (code->oFile, "%s:\n", sym->rname);
783 resolveIvalSym (sym->ival, sym->type);
784 //printIval (sym, sym->type, sym->ival, code->oFile);
785 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
787 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
789 printIval (sym, sym->type, sym->ival, pb);
796 fprintf (code->oFile, "%s:\n", sym->rname);
797 /* special case for character strings */
798 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
799 SPEC_CVAL (sym->etype).v_char)
800 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
801 /*printChar (code->oFile,
802 SPEC_CVAL (sym->etype).v_char,
803 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
805 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
813 /*-----------------------------------------------------------------*/
814 /* emitMaps - emits the code for the data portion the code */
815 /*-----------------------------------------------------------------*/
819 /* no special considerations for the following
820 data, idata & bit & xdata */
821 pic14emitRegularMap (data, TRUE, TRUE);
822 pic14emitRegularMap (idata, TRUE, TRUE);
823 pic14emitRegularMap (bit, TRUE, FALSE);
824 pic14emitRegularMap (xdata, TRUE, TRUE);
825 pic14emitRegularMap (sfr, FALSE, FALSE);
826 pic14emitRegularMap (sfrbit, FALSE, FALSE);
827 pic14emitRegularMap (code, TRUE, FALSE);
828 pic14emitStaticSeg (statsg);
831 /*-----------------------------------------------------------------*/
832 /* createInterruptVect - creates the interrupt vector */
833 /*-----------------------------------------------------------------*/
835 pic14createInterruptVect (FILE * vFile)
837 mainf = newSymbol ("main", 0);
840 /* only if the main function exists */
841 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
843 struct options *op = &options;
844 if (!(op->cc_only || noAssemble))
845 // werror (E_NO_MAIN);
846 fprintf(stderr,"WARNING: function 'main' undefined\n");
850 /* if the main is only a prototype ie. no body then do nothing */
851 if (!IFFUNC_HASBODY(mainf->type))
853 /* if ! compile only then main function should be present */
854 if (!(options.cc_only || noAssemble))
855 // werror (E_NO_MAIN);
856 fprintf(stderr,"WARNING: function 'main' undefined\n");
860 fprintf (vFile, "%s", iComments2);
861 fprintf (vFile, "; config word \n");
862 fprintf (vFile, "%s", iComments2);
863 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
865 fprintf (vFile, "%s", iComments2);
866 fprintf (vFile, "; reset vector \n");
867 fprintf (vFile, "%s", iComments2);
868 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
869 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
870 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
874 /*-----------------------------------------------------------------*/
875 /* initialComments - puts in some initial comments */
876 /*-----------------------------------------------------------------*/
878 pic14initialComments (FILE * afile)
880 initialComments (afile);
881 fprintf (afile, "; PIC port for the 14-bit core\n");
882 fprintf (afile, iComments2);
886 /*-----------------------------------------------------------------*/
887 /* printExterns - generates extern for external variables */
888 /*-----------------------------------------------------------------*/
890 pic14printExterns (FILE * afile)
894 fprintf (afile, "%s", iComments2);
895 fprintf (afile, "; extern variables in this module\n");
896 fprintf (afile, "%s", iComments2);
898 for (sym = setFirstItem (externs); sym;
899 sym = setNextItem (externs))
900 fprintf (afile, "\textern %s\n", sym->rname);
903 /*-----------------------------------------------------------------*/
904 /* printPublics - generates .global for publics */
905 /*-----------------------------------------------------------------*/
907 pic14printPublics (FILE * afile)
911 fprintf (afile, "%s", iComments2);
912 fprintf (afile, "; publics variables in this module\n");
913 fprintf (afile, "%s", iComments2);
915 for (sym = setFirstItem (publics); sym;
916 sym = setNextItem (publics)) {
918 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
919 if (!IS_BITVAR(sym->type))
920 fprintf (afile, "\tglobal %s\n", sym->rname);
922 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
923 if (!SPEC_ABSA (sym->etype))
924 fprintf (afile, "\tglobal %s\n", sym->rname);
929 /*-----------------------------------------------------------------*/
930 /* emitOverlay - will emit code for the overlay stuff */
931 /*-----------------------------------------------------------------*/
933 pic14emitOverlay (FILE * afile)
937 /* if (!elementsInSet (ovrSetSets))*/
939 /* the hack below, fixes translates for devices which
940 * only have udata_shr memory */
941 fprintf (afile, "%s\t%s\n",
942 (elementsInSet(ovrSetSets)?"":";"),
943 port->mem.overlay_name);
945 /* for each of the sets in the overlay segment do */
946 for (ovrset = setFirstItem (ovrSetSets); ovrset;
947 ovrset = setNextItem (ovrSetSets))
952 if (elementsInSet (ovrset))
954 /* this dummy area is used to fool the assembler
955 otherwise the assembler will append each of these
956 declarations into one chunk and will not overlay
959 /* I don't think this applies to us. We are using gpasm. CRF */
961 fprintf (afile, ";\t.area _DUMMY\n");
962 /* output the area informtion */
963 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
966 for (sym = setFirstItem (ovrset); sym;
967 sym = setNextItem (ovrset))
970 /* if extern then do nothing */
971 if (IS_EXTERN (sym->etype))
974 /* if allocation required check is needed
975 then check if the symbol really requires
976 allocation only for local variables */
977 if (!IS_AGGREGATE (sym->type) &&
978 !(sym->_isparm && !IS_REGPARM (sym->etype))
979 && !sym->allocreq && sym->level)
982 /* if global variable & not static or extern
983 and addPublics allowed then add it to the public set */
984 if ((sym->_isparm && !IS_REGPARM (sym->etype))
985 && !IS_STATIC (sym->etype))
986 addSetHead (&publics, sym);
988 /* if extern then do nothing or is a function
990 if (IS_FUNC (sym->type))
993 /* print extra debug info if required */
994 if (options.debug || sym->level == 0)
998 if (IS_STATIC (sym->etype))
999 fprintf (afile, "F%s_", moduleName); /* scope is file */
1001 fprintf (afile, "G_"); /* scope is global */
1004 /* symbol is local */
1005 fprintf (afile, "L%s_",
1006 (sym->localof ? sym->localof->name : "-null-"));
1007 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1010 /* if is has an absolute address then generate
1011 an equate for this no need to allocate space */
1012 if (SPEC_ABSA (sym->etype))
1015 if (options.debug || sym->level == 0)
1016 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1018 fprintf (afile, "%s\t=\t0x%04x\n",
1020 SPEC_ADDR (sym->etype));
1024 if (options.debug || sym->level == 0)
1025 fprintf (afile, "==.\n");
1027 /* allocate space */
1028 fprintf (afile, "%s:\n", sym->rname);
1029 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1037 /*-----------------------------------------------------------------*/
1038 /* glue - the final glue that hold the whole thing together */
1039 /*-----------------------------------------------------------------*/
1043 char udata_name[80];
1046 FILE *ovrFile = tempfile();
1048 addSetHead(&tmpfileSet,ovrFile);
1049 pCodeInitRegisters();
1051 /* check for main() */
1052 mainf = newSymbol ("main", 0);
1054 mainf = findSymWithLevel (SymbolTab, mainf);
1056 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1058 /* main missing -- import stack from main module */
1059 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1060 pic14_options.isLibrarySource = 1;
1064 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1066 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1069 /* entry point @ start of CSEG */
1070 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1071 /* put in the call to main */
1072 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1074 if (options.mainreturn) {
1076 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1077 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1081 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1082 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1088 /* At this point we've got all the code in the form of pCode structures */
1089 /* Now it needs to be rearranged into the order it should be placed in the */
1092 movepBlock2Head('P'); // Last
1093 movepBlock2Head(code->dbName);
1094 movepBlock2Head('X');
1095 movepBlock2Head(statsg->dbName); // First
1098 /* print the global struct definitions */
1104 addSetHead(&tmpfileSet,vFile);
1106 /* emit code for the all the variables declared */
1108 /* do the overlay segments */
1109 pic14emitOverlay(ovrFile);
1111 /* PENDING: this isnt the best place but it will do */
1112 if (port->general.glue_up_main) {
1113 /* create the interrupt vector table */
1114 pic14createInterruptVect (vFile);
1119 ReuseReg(); // ReuseReg where call tree permits
1128 /* now put it all together into the assembler file */
1129 /* create the assembler file name */
1131 if ((noAssemble || options.c1mode) && fullDstFileName)
1133 sprintf (buffer, fullDstFileName);
1137 sprintf (buffer, dstFileName);
1138 strcat (buffer, ".asm");
1141 if (!(asmFile = fopen (buffer, "w"))) {
1142 werror (E_FILE_OPEN_ERR, buffer);
1146 /* prepare statistics */
1147 resetpCodeStatistics ();
1149 /* initial comments */
1150 pic14initialComments (asmFile);
1152 /* print module name */
1153 fprintf (asmFile, ";\t.module %s\n", moduleName);
1155 /* Let the port generate any global directives, etc. */
1156 if (port->genAssemblerPreamble)
1158 port->genAssemblerPreamble(asmFile);
1161 /* print the extern variables in this module */
1162 pic14printExterns (asmFile);
1164 /* print the global variables in this module */
1165 pic14printPublics (asmFile);
1167 /* copy the sfr segment */
1168 fprintf (asmFile, "%s", iComments2);
1169 fprintf (asmFile, "; special function registers\n");
1170 fprintf (asmFile, "%s", iComments2);
1171 copyFile (asmFile, sfr->oFile);
1174 if (udata_section_name) {
1175 sprintf(udata_name,"%s",udata_section_name);
1177 sprintf(udata_name,"data_%s",moduleName);
1179 fprintf (asmFile, "%s", iComments2);
1180 fprintf (asmFile, "; udata\n");
1181 fprintf (asmFile, "%s", iComments2);
1182 fprintf (asmFile, "%s\tudata\n", udata_name);
1183 copyFile (asmFile, data->oFile);
1185 /* Put all variables into a cblock */
1187 writeUsedRegs(asmFile);
1189 /* create the overlay segments */
1190 fprintf (asmFile, "%s", iComments2);
1191 fprintf (asmFile, "; overlayable items in internal ram \n");
1192 fprintf (asmFile, "%s", iComments2);
1193 copyFile (asmFile, ovrFile);
1197 /* create the stack segment MOF */
1198 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1199 fprintf (asmFile, "%s", iComments2);
1200 fprintf (asmFile, "; Stack segment in internal ram \n");
1201 fprintf (asmFile, "%s", iComments2);
1202 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1203 ";__start__stack:\n;\t.ds\t1\n\n");
1206 /* create the idata segment */
1207 fprintf (asmFile, "%s", iComments2);
1208 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1209 fprintf (asmFile, "%s", iComments2);
1210 copyFile (asmFile, idata->oFile);
1212 /* if external stack then reserve space of it */
1213 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1214 fprintf (asmFile, "%s", iComments2);
1215 fprintf (asmFile, "; external stack \n");
1216 fprintf (asmFile, "%s", iComments2);
1217 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1218 fprintf (asmFile,";\t.ds 256\n");
1221 /* copy xtern ram data */
1222 fprintf (asmFile, "%s", iComments2);
1223 fprintf (asmFile, "; external ram data\n");
1224 fprintf (asmFile, "%s", iComments2);
1225 copyFile (asmFile, xdata->oFile);
1229 /* copy the bit segment */
1230 fprintf (asmFile, "%s", iComments2);
1231 fprintf (asmFile, "; bit data\n");
1232 fprintf (asmFile, "%s", iComments2);
1233 copyFile (asmFile, bit->oFile);
1235 /* copy the interrupt vector table */
1236 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1237 copyFile (asmFile, vFile);
1239 fprintf (asmFile, "%s", iComments2);
1240 fprintf (asmFile, "; interrupt and initialization code\n");
1241 fprintf (asmFile, "%s", iComments2);
1242 fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1244 /* interrupt service routine */
1245 fprintf (asmFile, "__sdcc_interrupt\n");
1246 copypCode(asmFile, 'I');
1248 /* initialize data memory */
1249 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1250 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1251 /* FIXME: This is temporary. The idata section should be used. If
1252 not, we could add a special feature to the linker. This will
1253 work in the mean time. Put all initalized data in main.c */
1254 copypCode(asmFile, statsg->dbName);
1255 fprintf (asmFile,"\tpagesel _main\n");
1256 fprintf (asmFile,"\tgoto _main\n");
1261 /* copy global & static initialisations */
1262 fprintf (asmFile, "%s", iComments2);
1263 fprintf (asmFile, "; global & static initialisations\n");
1264 fprintf (asmFile, "%s", iComments2);
1265 copypCode(asmFile, statsg->dbName);
1269 /* copy over code */
1270 fprintf (asmFile, "%s", iComments2);
1271 fprintf (asmFile, "; code\n");
1272 fprintf (asmFile, "%s", iComments2);
1273 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1276 copypCode(asmFile, 'X');
1278 /* _main function */
1279 copypCode(asmFile, 'M');
1281 /* other functions */
1282 copypCode(asmFile, code->dbName);
1285 copypCode(asmFile, 'P');
1287 dumppCodeStatistics (asmFile);
1289 fprintf (asmFile,"\tend\n");