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