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);
76 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
77 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
79 /* dbufs for initialized data (idata and code sections),
80 * extern, and global declarations */
81 struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
83 static set *emitted = NULL;
84 int pic14_stringInSet(const char *str, set **world, int autoAdd);
86 /*-----------------------------------------------------------------*/
87 /* aopLiteral - string from a literal value */
88 /*-----------------------------------------------------------------*/
89 unsigned int pic14aopLiteral (value *val, int offset)
96 /* if it is a float then it gets tricky */
97 /* otherwise it is fairly simple */
98 if (!IS_FLOAT(val->type)) {
99 unsigned long v = (unsigned long) floatFromVal(val);
101 return ( (v >> (offset * 8)) & 0xff);
104 /* it is type float */
105 fl.f = (float) floatFromVal(val);
106 #ifdef WORDS_BIGENDIAN
107 return fl.c[3-offset];
116 is_valid_identifier( const char *name )
122 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
123 if (!((a >= 'a' && a <= 'z')
124 || (a >= 'A' && a <= 'z')
129 while ((a = *name++))
131 if (!((a >= 'a' && a <= 'z')
132 || (a >= 'A' && a <= 'Z')
133 || (a >= '0' && a <= '9')
138 /* valid identifier */
144 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
146 int shared, low, high, size, i;
149 /* also emit STK symbols
150 * XXX: This is ugly and fails as soon as devices start to get
151 * differently sized sharebanks, since STK12 will be
152 * required by larger devices but only up to STK03 might
153 * be defined using smaller devices. */
154 shared = pic14_getSharedStack(&low, &high, &size);
155 if (!pic14_options.isLibrarySource)
157 pic = pic14_getPIC();
159 dbuf_printf (oBuf, "\n");
160 dbuf_printf (oBuf, "\tglobal PSAVE\n");
161 dbuf_printf (oBuf, "\tglobal SSAVE\n");
162 dbuf_printf (oBuf, "\tglobal WSAVE\n");
163 for (i = size - 4; i >= 0; i--) {
164 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
166 dbuf_printf (oBuf, "\n");
168 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
171 // for single banked devices: use normal, "banked" RAM
172 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
174 // for devices with at least two banks, require a sharebank section
175 dbuf_printf (oBuf, "sharebank udata_shr\n");
177 dbuf_printf (oBuf, "PSAVE\tres 1\n");
178 dbuf_printf (oBuf, "SSAVE\tres 1\n");
179 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
180 /* fill rest of sharebank with stack STKxx .. STK00 */
181 for (i = size - 4; i >= 0; i--) {
182 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
185 /* declare STKxx as extern for all files
186 * except the one containing main() */
187 dbuf_printf (oBufExt, "\n");
188 dbuf_printf (oBufExt, "\textern PSAVE\n");
189 dbuf_printf (oBufExt, "\textern SSAVE\n");
190 dbuf_printf (oBufExt, "\textern WSAVE\n");
191 for (i = size - 4; i >= 0; i--) {
193 SNPRINTF(&buffer[0], 127, "STK%02d", i);
194 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
195 pic14_stringInSet(&buffer[0], &emitted, 1);
198 dbuf_printf (oBuf, "\n");
202 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
205 int wasPresent = pic14_stringInSet(name, emitted, 1);
208 dbuf_printf (oBuf, fmt, name);
210 return (!wasPresent);
213 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
214 extern int IS_CONFIG_ADDRESS( int addr );
216 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
218 memmap *maps[] = { data, sfr, NULL };
223 int addr, min=-1, max=-1;
226 for (i=0; maps[i] != NULL; i++)
228 for (sym = (symbol *)setFirstItem (maps[i]->syms);
229 sym; sym = setNextItem (maps[i]->syms))
231 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
233 addr = SPEC_ADDR(sym->etype);
235 /* handle CONFIG words here */
236 if (IS_CONFIG_ADDRESS( addr ))
238 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
239 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
241 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
243 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
248 if (max == -1 || addr > max) max = addr;
249 if (min == -1 || addr < min) min = addr;
250 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
251 aliases = hTabItemWithKey (ht, addr);
253 /* May not use addSetHead, as we cannot update the
254 * list's head in the hastable `ht'. */
255 addSet (&aliases, sym);
257 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
258 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
261 addSet (&aliases, sym);
262 hTabAddItem (&ht, addr, aliases);
268 /* now emit definitions for all absolute symbols */
269 dbuf_printf (oBuf, "%s", iComments2);
270 dbuf_printf (oBuf, "; absolute symbol definitions\n");
271 dbuf_printf (oBuf, "%s", iComments2);
272 for (addr=min; addr <= max; addr++)
275 aliases = hTabItemWithKey (ht, addr);
276 if (aliases && elementsInSet(aliases)) {
277 /* Make sure there is no initialized value at this location! */
278 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
279 if (sym->ival) break;
283 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
284 moduleName, addr, addr);
285 for (sym = setFirstItem (aliases); sym;
286 sym = setNextItem (aliases))
288 if (getSize(sym->type) > size) {
289 size = getSize(sym->type);
292 /* initialized values are handled somewhere else */
293 if (sym->ival) continue;
295 /* emit STATUS as well as _STATUS, required for SFRs only */
296 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
297 dbuf_printf (oBuf, "%s\n", sym->rname);
299 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
300 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
301 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
304 dbuf_printf (oBuf, "\tres\t%d\n", size);
310 /*-----------------------------------------------------------------*/
311 /* emitRegularMap - emit code for maps with no special cases */
312 /*-----------------------------------------------------------------*/
314 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
319 /* print the area name */
321 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
323 for (sym = setFirstItem (map->syms); sym;
324 sym = setNextItem (map->syms)) {
326 //printf("%s\n",sym->name);
328 /* ignore if config word */
329 if (SPEC_ABSA(sym->etype)
330 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
333 /* if extern then add it into the extern list */
334 if (IS_EXTERN (sym->etype)) {
335 addSetHead (&externs, sym);
339 /* if allocation required check is needed
340 then check if the symbol really requires
341 allocation only for local variables */
342 if (arFlag && !IS_AGGREGATE (sym->type) &&
343 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
344 !sym->allocreq && sym->level)
347 /* if global variable & not static or extern
348 and addPublics allowed then add it to the public set */
349 if ((sym->level == 0 ||
350 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
352 !IS_STATIC (sym->etype))
354 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
355 addSetHead (&publics, sym);
358 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
361 /* if extern then do nothing or is a function
363 if (IS_FUNC (sym->type))
366 /* print extra debug info if required */
367 if (options.debug || sym->level == 0)
369 if (!sym->level) /* global */
370 if (IS_STATIC (sym->etype))
371 dbuf_printf (&map->oBuf, "F%s_", moduleName); /* scope is file */
373 dbuf_printf (&map->oBuf, "G_"); /* scope is global */
375 /* symbol is local */
376 dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
377 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
380 /* absolute symbols are handled in pic14_constructAbsMap */
381 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
384 /* if it has an absolute address then generate
385 an equate for this no need to allocate space */
386 if (0 && SPEC_ABSA (sym->etype))
388 //if (options.debug || sym->level == 0)
389 //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
391 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
393 SPEC_ADDR (sym->etype));
399 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
400 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
401 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
402 if (IS_BITVAR (sym->etype))
409 emitSymbol (&map->oBuf,
412 getSize (sym->type) & 0xffff,
413 SPEC_ABSA(sym->etype)
414 ? SPEC_ADDR(sym->etype)
423 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
425 for (i = 1; i < size; i++)
426 dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
431 //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
434 /* if it has a initial value then do it only if
435 it is a global variable */
437 /* mark symbol as already defined */
438 pic14_stringInSet(sym->name, &emitted, 1);
439 pic14_stringInSet(sym->rname, &emitted, 1);
442 /* if it has a initial value then do it only if
443 it is a global variable */
444 if (sym->ival && sym->level == 0) {
447 if (IS_AGGREGATE (sym->type))
448 ival = initAggregates (sym, sym->ival, NULL);
450 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
451 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
452 codeOutBuf = &statsg->oBuf;
454 eBBlockFromiCode (iCodeFromAst (ival));
464 /*-----------------------------------------------------------------*/
465 /* printIvalType - generates ival for int/char */
466 /*-----------------------------------------------------------------*/
468 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
473 //fprintf(stderr, "%s\n",__FUNCTION__);
475 /* if initList is deep */
476 if (ilist->type == INIT_DEEP)
477 ilist = ilist->init.deep;
479 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
480 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
483 if (!(val = list2val (ilist))) {
484 // assuming a warning has been thrown
488 if (val->type != type) {
489 val = valCastLiteral(type, floatFromVal(val));
493 ulval = (unsigned long) floatFromVal (val);
497 switch (getSize (type)) {
499 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
503 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
504 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
508 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
509 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
510 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
511 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
516 /*-----------------------------------------------------------------*/
517 /* printIvalBitFields - generate initializer for bitfields */
518 /*-----------------------------------------------------------------*/
519 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
523 initList *lilist = *ilist ;
524 unsigned long ival = 0;
530 val = list2val(lilist);
532 if (SPEC_BLEN(lsym->etype) > 8) {
533 size += ((SPEC_BLEN (lsym->etype) / 8) +
534 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
537 size = ((SPEC_BLEN (lsym->etype) / 8) +
538 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
540 i = (unsigned long)floatFromVal(val);
541 i <<= SPEC_BSTR (lsym->etype);
543 if (! ( lsym->next &&
544 (IS_BITFIELD(lsym->next->type)) &&
545 (SPEC_BSTR(lsym->next->etype)))) break;
547 lilist = lilist->next;
551 //tfprintf (oFile, "\t!db !constbyte\n",ival);
552 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
556 //tfprintf (oFile, "\t!dw !constword\n",ival);
557 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
558 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
561 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
562 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
563 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
564 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
565 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
572 /*-----------------------------------------------------------------*/
573 /* printIvalStruct - generates initial value for structures */
574 /*-----------------------------------------------------------------*/
575 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
578 initList *iloop = NULL;
580 sflds = SPEC_STRUCT (type)->fields;
583 if (ilist->type != INIT_DEEP) {
584 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
588 iloop = ilist->init.deep;
591 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
592 if (IS_BITFIELD(sflds->type)) {
593 printIvalBitFields(&sflds,&iloop,pb);
595 printIval (sym, sflds->type, iloop, pb);
599 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
604 /*-----------------------------------------------------------------*/
605 /* printIvalChar - generates initital value for character array */
606 /*-----------------------------------------------------------------*/
608 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
616 //fprintf(stderr, "%s\n",__FUNCTION__);
620 val = list2val (ilist);
622 /* if the value is a character string */
623 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
625 ilen = DCL_ELEM(val->type);
627 if (!DCL_ELEM (type))
628 DCL_ELEM (type) = ilen;
630 /* emit string constant */
631 for (remain = 0; remain < ilen; remain++) {
632 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
635 /* fill array up to desired size */
636 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
638 //tfprintf (oFile, "\t!db !constbyte\n", 0);
639 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
646 //printChar (oFile, s, strlen (s) + 1);
648 for(remain=0; remain<(int)strlen(s); remain++) {
649 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
650 //fprintf(stderr,"0x%02x ",s[remain]);
652 //fprintf(stderr,"\n");
657 /*-----------------------------------------------------------------*/
658 /* printIvalArray - generates code for array initialization */
659 /*-----------------------------------------------------------------*/
661 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
670 /* take care of the special case */
671 /* array of characters can be init */
673 if (IS_CHAR (type->next)) {
674 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
675 if (!IS_LITERAL(list2val(ilist)->etype)) {
676 werror (W_INIT_WRONG);
679 if (printIvalChar (type,
680 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
681 pb, SPEC_CVAL (sym->etype).v_char))
684 /* not the special case */
685 if (ilist->type != INIT_DEEP) {
686 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
690 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
691 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
692 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
695 printIval (sym, type->next, iloop, pb);
699 if (DCL_ELEM(type)) {
700 // pad with zeros if needed
701 if (size<DCL_ELEM(type)) {
702 size = (DCL_ELEM(type) - size) * getSize(type->next);
704 //tfprintf (oFile, "\t!db !constbyte\n", 0);
705 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
709 // we have not been given a size, but we now know it
710 DCL_ELEM (type) = size;
716 /*-----------------------------------------------------------------*/
717 /* printIvalPtr - generates code for initial value of pointers */
718 /*-----------------------------------------------------------------*/
719 extern value *initPointer (initList *, sym_link *toType);
722 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
729 fprintf (stderr, "FIXME: initializers for pointers...\n");
730 printTypeChain (type, stderr);
732 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
733 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
735 if (ilist && (ilist->type == INIT_DEEP))
736 ilist = ilist->init.deep;
738 /* function pointers */
739 if (IS_FUNC (type->next))
741 assert ( !"function pointers not yet handled" );
742 //printIvalFuncPtr (type, ilist, pb);
745 if (!(val = initPointer (ilist, type)))
748 if (IS_CHAR (type->next))
750 if (printIvalChar (type, ilist, pb, NULL)) return;
754 if (compareType (type, val->type) == 0)
756 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
757 printFromToType (val->type, type);
760 if (IS_LITERAL (val->etype))
762 switch (getSize (type))
765 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
768 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
770 case 3: /* gneric pointers */
771 assert ( !"generic pointers not yet handled" );
773 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
776 assert ( !"invaild size of value -- aborting" );
782 /* now handle symbolic values */
783 switch (getSize (type))
786 fprintf (stderr, "BYTE: %s", val->name);
789 fprintf (stderr, "WORD: %s", val->name);
792 fprintf (stderr, "LONG: %s", val->name);
795 assert ( !"invalid size of (symbolic) value -- aborting" );
799 /*-----------------------------------------------------------------*/
800 /* printIval - generates code for initial value */
801 /*-----------------------------------------------------------------*/
803 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
808 /* if structure then */
809 if (IS_STRUCT (type))
811 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
812 printIvalStruct (sym, type, ilist, pb);
816 /* if this is an array */
819 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
820 printIvalArray (sym, type, ilist, pb);
824 /* if this is a pointer */
827 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
828 printIvalPtr (sym, type, ilist, pb);
832 /* if type is SPECIFIER */
835 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
836 printIvalType (sym, type, ilist, pb);
843 extern void pCodeConstString(char *name, char *value);
844 /*-----------------------------------------------------------------*/
845 /* emitStaticSeg - emitcode for the static segment */
846 /*-----------------------------------------------------------------*/
848 pic14emitStaticSeg (memmap * map)
852 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
854 //fprintf(stderr, "%s\n",__FUNCTION__);
856 /* for all variables in this segment do */
857 for (sym = setFirstItem (map->syms); sym;
858 sym = setNextItem (map->syms))
860 /* if extern then add it into the extern list */
861 if (IS_EXTERN (sym->etype)) {
862 addSetHead (&externs, sym);
866 /* if it is not static add it to the public
868 if (!IS_STATIC (sym->etype))
869 addSetHead (&publics, sym);
871 /* print extra debug info if required */
872 if (options.debug || sym->level == 0)
876 if (IS_STATIC (sym->etype))
877 dbuf_printf (&code->oBuf, "F%s_", moduleName); /* scope is file */
879 dbuf_printf (&code->oBuf, "G_"); /* scope is global */
882 /* symbol is local */
883 dbuf_printf (&code->oBuf, "L%s_",
884 (sym->localof ? sym->localof->name : "-null-"));
885 dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
889 /* if it has an absolute address */
890 if (SPEC_ABSA (sym->etype))
892 if (options.debug || sym->level == 0)
893 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
895 dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
897 SPEC_ADDR (sym->etype));
901 if (options.debug || sym->level == 0)
902 dbuf_printf (&code->oBuf, " == .\n");
904 /* if it has an initial value */
910 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
912 resolveIvalSym (sym->ival, sym->type);
913 //printIval (sym, sym->type, sym->ival, &code->oBuf);
914 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
916 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
918 printIval (sym, sym->type, sym->ival, pb);
926 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
927 /* special case for character strings */
928 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
929 SPEC_CVAL (sym->etype).v_char)
930 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
931 /*printChar (code->oFile,
932 SPEC_CVAL (sym->etype).v_char,
933 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
935 dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
945 /*-----------------------------------------------------------------*/
946 /* emitMaps - emits the code for the data portion the code */
947 /*-----------------------------------------------------------------*/
951 pic14_constructAbsMap (&sfr->oBuf);
952 emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
953 /* no special considerations for the following
954 data, idata & bit & xdata */
955 pic14emitRegularMap (data, TRUE, TRUE);
956 pic14emitRegularMap (idata, TRUE, TRUE);
957 pic14emitRegularMap (bit, TRUE, FALSE);
958 pic14emitRegularMap (xdata, TRUE, TRUE);
959 pic14emitRegularMap (sfr, TRUE, FALSE);
960 pic14emitRegularMap (sfrbit, FALSE, FALSE);
961 pic14emitRegularMap (code, TRUE, FALSE);
962 pic14emitStaticSeg (statsg);
963 pic14emitStaticSeg (c_abs);
967 /*-----------------------------------------------------------------*/
968 /* createInterruptVect - creates the interrupt vector */
969 /*-----------------------------------------------------------------*/
970 pCodeOp *popGetExternal (char *str);
972 pic14createInterruptVect (struct dbuf_s * vBuf)
974 mainf = newSymbol ("main", 0);
977 /* only if the main function exists */
978 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
980 struct options *op = &options;
981 if (!(op->cc_only || noAssemble))
982 // werror (E_NO_MAIN);
983 fprintf(stderr,"WARNING: function 'main' undefined\n");
987 /* if the main is only a prototype ie. no body then do nothing */
988 if (!IFFUNC_HASBODY(mainf->type))
990 /* if ! compile only then main function should be present */
991 if (!(options.cc_only || noAssemble))
992 // werror (E_NO_MAIN);
993 fprintf(stderr,"WARNING: function 'main' undefined\n");
997 dbuf_printf (vBuf, "%s", iComments2);
998 dbuf_printf (vBuf, "; reset vector \n");
999 dbuf_printf (vBuf, "%s", iComments2);
1000 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1001 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
1002 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
1003 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
1004 popGetExternal("__sdcc_gsinit_startup");
1008 /*-----------------------------------------------------------------*/
1009 /* initialComments - puts in some initial comments */
1010 /*-----------------------------------------------------------------*/
1012 pic14initialComments (FILE * afile)
1014 initialComments (afile);
1015 fprintf (afile, "; PIC port for the 14-bit core\n");
1016 fprintf (afile, iComments2);
1021 pic14_stringInSet(const char *str, set **world, int autoAdd)
1028 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1031 if (0 == strcmp(s, str)) return 1;
1035 if (autoAdd) addSet(world, Safe_strdup(str));
1041 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1043 if (!pic14_stringInSet(sym, &emitted, 1)) {
1044 /* sym was not in emittedSymbols */
1045 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1046 /* sym is not a locally defined function---avoid bug #1443651 */
1047 fprintf( file, fmt, sym );
1056 /*-------------------------------------------------------------------*/
1057 /* emitSymbol - write a symbol definition only if it is not */
1058 /* already present */
1059 /*-------------------------------------------------------------------*/
1061 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1063 static unsigned int sec_idx = 0;
1065 /* workaround: variables declared via `sbit' result in a numeric
1066 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1067 * sbit is heavily used in the inc2h-generated header files!
1069 if (!is_valid_identifier(name))
1071 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1075 /* check whether the symbol is already defined */
1076 if (pic14_stringInSet(name, &emitted, 1)) return;
1078 /* new symbol -- define it */
1079 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1081 dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1083 /* we place each symbol into a section of its own to allow the linker
1084 * to distribute the data into all available memory banks */
1085 if (!section_type) section_type = "udata";
1088 /* absolute symbols are handled in pic14_constructAbsMap */
1091 if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1092 dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1093 sec_idx++, section_type);
1094 dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1102 /*-----------------------------------------------------------------*/
1103 /* printExterns - generates extern for external variables */
1104 /*-----------------------------------------------------------------*/
1106 pic14printExterns (FILE * afile)
1110 fprintf (afile, "%s", iComments2);
1111 fprintf (afile, "; extern variables in this module\n");
1112 fprintf (afile, "%s", iComments2);
1114 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1115 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1118 /*-----------------------------------------------------------------*/
1119 /* printPublics - generates .global for publics */
1120 /*-----------------------------------------------------------------*/
1122 pic14printPublics (FILE * afile)
1126 fprintf (afile, "%s", iComments2);
1127 fprintf (afile, "; public variables in this module\n");
1128 fprintf (afile, "%s", iComments2);
1130 for (sym = setFirstItem (publics); sym;
1131 sym = setNextItem (publics)) {
1133 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1134 if (!IS_BITVAR(sym->type))
1135 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1137 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1138 /* Not any longer! */
1139 //if (!SPEC_ABSA (sym->etype))
1140 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1147 * Interface to BANKSEL generation.
1148 * This function should return != 0 iff str1 and str2 denote operands that
1149 * are known to be allocated into the same bank. Consequently, there will
1150 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
1151 * select the current bank just previously.
1153 * If in doubt, return 0.
1156 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
1157 // see pic14printLocals
1159 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1160 // no clustering applied, each register resides in its own bank
1162 // check whether BOTH names are local registers
1163 // XXX: This is some kind of shortcut, should be safe...
1164 // In this model, all r0xXXXX are allocated into a single section
1165 // per file, so no BANKSEL required if accessing a r0xXXXX after a
1166 // (different) r0xXXXX. Works great for multi-byte operands.
1167 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
1170 // assume operands in different banks
1175 pic14printLocals (struct dbuf_s *oBuf)
1177 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1178 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1180 int i, is_first = 1;
1181 static unsigned sectionNr = 0;
1183 /* emit all registers from all possible sets */
1184 for (i = 0; i < 6; i++) {
1185 if (allregs[i] == NULL) continue;
1187 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1188 if (reg->isEmitted) continue;
1190 if (reg->wasUsed && !reg->isExtern) {
1191 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1193 // Should not happen, really...
1194 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1195 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1196 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1198 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1199 // assign each local register into its own section
1200 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1201 moduleName, sectionNr++, reg->name, reg->size);
1203 // group all local registers into a single section
1204 // This should greatly improve BANKSEL generation...
1206 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1209 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1219 /*-----------------------------------------------------------------*/
1220 /* emitOverlay - will emit code for the overlay stuff */
1221 /*-----------------------------------------------------------------*/
1223 pic14emitOverlay (struct dbuf_s * aBuf)
1227 /* if (!elementsInSet (ovrSetSets))*/
1229 /* the hack below, fixes translates for devices which
1230 * only have udata_shr memory */
1231 dbuf_printf (aBuf, "%s\t%s\n",
1232 (elementsInSet(ovrSetSets)?"":";"),
1233 port->mem.overlay_name);
1235 /* for each of the sets in the overlay segment do */
1236 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1237 ovrset = setNextItem (ovrSetSets))
1242 if (elementsInSet (ovrset))
1244 /* this dummy area is used to fool the assembler
1245 otherwise the assembler will append each of these
1246 declarations into one chunk and will not overlay
1249 /* I don't think this applies to us. We are using gpasm. CRF */
1251 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1252 /* output the area informtion */
1253 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1256 for (sym = setFirstItem (ovrset); sym;
1257 sym = setNextItem (ovrset))
1260 /* if extern then do nothing */
1261 if (IS_EXTERN (sym->etype))
1264 /* if allocation required check is needed
1265 then check if the symbol really requires
1266 allocation only for local variables */
1267 if (!IS_AGGREGATE (sym->type) &&
1268 !(sym->_isparm && !IS_REGPARM (sym->etype))
1269 && !sym->allocreq && sym->level)
1272 /* if global variable & not static or extern
1273 and addPublics allowed then add it to the public set */
1274 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1275 && !IS_STATIC (sym->etype))
1276 addSetHead (&publics, sym);
1278 /* if extern then do nothing or is a function
1280 if (IS_FUNC (sym->type))
1283 /* print extra debug info if required */
1284 if (options.debug || sym->level == 0)
1288 if (IS_STATIC (sym->etype))
1289 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1291 dbuf_printf (aBuf, "G_"); /* scope is global */
1294 /* symbol is local */
1295 dbuf_printf (aBuf, "L%s_",
1296 (sym->localof ? sym->localof->name : "-null-"));
1297 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1300 /* if is has an absolute address then generate
1301 an equate for this no need to allocate space */
1302 if (SPEC_ABSA (sym->etype))
1305 if (options.debug || sym->level == 0)
1306 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1308 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1310 SPEC_ADDR (sym->etype));
1314 if (options.debug || sym->level == 0)
1315 dbuf_printf (aBuf, "==.\n");
1317 /* allocate space */
1318 dbuf_printf (aBuf, "%s:\n", sym->rname);
1319 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1328 pic14_emitInterruptHandler (FILE * asmFile)
1330 if (pic14_hasInterrupt)
1333 fprintf (asmFile, "%s", iComments2);
1334 fprintf (asmFile, "; interrupt and initialization code\n");
1335 fprintf (asmFile, "%s", iComments2);
1336 // Note - for mplink may have to enlarge section vectors in .lnk file
1337 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1338 // source files's code segment (interrupt.c -> code_interrupt)
1339 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1341 /* interrupt service routine */
1342 fprintf (asmFile, "__sdcc_interrupt\n");
1343 copypCode(asmFile, 'I');
1347 /*-----------------------------------------------------------------*/
1348 /* glue - the final glue that hold the whole thing together */
1349 /*-----------------------------------------------------------------*/
1354 struct dbuf_s ovrBuf;
1357 dbuf_init(&ovrBuf, 4096);
1358 dbuf_init(&vBuf, 4096);
1360 pCodeInitRegisters();
1362 /* check for main() */
1363 mainf = newSymbol ("main", 0);
1365 mainf = findSymWithLevel (SymbolTab, mainf);
1367 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1369 /* main missing -- import stack from main module */
1370 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1371 pic14_options.isLibrarySource = 1;
1375 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1377 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1380 /* entry point @ start of CSEG */
1381 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1382 /* put in the call to main */
1383 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1385 if (options.mainreturn) {
1387 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1388 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1392 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1393 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1399 /* At this point we've got all the code in the form of pCode structures */
1400 /* Now it needs to be rearranged into the order it should be placed in the */
1403 movepBlock2Head('P'); // Last
1404 movepBlock2Head(code->dbName);
1405 movepBlock2Head('X');
1406 movepBlock2Head(statsg->dbName); // First
1409 /* print the global struct definitions */
1413 /* emit code for the all the variables declared */
1415 /* do the overlay segments */
1416 pic14emitOverlay(&ovrBuf);
1418 /* PENDING: this isnt the best place but it will do */
1419 if (port->general.glue_up_main) {
1420 /* create the interrupt vector table */
1421 pic14createInterruptVect (&vBuf);
1426 ReuseReg(); // ReuseReg where call tree permits
1435 /* now put it all together into the assembler file */
1436 /* create the assembler file name */
1438 if ((noAssemble || options.c1mode) && fullDstFileName)
1440 sprintf (buffer, fullDstFileName);
1444 sprintf (buffer, dstFileName);
1445 strcat (buffer, ".asm");
1448 if (!(asmFile = fopen (buffer, "w"))) {
1449 werror (E_FILE_OPEN_ERR, buffer);
1453 /* prepare statistics */
1454 resetpCodeStatistics ();
1456 /* initial comments */
1457 pic14initialComments (asmFile);
1459 /* print module name */
1460 fprintf (asmFile, ";\t.module %s\n", moduleName);
1462 /* Let the port generate any global directives, etc. */
1463 if (port->genAssemblerPreamble)
1465 port->genAssemblerPreamble(asmFile);
1468 /* print the global variables in this module */
1469 //pic14printPublics (asmFile);
1471 /* print the extern variables in this module */
1472 //pic14printExterns (asmFile);
1474 /* copy the sfr segment */
1476 fprintf (asmFile, "%s", iComments2);
1477 fprintf (asmFile, "; special function registers\n");
1478 fprintf (asmFile, "%s", iComments2);
1479 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1482 if (udata_section_name) {
1483 sprintf(udata_name,"%s",udata_section_name);
1485 sprintf(udata_name,"data_%s",moduleName);
1487 fprintf (asmFile, "%s", iComments2);
1488 fprintf (asmFile, "; udata\n");
1489 fprintf (asmFile, "%s", iComments2);
1490 fprintf (asmFile, "%s\tudata\n", udata_name);
1491 dbuf_write_and_destroy(&data->oBuf, asmFile);
1494 /* Put all variables into a cblock */
1497 /* emit initialized data */
1498 showAllMemmaps(asmFile);
1500 /* print the locally defined variables in this module */
1501 writeUsedRegs(asmFile);
1503 /* create the overlay segments */
1504 fprintf (asmFile, "%s", iComments2);
1505 fprintf (asmFile, "; overlayable items in internal ram \n");
1506 fprintf (asmFile, "%s", iComments2);
1507 dbuf_write_and_destroy (&ovrBuf, asmFile);
1511 /* create the stack segment MOF */
1512 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1513 fprintf (asmFile, "%s", iComments2);
1514 fprintf (asmFile, "; Stack segment in internal ram \n");
1515 fprintf (asmFile, "%s", iComments2);
1516 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1517 ";__start__stack:\n;\t.ds\t1\n\n");
1520 /* create the idata segment */
1521 fprintf (asmFile, "%s", iComments2);
1522 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1523 fprintf (asmFile, "%s", iComments2);
1524 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1526 /* if external stack then reserve space of it */
1527 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1528 fprintf (asmFile, "%s", iComments2);
1529 fprintf (asmFile, "; external stack \n");
1530 fprintf (asmFile, "%s", iComments2);
1531 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1532 fprintf (asmFile,";\t.ds 256\n");
1535 /* copy xtern ram data */
1536 fprintf (asmFile, "%s", iComments2);
1537 fprintf (asmFile, "; external ram data\n");
1538 fprintf (asmFile, "%s", iComments2);
1539 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1543 /* copy the bit segment */
1545 fprintf (asmFile, "%s", iComments2);
1546 fprintf (asmFile, "; bit data\n");
1547 fprintf (asmFile, "%s", iComments2);
1548 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1551 /* copy the interrupt vector table */
1552 if (mainf && IFFUNC_HASBODY(mainf->type))
1553 dbuf_write_and_destroy (&vBuf, asmFile);
1555 dbuf_destroy(&vBuf);
1557 /* create interupt ventor handler */
1558 pic14_emitInterruptHandler (asmFile);
1560 /* copy over code */
1561 fprintf (asmFile, "%s", iComments2);
1562 fprintf (asmFile, "; code\n");
1563 fprintf (asmFile, "%s", iComments2);
1564 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1567 copypCode(asmFile, 'X');
1569 /* _main function */
1570 copypCode(asmFile, 'M');
1572 /* other functions */
1573 copypCode(asmFile, code->dbName);
1576 copypCode(asmFile, 'P');
1578 dumppCodeStatistics (asmFile);
1580 fprintf (asmFile,"\tend\n");
1586 * Deal with initializers.
1591 #define DEBUGprintf printf
1594 #define DEBUGprintf 1 ? (void)0 : (void)printf
1598 void ast_print (ast * tree, FILE *outfile, int indent);
1605 showInitList(initList *list, int level)
1607 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1608 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1611 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1612 if (list->type == INIT_DEEP) {
1613 showInitList(list->init.deep, level + 1);
1614 } else if (list->type == INIT_NODE) {
1615 ast = list->init.node;
1616 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1617 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1618 if (ast->type == EX_VALUE) {
1619 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1620 } else if (ast->type == EX_LINK) {
1621 printTypeChain(ast->opval.lnk, NULL);
1622 } else if (ast->type == EX_OP) {
1623 printf (" OP %u\n", ast->opval.op);
1632 * DEBUG: Print a value.
1635 printVal(value *val)
1637 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1638 val, val->name, val->type, val->etype,
1639 val->sym ? val->sym->name : NULL, val->vArgs,
1640 (long)floatFromVal(val), (long)floatFromVal(val));
1641 printTypeChain(val->type, stdout);
1643 printTypeChain(val->etype, stdout);
1647 //prototype from ../SDCCicode.c
1648 operand *operandFromAst (ast * tree,int lvl);
1651 parseIvalAst (ast *node, int *inCodeSpace) {
1653 char *buffer = NULL;
1656 if (IS_AST_VALUE(node)) {
1657 value *val = AST_VALUE(node);
1658 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1659 if (inCodeSpace && val->type
1660 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1664 if (inCodeSpace && sym
1665 && (IS_FUNC(sym->type)
1666 || IS_CODE(getSpec(sym->type))))
1671 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1672 if (IS_AST_LIT_VALUE(node)) {
1673 buffer = Safe_alloc(LEN);
1674 SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node));
1675 } else if (IS_AST_SYM_VALUE(node)) {
1676 assert ( AST_SYMBOL(node) );
1678 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1679 printTypeChain(AST_SYMBOL(node)->type, stdout);
1680 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1681 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1683 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1685 assert ( !"Invalid values type for initializers in AST." );
1687 } else if (IS_AST_OP(node)) {
1688 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1689 switch (node->opval.op) {
1691 assert (node->right);
1692 buffer = parseIvalAst(node->right, inCodeSpace);
1693 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1696 assert ( node->left && !node->right );
1697 buffer = parseIvalAst(node->left, inCodeSpace);
1698 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1701 assert (node->left && node->right );
1702 left = parseIvalAst(node->left, inCodeSpace);
1703 right = parseIvalAst(node->right, inCodeSpace);
1704 buffer = Safe_alloc(LEN);
1705 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1706 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1711 assert ( node->left && node->right );
1712 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1713 right = parseIvalAst(node->right, inCodeSpace);
1714 buffer = Safe_alloc(LEN);
1715 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1716 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1718 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1721 assert ( !"Unhandled operation in initializer." );
1725 assert ( !"Invalid construct in initializer." );
1732 * Emit the section preamble, absolute location (if any) and
1733 * symbol name(s) for intialized data.
1736 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1739 static int in_code = 0;
1740 static int sectionNr = 0;
1743 // code or data space?
1744 if (IS_CODE(getSpec(sym->type))) {
1751 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1752 if (SPEC_ABSA(getSpec(sym->type))) {
1753 // specify address for absolute symbols
1754 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1756 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1758 addSet(&emitted, sym->rname);
1763 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1765 * Actually emit the initial values in .asm format.
1768 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1774 int inCodeSpace = 0;
1778 assert (size <= sizeof(long));
1779 assert (!list || (list->type == INIT_NODE));
1780 node = list ? list->init.node : NULL;
1782 in_code = emitIvalLabel(oBuf, sym);
1783 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1786 // initialize as zero
1787 for (i=0; i < size; i++) {
1789 dbuf_printf (oBuf, "\tretlw 0x00");
1791 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1794 dbuf_printf (oBuf, "\n");
1799 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1800 op = operandFromValue(val);
1801 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1803 } else if (IS_AST_VALUE(node)) {
1804 op = operandFromAst(node, 0);
1805 } else if (IS_AST_OP(node)) {
1806 str = parseIvalAst(node, &inCodeSpace);
1807 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1810 assert ( !"Unhandled construct in intializer." );
1816 //printOperand(op, of);
1819 for (i=0; i < size; i++) {
1820 char *text = op ? aopGet(AOP(op), i, 0, 0)
1821 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1823 dbuf_printf (oBuf, "\tretlw %s\n", text);
1825 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1828 dbuf_printf (oBuf, "\n");
1832 * For UNIONs, we first have to find the correct alternative to map the
1833 * initializer to. This function maps the structure of the initializer to
1834 * the UNION members recursively.
1835 * Returns the type of the first `fitting' member.
1838 matchIvalToUnion (initList *list, sym_link *type, int size)
1844 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1847 if (!list || (list->type == INIT_NODE)) {
1848 DEBUGprintf ("OK, simple type\n");
1851 DEBUGprintf ("ERROR, simple type\n");
1854 } else if (IS_BITFIELD(type)) {
1855 if (!list || (list->type == INIT_NODE)) {
1856 DEBUGprintf ("OK, bitfield\n");
1859 DEBUGprintf ("ERROR, bitfield\n");
1862 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1863 if (!list || (list->type == INIT_DEEP)) {
1864 if (list) list = list->init.deep;
1865 sym = SPEC_STRUCT(type)->fields;
1867 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1868 if (!matchIvalToUnion(list, sym->type, 0)) {
1869 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1872 if (list) list = list->next;
1876 // excess initializers?
1878 DEBUGprintf ("ERROR, excess initializers\n");
1882 DEBUGprintf ("OK, struct\n");
1886 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1887 if (!list || (list->type == INIT_DEEP)) {
1888 if (list) list = list->init.deep;
1889 sym = SPEC_STRUCT(type)->fields;
1891 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1892 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1893 && matchIvalToUnion(list, sym->type, size))
1895 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1902 DEBUGprintf ("ERROR, no match found.\n");
1905 assert ( !"Unhandled type in UNION." );
1908 assert ( !"No match found in UNION for the given initializer structure." );
1913 * Parse the type and its initializer and emit it (recursively).
1916 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1923 size = getSize(my_type);
1925 if (IS_PTR(my_type)) {
1926 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1927 emitIvals(oBuf, topsym, list, 0, size);
1931 if (IS_ARRAY(my_type) && topsym->isstrlit) {
1932 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1933 emitIvalLabel(oBuf, topsym);
1935 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1940 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1941 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1942 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1946 if (IS_ARRAY(my_type)) {
1947 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1948 assert (!list || list->type == INIT_DEEP);
1949 if (list) list = list->init.deep;
1950 for (i = 0; i < DCL_ELEM(my_type); i++) {
1951 emitInitVal(oBuf, topsym, my_type->next, list);
1953 if (list) list = list->next;
1958 if (IS_FLOAT(my_type)) {
1960 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1961 emitIvals(oBuf, topsym, list, 0, size);
1965 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1966 // integral type, 8, 16, or 32 bit
1967 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1968 emitIvals(oBuf, topsym, list, 0, size);
1971 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1973 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1974 assert (!list || (list->type == INIT_DEEP));
1976 // iterate over struct members and initList
1977 if (list) list = list->init.deep;
1978 sym = SPEC_STRUCT(my_type)->fields;
1982 if (IS_BITFIELD(sym->type)) {
1983 while (sym && IS_BITFIELD(sym->type)) {
1984 assert (!list || ((list->type == INIT_NODE)
1985 && IS_AST_LIT_VALUE(list->init.node)));
1986 lit = list ? list2int(list) : 0;
1987 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1988 lit, SPEC_BLEN(getSpec(sym->type)),
1989 SPEC_BSTR(getSpec(sym->type)), bitfield);
1990 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1991 len += SPEC_BLEN(getSpec(sym->type));
1994 if (list) list = list->next;
1996 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
1997 len = (len + 7) & ~0x07; // round up to full bytes
1998 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2003 emitInitVal(oBuf, topsym, sym->type, list);
2006 if (list) list = list->next;
2010 assert ( !"Excess initializers." );
2014 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2016 DEBUGprintf ("(union, %d byte) handled below\n", size);
2017 assert (list && list->type == INIT_DEEP);
2019 // iterate over union members and initList, try to map number and type of fields and initializers
2020 my_type = matchIvalToUnion(list, my_type, size);
2022 emitInitVal(oBuf, topsym, my_type, list->init.deep);
2024 size -= getSize(my_type);
2026 // pad with (leading) zeros
2027 emitIvals(oBuf, NULL, NULL, 0, size);
2032 assert ( !"No UNION member matches the initializer structure.");
2033 } else if (IS_BITFIELD(my_type)) {
2034 assert ( !"bitfields should only occur in structs..." );
2037 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2038 assert( !"Unhandled initialized type.");
2043 * Emit a set of symbols.
2044 * type - 0: have symbol tell whether it is local, extern or global
2045 * 1: assume all symbols in set to be global
2046 * 2: assume all symbols in set to be extern
2049 emitSymbolSet(set *s, int type)
2053 unsigned sectionNr = 0;
2055 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2057 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2058 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2061 if (sym->etype && SPEC_ABSA(sym->etype)
2062 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
2065 // handle config words
2066 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2067 (int)list2int(sym->ival));
2068 pic14_stringInSet(sym->rname, &emitted, 1);
2072 if (sym->isstrlit) {
2073 // special case: string literals
2074 emitInitVal(ivalBuf, sym, sym->type, NULL);
2078 if (type != 0 || sym->cdef
2079 || (!IS_STATIC(sym->etype)
2082 // bail out for ___fsadd and friends
2083 if (sym->cdef && !sym->used) continue;
2085 /* export or import non-static globals */
2086 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2088 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2090 /* do not add to emitted set, it might occur again! */
2091 //if (!sym->used) continue;
2093 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2096 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2097 if (!sym->ival && !IS_FUNC(sym->type)) {
2098 // also define symbol
2099 if (IS_ABSOLUTE(sym->etype)) {
2100 // absolute location?
2101 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2102 // deferred to pic14_constructAbsMap
2104 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2105 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2109 pic14_stringInSet(sym->rname, &emitted, 1);
2113 //if (list) showInitList(list, 0);
2115 resolveIvalSym( list, sym->type );
2116 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2117 dbuf_printf (ivalBuf, "\n");
2123 * Iterate over all memmaps and emit their contents (attributes, symbols).
2126 showAllMemmaps(FILE *of)
2128 struct dbuf_s locBuf;
2130 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2131 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2132 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2136 DEBUGprintf ("---begin memmaps---\n");
2137 if (!extBuf) extBuf = dbuf_new(1024);
2138 if (!gloBuf) gloBuf = dbuf_new(1024);
2139 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2140 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2141 dbuf_init(&locBuf, 1024);
2143 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2144 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2145 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2146 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2147 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2149 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2151 //DEBUGprintf ("memmap %i: %p\n", i, map);
2154 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",
2155 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2156 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2157 map->codesp, map->regsp, map->syms);
2159 emitSymbolSet(map->syms, 0);
2162 DEBUGprintf ("---end of memmaps---\n");
2164 emitSymbolSet(publics, 1);
2165 emitSymbolSet(externs, 2);
2167 emitPseudoStack(gloBuf, extBuf);
2168 pic14_constructAbsMap(gloDefBuf, gloBuf);
2169 pic14printLocals (&locBuf);
2170 pic14_emitConfigWord(of); // must be done after all the rest
2172 dbuf_write_and_destroy(extBuf, of);
2173 dbuf_write_and_destroy(gloBuf, of);
2174 dbuf_write_and_destroy(gloDefBuf, of);
2175 dbuf_write_and_destroy(&locBuf, of);
2176 dbuf_write_and_destroy(ivalBuf, of);
2178 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;