* src/z80/gen.c (_vemit2): suppress compiler warning
[fw/sdcc] / src / pic / glue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
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
9    later version.
10
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.
15
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.
19
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 -------------------------------------------------------------------------*/
24
25 #include "glue.h"
26 #include "dbuf_string.h"
27
28 #include "device.h"
29 #include "gen.h"
30 #include "main.h"
31
32 /*
33  * Imports
34  */
35 extern set *publics;
36 extern set *externs;
37 extern symbol *mainf;
38 extern struct dbuf_s *codeOutBuf;
39
40 extern DEFSETFUNC(closeTmpFiles);
41 extern DEFSETFUNC(rmTmpFiles);
42 extern void initialComments(FILE *afile);
43 extern operand *operandFromAst(ast *tree, int lvl);
44 extern value *initPointer(initList *ilist, sym_link *toType);
45
46
47 set *pic14_localFunctions = NULL;
48 int pic14_hasInterrupt = 0;             // Indicates whether to emit interrupt handler or not
49
50 int pic14_stringInSet(const char *str, set **world, int autoAdd);
51
52
53 #ifdef WORDS_BIGENDIAN
54 #define _ENDIAN(x)  (3-x)
55 #else
56 #define _ENDIAN(x)  (x)
57 #endif
58
59 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
60 #define IS_GLOBAL(sym)  ((sym)->level == 0)
61 #define IS_DEFINED_HERE(sym)    (!IS_EXTERN(sym->etype))
62
63 /* dbufs for initialized data (idata and code sections),
64  * extern, and global declarations */
65 static struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
66
67 static set *emitted = NULL;
68
69 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
70
71 #if 0
72 static int
73 is_valid_identifier( const char *name )
74 {
75   char a;
76   if (!name) return 0;
77   a = *name;
78
79   /* only accept [a-zA-Z_][a-zA-Z0-9_] */
80   if (!((a >= 'a' && a <= 'z')
81         || (a >= 'A' && a <= 'z')
82         || (a == '_')))
83     return 0;
84
85   name++;
86   while ((a = *name++))
87   {
88     if (!((a >= 'a' && a <= 'z')
89         || (a >= 'A' && a <= 'Z')
90         || (a >= '0' && a <= '9')
91         || (a == '_')))
92       return 0;
93   } // while
94
95   /* valid identifier */
96   return 1;
97 }
98 #endif
99
100 static void
101 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
102 {
103     int shared, low, high, size, i;
104     PIC_device *pic;
105
106     /* also emit STK symbols
107      * XXX: This is ugly and fails as soon as devices start to get
108      *      differently sized sharebanks, since STK12 will be
109      *      required by larger devices but only up to STK03 might
110      *      be defined using smaller devices. */
111     shared = pic14_getSharedStack(&low, &high, &size);
112     if (!pic14_options.isLibrarySource)
113     {
114         pic = pic14_getPIC();
115
116         dbuf_printf (oBuf, "\n");
117         dbuf_printf (oBuf, "\tglobal PSAVE\n");
118         dbuf_printf (oBuf, "\tglobal SSAVE\n");
119         dbuf_printf (oBuf, "\tglobal WSAVE\n");
120         for (i = size - 4; i >= 0; i--) {
121             dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
122         } // for i
123         dbuf_printf (oBuf, "\n");
124
125         // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
126         // banks, sigh...
127         if (1 || !shared) {
128             // for single banked devices: use normal, "banked" RAM
129             dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
130         } else {
131             // for devices with at least two banks, require a sharebank section
132             dbuf_printf (oBuf, "sharebank udata_shr\n");
133         }
134         dbuf_printf (oBuf, "PSAVE\tres 1\n");
135         dbuf_printf (oBuf, "SSAVE\tres 1\n");
136         dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
137         /* fill rest of sharebank with stack STKxx .. STK00 */
138         for (i = size - 4; i >= 0; i--) {
139             dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
140         } // for i
141     } else {
142         /* declare STKxx as extern for all files
143          * except the one containing main() */
144         dbuf_printf (oBufExt, "\n");
145         dbuf_printf (oBufExt, "\textern PSAVE\n");
146         dbuf_printf (oBufExt, "\textern SSAVE\n");
147         dbuf_printf (oBufExt, "\textern WSAVE\n");
148         for (i = size - 4; i >= 0; i--) {
149             char buffer[128];
150             SNPRINTF(&buffer[0], 127, "STK%02d", i);
151             dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
152             pic14_stringInSet(&buffer[0], &emitted, 1);
153         } // for i
154     }
155     dbuf_printf (oBuf, "\n");
156 }
157
158 static int
159 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
160         const char *name)
161 {
162     int wasPresent = pic14_stringInSet(name, emitted, 1);
163
164     if (!wasPresent) {
165         dbuf_printf (oBuf, fmt, name);
166     } // if
167     return (!wasPresent);
168 }
169
170 static void
171 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
172 {
173   memmap *maps[] = { data, sfr, NULL };
174   int i;
175   hTab *ht = NULL;
176   symbol *sym;
177   set *aliases;
178   int addr, min=-1, max=-1;
179   int size;
180
181   for (i=0; maps[i] != NULL; i++)
182   {
183     for (sym = (symbol *)setFirstItem (maps[i]->syms);
184         sym; sym = setNextItem (maps[i]->syms))
185     {
186       if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
187       {
188         addr = SPEC_ADDR(sym->etype);
189
190         /* handle CONFIG words here */
191         if (IS_CONFIG_ADDRESS( addr ))
192         {
193           //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
194           //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
195           if (sym->ival) {
196             pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
197           } else {
198             fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
199           }
200           continue;
201         }
202
203         if (max == -1 || addr > max) max = addr;
204         if (min == -1 || addr < min) min = addr;
205         //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
206         aliases = hTabItemWithKey (ht, addr);
207         if (aliases) {
208           /* May not use addSetHead, as we cannot update the
209            * list's head in the hastable `ht'. */
210           addSet (&aliases, sym);
211 #if 0
212           fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
213               __FUNCTION__, elementsInSet(aliases), sym->name, addr);
214 #endif
215         } else {
216           addSet (&aliases, sym);
217           hTabAddItem (&ht, addr, aliases);
218         } // if
219       } // if
220     } // for sym
221   } // for i
222
223   /* now emit definitions for all absolute symbols */
224   dbuf_printf (oBuf, "%s", iComments2);
225   dbuf_printf (oBuf, "; absolute symbol definitions\n");
226   dbuf_printf (oBuf, "%s", iComments2);
227   for (addr=min; addr <= max; addr++)
228   {
229     size = 1;
230     aliases = hTabItemWithKey (ht, addr);
231     if (aliases && elementsInSet(aliases)) {
232       /* Make sure there is no initialized value at this location! */
233       for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
234           if (sym->ival) break;
235       } // for
236       if (sym) continue;
237
238       dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
239           moduleName, addr, addr);
240       for (sym = setFirstItem (aliases); sym;
241           sym = setNextItem (aliases))
242       {
243         if (getSize(sym->type) > size) {
244           size = getSize(sym->type);
245         }
246
247         /* initialized values are handled somewhere else */
248         if (sym->ival) continue;
249
250         /* emit STATUS as well as _STATUS, required for SFRs only */
251         //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
252         dbuf_printf (oBuf, "%s\n", sym->rname);
253
254         if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
255             //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
256             emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
257         } // if
258       } // for
259       dbuf_printf (oBuf, "\tres\t%d\n", size);
260     } // if
261   } // for i
262 }
263
264 #if 0
265 /*-----------------------------------------------------------------*/
266 /* emitRegularMap - emit code for maps with no special cases       */
267 /*-----------------------------------------------------------------*/
268 static void
269 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
270 {
271         symbol *sym;
272         int bitvars = 0;;
273
274         /* print the area name */
275         if (addPublics)
276                 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
277
278         for (sym = setFirstItem (map->syms); sym;
279         sym = setNextItem (map->syms)) {
280
281                 //printf("%s\n",sym->name);
282
283                 /* ignore if config word */
284                 if (SPEC_ABSA(sym->etype)
285                     && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
286                         continue;
287
288                 /* if extern then add it into the extern list */
289                 if (IS_EXTERN (sym->etype)) {
290                         addSetHead (&externs, sym);
291                         continue;
292                 }
293
294                 /* if allocation required check is needed
295                 then check if the symbol really requires
296                 allocation only for local variables */
297                 if (arFlag && !IS_AGGREGATE (sym->type) &&
298                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
299                         !sym->allocreq && sym->level)
300                         continue;
301
302                 /* if global variable & not static or extern
303                 and addPublics allowed then add it to the public set */
304                 if ((sym->level == 0 ||
305                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
306                         addPublics &&
307                         !IS_STATIC (sym->etype))
308                 {
309                         //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
310                         addSetHead (&publics, sym);
311                 }
312
313                 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
314                 if (sym->_isparm)
315                         continue;
316                         /* if extern then do nothing or is a function
317                 then do nothing */
318                 if (IS_FUNC (sym->type))
319                         continue;
320 #if 0
321                 /* print extra debug info if required */
322                 if (options.debug || sym->level == 0)
323                 {
324                         if (!sym->level)        /* global */
325                                 if (IS_STATIC (sym->etype))
326                                         dbuf_printf (&map->oBuf, "F%s_", moduleName);           /* scope is file */
327                                 else
328                                         dbuf_printf (&map->oBuf, "G_"); /* scope is global */
329                                 else
330                                         /* symbol is local */
331                                         dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
332                                 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
333                 }
334 #endif
335                 /* absolute symbols are handled in pic14_constructAbsMap */
336                 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
337                         continue;
338
339                 /* if it has an absolute address then generate
340                 an equate for this no need to allocate space */
341                 if (0 && SPEC_ABSA (sym->etype))
342                 {
343                         //if (options.debug || sym->level == 0)
344                         //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
345
346                         dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
347                                 sym->rname,
348                                 SPEC_ADDR (sym->etype));
349                 }
350                 else
351                 {
352                         /* allocate space */
353
354                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
355                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
356                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
357                         if (IS_BITVAR (sym->etype))
358                         {
359                                 bitvars++;
360                         }
361                         else
362                         {
363                             if (!sym->ival) {
364                                 emitSymbol (&map->oBuf,
365                                         sym->rname,
366                                         NULL,
367                                         getSize (sym->type) & 0xffff,
368                                         SPEC_ABSA(sym->etype)
369                                                 ? SPEC_ADDR(sym->etype)
370                                                 : -1,
371                                         0,
372                                         0);
373                             }
374                                 /*
375                                 {
376                                 int i, size;
377
378                                   if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
379                                   {
380                                   for (i = 1; i < size; i++)
381                                   dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
382                                   }
383                                   }
384                                 */
385                         }
386                         //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
387                 }
388
389                 /* if it has a initial value then do it only if
390                 it is a global variable */
391                 if (sym->ival) {
392                     /* mark symbol as already defined */
393                     pic14_stringInSet(sym->name, &emitted, 1);
394                     pic14_stringInSet(sym->rname, &emitted, 1);
395                 }
396 #if 0
397                 /* if it has a initial value then do it only if
398                 it is a global variable */
399                 if (sym->ival && sym->level == 0) {
400                         ast *ival = NULL;
401
402                         if (IS_AGGREGATE (sym->type))
403                                 ival = initAggregates (sym, sym->ival, NULL);
404                         else
405                                 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
406                                 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
407                         codeOutBuf = &statsg->oBuf;
408                         GcurMemmap = statsg;
409                         eBBlockFromiCode (iCodeFromAst (ival));
410                         sym->ival = NULL;
411                 }
412 #endif
413         }
414 }
415 #endif
416
417
418 #if 0
419 /*-----------------------------------------------------------------*/
420 /* printIvalType - generates ival for int/char                     */
421 /*-----------------------------------------------------------------*/
422 static void
423 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
424 {
425         value *val;
426         unsigned long ulval;
427
428         //fprintf(stderr, "%s\n",__FUNCTION__);
429
430         /* if initList is deep */
431         if (ilist->type == INIT_DEEP)
432                 ilist = ilist->init.deep;
433
434         if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
435                 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
436         }
437
438         if (!(val = list2val (ilist))) {
439                 // assuming a warning has been thrown
440                 val = constCharVal (0);
441         }
442
443         if (val->type != type) {
444                 val = valCastLiteral(type, floatFromVal(val));
445         }
446
447         if(val)
448                 ulval = ulFromVal (val);
449         else
450                 ulval =0;
451
452         switch (getSize (type)) {
453         case 1:
454                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
455                 break;
456
457         case 2:
458                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
459                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
460                 break;
461
462         case 4:
463                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
464                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
465                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
466                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
467                 break;
468         }
469 }
470
471 /*-----------------------------------------------------------------*/
472 /* printIvalBitFields - generate initializer for bitfields         */
473 /*-----------------------------------------------------------------*/
474 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
475 {
476         value *val ;
477         symbol *lsym = *sym;
478         initList *lilist = *ilist ;
479         unsigned long ival = 0;
480         int size =0;
481
482
483         do {
484                 unsigned long i;
485                 val = list2val(lilist);
486                 if (size) {
487                         if (SPEC_BLEN(lsym->etype) > 8) {
488                                 size += ((SPEC_BLEN (lsym->etype) / 8) +
489                                         (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
490                         }
491                 } else {
492                         size = ((SPEC_BLEN (lsym->etype) / 8) +
493                                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
494                 }
495                 i = ulFromVal (val);
496                 i <<= SPEC_BSTR (lsym->etype);
497                 ival |= i;
498                 if (! ( lsym->next &&
499                         (IS_BITFIELD(lsym->next->type)) &&
500                         (SPEC_BSTR(lsym->next->etype)))) break;
501                 lsym = lsym->next;
502                 lilist = lilist->next;
503         } while (1);
504         switch (size) {
505         case 1:
506                 //tfprintf (oFile, "\t!db !constbyte\n",ival);
507                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
508                 break;
509
510         case 2:
511                 //tfprintf (oFile, "\t!dw !constword\n",ival);
512                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
513                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
514                 break;
515         case 4:
516                 //tfprintf (oFile, "\t!db  !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
517                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
518                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
519                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
520                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
521                 break;
522         }
523         *sym = lsym;
524         *ilist = lilist;
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* printIvalStruct - generates initial value for structures        */
529 /*-----------------------------------------------------------------*/
530 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
531 {
532         symbol *sflds;
533         initList *iloop = NULL;
534
535         sflds = SPEC_STRUCT (type)->fields;
536
537         if (ilist) {
538                 if (ilist->type != INIT_DEEP) {
539                         werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
540                         return;
541                 }
542
543                 iloop = ilist->init.deep;
544         }
545
546         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
547                 if (IS_BITFIELD(sflds->type)) {
548                         printIvalBitFields(&sflds,&iloop,pb);
549                 } else {
550                         printIval (sym, sflds->type, iloop, pb);
551                 }
552         }
553         if (iloop) {
554                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
555         }
556         return;
557 }
558
559 /*-----------------------------------------------------------------*/
560 /* printIvalChar - generates initital value for character array    */
561 /*-----------------------------------------------------------------*/
562 static int
563 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
564 {
565         value *val;
566         int remain, ilen;
567
568         if(!pb)
569                 return 0;
570
571         //fprintf(stderr, "%s\n",__FUNCTION__);
572         if (!s)
573         {
574
575                 val = list2val (ilist);
576
577                 /* if the value is a character string  */
578                 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
579                 {
580                         ilen = DCL_ELEM(val->type);
581
582                         if (!DCL_ELEM (type))
583                                 DCL_ELEM (type) = ilen;
584
585                         /* emit string constant */
586                         for (remain = 0; remain < ilen; remain++) {
587                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
588                         }
589
590                         /* fill array up to desired size */
591                         if ((remain = (DCL_ELEM (type) - ilen)) > 0)
592                                 while (remain--)
593                                         //tfprintf (oFile, "\t!db !constbyte\n", 0);
594                                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
595                                 return 1;
596                 }
597                 else
598                         return 0;
599         }
600         else {
601                 //printChar (oFile, s, strlen (s) + 1);
602
603                 for(remain=0; remain<(int)strlen(s); remain++) {
604                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
605                         //fprintf(stderr,"0x%02x ",s[remain]);
606                 }
607                 //fprintf(stderr,"\n");
608         }
609         return 1;
610 }
611
612 /*-----------------------------------------------------------------*/
613 /* printIvalArray - generates code for array initialization        */
614 /*-----------------------------------------------------------------*/
615 static void
616 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
617                                 pBlock *pb)
618 {
619         initList *iloop;
620         unsigned size = 0;
621
622         if(!pb)
623                 return;
624         if (ilist) {
625                 /* take care of the special   case  */
626                 /* array of characters can be init  */
627                 /* by a string                      */
628                 if (IS_CHAR (type->next)) {
629                         //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
630                         if (!IS_LITERAL(list2val(ilist)->etype)) {
631                                 werror (W_INIT_WRONG);
632                                 return;
633                         }
634                         if (printIvalChar (type,
635                                 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
636                                 pb, SPEC_CVAL (sym->etype).v_char))
637                                 return;
638                 }
639                 /* not the special case */
640                 if (ilist->type != INIT_DEEP) {
641                         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
642                         return;
643                 }
644
645                 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
646                         if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
647                                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
648                                 break;
649                         }
650                         printIval (sym, type->next, iloop, pb);
651                 }
652         }
653
654         if (DCL_ELEM(type)) {
655                 // pad with zeros if needed
656                 if (size<DCL_ELEM(type)) {
657                         size = (DCL_ELEM(type) - size) * getSize(type->next);
658                         while (size--) {
659                                 //tfprintf (oFile, "\t!db !constbyte\n", 0);
660                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
661                         }
662                 }
663         } else {
664                 // we have not been given a size, but we now know it
665                 DCL_ELEM (type) = size;
666         }
667
668         return;
669 }
670
671 /*-----------------------------------------------------------------*/
672 /* printIvalPtr - generates code for initial value of pointers     */
673 /*-----------------------------------------------------------------*/
674 static void
675 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
676 {
677         value *val;
678
679         if (!ilist || !pb)
680                 return;
681
682         fprintf (stderr, "FIXME: initializers for pointers...\n");
683         printTypeChain (type, stderr);
684
685         fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
686         fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
687
688         if (ilist && (ilist->type == INIT_DEEP))
689           ilist = ilist->init.deep;
690
691         /* function pointers */
692         if (IS_FUNC (type->next))
693         {
694                 assert ( !"function pointers not yet handled" );
695                 //printIvalFuncPtr (type, ilist, pb);
696         }
697
698         if (!(val = initPointer (ilist, type)))
699                 return;
700
701         if (IS_CHAR (type->next))
702         {
703                 if (printIvalChar (type, ilist, pb, NULL)) return;
704         }
705
706         /* check the type */
707         if (compareType (type, val->type) == 0)
708         {
709                 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
710                 printFromToType (val->type, type);
711         }
712
713         if (IS_LITERAL (val->etype))
714         {
715                 switch (getSize (type))
716                 {
717                 case 1:
718                         fprintf (stderr, "BYTE: %i\n", (unsigned char) ulFromVal (val) & 0x00FF);
719                         break;
720                 case 2:
721                         fprintf (stderr, "WORD: %i\n", (unsigned int) ulFromVal (val) & 0x00FFFF);
722                         break;
723                 case 3: /* gneric pointers */
724                         assert ( !"generic pointers not yet handled" );
725                 case 4:
726                         fprintf (stderr, "LONG: %i\n", (unsigned int) ulFromVal (val) & 0x0000FFFFFFFF);
727                         break;
728                 default:
729                         assert ( !"invaild size of value -- aborting" );
730                 } // switch
731
732                 return;
733         } // if (IS_LITERAL)
734
735         /* now handle symbolic values */
736         switch (getSize (type))
737         {
738         case 1:
739                 fprintf (stderr, "BYTE: %s", val->name);
740                 break;
741         case 2:
742                 fprintf (stderr, "WORD: %s", val->name);
743                 break;
744         case 4:
745                 fprintf (stderr, "LONG: %s", val->name);
746                 break;
747         default:
748                 assert ( !"invalid size of (symbolic) value -- aborting" );
749         } // switch
750 }
751
752 /*-----------------------------------------------------------------*/
753 /* printIval - generates code for initial value                    */
754 /*-----------------------------------------------------------------*/
755 static void
756 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
757 {
758         if (!ilist || !pb)
759                 return;
760
761         /* if structure then    */
762         if (IS_STRUCT (type))
763         {
764                 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
765                 printIvalStruct (sym, type, ilist, pb);
766                 return;
767         }
768
769         /* if this is an array   */
770         if (IS_ARRAY (type))
771         {
772                 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
773                 printIvalArray (sym, type, ilist, pb);
774                 return;
775         }
776
777         /* if this is a pointer */
778         if (IS_PTR (type))
779         {
780                 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
781                 printIvalPtr (sym, type, ilist, pb);
782                 return;
783         }
784
785         /* if type is SPECIFIER */
786         if (IS_SPEC (type))
787         {
788                 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
789                 printIvalType (sym, type, ilist, pb);
790                 return;
791         }
792 }
793 #endif
794
795 #if 0
796 /*-----------------------------------------------------------------*/
797 /* emitStaticSeg - emitcode for the static segment                 */
798 /*-----------------------------------------------------------------*/
799 static void
800 pic14emitStaticSeg (memmap * map)
801 {
802         symbol *sym;
803
804         dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
805
806         //fprintf(stderr, "%s\n",__FUNCTION__);
807
808         /* for all variables in this segment do */
809         for (sym = setFirstItem (map->syms); sym;
810         sym = setNextItem (map->syms))
811         {
812                 /* if extern then add it into the extern list */
813                 if (IS_EXTERN (sym->etype)) {
814                         addSetHead (&externs, sym);
815                         continue;
816                 }
817
818                 /* if it is not static add it to the public
819                 table */
820                 if (!IS_STATIC (sym->etype))
821                         addSetHead (&publics, sym);
822
823                 /* print extra debug info if required */
824                 if (options.debug || sym->level == 0)
825                 {
826                         if (!sym->level)
827                         {                       /* global */
828                                 if (IS_STATIC (sym->etype))
829                                         dbuf_printf (&code->oBuf, "F%s_", moduleName);  /* scope is file */
830                                 else
831                                         dbuf_printf (&code->oBuf, "G_");        /* scope is global */
832                         }
833                         else
834                                 /* symbol is local */
835                                 dbuf_printf (&code->oBuf, "L%s_",
836                                 (sym->localof ? sym->localof->name : "-null-"));
837                         dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
838
839                 }
840
841                 /* if it has an absolute address */
842                 if (SPEC_ABSA (sym->etype))
843                 {
844                         if (options.debug || sym->level == 0)
845                                 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
846
847                         dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
848                                 sym->rname,
849                                 SPEC_ADDR (sym->etype));
850                 }
851                 else
852                 {
853                         if (options.debug || sym->level == 0)
854                                 dbuf_printf (&code->oBuf, " == .\n");
855
856                         /* if it has an initial value */
857                         if (sym->ival)
858                         {
859 #if 0
860                                 pBlock *pb;
861
862                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
863                                 noAlloc++;
864                                 resolveIvalSym (sym->ival, sym->type);
865                                 //printIval (sym, sym->type, sym->ival, &code->oBuf);
866                                 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
867                                 addpBlock(pb);
868                                 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
869
870                                 printIval (sym, sym->type, sym->ival, pb);
871                                 noAlloc--;
872 #endif
873                         }
874                         else
875                         {
876
877                                 /* allocate space */
878                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
879                                 /* special case for character strings */
880                                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
881                                         SPEC_CVAL (sym->etype).v_char)
882                                         pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
883                                         /*printChar (code->oFile,
884                                         SPEC_CVAL (sym->etype).v_char,
885                                 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
886                                 else
887                                         dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
888                         }
889                 }
890         }
891
892 }
893 #endif
894
895
896 #if 0
897 /*-----------------------------------------------------------------*/
898 /* emitMaps - emits the code for the data portion the code         */
899 /*-----------------------------------------------------------------*/
900 static void
901 pic14emitMaps ()
902 {
903         pic14_constructAbsMap (&sfr->oBuf);
904         emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
905 /* no special considerations for the following
906         data, idata & bit & xdata */
907         pic14emitRegularMap (data, TRUE, TRUE);
908         pic14emitRegularMap (idata, TRUE, TRUE);
909         pic14emitRegularMap (bit, TRUE, FALSE);
910         pic14emitRegularMap (xdata, TRUE, TRUE);
911         pic14emitRegularMap (sfr, TRUE, FALSE);
912         pic14emitRegularMap (sfrbit, FALSE, FALSE);
913         pic14emitRegularMap (code, TRUE, FALSE);
914         pic14emitStaticSeg (statsg);
915         pic14emitStaticSeg (c_abs);
916 }
917 #endif
918
919 /*-----------------------------------------------------------------*/
920 /* createInterruptVect - creates the interrupt vector              */
921 /*-----------------------------------------------------------------*/
922 static void
923 pic14createInterruptVect (struct dbuf_s * vBuf)
924 {
925         mainf = newSymbol ("main", 0);
926         mainf->block = 0;
927
928         /* only if the main function exists */
929         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
930         {
931                 struct options *op = &options;
932                 if (!(op->cc_only || noAssemble))
933                         //      werror (E_NO_MAIN);
934                         fprintf(stderr,"WARNING: function 'main' undefined\n");
935                 return;
936         }
937
938         /* if the main is only a prototype ie. no body then do nothing */
939         if (!IFFUNC_HASBODY(mainf->type))
940         {
941                 /* if ! compile only then main function should be present */
942                 if (!(options.cc_only || noAssemble))
943                         //      werror (E_NO_MAIN);
944                         fprintf(stderr,"WARNING: function 'main' undefined\n");
945                 return;
946         }
947
948         dbuf_printf (vBuf, "%s", iComments2);
949         dbuf_printf (vBuf, "; reset vector \n");
950         dbuf_printf (vBuf, "%s", iComments2);
951         dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
952         dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
953         dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
954         dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
955         popGetExternal("__sdcc_gsinit_startup", 0);
956 }
957
958
959 /*-----------------------------------------------------------------*/
960 /* initialComments - puts in some initial comments                 */
961 /*-----------------------------------------------------------------*/
962 static void
963 pic14initialComments (FILE * afile)
964 {
965         initialComments (afile);
966         fprintf (afile, "; PIC port for the 14-bit core\n");
967         fprintf (afile, iComments2);
968
969 }
970
971 int
972 pic14_stringInSet(const char *str, set **world, int autoAdd)
973 {
974   char *s;
975
976   if (!str) return 1;
977   assert(world);
978
979   for (s = setFirstItem(*world); s; s = setNextItem(*world))
980   {
981     /* found in set */
982     if (0 == strcmp(s, str)) return 1;
983   }
984
985   /* not found */
986   if (autoAdd) addSet(world, Safe_strdup(str));
987   return 0;
988 }
989
990 #if 0
991 static int
992 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
993 {
994   if (!pic14_stringInSet(sym, &emitted, 1)) {
995     /* sym was not in emittedSymbols */
996     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
997       /* sym is not a locally defined function---avoid bug #1443651 */
998       fprintf( file, fmt, sym );
999       return 0;
1000     }
1001   }
1002   return 1;
1003 }
1004 #endif
1005
1006 #if 0
1007 /*-------------------------------------------------------------------*/
1008 /* emitSymbol - write a symbol definition only if it is not    */
1009 /*                    already present                                */
1010 /*-------------------------------------------------------------------*/
1011 static void
1012 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1013 {
1014     static unsigned int sec_idx = 0;
1015
1016     /* workaround: variables declared via `sbit' result in a numeric
1017      * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1018      * sbit is heavily used in the inc2h-generated header files!
1019      */
1020     if (!is_valid_identifier(name))
1021     {
1022         //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1023         return;
1024     }
1025
1026     /* check whether the symbol is already defined */
1027     if (pic14_stringInSet(name, &emitted, 1)) return;
1028
1029     /* new symbol -- define it */
1030     //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1031     if (useEQU) {
1032         dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1033     } else {
1034         /* we place each symbol into a section of its own to allow the linker
1035          * to distribute the data into all available memory banks */
1036         if (!section_type) section_type = "udata";
1037         if (addr != -1)
1038         {
1039             /* absolute symbols are handled in pic14_constructAbsMap */
1040             /* do nothing */
1041         } else {
1042             if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1043             dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1044                     sec_idx++, section_type);
1045             dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1046         }
1047     }
1048 }
1049 #endif
1050
1051
1052 #if 0
1053 /*-----------------------------------------------------------------*/
1054 /* printExterns - generates extern for external variables          */
1055 /*-----------------------------------------------------------------*/
1056 static void
1057 pic14printExterns (FILE * afile)
1058 {
1059         symbol *sym;
1060
1061         fprintf (afile, "%s", iComments2);
1062         fprintf (afile, "; extern variables in this module\n");
1063         fprintf (afile, "%s", iComments2);
1064
1065         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1066                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1067 }
1068
1069 /*-----------------------------------------------------------------*/
1070 /* printPublics - generates .global for publics                    */
1071 /*-----------------------------------------------------------------*/
1072 static void
1073 pic14printPublics (FILE * afile)
1074 {
1075   symbol *sym;
1076
1077   fprintf (afile, "%s", iComments2);
1078   fprintf (afile, "; public variables in this module\n");
1079   fprintf (afile, "%s", iComments2);
1080
1081   for (sym = setFirstItem (publics); sym;
1082       sym = setNextItem (publics)) {
1083
1084     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1085       if (!IS_BITVAR(sym->type))
1086         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1087     } else {
1088       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1089       /* Not any longer! */
1090       //if (!SPEC_ABSA (sym->etype))
1091       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1092     }
1093   }
1094 }
1095 #endif
1096
1097 static void
1098 pic14printLocals (struct dbuf_s *oBuf)
1099 {
1100     set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1101         dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1102     regs *reg;
1103     int i, is_first = 1;
1104     static unsigned sectionNr = 0;
1105
1106     /* emit all registers from all possible sets */
1107     for (i = 0; i < 6; i++) {
1108         if (allregs[i] == NULL) continue;
1109
1110         for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1111             if (reg->isEmitted) continue;
1112
1113             if (reg->wasUsed && !reg->isExtern) {
1114                 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1115                     if (reg->isFixed) {
1116                         // Should not happen, really...
1117                         assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1118                         dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1119                                 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1120                     } else {
1121                         if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1122                             // assign each local register into its own section
1123                             dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1124                                     moduleName, sectionNr++, reg->name, reg->size);
1125                         } else {
1126                             // group all local registers into a single section
1127                             // This should greatly improve BANKSEL generation...
1128                             if (is_first) {
1129                                 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1130                                 is_first = 0;
1131                             }
1132                             dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1133                         }
1134                     }
1135                 }
1136             }
1137             reg->isEmitted = 1;
1138         } // for
1139     } // for
1140 }
1141
1142 /*-----------------------------------------------------------------*/
1143 /* emitOverlay - will emit code for the overlay stuff              */
1144 /*-----------------------------------------------------------------*/
1145 static void
1146 pic14emitOverlay (struct dbuf_s * aBuf)
1147 {
1148         set *ovrset;
1149
1150         /*  if (!elementsInSet (ovrSetSets))*/
1151
1152         /* the hack below, fixes translates for devices which
1153         * only have udata_shr memory */
1154         dbuf_printf (aBuf, "%s\t%s\n",
1155                 (elementsInSet(ovrSetSets)?"":";"),
1156                 port->mem.overlay_name);
1157
1158         /* for each of the sets in the overlay segment do */
1159         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1160         ovrset = setNextItem (ovrSetSets))
1161         {
1162
1163                 symbol *sym;
1164
1165                 if (elementsInSet (ovrset))
1166                 {
1167                 /* this dummy area is used to fool the assembler
1168                 otherwise the assembler will append each of these
1169                 declarations into one chunk and will not overlay
1170                         sad but true */
1171
1172                         /* I don't think this applies to us. We are using gpasm.  CRF */
1173
1174                         dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1175                         /* output the area informtion */
1176                         dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);   /* MOF */
1177                 }
1178
1179                 for (sym = setFirstItem (ovrset); sym;
1180                 sym = setNextItem (ovrset))
1181                 {
1182
1183                         /* if extern then do nothing */
1184                         if (IS_EXTERN (sym->etype))
1185                                 continue;
1186
1187                                 /* if allocation required check is needed
1188                                 then check if the symbol really requires
1189                         allocation only for local variables */
1190                         if (!IS_AGGREGATE (sym->type) &&
1191                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1192                                 && !sym->allocreq && sym->level)
1193                                 continue;
1194
1195                                 /* if global variable & not static or extern
1196                         and addPublics allowed then add it to the public set */
1197                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1198                                 && !IS_STATIC (sym->etype))
1199                                 addSetHead (&publics, sym);
1200
1201                                 /* if extern then do nothing or is a function
1202                         then do nothing */
1203                         if (IS_FUNC (sym->type))
1204                                 continue;
1205
1206                         /* print extra debug info if required */
1207                         if (options.debug || sym->level == 0)
1208                         {
1209                                 if (!sym->level)
1210                                 {               /* global */
1211                                         if (IS_STATIC (sym->etype))
1212                                                 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1213                                         else
1214                                                 dbuf_printf (aBuf, "G_");       /* scope is global */
1215                                 }
1216                                 else
1217                                         /* symbol is local */
1218                                         dbuf_printf (aBuf, "L%s_",
1219                                         (sym->localof ? sym->localof->name : "-null-"));
1220                                 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1221                         }
1222
1223                         /* if is has an absolute address then generate
1224                         an equate for this no need to allocate space */
1225                         if (SPEC_ABSA (sym->etype))
1226                         {
1227
1228                                 if (options.debug || sym->level == 0)
1229                                         dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1230
1231                                 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1232                                         sym->rname,
1233                                         SPEC_ADDR (sym->etype));
1234                         }
1235                         else
1236                         {
1237                                 if (options.debug || sym->level == 0)
1238                                         dbuf_printf (aBuf, "==.\n");
1239
1240                                 /* allocate space */
1241                                 dbuf_printf (aBuf, "%s:\n", sym->rname);
1242                                 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1243                         }
1244
1245                 }
1246         }
1247 }
1248
1249
1250 static void
1251 pic14_emitInterruptHandler (FILE * asmFile)
1252 {
1253         if (pic14_hasInterrupt)
1254         {
1255
1256                 fprintf (asmFile, "%s", iComments2);
1257                 fprintf (asmFile, "; interrupt and initialization code\n");
1258                 fprintf (asmFile, "%s", iComments2);
1259                 // Note - for mplink may have to enlarge section vectors in .lnk file
1260                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1261                 //       source files's code segment (interrupt.c -> code_interrupt)
1262                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1263
1264                 /* interrupt service routine */
1265                 fprintf (asmFile, "__sdcc_interrupt\n");
1266                 copypCode(asmFile, 'I');
1267         }
1268 }
1269
1270 /*-----------------------------------------------------------------*/
1271 /* glue - the final glue that hold the whole thing together        */
1272 /*-----------------------------------------------------------------*/
1273 void
1274 picglue ()
1275 {
1276         FILE *asmFile;
1277         struct dbuf_s ovrBuf;
1278         struct dbuf_s vBuf;
1279
1280         dbuf_init(&ovrBuf, 4096);
1281         dbuf_init(&vBuf, 4096);
1282
1283         pCodeInitRegisters();
1284
1285         /* check for main() */
1286         mainf = newSymbol ("main", 0);
1287         mainf->block = 0;
1288         mainf = findSymWithLevel (SymbolTab, mainf);
1289
1290         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1291         {
1292                 /* main missing -- import stack from main module */
1293                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1294                 pic14_options.isLibrarySource = 1;
1295         }
1296
1297 #if 0
1298         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1299
1300                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1301                 addpBlock(pb);
1302
1303                 /* entry point @ start of CSEG */
1304                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1305                 /* put in the call to main */
1306                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1307
1308                 if (options.mainreturn) {
1309
1310                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1311                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1312
1313                 } else {
1314
1315                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1316                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1317
1318                 }
1319         }
1320 #endif
1321
1322         /* At this point we've got all the code in the form of pCode structures */
1323         /* Now it needs to be rearranged into the order it should be placed in the */
1324         /* code space */
1325
1326         movepBlock2Head('P');              // Last
1327         movepBlock2Head(code->dbName);
1328         movepBlock2Head('X');
1329         movepBlock2Head(statsg->dbName);   // First
1330
1331
1332         /* print the global struct definitions */
1333         if (options.debug)
1334                 cdbStructBlock (0);
1335
1336         /* emit code for the all the variables declared */
1337         //pic14emitMaps ();
1338         /* do the overlay segments */
1339         pic14emitOverlay(&ovrBuf);
1340
1341         /* PENDING: this isnt the best place but it will do */
1342         if (port->general.glue_up_main) {
1343                 /* create the interrupt vector table */
1344                 pic14createInterruptVect (&vBuf);
1345         }
1346
1347         AnalyzepCode('*');
1348
1349         ReuseReg(); // ReuseReg where call tree permits
1350
1351         InlinepCode();
1352
1353         AnalyzepCode('*');
1354
1355         if (options.debug) pcode_test();
1356
1357
1358         /* now put it all together into the assembler file */
1359         /* create the assembler file name */
1360
1361         if ((noAssemble || options.c1mode) && fullDstFileName)
1362         {
1363                 sprintf (buffer, fullDstFileName);
1364         }
1365         else
1366         {
1367                 sprintf (buffer, dstFileName);
1368                 strcat (buffer, ".asm");
1369         }
1370
1371         if (!(asmFile = fopen (buffer, "w"))) {
1372                 werror (E_FILE_OPEN_ERR, buffer);
1373                 exit (1);
1374         }
1375
1376         /* prepare statistics */
1377         resetpCodeStatistics ();
1378
1379         /* initial comments */
1380         pic14initialComments (asmFile);
1381
1382         /* print module name */
1383         fprintf (asmFile, "%s\t.file\t\"%s\"\n",
1384             options.debug ? "" : ";", fullSrcFileName);
1385
1386         /* Let the port generate any global directives, etc. */
1387         if (port->genAssemblerPreamble)
1388         {
1389                 port->genAssemblerPreamble(asmFile);
1390         }
1391
1392         /* print the global variables in this module */
1393         //pic14printPublics (asmFile);
1394
1395         /* print the extern variables in this module */
1396         //pic14printExterns (asmFile);
1397
1398         /* copy the sfr segment */
1399 #if 0
1400         fprintf (asmFile, "%s", iComments2);
1401         fprintf (asmFile, "; special function registers\n");
1402         fprintf (asmFile, "%s", iComments2);
1403         dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1404
1405
1406         if (udata_section_name) {
1407                 sprintf(udata_name,"%s",udata_section_name);
1408         } else {
1409                 sprintf(udata_name,"data_%s",moduleName);
1410         }
1411         fprintf (asmFile, "%s", iComments2);
1412         fprintf (asmFile, "; udata\n");
1413         fprintf (asmFile, "%s", iComments2);
1414         fprintf (asmFile, "%s\tudata\n", udata_name);
1415         dbuf_write_and_destroy(&data->oBuf, asmFile);
1416 #endif
1417
1418         /* Put all variables into a cblock */
1419         AnalyzeBanking();
1420
1421         /* emit initialized data */
1422         showAllMemmaps(asmFile);
1423
1424         /* print the locally defined variables in this module */
1425         writeUsedRegs(asmFile);
1426
1427         /* create the overlay segments */
1428         fprintf (asmFile, "%s", iComments2);
1429         fprintf (asmFile, "; overlayable items in internal ram \n");
1430         fprintf (asmFile, "%s", iComments2);
1431         dbuf_write_and_destroy (&ovrBuf, asmFile);
1432
1433 #if 0
1434
1435         /* create the stack segment MOF */
1436         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1437                 fprintf (asmFile, "%s", iComments2);
1438                 fprintf (asmFile, "; Stack segment in internal ram \n");
1439                 fprintf (asmFile, "%s", iComments2);
1440                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1441                         ";__start__stack:\n;\t.ds\t1\n\n");
1442         }
1443
1444         /* create the idata segment */
1445         fprintf (asmFile, "%s", iComments2);
1446         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1447         fprintf (asmFile, "%s", iComments2);
1448         dbuf_write_and_destroy (&idata->oBuf, asmFile);
1449
1450         /* if external stack then reserve space of it */
1451         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1452                 fprintf (asmFile, "%s", iComments2);
1453                 fprintf (asmFile, "; external stack \n");
1454                 fprintf (asmFile, "%s", iComments2);
1455                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1456                 fprintf (asmFile,";\t.ds 256\n");
1457         }
1458
1459         /* copy xtern ram data */
1460         fprintf (asmFile, "%s", iComments2);
1461         fprintf (asmFile, "; external ram data\n");
1462         fprintf (asmFile, "%s", iComments2);
1463         dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1464
1465 #endif
1466
1467         /* copy the bit segment */
1468 #if 0
1469         fprintf (asmFile, "%s", iComments2);
1470         fprintf (asmFile, "; bit data\n");
1471         fprintf (asmFile, "%s", iComments2);
1472         dbuf_write_and_destroy (&bit->oBuf, asmFile);
1473 #endif
1474
1475         /* copy the interrupt vector table */
1476         if (mainf && IFFUNC_HASBODY(mainf->type))
1477           dbuf_write_and_destroy (&vBuf, asmFile);
1478         else
1479           dbuf_destroy(&vBuf);
1480
1481         /* create interupt ventor handler */
1482         pic14_emitInterruptHandler (asmFile);
1483
1484         /* copy over code */
1485         fprintf (asmFile, "%s", iComments2);
1486         fprintf (asmFile, "; code\n");
1487         fprintf (asmFile, "%s", iComments2);
1488         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1489
1490         /* unknown */
1491         copypCode(asmFile, 'X');
1492
1493         /* _main function */
1494         copypCode(asmFile, 'M');
1495
1496         /* other functions */
1497         copypCode(asmFile, code->dbName);
1498
1499         /* unknown */
1500         copypCode(asmFile, 'P');
1501
1502         dumppCodeStatistics (asmFile);
1503
1504         fprintf (asmFile,"\tend\n");
1505
1506         fclose (asmFile);
1507         pic14_debugLogClose();
1508 }
1509
1510 /*
1511  * Deal with initializers.
1512  */
1513 #undef DEBUGprintf
1514 #if 0
1515 // debugging output
1516 #define DEBUGprintf printf
1517 #else
1518 // be quiet
1519 #define DEBUGprintf 1 ? (void)0 : (void)printf
1520 #endif
1521
1522
1523 #if 0
1524 /*
1525  * Emit all memmaps.
1526  */
1527 static void
1528 showInitList(initList *list, int level)
1529 {
1530     static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1531     static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1532     struct ast *ast;
1533     while (list) {
1534         printf ("      %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1535         if (list->type == INIT_DEEP) {
1536             showInitList(list->init.deep, level + 1);
1537         } else if (list->type == INIT_NODE) {
1538             ast = list->init.node;
1539             printf ("        type %u (%s), level %d, block %d, seqPoint %d\n",
1540                     ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1541             if (ast->type == EX_VALUE) {
1542                 printf ("          VAL %lf\n", floatFromVal(ast->opval.val));
1543             } else if (ast->type == EX_LINK) {
1544                 printTypeChain(ast->opval.lnk, NULL);
1545             } else if (ast->type == EX_OP) {
1546                 printf ("          OP %u\n", ast->opval.op);
1547             }
1548         } // if
1549         list = list->next;
1550     } // while
1551 }
1552 #endif
1553
1554 #if 0
1555 /*
1556  * DEBUG: Print a value.
1557  */
1558 static void
1559 printValue(value *val)
1560 {
1561     printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1562             val, val->name, val->type, val->etype,
1563             val->sym ? val->sym->name : NULL, val->vArgs,
1564             (long) ulFromVal (val), (long) ulFromVal (val));
1565     printTypeChain(val->type, stdout);
1566     printf ("\n");
1567     printTypeChain(val->etype, stdout);
1568     printf ("\n");
1569 }
1570 #endif
1571
1572 static char *
1573 parseIvalAst (ast *node, int *inCodeSpace) {
1574 #define LEN 4096
1575     char *buffer = NULL;
1576     char *left, *right;
1577
1578     if (IS_AST_VALUE(node)) {
1579         value *val = AST_VALUE(node);
1580         symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1581         if (inCodeSpace && val->type
1582                 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1583         {
1584             *inCodeSpace = 1;
1585         }
1586         if (inCodeSpace && sym
1587                 && (IS_FUNC(sym->type)
1588                     || IS_CODE(getSpec(sym->type))))
1589         {
1590             *inCodeSpace = 1;
1591         }
1592
1593         DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1594         if (IS_AST_LIT_VALUE(node)) {
1595             buffer = Safe_alloc(LEN);
1596             SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
1597         } else if (IS_AST_SYM_VALUE(node)) {
1598             assert ( AST_SYMBOL(node) );
1599             /*
1600             printf ("sym %s: ", AST_SYMBOL(node)->rname);
1601             printTypeChain(AST_SYMBOL(node)->type, stdout);
1602             printTypeChain(AST_SYMBOL(node)->etype, stdout);
1603             printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1604             */
1605             buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1606         } else {
1607             assert ( !"Invalid values type for initializers in AST." );
1608         }
1609     } else if (IS_AST_OP(node)) {
1610         DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1611         switch (node->opval.op) {
1612         case CAST:
1613             assert (node->right);
1614             buffer = parseIvalAst(node->right, inCodeSpace);
1615             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1616             break;
1617         case '&':
1618             assert ( node->left && !node->right );
1619             buffer = parseIvalAst(node->left, inCodeSpace);
1620             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1621             break;
1622         case '+':
1623             assert (node->left && node->right );
1624             left = parseIvalAst(node->left, inCodeSpace);
1625             right = parseIvalAst(node->right, inCodeSpace);
1626             buffer = Safe_alloc(LEN);
1627             SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1628             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1629             Safe_free(left);
1630             Safe_free(right);
1631             break;
1632         case '[':
1633             assert ( node->left && node->right );
1634             assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1635             right = parseIvalAst(node->right, inCodeSpace);
1636             buffer = Safe_alloc(LEN);
1637             SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1638                     AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1639             Safe_free(right);
1640             DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1641             break;
1642         default:
1643             assert ( !"Unhandled operation in initializer." );
1644             break;
1645         }
1646     } else {
1647         assert ( !"Invalid construct in initializer." );
1648     }
1649
1650     return (buffer);
1651 }
1652
1653 /*
1654  * Emit the section preamble, absolute location (if any) and
1655  * symbol name(s) for intialized data.
1656  */
1657 static int
1658 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1659 {
1660     char *segname;
1661     static int in_code = 0;
1662     static int sectionNr = 0;
1663
1664     if (sym) {
1665         // code or data space?
1666         if (IS_CODE(getSpec(sym->type))) {
1667             segname = "code";
1668             in_code = 1;
1669         } else {
1670             segname = "idata";
1671             in_code  = 0;
1672         }
1673         dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1674         if (SPEC_ABSA(getSpec(sym->type))) {
1675             // specify address for absolute symbols
1676             dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1677         } // if
1678         dbuf_printf(oBuf, "\n%s\n", sym->rname);
1679
1680         addSet(&emitted, sym->rname);
1681     }
1682     return (in_code);
1683 }
1684
1685 /*
1686  * Actually emit the initial values in .asm format.
1687  */
1688 static void
1689 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1690 {
1691     int i;
1692     ast *node;
1693     operand *op;
1694     value *val = NULL;
1695     int inCodeSpace = 0;
1696     char *str = NULL;
1697     int in_code;
1698
1699     assert (size <= sizeof(long));
1700     assert (!list || (list->type == INIT_NODE));
1701     node = list ? list->init.node : NULL;
1702
1703     in_code = emitIvalLabel(oBuf, sym);
1704     if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1705
1706     if (!node) {
1707         // initialize as zero
1708         for (i=0; i < size; i++) {
1709             if (in_code) {
1710                 dbuf_printf (oBuf, "\tretlw 0x00");
1711             } else {
1712                 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1713             }
1714         } // for
1715         dbuf_printf (oBuf, "\n");
1716         return;
1717     } // if
1718
1719     op = NULL;
1720     if (constExprTree(node) && (val = constExprValue(node, 0))) {
1721         op = operandFromValue(val);
1722         DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1723         //printValue(val);
1724     } else if (IS_AST_VALUE(node)) {
1725         op = operandFromAst(node, 0);
1726     } else if (IS_AST_OP(node)) {
1727         str = parseIvalAst(node, &inCodeSpace);
1728         DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1729         op = NULL;
1730     } else {
1731         assert ( !"Unhandled construct in intializer." );
1732     }
1733
1734     if (op) {
1735         aopOp(op, NULL, 1);
1736         assert(AOP(op));
1737         //printOperand(op, of);
1738     }
1739
1740     for (i=0; i < size; i++) {
1741         char *text;
1742
1743         /*
1744          * FIXME: This is hacky and needs some more thought.
1745          */
1746         if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
1747             /* This branch is introduced to fix #1427663. */
1748             PCOI(AOP(op)->aopu.pcop)->offset+=i;
1749             text = get_op(AOP(op)->aopu.pcop, NULL, 0);
1750             PCOI(AOP(op)->aopu.pcop)->offset-=i;
1751         } else {
1752             text = op ? aopGet(AOP(op), i, 0, 0)
1753             : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1754         } // if
1755         if (in_code) {
1756             dbuf_printf (oBuf, "\tretlw %s\n", text);
1757         } else {
1758             dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1759         }
1760     } // for
1761     dbuf_printf (oBuf, "\n");
1762 }
1763
1764 /*
1765  * For UNIONs, we first have to find the correct alternative to map the
1766  * initializer to. This function maps the structure of the initializer to
1767  * the UNION members recursively.
1768  * Returns the type of the first `fitting' member.
1769  */
1770 static sym_link *
1771 matchIvalToUnion (initList *list, sym_link *type, int size)
1772 {
1773     symbol *sym;
1774
1775     assert (type);
1776
1777     if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1778             || IS_FLOAT(type))
1779     {
1780         if (!list || (list->type == INIT_NODE)) {
1781             DEBUGprintf ("OK, simple type\n");
1782             return (type);
1783         } else {
1784             DEBUGprintf ("ERROR, simple type\n");
1785             return (NULL);
1786         }
1787     } else if (IS_BITFIELD(type)) {
1788         if (!list || (list->type == INIT_NODE)) {
1789             DEBUGprintf ("OK, bitfield\n");
1790             return (type);
1791         } else {
1792             DEBUGprintf ("ERROR, bitfield\n");
1793             return (NULL);
1794         }
1795     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1796         if (!list || (list->type == INIT_DEEP)) {
1797             if (list) list = list->init.deep;
1798             sym = SPEC_STRUCT(type)->fields;
1799             while (sym) {
1800                 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1801                 if (!matchIvalToUnion(list, sym->type, 0)) {
1802                     DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1803                     return (NULL);
1804                 }
1805                 if (list) list = list->next;
1806                 sym = sym->next;
1807             } // while
1808
1809             // excess initializers?
1810             if (list) {
1811                 DEBUGprintf ("ERROR, excess initializers\n");
1812                 return (NULL);
1813             }
1814
1815             DEBUGprintf ("OK, struct\n");
1816             return (type);
1817         }
1818         return (NULL);
1819     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1820         if (!list || (list->type == INIT_DEEP)) {
1821             if (list) list = list->init.deep;
1822             sym = SPEC_STRUCT(type)->fields;
1823             while (sym) {
1824                 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1825                 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1826                         && matchIvalToUnion(list, sym->type, size))
1827                 {
1828                     DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1829                     return (sym->type);
1830                 }
1831                 sym = sym->next;
1832             } // while
1833         } // if
1834         // no match found
1835         DEBUGprintf ("ERROR, no match found.\n");
1836         return (NULL);
1837     } else {
1838         assert ( !"Unhandled type in UNION." );
1839     }
1840
1841     assert ( !"No match found in UNION for the given initializer structure." );
1842     return (NULL);
1843 }
1844
1845 /*
1846  * Parse the type and its initializer and emit it (recursively).
1847  */
1848 static void
1849 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1850 {
1851     symbol *sym;
1852     int size, i;
1853     long lit;
1854     unsigned char *str;
1855
1856     size = getSize(my_type);
1857
1858     if (IS_PTR(my_type)) {
1859         DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1860         emitIvals(oBuf, topsym, list, 0, size);
1861         return;
1862     }
1863
1864     if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
1865         str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1866         emitIvalLabel(oBuf, topsym);
1867         do {
1868             dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1869         } while (*(str++));
1870         return;
1871     }
1872
1873     if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1874         fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1875         assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1876         return;
1877     }
1878
1879     if (IS_ARRAY(my_type)) {
1880         DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1881         assert (!list || list->type == INIT_DEEP);
1882         if (list) list = list->init.deep;
1883         for (i = 0; i < DCL_ELEM(my_type); i++) {
1884             emitInitVal(oBuf, topsym, my_type->next, list);
1885             topsym = NULL;
1886             if (list) list = list->next;
1887         } // for i
1888         return;
1889     }
1890
1891     if (IS_FLOAT(my_type)) {
1892         // float, 32 bit
1893         DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1894         emitIvals(oBuf, topsym, list, 0, size);
1895         return;
1896     }
1897
1898     if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1899         // integral type, 8, 16, or 32 bit
1900         DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1901         emitIvals(oBuf, topsym, list, 0, size);
1902         return;
1903
1904     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1905         // struct
1906         DEBUGprintf ("(struct, %d byte) handled below\n", size);
1907         assert (!list || (list->type == INIT_DEEP));
1908
1909         // iterate over struct members and initList
1910         if (list) list = list->init.deep;
1911         sym = SPEC_STRUCT(my_type)->fields;
1912         while (sym) {
1913             long bitfield = 0;
1914             int len = 0;
1915             if (IS_BITFIELD(sym->type)) {
1916                 while (sym && IS_BITFIELD(sym->type)) {
1917                     assert (!list || ((list->type == INIT_NODE)
1918                                 && IS_AST_LIT_VALUE(list->init.node)));
1919                     lit = (long) (list ? list2int(list) : 0);
1920                     DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1921                             lit, SPEC_BLEN(getSpec(sym->type)),
1922                             SPEC_BSTR(getSpec(sym->type)), bitfield);
1923                     bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1924                     len += SPEC_BLEN(getSpec(sym->type));
1925
1926                     sym = sym->next;
1927                     if (list) list = list->next;
1928                 } // while
1929                 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
1930                 len = (len + 7) & ~0x07; // round up to full bytes
1931                 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
1932                 topsym = NULL;
1933             } // if
1934
1935             if (sym) {
1936                 emitInitVal(oBuf, topsym, sym->type, list);
1937                 topsym = NULL;
1938                 sym = sym->next;
1939                 if (list) list = list->next;
1940             } // if
1941         } // while
1942         if (list) {
1943             assert ( !"Excess initializers." );
1944         } // if
1945         return;
1946
1947     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
1948         // union
1949         DEBUGprintf ("(union, %d byte) handled below\n", size);
1950         assert (list && list->type == INIT_DEEP);
1951
1952         // iterate over union members and initList, try to map number and type of fields and initializers
1953         my_type = matchIvalToUnion(list, my_type, size);
1954         if (my_type) {
1955             emitInitVal(oBuf, topsym, my_type, list->init.deep);
1956             topsym = NULL;
1957             size -= getSize(my_type);
1958             if (size > 0) {
1959                 // pad with (leading) zeros
1960                 emitIvals(oBuf, NULL, NULL, 0, size);
1961             }
1962             return;
1963         } // if
1964
1965         assert ( !"No UNION member matches the initializer structure.");
1966     } else if (IS_BITFIELD(my_type)) {
1967         assert ( !"bitfields should only occur in structs..." );
1968
1969     } else {
1970         printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
1971         assert( !"Unhandled initialized type.");
1972     }
1973 }
1974
1975 /*
1976  * Emit a set of symbols.
1977  * type - 0: have symbol tell whether it is local, extern or global
1978  *        1: assume all symbols in set to be global
1979  *        2: assume all symbols in set to be extern
1980  */
1981 static void
1982 emitSymbolSet(set *s, int type)
1983 {
1984     symbol *sym;
1985     initList *list;
1986     unsigned sectionNr = 0;
1987
1988     for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
1989 #if 0
1990         fprintf (stdout, ";    name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
1991                 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
1992 #endif
1993
1994         if (sym->etype && SPEC_ABSA(sym->etype)
1995                 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
1996                 && sym->ival)
1997         {
1998             // handle config words
1999             pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2000                     (int)list2int(sym->ival));
2001             pic14_stringInSet(sym->rname, &emitted, 1);
2002             continue;
2003         }
2004
2005         if (sym->isstrlit) {
2006             // special case: string literals
2007             emitInitVal(ivalBuf, sym, sym->type, NULL);
2008             continue;
2009         }
2010
2011         if (type != 0 || sym->cdef
2012                 || (!IS_STATIC(sym->etype)
2013                     && IS_GLOBAL(sym)))
2014         {
2015             // bail out for ___fsadd and friends
2016             if (sym->cdef && !sym->used) continue;
2017
2018             /* export or import non-static globals */
2019             if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2020
2021                 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2022                 {
2023                     /* do not add to emitted set, it might occur again! */
2024                     //if (!sym->used) continue;
2025                     // declare symbol
2026                     emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2027                 } else {
2028                     // declare symbol
2029                     emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2030                     if (!sym->ival && !IS_FUNC(sym->type)) {
2031                         // also define symbol
2032                         if (IS_ABSOLUTE(sym->etype)) {
2033                             // absolute location?
2034                             //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2035                             // deferred to pic14_constructAbsMap
2036                         } else {
2037                             dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2038                             dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2039                         }
2040                     } // if
2041                 } // if
2042                 pic14_stringInSet(sym->rname, &emitted, 1);
2043             } // if
2044         } // if
2045         list = sym->ival;
2046         //if (list) showInitList(list, 0);
2047         if (list) {
2048             resolveIvalSym( list, sym->type );
2049             emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2050             dbuf_printf (ivalBuf, "\n");
2051         }
2052     } // for sym
2053 }
2054
2055 /*
2056  * Iterate over all memmaps and emit their contents (attributes, symbols).
2057  */
2058 static void
2059 showAllMemmaps(FILE *of)
2060 {
2061     struct dbuf_s locBuf;
2062     memmap *maps[] = {
2063         xstack, istack, code, data, pdata, xdata, xidata, xinit,
2064         idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2065         sfr, sfrbit, reg, generic, overlay, eeprom, home };
2066     memmap * map;
2067     int i;
2068
2069     DEBUGprintf ("---begin memmaps---\n");
2070     if (!extBuf) extBuf = dbuf_new(1024);
2071     if (!gloBuf) gloBuf = dbuf_new(1024);
2072     if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2073     if (!ivalBuf) ivalBuf = dbuf_new(1024);
2074     dbuf_init(&locBuf, 1024);
2075
2076     dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2077     dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2078     dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2079     dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2080     dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2081
2082     for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2083         map = maps[i];
2084         //DEBUGprintf ("memmap %i: %p\n", i, map);
2085         if (map) {
2086 #if 0
2087             fprintf (stdout, ";  pageno %c, sname %s, dbName %c, ptrType %d, slbl %d, sloc %u, fmap %u, paged %u, direct %u, bitsp %u, codesp %u, regsp %u, syms %p\n",
2088                     map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2089                     map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2090                     map->codesp, map->regsp, map->syms);
2091 #endif
2092             emitSymbolSet(map->syms, 0);
2093         } // if (map)
2094     } // for i
2095     DEBUGprintf ("---end of memmaps---\n");
2096
2097     emitSymbolSet(publics, 1);
2098     emitSymbolSet(externs, 2);
2099
2100     emitPseudoStack(gloBuf, extBuf);
2101     pic14_constructAbsMap(gloDefBuf, gloBuf);
2102     pic14printLocals (&locBuf);
2103     pic14_emitConfigWord(of); // must be done after all the rest
2104
2105     dbuf_write_and_destroy(extBuf, of);
2106     dbuf_write_and_destroy(gloBuf, of);
2107     dbuf_write_and_destroy(gloDefBuf, of);
2108     dbuf_write_and_destroy(&locBuf, of);
2109     dbuf_write_and_destroy(ivalBuf, of);
2110
2111     extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;
2112 }