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