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 -------------------------------------------------------------------------*/
26 #include "dbuf_string.h"
38 extern struct dbuf_s *codeOutBuf;
40 extern DEFSETFUNC(closeTmpFiles);
41 extern DEFSETFUNC(rmTmpFiles);
42 extern void initialComments(FILE *afile);
43 extern operand *operandFromAst(ast *tree, int lvl);
44 extern value *initPointer(initList *ilist, sym_link *toType);
47 set *pic14_localFunctions = NULL;
48 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
50 int pic14_stringInSet(const char *str, set **world, int autoAdd);
53 #ifdef WORDS_BIGENDIAN
54 #define _ENDIAN(x) (3-x)
56 #define _ENDIAN(x) (x)
59 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
60 #define IS_GLOBAL(sym) ((sym)->level == 0)
61 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
63 /* dbufs for initialized data (idata and code sections),
64 * extern, and global declarations */
65 static struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
67 static set *emitted = NULL;
69 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
73 is_valid_identifier( const char *name )
79 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
80 if (!((a >= 'a' && a <= 'z')
81 || (a >= 'A' && a <= 'z')
88 if (!((a >= 'a' && a <= 'z')
89 || (a >= 'A' && a <= 'Z')
90 || (a >= '0' && a <= '9')
95 /* valid identifier */
101 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
103 int shared, low, high, size, i;
106 /* also emit STK symbols
107 * XXX: This is ugly and fails as soon as devices start to get
108 * differently sized sharebanks, since STK12 will be
109 * required by larger devices but only up to STK03 might
110 * be defined using smaller devices. */
111 shared = pic14_getSharedStack(&low, &high, &size);
112 if (!pic14_options.isLibrarySource)
114 pic = pic14_getPIC();
116 dbuf_printf (oBuf, "\n");
117 dbuf_printf (oBuf, "\tglobal PSAVE\n");
118 dbuf_printf (oBuf, "\tglobal SSAVE\n");
119 dbuf_printf (oBuf, "\tglobal WSAVE\n");
120 for (i = size - 4; i >= 0; i--) {
121 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
123 dbuf_printf (oBuf, "\n");
125 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
128 // for single banked devices: use normal, "banked" RAM
129 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
131 // for devices with at least two banks, require a sharebank section
132 dbuf_printf (oBuf, "sharebank udata_shr\n");
134 dbuf_printf (oBuf, "PSAVE\tres 1\n");
135 dbuf_printf (oBuf, "SSAVE\tres 1\n");
136 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
137 /* fill rest of sharebank with stack STKxx .. STK00 */
138 for (i = size - 4; i >= 0; i--) {
139 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
142 /* declare STKxx as extern for all files
143 * except the one containing main() */
144 dbuf_printf (oBufExt, "\n");
145 dbuf_printf (oBufExt, "\textern PSAVE\n");
146 dbuf_printf (oBufExt, "\textern SSAVE\n");
147 dbuf_printf (oBufExt, "\textern WSAVE\n");
148 for (i = size - 4; i >= 0; i--) {
150 SNPRINTF(&buffer[0], 127, "STK%02d", i);
151 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
152 pic14_stringInSet(&buffer[0], &emitted, 1);
155 dbuf_printf (oBuf, "\n");
159 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
162 int wasPresent = pic14_stringInSet(name, emitted, 1);
165 dbuf_printf (oBuf, fmt, name);
167 return (!wasPresent);
171 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
173 memmap *maps[] = { data, sfr, NULL };
178 int addr, min=-1, max=-1;
181 for (i=0; maps[i] != NULL; i++)
183 for (sym = (symbol *)setFirstItem (maps[i]->syms);
184 sym; sym = setNextItem (maps[i]->syms))
186 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
188 addr = SPEC_ADDR(sym->etype);
190 /* handle CONFIG words here */
191 if (IS_CONFIG_ADDRESS( addr ))
193 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
194 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
196 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
198 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
203 if (max == -1 || addr > max) max = addr;
204 if (min == -1 || addr < min) min = addr;
205 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
206 aliases = hTabItemWithKey (ht, addr);
208 /* May not use addSetHead, as we cannot update the
209 * list's head in the hastable `ht'. */
210 addSet (&aliases, sym);
212 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
213 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
216 addSet (&aliases, sym);
217 hTabAddItem (&ht, addr, aliases);
223 /* now emit definitions for all absolute symbols */
224 dbuf_printf (oBuf, "%s", iComments2);
225 dbuf_printf (oBuf, "; absolute symbol definitions\n");
226 dbuf_printf (oBuf, "%s", iComments2);
227 for (addr=min; addr <= max; addr++)
230 aliases = hTabItemWithKey (ht, addr);
231 if (aliases && elementsInSet(aliases)) {
232 /* Make sure there is no initialized value at this location! */
233 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
234 if (sym->ival) break;
238 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
239 moduleName, addr, addr);
240 for (sym = setFirstItem (aliases); sym;
241 sym = setNextItem (aliases))
243 if (getSize(sym->type) > size) {
244 size = getSize(sym->type);
247 /* initialized values are handled somewhere else */
248 if (sym->ival) continue;
250 /* emit STATUS as well as _STATUS, required for SFRs only */
251 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
252 dbuf_printf (oBuf, "%s\n", sym->rname);
254 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
255 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
256 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
259 dbuf_printf (oBuf, "\tres\t%d\n", size);
265 /*-----------------------------------------------------------------*/
266 /* emitRegularMap - emit code for maps with no special cases */
267 /*-----------------------------------------------------------------*/
269 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
274 /* print the area name */
276 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
278 for (sym = setFirstItem (map->syms); sym;
279 sym = setNextItem (map->syms)) {
281 //printf("%s\n",sym->name);
283 /* ignore if config word */
284 if (SPEC_ABSA(sym->etype)
285 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
288 /* if extern then add it into the extern list */
289 if (IS_EXTERN (sym->etype)) {
290 addSetHead (&externs, sym);
294 /* if allocation required check is needed
295 then check if the symbol really requires
296 allocation only for local variables */
297 if (arFlag && !IS_AGGREGATE (sym->type) &&
298 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
299 !sym->allocreq && sym->level)
302 /* if global variable & not static or extern
303 and addPublics allowed then add it to the public set */
304 if ((sym->level == 0 ||
305 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
307 !IS_STATIC (sym->etype))
309 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
310 addSetHead (&publics, sym);
313 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
316 /* if extern then do nothing or is a function
318 if (IS_FUNC (sym->type))
321 /* print extra debug info if required */
322 if (options.debug || sym->level == 0)
324 if (!sym->level) /* global */
325 if (IS_STATIC (sym->etype))
326 dbuf_printf (&map->oBuf, "F%s_", moduleName); /* scope is file */
328 dbuf_printf (&map->oBuf, "G_"); /* scope is global */
330 /* symbol is local */
331 dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
332 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
335 /* absolute symbols are handled in pic14_constructAbsMap */
336 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
339 /* if it has an absolute address then generate
340 an equate for this no need to allocate space */
341 if (0 && SPEC_ABSA (sym->etype))
343 //if (options.debug || sym->level == 0)
344 //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
346 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
348 SPEC_ADDR (sym->etype));
354 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
355 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
356 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
357 if (IS_BITVAR (sym->etype))
364 emitSymbol (&map->oBuf,
367 getSize (sym->type) & 0xffff,
368 SPEC_ABSA(sym->etype)
369 ? SPEC_ADDR(sym->etype)
378 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
380 for (i = 1; i < size; i++)
381 dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
386 //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
389 /* if it has a initial value then do it only if
390 it is a global variable */
392 /* mark symbol as already defined */
393 pic14_stringInSet(sym->name, &emitted, 1);
394 pic14_stringInSet(sym->rname, &emitted, 1);
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 codeOutBuf = &statsg->oBuf;
409 eBBlockFromiCode (iCodeFromAst (ival));
419 /*-----------------------------------------------------------------*/
420 /* printIvalType - generates ival for int/char */
421 /*-----------------------------------------------------------------*/
423 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
428 //fprintf(stderr, "%s\n",__FUNCTION__);
430 /* if initList is deep */
431 if (ilist->type == INIT_DEEP)
432 ilist = ilist->init.deep;
434 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
435 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
438 if (!(val = list2val (ilist))) {
439 // assuming a warning has been thrown
440 val = constCharVal (0);
443 if (val->type != type) {
444 val = valCastLiteral(type, floatFromVal(val));
448 ulval = ulFromVal (val);
452 switch (getSize (type)) {
454 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
458 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
459 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
463 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
464 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
465 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
466 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
471 /*-----------------------------------------------------------------*/
472 /* printIvalBitFields - generate initializer for bitfields */
473 /*-----------------------------------------------------------------*/
474 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
478 initList *lilist = *ilist ;
479 unsigned long ival = 0;
485 val = list2val(lilist);
487 if (SPEC_BLEN(lsym->etype) > 8) {
488 size += ((SPEC_BLEN (lsym->etype) / 8) +
489 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
492 size = ((SPEC_BLEN (lsym->etype) / 8) +
493 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
496 i <<= SPEC_BSTR (lsym->etype);
498 if (! ( lsym->next &&
499 (IS_BITFIELD(lsym->next->type)) &&
500 (SPEC_BSTR(lsym->next->etype)))) break;
502 lilist = lilist->next;
506 //tfprintf (oFile, "\t!db !constbyte\n",ival);
507 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
511 //tfprintf (oFile, "\t!dw !constword\n",ival);
512 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
513 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
516 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
517 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
518 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
519 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
520 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
527 /*-----------------------------------------------------------------*/
528 /* printIvalStruct - generates initial value for structures */
529 /*-----------------------------------------------------------------*/
530 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
533 initList *iloop = NULL;
535 sflds = SPEC_STRUCT (type)->fields;
538 if (ilist->type != INIT_DEEP) {
539 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
543 iloop = ilist->init.deep;
546 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
547 if (IS_BITFIELD(sflds->type)) {
548 printIvalBitFields(&sflds,&iloop,pb);
550 printIval (sym, sflds->type, iloop, pb);
554 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
559 /*-----------------------------------------------------------------*/
560 /* printIvalChar - generates initital value for character array */
561 /*-----------------------------------------------------------------*/
563 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
571 //fprintf(stderr, "%s\n",__FUNCTION__);
575 val = list2val (ilist);
577 /* if the value is a character string */
578 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
580 ilen = DCL_ELEM(val->type);
582 if (!DCL_ELEM (type))
583 DCL_ELEM (type) = ilen;
585 /* emit string constant */
586 for (remain = 0; remain < ilen; remain++) {
587 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
590 /* fill array up to desired size */
591 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
593 //tfprintf (oFile, "\t!db !constbyte\n", 0);
594 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
601 //printChar (oFile, s, strlen (s) + 1);
603 for(remain=0; remain<(int)strlen(s); remain++) {
604 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
605 //fprintf(stderr,"0x%02x ",s[remain]);
607 //fprintf(stderr,"\n");
612 /*-----------------------------------------------------------------*/
613 /* printIvalArray - generates code for array initialization */
614 /*-----------------------------------------------------------------*/
616 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
625 /* take care of the special case */
626 /* array of characters can be init */
628 if (IS_CHAR (type->next)) {
629 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
630 if (!IS_LITERAL(list2val(ilist)->etype)) {
631 werror (W_INIT_WRONG);
634 if (printIvalChar (type,
635 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
636 pb, SPEC_CVAL (sym->etype).v_char))
639 /* not the special case */
640 if (ilist->type != INIT_DEEP) {
641 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
645 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
646 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
647 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
650 printIval (sym, type->next, iloop, pb);
654 if (DCL_ELEM(type)) {
655 // pad with zeros if needed
656 if (size<DCL_ELEM(type)) {
657 size = (DCL_ELEM(type) - size) * getSize(type->next);
659 //tfprintf (oFile, "\t!db !constbyte\n", 0);
660 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
664 // we have not been given a size, but we now know it
665 DCL_ELEM (type) = size;
671 /*-----------------------------------------------------------------*/
672 /* printIvalPtr - generates code for initial value of pointers */
673 /*-----------------------------------------------------------------*/
675 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
682 fprintf (stderr, "FIXME: initializers for pointers...\n");
683 printTypeChain (type, stderr);
685 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
686 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
688 if (ilist && (ilist->type == INIT_DEEP))
689 ilist = ilist->init.deep;
691 /* function pointers */
692 if (IS_FUNC (type->next))
694 assert ( !"function pointers not yet handled" );
695 //printIvalFuncPtr (type, ilist, pb);
698 if (!(val = initPointer (ilist, type)))
701 if (IS_CHAR (type->next))
703 if (printIvalChar (type, ilist, pb, NULL)) return;
707 if (compareType (type, val->type) == 0)
709 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
710 printFromToType (val->type, type);
713 if (IS_LITERAL (val->etype))
715 switch (getSize (type))
718 fprintf (stderr, "BYTE: %i\n", (unsigned char) ulFromVal (val) & 0x00FF);
721 fprintf (stderr, "WORD: %i\n", (unsigned int) ulFromVal (val) & 0x00FFFF);
723 case 3: /* gneric pointers */
724 assert ( !"generic pointers not yet handled" );
726 fprintf (stderr, "LONG: %i\n", (unsigned int) ulFromVal (val) & 0x0000FFFFFFFF);
729 assert ( !"invaild size of value -- aborting" );
735 /* now handle symbolic values */
736 switch (getSize (type))
739 fprintf (stderr, "BYTE: %s", val->name);
742 fprintf (stderr, "WORD: %s", val->name);
745 fprintf (stderr, "LONG: %s", val->name);
748 assert ( !"invalid size of (symbolic) value -- aborting" );
752 /*-----------------------------------------------------------------*/
753 /* printIval - generates code for initial value */
754 /*-----------------------------------------------------------------*/
756 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
761 /* if structure then */
762 if (IS_STRUCT (type))
764 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
765 printIvalStruct (sym, type, ilist, pb);
769 /* if this is an array */
772 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
773 printIvalArray (sym, type, ilist, pb);
777 /* if this is a pointer */
780 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
781 printIvalPtr (sym, type, ilist, pb);
785 /* if type is SPECIFIER */
788 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
789 printIvalType (sym, type, ilist, pb);
796 /*-----------------------------------------------------------------*/
797 /* emitStaticSeg - emitcode for the static segment */
798 /*-----------------------------------------------------------------*/
800 pic14emitStaticSeg (memmap * map)
804 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
806 //fprintf(stderr, "%s\n",__FUNCTION__);
808 /* for all variables in this segment do */
809 for (sym = setFirstItem (map->syms); sym;
810 sym = setNextItem (map->syms))
812 /* if extern then add it into the extern list */
813 if (IS_EXTERN (sym->etype)) {
814 addSetHead (&externs, sym);
818 /* if it is not static add it to the public
820 if (!IS_STATIC (sym->etype))
821 addSetHead (&publics, sym);
823 /* print extra debug info if required */
824 if (options.debug || sym->level == 0)
828 if (IS_STATIC (sym->etype))
829 dbuf_printf (&code->oBuf, "F%s_", moduleName); /* scope is file */
831 dbuf_printf (&code->oBuf, "G_"); /* scope is global */
834 /* symbol is local */
835 dbuf_printf (&code->oBuf, "L%s_",
836 (sym->localof ? sym->localof->name : "-null-"));
837 dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
841 /* if it has an absolute address */
842 if (SPEC_ABSA (sym->etype))
844 if (options.debug || sym->level == 0)
845 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
847 dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
849 SPEC_ADDR (sym->etype));
853 if (options.debug || sym->level == 0)
854 dbuf_printf (&code->oBuf, " == .\n");
856 /* if it has an initial value */
862 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
864 resolveIvalSym (sym->ival, sym->type);
865 //printIval (sym, sym->type, sym->ival, &code->oBuf);
866 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
868 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
870 printIval (sym, sym->type, sym->ival, pb);
878 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
879 /* special case for character strings */
880 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
881 SPEC_CVAL (sym->etype).v_char)
882 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
883 /*printChar (code->oFile,
884 SPEC_CVAL (sym->etype).v_char,
885 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
887 dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
897 /*-----------------------------------------------------------------*/
898 /* emitMaps - emits the code for the data portion the code */
899 /*-----------------------------------------------------------------*/
903 pic14_constructAbsMap (&sfr->oBuf);
904 emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
905 /* no special considerations for the following
906 data, idata & bit & xdata */
907 pic14emitRegularMap (data, TRUE, TRUE);
908 pic14emitRegularMap (idata, TRUE, TRUE);
909 pic14emitRegularMap (bit, TRUE, FALSE);
910 pic14emitRegularMap (xdata, TRUE, TRUE);
911 pic14emitRegularMap (sfr, TRUE, FALSE);
912 pic14emitRegularMap (sfrbit, FALSE, FALSE);
913 pic14emitRegularMap (code, TRUE, FALSE);
914 pic14emitStaticSeg (statsg);
915 pic14emitStaticSeg (c_abs);
919 /*-----------------------------------------------------------------*/
920 /* createInterruptVect - creates the interrupt vector */
921 /*-----------------------------------------------------------------*/
923 pic14createInterruptVect (struct dbuf_s * vBuf)
925 mainf = newSymbol ("main", 0);
928 /* only if the main function exists */
929 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
931 struct options *op = &options;
932 if (!(op->cc_only || noAssemble))
933 // werror (E_NO_MAIN);
934 fprintf(stderr,"WARNING: function 'main' undefined\n");
938 /* if the main is only a prototype ie. no body then do nothing */
939 if (!IFFUNC_HASBODY(mainf->type))
941 /* if ! compile only then main function should be present */
942 if (!(options.cc_only || noAssemble))
943 // werror (E_NO_MAIN);
944 fprintf(stderr,"WARNING: function 'main' undefined\n");
948 dbuf_printf (vBuf, "%s", iComments2);
949 dbuf_printf (vBuf, "; reset vector \n");
950 dbuf_printf (vBuf, "%s", iComments2);
951 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
952 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
953 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
954 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
955 popGetExternal("__sdcc_gsinit_startup", 0);
959 /*-----------------------------------------------------------------*/
960 /* initialComments - puts in some initial comments */
961 /*-----------------------------------------------------------------*/
963 pic14initialComments (FILE * afile)
965 initialComments (afile);
966 fprintf (afile, "; PIC port for the 14-bit core\n");
967 fprintf (afile, iComments2);
972 pic14_stringInSet(const char *str, set **world, int autoAdd)
979 for (s = setFirstItem(*world); s; s = setNextItem(*world))
982 if (0 == strcmp(s, str)) return 1;
986 if (autoAdd) addSet(world, Safe_strdup(str));
992 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
994 if (!pic14_stringInSet(sym, &emitted, 1)) {
995 /* sym was not in emittedSymbols */
996 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
997 /* sym is not a locally defined function---avoid bug #1443651 */
998 fprintf( file, fmt, sym );
1007 /*-------------------------------------------------------------------*/
1008 /* emitSymbol - write a symbol definition only if it is not */
1009 /* already present */
1010 /*-------------------------------------------------------------------*/
1012 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1014 static unsigned int sec_idx = 0;
1016 /* workaround: variables declared via `sbit' result in a numeric
1017 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1018 * sbit is heavily used in the inc2h-generated header files!
1020 if (!is_valid_identifier(name))
1022 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1026 /* check whether the symbol is already defined */
1027 if (pic14_stringInSet(name, &emitted, 1)) return;
1029 /* new symbol -- define it */
1030 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1032 dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1034 /* we place each symbol into a section of its own to allow the linker
1035 * to distribute the data into all available memory banks */
1036 if (!section_type) section_type = "udata";
1039 /* absolute symbols are handled in pic14_constructAbsMap */
1042 if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1043 dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1044 sec_idx++, section_type);
1045 dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1053 /*-----------------------------------------------------------------*/
1054 /* printExterns - generates extern for external variables */
1055 /*-----------------------------------------------------------------*/
1057 pic14printExterns (FILE * afile)
1061 fprintf (afile, "%s", iComments2);
1062 fprintf (afile, "; extern variables in this module\n");
1063 fprintf (afile, "%s", iComments2);
1065 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1066 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1069 /*-----------------------------------------------------------------*/
1070 /* printPublics - generates .global for publics */
1071 /*-----------------------------------------------------------------*/
1073 pic14printPublics (FILE * afile)
1077 fprintf (afile, "%s", iComments2);
1078 fprintf (afile, "; public variables in this module\n");
1079 fprintf (afile, "%s", iComments2);
1081 for (sym = setFirstItem (publics); sym;
1082 sym = setNextItem (publics)) {
1084 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1085 if (!IS_BITVAR(sym->type))
1086 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1088 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1089 /* Not any longer! */
1090 //if (!SPEC_ABSA (sym->etype))
1091 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1098 pic14printLocals (struct dbuf_s *oBuf)
1100 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1101 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1103 int i, is_first = 1;
1104 static unsigned sectionNr = 0;
1106 /* emit all registers from all possible sets */
1107 for (i = 0; i < 6; i++) {
1108 if (allregs[i] == NULL) continue;
1110 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1111 if (reg->isEmitted) continue;
1113 if (reg->wasUsed && !reg->isExtern) {
1114 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1116 // Should not happen, really...
1117 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1118 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1119 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1121 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1122 // assign each local register into its own section
1123 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1124 moduleName, sectionNr++, reg->name, reg->size);
1126 // group all local registers into a single section
1127 // This should greatly improve BANKSEL generation...
1129 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1132 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1142 /*-----------------------------------------------------------------*/
1143 /* emitOverlay - will emit code for the overlay stuff */
1144 /*-----------------------------------------------------------------*/
1146 pic14emitOverlay (struct dbuf_s * aBuf)
1150 /* if (!elementsInSet (ovrSetSets))*/
1152 /* the hack below, fixes translates for devices which
1153 * only have udata_shr memory */
1154 dbuf_printf (aBuf, "%s\t%s\n",
1155 (elementsInSet(ovrSetSets)?"":";"),
1156 port->mem.overlay_name);
1158 /* for each of the sets in the overlay segment do */
1159 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1160 ovrset = setNextItem (ovrSetSets))
1165 if (elementsInSet (ovrset))
1167 /* this dummy area is used to fool the assembler
1168 otherwise the assembler will append each of these
1169 declarations into one chunk and will not overlay
1172 /* I don't think this applies to us. We are using gpasm. CRF */
1174 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1175 /* output the area informtion */
1176 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1179 for (sym = setFirstItem (ovrset); sym;
1180 sym = setNextItem (ovrset))
1183 /* if extern then do nothing */
1184 if (IS_EXTERN (sym->etype))
1187 /* if allocation required check is needed
1188 then check if the symbol really requires
1189 allocation only for local variables */
1190 if (!IS_AGGREGATE (sym->type) &&
1191 !(sym->_isparm && !IS_REGPARM (sym->etype))
1192 && !sym->allocreq && sym->level)
1195 /* if global variable & not static or extern
1196 and addPublics allowed then add it to the public set */
1197 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1198 && !IS_STATIC (sym->etype))
1199 addSetHead (&publics, sym);
1201 /* if extern then do nothing or is a function
1203 if (IS_FUNC (sym->type))
1206 /* print extra debug info if required */
1207 if (options.debug || sym->level == 0)
1211 if (IS_STATIC (sym->etype))
1212 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1214 dbuf_printf (aBuf, "G_"); /* scope is global */
1217 /* symbol is local */
1218 dbuf_printf (aBuf, "L%s_",
1219 (sym->localof ? sym->localof->name : "-null-"));
1220 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1223 /* if is has an absolute address then generate
1224 an equate for this no need to allocate space */
1225 if (SPEC_ABSA (sym->etype))
1228 if (options.debug || sym->level == 0)
1229 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1231 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1233 SPEC_ADDR (sym->etype));
1237 if (options.debug || sym->level == 0)
1238 dbuf_printf (aBuf, "==.\n");
1240 /* allocate space */
1241 dbuf_printf (aBuf, "%s:\n", sym->rname);
1242 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1251 pic14_emitInterruptHandler (FILE * asmFile)
1253 if (pic14_hasInterrupt)
1256 fprintf (asmFile, "%s", iComments2);
1257 fprintf (asmFile, "; interrupt and initialization code\n");
1258 fprintf (asmFile, "%s", iComments2);
1259 // Note - for mplink may have to enlarge section vectors in .lnk file
1260 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1261 // source files's code segment (interrupt.c -> code_interrupt)
1262 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1264 /* interrupt service routine */
1265 fprintf (asmFile, "__sdcc_interrupt\n");
1266 copypCode(asmFile, 'I');
1270 /*-----------------------------------------------------------------*/
1271 /* glue - the final glue that hold the whole thing together */
1272 /*-----------------------------------------------------------------*/
1277 struct dbuf_s ovrBuf;
1280 dbuf_init(&ovrBuf, 4096);
1281 dbuf_init(&vBuf, 4096);
1283 pCodeInitRegisters();
1285 /* check for main() */
1286 mainf = newSymbol ("main", 0);
1288 mainf = findSymWithLevel (SymbolTab, mainf);
1290 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1292 /* main missing -- import stack from main module */
1293 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1294 pic14_options.isLibrarySource = 1;
1298 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1300 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1303 /* entry point @ start of CSEG */
1304 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1305 /* put in the call to main */
1306 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1308 if (options.mainreturn) {
1310 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1311 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1315 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1316 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1322 /* At this point we've got all the code in the form of pCode structures */
1323 /* Now it needs to be rearranged into the order it should be placed in the */
1326 movepBlock2Head('P'); // Last
1327 movepBlock2Head(code->dbName);
1328 movepBlock2Head('X');
1329 movepBlock2Head(statsg->dbName); // First
1332 /* print the global struct definitions */
1336 /* emit code for the all the variables declared */
1338 /* do the overlay segments */
1339 pic14emitOverlay(&ovrBuf);
1341 /* PENDING: this isnt the best place but it will do */
1342 if (port->general.glue_up_main) {
1343 /* create the interrupt vector table */
1344 pic14createInterruptVect (&vBuf);
1349 ReuseReg(); // ReuseReg where call tree permits
1355 if (options.debug) pcode_test();
1358 /* now put it all together into the assembler file */
1359 /* create the assembler file name */
1361 if ((noAssemble || options.c1mode) && fullDstFileName)
1363 sprintf (buffer, fullDstFileName);
1367 sprintf (buffer, dstFileName);
1368 strcat (buffer, ".asm");
1371 if (!(asmFile = fopen (buffer, "w"))) {
1372 werror (E_FILE_OPEN_ERR, buffer);
1376 /* prepare statistics */
1377 resetpCodeStatistics ();
1379 /* initial comments */
1380 pic14initialComments (asmFile);
1382 /* print module name */
1383 fprintf (asmFile, "%s\t.file\t\"%s\"\n",
1384 options.debug ? "" : ";", fullSrcFileName);
1386 /* Let the port generate any global directives, etc. */
1387 if (port->genAssemblerPreamble)
1389 port->genAssemblerPreamble(asmFile);
1392 /* print the global variables in this module */
1393 //pic14printPublics (asmFile);
1395 /* print the extern variables in this module */
1396 //pic14printExterns (asmFile);
1398 /* copy the sfr segment */
1400 fprintf (asmFile, "%s", iComments2);
1401 fprintf (asmFile, "; special function registers\n");
1402 fprintf (asmFile, "%s", iComments2);
1403 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1406 if (udata_section_name) {
1407 sprintf(udata_name,"%s",udata_section_name);
1409 sprintf(udata_name,"data_%s",moduleName);
1411 fprintf (asmFile, "%s", iComments2);
1412 fprintf (asmFile, "; udata\n");
1413 fprintf (asmFile, "%s", iComments2);
1414 fprintf (asmFile, "%s\tudata\n", udata_name);
1415 dbuf_write_and_destroy(&data->oBuf, asmFile);
1418 /* Put all variables into a cblock */
1421 /* emit initialized data */
1422 showAllMemmaps(asmFile);
1424 /* print the locally defined variables in this module */
1425 writeUsedRegs(asmFile);
1427 /* create the overlay segments */
1428 fprintf (asmFile, "%s", iComments2);
1429 fprintf (asmFile, "; overlayable items in internal ram \n");
1430 fprintf (asmFile, "%s", iComments2);
1431 dbuf_write_and_destroy (&ovrBuf, asmFile);
1435 /* create the stack segment MOF */
1436 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1437 fprintf (asmFile, "%s", iComments2);
1438 fprintf (asmFile, "; Stack segment in internal ram \n");
1439 fprintf (asmFile, "%s", iComments2);
1440 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1441 ";__start__stack:\n;\t.ds\t1\n\n");
1444 /* create the idata segment */
1445 fprintf (asmFile, "%s", iComments2);
1446 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1447 fprintf (asmFile, "%s", iComments2);
1448 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1450 /* if external stack then reserve space of it */
1451 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1452 fprintf (asmFile, "%s", iComments2);
1453 fprintf (asmFile, "; external stack \n");
1454 fprintf (asmFile, "%s", iComments2);
1455 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1456 fprintf (asmFile,";\t.ds 256\n");
1459 /* copy xtern ram data */
1460 fprintf (asmFile, "%s", iComments2);
1461 fprintf (asmFile, "; external ram data\n");
1462 fprintf (asmFile, "%s", iComments2);
1463 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1467 /* copy the bit segment */
1469 fprintf (asmFile, "%s", iComments2);
1470 fprintf (asmFile, "; bit data\n");
1471 fprintf (asmFile, "%s", iComments2);
1472 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1475 /* copy the interrupt vector table */
1476 if (mainf && IFFUNC_HASBODY(mainf->type))
1477 dbuf_write_and_destroy (&vBuf, asmFile);
1479 dbuf_destroy(&vBuf);
1481 /* create interupt ventor handler */
1482 pic14_emitInterruptHandler (asmFile);
1484 /* copy over code */
1485 fprintf (asmFile, "%s", iComments2);
1486 fprintf (asmFile, "; code\n");
1487 fprintf (asmFile, "%s", iComments2);
1488 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1491 copypCode(asmFile, 'X');
1493 /* _main function */
1494 copypCode(asmFile, 'M');
1496 /* other functions */
1497 copypCode(asmFile, code->dbName);
1500 copypCode(asmFile, 'P');
1502 dumppCodeStatistics (asmFile);
1504 fprintf (asmFile,"\tend\n");
1507 pic14_debugLogClose();
1511 * Deal with initializers.
1516 #define DEBUGprintf printf
1519 #define DEBUGprintf 1 ? (void)0 : (void)printf
1528 showInitList(initList *list, int level)
1530 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1531 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1534 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1535 if (list->type == INIT_DEEP) {
1536 showInitList(list->init.deep, level + 1);
1537 } else if (list->type == INIT_NODE) {
1538 ast = list->init.node;
1539 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1540 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1541 if (ast->type == EX_VALUE) {
1542 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1543 } else if (ast->type == EX_LINK) {
1544 printTypeChain(ast->opval.lnk, NULL);
1545 } else if (ast->type == EX_OP) {
1546 printf (" OP %u\n", ast->opval.op);
1556 * DEBUG: Print a value.
1559 printValue(value *val)
1561 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1562 val, val->name, val->type, val->etype,
1563 val->sym ? val->sym->name : NULL, val->vArgs,
1564 (long) ulFromVal (val), (long) ulFromVal (val));
1565 printTypeChain(val->type, stdout);
1567 printTypeChain(val->etype, stdout);
1573 parseIvalAst (ast *node, int *inCodeSpace) {
1575 char *buffer = NULL;
1578 if (IS_AST_VALUE(node)) {
1579 value *val = AST_VALUE(node);
1580 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1581 if (inCodeSpace && val->type
1582 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1586 if (inCodeSpace && sym
1587 && (IS_FUNC(sym->type)
1588 || IS_CODE(getSpec(sym->type))))
1593 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1594 if (IS_AST_LIT_VALUE(node)) {
1595 buffer = Safe_alloc(LEN);
1596 SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
1597 } else if (IS_AST_SYM_VALUE(node)) {
1598 assert ( AST_SYMBOL(node) );
1600 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1601 printTypeChain(AST_SYMBOL(node)->type, stdout);
1602 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1603 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1605 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1607 assert ( !"Invalid values type for initializers in AST." );
1609 } else if (IS_AST_OP(node)) {
1610 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1611 switch (node->opval.op) {
1613 assert (node->right);
1614 buffer = parseIvalAst(node->right, inCodeSpace);
1615 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1618 assert ( node->left && !node->right );
1619 buffer = parseIvalAst(node->left, inCodeSpace);
1620 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1623 assert (node->left && node->right );
1624 left = parseIvalAst(node->left, inCodeSpace);
1625 right = parseIvalAst(node->right, inCodeSpace);
1626 buffer = Safe_alloc(LEN);
1627 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1628 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1633 assert ( node->left && node->right );
1634 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1635 right = parseIvalAst(node->right, inCodeSpace);
1636 buffer = Safe_alloc(LEN);
1637 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1638 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1640 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1643 assert ( !"Unhandled operation in initializer." );
1647 assert ( !"Invalid construct in initializer." );
1654 * Emit the section preamble, absolute location (if any) and
1655 * symbol name(s) for intialized data.
1658 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1661 static int in_code = 0;
1662 static int sectionNr = 0;
1665 // code or data space?
1666 if (IS_CODE(getSpec(sym->type))) {
1673 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1674 if (SPEC_ABSA(getSpec(sym->type))) {
1675 // specify address for absolute symbols
1676 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1678 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1680 addSet(&emitted, sym->rname);
1686 * Actually emit the initial values in .asm format.
1689 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1695 int inCodeSpace = 0;
1699 assert (size <= sizeof(long));
1700 assert (!list || (list->type == INIT_NODE));
1701 node = list ? list->init.node : NULL;
1703 in_code = emitIvalLabel(oBuf, sym);
1704 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1707 // initialize as zero
1708 for (i=0; i < size; i++) {
1710 dbuf_printf (oBuf, "\tretlw 0x00");
1712 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1715 dbuf_printf (oBuf, "\n");
1720 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1721 op = operandFromValue(val);
1722 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1724 } else if (IS_AST_VALUE(node)) {
1725 op = operandFromAst(node, 0);
1726 } else if (IS_AST_OP(node)) {
1727 str = parseIvalAst(node, &inCodeSpace);
1728 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1731 assert ( !"Unhandled construct in intializer." );
1737 //printOperand(op, of);
1740 for (i=0; i < size; i++) {
1744 * FIXME: This is hacky and needs some more thought.
1746 if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
1747 /* This branch is introduced to fix #1427663. */
1748 PCOI(AOP(op)->aopu.pcop)->offset+=i;
1749 text = get_op(AOP(op)->aopu.pcop, NULL, 0);
1750 PCOI(AOP(op)->aopu.pcop)->offset-=i;
1752 text = op ? aopGet(AOP(op), i, 0, 0)
1753 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1756 dbuf_printf (oBuf, "\tretlw %s\n", text);
1758 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1761 dbuf_printf (oBuf, "\n");
1765 * For UNIONs, we first have to find the correct alternative to map the
1766 * initializer to. This function maps the structure of the initializer to
1767 * the UNION members recursively.
1768 * Returns the type of the first `fitting' member.
1771 matchIvalToUnion (initList *list, sym_link *type, int size)
1777 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1780 if (!list || (list->type == INIT_NODE)) {
1781 DEBUGprintf ("OK, simple type\n");
1784 DEBUGprintf ("ERROR, simple type\n");
1787 } else if (IS_BITFIELD(type)) {
1788 if (!list || (list->type == INIT_NODE)) {
1789 DEBUGprintf ("OK, bitfield\n");
1792 DEBUGprintf ("ERROR, bitfield\n");
1795 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1796 if (!list || (list->type == INIT_DEEP)) {
1797 if (list) list = list->init.deep;
1798 sym = SPEC_STRUCT(type)->fields;
1800 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1801 if (!matchIvalToUnion(list, sym->type, 0)) {
1802 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1805 if (list) list = list->next;
1809 // excess initializers?
1811 DEBUGprintf ("ERROR, excess initializers\n");
1815 DEBUGprintf ("OK, struct\n");
1819 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1820 if (!list || (list->type == INIT_DEEP)) {
1821 if (list) list = list->init.deep;
1822 sym = SPEC_STRUCT(type)->fields;
1824 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1825 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1826 && matchIvalToUnion(list, sym->type, size))
1828 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1835 DEBUGprintf ("ERROR, no match found.\n");
1838 assert ( !"Unhandled type in UNION." );
1841 assert ( !"No match found in UNION for the given initializer structure." );
1846 * Parse the type and its initializer and emit it (recursively).
1849 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1856 size = getSize(my_type);
1858 if (IS_PTR(my_type)) {
1859 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1860 emitIvals(oBuf, topsym, list, 0, size);
1864 if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
1865 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1866 emitIvalLabel(oBuf, topsym);
1868 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1873 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1874 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1875 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1879 if (IS_ARRAY(my_type)) {
1880 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1881 assert (!list || list->type == INIT_DEEP);
1882 if (list) list = list->init.deep;
1883 for (i = 0; i < DCL_ELEM(my_type); i++) {
1884 emitInitVal(oBuf, topsym, my_type->next, list);
1886 if (list) list = list->next;
1891 if (IS_FLOAT(my_type)) {
1893 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1894 emitIvals(oBuf, topsym, list, 0, size);
1898 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1899 // integral type, 8, 16, or 32 bit
1900 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1901 emitIvals(oBuf, topsym, list, 0, size);
1904 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1906 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1907 assert (!list || (list->type == INIT_DEEP));
1909 // iterate over struct members and initList
1910 if (list) list = list->init.deep;
1911 sym = SPEC_STRUCT(my_type)->fields;
1915 if (IS_BITFIELD(sym->type)) {
1916 while (sym && IS_BITFIELD(sym->type)) {
1917 assert (!list || ((list->type == INIT_NODE)
1918 && IS_AST_LIT_VALUE(list->init.node)));
1919 lit = (long) (list ? list2int(list) : 0);
1920 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1921 lit, SPEC_BLEN(getSpec(sym->type)),
1922 SPEC_BSTR(getSpec(sym->type)), bitfield);
1923 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1924 len += SPEC_BLEN(getSpec(sym->type));
1927 if (list) list = list->next;
1929 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
1930 len = (len + 7) & ~0x07; // round up to full bytes
1931 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
1936 emitInitVal(oBuf, topsym, sym->type, list);
1939 if (list) list = list->next;
1943 assert ( !"Excess initializers." );
1947 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
1949 DEBUGprintf ("(union, %d byte) handled below\n", size);
1950 assert (list && list->type == INIT_DEEP);
1952 // iterate over union members and initList, try to map number and type of fields and initializers
1953 my_type = matchIvalToUnion(list, my_type, size);
1955 emitInitVal(oBuf, topsym, my_type, list->init.deep);
1957 size -= getSize(my_type);
1959 // pad with (leading) zeros
1960 emitIvals(oBuf, NULL, NULL, 0, size);
1965 assert ( !"No UNION member matches the initializer structure.");
1966 } else if (IS_BITFIELD(my_type)) {
1967 assert ( !"bitfields should only occur in structs..." );
1970 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
1971 assert( !"Unhandled initialized type.");
1976 * Emit a set of symbols.
1977 * type - 0: have symbol tell whether it is local, extern or global
1978 * 1: assume all symbols in set to be global
1979 * 2: assume all symbols in set to be extern
1982 emitSymbolSet(set *s, int type)
1986 unsigned sectionNr = 0;
1988 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
1990 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
1991 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
1994 if (sym->etype && SPEC_ABSA(sym->etype)
1995 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
1998 // handle config words
1999 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2000 (int)list2int(sym->ival));
2001 pic14_stringInSet(sym->rname, &emitted, 1);
2005 if (sym->isstrlit) {
2006 // special case: string literals
2007 emitInitVal(ivalBuf, sym, sym->type, NULL);
2011 if (type != 0 || sym->cdef
2012 || (!IS_STATIC(sym->etype)
2015 // bail out for ___fsadd and friends
2016 if (sym->cdef && !sym->used) continue;
2018 /* export or import non-static globals */
2019 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2021 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2023 /* do not add to emitted set, it might occur again! */
2024 //if (!sym->used) continue;
2026 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2029 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2030 if (!sym->ival && !IS_FUNC(sym->type)) {
2031 // also define symbol
2032 if (IS_ABSOLUTE(sym->etype)) {
2033 // absolute location?
2034 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2035 // deferred to pic14_constructAbsMap
2037 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2038 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2042 pic14_stringInSet(sym->rname, &emitted, 1);
2046 //if (list) showInitList(list, 0);
2048 resolveIvalSym( list, sym->type );
2049 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2050 dbuf_printf (ivalBuf, "\n");
2056 * Iterate over all memmaps and emit their contents (attributes, symbols).
2059 showAllMemmaps(FILE *of)
2061 struct dbuf_s locBuf;
2063 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2064 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2065 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2069 DEBUGprintf ("---begin memmaps---\n");
2070 if (!extBuf) extBuf = dbuf_new(1024);
2071 if (!gloBuf) gloBuf = dbuf_new(1024);
2072 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2073 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2074 dbuf_init(&locBuf, 1024);
2076 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2077 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2078 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2079 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2080 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2082 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2084 //DEBUGprintf ("memmap %i: %p\n", i, map);
2087 fprintf (stdout, "; pageno %c, sname %s, dbName %c, ptrType %d, slbl %d, sloc %u, fmap %u, paged %u, direct %u, bitsp %u, codesp %u, regsp %u, syms %p\n",
2088 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2089 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2090 map->codesp, map->regsp, map->syms);
2092 emitSymbolSet(map->syms, 0);
2095 DEBUGprintf ("---end of memmaps---\n");
2097 emitSymbolSet(publics, 1);
2098 emitSymbolSet(externs, 2);
2100 emitPseudoStack(gloBuf, extBuf);
2101 pic14_constructAbsMap(gloDefBuf, gloBuf);
2102 pic14printLocals (&locBuf);
2103 pic14_emitConfigWord(of); // must be done after all the rest
2105 dbuf_write_and_destroy(extBuf, of);
2106 dbuf_write_and_destroy(gloBuf, of);
2107 dbuf_write_and_destroy(gloDefBuf, of);
2108 dbuf_write_and_destroy(&locBuf, of);
2109 dbuf_write_and_destroy(ivalBuf, of);
2111 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;