* src/pic/pcode.c (isValidIdChar,bankCompare): fuzzy matching of
[fw/sdcc] / src / pic / glue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "../common.h"
26 #include <time.h>
27 #include "ralloc.h"
28 #include "pcode.h"
29 #include "newalloc.h"
30 #include "gen.h"
31 #include "main.h"
32 #include "device.h"
33 #include "dbuf_string.h"
34
35
36 #ifdef WORDS_BIGENDIAN
37 #define _ENDIAN(x)  (3-x)
38 #else
39 #define _ENDIAN(x)  (x)
40 #endif
41
42 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 #define IS_GLOBAL(sym)  ((sym)->level == 0)
44
45 extern symbol *interrupts[256];
46 static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols
47 extern int noAlloc;
48 extern set *publics;
49 extern set *externs;
50 extern unsigned maxInterrupts;
51 extern int maxRegBank;
52 extern symbol *mainf;
53 extern char *VersionString;
54 extern struct dbuf_s *codeOutBuf;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
58 set *pic14_localFunctions = NULL;
59
60 extern DEFSETFUNC (closeTmpFiles);
61 extern DEFSETFUNC (rmTmpFiles);
62
63 extern void AnalyzeBanking (void);
64 extern void ReuseReg(void);
65 extern void InlinepCode(void);
66 extern void writeUsedRegs(FILE *);
67
68 extern void initialComments (FILE * afile);
69 extern void printPublics (FILE * afile);
70
71 extern void printChar (FILE * ofile, char *s, int plen);
72 void  pCodeInitRegisters(void);
73 int getConfigWord(int address);
74 int getHasSecondConfigReg(void);
75
76 char *udata_section_name=0;             // FIXME Temporary fix to change udata section name -- VR
77 int pic14_hasInterrupt = 0;             // Indicates whether to emit interrupt handler or not
78
79 /* dbufs for initialized data (idata and code sections),
80  * extern, and global declarations */
81 struct dbuf_s *ivalBuf, *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 = (unsigned long) floatFromVal(val);
100                 
101                 return ( (v >> (offset * 8)) & 0xff);
102         }
103         
104         /* it is type float */
105         fl.f = (float) floatFromVal(val);
106 #ifdef WORDS_BIGENDIAN
107         return fl.c[3-offset];
108 #else
109         return fl.c[offset];
110 #endif
111         
112 }
113
114 #if 0
115 static int
116 is_valid_identifier( const char *name )
117 {
118   char a;
119   if (!name) return 0;
120   a = *name;
121   
122   /* only accept [a-zA-Z_][a-zA-Z0-9_] */
123   if (!((a >= 'a' && a <= 'z')
124         || (a >= 'A' && a <= 'z')
125         || (a == '_')))
126     return 0;
127
128   name++;
129   while ((a = *name++))
130   {
131     if (!((a >= 'a' && a <= 'z')
132         || (a >= 'A' && a <= 'Z')
133         || (a >= '0' && a <= '9')
134         || (a == '_')))
135       return 0;
136   } // while
137
138   /* valid identifier */
139   return 1;
140 }
141 #endif
142
143 static void
144 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
145 {
146     int shared, low, high, size, i;
147     PIC_device *pic;
148
149     /* also emit STK symbols
150      * XXX: This is ugly and fails as soon as devices start to get
151      *      differently sized sharebanks, since STK12 will be
152      *      required by larger devices but only up to STK03 might
153      *      be defined using smaller devices. */
154     shared = pic14_getSharedStack(&low, &high, &size);
155     if (!pic14_options.isLibrarySource)
156     {
157         pic = pic14_getPIC();
158
159         dbuf_printf (oBuf, "\n");
160         dbuf_printf (oBuf, "\tglobal PSAVE\n");
161         dbuf_printf (oBuf, "\tglobal SSAVE\n");
162         dbuf_printf (oBuf, "\tglobal WSAVE\n");
163         for (i = size - 4; i >= 0; i--) {
164             dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
165         } // for i
166         dbuf_printf (oBuf, "\n");
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=constVal("0");
486         }
487         
488         if (val->type != type) {
489                 val = valCastLiteral(type, floatFromVal(val));
490         }
491         
492         if(val) 
493                 ulval = (unsigned long) floatFromVal (val);
494         else
495                 ulval =0;
496         
497         switch (getSize (type)) {
498         case 1:
499                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
500                 break;
501                 
502         case 2:
503                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
504                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
505                 break;
506                 
507         case 4:
508                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
509                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
510                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
511                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
512                 break;
513         }
514 }
515
516 /*-----------------------------------------------------------------*/
517 /* printIvalBitFields - generate initializer for bitfields         */
518 /*-----------------------------------------------------------------*/
519 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb ) 
520 {
521         value *val ;
522         symbol *lsym = *sym;
523         initList *lilist = *ilist ;
524         unsigned long ival = 0;
525         int size =0;
526         
527         
528         do {
529                 unsigned long i;
530                 val = list2val(lilist);
531                 if (size) {
532                         if (SPEC_BLEN(lsym->etype) > 8) {
533                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
534                                         (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
535                         }
536                 } else {
537                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
538                                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
539                 }
540                 i = (unsigned long)floatFromVal(val);
541                 i <<= SPEC_BSTR (lsym->etype);
542                 ival |= i;
543                 if (! ( lsym->next &&
544                         (IS_BITFIELD(lsym->next->type)) &&
545                         (SPEC_BSTR(lsym->next->etype)))) break;
546                 lsym = lsym->next;
547                 lilist = lilist->next;
548         } while (1);
549         switch (size) {
550         case 1:
551                 //tfprintf (oFile, "\t!db !constbyte\n",ival);
552                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
553                 break;
554                 
555         case 2:
556                 //tfprintf (oFile, "\t!dw !constword\n",ival);
557                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
558                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
559                 break;
560         case 4:
561                 //tfprintf (oFile, "\t!db  !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
562                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
563                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
564                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
565                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
566                 break;
567         }
568         *sym = lsym;
569         *ilist = lilist;
570 }
571
572 /*-----------------------------------------------------------------*/
573 /* printIvalStruct - generates initial value for structures        */
574 /*-----------------------------------------------------------------*/
575 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
576 {
577         symbol *sflds;
578         initList *iloop = NULL;
579         
580         sflds = SPEC_STRUCT (type)->fields;
581         
582         if (ilist) {
583                 if (ilist->type != INIT_DEEP) {
584                         werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
585                         return;
586                 }
587                 
588                 iloop = ilist->init.deep;
589         }
590         
591         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
592                 if (IS_BITFIELD(sflds->type)) {
593                         printIvalBitFields(&sflds,&iloop,pb);
594                 } else {
595                         printIval (sym, sflds->type, iloop, pb);
596                 }
597         }
598         if (iloop) {
599                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
600         }
601         return;
602 }
603
604 /*-----------------------------------------------------------------*/
605 /* printIvalChar - generates initital value for character array    */
606 /*-----------------------------------------------------------------*/
607 static int 
608 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
609 {
610         value *val;
611         int remain, ilen;
612         
613         if(!pb)
614                 return 0;
615         
616         //fprintf(stderr, "%s\n",__FUNCTION__);
617         if (!s)
618         {
619                 
620                 val = list2val (ilist);
621
622                 /* if the value is a character string  */
623                 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
624                 {
625                         ilen = DCL_ELEM(val->type);
626
627                         if (!DCL_ELEM (type))
628                                 DCL_ELEM (type) = ilen;
629                 
630                         /* emit string constant */
631                         for (remain = 0; remain < ilen; remain++) {
632                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
633                         }
634                         
635                         /* fill array up to desired size */
636                         if ((remain = (DCL_ELEM (type) - ilen)) > 0)
637                                 while (remain--)
638                                         //tfprintf (oFile, "\t!db !constbyte\n", 0);
639                                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
640                                 return 1;
641                 }
642                 else
643                         return 0;
644         }
645         else {
646                 //printChar (oFile, s, strlen (s) + 1);
647                 
648                 for(remain=0; remain<(int)strlen(s); remain++) {
649                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
650                         //fprintf(stderr,"0x%02x ",s[remain]);
651                 }
652                 //fprintf(stderr,"\n");
653         }
654         return 1;
655 }
656
657 /*-----------------------------------------------------------------*/
658 /* printIvalArray - generates code for array initialization        */
659 /*-----------------------------------------------------------------*/
660 static void 
661 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
662                                 pBlock *pb)
663 {
664         initList *iloop;
665         unsigned size = 0;
666
667         if(!pb)
668                 return;
669         if (ilist) {
670                 /* take care of the special   case  */
671                 /* array of characters can be init  */
672                 /* by a string                      */
673                 if (IS_CHAR (type->next)) {
674                         //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
675                         if (!IS_LITERAL(list2val(ilist)->etype)) {
676                                 werror (W_INIT_WRONG);
677                                 return;
678                         }
679                         if (printIvalChar (type,
680                                 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
681                                 pb, SPEC_CVAL (sym->etype).v_char))
682                                 return;
683                 }
684                 /* not the special case */
685                 if (ilist->type != INIT_DEEP) {
686                         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
687                         return;
688                 }
689
690                 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
691                         if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
692                                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
693                                 break;
694                         }
695                         printIval (sym, type->next, iloop, pb);
696                 }
697         }
698
699         if (DCL_ELEM(type)) {
700                 // pad with zeros if needed
701                 if (size<DCL_ELEM(type)) {
702                         size = (DCL_ELEM(type) - size) * getSize(type->next);
703                         while (size--) {
704                                 //tfprintf (oFile, "\t!db !constbyte\n", 0);
705                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
706                         }
707                 }
708         } else {
709                 // we have not been given a size, but we now know it
710                 DCL_ELEM (type) = size;
711         }
712
713         return;
714 }
715
716 /*-----------------------------------------------------------------*/
717 /* printIvalPtr - generates code for initial value of pointers     */
718 /*-----------------------------------------------------------------*/
719 extern value *initPointer (initList *, sym_link *toType);
720
721 static void 
722 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
723 {
724         value *val;
725         
726         if (!ilist || !pb)
727                 return;
728         
729         fprintf (stderr, "FIXME: initializers for pointers...\n");
730         printTypeChain (type, stderr);
731         
732         fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
733         fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
734
735         if (ilist && (ilist->type == INIT_DEEP))
736           ilist = ilist->init.deep;
737         
738         /* function pointers */
739         if (IS_FUNC (type->next))
740         {
741                 assert ( !"function pointers not yet handled" );
742                 //printIvalFuncPtr (type, ilist, pb);
743         }
744
745         if (!(val = initPointer (ilist, type)))
746                 return;
747         
748         if (IS_CHAR (type->next))
749         {
750                 if (printIvalChar (type, ilist, pb, NULL)) return;
751         }
752
753         /* check the type */
754         if (compareType (type, val->type) == 0)
755         {
756                 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
757                 printFromToType (val->type, type);
758         }
759
760         if (IS_LITERAL (val->etype))
761         {
762                 switch (getSize (type))
763                 {
764                 case 1:
765                         fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
766                         break;
767                 case 2:
768                         fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
769                         break;
770                 case 3: /* gneric pointers */
771                         assert ( !"generic pointers not yet handled" );
772                 case 4:
773                         fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
774                         break;
775                 default:
776                         assert ( !"invaild size of value -- aborting" );
777                 } // switch
778
779                 return;
780         } // if (IS_LITERAL)
781
782         /* now handle symbolic values */
783         switch (getSize (type))
784         {
785         case 1:
786                 fprintf (stderr, "BYTE: %s", val->name);
787                 break;
788         case 2:
789                 fprintf (stderr, "WORD: %s", val->name);
790                 break;
791         case 4:
792                 fprintf (stderr, "LONG: %s", val->name);
793                 break;
794         default:
795                 assert ( !"invalid size of (symbolic) value -- aborting" );
796         } // switch
797 }
798
799 /*-----------------------------------------------------------------*/
800 /* printIval - generates code for initial value                    */
801 /*-----------------------------------------------------------------*/
802 static void 
803 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
804 {
805         if (!ilist || !pb)
806                 return;
807         
808         /* if structure then    */
809         if (IS_STRUCT (type))
810         {
811                 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
812                 printIvalStruct (sym, type, ilist, pb);
813                 return;
814         }
815         
816         /* if this is an array   */
817         if (IS_ARRAY (type))
818         {
819                 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
820                 printIvalArray (sym, type, ilist, pb);
821                 return;
822         }
823         
824         /* if this is a pointer */
825         if (IS_PTR (type))
826         {
827                 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
828                 printIvalPtr (sym, type, ilist, pb);
829                 return;
830         }
831         
832         /* if type is SPECIFIER */
833         if (IS_SPEC (type))
834         {
835                 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
836                 printIvalType (sym, type, ilist, pb);
837                 return;
838         }
839 }
840 #endif
841
842 #if 0
843 extern void pCodeConstString(char *name, char *value);
844 /*-----------------------------------------------------------------*/
845 /* emitStaticSeg - emitcode for the static segment                 */
846 /*-----------------------------------------------------------------*/
847 static void
848 pic14emitStaticSeg (memmap * map)
849 {
850         symbol *sym;
851         
852         dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
853         
854         //fprintf(stderr, "%s\n",__FUNCTION__);
855         
856         /* for all variables in this segment do */
857         for (sym = setFirstItem (map->syms); sym;
858         sym = setNextItem (map->syms))
859         {
860                 /* if extern then add it into the extern list */
861                 if (IS_EXTERN (sym->etype)) {
862                         addSetHead (&externs, sym);
863                         continue;
864                 }
865                 
866                 /* if it is not static add it to the public
867                 table */
868                 if (!IS_STATIC (sym->etype))
869                         addSetHead (&publics, sym);
870                 
871                 /* print extra debug info if required */
872                 if (options.debug || sym->level == 0)
873                 {
874                         if (!sym->level)
875                         {                       /* global */
876                                 if (IS_STATIC (sym->etype))
877                                         dbuf_printf (&code->oBuf, "F%s_", moduleName);  /* scope is file */
878                                 else
879                                         dbuf_printf (&code->oBuf, "G_");        /* scope is global */
880                         }
881                         else
882                                 /* symbol is local */
883                                 dbuf_printf (&code->oBuf, "L%s_",
884                                 (sym->localof ? sym->localof->name : "-null-"));
885                         dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
886                         
887                 }
888                 
889                 /* if it has an absolute address */
890                 if (SPEC_ABSA (sym->etype))
891                 {
892                         if (options.debug || sym->level == 0)
893                                 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
894                         
895                         dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
896                                 sym->rname,
897                                 SPEC_ADDR (sym->etype));
898                 }
899                 else
900                 {
901                         if (options.debug || sym->level == 0)
902                                 dbuf_printf (&code->oBuf, " == .\n");
903                         
904                         /* if it has an initial value */
905                         if (sym->ival)
906                         {
907 #if 0
908                                 pBlock *pb;
909                                 
910                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
911                                 noAlloc++;
912                                 resolveIvalSym (sym->ival, sym->type);
913                                 //printIval (sym, sym->type, sym->ival, &code->oBuf);
914                                 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
915                                 addpBlock(pb);
916                                 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
917                                 
918                                 printIval (sym, sym->type, sym->ival, pb);
919                                 noAlloc--;
920 #endif
921                         }
922                         else
923                         {
924                                 
925                                 /* allocate space */
926                                 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
927                                 /* special case for character strings */
928                                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
929                                         SPEC_CVAL (sym->etype).v_char)
930                                         pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
931                                         /*printChar (code->oFile,
932                                         SPEC_CVAL (sym->etype).v_char,
933                                 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
934                                 else
935                                         dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
936                         }
937                 }
938         }
939         
940 }
941 #endif
942
943
944 #if 0
945 /*-----------------------------------------------------------------*/
946 /* emitMaps - emits the code for the data portion the code         */
947 /*-----------------------------------------------------------------*/
948 static void
949 pic14emitMaps ()
950 {
951         pic14_constructAbsMap (&sfr->oBuf);
952         emitPseudoStack(&sfr->oBuf, &sfr->oBuf);
953 /* no special considerations for the following
954         data, idata & bit & xdata */
955         pic14emitRegularMap (data, TRUE, TRUE);
956         pic14emitRegularMap (idata, TRUE, TRUE);
957         pic14emitRegularMap (bit, TRUE, FALSE);
958         pic14emitRegularMap (xdata, TRUE, TRUE);
959         pic14emitRegularMap (sfr, TRUE, FALSE);
960         pic14emitRegularMap (sfrbit, FALSE, FALSE);
961         pic14emitRegularMap (code, TRUE, FALSE);
962         pic14emitStaticSeg (statsg);
963         pic14emitStaticSeg (c_abs);
964 }
965 #endif
966
967 /*-----------------------------------------------------------------*/
968 /* createInterruptVect - creates the interrupt vector              */
969 /*-----------------------------------------------------------------*/
970 pCodeOp *popGetExternal (char *str);
971 static void
972 pic14createInterruptVect (struct dbuf_s * vBuf)
973 {
974         mainf = newSymbol ("main", 0);
975         mainf->block = 0;
976         
977         /* only if the main function exists */
978         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
979         {
980                 struct options *op = &options;
981                 if (!(op->cc_only || noAssemble))
982                         //      werror (E_NO_MAIN);
983                         fprintf(stderr,"WARNING: function 'main' undefined\n");
984                 return;
985         }
986         
987         /* if the main is only a prototype ie. no body then do nothing */
988         if (!IFFUNC_HASBODY(mainf->type))
989         {
990                 /* if ! compile only then main function should be present */
991                 if (!(options.cc_only || noAssemble))
992                         //      werror (E_NO_MAIN);
993                         fprintf(stderr,"WARNING: function 'main' undefined\n");
994                 return;
995         }
996         
997         dbuf_printf (vBuf, "%s", iComments2);
998         dbuf_printf (vBuf, "; reset vector \n");
999         dbuf_printf (vBuf, "%s", iComments2);
1000         dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1001         dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
1002         dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
1003         dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
1004         popGetExternal("__sdcc_gsinit_startup");
1005 }
1006
1007
1008 /*-----------------------------------------------------------------*/
1009 /* initialComments - puts in some initial comments                 */
1010 /*-----------------------------------------------------------------*/
1011 static void
1012 pic14initialComments (FILE * afile)
1013 {
1014         initialComments (afile);
1015         fprintf (afile, "; PIC port for the 14-bit core\n");
1016         fprintf (afile, iComments2);
1017         
1018 }
1019
1020 int
1021 pic14_stringInSet(const char *str, set **world, int autoAdd)
1022 {
1023   char *s;
1024
1025   if (!str) return 1;
1026   assert(world);
1027
1028   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1029   {
1030     /* found in set */
1031     if (0 == strcmp(s, str)) return 1;
1032   }
1033
1034   /* not found */
1035   if (autoAdd) addSet(world, Safe_strdup(str));
1036   return 0;
1037 }
1038
1039 #if 0
1040 static int
1041 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1042 {
1043   if (!pic14_stringInSet(sym, &emitted, 1)) {
1044     /* sym was not in emittedSymbols */
1045     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1046       /* sym is not a locally defined function---avoid bug #1443651 */
1047       fprintf( file, fmt, sym );
1048       return 0;
1049     }
1050   }
1051   return 1;
1052 }
1053 #endif
1054
1055 #if 0
1056 /*-------------------------------------------------------------------*/
1057 /* emitSymbol - write a symbol definition only if it is not    */
1058 /*                    already present                                */
1059 /*-------------------------------------------------------------------*/
1060 static void
1061 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1062 {
1063     static unsigned int sec_idx = 0;
1064
1065     /* workaround: variables declared via `sbit' result in a numeric
1066      * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1067      * sbit is heavily used in the inc2h-generated header files!
1068      */
1069     if (!is_valid_identifier(name))
1070     {
1071         //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1072         return;
1073     }
1074
1075     /* check whether the symbol is already defined */
1076     if (pic14_stringInSet(name, &emitted, 1)) return;
1077
1078     /* new symbol -- define it */
1079     //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1080     if (useEQU) {
1081         dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1082     } else {
1083         /* we place each symbol into a section of its own to allow the linker
1084          * to distribute the data into all available memory banks */
1085         if (!section_type) section_type = "udata";
1086         if (addr != -1)
1087         {
1088             /* absolute symbols are handled in pic14_constructAbsMap */
1089             /* do nothing */
1090         } else {
1091             if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1092             dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1093                     sec_idx++, section_type);
1094             dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1095         }
1096     }
1097 }
1098 #endif
1099
1100
1101 #if 0
1102 /*-----------------------------------------------------------------*/
1103 /* printExterns - generates extern for external variables          */
1104 /*-----------------------------------------------------------------*/
1105 static void
1106 pic14printExterns (FILE * afile)
1107 {
1108         symbol *sym;
1109         
1110         fprintf (afile, "%s", iComments2);
1111         fprintf (afile, "; extern variables in this module\n");
1112         fprintf (afile, "%s", iComments2);
1113         
1114         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1115                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1116 }
1117
1118 /*-----------------------------------------------------------------*/
1119 /* printPublics - generates .global for publics                    */
1120 /*-----------------------------------------------------------------*/
1121 static void
1122 pic14printPublics (FILE * afile)
1123 {
1124   symbol *sym;
1125
1126   fprintf (afile, "%s", iComments2);
1127   fprintf (afile, "; public variables in this module\n");
1128   fprintf (afile, "%s", iComments2);
1129
1130   for (sym = setFirstItem (publics); sym;
1131       sym = setNextItem (publics)) {
1132
1133     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1134       if (!IS_BITVAR(sym->type))
1135         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1136     } else {
1137       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1138       /* Not any longer! */
1139       //if (!SPEC_ABSA (sym->etype))
1140       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1141     }
1142   }
1143 }
1144 #endif
1145
1146 /*
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         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, ";\t.module %s\n", moduleName);
1461         
1462         /* Let the port generate any global directives, etc. */
1463         if (port->genAssemblerPreamble)
1464         {
1465                 port->genAssemblerPreamble(asmFile);
1466         }
1467
1468         /* Emit the __config directive */
1469         pic14_emitConfigWord (asmFile);
1470         
1471         /* print the global variables in this module */
1472         //pic14printPublics (asmFile);
1473         
1474         /* print the extern variables in this module */
1475         //pic14printExterns (asmFile);
1476         
1477         /* copy the sfr segment */
1478 #if 0
1479         fprintf (asmFile, "%s", iComments2);
1480         fprintf (asmFile, "; special function registers\n");
1481         fprintf (asmFile, "%s", iComments2);
1482         dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1483         
1484         
1485         if (udata_section_name) {
1486                 sprintf(udata_name,"%s",udata_section_name);
1487         } else {
1488                 sprintf(udata_name,"data_%s",moduleName);
1489         }
1490         fprintf (asmFile, "%s", iComments2);
1491         fprintf (asmFile, "; udata\n");
1492         fprintf (asmFile, "%s", iComments2);
1493         fprintf (asmFile, "%s\tudata\n", udata_name);
1494         dbuf_write_and_destroy(&data->oBuf, asmFile);
1495 #endif
1496
1497         /* Put all variables into a cblock */
1498         AnalyzeBanking();
1499
1500         /* emit initialized data */
1501         showAllMemmaps(asmFile);
1502
1503         /* print the locally defined variables in this module */
1504         writeUsedRegs(asmFile);
1505         
1506         /* create the overlay segments */
1507         fprintf (asmFile, "%s", iComments2);
1508         fprintf (asmFile, "; overlayable items in internal ram \n");
1509         fprintf (asmFile, "%s", iComments2);    
1510         dbuf_write_and_destroy (&ovrBuf, asmFile);
1511         
1512 #if 0
1513         
1514         /* create the stack segment MOF */
1515         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1516                 fprintf (asmFile, "%s", iComments2);
1517                 fprintf (asmFile, "; Stack segment in internal ram \n");
1518                 fprintf (asmFile, "%s", iComments2);    
1519                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1520                         ";__start__stack:\n;\t.ds\t1\n\n");
1521         }
1522         
1523         /* create the idata segment */
1524         fprintf (asmFile, "%s", iComments2);
1525         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1526         fprintf (asmFile, "%s", iComments2);
1527         dbuf_write_and_destroy (&idata->oBuf, asmFile);
1528
1529         /* if external stack then reserve space of it */
1530         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1531                 fprintf (asmFile, "%s", iComments2);
1532                 fprintf (asmFile, "; external stack \n");
1533                 fprintf (asmFile, "%s", iComments2);
1534                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1535                 fprintf (asmFile,";\t.ds 256\n");
1536         }
1537         
1538         /* copy xtern ram data */
1539         fprintf (asmFile, "%s", iComments2);
1540         fprintf (asmFile, "; external ram data\n");
1541         fprintf (asmFile, "%s", iComments2);
1542         dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1543
1544 #endif
1545         
1546         /* copy the bit segment */
1547 #if 0
1548         fprintf (asmFile, "%s", iComments2);
1549         fprintf (asmFile, "; bit data\n");
1550         fprintf (asmFile, "%s", iComments2);
1551         dbuf_write_and_destroy (&bit->oBuf, asmFile);
1552 #endif
1553
1554         /* copy the interrupt vector table */
1555         if (mainf && IFFUNC_HASBODY(mainf->type))
1556           dbuf_write_and_destroy (&vBuf, asmFile);
1557         else
1558           dbuf_destroy(&vBuf);
1559
1560         /* create interupt ventor handler */
1561         pic14_emitInterruptHandler (asmFile);
1562         
1563         /* copy over code */
1564         fprintf (asmFile, "%s", iComments2);
1565         fprintf (asmFile, "; code\n");
1566         fprintf (asmFile, "%s", iComments2);
1567         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1568         
1569         /* unknown */
1570         copypCode(asmFile, 'X');
1571         
1572         /* _main function */
1573         copypCode(asmFile, 'M');
1574         
1575         /* other functions */
1576         copypCode(asmFile, code->dbName);
1577         
1578         /* unknown */
1579         copypCode(asmFile, 'P');
1580
1581         dumppCodeStatistics (asmFile);
1582         
1583         fprintf (asmFile,"\tend\n");
1584         
1585         fclose (asmFile);
1586 }
1587
1588 /*
1589  * Deal with initializers.
1590  */
1591 #undef DEBUGprintf
1592 #if 0
1593 // debugging output
1594 #define DEBUGprintf printf
1595 #else
1596 // be quiet
1597 #define DEBUGprintf 1 ? (void)0 : (void)printf
1598 #endif
1599
1600
1601 void ast_print (ast * tree, FILE *outfile, int indent);
1602
1603 #if 0
1604 /*
1605  * Emit all memmaps.
1606  */
1607 static void
1608 showInitList(initList *list, int level)
1609 {
1610     static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" };
1611     static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" };
1612     struct ast *ast;
1613     while (list) {
1614         printf ("      %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next);
1615         if (list->type == INIT_DEEP) {
1616             showInitList(list->init.deep, level + 1);
1617         } else if (list->type == INIT_NODE) {
1618             ast = list->init.node;
1619             printf ("        type %u (%s), level %d, block %d, seqPoint %d\n",
1620                     ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint);
1621             if (ast->type == EX_VALUE) {
1622                 printf ("          VAL %lf\n", floatFromVal(ast->opval.val));
1623             } else if (ast->type == EX_LINK) {
1624                 printTypeChain(ast->opval.lnk, NULL);
1625             } else if (ast->type == EX_OP) {
1626                 printf ("          OP %u\n", ast->opval.op);
1627             }
1628         } // if
1629         list = list->next;
1630     } // while
1631 }
1632 #endif
1633
1634 /*
1635  * DEBUG: Print a value.
1636  */
1637 void
1638 printVal(value *val)
1639 {
1640     printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n",
1641             val, val->name, val->type, val->etype,
1642             val->sym ? val->sym->name : NULL, val->vArgs,
1643             (long)floatFromVal(val), (long)floatFromVal(val));
1644     printTypeChain(val->type, stdout);
1645     printf ("\n");
1646     printTypeChain(val->etype, stdout);
1647     printf ("\n");
1648 }
1649
1650 //prototype from ../SDCCicode.c
1651 operand *operandFromAst (ast * tree,int lvl);
1652
1653 char *
1654 parseIvalAst (ast *node, int *inCodeSpace) {
1655 #define LEN 4096
1656     char *buffer = NULL;
1657     char *left, *right;
1658     
1659     if (IS_AST_VALUE(node)) {
1660         value *val = AST_VALUE(node);
1661         symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
1662         if (inCodeSpace && val->type
1663                 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
1664         {
1665             *inCodeSpace = 1;
1666         }
1667         if (inCodeSpace && sym
1668                 && (IS_FUNC(sym->type)
1669                     || IS_CODE(getSpec(sym->type))))
1670         {
1671             *inCodeSpace = 1;
1672         }
1673         
1674         DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
1675         if (IS_AST_LIT_VALUE(node)) {
1676             buffer = Safe_alloc(LEN);
1677             SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node));
1678         } else if (IS_AST_SYM_VALUE(node)) {
1679             assert ( AST_SYMBOL(node) );
1680             /*
1681             printf ("sym %s: ", AST_SYMBOL(node)->rname);
1682             printTypeChain(AST_SYMBOL(node)->type, stdout);
1683             printTypeChain(AST_SYMBOL(node)->etype, stdout);
1684             printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
1685             */
1686             buffer = Safe_strdup(AST_SYMBOL(node)->rname);
1687         } else {
1688             assert ( !"Invalid values type for initializers in AST." );
1689         }
1690     } else if (IS_AST_OP(node)) {
1691         DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
1692         switch (node->opval.op) {
1693         case CAST:
1694             assert (node->right);
1695             buffer = parseIvalAst(node->right, inCodeSpace);
1696             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1697             break;
1698         case '&':
1699             assert ( node->left && !node->right );
1700             buffer = parseIvalAst(node->left, inCodeSpace);
1701             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1702             break;
1703         case '+':
1704             assert (node->left && node->right );
1705             left = parseIvalAst(node->left, inCodeSpace);
1706             right = parseIvalAst(node->right, inCodeSpace);
1707             buffer = Safe_alloc(LEN);
1708             SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
1709             DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
1710             Safe_free(left);
1711             Safe_free(right);
1712             break;
1713         case '[':
1714             assert ( node->left && node->right );
1715             assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
1716             right = parseIvalAst(node->right, inCodeSpace);
1717             buffer = Safe_alloc(LEN);
1718             SNPRINTF(buffer, LEN, "(%s + %u * %s)",
1719                     AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
1720             Safe_free(right);
1721             DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
1722             break;
1723         default:
1724             assert ( !"Unhandled operation in initializer." );
1725             break;
1726         }
1727     } else {
1728         assert ( !"Invalid construct in initializer." );
1729     }
1730     
1731     return (buffer);
1732 }
1733
1734 /*
1735  * Emit the section preamble, absolute location (if any) and 
1736  * symbol name(s) for intialized data.
1737  */
1738 static int
1739 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
1740 {
1741     char *segname;
1742     static int in_code = 0;
1743     static int sectionNr = 0;
1744     
1745     if (sym) {
1746         // code or data space?
1747         if (IS_CODE(getSpec(sym->type))) {
1748             segname = "code";
1749             in_code = 1;
1750         } else {
1751             segname = "idata";
1752             in_code  = 0;
1753         }
1754         dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
1755         if (SPEC_ABSA(getSpec(sym->type))) {
1756             // specify address for absolute symbols
1757             dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
1758         } // if
1759         dbuf_printf(oBuf, "\n%s\n", sym->rname);
1760
1761         addSet(&emitted, sym->rname);
1762     }
1763     return (in_code);
1764 }
1765
1766 char *get_op(pCodeOp *pcop,char *buffer, size_t size);
1767 /*
1768  * Actually emit the initial values in .asm format.
1769  */
1770 static void
1771 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
1772 {
1773     int i;
1774     ast *node;
1775     operand *op;
1776     value *val = NULL;
1777     int inCodeSpace = 0;
1778     char *str = NULL;
1779     int in_code;
1780     
1781     assert (size <= sizeof(long));
1782     assert (!list || (list->type == INIT_NODE));
1783     node = list ? list->init.node : NULL;
1784     
1785     in_code = emitIvalLabel(oBuf, sym);
1786     if (!in_code) dbuf_printf (oBuf, "\tdb\t");
1787
1788     if (!node) {
1789         // initialize as zero
1790         for (i=0; i < size; i++) {
1791             if (in_code) {
1792                 dbuf_printf (oBuf, "\tretlw 0x00");
1793             } else {
1794                 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
1795             }
1796         } // for
1797         dbuf_printf (oBuf, "\n");
1798         return;
1799     } // if
1800     
1801     op = NULL;
1802     if (constExprTree(node) && (val = constExprValue(node, 0))) {
1803         op = operandFromValue(val);
1804         DEBUGprintf ("%s: constExpr ", __FUNCTION__);
1805         //printVal(val);
1806     } else if (IS_AST_VALUE(node)) {
1807         op = operandFromAst(node, 0);
1808     } else if (IS_AST_OP(node)) {
1809         str = parseIvalAst(node, &inCodeSpace);
1810         DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
1811         op = NULL;
1812     } else {
1813         assert ( !"Unhandled construct in intializer." );
1814     }
1815
1816     if (op) { 
1817         aopOp(op, NULL, 1);
1818         assert(AOP(op));
1819         //printOperand(op, of);
1820     }
1821     
1822     for (i=0; i < size; i++) {
1823         char *text = op ? aopGet(AOP(op), i, 0, 0)
1824             : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
1825         if (in_code) {
1826             dbuf_printf (oBuf, "\tretlw %s\n", text);
1827         } else {
1828             dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
1829         }
1830     } // for
1831     dbuf_printf (oBuf, "\n");
1832 }
1833
1834 /*
1835  * For UNIONs, we first have to find the correct alternative to map the
1836  * initializer to. This function maps the structure of the initializer to
1837  * the UNION members recursively.
1838  * Returns the type of the first `fitting' member.
1839  */
1840 static sym_link *
1841 matchIvalToUnion (initList *list, sym_link *type, int size)
1842 {
1843     symbol *sym;
1844     
1845     assert (type);
1846
1847     if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
1848             || IS_FLOAT(type)) 
1849     {
1850         if (!list || (list->type == INIT_NODE)) {
1851             DEBUGprintf ("OK, simple type\n");
1852             return (type);
1853         } else {
1854             DEBUGprintf ("ERROR, simple type\n");
1855             return (NULL);
1856         }
1857     } else if (IS_BITFIELD(type)) {
1858         if (!list || (list->type == INIT_NODE)) {
1859             DEBUGprintf ("OK, bitfield\n");
1860             return (type);
1861         } else {
1862             DEBUGprintf ("ERROR, bitfield\n");
1863             return (NULL);
1864         }
1865     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
1866         if (!list || (list->type == INIT_DEEP)) {
1867             if (list) list = list->init.deep;
1868             sym = SPEC_STRUCT(type)->fields;
1869             while (sym) {
1870                 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
1871                 if (!matchIvalToUnion(list, sym->type, 0)) {
1872                     DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
1873                     return (NULL);
1874                 }
1875                 if (list) list = list->next;
1876                 sym = sym->next;
1877             } // while
1878             
1879             // excess initializers?
1880             if (list) {
1881                 DEBUGprintf ("ERROR, excess initializers\n");
1882                 return (NULL);
1883             }
1884             
1885             DEBUGprintf ("OK, struct\n");
1886             return (type);
1887         }
1888         return (NULL);
1889     } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
1890         if (!list || (list->type == INIT_DEEP)) {
1891             if (list) list = list->init.deep;
1892             sym = SPEC_STRUCT(type)->fields;
1893             while (sym) {
1894                 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
1895                 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
1896                         && matchIvalToUnion(list, sym->type, size))
1897                 {
1898                     DEBUGprintf ("Matched UNION member %s.\n", sym->name);
1899                     return (sym->type);
1900                 }
1901                 sym = sym->next;
1902             } // while
1903         } // if
1904         // no match found
1905         DEBUGprintf ("ERROR, no match found.\n");
1906         return (NULL);
1907     } else {
1908         assert ( !"Unhandled type in UNION." );
1909     }
1910
1911     assert ( !"No match found in UNION for the given initializer structure." );
1912     return (NULL);
1913 }
1914
1915 /*
1916  * Parse the type and its initializer and emit it (recursively).
1917  */
1918 static void
1919 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
1920 {
1921     symbol *sym;
1922     int size, i;
1923     long lit;
1924     unsigned char *str;
1925
1926     size = getSize(my_type);
1927
1928     if (IS_PTR(my_type)) {
1929         DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
1930         emitIvals(oBuf, topsym, list, 0, size);
1931         return;
1932     }
1933
1934     if (IS_ARRAY(my_type) && topsym->isstrlit) {
1935         str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
1936         emitIvalLabel(oBuf, topsym);
1937         do {
1938             dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
1939         } while (*(str++));
1940         return;
1941     }
1942
1943     if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
1944         fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
1945         assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
1946         return;
1947     }
1948
1949     if (IS_ARRAY(my_type)) {
1950         DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
1951         assert (!list || list->type == INIT_DEEP);
1952         if (list) list = list->init.deep;
1953         for (i = 0; i < DCL_ELEM(my_type); i++) {
1954             emitInitVal(oBuf, topsym, my_type->next, list);
1955             topsym = NULL;
1956             if (list) list = list->next;
1957         } // for i
1958         return;
1959     }
1960     
1961     if (IS_FLOAT(my_type)) {
1962         // float, 32 bit
1963         DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
1964         emitIvals(oBuf, topsym, list, 0, size);
1965         return;
1966     }
1967     
1968     if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
1969         // integral type, 8, 16, or 32 bit
1970         DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
1971         emitIvals(oBuf, topsym, list, 0, size);
1972         return;
1973         
1974     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
1975         // struct
1976         DEBUGprintf ("(struct, %d byte) handled below\n", size);
1977         assert (!list || (list->type == INIT_DEEP));
1978
1979         // iterate over struct members and initList
1980         if (list) list = list->init.deep;
1981         sym = SPEC_STRUCT(my_type)->fields;
1982         while (sym) {
1983             long bitfield = 0;
1984             int len = 0;
1985             if (IS_BITFIELD(sym->type)) {
1986                 while (sym && IS_BITFIELD(sym->type)) {
1987                     assert (!list || ((list->type == INIT_NODE) 
1988                                 && IS_AST_LIT_VALUE(list->init.node)));
1989                     lit = list ? list2int(list) : 0;
1990                     DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
1991                             lit, SPEC_BLEN(getSpec(sym->type)),
1992                             SPEC_BSTR(getSpec(sym->type)), bitfield);
1993                     bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
1994                     len += SPEC_BLEN(getSpec(sym->type));
1995
1996                     sym = sym->next;
1997                     if (list) list = list->next;
1998                 } // while
1999                 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
2000                 len = (len + 7) & ~0x07; // round up to full bytes
2001                 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
2002                 topsym = NULL;
2003             } // if
2004             
2005             if (sym) {
2006                 emitInitVal(oBuf, topsym, sym->type, list);
2007                 topsym = NULL;
2008                 sym = sym->next;
2009                 if (list) list = list->next;
2010             } // if
2011         } // while
2012         if (list) {
2013             assert ( !"Excess initializers." );
2014         } // if
2015         return;
2016         
2017     } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
2018         // union
2019         DEBUGprintf ("(union, %d byte) handled below\n", size);
2020         assert (list && list->type == INIT_DEEP);
2021
2022         // iterate over union members and initList, try to map number and type of fields and initializers
2023         my_type = matchIvalToUnion(list, my_type, size);
2024         if (my_type) {
2025             emitInitVal(oBuf, topsym, my_type, list->init.deep);
2026             topsym = NULL;
2027             size -= getSize(my_type);
2028             if (size > 0) {
2029                 // pad with (leading) zeros
2030                 emitIvals(oBuf, NULL, NULL, 0, size);
2031             }
2032             return;
2033         } // if
2034         
2035         assert ( !"No UNION member matches the initializer structure.");
2036     } else if (IS_BITFIELD(my_type)) {
2037         assert ( !"bitfields should only occur in structs..." );
2038         
2039     } else {
2040         printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
2041         assert( !"Unhandled initialized type.");
2042     }
2043 }
2044
2045 /*
2046  * Emit a set of symbols.
2047  * type - 0: have symbol tell whether it is local, extern or global
2048  *        1: assume all symbols in set to be global
2049  *        2: assume all symbols in set to be extern
2050  */
2051 static void
2052 emitSymbolSet(set *s, int type)
2053 {
2054     symbol *sym;
2055     initList *list;
2056     unsigned sectionNr = 0;
2057
2058     for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
2059 #if 0
2060         fprintf (stdout, ";    name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
2061                 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
2062 #endif
2063
2064         if (sym->isstrlit) {
2065             // special case: string literals
2066             emitInitVal(ivalBuf, sym, sym->type, NULL);
2067             continue;
2068         }
2069
2070         if (type != 0 || sym->cdef
2071                 || (!IS_STATIC(sym->etype)
2072                     && IS_GLOBAL(sym)))
2073         {
2074             // bail out for ___fsadd and friends
2075             if (sym->cdef && !sym->used) continue;
2076
2077             /* export or import non-static globals */
2078             if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
2079
2080                 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
2081                 {
2082                     /* do not add to emitted set, it might occur again! */
2083                     //if (!sym->used) continue;
2084                     // declare symbol
2085                     emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
2086                 } else {
2087                     // declare symbol
2088                     emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
2089                     if (!sym->ival && !IS_FUNC(sym->type)) {
2090                         // also define symbol
2091                         if (IS_ABSOLUTE(sym->etype)) {
2092                             // absolute location?
2093                             //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
2094                             // deferred to pic14_constructAbsMap
2095                         } else {
2096                             dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
2097                             dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
2098                         }
2099                     } // if
2100                 } // if
2101                 pic14_stringInSet(sym->rname, &emitted, 1);
2102             } // if
2103         } // if
2104         list = sym->ival;
2105         //if (list) showInitList(list, 0);
2106         if (list) {
2107             resolveIvalSym( list, sym->type );
2108             emitInitVal(ivalBuf, sym, sym->type, sym->ival);
2109             dbuf_printf (ivalBuf, "\n");
2110         }
2111     } // for sym
2112 }
2113
2114 /*
2115  * Iterate over all memmaps and emit their contents (attributes, symbols).
2116  */
2117 static void
2118 showAllMemmaps(FILE *of)
2119 {
2120     struct dbuf_s locBuf;
2121     memmap *maps[] = {
2122         xstack, istack, code, data, pdata, xdata, xidata, xinit,
2123         idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
2124         sfr, sfrbit, reg, generic, overlay, eeprom, home };
2125     memmap * map;
2126     int i;
2127
2128     DEBUGprintf ("---begin memmaps---\n");
2129     if (!extBuf) extBuf = dbuf_new(1024);
2130     if (!gloBuf) gloBuf = dbuf_new(1024);
2131     if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
2132     if (!ivalBuf) ivalBuf = dbuf_new(1024);
2133     dbuf_init(&locBuf, 1024);
2134
2135     dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
2136     dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
2137     dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
2138     dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
2139     dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
2140
2141     for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
2142         map = maps[i];
2143         //DEBUGprintf ("memmap %i: %p\n", i, map);
2144         if (map) {
2145 #if 0
2146             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", 
2147                     map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
2148                     map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
2149                     map->codesp, map->regsp, map->syms);
2150 #endif
2151             emitSymbolSet(map->syms, 0);
2152         } // if (map)
2153     } // for i
2154     DEBUGprintf ("---end of memmaps---\n");
2155
2156     emitSymbolSet(publics, 1);
2157     emitSymbolSet(externs, 2);
2158
2159     emitPseudoStack(gloBuf, extBuf);
2160     pic14_constructAbsMap(gloDefBuf, gloBuf);
2161
2162     pic14printLocals (&locBuf);
2163
2164     dbuf_write_and_destroy(extBuf, of);
2165     dbuf_write_and_destroy(gloBuf, of);
2166     dbuf_write_and_destroy(gloDefBuf, of);
2167     dbuf_write_and_destroy(&locBuf, of);
2168     dbuf_write_and_destroy(ivalBuf, of);
2169
2170     extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;
2171 }
2172