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