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"
35 #ifdef WORDS_BIGENDIAN
36 #define _ENDIAN(x) (3-x)
38 #define _ENDIAN(x) (x)
41 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 extern symbol *interrupts[256];
44 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
48 extern unsigned maxInterrupts;
49 extern int maxRegBank;
51 extern char *VersionString;
52 extern FILE *codeOutFile;
53 extern set *tmpfileSet;
54 extern set *tmpfileNameSet;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
58 set *pic14_localFunctions = NULL;
60 extern DEFSETFUNC (closeTmpFiles);
61 extern DEFSETFUNC (rmTmpFiles);
63 extern void AnalyzeBanking (void);
64 extern void copyFile (FILE * dest, FILE * src);
65 extern void ReuseReg(void);
66 extern void InlinepCode(void);
67 extern void writeUsedRegs(FILE *);
69 extern void initialComments (FILE * afile);
70 extern void printPublics (FILE * afile);
72 extern void printChar (FILE * ofile, char *s, int plen);
73 void pCodeInitRegisters(void);
74 int getConfigWord(int address);
75 int getHasSecondConfigReg(void);
77 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
78 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
80 static set *emitted = NULL;
81 int pic14_stringInSet(const char *str, set **world, int autoAdd);
82 static void emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
84 /*-----------------------------------------------------------------*/
85 /* aopLiteral - string from a literal value */
86 /*-----------------------------------------------------------------*/
87 unsigned int pic14aopLiteral (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];
113 is_valid_identifier( const char *name )
119 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
120 if (!((a >= 'a' && a <= 'z')
121 || (a >= 'A' && a <= 'z')
126 while ((a = *name++))
128 if (!((a >= 'a' && a <= 'z')
129 || (a >= 'A' && a <= 'Z')
130 || (a >= '0' && a <= '9')
135 /* valid identifier */
139 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
140 extern int IS_CONFIG_ADDRESS( int addr );
142 pic14_constructAbsMap (FILE *ofile)
144 memmap *maps[] = { data, sfr, NULL };
149 int addr, min=-1, max=-1;
152 int low, high, shared;
154 for (i=0; maps[i] != NULL; i++)
156 for (sym = (symbol *)setFirstItem (maps[i]->syms);
157 sym; sym = setNextItem (maps[i]->syms))
159 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
161 addr = SPEC_ADDR(sym->etype);
163 /* handle CONFIG words here */
164 if (IS_CONFIG_ADDRESS( addr ))
166 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
167 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
169 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
171 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
176 if (max == -1 || addr > max) max = addr;
177 if (min == -1 || addr < min) min = addr;
178 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
179 aliases = hTabItemWithKey (ht, addr);
181 /* May not use addSetHead, as we cannot update the
182 * list's head in the hastable `ht'. */
183 addSet (&aliases, sym);
185 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
186 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
189 addSet (&aliases, sym);
190 hTabAddItem (&ht, addr, aliases);
196 /* now emit definitions for all absolute symbols */
197 fprintf (ofile, "%s", iComments2);
198 fprintf (ofile, "; absolute symbol definitions\n");
199 fprintf (ofile, "%s", iComments2);
200 for (addr=min; addr <= max; addr++)
203 aliases = hTabItemWithKey (ht, addr);
204 if (aliases && elementsInSet(aliases)) {
205 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
206 moduleName, addr, addr);
207 for (sym = setFirstItem (aliases); sym;
208 sym = setNextItem (aliases))
210 /* emit STATUS as well as _STATUS, required for SFRs only */
211 fprintf (ofile, "\n%s", sym->name);
212 fprintf (ofile, "\n%s", sym->rname);
213 if (getSize(sym->type) > size) {
214 size = getSize(sym->type);
217 // global symbols must be emitted again as 'global sym->name'
218 pic14_stringInSet(sym->name, &emitted, 1);
219 pic14_stringInSet(sym->rname, &emitted, 1);
222 fprintf (ofile, "\tres\t%d\n", size);
226 /* also emit STK symbols
227 * XXX: This is ugly and fails as soon as devices start to get
228 * differently sized sharebanks, since STK12 will be
229 * required by larger devices but only up to STK03 might
230 * be defined using smaller devices. */
231 fprintf (ofile, "\n");
232 shared = pic14_getSharedStack(&low, &high, &size);
233 if (!pic14_options.isLibrarySource)
235 pic = pic14_getPIC();
237 fprintf (ofile, "\tglobal PSAVE\n");
238 fprintf (ofile, "\tglobal SSAVE\n");
239 fprintf (ofile, "\tglobal WSAVE\n");
240 for (i = size - 4; i >= 0; i--) {
241 fprintf (ofile, "\tglobal STK%02d\n", i);
244 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
247 // for single banked devices: use normal, "banked" RAM
248 fprintf (ofile, "sharebank udata_ovr 0x%04X\n", low);
250 // for devices with at least two banks, require a sharebank section
251 fprintf (ofile, "sharebank udata_shr\n");
253 fprintf (ofile, "PSAVE\tres 1\n");
254 fprintf (ofile, "SSAVE\tres 1\n");
255 fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
256 /* fill rest of sharebank with stack STKxx .. STK00 */
257 for (i = size - 4; i >= 0; i--) {
258 fprintf (ofile, "STK%02d\tres 1\n", i);
261 /* declare STKxx as extern for all files
262 * except the one containing main() */
263 fprintf (ofile, "\textern PSAVE\n");
264 fprintf (ofile, "\textern SSAVE\n");
265 fprintf (ofile, "\textern WSAVE\n");
266 for (i = size - 4; i >= 0; i--) {
268 SNPRINTF(&buffer[0], 127, "STK%02d", i);
269 fprintf (ofile, "\textern %s\n", &buffer[0]);
270 pic14_stringInSet(&buffer[0], &emitted, 1);
275 /*-----------------------------------------------------------------*/
276 /* emitRegularMap - emit code for maps with no special cases */
277 /*-----------------------------------------------------------------*/
279 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
284 /* print the area name */
286 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
288 for (sym = setFirstItem (map->syms); sym;
289 sym = setNextItem (map->syms)) {
291 //printf("%s\n",sym->name);
293 /* ignore if config word */
294 if (SPEC_ABSA(sym->etype)
295 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
298 /* if extern then add it into the extern list */
299 if (IS_EXTERN (sym->etype)) {
300 addSetHead (&externs, sym);
304 /* if allocation required check is needed
305 then check if the symbol really requires
306 allocation only for local variables */
307 if (arFlag && !IS_AGGREGATE (sym->type) &&
308 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
309 !sym->allocreq && sym->level)
312 /* if global variable & not static or extern
313 and addPublics allowed then add it to the public set */
314 if ((sym->level == 0 ||
315 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
317 !IS_STATIC (sym->etype))
319 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
320 addSetHead (&publics, sym);
323 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
326 /* if extern then do nothing or is a function
328 if (IS_FUNC (sym->type))
331 /* print extra debug info if required */
332 if (options.debug || sym->level == 0)
334 if (!sym->level) /* global */
335 if (IS_STATIC (sym->etype))
336 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
338 fprintf (map->oFile, "G_"); /* scope is global */
340 /* symbol is local */
341 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
342 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
345 /* absolute symbols are handled in pic14_constructAbsMap */
346 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
349 /* if it has an absolute address then generate
350 an equate for this no need to allocate space */
351 if (0 && SPEC_ABSA (sym->etype))
353 //if (options.debug || sym->level == 0)
354 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
356 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
358 SPEC_ADDR (sym->etype));
364 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
365 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
366 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
367 if (IS_BITVAR (sym->etype))
373 emitSymbolToFile (map->oFile,
376 getSize (sym->type) & 0xffff,
377 SPEC_ABSA(sym->etype)
378 ? SPEC_ADDR(sym->etype)
386 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
388 for (i = 1; i < size; i++)
389 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
394 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
397 /* if it has a initial value then do it only if
398 it is a global variable */
399 if (sym->ival && sym->level == 0) {
402 if (IS_AGGREGATE (sym->type))
403 ival = initAggregates (sym, sym->ival, NULL);
405 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
406 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
407 codeOutFile = statsg->oFile;
409 eBBlockFromiCode (iCodeFromAst (ival));
416 /*-----------------------------------------------------------------*/
417 /* printIvalType - generates ival for int/char */
418 /*-----------------------------------------------------------------*/
420 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
425 //fprintf(stderr, "%s\n",__FUNCTION__);
427 /* if initList is deep */
428 if (ilist->type == INIT_DEEP)
429 ilist = ilist->init.deep;
431 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
432 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
435 if (!(val = list2val (ilist))) {
436 // assuming a warning has been thrown
440 if (val->type != type) {
441 val = valCastLiteral(type, floatFromVal(val));
445 ulval = (unsigned long) floatFromVal (val);
449 switch (getSize (type)) {
451 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
455 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
456 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
460 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
461 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
462 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
463 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
468 /*-----------------------------------------------------------------*/
469 /* printIvalBitFields - generate initializer for bitfields */
470 /*-----------------------------------------------------------------*/
471 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
475 initList *lilist = *ilist ;
476 unsigned long ival = 0;
482 val = list2val(lilist);
484 if (SPEC_BLEN(lsym->etype) > 8) {
485 size += ((SPEC_BLEN (lsym->etype) / 8) +
486 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
489 size = ((SPEC_BLEN (lsym->etype) / 8) +
490 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
492 i = (unsigned long)floatFromVal(val);
493 i <<= SPEC_BSTR (lsym->etype);
495 if (! ( lsym->next &&
496 (IS_BITFIELD(lsym->next->type)) &&
497 (SPEC_BSTR(lsym->next->etype)))) break;
499 lilist = lilist->next;
503 //tfprintf (oFile, "\t!db !constbyte\n",ival);
504 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
508 //tfprintf (oFile, "\t!dw !constword\n",ival);
509 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
510 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
513 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
514 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
515 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
516 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
517 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
524 /*-----------------------------------------------------------------*/
525 /* printIvalStruct - generates initial value for structures */
526 /*-----------------------------------------------------------------*/
527 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
530 initList *iloop = NULL;
532 sflds = SPEC_STRUCT (type)->fields;
535 if (ilist->type != INIT_DEEP) {
536 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
540 iloop = ilist->init.deep;
543 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
544 if (IS_BITFIELD(sflds->type)) {
545 printIvalBitFields(&sflds,&iloop,pb);
547 printIval (sym, sflds->type, iloop, pb);
551 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
556 /*-----------------------------------------------------------------*/
557 /* printIvalChar - generates initital value for character array */
558 /*-----------------------------------------------------------------*/
560 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
568 //fprintf(stderr, "%s\n",__FUNCTION__);
572 val = list2val (ilist);
574 /* if the value is a character string */
575 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
577 ilen = DCL_ELEM(val->type);
579 if (!DCL_ELEM (type))
580 DCL_ELEM (type) = ilen;
582 /* emit string constant */
583 for (remain = 0; remain < ilen; remain++) {
584 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
587 /* fill array up to desired size */
588 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
590 //tfprintf (oFile, "\t!db !constbyte\n", 0);
591 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
598 //printChar (oFile, s, strlen (s) + 1);
600 for(remain=0; remain<(int)strlen(s); remain++) {
601 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
602 //fprintf(stderr,"0x%02x ",s[remain]);
604 //fprintf(stderr,"\n");
609 /*-----------------------------------------------------------------*/
610 /* printIvalArray - generates code for array initialization */
611 /*-----------------------------------------------------------------*/
613 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
622 /* take care of the special case */
623 /* array of characters can be init */
625 if (IS_CHAR (type->next)) {
626 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
627 if (!IS_LITERAL(list2val(ilist)->etype)) {
628 werror (W_INIT_WRONG);
631 if (printIvalChar (type,
632 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
633 pb, SPEC_CVAL (sym->etype).v_char))
636 /* not the special case */
637 if (ilist->type != INIT_DEEP) {
638 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
642 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
643 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
644 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
647 printIval (sym, type->next, iloop, pb);
651 if (DCL_ELEM(type)) {
652 // pad with zeros if needed
653 if (size<DCL_ELEM(type)) {
654 size = (DCL_ELEM(type) - size) * getSize(type->next);
656 //tfprintf (oFile, "\t!db !constbyte\n", 0);
657 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
661 // we have not been given a size, but we now know it
662 DCL_ELEM (type) = size;
668 /*-----------------------------------------------------------------*/
669 /* printIvalPtr - generates code for initial value of pointers */
670 /*-----------------------------------------------------------------*/
671 extern value *initPointer (initList *, sym_link *toType);
674 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
681 fprintf (stderr, "FIXME: initializers for pointers...\n");
682 printTypeChain (type, stderr);
684 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
685 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
687 if (ilist && (ilist->type == INIT_DEEP))
688 ilist = ilist->init.deep;
690 /* function pointers */
691 if (IS_FUNC (type->next))
693 assert ( !"function pointers not yet handled" );
694 //printIvalFuncPtr (type, ilist, pb);
697 if (!(val = initPointer (ilist, type)))
700 if (IS_CHAR (type->next))
702 if (printIvalChar (type, ilist, pb, NULL)) return;
706 if (compareType (type, val->type) == 0)
708 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
709 printFromToType (val->type, type);
712 if (IS_LITERAL (val->etype))
714 switch (getSize (type))
717 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
720 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
722 case 3: /* gneric pointers */
723 assert ( !"generic pointers not yet handled" );
725 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
728 assert ( !"invaild size of value -- aborting" );
734 /* now handle symbolic values */
735 switch (getSize (type))
738 fprintf (stderr, "BYTE: %s", val->name);
741 fprintf (stderr, "WORD: %s", val->name);
744 fprintf (stderr, "LONG: %s", val->name);
747 assert ( !"invalid size of (symbolic) value -- aborting" );
751 /*-----------------------------------------------------------------*/
752 /* printIval - generates code for initial value */
753 /*-----------------------------------------------------------------*/
755 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
760 /* if structure then */
761 if (IS_STRUCT (type))
763 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
764 printIvalStruct (sym, type, ilist, pb);
768 /* if this is an array */
771 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
772 printIvalArray (sym, type, ilist, pb);
776 /* if this is a pointer */
779 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
780 printIvalPtr (sym, type, ilist, pb);
784 /* if type is SPECIFIER */
787 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
788 printIvalType (sym, type, ilist, pb);
793 extern void pCodeConstString(char *name, char *value);
794 /*-----------------------------------------------------------------*/
795 /* emitStaticSeg - emitcode for the static segment */
796 /*-----------------------------------------------------------------*/
798 pic14emitStaticSeg (memmap * map)
802 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
804 //fprintf(stderr, "%s\n",__FUNCTION__);
806 /* for all variables in this segment do */
807 for (sym = setFirstItem (map->syms); sym;
808 sym = setNextItem (map->syms))
810 /* if extern then add it into the extern list */
811 if (IS_EXTERN (sym->etype)) {
812 addSetHead (&externs, sym);
816 /* if it is not static add it to the public
818 if (!IS_STATIC (sym->etype))
819 addSetHead (&publics, sym);
821 /* print extra debug info if required */
822 if (options.debug || sym->level == 0)
826 if (IS_STATIC (sym->etype))
827 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
829 fprintf (code->oFile, "G_"); /* scope is global */
832 /* symbol is local */
833 fprintf (code->oFile, "L%s_",
834 (sym->localof ? sym->localof->name : "-null-"));
835 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
839 /* if it has an absolute address */
840 if (SPEC_ABSA (sym->etype))
842 if (options.debug || sym->level == 0)
843 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
845 fprintf (code->oFile, "%s\t=\t0x%04x\n",
847 SPEC_ADDR (sym->etype));
851 if (options.debug || sym->level == 0)
852 fprintf (code->oFile, " == .\n");
854 /* if it has an initial value */
859 fprintf (code->oFile, "%s:\n", sym->rname);
861 resolveIvalSym (sym->ival, sym->type);
862 //printIval (sym, sym->type, sym->ival, code->oFile);
863 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
865 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
867 printIval (sym, sym->type, sym->ival, pb);
874 fprintf (code->oFile, "%s:\n", sym->rname);
875 /* special case for character strings */
876 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
877 SPEC_CVAL (sym->etype).v_char)
878 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
879 /*printChar (code->oFile,
880 SPEC_CVAL (sym->etype).v_char,
881 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
883 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
891 /*-----------------------------------------------------------------*/
892 /* emitMaps - emits the code for the data portion the code */
893 /*-----------------------------------------------------------------*/
897 pic14_constructAbsMap (sfr->oFile);
898 /* no special considerations for the following
899 data, idata & bit & xdata */
900 pic14emitRegularMap (data, TRUE, TRUE);
901 pic14emitRegularMap (idata, TRUE, TRUE);
902 pic14emitRegularMap (bit, TRUE, FALSE);
903 pic14emitRegularMap (xdata, TRUE, TRUE);
904 pic14emitRegularMap (sfr, TRUE, FALSE);
905 pic14emitRegularMap (sfrbit, FALSE, FALSE);
906 pic14emitRegularMap (code, TRUE, FALSE);
907 pic14emitStaticSeg (statsg);
908 pic14emitStaticSeg (c_abs);
911 /*-----------------------------------------------------------------*/
912 /* createInterruptVect - creates the interrupt vector */
913 /*-----------------------------------------------------------------*/
915 pic14createInterruptVect (FILE * vFile)
917 mainf = newSymbol ("main", 0);
920 /* only if the main function exists */
921 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
923 struct options *op = &options;
924 if (!(op->cc_only || noAssemble))
925 // werror (E_NO_MAIN);
926 fprintf(stderr,"WARNING: function 'main' undefined\n");
930 /* if the main is only a prototype ie. no body then do nothing */
931 if (!IFFUNC_HASBODY(mainf->type))
933 /* if ! compile only then main function should be present */
934 if (!(options.cc_only || noAssemble))
935 // werror (E_NO_MAIN);
936 fprintf(stderr,"WARNING: function 'main' undefined\n");
940 fprintf (vFile, "%s", iComments2);
941 fprintf (vFile, "; reset vector \n");
942 fprintf (vFile, "%s", iComments2);
943 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
944 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
945 fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
946 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
950 /*-----------------------------------------------------------------*/
951 /* initialComments - puts in some initial comments */
952 /*-----------------------------------------------------------------*/
954 pic14initialComments (FILE * afile)
956 initialComments (afile);
957 fprintf (afile, "; PIC port for the 14-bit core\n");
958 fprintf (afile, iComments2);
963 pic14_stringInSet(const char *str, set **world, int autoAdd)
970 for (s = setFirstItem(*world); s; s = setNextItem(*world))
973 if (0 == strcmp(s, str)) return 1;
977 if (autoAdd) addSet(world, Safe_strdup(str));
982 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
984 if (!pic14_stringInSet(sym, &emitted, 1)) {
985 /* sym was not in emittedSymbols */
986 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
987 /* sym is not a locally defined function---avoid bug #1443651 */
988 fprintf( file, fmt, sym );
995 /*-------------------------------------------------------------------*/
996 /* emitSymbolToFile - write a symbol definition only if it is not */
997 /* already present */
998 /*-------------------------------------------------------------------*/
1000 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1002 static unsigned int sec_idx = 0;
1004 /* workaround: variables declared via `sbit' result in a numeric
1005 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1006 * sbit is heavily used in the inc2h-generated header files!
1008 if (!is_valid_identifier(name))
1010 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1014 /* check whether the symbol is already defined */
1015 if (pic14_stringInSet(name, &emitted, 1)) return;
1017 /* new symbol -- define it */
1018 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1020 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
1022 /* we place each symbol into a section of its own to allow the linker
1023 * to distribute the data into all available memory banks */
1024 if (!section_type) section_type = "udata";
1027 /* absolute symbols are handled in pic14_constructAbsMap */
1030 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
1031 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
1032 sec_idx++, section_type);
1033 fprintf (of, "%s\tres\t%d\n", name, size);
1038 /*-----------------------------------------------------------------*/
1039 /* printExterns - generates extern for external variables */
1040 /*-----------------------------------------------------------------*/
1042 pic14printExterns (FILE * afile)
1046 fprintf (afile, "%s", iComments2);
1047 fprintf (afile, "; extern variables in this module\n");
1048 fprintf (afile, "%s", iComments2);
1050 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1051 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1054 /*-----------------------------------------------------------------*/
1055 /* printPublics - generates .global for publics */
1056 /*-----------------------------------------------------------------*/
1058 pic14printPublics (FILE * afile)
1062 fprintf (afile, "%s", iComments2);
1063 fprintf (afile, "; public variables in this module\n");
1064 fprintf (afile, "%s", iComments2);
1066 for (sym = setFirstItem (publics); sym;
1067 sym = setNextItem (publics)) {
1069 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1070 if (!IS_BITVAR(sym->type))
1071 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1073 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1074 /* Not any longer! */
1075 //if (!SPEC_ABSA (sym->etype))
1076 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1082 pic14printLocals (FILE * afile)
1084 set *allregs[6] = { dynAllocRegs, dynStackRegs, dynProcessorRegs, dynDirectRegs, dynDirectBitRegs, dynInternalRegs };
1088 /* emit all registers from all possible sets */
1089 for (i = 0; i < 6; i++) {
1090 if (allregs[i] == NULL) continue;
1092 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1093 if (reg->isEmitted) continue;
1095 if (reg->wasUsed && !reg->isExtern) {
1096 emitSymbolToFile(afile, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, reg->isPublic);
1103 /*-----------------------------------------------------------------*/
1104 /* emitOverlay - will emit code for the overlay stuff */
1105 /*-----------------------------------------------------------------*/
1107 pic14emitOverlay (FILE * afile)
1111 /* if (!elementsInSet (ovrSetSets))*/
1113 /* the hack below, fixes translates for devices which
1114 * only have udata_shr memory */
1115 fprintf (afile, "%s\t%s\n",
1116 (elementsInSet(ovrSetSets)?"":";"),
1117 port->mem.overlay_name);
1119 /* for each of the sets in the overlay segment do */
1120 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1121 ovrset = setNextItem (ovrSetSets))
1126 if (elementsInSet (ovrset))
1128 /* this dummy area is used to fool the assembler
1129 otherwise the assembler will append each of these
1130 declarations into one chunk and will not overlay
1133 /* I don't think this applies to us. We are using gpasm. CRF */
1135 fprintf (afile, ";\t.area _DUMMY\n");
1136 /* output the area informtion */
1137 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1140 for (sym = setFirstItem (ovrset); sym;
1141 sym = setNextItem (ovrset))
1144 /* if extern then do nothing */
1145 if (IS_EXTERN (sym->etype))
1148 /* if allocation required check is needed
1149 then check if the symbol really requires
1150 allocation only for local variables */
1151 if (!IS_AGGREGATE (sym->type) &&
1152 !(sym->_isparm && !IS_REGPARM (sym->etype))
1153 && !sym->allocreq && sym->level)
1156 /* if global variable & not static or extern
1157 and addPublics allowed then add it to the public set */
1158 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1159 && !IS_STATIC (sym->etype))
1160 addSetHead (&publics, sym);
1162 /* if extern then do nothing or is a function
1164 if (IS_FUNC (sym->type))
1167 /* print extra debug info if required */
1168 if (options.debug || sym->level == 0)
1172 if (IS_STATIC (sym->etype))
1173 fprintf (afile, "F%s_", moduleName); /* scope is file */
1175 fprintf (afile, "G_"); /* scope is global */
1178 /* symbol is local */
1179 fprintf (afile, "L%s_",
1180 (sym->localof ? sym->localof->name : "-null-"));
1181 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1184 /* if is has an absolute address then generate
1185 an equate for this no need to allocate space */
1186 if (SPEC_ABSA (sym->etype))
1189 if (options.debug || sym->level == 0)
1190 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1192 fprintf (afile, "%s\t=\t0x%04x\n",
1194 SPEC_ADDR (sym->etype));
1198 if (options.debug || sym->level == 0)
1199 fprintf (afile, "==.\n");
1201 /* allocate space */
1202 fprintf (afile, "%s:\n", sym->rname);
1203 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1212 pic14_emitInterruptHandler (FILE * asmFile)
1214 if (pic14_hasInterrupt)
1217 fprintf (asmFile, "%s", iComments2);
1218 fprintf (asmFile, "; interrupt and initialization code\n");
1219 fprintf (asmFile, "%s", iComments2);
1220 // Note - for mplink may have to enlarge section vectors in .lnk file
1221 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1222 // source files's code segment (interrupt.c -> code_interrupt)
1223 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1225 /* interrupt service routine */
1226 fprintf (asmFile, "__sdcc_interrupt\n");
1227 copypCode(asmFile, 'I');
1231 /*-----------------------------------------------------------------*/
1232 /* glue - the final glue that hold the whole thing together */
1233 /*-----------------------------------------------------------------*/
1237 char udata_name[80];
1240 FILE *ovrFile = tempfile();
1242 addSetHead(&tmpfileSet,ovrFile);
1243 pCodeInitRegisters();
1245 /* check for main() */
1246 mainf = newSymbol ("main", 0);
1248 mainf = findSymWithLevel (SymbolTab, mainf);
1250 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1252 /* main missing -- import stack from main module */
1253 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1254 pic14_options.isLibrarySource = 1;
1258 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1260 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1263 /* entry point @ start of CSEG */
1264 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1265 /* put in the call to main */
1266 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1268 if (options.mainreturn) {
1270 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1271 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1275 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1276 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1282 /* At this point we've got all the code in the form of pCode structures */
1283 /* Now it needs to be rearranged into the order it should be placed in the */
1286 movepBlock2Head('P'); // Last
1287 movepBlock2Head(code->dbName);
1288 movepBlock2Head('X');
1289 movepBlock2Head(statsg->dbName); // First
1292 /* print the global struct definitions */
1298 addSetHead(&tmpfileSet,vFile);
1300 /* emit code for the all the variables declared */
1302 /* do the overlay segments */
1303 pic14emitOverlay(ovrFile);
1305 /* PENDING: this isnt the best place but it will do */
1306 if (port->general.glue_up_main) {
1307 /* create the interrupt vector table */
1308 pic14createInterruptVect (vFile);
1313 ReuseReg(); // ReuseReg where call tree permits
1322 /* now put it all together into the assembler file */
1323 /* create the assembler file name */
1325 if ((noAssemble || options.c1mode) && fullDstFileName)
1327 sprintf (buffer, fullDstFileName);
1331 sprintf (buffer, dstFileName);
1332 strcat (buffer, ".asm");
1335 if (!(asmFile = fopen (buffer, "w"))) {
1336 werror (E_FILE_OPEN_ERR, buffer);
1340 /* prepare statistics */
1341 resetpCodeStatistics ();
1343 /* initial comments */
1344 pic14initialComments (asmFile);
1346 /* print module name */
1347 fprintf (asmFile, ";\t.module %s\n", moduleName);
1349 /* Let the port generate any global directives, etc. */
1350 if (port->genAssemblerPreamble)
1352 port->genAssemblerPreamble(asmFile);
1355 /* Emit the __config directive */
1356 pic14_emitConfigWord (asmFile);
1358 /* print the global variables in this module */
1359 pic14printPublics (asmFile);
1361 /* print the extern variables in this module */
1362 pic14printExterns (asmFile);
1364 /* copy the sfr segment */
1365 fprintf (asmFile, "%s", iComments2);
1366 fprintf (asmFile, "; special function registers\n");
1367 fprintf (asmFile, "%s", iComments2);
1368 copyFile (asmFile, sfr->oFile);
1371 if (udata_section_name) {
1372 sprintf(udata_name,"%s",udata_section_name);
1374 sprintf(udata_name,"data_%s",moduleName);
1376 fprintf (asmFile, "%s", iComments2);
1377 fprintf (asmFile, "; udata\n");
1378 fprintf (asmFile, "%s", iComments2);
1379 fprintf (asmFile, "%s\tudata\n", udata_name);
1380 copyFile (asmFile, data->oFile);
1382 /* Put all variables into a cblock */
1385 /* print the locally defined variables in this module */
1386 writeUsedRegs(asmFile);
1387 pic14printLocals (asmFile);
1389 /* create the overlay segments */
1390 fprintf (asmFile, "%s", iComments2);
1391 fprintf (asmFile, "; overlayable items in internal ram \n");
1392 fprintf (asmFile, "%s", iComments2);
1393 copyFile (asmFile, ovrFile);
1397 /* create the stack segment MOF */
1398 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1399 fprintf (asmFile, "%s", iComments2);
1400 fprintf (asmFile, "; Stack segment in internal ram \n");
1401 fprintf (asmFile, "%s", iComments2);
1402 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1403 ";__start__stack:\n;\t.ds\t1\n\n");
1406 /* create the idata segment */
1407 fprintf (asmFile, "%s", iComments2);
1408 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1409 fprintf (asmFile, "%s", iComments2);
1410 copyFile (asmFile, idata->oFile);
1412 /* if external stack then reserve space of it */
1413 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1414 fprintf (asmFile, "%s", iComments2);
1415 fprintf (asmFile, "; external stack \n");
1416 fprintf (asmFile, "%s", iComments2);
1417 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1418 fprintf (asmFile,";\t.ds 256\n");
1421 /* copy xtern ram data */
1422 fprintf (asmFile, "%s", iComments2);
1423 fprintf (asmFile, "; external ram data\n");
1424 fprintf (asmFile, "%s", iComments2);
1425 copyFile (asmFile, xdata->oFile);
1429 /* copy the bit segment */
1430 fprintf (asmFile, "%s", iComments2);
1431 fprintf (asmFile, "; bit data\n");
1432 fprintf (asmFile, "%s", iComments2);
1433 copyFile (asmFile, bit->oFile);
1435 /* copy the interrupt vector table */
1436 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1437 copyFile (asmFile, vFile);
1440 /* create interupt ventor handler */
1441 pic14_emitInterruptHandler (asmFile);
1443 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1444 /* initialize data memory */
1445 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1446 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1447 /* FIXME: This is temporary. The idata section should be used. If
1448 not, we could add a special feature to the linker. This will
1449 work in the mean time. Put all initalized data in main.c */
1450 copypCode(asmFile, statsg->dbName);
1451 fprintf (asmFile,"\tpagesel _main\n");
1452 fprintf (asmFile,"\tgoto _main\n");
1457 /* copy global & static initialisations */
1458 fprintf (asmFile, "%s", iComments2);
1459 fprintf (asmFile, "; global & static initialisations\n");
1460 fprintf (asmFile, "%s", iComments2);
1461 copypCode(asmFile, statsg->dbName);
1465 /* copy over code */
1466 fprintf (asmFile, "%s", iComments2);
1467 fprintf (asmFile, "; code\n");
1468 fprintf (asmFile, "%s", iComments2);
1469 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1472 copypCode(asmFile, 'X');
1474 /* _main function */
1475 copypCode(asmFile, 'M');
1477 /* other functions */
1478 copypCode(asmFile, code->dbName);
1481 copypCode(asmFile, 'P');
1483 dumppCodeStatistics (asmFile);
1485 fprintf (asmFile,"\tend\n");