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