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"
33 #include "dbuf_string.h"
36 #ifdef WORDS_BIGENDIAN
37 #define _ENDIAN(x) (3-x)
39 #define _ENDIAN(x) (x)
42 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 #define IS_GLOBAL(sym) ((sym)->level == 0)
45 extern symbol *interrupts[256];
46 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
50 extern unsigned maxInterrupts;
51 extern int maxRegBank;
53 extern char *VersionString;
54 extern struct dbuf_s *codeOutBuf;
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 ReuseReg(void);
65 extern void InlinepCode(void);
66 extern void writeUsedRegs(FILE *);
68 extern void initialComments (FILE * afile);
69 extern void printPublics (FILE * afile);
71 extern void printChar (FILE * ofile, char *s, int plen);
72 void pCodeInitRegisters(void);
73 int getConfigWord(int address);
74 int getHasSecondConfigReg(void);
75 void pic14_debugLogClose(void); // from ralloc.c
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 /* dbufs for initialized data (idata and code sections),
81 * extern, and global declarations */
82 struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
84 static set *emitted = NULL;
85 int pic14_stringInSet(const char *str, set **world, int autoAdd);
87 /*-----------------------------------------------------------------*/
88 /* aopLiteral - string from a literal value */
89 /*-----------------------------------------------------------------*/
90 unsigned int pic14aopLiteral (value *val, int offset)
97 /* if it is a float then it gets tricky */
98 /* otherwise it is fairly simple */
99 if (!IS_FLOAT(val->type)) {
100 unsigned long v = (unsigned long) floatFromVal(val);
102 return ( (v >> (offset * 8)) & 0xff);
105 /* it is type float */
106 fl.f = (float) floatFromVal(val);
107 #ifdef WORDS_BIGENDIAN
108 return fl.c[3-offset];
117 is_valid_identifier( const char *name )
123 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
124 if (!((a >= 'a' && a <= 'z')
125 || (a >= 'A' && a <= 'z')
130 while ((a = *name++))
132 if (!((a >= 'a' && a <= 'z')
133 || (a >= 'A' && a <= 'Z')
134 || (a >= '0' && a <= '9')
139 /* valid identifier */
145 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
147 int shared, low, high, size, i;
150 /* also emit STK symbols
151 * XXX: This is ugly and fails as soon as devices start to get
152 * differently sized sharebanks, since STK12 will be
153 * required by larger devices but only up to STK03 might
154 * be defined using smaller devices. */
155 shared = pic14_getSharedStack(&low, &high, &size);
156 if (!pic14_options.isLibrarySource)
158 pic = pic14_getPIC();
160 dbuf_printf (oBuf, "\n");
161 dbuf_printf (oBuf, "\tglobal PSAVE\n");
162 dbuf_printf (oBuf, "\tglobal SSAVE\n");
163 dbuf_printf (oBuf, "\tglobal WSAVE\n");
164 for (i = size - 4; i >= 0; i--) {
165 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
167 dbuf_printf (oBuf, "\n");
169 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
172 // for single banked devices: use normal, "banked" RAM
173 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
175 // for devices with at least two banks, require a sharebank section
176 dbuf_printf (oBuf, "sharebank udata_shr\n");
178 dbuf_printf (oBuf, "PSAVE\tres 1\n");
179 dbuf_printf (oBuf, "SSAVE\tres 1\n");
180 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
181 /* fill rest of sharebank with stack STKxx .. STK00 */
182 for (i = size - 4; i >= 0; i--) {
183 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
186 /* declare STKxx as extern for all files
187 * except the one containing main() */
188 dbuf_printf (oBufExt, "\n");
189 dbuf_printf (oBufExt, "\textern PSAVE\n");
190 dbuf_printf (oBufExt, "\textern SSAVE\n");
191 dbuf_printf (oBufExt, "\textern WSAVE\n");
192 for (i = size - 4; i >= 0; i--) {
194 SNPRINTF(&buffer[0], 127, "STK%02d", i);
195 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
196 pic14_stringInSet(&buffer[0], &emitted, 1);
199 dbuf_printf (oBuf, "\n");
203 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
206 int wasPresent = pic14_stringInSet(name, emitted, 1);
209 dbuf_printf (oBuf, fmt, name);
211 return (!wasPresent);
214 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
215 extern int IS_CONFIG_ADDRESS( int addr );
217 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
219 memmap *maps[] = { data, sfr, NULL };
224 int addr, min=-1, max=-1;
227 for (i=0; maps[i] != NULL; i++)
229 for (sym = (symbol *)setFirstItem (maps[i]->syms);
230 sym; sym = setNextItem (maps[i]->syms))
232 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
234 addr = SPEC_ADDR(sym->etype);
236 /* handle CONFIG words here */
237 if (IS_CONFIG_ADDRESS( addr ))
239 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
240 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
242 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
244 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
249 if (max == -1 || addr > max) max = addr;
250 if (min == -1 || addr < min) min = addr;
251 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
252 aliases = hTabItemWithKey (ht, addr);
254 /* May not use addSetHead, as we cannot update the
255 * list's head in the hastable `ht'. */
256 addSet (&aliases, sym);
258 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
259 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
262 addSet (&aliases, sym);
263 hTabAddItem (&ht, addr, aliases);
269 /* now emit definitions for all absolute symbols */
270 dbuf_printf (oBuf, "%s", iComments2);
271 dbuf_printf (oBuf, "; absolute symbol definitions\n");
272 dbuf_printf (oBuf, "%s", iComments2);
273 for (addr=min; addr <= max; addr++)
276 aliases = hTabItemWithKey (ht, addr);
277 if (aliases && elementsInSet(aliases)) {
278 /* Make sure there is no initialized value at this location! */
279 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
280 if (sym->ival) break;
284 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
285 moduleName, addr, addr);
286 for (sym = setFirstItem (aliases); sym;
287 sym = setNextItem (aliases))
289 if (getSize(sym->type) > size) {
290 size = getSize(sym->type);
293 /* initialized values are handled somewhere else */
294 if (sym->ival) continue;
296 /* emit STATUS as well as _STATUS, required for SFRs only */
297 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
298 dbuf_printf (oBuf, "%s\n", sym->rname);
300 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
301 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
302 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
305 dbuf_printf (oBuf, "\tres\t%d\n", size);
311 /*-----------------------------------------------------------------*/
312 /* emitRegularMap - emit code for maps with no special cases */
313 /*-----------------------------------------------------------------*/
315 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
320 /* print the area name */
322 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
324 for (sym = setFirstItem (map->syms); sym;
325 sym = setNextItem (map->syms)) {
327 //printf("%s\n",sym->name);
329 /* ignore if config word */
330 if (SPEC_ABSA(sym->etype)
331 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
334 /* if extern then add it into the extern list */
335 if (IS_EXTERN (sym->etype)) {
336 addSetHead (&externs, sym);
340 /* if allocation required check is needed
341 then check if the symbol really requires
342 allocation only for local variables */
343 if (arFlag && !IS_AGGREGATE (sym->type) &&
344 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
345 !sym->allocreq && sym->level)
348 /* if global variable & not static or extern
349 and addPublics allowed then add it to the public set */
350 if ((sym->level == 0 ||
351 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
353 !IS_STATIC (sym->etype))
355 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
356 addSetHead (&publics, sym);
359 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
362 /* if extern then do nothing or is a function
364 if (IS_FUNC (sym->type))
367 /* print extra debug info if required */
368 if (options.debug || sym->level == 0)
370 if (!sym->level) /* global */
371 if (IS_STATIC (sym->etype))
372 dbuf_printf (&map->oBuf, "F%s_", moduleName); /* scope is file */
374 dbuf_printf (&map->oBuf, "G_"); /* scope is global */
376 /* symbol is local */
377 dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
378 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
381 /* absolute symbols are handled in pic14_constructAbsMap */
382 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
385 /* if it has an absolute address then generate
386 an equate for this no need to allocate space */
387 if (0 && SPEC_ABSA (sym->etype))
389 //if (options.debug || sym->level == 0)
390 //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
392 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
394 SPEC_ADDR (sym->etype));
400 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
401 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
402 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
403 if (IS_BITVAR (sym->etype))
410 emitSymbol (&map->oBuf,
413 getSize (sym->type) & 0xffff,
414 SPEC_ABSA(sym->etype)
415 ? SPEC_ADDR(sym->etype)
424 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
426 for (i = 1; i < size; i++)
427 dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
432 //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
435 /* if it has a initial value then do it only if
436 it is a global variable */
438 /* mark symbol as already defined */
439 pic14_stringInSet(sym->name, &emitted, 1);
440 pic14_stringInSet(sym->rname, &emitted, 1);
443 /* if it has a initial value then do it only if
444 it is a global variable */
445 if (sym->ival && sym->level == 0) {
448 if (IS_AGGREGATE (sym->type))
449 ival = initAggregates (sym, sym->ival, NULL);
451 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
452 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
453 codeOutBuf = &statsg->oBuf;
455 eBBlockFromiCode (iCodeFromAst (ival));
465 /*-----------------------------------------------------------------*/
466 /* printIvalType - generates ival for int/char */
467 /*-----------------------------------------------------------------*/
469 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
474 //fprintf(stderr, "%s\n",__FUNCTION__);
476 /* if initList is deep */
477 if (ilist->type == INIT_DEEP)
478 ilist = ilist->init.deep;
480 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
481 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
484 if (!(val = list2val (ilist))) {
485 // assuming a warning has been thrown
489 if (val->type != type) {
490 val = valCastLiteral(type, floatFromVal(val));
494 ulval = (unsigned long) floatFromVal (val);
498 switch (getSize (type)) {
500 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
504 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
505 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
509 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
510 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
511 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
512 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
517 /*-----------------------------------------------------------------*/
518 /* printIvalBitFields - generate initializer for bitfields */
519 /*-----------------------------------------------------------------*/
520 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
524 initList *lilist = *ilist ;
525 unsigned long ival = 0;
531 val = list2val(lilist);
533 if (SPEC_BLEN(lsym->etype) > 8) {
534 size += ((SPEC_BLEN (lsym->etype) / 8) +
535 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
538 size = ((SPEC_BLEN (lsym->etype) / 8) +
539 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
541 i = (unsigned long)floatFromVal(val);
542 i <<= SPEC_BSTR (lsym->etype);
544 if (! ( lsym->next &&
545 (IS_BITFIELD(lsym->next->type)) &&
546 (SPEC_BSTR(lsym->next->etype)))) break;
548 lilist = lilist->next;
552 //tfprintf (oFile, "\t!db !constbyte\n",ival);
553 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
557 //tfprintf (oFile, "\t!dw !constword\n",ival);
558 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
559 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
562 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
563 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
564 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
565 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
566 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
573 /*-----------------------------------------------------------------*/
574 /* printIvalStruct - generates initial value for structures */
575 /*-----------------------------------------------------------------*/
576 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
579 initList *iloop = NULL;
581 sflds = SPEC_STRUCT (type)->fields;
584 if (ilist->type != INIT_DEEP) {
585 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
589 iloop = ilist->init.deep;
592 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
593 if (IS_BITFIELD(sflds->type)) {
594 printIvalBitFields(&sflds,&iloop,pb);
596 printIval (sym, sflds->type, iloop, pb);
600 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
605 /*-----------------------------------------------------------------*/
606 /* printIvalChar - generates initital value for character array */
607 /*-----------------------------------------------------------------*/
609 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
617 //fprintf(stderr, "%s\n",__FUNCTION__);
621 val = list2val (ilist);
623 /* if the value is a character string */
624 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
626 ilen = DCL_ELEM(val->type);
628 if (!DCL_ELEM (type))
629 DCL_ELEM (type) = ilen;
631 /* emit string constant */
632 for (remain = 0; remain < ilen; remain++) {
633 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
636 /* fill array up to desired size */
637 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
639 //tfprintf (oFile, "\t!db !constbyte\n", 0);
640 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
647 //printChar (oFile, s, strlen (s) + 1);
649 for(remain=0; remain<(int)strlen(s); remain++) {
650 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
651 //fprintf(stderr,"0x%02x ",s[remain]);
653 //fprintf(stderr,"\n");
658 /*-----------------------------------------------------------------*/
659 /* printIvalArray - generates code for array initialization */
660 /*-----------------------------------------------------------------*/
662 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
671 /* take care of the special case */
672 /* array of characters can be init */
674 if (IS_CHAR (type->next)) {
675 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
676 if (!IS_LITERAL(list2val(ilist)->etype)) {
677 werror (W_INIT_WRONG);
680 if (printIvalChar (type,
681 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
682 pb, SPEC_CVAL (sym->etype).v_char))
685 /* not the special case */
686 if (ilist->type != INIT_DEEP) {
687 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
691 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
692 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
693 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
696 printIval (sym, type->next, iloop, pb);
700 if (DCL_ELEM(type)) {
701 // pad with zeros if needed
702 if (size<DCL_ELEM(type)) {
703 size = (DCL_ELEM(type) - size) * getSize(type->next);
705 //tfprintf (oFile, "\t!db !constbyte\n", 0);
706 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
710 // we have not been given a size, but we now know it
711 DCL_ELEM (type) = size;
717 /*-----------------------------------------------------------------*/
718 /* printIvalPtr - generates code for initial value of pointers */
719 /*-----------------------------------------------------------------*/
720 extern value *initPointer (initList *, sym_link *toType);
723 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
730 fprintf (stderr, "FIXME: initializers for pointers...\n");
731 printTypeChain (type, stderr);
733 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
734 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
736 if (ilist && (ilist->type == INIT_DEEP))
737 ilist = ilist->init.deep;
739 /* function pointers */
740 if (IS_FUNC (type->next))
742 assert ( !"function pointers not yet handled" );
743 //printIvalFuncPtr (type, ilist, pb);
746 if (!(val = initPointer (ilist, type)))
749 if (IS_CHAR (type->next))
751 if (printIvalChar (type, ilist, pb, NULL)) return;
755 if (compareType (type, val->type) == 0)
757 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
758 printFromToType (val->type, type);
761 if (IS_LITERAL (val->etype))
763 switch (getSize (type))
766 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
769 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
771 case 3: /* gneric pointers */
772 assert ( !"generic pointers not yet handled" );
774 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
777 assert ( !"invaild size of value -- aborting" );
783 /* now handle symbolic values */
784 switch (getSize (type))
787 fprintf (stderr, "BYTE: %s", val->name);
790 fprintf (stderr, "WORD: %s", val->name);
793 fprintf (stderr, "LONG: %s", val->name);
796 assert ( !"invalid size of (symbolic) value -- aborting" );
800 /*-----------------------------------------------------------------*/
801 /* printIval - generates code for initial value */
802 /*-----------------------------------------------------------------*/
804 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
809 /* if structure then */
810 if (IS_STRUCT (type))
812 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
813 printIvalStruct (sym, type, ilist, pb);
817 /* if this is an array */
820 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
821 printIvalArray (sym, type, ilist, pb);
825 /* if this is a pointer */
828 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
829 printIvalPtr (sym, type, ilist, pb);
833 /* if type is SPECIFIER */
836 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
837 printIvalType (sym, type, ilist, pb);
844 extern void pCodeConstString(char *name, char *value);
845 /*-----------------------------------------------------------------*/
846 /* emitStaticSeg - emitcode for the static segment */
847 /*-----------------------------------------------------------------*/
849 pic14emitStaticSeg (memmap * map)
853 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
855 //fprintf(stderr, "%s\n",__FUNCTION__);
857 /* for all variables in this segment do */
858 for (sym = setFirstItem (map->syms); sym;
859 sym = setNextItem (map->syms))
861 /* if extern then add it into the extern list */
862 if (IS_EXTERN (sym->etype)) {
863 addSetHead (&externs, sym);
867 /* if it is not static add it to the public
869 if (!IS_STATIC (sym->etype))
870 addSetHead (&publics, sym);
872 /* print extra debug info if required */
873 if (options.debug || sym->level == 0)
877 if (IS_STATIC (sym->etype))
878 dbuf_printf (&code->oBuf, "F%s_", moduleName); /* scope is file */
880 dbuf_printf (&code->oBuf, "G_"); /* scope is global */
883 /* symbol is local */
884 dbuf_printf (&code->oBuf, "L%s_",
885 (sym->localof ? sym->localof->name : "-null-"));
886 dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
890 /* if it has an absolute address */
891 if (SPEC_ABSA (sym->etype))
893 if (options.debug || sym->level == 0)
894 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
896 dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
898 SPEC_ADDR (sym->etype));
902 if (options.debug || sym->level == 0)
903 dbuf_printf (&code->oBuf, " == .\n");
905 /* if it has an initial value */
911 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
913 resolveIvalSym (sym->ival, sym->type);
914 //printIval (sym, sym->type, sym->ival, &code->oBuf);
915 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
917 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
919 printIval (sym, sym->type, sym->ival, pb);
927 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
928 /* special case for character strings */
929 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
930 SPEC_CVAL (sym->etype).v_char)
931 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
932 /*printChar (code->oFile,
933 SPEC_CVAL (sym->etype).v_char,
934 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
936 dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
946 /*-----------------------------------------------------------------*/
947 /* emitMaps - emits the code for the data portion the code */
948 /*-----------------------------------------------------------------*/
952 pic14_constructAbsMap (&sfr->oBuf);
953 emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
954 /* no special considerations for the following
955 data, idata & bit & xdata */
956 pic14emitRegularMap (data, TRUE, TRUE);
957 pic14emitRegularMap (idata, TRUE, TRUE);
958 pic14emitRegularMap (bit, TRUE, FALSE);
959 pic14emitRegularMap (xdata, TRUE, TRUE);
960 pic14emitRegularMap (sfr, TRUE, FALSE);
961 pic14emitRegularMap (sfrbit, FALSE, FALSE);
962 pic14emitRegularMap (code, TRUE, FALSE);
963 pic14emitStaticSeg (statsg);
964 pic14emitStaticSeg (c_abs);
968 /*-----------------------------------------------------------------*/
969 /* createInterruptVect - creates the interrupt vector */
970 /*-----------------------------------------------------------------*/
971 pCodeOp *popGetExternal (char *str, int isReg);
973 pic14createInterruptVect (struct dbuf_s * vBuf)
975 mainf = newSymbol ("main", 0);
978 /* only if the main function exists */
979 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
981 struct options *op = &options;
982 if (!(op->cc_only || noAssemble))
983 // werror (E_NO_MAIN);
984 fprintf(stderr,"WARNING: function 'main' undefined\n");
988 /* if the main is only a prototype ie. no body then do nothing */
989 if (!IFFUNC_HASBODY(mainf->type))
991 /* if ! compile only then main function should be present */
992 if (!(options.cc_only || noAssemble))
993 // werror (E_NO_MAIN);
994 fprintf(stderr,"WARNING: function 'main' undefined\n");
998 dbuf_printf (vBuf, "%s", iComments2);
999 dbuf_printf (vBuf, "; reset vector \n");
1000 dbuf_printf (vBuf, "%s", iComments2);
1001 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1002 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
1003 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
1004 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
1005 popGetExternal("__sdcc_gsinit_startup", 0);
1009 /*-----------------------------------------------------------------*/
1010 /* initialComments - puts in some initial comments */
1011 /*-----------------------------------------------------------------*/
1013 pic14initialComments (FILE * afile)
1015 initialComments (afile);
1016 fprintf (afile, "; PIC port for the 14-bit core\n");
1017 fprintf (afile, iComments2);
1022 pic14_stringInSet(const char *str, set **world, int autoAdd)
1029 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1032 if (0 == strcmp(s, str)) return 1;
1036 if (autoAdd) addSet(world, Safe_strdup(str));
1042 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1044 if (!pic14_stringInSet(sym, &emitted, 1)) {
1045 /* sym was not in emittedSymbols */
1046 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1047 /* sym is not a locally defined function---avoid bug #1443651 */
1048 fprintf( file, fmt, sym );
1057 /*-------------------------------------------------------------------*/
1058 /* emitSymbol - write a symbol definition only if it is not */
1059 /* already present */
1060 /*-------------------------------------------------------------------*/
1062 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1064 static unsigned int sec_idx = 0;
1066 /* workaround: variables declared via `sbit' result in a numeric
1067 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1068 * sbit is heavily used in the inc2h-generated header files!
1070 if (!is_valid_identifier(name))
1072 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1076 /* check whether the symbol is already defined */
1077 if (pic14_stringInSet(name, &emitted, 1)) return;
1079 /* new symbol -- define it */
1080 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1082 dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1084 /* we place each symbol into a section of its own to allow the linker
1085 * to distribute the data into all available memory banks */
1086 if (!section_type) section_type = "udata";
1089 /* absolute symbols are handled in pic14_constructAbsMap */
1092 if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1093 dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1094 sec_idx++, section_type);
1095 dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1103 /*-----------------------------------------------------------------*/
1104 /* printExterns - generates extern for external variables */
1105 /*-----------------------------------------------------------------*/
1107 pic14printExterns (FILE * afile)
1111 fprintf (afile, "%s", iComments2);
1112 fprintf (afile, "; extern variables in this module\n");
1113 fprintf (afile, "%s", iComments2);
1115 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1116 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1119 /*-----------------------------------------------------------------*/
1120 /* printPublics - generates .global for publics */
1121 /*-----------------------------------------------------------------*/
1123 pic14printPublics (FILE * afile)
1127 fprintf (afile, "%s", iComments2);
1128 fprintf (afile, "; public variables in this module\n");
1129 fprintf (afile, "%s", iComments2);
1131 for (sym = setFirstItem (publics); sym;
1132 sym = setNextItem (publics)) {
1134 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1135 if (!IS_BITVAR(sym->type))
1136 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1138 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1139 /* Not any longer! */
1140 //if (!SPEC_ABSA (sym->etype))
1141 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1148 * Interface to BANKSEL generation.
1149 * This function should return != 0 iff str1 and str2 denote operands that
1150 * are known to be allocated into the same bank. Consequently, there will
1151 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
1152 * select the current bank just previously.
1154 * If in doubt, return 0.
1157 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
1158 // see pic14printLocals
1160 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1161 // no clustering applied, each register resides in its own bank
1163 // check whether BOTH names are local registers
1164 // XXX: This is some kind of shortcut, should be safe...
1165 // In this model, all r0xXXXX are allocated into a single section
1166 // per file, so no BANKSEL required if accessing a r0xXXXX after a
1167 // (different) r0xXXXX. Works great for multi-byte operands.
1168 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
1171 // assume operands in different banks
1176 pic14printLocals (struct dbuf_s *oBuf)
1178 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1179 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1181 int i, is_first = 1;
1182 static unsigned sectionNr = 0;
1184 /* emit all registers from all possible sets */
1185 for (i = 0; i < 6; i++) {
1186 if (allregs[i] == NULL) continue;
1188 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1189 if (reg->isEmitted) continue;
1191 if (reg->wasUsed && !reg->isExtern) {
1192 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1194 // Should not happen, really...
1195 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1196 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1197 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1199 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1200 // assign each local register into its own section
1201 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1202 moduleName, sectionNr++, reg->name, reg->size);
1204 // group all local registers into a single section
1205 // This should greatly improve BANKSEL generation...
1207 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1210 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1220 /*-----------------------------------------------------------------*/
1221 /* emitOverlay - will emit code for the overlay stuff */
1222 /*-----------------------------------------------------------------*/
1224 pic14emitOverlay (struct dbuf_s * aBuf)
1228 /* if (!elementsInSet (ovrSetSets))*/
1230 /* the hack below, fixes translates for devices which
1231 * only have udata_shr memory */
1232 dbuf_printf (aBuf, "%s\t%s\n",
1233 (elementsInSet(ovrSetSets)?"":";"),
1234 port->mem.overlay_name);
1236 /* for each of the sets in the overlay segment do */
1237 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1238 ovrset = setNextItem (ovrSetSets))
1243 if (elementsInSet (ovrset))
1245 /* this dummy area is used to fool the assembler
1246 otherwise the assembler will append each of these
1247 declarations into one chunk and will not overlay
1250 /* I don't think this applies to us. We are using gpasm. CRF */
1252 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1253 /* output the area informtion */
1254 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1257 for (sym = setFirstItem (ovrset); sym;
1258 sym = setNextItem (ovrset))
1261 /* if extern then do nothing */
1262 if (IS_EXTERN (sym->etype))
1265 /* if allocation required check is needed
1266 then check if the symbol really requires
1267 allocation only for local variables */
1268 if (!IS_AGGREGATE (sym->type) &&
1269 !(sym->_isparm && !IS_REGPARM (sym->etype))
1270 && !sym->allocreq && sym->level)
1273 /* if global variable & not static or extern
1274 and addPublics allowed then add it to the public set */
1275 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1276 && !IS_STATIC (sym->etype))
1277 addSetHead (&publics, sym);
1279 /* if extern then do nothing or is a function
1281 if (IS_FUNC (sym->type))
1284 /* print extra debug info if required */
1285 if (options.debug || sym->level == 0)
1289 if (IS_STATIC (sym->etype))
1290 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1292 dbuf_printf (aBuf, "G_"); /* scope is global */
1295 /* symbol is local */
1296 dbuf_printf (aBuf, "L%s_",
1297 (sym->localof ? sym->localof->name : "-null-"));
1298 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1301 /* if is has an absolute address then generate
1302 an equate for this no need to allocate space */
1303 if (SPEC_ABSA (sym->etype))
1306 if (options.debug || sym->level == 0)
1307 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1309 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1311 SPEC_ADDR (sym->etype));
1315 if (options.debug || sym->level == 0)
1316 dbuf_printf (aBuf, "==.\n");
1318 /* allocate space */
1319 dbuf_printf (aBuf, "%s:\n", sym->rname);
1320 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1329 pic14_emitInterruptHandler (FILE * asmFile)
1331 if (pic14_hasInterrupt)
1334 fprintf (asmFile, "%s", iComments2);
1335 fprintf (asmFile, "; interrupt and initialization code\n");
1336 fprintf (asmFile, "%s", iComments2);
1337 // Note - for mplink may have to enlarge section vectors in .lnk file
1338 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1339 // source files's code segment (interrupt.c -> code_interrupt)
1340 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1342 /* interrupt service routine */
1343 fprintf (asmFile, "__sdcc_interrupt\n");
1344 copypCode(asmFile, 'I');
1348 /*-----------------------------------------------------------------*/
1349 /* glue - the final glue that hold the whole thing together */
1350 /*-----------------------------------------------------------------*/
1355 struct dbuf_s ovrBuf;
1358 dbuf_init(&ovrBuf, 4096);
1359 dbuf_init(&vBuf, 4096);
1361 pCodeInitRegisters();
1363 /* check for main() */
1364 mainf = newSymbol ("main", 0);
1366 mainf = findSymWithLevel (SymbolTab, mainf);
1368 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1370 /* main missing -- import stack from main module */
1371 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1372 pic14_options.isLibrarySource = 1;
1376 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1378 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1381 /* entry point @ start of CSEG */
1382 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1383 /* put in the call to main */
1384 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1386 if (options.mainreturn) {
1388 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1389 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1393 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1394 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1400 /* At this point we've got all the code in the form of pCode structures */
1401 /* Now it needs to be rearranged into the order it should be placed in the */
1404 movepBlock2Head('P'); // Last
1405 movepBlock2Head(code->dbName);
1406 movepBlock2Head('X');
1407 movepBlock2Head(statsg->dbName); // First
1410 /* print the global struct definitions */
1414 /* emit code for the all the variables declared */
1416 /* do the overlay segments */
1417 pic14emitOverlay(&ovrBuf);
1419 /* PENDING: this isnt the best place but it will do */
1420 if (port->general.glue_up_main) {
1421 /* create the interrupt vector table */
1422 pic14createInterruptVect (&vBuf);
1427 ReuseReg(); // ReuseReg where call tree permits
1433 if (options.debug) pcode_test();
1436 /* now put it all together into the assembler file */
1437 /* create the assembler file name */
1439 if ((noAssemble || options.c1mode) && fullDstFileName)
1441 sprintf (buffer, fullDstFileName);
1445 sprintf (buffer, dstFileName);
1446 strcat (buffer, ".asm");
1449 if (!(asmFile = fopen (buffer, "w"))) {
1450 werror (E_FILE_OPEN_ERR, buffer);
1454 /* prepare statistics */
1455 resetpCodeStatistics ();
1457 /* initial comments */
1458 pic14initialComments (asmFile);
1460 /* print module name */
1461 fprintf (asmFile, ";\t.module %s\n", moduleName);
1463 /* Let the port generate any global directives, etc. */
1464 if (port->genAssemblerPreamble)
1466 port->genAssemblerPreamble(asmFile);
1469 /* print the global variables in this module */
1470 //pic14printPublics (asmFile);
1472 /* print the extern variables in this module */
1473 //pic14printExterns (asmFile);
1475 /* copy the sfr segment */
1477 fprintf (asmFile, "%s", iComments2);
1478 fprintf (asmFile, "; special function registers\n");
1479 fprintf (asmFile, "%s", iComments2);
1480 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1483 if (udata_section_name) {
1484 sprintf(udata_name,"%s",udata_section_name);
1486 sprintf(udata_name,"data_%s",moduleName);
1488 fprintf (asmFile, "%s", iComments2);
1489 fprintf (asmFile, "; udata\n");
1490 fprintf (asmFile, "%s", iComments2);
1491 fprintf (asmFile, "%s\tudata\n", udata_name);
1492 dbuf_write_and_destroy(&data->oBuf, asmFile);
1495 /* Put all variables into a cblock */
1498 /* emit initialized data */
1499 showAllMemmaps(asmFile);
1501 /* print the locally defined variables in this module */
1502 writeUsedRegs(asmFile);
1504 /* create the overlay segments */
1505 fprintf (asmFile, "%s", iComments2);
1506 fprintf (asmFile, "; overlayable items in internal ram \n");
1507 fprintf (asmFile, "%s", iComments2);
1508 dbuf_write_and_destroy (&ovrBuf, asmFile);
1512 /* create the stack segment MOF */
1513 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1514 fprintf (asmFile, "%s", iComments2);
1515 fprintf (asmFile, "; Stack segment in internal ram \n");
1516 fprintf (asmFile, "%s", iComments2);
1517 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1518 ";__start__stack:\n;\t.ds\t1\n\n");
1521 /* create the idata segment */
1522 fprintf (asmFile, "%s", iComments2);
1523 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1524 fprintf (asmFile, "%s", iComments2);
1525 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1527 /* if external stack then reserve space of it */
1528 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1529 fprintf (asmFile, "%s", iComments2);
1530 fprintf (asmFile, "; external stack \n");
1531 fprintf (asmFile, "%s", iComments2);
1532 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1533 fprintf (asmFile,";\t.ds 256\n");
1536 /* copy xtern ram data */
1537 fprintf (asmFile, "%s", iComments2);
1538 fprintf (asmFile, "; external ram data\n");
1539 fprintf (asmFile, "%s", iComments2);
1540 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1544 /* copy the bit segment */
1546 fprintf (asmFile, "%s", iComments2);
1547 fprintf (asmFile, "; bit data\n");
1548 fprintf (asmFile, "%s", iComments2);
1549 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1552 /* copy the interrupt vector table */
1553 if (mainf && IFFUNC_HASBODY(mainf->type))
1554 dbuf_write_and_destroy (&vBuf, asmFile);
1556 dbuf_destroy(&vBuf);
1558 /* create interupt ventor handler */
1559 pic14_emitInterruptHandler (asmFile);
1561 /* copy over code */
1562 fprintf (asmFile, "%s", iComments2);
1563 fprintf (asmFile, "; code\n");
1564 fprintf (asmFile, "%s", iComments2);
1565 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1568 copypCode(asmFile, 'X');
1570 /* _main function */
1571 copypCode(asmFile, 'M');
1573 /* other functions */
1574 copypCode(asmFile, code->dbName);
1577 copypCode(asmFile, 'P');
1579 dumppCodeStatistics (asmFile);
1581 fprintf (asmFile,"\tend\n");
1584 pic14_debugLogClose();
1588 * Deal with initializers.
1593 #define DEBUGprintf printf
1596 #define DEBUGprintf 1 ? (void)0 : (void)printf
1600 void ast_print (ast * tree, FILE *outfile, int indent);
1607 showInitList(initList *list, int level)
1609 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1610 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1613 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1614 if (list->type == INIT_DEEP) {
1615 showInitList(list->init.deep, level + 1);
1616 } else if (list->type == INIT_NODE) {
1617 ast = list->init.node;
1618 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1619 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1620 if (ast->type == EX_VALUE) {
1621 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1622 } else if (ast->type == EX_LINK) {
1623 printTypeChain(ast->opval.lnk, NULL);
1624 } else if (ast->type == EX_OP) {
1625 printf (" OP %u\n", ast->opval.op);
1634 * DEBUG: Print a value.
1637 printVal(value *val)
1639 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1640 val, val->name, val->type, val->etype,
1641 val->sym ? val->sym->name : NULL, val->vArgs,
1642 (long)floatFromVal(val), (long)floatFromVal(val));
1643 printTypeChain(val->type, stdout);
1645 printTypeChain(val->etype, stdout);
1649 //prototype from ../SDCCicode.c
1650 operand *operandFromAst (ast * tree,int lvl);
1653 parseIvalAst (ast *node, int *inCodeSpace) {
1655 char *buffer = NULL;
1658 if (IS_AST_VALUE(node)) {
1659 value *val = AST_VALUE(node);
1660 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1661 if (inCodeSpace && val->type
1662 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1666 if (inCodeSpace && sym
1667 && (IS_FUNC(sym->type)
1668 || IS_CODE(getSpec(sym->type))))
1673 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1674 if (IS_AST_LIT_VALUE(node)) {
1675 buffer = Safe_alloc(LEN);
1676 SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node));
1677 } else if (IS_AST_SYM_VALUE(node)) {
1678 assert ( AST_SYMBOL(node) );
1680 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1681 printTypeChain(AST_SYMBOL(node)->type, stdout);
1682 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1683 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1685 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1687 assert ( !"Invalid values type for initializers in AST." );
1689 } else if (IS_AST_OP(node)) {
1690 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1691 switch (node->opval.op) {
1693 assert (node->right);
1694 buffer = parseIvalAst(node->right, inCodeSpace);
1695 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1698 assert ( node->left && !node->right );
1699 buffer = parseIvalAst(node->left, inCodeSpace);
1700 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1703 assert (node->left && node->right );
1704 left = parseIvalAst(node->left, inCodeSpace);
1705 right = parseIvalAst(node->right, inCodeSpace);
1706 buffer = Safe_alloc(LEN);
1707 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1708 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1713 assert ( node->left && node->right );
1714 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1715 right = parseIvalAst(node->right, inCodeSpace);
1716 buffer = Safe_alloc(LEN);
1717 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1718 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1720 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1723 assert ( !"Unhandled operation in initializer." );
1727 assert ( !"Invalid construct in initializer." );
1734 * Emit the section preamble, absolute location (if any) and
1735 * symbol name(s) for intialized data.
1738 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1741 static int in_code = 0;
1742 static int sectionNr = 0;
1745 // code or data space?
1746 if (IS_CODE(getSpec(sym->type))) {
1753 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1754 if (SPEC_ABSA(getSpec(sym->type))) {
1755 // specify address for absolute symbols
1756 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1758 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1760 addSet(&emitted, sym->rname);
1765 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1767 * Actually emit the initial values in .asm format.
1770 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1776 int inCodeSpace = 0;
1780 assert (size <= sizeof(long));
1781 assert (!list || (list->type == INIT_NODE));
1782 node = list ? list->init.node : NULL;
1784 in_code = emitIvalLabel(oBuf, sym);
1785 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1788 // initialize as zero
1789 for (i=0; i < size; i++) {
1791 dbuf_printf (oBuf, "\tretlw 0x00");
1793 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1796 dbuf_printf (oBuf, "\n");
1801 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1802 op = operandFromValue(val);
1803 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1805 } else if (IS_AST_VALUE(node)) {
1806 op = operandFromAst(node, 0);
1807 } else if (IS_AST_OP(node)) {
1808 str = parseIvalAst(node, &inCodeSpace);
1809 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1812 assert ( !"Unhandled construct in intializer." );
1818 //printOperand(op, of);
1821 for (i=0; i < size; i++) {
1822 char *text = op ? aopGet(AOP(op), i, 0, 0)
1823 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1825 dbuf_printf (oBuf, "\tretlw %s\n", text);
1827 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1830 dbuf_printf (oBuf, "\n");
1834 * For UNIONs, we first have to find the correct alternative to map the
1835 * initializer to. This function maps the structure of the initializer to
1836 * the UNION members recursively.
1837 * Returns the type of the first `fitting' member.
1840 matchIvalToUnion (initList *list, sym_link *type, int size)
1846 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1849 if (!list || (list->type == INIT_NODE)) {
1850 DEBUGprintf ("OK, simple type\n");
1853 DEBUGprintf ("ERROR, simple type\n");
1856 } else if (IS_BITFIELD(type)) {
1857 if (!list || (list->type == INIT_NODE)) {
1858 DEBUGprintf ("OK, bitfield\n");
1861 DEBUGprintf ("ERROR, bitfield\n");
1864 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1865 if (!list || (list->type == INIT_DEEP)) {
1866 if (list) list = list->init.deep;
1867 sym = SPEC_STRUCT(type)->fields;
1869 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1870 if (!matchIvalToUnion(list, sym->type, 0)) {
1871 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1874 if (list) list = list->next;
1878 // excess initializers?
1880 DEBUGprintf ("ERROR, excess initializers\n");
1884 DEBUGprintf ("OK, struct\n");
1888 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1889 if (!list || (list->type == INIT_DEEP)) {
1890 if (list) list = list->init.deep;
1891 sym = SPEC_STRUCT(type)->fields;
1893 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1894 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1895 && matchIvalToUnion(list, sym->type, size))
1897 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1904 DEBUGprintf ("ERROR, no match found.\n");
1907 assert ( !"Unhandled type in UNION." );
1910 assert ( !"No match found in UNION for the given initializer structure." );
1915 * Parse the type and its initializer and emit it (recursively).
1918 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1925 size = getSize(my_type);
1927 if (IS_PTR(my_type)) {
1928 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1929 emitIvals(oBuf, topsym, list, 0, size);
1933 if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
1934 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1935 emitIvalLabel(oBuf, topsym);
1937 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1942 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1943 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1944 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1948 if (IS_ARRAY(my_type)) {
1949 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1950 assert (!list || list->type == INIT_DEEP);
1951 if (list) list = list->init.deep;
1952 for (i = 0; i < DCL_ELEM(my_type); i++) {
1953 emitInitVal(oBuf, topsym, my_type->next, list);
1955 if (list) list = list->next;
1960 if (IS_FLOAT(my_type)) {
1962 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1963 emitIvals(oBuf, topsym, list, 0, size);
1967 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1968 // integral type, 8, 16, or 32 bit
1969 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1970 emitIvals(oBuf, topsym, list, 0, size);
1973 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1975 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1976 assert (!list || (list->type == INIT_DEEP));
1978 // iterate over struct members and initList
1979 if (list) list = list->init.deep;
1980 sym = SPEC_STRUCT(my_type)->fields;
1984 if (IS_BITFIELD(sym->type)) {
1985 while (sym && IS_BITFIELD(sym->type)) {
1986 assert (!list || ((list->type == INIT_NODE)
1987 && IS_AST_LIT_VALUE(list->init.node)));
1988 lit = list ? list2int(list) : 0;
1989 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1990 lit, SPEC_BLEN(getSpec(sym->type)),
1991 SPEC_BSTR(getSpec(sym->type)), bitfield);
1992 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1993 len += SPEC_BLEN(getSpec(sym->type));
1996 if (list) list = list->next;
1998 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
1999 len = (len + 7) & ~0x07; // round up to full bytes
2000 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2005 emitInitVal(oBuf, topsym, sym->type, list);
2008 if (list) list = list->next;
2012 assert ( !"Excess initializers." );
2016 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2018 DEBUGprintf ("(union, %d byte) handled below\n", size);
2019 assert (list && list->type == INIT_DEEP);
2021 // iterate over union members and initList, try to map number and type of fields and initializers
2022 my_type = matchIvalToUnion(list, my_type, size);
2024 emitInitVal(oBuf, topsym, my_type, list->init.deep);
2026 size -= getSize(my_type);
2028 // pad with (leading) zeros
2029 emitIvals(oBuf, NULL, NULL, 0, size);
2034 assert ( !"No UNION member matches the initializer structure.");
2035 } else if (IS_BITFIELD(my_type)) {
2036 assert ( !"bitfields should only occur in structs..." );
2039 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2040 assert( !"Unhandled initialized type.");
2045 * Emit a set of symbols.
2046 * type - 0: have symbol tell whether it is local, extern or global
2047 * 1: assume all symbols in set to be global
2048 * 2: assume all symbols in set to be extern
2051 emitSymbolSet(set *s, int type)
2055 unsigned sectionNr = 0;
2057 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2059 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2060 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2063 if (sym->etype && SPEC_ABSA(sym->etype)
2064 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
2067 // handle config words
2068 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2069 (int)list2int(sym->ival));
2070 pic14_stringInSet(sym->rname, &emitted, 1);
2074 if (sym->isstrlit) {
2075 // special case: string literals
2076 emitInitVal(ivalBuf, sym, sym->type, NULL);
2080 if (type != 0 || sym->cdef
2081 || (!IS_STATIC(sym->etype)
2084 // bail out for ___fsadd and friends
2085 if (sym->cdef && !sym->used) continue;
2087 /* export or import non-static globals */
2088 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2090 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2092 /* do not add to emitted set, it might occur again! */
2093 //if (!sym->used) continue;
2095 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2098 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2099 if (!sym->ival && !IS_FUNC(sym->type)) {
2100 // also define symbol
2101 if (IS_ABSOLUTE(sym->etype)) {
2102 // absolute location?
2103 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2104 // deferred to pic14_constructAbsMap
2106 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2107 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2111 pic14_stringInSet(sym->rname, &emitted, 1);
2115 //if (list) showInitList(list, 0);
2117 resolveIvalSym( list, sym->type );
2118 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2119 dbuf_printf (ivalBuf, "\n");
2125 * Iterate over all memmaps and emit their contents (attributes, symbols).
2128 showAllMemmaps(FILE *of)
2130 struct dbuf_s locBuf;
2132 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2133 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2134 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2138 DEBUGprintf ("---begin memmaps---\n");
2139 if (!extBuf) extBuf = dbuf_new(1024);
2140 if (!gloBuf) gloBuf = dbuf_new(1024);
2141 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2142 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2143 dbuf_init(&locBuf, 1024);
2145 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2146 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2147 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2148 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2149 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2151 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2153 //DEBUGprintf ("memmap %i: %p\n", i, map);
2156 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",
2157 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2158 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2159 map->codesp, map->regsp, map->syms);
2161 emitSymbolSet(map->syms, 0);
2164 DEBUGprintf ("---end of memmaps---\n");
2166 emitSymbolSet(publics, 1);
2167 emitSymbolSet(externs, 2);
2169 emitPseudoStack(gloBuf, extBuf);
2170 pic14_constructAbsMap(gloDefBuf, gloBuf);
2171 pic14printLocals (&locBuf);
2172 pic14_emitConfigWord(of); // must be done after all the rest
2174 dbuf_write_and_destroy(extBuf, of);
2175 dbuf_write_and_destroy(gloBuf, of);
2176 dbuf_write_and_destroy(gloDefBuf, of);
2177 dbuf_write_and_destroy(&locBuf, of);
2178 dbuf_write_and_destroy(ivalBuf, of);
2180 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;