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