* src/regression/init0.c: new test for initialized arrays of function
[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 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 void pic14_debugLogClose(void); // from ralloc.c
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, *extBuf, *gloBuf, *gloDefBuf;
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 = ulFromVal (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");
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");
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 = constCharVal (0);
486         }
487
488         if (val->type != type) {
489                 val = valCastLiteral(type, floatFromVal(val));
490         }
491
492         if(val)
493                 ulval = ulFromVal (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 = ulFromVal (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) ulFromVal (val) & 0x00FF);
766                         break;
767                 case 2:
768                         fprintf (stderr, "WORD: %i\n", (unsigned int) ulFromVal (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) ulFromVal (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, int isReg);
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", 0);
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 /*
1147  * Interface to BANKSEL generation.
1148  * This function should return != 0 iff str1 and str2 denote operands that
1149  * are known to be allocated into the same bank. Consequently, there will
1150  * be no BANKSEL emitted if str2 is accessed while str1 has been used to
1151  * select the current bank just previously.
1152  *
1153  * If in doubt, return 0.
1154  */
1155 int
1156 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
1157     // see pic14printLocals
1158
1159     if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1160         // no clustering applied, each register resides in its own bank
1161     } else {
1162         // check whether BOTH names are local registers
1163         // XXX: This is some kind of shortcut, should be safe...
1164         // In this model, all r0xXXXX are allocated into a single section
1165         // per file, so no BANKSEL required if accessing a r0xXXXX after a
1166         // (different) r0xXXXX. Works great for multi-byte operands.
1167         if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
1168     } // if
1169
1170     // assume operands in different banks
1171     return (0);
1172 }
1173
1174 static void
1175 pic14printLocals (struct dbuf_s *oBuf)
1176 {
1177     set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
1178         dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
1179     regs *reg;
1180     int i, is_first = 1;
1181     static unsigned sectionNr = 0;
1182
1183     /* emit all registers from all possible sets */
1184     for (i = 0; i < 6; i++) {
1185         if (allregs[i] == NULL) continue;
1186
1187         for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1188             if (reg->isEmitted) continue;
1189
1190             if (reg->wasUsed && !reg->isExtern) {
1191                 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
1192                     if (reg->isFixed) {
1193                         // Should not happen, really...
1194                         assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
1195                         dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
1196                                 moduleName, sectionNr++, reg->address, reg->name, reg->size);
1197                     } else {
1198                         if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
1199                             // assign each local register into its own section
1200                             dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
1201                                     moduleName, sectionNr++, reg->name, reg->size);
1202                         } else {
1203                             // group all local registers into a single section
1204                             // This should greatly improve BANKSEL generation...
1205                             if (is_first) {
1206                                 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
1207                                 is_first = 0;
1208                             }
1209                             dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
1210                         }
1211                     }
1212                 }
1213             }
1214             reg->isEmitted = 1;
1215         } // for
1216     } // for
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* emitOverlay - will emit code for the overlay stuff              */
1221 /*-----------------------------------------------------------------*/
1222 static void
1223 pic14emitOverlay (struct dbuf_s * aBuf)
1224 {
1225         set *ovrset;
1226
1227         /*  if (!elementsInSet (ovrSetSets))*/
1228
1229         /* the hack below, fixes translates for devices which
1230         * only have udata_shr memory */
1231         dbuf_printf (aBuf, "%s\t%s\n",
1232                 (elementsInSet(ovrSetSets)?"":";"),
1233                 port->mem.overlay_name);
1234
1235         /* for each of the sets in the overlay segment do */
1236         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1237         ovrset = setNextItem (ovrSetSets))
1238         {
1239
1240                 symbol *sym;
1241
1242                 if (elementsInSet (ovrset))
1243                 {
1244                 /* this dummy area is used to fool the assembler
1245                 otherwise the assembler will append each of these
1246                 declarations into one chunk and will not overlay
1247                         sad but true */
1248
1249                         /* I don't think this applies to us. We are using gpasm.  CRF */
1250
1251                         dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1252                         /* output the area informtion */
1253                         dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);   /* MOF */
1254                 }
1255
1256                 for (sym = setFirstItem (ovrset); sym;
1257                 sym = setNextItem (ovrset))
1258                 {
1259
1260                         /* if extern then do nothing */
1261                         if (IS_EXTERN (sym->etype))
1262                                 continue;
1263
1264                                 /* if allocation required check is needed
1265                                 then check if the symbol really requires
1266                         allocation only for local variables */
1267                         if (!IS_AGGREGATE (sym->type) &&
1268                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1269                                 && !sym->allocreq && sym->level)
1270                                 continue;
1271
1272                                 /* if global variable & not static or extern
1273                         and addPublics allowed then add it to the public set */
1274                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1275                                 && !IS_STATIC (sym->etype))
1276                                 addSetHead (&publics, sym);
1277
1278                                 /* if extern then do nothing or is a function
1279                         then do nothing */
1280                         if (IS_FUNC (sym->type))
1281                                 continue;
1282
1283                         /* print extra debug info if required */
1284                         if (options.debug || sym->level == 0)
1285                         {
1286                                 if (!sym->level)
1287                                 {               /* global */
1288                                         if (IS_STATIC (sym->etype))
1289                                                 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1290                                         else
1291                                                 dbuf_printf (aBuf, "G_");       /* scope is global */
1292                                 }
1293                                 else
1294                                         /* symbol is local */
1295                                         dbuf_printf (aBuf, "L%s_",
1296                                         (sym->localof ? sym->localof->name : "-null-"));
1297                                 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1298                         }
1299
1300                         /* if is has an absolute address then generate
1301                         an equate for this no need to allocate space */
1302                         if (SPEC_ABSA (sym->etype))
1303                         {
1304
1305                                 if (options.debug || sym->level == 0)
1306                                         dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1307
1308                                 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1309                                         sym->rname,
1310                                         SPEC_ADDR (sym->etype));
1311                         }
1312                         else
1313                         {
1314                                 if (options.debug || sym->level == 0)
1315                                         dbuf_printf (aBuf, "==.\n");
1316
1317                                 /* allocate space */
1318                                 dbuf_printf (aBuf, "%s:\n", sym->rname);
1319                                 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1320                         }
1321
1322                 }
1323         }
1324 }
1325
1326
1327 void
1328 pic14_emitInterruptHandler (FILE * asmFile)
1329 {
1330         if (pic14_hasInterrupt)
1331         {
1332
1333                 fprintf (asmFile, "%s", iComments2);
1334                 fprintf (asmFile, "; interrupt and initialization code\n");
1335                 fprintf (asmFile, "%s", iComments2);
1336                 // Note - for mplink may have to enlarge section vectors in .lnk file
1337                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1338                 //       source files's code segment (interrupt.c -> code_interrupt)
1339                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1340
1341                 /* interrupt service routine */
1342                 fprintf (asmFile, "__sdcc_interrupt\n");
1343                 copypCode(asmFile, 'I');
1344         }
1345 }
1346
1347 /*-----------------------------------------------------------------*/
1348 /* glue - the final glue that hold the whole thing together        */
1349 /*-----------------------------------------------------------------*/
1350 void
1351 picglue ()
1352 {
1353         FILE *asmFile;
1354         struct dbuf_s ovrBuf;
1355         struct dbuf_s vBuf;
1356
1357         dbuf_init(&ovrBuf, 4096);
1358         dbuf_init(&vBuf, 4096);
1359
1360         pCodeInitRegisters();
1361
1362         /* check for main() */
1363         mainf = newSymbol ("main", 0);
1364         mainf->block = 0;
1365         mainf = findSymWithLevel (SymbolTab, mainf);
1366
1367         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1368         {
1369                 /* main missing -- import stack from main module */
1370                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1371                 pic14_options.isLibrarySource = 1;
1372         }
1373
1374 #if 0
1375         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1376
1377                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1378                 addpBlock(pb);
1379
1380                 /* entry point @ start of CSEG */
1381                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1382                 /* put in the call to main */
1383                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1384
1385                 if (options.mainreturn) {
1386
1387                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1388                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1389
1390                 } else {
1391
1392                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1393                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1394
1395                 }
1396         }
1397 #endif
1398
1399         /* At this point we've got all the code in the form of pCode structures */
1400         /* Now it needs to be rearranged into the order it should be placed in the */
1401         /* code space */
1402
1403         movepBlock2Head('P');              // Last
1404         movepBlock2Head(code->dbName);
1405         movepBlock2Head('X');
1406         movepBlock2Head(statsg->dbName);   // First
1407
1408
1409         /* print the global struct definitions */
1410         if (options.debug)
1411                 cdbStructBlock (0);
1412
1413         /* emit code for the all the variables declared */
1414         //pic14emitMaps ();
1415         /* do the overlay segments */
1416         pic14emitOverlay(&ovrBuf);
1417
1418         /* PENDING: this isnt the best place but it will do */
1419         if (port->general.glue_up_main) {
1420                 /* create the interrupt vector table */
1421                 pic14createInterruptVect (&vBuf);
1422         }
1423
1424         AnalyzepCode('*');
1425
1426         ReuseReg(); // ReuseReg where call tree permits
1427
1428         InlinepCode();
1429
1430         AnalyzepCode('*');
1431
1432         if (options.debug) pcode_test();
1433
1434
1435         /* now put it all together into the assembler file */
1436         /* create the assembler file name */
1437
1438         if ((noAssemble || options.c1mode) && fullDstFileName)
1439         {
1440                 sprintf (buffer, fullDstFileName);
1441         }
1442         else
1443         {
1444                 sprintf (buffer, dstFileName);
1445                 strcat (buffer, ".asm");
1446         }
1447
1448         if (!(asmFile = fopen (buffer, "w"))) {
1449                 werror (E_FILE_OPEN_ERR, buffer);
1450                 exit (1);
1451         }
1452
1453         /* prepare statistics */
1454         resetpCodeStatistics ();
1455
1456         /* initial comments */
1457         pic14initialComments (asmFile);
1458
1459         /* print module name */
1460         fprintf (asmFile, "%s\t.file\t\"%s\"\n",
1461             options.debug ? "" : ";", fullSrcFileName);
1462
1463         /* Let the port generate any global directives, etc. */
1464         if (port->genAssemblerPreamble)
1465         {
1466                 port->genAssemblerPreamble(asmFile);
1467         }
1468
1469         /* print the global variables in this module */
1470         //pic14printPublics (asmFile);
1471
1472         /* print the extern variables in this module */
1473         //pic14printExterns (asmFile);
1474
1475         /* copy the sfr segment */
1476 #if 0
1477         fprintf (asmFile, "%s", iComments2);
1478         fprintf (asmFile, "; special function registers\n");
1479         fprintf (asmFile, "%s", iComments2);
1480         dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1481
1482
1483         if (udata_section_name) {
1484                 sprintf(udata_name,"%s",udata_section_name);
1485         } else {
1486                 sprintf(udata_name,"data_%s",moduleName);
1487         }
1488         fprintf (asmFile, "%s", iComments2);
1489         fprintf (asmFile, "; udata\n");
1490         fprintf (asmFile, "%s", iComments2);
1491         fprintf (asmFile, "%s\tudata\n", udata_name);
1492         dbuf_write_and_destroy(&data->oBuf, asmFile);
1493 #endif
1494
1495         /* Put all variables into a cblock */
1496         AnalyzeBanking();
1497
1498         /* emit initialized data */
1499         showAllMemmaps(asmFile);
1500
1501         /* print the locally defined variables in this module */
1502         writeUsedRegs(asmFile);
1503
1504         /* create the overlay segments */
1505         fprintf (asmFile, "%s", iComments2);
1506         fprintf (asmFile, "; overlayable items in internal ram \n");
1507         fprintf (asmFile, "%s", iComments2);
1508         dbuf_write_and_destroy (&ovrBuf, asmFile);
1509
1510 #if 0
1511
1512         /* create the stack segment MOF */
1513         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1514                 fprintf (asmFile, "%s", iComments2);
1515                 fprintf (asmFile, "; Stack segment in internal ram \n");
1516                 fprintf (asmFile, "%s", iComments2);
1517                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1518                         ";__start__stack:\n;\t.ds\t1\n\n");
1519         }
1520
1521         /* create the idata segment */
1522         fprintf (asmFile, "%s", iComments2);
1523         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1524         fprintf (asmFile, "%s", iComments2);
1525         dbuf_write_and_destroy (&idata->oBuf, asmFile);
1526
1527         /* if external stack then reserve space of it */
1528         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1529                 fprintf (asmFile, "%s", iComments2);
1530                 fprintf (asmFile, "; external stack \n");
1531                 fprintf (asmFile, "%s", iComments2);
1532                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1533                 fprintf (asmFile,";\t.ds 256\n");
1534         }
1535
1536         /* copy xtern ram data */
1537         fprintf (asmFile, "%s", iComments2);
1538         fprintf (asmFile, "; external ram data\n");
1539         fprintf (asmFile, "%s", iComments2);
1540         dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1541
1542 #endif
1543
1544         /* copy the bit segment */
1545 #if 0
1546         fprintf (asmFile, "%s", iComments2);
1547         fprintf (asmFile, "; bit data\n");
1548         fprintf (asmFile, "%s", iComments2);
1549         dbuf_write_and_destroy (&bit->oBuf, asmFile);
1550 #endif
1551
1552         /* copy the interrupt vector table */
1553         if (mainf && IFFUNC_HASBODY(mainf->type))
1554           dbuf_write_and_destroy (&vBuf, asmFile);
1555         else
1556           dbuf_destroy(&vBuf);
1557
1558         /* create interupt ventor handler */
1559         pic14_emitInterruptHandler (asmFile);
1560
1561         /* copy over code */
1562         fprintf (asmFile, "%s", iComments2);
1563         fprintf (asmFile, "; code\n");
1564         fprintf (asmFile, "%s", iComments2);
1565         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1566
1567         /* unknown */
1568         copypCode(asmFile, 'X');
1569
1570         /* _main function */
1571         copypCode(asmFile, 'M');
1572
1573         /* other functions */
1574         copypCode(asmFile, code->dbName);
1575
1576         /* unknown */
1577         copypCode(asmFile, 'P');
1578
1579         dumppCodeStatistics (asmFile);
1580
1581         fprintf (asmFile,"\tend\n");
1582
1583         fclose (asmFile);
1584         pic14_debugLogClose();
1585 }
1586
1587 /*
1588  * Deal with initializers.
1589  */
1590 #undef DEBUGprintf
1591 #if 0
1592 // debugging output
1593 #define DEBUGprintf printf
1594 #else
1595 // be quiet
1596 #define DEBUGprintf 1 ? (void)0 : (void)printf
1597 #endif
1598
1599
1600 void ast_print (ast * tree, FILE *outfile, int indent);
1601
1602 #if 0
1603 /*
1604  * Emit all memmaps.
1605  */
1606 static void
1607 showInitList(initList *list, int level)
1608 {
1609     static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1610     static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1611     struct ast *ast;
1612     while (list) {
1613         printf ("      %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1614         if (list->type == INIT_DEEP) {
1615             showInitList(list->init.deep, level + 1);
1616         } else if (list->type == INIT_NODE) {
1617             ast = list->init.node;
1618             printf ("        type %u (%s), level %d, block %d, seqPoint %d\n",
1619                     ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1620             if (ast->type == EX_VALUE) {
1621                 printf ("          VAL %lf\n", floatFromVal(ast->opval.val));
1622             } else if (ast->type == EX_LINK) {
1623                 printTypeChain(ast->opval.lnk, NULL);
1624             } else if (ast->type == EX_OP) {
1625                 printf ("          OP %u\n", ast->opval.op);
1626             }
1627         } // if
1628         list = list->next;
1629     } // while
1630 }
1631 #endif
1632
1633 /*
1634  * DEBUG: Print a value.
1635  */
1636 void
1637 printVal(value *val)
1638 {
1639     printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1640             val, val->name, val->type, val->etype,
1641             val->sym ? val->sym->name : NULL, val->vArgs,
1642             (long) ulFromVal (val), (long) ulFromVal (val));
1643     printTypeChain(val->type, stdout);
1644     printf ("\n");
1645     printTypeChain(val->etype, stdout);
1646     printf ("\n");
1647 }
1648
1649 //prototype from ../SDCCicode.c
1650 operand *operandFromAst (ast * tree,int lvl);
1651
1652 char *
1653 parseIvalAst (ast *node, int *inCodeSpace) {
1654 #define LEN 4096
1655     char *buffer = NULL;
1656     char *left, *right;
1657
1658     if (IS_AST_VALUE(node)) {
1659         value *val = AST_VALUE(node);
1660         symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1661         if (inCodeSpace && val->type
1662                 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1663         {
1664             *inCodeSpace = 1;
1665         }
1666         if (inCodeSpace && sym
1667                 && (IS_FUNC(sym->type)
1668                     || IS_CODE(getSpec(sym->type))))
1669         {
1670             *inCodeSpace = 1;
1671         }
1672
1673         DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1674         if (IS_AST_LIT_VALUE(node)) {
1675             buffer = Safe_alloc(LEN);
1676             SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
1677         } else if (IS_AST_SYM_VALUE(node)) {
1678             assert ( AST_SYMBOL(node) );
1679             /*
1680             printf ("sym %s: ", AST_SYMBOL(node)->rname);
1681             printTypeChain(AST_SYMBOL(node)->type, stdout);
1682             printTypeChain(AST_SYMBOL(node)->etype, stdout);
1683             printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1684             */
1685             buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1686         } else {
1687             assert ( !"Invalid values type for initializers in AST." );
1688         }
1689     } else if (IS_AST_OP(node)) {
1690         DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1691         switch (node->opval.op) {
1692         case CAST:
1693             assert (node->right);
1694             buffer = parseIvalAst(node->right, inCodeSpace);
1695             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1696             break;
1697         case '&':
1698             assert ( node->left && !node->right );
1699             buffer = parseIvalAst(node->left, inCodeSpace);
1700             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1701             break;
1702         case '+':
1703             assert (node->left && node->right );
1704             left = parseIvalAst(node->left, inCodeSpace);
1705             right = parseIvalAst(node->right, inCodeSpace);
1706             buffer = Safe_alloc(LEN);
1707             SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1708             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1709             Safe_free(left);
1710             Safe_free(right);
1711             break;
1712         case '[':
1713             assert ( node->left && node->right );
1714             assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1715             right = parseIvalAst(node->right, inCodeSpace);
1716             buffer = Safe_alloc(LEN);
1717             SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1718                     AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1719             Safe_free(right);
1720             DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1721             break;
1722         default:
1723             assert ( !"Unhandled operation in initializer." );
1724             break;
1725         }
1726     } else {
1727         assert ( !"Invalid construct in initializer." );
1728     }
1729
1730     return (buffer);
1731 }
1732
1733 /*
1734  * Emit the section preamble, absolute location (if any) and
1735  * symbol name(s) for intialized data.
1736  */
1737 static int
1738 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1739 {
1740     char *segname;
1741     static int in_code = 0;
1742     static int sectionNr = 0;
1743
1744     if (sym) {
1745         // code or data space?
1746         if (IS_CODE(getSpec(sym->type))) {
1747             segname = "code";
1748             in_code = 1;
1749         } else {
1750             segname = "idata";
1751             in_code  = 0;
1752         }
1753         dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1754         if (SPEC_ABSA(getSpec(sym->type))) {
1755             // specify address for absolute symbols
1756             dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1757         } // if
1758         dbuf_printf(oBuf, "\n%s\n", sym->rname);
1759
1760         addSet(&emitted, sym->rname);
1761     }
1762     return (in_code);
1763 }
1764
1765 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1766 /*
1767  * Actually emit the initial values in .asm format.
1768  */
1769 static void
1770 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1771 {
1772     int i;
1773     ast *node;
1774     operand *op;
1775     value *val = NULL;
1776     int inCodeSpace = 0;
1777     char *str = NULL;
1778     int in_code;
1779
1780     assert (size <= sizeof(long));
1781     assert (!list || (list->type == INIT_NODE));
1782     node = list ? list->init.node : NULL;
1783
1784     in_code = emitIvalLabel(oBuf, sym);
1785     if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1786
1787     if (!node) {
1788         // initialize as zero
1789         for (i=0; i < size; i++) {
1790             if (in_code) {
1791                 dbuf_printf (oBuf, "\tretlw 0x00");
1792             } else {
1793                 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1794             }
1795         } // for
1796         dbuf_printf (oBuf, "\n");
1797         return;
1798     } // if
1799
1800     op = NULL;
1801     if (constExprTree(node) && (val = constExprValue(node, 0))) {
1802         op = operandFromValue(val);
1803         DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1804         //printVal(val);
1805     } else if (IS_AST_VALUE(node)) {
1806         op = operandFromAst(node, 0);
1807     } else if (IS_AST_OP(node)) {
1808         str = parseIvalAst(node, &inCodeSpace);
1809         DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1810         op = NULL;
1811     } else {
1812         assert ( !"Unhandled construct in intializer." );
1813     }
1814
1815     if (op) {
1816         aopOp(op, NULL, 1);
1817         assert(AOP(op));
1818         //printOperand(op, of);
1819     }
1820
1821     for (i=0; i < size; i++) {
1822         char *text;
1823
1824         /*
1825          * FIXME: This is hacky and needs some more thought.
1826          */
1827         if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
1828             /* This branch is introduced to fix #1427663. */
1829             PCOI(AOP(op)->aopu.pcop)->offset+=i;
1830             text = get_op(AOP(op)->aopu.pcop, NULL, 0);
1831             PCOI(AOP(op)->aopu.pcop)->offset-=i;
1832         } else {
1833             text = op ? aopGet(AOP(op), i, 0, 0)
1834             : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1835         } // if
1836         if (in_code) {
1837             dbuf_printf (oBuf, "\tretlw %s\n", text);
1838         } else {
1839             dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1840         }
1841     } // for
1842     dbuf_printf (oBuf, "\n");
1843 }
1844
1845 /*
1846  * For UNIONs, we first have to find the correct alternative to map the
1847  * initializer to. This function maps the structure of the initializer to
1848  * the UNION members recursively.
1849  * Returns the type of the first `fitting' member.
1850  */
1851 static sym_link *
1852 matchIvalToUnion (initList *list, sym_link *type, int size)
1853 {
1854     symbol *sym;
1855
1856     assert (type);
1857
1858     if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1859             || IS_FLOAT(type))
1860     {
1861         if (!list || (list->type == INIT_NODE)) {
1862             DEBUGprintf ("OK, simple type\n");
1863             return (type);
1864         } else {
1865             DEBUGprintf ("ERROR, simple type\n");
1866             return (NULL);
1867         }
1868     } else if (IS_BITFIELD(type)) {
1869         if (!list || (list->type == INIT_NODE)) {
1870             DEBUGprintf ("OK, bitfield\n");
1871             return (type);
1872         } else {
1873             DEBUGprintf ("ERROR, bitfield\n");
1874             return (NULL);
1875         }
1876     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1877         if (!list || (list->type == INIT_DEEP)) {
1878             if (list) list = list->init.deep;
1879             sym = SPEC_STRUCT(type)->fields;
1880             while (sym) {
1881                 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1882                 if (!matchIvalToUnion(list, sym->type, 0)) {
1883                     DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1884                     return (NULL);
1885                 }
1886                 if (list) list = list->next;
1887                 sym = sym->next;
1888             } // while
1889
1890             // excess initializers?
1891             if (list) {
1892                 DEBUGprintf ("ERROR, excess initializers\n");
1893                 return (NULL);
1894             }
1895
1896             DEBUGprintf ("OK, struct\n");
1897             return (type);
1898         }
1899         return (NULL);
1900     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1901         if (!list || (list->type == INIT_DEEP)) {
1902             if (list) list = list->init.deep;
1903             sym = SPEC_STRUCT(type)->fields;
1904             while (sym) {
1905                 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1906                 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1907                         && matchIvalToUnion(list, sym->type, size))
1908                 {
1909                     DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1910                     return (sym->type);
1911                 }
1912                 sym = sym->next;
1913             } // while
1914         } // if
1915         // no match found
1916         DEBUGprintf ("ERROR, no match found.\n");
1917         return (NULL);
1918     } else {
1919         assert ( !"Unhandled type in UNION." );
1920     }
1921
1922     assert ( !"No match found in UNION for the given initializer structure." );
1923     return (NULL);
1924 }
1925
1926 /*
1927  * Parse the type and its initializer and emit it (recursively).
1928  */
1929 static void
1930 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1931 {
1932     symbol *sym;
1933     int size, i;
1934     long lit;
1935     unsigned char *str;
1936
1937     size = getSize(my_type);
1938
1939     if (IS_PTR(my_type)) {
1940         DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1941         emitIvals(oBuf, topsym, list, 0, size);
1942         return;
1943     }
1944
1945     if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
1946         str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1947         emitIvalLabel(oBuf, topsym);
1948         do {
1949             dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1950         } while (*(str++));
1951         return;
1952     }
1953
1954     if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1955         fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1956         assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1957         return;
1958     }
1959
1960     if (IS_ARRAY(my_type)) {
1961         DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1962         assert (!list || list->type == INIT_DEEP);
1963         if (list) list = list->init.deep;
1964         for (i = 0; i < DCL_ELEM(my_type); i++) {
1965             emitInitVal(oBuf, topsym, my_type->next, list);
1966             topsym = NULL;
1967             if (list) list = list->next;
1968         } // for i
1969         return;
1970     }
1971
1972     if (IS_FLOAT(my_type)) {
1973         // float, 32 bit
1974         DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1975         emitIvals(oBuf, topsym, list, 0, size);
1976         return;
1977     }
1978
1979     if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1980         // integral type, 8, 16, or 32 bit
1981         DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1982         emitIvals(oBuf, topsym, list, 0, size);
1983         return;
1984
1985     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1986         // struct
1987         DEBUGprintf ("(struct, %d byte) handled below\n", size);
1988         assert (!list || (list->type == INIT_DEEP));
1989
1990         // iterate over struct members and initList
1991         if (list) list = list->init.deep;
1992         sym = SPEC_STRUCT(my_type)->fields;
1993         while (sym) {
1994             long bitfield = 0;
1995             int len = 0;
1996             if (IS_BITFIELD(sym->type)) {
1997                 while (sym && IS_BITFIELD(sym->type)) {
1998                     assert (!list || ((list->type == INIT_NODE)
1999                                 && IS_AST_LIT_VALUE(list->init.node)));
2000                     lit = (long) (list ? list2int(list) : 0);
2001                     DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
2002                             lit, SPEC_BLEN(getSpec(sym->type)),
2003                             SPEC_BSTR(getSpec(sym->type)), bitfield);
2004                     bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
2005                     len += SPEC_BLEN(getSpec(sym->type));
2006
2007                     sym = sym->next;
2008                     if (list) list = list->next;
2009                 } // while
2010                 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
2011                 len = (len + 7) & ~0x07; // round up to full bytes
2012                 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2013                 topsym = NULL;
2014             } // if
2015
2016             if (sym) {
2017                 emitInitVal(oBuf, topsym, sym->type, list);
2018                 topsym = NULL;
2019                 sym = sym->next;
2020                 if (list) list = list->next;
2021             } // if
2022         } // while
2023         if (list) {
2024             assert ( !"Excess initializers." );
2025         } // if
2026         return;
2027
2028     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2029         // union
2030         DEBUGprintf ("(union, %d byte) handled below\n", size);
2031         assert (list && list->type == INIT_DEEP);
2032
2033         // iterate over union members and initList, try to map number and type of fields and initializers
2034         my_type = matchIvalToUnion(list, my_type, size);
2035         if (my_type) {
2036             emitInitVal(oBuf, topsym, my_type, list->init.deep);
2037             topsym = NULL;
2038             size -= getSize(my_type);
2039             if (size > 0) {
2040                 // pad with (leading) zeros
2041                 emitIvals(oBuf, NULL, NULL, 0, size);
2042             }
2043             return;
2044         } // if
2045
2046         assert ( !"No UNION member matches the initializer structure.");
2047     } else if (IS_BITFIELD(my_type)) {
2048         assert ( !"bitfields should only occur in structs..." );
2049
2050     } else {
2051         printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2052         assert( !"Unhandled initialized type.");
2053     }
2054 }
2055
2056 /*
2057  * Emit a set of symbols.
2058  * type - 0: have symbol tell whether it is local, extern or global
2059  *        1: assume all symbols in set to be global
2060  *        2: assume all symbols in set to be extern
2061  */
2062 static void
2063 emitSymbolSet(set *s, int type)
2064 {
2065     symbol *sym;
2066     initList *list;
2067     unsigned sectionNr = 0;
2068
2069     for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2070 #if 0
2071         fprintf (stdout, ";    name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2072                 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2073 #endif
2074
2075         if (sym->etype && SPEC_ABSA(sym->etype)
2076                 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
2077                 && sym->ival)
2078         {
2079             // handle config words
2080             pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
2081                     (int)list2int(sym->ival));
2082             pic14_stringInSet(sym->rname, &emitted, 1);
2083             continue;
2084         }
2085
2086         if (sym->isstrlit) {
2087             // special case: string literals
2088             emitInitVal(ivalBuf, sym, sym->type, NULL);
2089             continue;
2090         }
2091
2092         if (type != 0 || sym->cdef
2093                 || (!IS_STATIC(sym->etype)
2094                     && IS_GLOBAL(sym)))
2095         {
2096             // bail out for ___fsadd and friends
2097             if (sym->cdef && !sym->used) continue;
2098
2099             /* export or import non-static globals */
2100             if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2101
2102                 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2103                 {
2104                     /* do not add to emitted set, it might occur again! */
2105                     //if (!sym->used) continue;
2106                     // declare symbol
2107                     emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2108                 } else {
2109                     // declare symbol
2110                     emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2111                     if (!sym->ival && !IS_FUNC(sym->type)) {
2112                         // also define symbol
2113                         if (IS_ABSOLUTE(sym->etype)) {
2114                             // absolute location?
2115                             //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2116                             // deferred to pic14_constructAbsMap
2117                         } else {
2118                             dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2119                             dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2120                         }
2121                     } // if
2122                 } // if
2123                 pic14_stringInSet(sym->rname, &emitted, 1);
2124             } // if
2125         } // if
2126         list = sym->ival;
2127         //if (list) showInitList(list, 0);
2128         if (list) {
2129             resolveIvalSym( list, sym->type );
2130             emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2131             dbuf_printf (ivalBuf, "\n");
2132         }
2133     } // for sym
2134 }
2135
2136 /*
2137  * Iterate over all memmaps and emit their contents (attributes, symbols).
2138  */
2139 static void
2140 showAllMemmaps(FILE *of)
2141 {
2142     struct dbuf_s locBuf;
2143     memmap *maps[] = {
2144         xstack, istack, code, data, pdata, xdata, xidata, xinit,
2145         idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2146         sfr, sfrbit, reg, generic, overlay, eeprom, home };
2147     memmap * map;
2148     int i;
2149
2150     DEBUGprintf ("---begin memmaps---\n");
2151     if (!extBuf) extBuf = dbuf_new(1024);
2152     if (!gloBuf) gloBuf = dbuf_new(1024);
2153     if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2154     if (!ivalBuf) ivalBuf = dbuf_new(1024);
2155     dbuf_init(&locBuf, 1024);
2156
2157     dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2158     dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2159     dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2160     dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2161     dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2162
2163     for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2164         map = maps[i];
2165         //DEBUGprintf ("memmap %i: %p\n", i, map);
2166         if (map) {
2167 #if 0
2168             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",
2169                     map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2170                     map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2171                     map->codesp, map->regsp, map->syms);
2172 #endif
2173             emitSymbolSet(map->syms, 0);
2174         } // if (map)
2175     } // for i
2176     DEBUGprintf ("---end of memmaps---\n");
2177
2178     emitSymbolSet(publics, 1);
2179     emitSymbolSet(externs, 2);
2180
2181     emitPseudoStack(gloBuf, extBuf);
2182     pic14_constructAbsMap(gloDefBuf, gloBuf);
2183     pic14printLocals (&locBuf);
2184     pic14_emitConfigWord(of); // must be done after all the rest
2185
2186     dbuf_write_and_destroy(extBuf, of);
2187     dbuf_write_and_destroy(gloBuf, of);
2188     dbuf_write_and_destroy(gloDefBuf, of);
2189     dbuf_write_and_destroy(&locBuf, of);
2190     dbuf_write_and_destroy(ivalBuf, of);
2191
2192     extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;
2193 }