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 /* Emit the __config directive */
1469 pic14_emitConfigWord (asmFile);
1471 /* print the global variables in this module */
1472 //pic14printPublics (asmFile);
1474 /* print the extern variables in this module */
1475 //pic14printExterns (asmFile);
1477 /* copy the sfr segment */
1479 fprintf (asmFile, "%s", iComments2);
1480 fprintf (asmFile, "; special function registers\n");
1481 fprintf (asmFile, "%s", iComments2);
1482 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1485 if (udata_section_name) {
1486 sprintf(udata_name,"%s",udata_section_name);
1488 sprintf(udata_name,"data_%s",moduleName);
1490 fprintf (asmFile, "%s", iComments2);
1491 fprintf (asmFile, "; udata\n");
1492 fprintf (asmFile, "%s", iComments2);
1493 fprintf (asmFile, "%s\tudata\n", udata_name);
1494 dbuf_write_and_destroy(&data->oBuf, asmFile);
1497 /* Put all variables into a cblock */
1500 /* emit initialized data */
1501 showAllMemmaps(asmFile);
1503 /* print the locally defined variables in this module */
1504 writeUsedRegs(asmFile);
1506 /* create the overlay segments */
1507 fprintf (asmFile, "%s", iComments2);
1508 fprintf (asmFile, "; overlayable items in internal ram \n");
1509 fprintf (asmFile, "%s", iComments2);
1510 dbuf_write_and_destroy (&ovrBuf, asmFile);
1514 /* create the stack segment MOF */
1515 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1516 fprintf (asmFile, "%s", iComments2);
1517 fprintf (asmFile, "; Stack segment in internal ram \n");
1518 fprintf (asmFile, "%s", iComments2);
1519 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1520 ";__start__stack:\n;\t.ds\t1\n\n");
1523 /* create the idata segment */
1524 fprintf (asmFile, "%s", iComments2);
1525 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1526 fprintf (asmFile, "%s", iComments2);
1527 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1529 /* if external stack then reserve space of it */
1530 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1531 fprintf (asmFile, "%s", iComments2);
1532 fprintf (asmFile, "; external stack \n");
1533 fprintf (asmFile, "%s", iComments2);
1534 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1535 fprintf (asmFile,";\t.ds 256\n");
1538 /* copy xtern ram data */
1539 fprintf (asmFile, "%s", iComments2);
1540 fprintf (asmFile, "; external ram data\n");
1541 fprintf (asmFile, "%s", iComments2);
1542 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1546 /* copy the bit segment */
1548 fprintf (asmFile, "%s", iComments2);
1549 fprintf (asmFile, "; bit data\n");
1550 fprintf (asmFile, "%s", iComments2);
1551 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1554 /* copy the interrupt vector table */
1555 if (mainf && IFFUNC_HASBODY(mainf->type))
1556 dbuf_write_and_destroy (&vBuf, asmFile);
1558 dbuf_destroy(&vBuf);
1560 /* create interupt ventor handler */
1561 pic14_emitInterruptHandler (asmFile);
1563 /* copy over code */
1564 fprintf (asmFile, "%s", iComments2);
1565 fprintf (asmFile, "; code\n");
1566 fprintf (asmFile, "%s", iComments2);
1567 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1570 copypCode(asmFile, 'X');
1572 /* _main function */
1573 copypCode(asmFile, 'M');
1575 /* other functions */
1576 copypCode(asmFile, code->dbName);
1579 copypCode(asmFile, 'P');
1581 dumppCodeStatistics (asmFile);
1583 fprintf (asmFile,"\tend\n");
1589 * Deal with initializers.
1594 #define DEBUGprintf printf
1597 #define DEBUGprintf 1 ? (void)0 : (void)printf
1601 void ast_print (ast * tree, FILE *outfile, int indent);
1608 showInitList(initList *list, int level)
1610 static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1611 static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1614 printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1615 if (list->type == INIT_DEEP) {
1616 showInitList(list->init.deep, level + 1);
1617 } else if (list->type == INIT_NODE) {
1618 ast = list->init.node;
1619 printf (" type %u (%s), level %d, block %d, seqPoint %d\n",
1620 ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1621 if (ast->type == EX_VALUE) {
1622 printf (" VAL %lf\n", floatFromVal(ast->opval.val));
1623 } else if (ast->type == EX_LINK) {
1624 printTypeChain(ast->opval.lnk, NULL);
1625 } else if (ast->type == EX_OP) {
1626 printf (" OP %u\n", ast->opval.op);
1635 * DEBUG: Print a value.
1638 printVal(value *val)
1640 printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1641 val, val->name, val->type, val->etype,
1642 val->sym ? val->sym->name : NULL, val->vArgs,
1643 (long)floatFromVal(val), (long)floatFromVal(val));
1644 printTypeChain(val->type, stdout);
1646 printTypeChain(val->etype, stdout);
1650 //prototype from ../SDCCicode.c
1651 operand *operandFromAst (ast * tree,int lvl);
1654 parseIvalAst (ast *node, int *inCodeSpace) {
1656 char *buffer = NULL;
1659 if (IS_AST_VALUE(node)) {
1660 value *val = AST_VALUE(node);
1661 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1662 if (inCodeSpace && val->type
1663 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1667 if (inCodeSpace && sym
1668 && (IS_FUNC(sym->type)
1669 || IS_CODE(getSpec(sym->type))))
1674 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1675 if (IS_AST_LIT_VALUE(node)) {
1676 buffer = Safe_alloc(LEN);
1677 SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node));
1678 } else if (IS_AST_SYM_VALUE(node)) {
1679 assert ( AST_SYMBOL(node) );
1681 printf ("sym %s: ", AST_SYMBOL(node)->rname);
1682 printTypeChain(AST_SYMBOL(node)->type, stdout);
1683 printTypeChain(AST_SYMBOL(node)->etype, stdout);
1684 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1686 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1688 assert ( !"Invalid values type for initializers in AST." );
1690 } else if (IS_AST_OP(node)) {
1691 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1692 switch (node->opval.op) {
1694 assert (node->right);
1695 buffer = parseIvalAst(node->right, inCodeSpace);
1696 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1699 assert ( node->left && !node->right );
1700 buffer = parseIvalAst(node->left, inCodeSpace);
1701 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1704 assert (node->left && node->right );
1705 left = parseIvalAst(node->left, inCodeSpace);
1706 right = parseIvalAst(node->right, inCodeSpace);
1707 buffer = Safe_alloc(LEN);
1708 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1709 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1714 assert ( node->left && node->right );
1715 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1716 right = parseIvalAst(node->right, inCodeSpace);
1717 buffer = Safe_alloc(LEN);
1718 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1719 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1721 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1724 assert ( !"Unhandled operation in initializer." );
1728 assert ( !"Invalid construct in initializer." );
1735 * Emit the section preamble, absolute location (if any) and
1736 * symbol name(s) for intialized data.
1739 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1742 static int in_code = 0;
1743 static int sectionNr = 0;
1746 // code or data space?
1747 if (IS_CODE(getSpec(sym->type))) {
1754 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1755 if (SPEC_ABSA(getSpec(sym->type))) {
1756 // specify address for absolute symbols
1757 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1759 dbuf_printf(oBuf, "\n%s\n", sym->rname);
1761 addSet(&emitted, sym->rname);
1766 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1768 * Actually emit the initial values in .asm format.
1771 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1777 int inCodeSpace = 0;
1781 assert (size <= sizeof(long));
1782 assert (!list || (list->type == INIT_NODE));
1783 node = list ? list->init.node : NULL;
1785 in_code = emitIvalLabel(oBuf, sym);
1786 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1789 // initialize as zero
1790 for (i=0; i < size; i++) {
1792 dbuf_printf (oBuf, "\tretlw 0x00");
1794 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1797 dbuf_printf (oBuf, "\n");
1802 if (constExprTree(node) && (val = constExprValue(node, 0))) {
1803 op = operandFromValue(val);
1804 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1806 } else if (IS_AST_VALUE(node)) {
1807 op = operandFromAst(node, 0);
1808 } else if (IS_AST_OP(node)) {
1809 str = parseIvalAst(node, &inCodeSpace);
1810 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1813 assert ( !"Unhandled construct in intializer." );
1819 //printOperand(op, of);
1822 for (i=0; i < size; i++) {
1823 char *text = op ? aopGet(AOP(op), i, 0, 0)
1824 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1826 dbuf_printf (oBuf, "\tretlw %s\n", text);
1828 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1831 dbuf_printf (oBuf, "\n");
1835 * For UNIONs, we first have to find the correct alternative to map the
1836 * initializer to. This function maps the structure of the initializer to
1837 * the UNION members recursively.
1838 * Returns the type of the first `fitting' member.
1841 matchIvalToUnion (initList *list, sym_link *type, int size)
1847 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1850 if (!list || (list->type == INIT_NODE)) {
1851 DEBUGprintf ("OK, simple type\n");
1854 DEBUGprintf ("ERROR, simple type\n");
1857 } else if (IS_BITFIELD(type)) {
1858 if (!list || (list->type == INIT_NODE)) {
1859 DEBUGprintf ("OK, bitfield\n");
1862 DEBUGprintf ("ERROR, bitfield\n");
1865 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1866 if (!list || (list->type == INIT_DEEP)) {
1867 if (list) list = list->init.deep;
1868 sym = SPEC_STRUCT(type)->fields;
1870 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1871 if (!matchIvalToUnion(list, sym->type, 0)) {
1872 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1875 if (list) list = list->next;
1879 // excess initializers?
1881 DEBUGprintf ("ERROR, excess initializers\n");
1885 DEBUGprintf ("OK, struct\n");
1889 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1890 if (!list || (list->type == INIT_DEEP)) {
1891 if (list) list = list->init.deep;
1892 sym = SPEC_STRUCT(type)->fields;
1894 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1895 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1896 && matchIvalToUnion(list, sym->type, size))
1898 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1905 DEBUGprintf ("ERROR, no match found.\n");
1908 assert ( !"Unhandled type in UNION." );
1911 assert ( !"No match found in UNION for the given initializer structure." );
1916 * Parse the type and its initializer and emit it (recursively).
1919 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1926 size = getSize(my_type);
1928 if (IS_PTR(my_type)) {
1929 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1930 emitIvals(oBuf, topsym, list, 0, size);
1934 if (IS_ARRAY(my_type) && topsym->isstrlit) {
1935 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1936 emitIvalLabel(oBuf, topsym);
1938 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1943 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1944 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1945 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1949 if (IS_ARRAY(my_type)) {
1950 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1951 assert (!list || list->type == INIT_DEEP);
1952 if (list) list = list->init.deep;
1953 for (i = 0; i < DCL_ELEM(my_type); i++) {
1954 emitInitVal(oBuf, topsym, my_type->next, list);
1956 if (list) list = list->next;
1961 if (IS_FLOAT(my_type)) {
1963 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1964 emitIvals(oBuf, topsym, list, 0, size);
1968 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1969 // integral type, 8, 16, or 32 bit
1970 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1971 emitIvals(oBuf, topsym, list, 0, size);
1974 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1976 DEBUGprintf ("(struct, %d byte) handled below\n", size);
1977 assert (!list || (list->type == INIT_DEEP));
1979 // iterate over struct members and initList
1980 if (list) list = list->init.deep;
1981 sym = SPEC_STRUCT(my_type)->fields;
1985 if (IS_BITFIELD(sym->type)) {
1986 while (sym && IS_BITFIELD(sym->type)) {
1987 assert (!list || ((list->type == INIT_NODE)
1988 && IS_AST_LIT_VALUE(list->init.node)));
1989 lit = list ? list2int(list) : 0;
1990 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1991 lit, SPEC_BLEN(getSpec(sym->type)),
1992 SPEC_BSTR(getSpec(sym->type)), bitfield);
1993 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1994 len += SPEC_BLEN(getSpec(sym->type));
1997 if (list) list = list->next;
1999 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
2000 len = (len + 7) & ~0x07; // round up to full bytes
2001 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2006 emitInitVal(oBuf, topsym, sym->type, list);
2009 if (list) list = list->next;
2013 assert ( !"Excess initializers." );
2017 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2019 DEBUGprintf ("(union, %d byte) handled below\n", size);
2020 assert (list && list->type == INIT_DEEP);
2022 // iterate over union members and initList, try to map number and type of fields and initializers
2023 my_type = matchIvalToUnion(list, my_type, size);
2025 emitInitVal(oBuf, topsym, my_type, list->init.deep);
2027 size -= getSize(my_type);
2029 // pad with (leading) zeros
2030 emitIvals(oBuf, NULL, NULL, 0, size);
2035 assert ( !"No UNION member matches the initializer structure.");
2036 } else if (IS_BITFIELD(my_type)) {
2037 assert ( !"bitfields should only occur in structs..." );
2040 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2041 assert( !"Unhandled initialized type.");
2046 * Emit a set of symbols.
2047 * type - 0: have symbol tell whether it is local, extern or global
2048 * 1: assume all symbols in set to be global
2049 * 2: assume all symbols in set to be extern
2052 emitSymbolSet(set *s, int type)
2056 unsigned sectionNr = 0;
2058 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2060 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2061 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2064 if (sym->isstrlit) {
2065 // special case: string literals
2066 emitInitVal(ivalBuf, sym, sym->type, NULL);
2070 if (type != 0 || sym->cdef
2071 || (!IS_STATIC(sym->etype)
2074 // bail out for ___fsadd and friends
2075 if (sym->cdef && !sym->used) continue;
2077 /* export or import non-static globals */
2078 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2080 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2082 /* do not add to emitted set, it might occur again! */
2083 //if (!sym->used) continue;
2085 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2088 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2089 if (!sym->ival && !IS_FUNC(sym->type)) {
2090 // also define symbol
2091 if (IS_ABSOLUTE(sym->etype)) {
2092 // absolute location?
2093 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2094 // deferred to pic14_constructAbsMap
2096 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2097 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2101 pic14_stringInSet(sym->rname, &emitted, 1);
2105 //if (list) showInitList(list, 0);
2107 resolveIvalSym( list, sym->type );
2108 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2109 dbuf_printf (ivalBuf, "\n");
2115 * Iterate over all memmaps and emit their contents (attributes, symbols).
2118 showAllMemmaps(FILE *of)
2120 struct dbuf_s locBuf;
2122 xstack, istack, code, data, pdata, xdata, xidata, xinit,
2123 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2124 sfr, sfrbit, reg, generic, overlay, eeprom, home };
2128 DEBUGprintf ("---begin memmaps---\n");
2129 if (!extBuf) extBuf = dbuf_new(1024);
2130 if (!gloBuf) gloBuf = dbuf_new(1024);
2131 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2132 if (!ivalBuf) ivalBuf = dbuf_new(1024);
2133 dbuf_init(&locBuf, 1024);
2135 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2136 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2137 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2138 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2139 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2141 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2143 //DEBUGprintf ("memmap %i: %p\n", i, map);
2146 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",
2147 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2148 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2149 map->codesp, map->regsp, map->syms);
2151 emitSymbolSet(map->syms, 0);
2154 DEBUGprintf ("---end of memmaps---\n");
2156 emitSymbolSet(publics, 1);
2157 emitSymbolSet(externs, 2);
2159 emitPseudoStack(gloBuf, extBuf);
2160 pic14_constructAbsMap(gloDefBuf, gloBuf);
2162 pic14printLocals (&locBuf);
2164 dbuf_write_and_destroy(extBuf, of);
2165 dbuf_write_and_destroy(gloBuf, of);
2166 dbuf_write_and_destroy(gloDefBuf, of);
2167 dbuf_write_and_destroy(&locBuf, of);
2168 dbuf_write_and_destroy(ivalBuf, of);
2170 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;